diff options
author | Harald Welte <laforge@osmocom.org> | 2020-03-20 13:05:40 +0100 |
---|---|---|
committer | Harald Welte <laforge@osmocom.org> | 2020-03-21 16:31:17 +0100 |
commit | 429adecfd8e817b1d3d4eb9590ee0e351696bad9 (patch) | |
tree | ffbae2a5fcd1ee02fe07e23691fea59fe2e8331d | |
parent | bf90d747ad678fd301831b299c12f9de332341f9 (diff) |
sim: re-structure how we support cards + applications
Before this change, a card application (USIM, ISIM, ...) didn't
exist as a separate concept from a card profile. This meant,
we had a manual combination of UICC card profile with USIM application,
and another one of UICC card profile and ISIM application. But what
if there's a combined USIM+ISIM?
In reality, applications exist as separate objects, on top of an
ETSI UICC. Lets therefore register all known applications to the
osim library core, and add code to osmo-sim-test which dynamically
detects all applications present on a given card (by reading EF.DIR).
Change-Id: Ic4b4ac433a9976842b30a017fb0fc347d87201cd
-rw-r--r-- | include/osmocom/sim/sim.h | 47 | ||||
-rw-r--r-- | src/sim/card_fs_isim.c | 32 | ||||
-rw-r--r-- | src/sim/card_fs_uicc.c | 50 | ||||
-rw-r--r-- | src/sim/card_fs_usim.c | 55 | ||||
-rw-r--r-- | src/sim/core.c | 101 | ||||
-rw-r--r-- | src/sim/reader_pcsc.c | 1 | ||||
-rw-r--r-- | src/sim/sim_int.h | 13 | ||||
-rw-r--r-- | utils/osmo-sim-test.c | 149 |
8 files changed, 326 insertions, 122 deletions
diff --git a/include/osmocom/sim/sim.h b/include/osmocom/sim/sim.h index 5440d855..33ebdd75 100644 --- a/include/osmocom/sim/sim.h +++ b/include/osmocom/sim/sim.h @@ -9,6 +9,7 @@ #include <osmocom/core/linuxlist.h> #define APDU_HDR_LEN 5 +#define MAX_AID_LEN 16 /* Table 13.2 of TS 102 221 */ /*! command-response pairs cases * @@ -66,6 +67,8 @@ struct osim_msgb_cb { #define msgb_apdu_dc(__x) ((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr)) #define msgb_apdu_de(__x) ((__x)->l2h + sizeof(struct osim_apdu_cmd_hdr) + msgb_apdu_lc(__x)) +int osim_init(void *ctx); + /* FILES */ struct osim_file; @@ -285,6 +288,28 @@ struct osim_card_sw { .class = SW_CLS_NONE, .u.str = NULL \ } +/*! A card application (e.g. USIM, ISIM, HPSIM) */ +struct osim_card_app_profile { + /*! entry in the global list of card application profiles */ + struct llist_head list; + /*! human-readable name */ + const char *name; + /*! AID of this application, as used in EF.DIR */ + uint8_t aid[MAX_AID_LEN]; + uint8_t aid_len; + /*! file system description */ + struct osim_file_desc *adf; + /*! Status words defined by application */ + const struct osim_card_sw *sw; +}; + +const struct osim_card_app_profile * +osim_app_profile_find_by_name(const char *name); + +const struct osim_card_app_profile * +osim_app_profile_find_by_aid(const uint8_t *aid, uint8_t aid_len); + + /*! A card profile (e.g. SIM card */ struct osim_card_profile { const char *name; @@ -357,6 +382,19 @@ struct osim_reader_hdl { struct osim_card_hdl *card; }; +/*! descriptor for a given application present on a card */ +struct osim_card_app_hdl { + /*! member in card list of applications */ + struct llist_head list; + /*! AID of the application */ + uint8_t aid[MAX_AID_LEN]; + uint8_t aid_len; + /*! application label from EF_DIR */ + char *label; + /*! application profile (if any known) */ + const struct osim_card_app_profile *prof; +}; + struct osim_card_hdl { /*! member in global list of cards */ struct llist_head list; @@ -369,6 +407,9 @@ struct osim_card_hdl { /*! list of channels for this card */ struct llist_head channels; + + /*! list of applications found on card */ + struct llist_head apps; }; struct osim_chan_hdl { @@ -376,9 +417,15 @@ struct osim_chan_hdl { struct llist_head list; /*! card to which this channel belongs */ struct osim_card_hdl *card; + /*! current working directory */ const struct osim_file_desc *cwd; + /*! currently selected application (if any) */ + struct osim_card_app_hdl *cur_app; }; +int osim_card_hdl_add_app(struct osim_card_hdl *ch, const uint8_t *aid, uint8_t aid_len, + const char *label); + /* reader.c */ int osim_transceive_apdu(struct osim_chan_hdl *st, struct msgb *amsg); struct osim_reader_hdl *osim_reader_open(enum osim_reader_driver drv, int idx, diff --git a/src/sim/card_fs_isim.c b/src/sim/card_fs_isim.c index e6ba0d09..2970c45e 100644 --- a/src/sim/card_fs_isim.c +++ b/src/sim/card_fs_isim.c @@ -43,12 +43,6 @@ const struct osim_card_sw ts31_103_sw[] = { OSIM_CARD_SW_LAST }; -static const struct osim_card_sw *isim_card_sws[] = { - ts31_103_sw, - ts102221_uicc_sw, - NULL -}; - /* TS 31.103 Version 11.2.0 Release 11 / Chapoter 4.2 */ static const struct osim_file_desc isim_ef_in_adf_isim[] = { EF_TRANSP_N(0x6F02, 0x02, "EF.IMPI", 0, 1, 256, @@ -86,23 +80,21 @@ static const struct osim_file_desc isim_ef_in_adf_isim[] = { /* Annex E - TS 101 220 */ static const uint8_t adf_isim_aid[] = { 0xA0, 0x00, 0x00, 0x00, 0x87, 0x10, 0x04 }; -struct osim_card_profile *osim_cprof_isim(void *ctx) +struct osim_card_app_profile *osim_aprof_isim(void *ctx) { - struct osim_card_profile *cprof; - struct osim_file_desc *mf; - - cprof = talloc_zero(ctx, struct osim_card_profile); - cprof->name = "3GPP ISIM"; - cprof->sws = isim_card_sws; - - mf = alloc_df(cprof, 0x3f00, "MF"); + struct osim_card_app_profile *aprof; + struct osim_file_desc *iadf; - cprof->mf = mf; + aprof = talloc_zero(ctx, struct osim_card_app_profile); + aprof->name = "3GPP ISIM"; + aprof->sw = ts31_103_sw; + aprof->aid_len = sizeof(adf_isim_aid); + memcpy(aprof->aid, adf_isim_aid, aprof->aid_len); /* ADF.USIM with its EF siblings */ - add_adf_with_ef(mf, adf_isim_aid, sizeof(adf_isim_aid), - "ADF.ISIM", isim_ef_in_adf_isim, - ARRAY_SIZE(isim_ef_in_adf_isim)); + iadf = alloc_adf_with_ef(aprof, adf_isim_aid, sizeof(adf_isim_aid), "ADF.ISIM", + isim_ef_in_adf_isim, ARRAY_SIZE(isim_ef_in_adf_isim)); + aprof->adf = iadf; - return cprof; + return aprof; } diff --git a/src/sim/card_fs_uicc.c b/src/sim/card_fs_uicc.c index af6061cf..c73fc9a2 100644 --- a/src/sim/card_fs_uicc.c +++ b/src/sim/card_fs_uicc.c @@ -1,7 +1,7 @@ /*! \file card_fs_uicc.c * ETSI UICC specific structures / routines. */ /* - * (C) 2012 by Harald Welte <laforge@gnumonks.org> + * (C) 2012-2020 by Harald Welte <laforge@gnumonks.org> * * All Rights Reserved * @@ -25,8 +25,12 @@ #include <osmocom/sim/sim.h> +#include <osmocom/core/talloc.h> #include <osmocom/gsm/tlv.h> +#include "sim_int.h" +#include "gsm_int.h" + /* TS 102 221 V10.0.0 / 10.2.1 */ const struct osim_card_sw ts102221_uicc_sw[] = { { @@ -171,6 +175,23 @@ const struct osim_card_sw ts102221_uicc_sw[] = { OSIM_CARD_SW_LAST }; +static const struct osim_card_sw *uicc_card_sws[] = { + ts102221_uicc_sw, + NULL +}; + +/* TS 102 221 Chapter 13.1 */ +static const struct osim_file_desc uicc_ef_in_mf[] = { + EF_LIN_FIX_N(0x2f00, SFI_NONE, "EF.DIR", 0, 1, 32, + "Application directory"), + EF_TRANSP_N(0x2FE2, SFI_NONE, "EF.ICCID", 0, 10, 10, + "ICC Identification"), + EF_TRANSP_N(0x2F05, SFI_NONE, "EF.PL", 0, 2, 20, + "Preferred Languages"), + EF_LIN_FIX_N(0x2F06, SFI_NONE, "EF.ARR", F_OPTIONAL, 1, 256, + "Access Rule Reference"), +}; + const struct value_string ts102221_fcp_vals[14] = { { UICC_FCP_T_FCP, "File control parameters" }, { UICC_FCP_T_FILE_SIZE, "File size" }, @@ -209,3 +230,30 @@ const struct tlv_definition ts102221_fcp_tlv_def = { /* Annex E - TS 101 220 */ static const uint8_t __attribute__((__unused__)) adf_uicc_aid[] = { 0xA0, 0x00, 0x00, 0x00, 0x87, 0x10, 0x01 }; + +struct osim_card_profile *osim_cprof_uicc(void *ctx) +{ + struct osim_card_profile *cprof; + struct osim_file_desc *mf; + int rc; + + cprof = talloc_zero(ctx, struct osim_card_profile); + cprof->name = "3GPP UICC"; + cprof->sws = uicc_card_sws; // FIXME: extend later + + mf = alloc_df(cprof, 0x3f00, "MF"); + + cprof->mf = mf; + + /* Core UICC Files */ + add_filedesc(mf, uicc_ef_in_mf, ARRAY_SIZE(uicc_ef_in_mf)); + + /* DF.TELECOM hierarchy as sub-directory of MF */ + rc = osim_int_cprof_add_telecom(mf); + if (rc != 0) { + talloc_free(cprof); + return NULL; + } + + return cprof; +} diff --git a/src/sim/card_fs_usim.c b/src/sim/card_fs_usim.c index 3b33c0f6..97f712ac 100644 --- a/src/sim/card_fs_usim.c +++ b/src/sim/card_fs_usim.c @@ -1,7 +1,7 @@ /*! \file card_fs_usim.c * 3GPP USIM specific structures / routines. */ /* - * (C) 2012-2014 by Harald Welte <laforge@gnumonks.org> + * (C) 2012-2020 by Harald Welte <laforge@gnumonks.org> * * All Rights Reserved * @@ -47,24 +47,6 @@ const struct osim_card_sw ts31_102_sw[] = { OSIM_CARD_SW_LAST }; -static const struct osim_card_sw *usim_card_sws[] = { - ts31_102_sw, - ts102221_uicc_sw, - NULL -}; - -/* TS 102 221 Chapter 13.1 */ -static const struct osim_file_desc uicc_ef_in_mf[] = { - EF_LIN_FIX_N(0x2f00, SFI_NONE, "EF.DIR", 0, 1, 32, - "Application directory"), - EF_TRANSP_N(0x2FE2, SFI_NONE, "EF.ICCID", 0, 10, 10, - "ICC Identification"), - EF_TRANSP_N(0x2F05, SFI_NONE, "EF.PL", 0, 2, 20, - "Preferred Languages"), - EF_LIN_FIX_N(0x2F06, SFI_NONE, "EF.ARR", F_OPTIONAL, 1, 256, - "Access Rule Reference"), -}; - /* 31.102 Chapter 4.4.3 */ static const struct osim_file_desc usim_ef_in_df_gsm_access[] = { EF_TRANSP_N(0x4f20, 0x01, "EF.Kc", 0, 9, 9, @@ -330,27 +312,21 @@ static const struct osim_file_desc usim_ef_in_df_hnb[] = { /* Annex E - TS 101 220 */ static const uint8_t adf_usim_aid[] = { 0xA0, 0x00, 0x00, 0x00, 0x87, 0x10, 0x02 }; -struct osim_card_profile *osim_cprof_usim(void *ctx) +struct osim_card_app_profile *osim_aprof_usim(void *ctx) { - struct osim_card_profile *cprof; - struct osim_file_desc *mf, *uadf; - int rc; - - cprof = talloc_zero(ctx, struct osim_card_profile); - cprof->name = "3GPP USIM"; - cprof->sws = usim_card_sws; - - mf = alloc_df(cprof, 0x3f00, "MF"); - - cprof->mf = mf; + struct osim_card_app_profile *aprof; + struct osim_file_desc *uadf; - /* Core UICC Files */ - add_filedesc(mf, uicc_ef_in_mf, ARRAY_SIZE(uicc_ef_in_mf)); + aprof = talloc_zero(ctx, struct osim_card_app_profile); + aprof->name = "3GPP USIM"; + aprof->sw = ts31_102_sw; + aprof->aid_len = sizeof(adf_usim_aid); + memcpy(aprof->aid, adf_usim_aid, aprof->aid_len); /* ADF.USIM with its EF siblings */ - uadf = add_adf_with_ef(mf, adf_usim_aid, sizeof(adf_usim_aid), - "ADF.USIM", usim_ef_in_adf_usim, - ARRAY_SIZE(usim_ef_in_adf_usim)); + uadf = alloc_adf_with_ef(aprof, adf_usim_aid, sizeof(adf_usim_aid), + "ADF.USIM", usim_ef_in_adf_usim, ARRAY_SIZE(usim_ef_in_adf_usim)); + aprof->adf = uadf; /* DFs under ADF.USIM */ add_df_with_ef(uadf, 0x5F3A, "DF.PHONEBOOK", NULL, 0); @@ -369,13 +345,14 @@ struct osim_card_profile *osim_cprof_usim(void *ctx) /* OMA BCAST Smart Card Profile */ add_df_with_ef(uadf, 0x5F80, "DF.BCAST", NULL, 0); - /* DF.GSM and DF.TELECOM hierarchy as sub-directory of MF */ +#if 0 + /* DF.GSM as sub-directory of MF */ rc = osim_int_cprof_add_gsm(mf); - rc |= osim_int_cprof_add_telecom(mf); if (rc != 0) { talloc_free(cprof); return NULL; } +#endif - return cprof; + return aprof; } diff --git a/src/sim/core.c b/src/sim/core.c index 4360ff11..80a168f4 100644 --- a/src/sim/core.c +++ b/src/sim/core.c @@ -1,7 +1,7 @@ /*! \file core.c * Core routines for SIM/UICC/USIM access. */ /* - * (C) 2012 by Harald Welte <laforge@gnumonks.org> + * (C) 2012-2020 by Harald Welte <laforge@gnumonks.org> * * All Rights Reserved * @@ -27,10 +27,13 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> +#include <errno.h> #include <osmocom/core/talloc.h> #include <osmocom/sim/sim.h> +#include "sim_int.h" + struct osim_decoded_data *osim_file_decode(struct osim_file *file, int len, uint8_t *data) { @@ -154,21 +157,19 @@ add_df_with_ef(struct osim_file_desc *parent, } struct osim_file_desc * -add_adf_with_ef(struct osim_file_desc *parent, +alloc_adf_with_ef(void *ctx, const uint8_t *adf_name, uint8_t adf_name_len, const char *name, const struct osim_file_desc *in, int num) { struct osim_file_desc *df; - df = alloc_df(parent, 0xffff, name); + df = alloc_df(ctx, 0xffff, name); if (!df) return NULL; df->type = TYPE_ADF; df->df_name = adf_name; df->df_name_len = adf_name_len; - df->parent = parent; - llist_add_tail(&df->list, &parent->child_list); add_filedesc(df, in, num); return df; @@ -229,6 +230,88 @@ osim_file_desc_find_sfid(struct osim_file_desc *parent, uint8_t sfid) } +/*********************************************************************** + * Application Profiles + Applications + ***********************************************************************/ + +static LLIST_HEAD(g_app_profiles); + +/*! Register an application profile. Typically called at early start-up. */ +void osim_app_profile_register(struct osim_card_app_profile *aprof) +{ + OSMO_ASSERT(!osim_app_profile_find_by_name(aprof->name)); + OSMO_ASSERT(!osim_app_profile_find_by_aid(aprof->aid, aprof->aid_len)); + llist_add_tail(&aprof->list, &g_app_profiles); +} + +/*! Find any registered application profile based on its name (e.g. "ADF.USIM") */ +const struct osim_card_app_profile * +osim_app_profile_find_by_name(const char *name) +{ + struct osim_card_app_profile *ap; + + llist_for_each_entry(ap, &g_app_profiles, list) { + if (!strcmp(name, ap->name)) + return ap; + } + return NULL; +} + +/*! Find any registered application profile based on its AID */ +const struct osim_card_app_profile * +osim_app_profile_find_by_aid(const uint8_t *aid, uint8_t aid_len) +{ + struct osim_card_app_profile *ap; + + llist_for_each_entry(ap, &g_app_profiles, list) { + if (ap->aid_len > aid_len) + continue; + if (!memcmp(ap->aid, aid, ap->aid_len)) + return ap; + } + return NULL; +} + +struct osim_card_app_hdl * +osim_card_hdl_find_app(struct osim_card_hdl *ch, const uint8_t *aid, uint8_t aid_len) +{ + struct osim_card_app_hdl *ah; + + if (aid_len > MAX_AID_LEN) + return NULL; + + llist_for_each_entry(ah, &ch->apps, list) { + if (!memcmp(ah->aid, aid, aid_len)) + return ah; + } + return NULL; +} + +/*! Add an application to a given card */ +int osim_card_hdl_add_app(struct osim_card_hdl *ch, const uint8_t *aid, uint8_t aid_len, + const char *label) +{ + struct osim_card_app_hdl *ah; + + if (aid_len > MAX_AID_LEN) + return -EINVAL; + + if (osim_card_hdl_find_app(ch, aid, aid_len)) + return -EEXIST; + + ah = talloc_zero(ch, struct osim_card_app_hdl); + if (!ah) + return -ENOMEM; + + memcpy(ah->aid, aid, aid_len); + ah->aid_len = aid_len; + ah->prof = osim_app_profile_find_by_aid(ah->aid, ah->aid_len); + if (label) + ah->label = talloc_strdup(ah, label); + llist_add_tail(&ah->list, &ch->apps); + return 0; +} + /*! Generate an APDU message and initialize APDU command header * \param[in] cla CLASS byte * \param[in] ins INSTRUCTION byte @@ -365,3 +448,11 @@ int default_decode(struct osim_decoded_data *dd, return 0; } + +int osim_init(void *ctx) +{ + osim_app_profile_register(osim_aprof_usim(ctx)); + osim_app_profile_register(osim_aprof_isim(ctx)); + + return 0; +} diff --git a/src/sim/reader_pcsc.c b/src/sim/reader_pcsc.c index 04a86223..c37380a3 100644 --- a/src/sim/reader_pcsc.c +++ b/src/sim/reader_pcsc.c @@ -121,6 +121,7 @@ static struct osim_card_hdl *pcsc_card_open(struct osim_reader_hdl *rh, card = talloc_zero(rh, struct osim_card_hdl); INIT_LLIST_HEAD(&card->channels); + INIT_LLIST_HEAD(&card->apps); card->reader = rh; rh->card = card; diff --git a/src/sim/sim_int.h b/src/sim/sim_int.h index 885011ed..99a22428 100644 --- a/src/sim/sim_int.h +++ b/src/sim/sim_int.h @@ -12,8 +12,6 @@ struct osim_decoded_element * element_alloc_sub(struct osim_decoded_element *ee, const char *name, enum osim_element_type type, enum osim_element_repr repr); -extern const struct osim_card_sw ts102221_uicc_sw[0]; - int default_decode(struct osim_decoded_data *dd, const struct osim_file_desc *desc, int len, uint8_t *data); @@ -26,11 +24,14 @@ add_df_with_ef(struct osim_file_desc *parent, const struct osim_file_desc *in, int num); struct osim_file_desc * -add_adf_with_ef(struct osim_file_desc *parent, - const uint8_t *adf_name, uint8_t adf_name_len, - const char *name, const struct osim_file_desc *in, - int num); +alloc_adf_with_ef(void *ctx, const uint8_t *adf_name, uint8_t adf_name_len, + const char *name, const struct osim_file_desc *in, int num); extern const struct osim_reader_ops pcsc_reader_ops; +void osim_app_profile_register(struct osim_card_app_profile *aprof); + +struct osim_card_app_profile *osim_aprof_usim(void *ctx); +struct osim_card_app_profile *osim_aprof_isim(void *ctx); + #endif diff --git a/utils/osmo-sim-test.c b/utils/osmo-sim-test.c index a9ab0d02..e71d0ef1 100644 --- a/utils/osmo-sim-test.c +++ b/utils/osmo-sim-test.c @@ -77,6 +77,7 @@ static struct msgb *select_file(struct osim_chan_hdl *st, uint16_t fid) return _select_file(st, 0x00, p2, (uint8_t *)&cfid, 2); } +#if 0 /* 11.1.9 */ static int verify_pin(struct osim_chan_hdl *st, uint8_t pin_nr, char *pin) { @@ -94,6 +95,7 @@ static int verify_pin(struct osim_chan_hdl *st, uint8_t pin_nr, char *pin) return osim_transceive_apdu(st, msg); } +#endif /* 11.1.5 */ static struct msgb *read_record_nr(struct osim_chan_hdl *st, uint8_t rec_nr, uint16_t rec_size) @@ -241,49 +243,59 @@ static int osim_fcp_fd_decode_sim(struct osim_fcp_fd_decoded *ofd, const uint8_t return 0; } -extern struct osim_card_profile *osim_cprof_sim(void *ctx); -extern struct osim_card_profile *osim_cprof_usim(void *ctx); -extern struct osim_card_profile *osim_cprof_isim(void *ctx); - -static struct msgb *try_select_adf_usim(struct osim_chan_hdl *st) +/*! scan an UICC for all installed apps; allocate osim_card_app_hdl for each of them */ +static int osim_uicc_scan_apps(struct osim_chan_hdl *st) { struct tlv_parsed tp; struct osim_fcp_fd_decoded ofd; - struct msgb *msg, *msg2; + struct msgb *msg; uint8_t *cur; int rc, i; + /* we don't know where we currently might be; go back to MF */ + msg = select_file(st, 0x3f00); + if (!msg) + return -EIO; + if (msgb_apdu_sw(msg) != 0x9000) + return -msgb_apdu_sw(msg); + + /* select EF.DIR */ msg = select_file(st, 0x2f00); if (!msg) - return NULL; + return -EIO; /* return status word in case of error */ if (msgb_apdu_sw(msg) != 0x9000) - return msg; + return -msgb_apdu_sw(msg); + /* various FCP related sanity checks */ rc = tlv_parse(&tp, &ts102221_fcp_tlv_def, msgb_apdu_de(msg)+2, msgb_apdu_le(msg)-2, 0, 0); if (rc < 0) { + fprintf(stderr, "Error decoding EF.DIR FCP TLV\n"); msgb_free(msg); - return NULL; + return -EINVAL; } dump_fcp_template(&tp); if (!TLVP_PRESENT(&tp, UICC_FCP_T_FILE_DESC) || TLVP_LEN(&tp, UICC_FCP_T_FILE_DESC) < 5) { + fprintf(stderr, "No EF.DIR FCP file description\n"); msgb_free(msg); - return NULL; + return -EINVAL; } rc = osim_fcp_fd_decode(&ofd, TLVP_VAL(&tp, UICC_FCP_T_FILE_DESC), TLVP_LEN(&tp, UICC_FCP_T_FILE_DESC)); if (rc < 0) { + fprintf(stderr, "Error decoding EF.DIR FCP file description\n"); msgb_free(msg); - return NULL; + return -EINVAL; } if (ofd.type != TYPE_EF || ofd.ef_type != EF_TYPE_RECORD_FIXED) { + fprintf(stderr, "EF.DIR is not a fixed record EF!?!\n"); msgb_free(msg); - return NULL; + return -EINVAL; } msgb_free(msg); @@ -291,39 +303,46 @@ static struct msgb *try_select_adf_usim(struct osim_chan_hdl *st) printf("ofd rec_len = %u, num_rec = %u\n", ofd.rec_len, ofd.num_rec); for (i = 0; i < ofd.num_rec; i++) { + const uint8_t *aid; + uint8_t aid_len; msg = read_record_nr(st, i+1, ofd.rec_len); - if (!msg) - return NULL; + if (!msg) { + fprintf(stderr, "Error reading Record %u of EF.DIR, skipping\n", i+1); + continue; + } + + /* Entries look like this: + * 61194f10 a0000000871002ffffffff8907090000 5005 5553696d31 ffffffffffffffffffffff */ cur = msgb_apdu_de(msg); if (msgb_apdu_le(msg) < 5) { + fprintf(stderr, "Record length %u too short for EF.DIR, skipping\n", msgb_apdu_le(msg)); msgb_free(msg); - return NULL; + continue; } if (cur[0] != 0x61 || cur[1] < 0x03 || cur[1] > 0x7f || cur[2] != 0x4F || cur[3] < 0x01 || cur[3] > 0x10) { + fprintf(stderr, "Unexpected/unknown record in EF.DIR: %s, skipping\n", + osmo_hexdump_nospc(msgb_apdu_de(msg), msgb_apdu_le(msg))); msgb_free(msg); - return NULL; + continue; } + aid_len = cur[3]; + aid = cur+4; - /* FIXME: actually check if it is an AID that we support, or - * iterate until we find one that we support */ - - msg2 = select_adf(st, cur+4, cur[3]); - - /* attach the USIM profile, FIXME: do this based on AID match */ - st->card->prof = osim_cprof_usim(st->card); - st->cwd = osim_file_desc_find_name(st->card->prof->mf, "ADF.USIM"); - - msgb_free(msg); - - return msg2; + /* FIXME: parse / pass label*/ + printf("Detected AID %s\n", osmo_hexdump_nospc(aid, aid_len)); + osim_card_hdl_add_app(st->card, aid, aid_len, NULL); } - return NULL; + return i; } + +extern struct osim_card_profile *osim_cprof_sim(void *ctx); +extern struct osim_card_profile *osim_cprof_uicc(void *ctx); + static int dump_file(struct osim_chan_hdl *chan, const char *short_name, uint16_t fid) { struct tlv_parsed tp; @@ -557,16 +576,52 @@ static void iterate_fs(struct osim_chan_hdl *chan) } } +static void iterate_apps(struct osim_chan_hdl *chan) +{ + struct osim_card_app_hdl *cah; + + llist_for_each_entry(cah, &chan->card->apps, list) { + const struct osim_card_app_profile *cap = cah->prof; + struct msgb *msg; + + if (!cap) { + fprintf(stderr, "Unknown AID %s; skipping\n", + osmo_hexdump_nospc(cah->aid, cah->aid_len)); + continue; + } + + msg = select_adf(chan, cah->aid, cah->aid_len); + if (!msg) { + fprintf(stderr, "Error selectiong ADF for AID %s; skipping\n", + osmo_hexdump_nospc(cah->aid, cah->aid_len)); + continue; + } + printf("SW: %s\n", osim_print_sw(chan->card, msgb_apdu_sw(msg))); + chan->cur_app = cah; + chan->cwd = cap->adf; + + if (g_output_dir) + mkdir_and_chdir(cap->adf->short_name, 0750); + + iterate_fs(chan); + + if (g_output_dir) + OSMO_ASSERT(chdir("..") == 0); + } +} + int main(int argc, char **argv) { struct osim_reader_hdl *reader; struct osim_card_hdl *card; struct osim_chan_hdl *chan; - struct msgb *msg; + int rc; handle_options(argc, argv); + osim_init(NULL); + if (g_output_dir) { int rc; rc = mkdir(g_output_dir, 0750); @@ -593,34 +648,26 @@ int main(int argc, char **argv) if (!chan) exit(3); - msg = try_select_adf_usim(chan); - if (!msg) { - exit(4); - } else if (msgb_apdu_sw(msg) == 0x6e00) { + //verify_pin(chan, 1, "1653"); + + rc = osim_uicc_scan_apps(chan); + if (rc >= 0) { + chan->card->prof = osim_cprof_uicc(chan->card); + chan->cwd = chan->card->prof->mf; + } else if (rc == -0x6e00) { /* CLA not supported: must be classic SIM, not USIM */ g_class = 0xA0; chan->card->prof = osim_cprof_sim(chan->card); chan->cwd = chan->card->prof->mf; - msgb_free(msg); - } else if (msgb_apdu_sw(msg) == 0x9000) { - /* normal file */ - dump_fcp_template_msg(msg); - msgb_free(msg); - mkdir_and_chdir("ADF_USIM", 0750); + } else if (rc < 0) { + exit(4); } - msg = select_file(chan, 0x6fc5); - dump_fcp_template_msg(msg); - printf("SW: %s\n", osim_print_sw(chan->card, msgb_apdu_sw(msg))); - msgb_free(msg); - - verify_pin(chan, 1, "1653"); - - msg = select_file(chan, 0x6f06); - dump_fcp_template_msg(msg); - msgb_free(msg); - + /* first iterate over normal file system */ iterate_fs(chan); + /* then itereate over all apps and their file system */ + iterate_apps(chan); + exit(0); } |