<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/17555">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

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

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ic4b4ac433a9976842b30a017fb0fc347d87201cd </div>
<div style="display:none"> Gerrit-Change-Number: 17555 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>