aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2020-03-20 13:05:40 +0100
committerHarald Welte <laforge@osmocom.org>2020-03-21 16:31:17 +0100
commit429adecfd8e817b1d3d4eb9590ee0e351696bad9 (patch)
treeffbae2a5fcd1ee02fe07e23691fea59fe2e8331d
parentbf90d747ad678fd301831b299c12f9de332341f9 (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.h47
-rw-r--r--src/sim/card_fs_isim.c32
-rw-r--r--src/sim/card_fs_uicc.c50
-rw-r--r--src/sim/card_fs_usim.c55
-rw-r--r--src/sim/core.c101
-rw-r--r--src/sim/reader_pcsc.c1
-rw-r--r--src/sim/sim_int.h13
-rw-r--r--utils/osmo-sim-test.c149
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);
}