diff options
Diffstat (limited to 'src/sim')
-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 |
6 files changed, 181 insertions, 71 deletions
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 |