00001 
00002 
00003 
00004 
00005 
00006 
00007 #include <ccid.h>
00008 #include <sim.h>
00009 #include "sim-internal.h"
00010 
00011 #if DEBUG
00012 #define dprintf print
00013 #else
00014 #define dprintf(...) do {} while(0)
00015 #endif
00016 
00017 static void chv_byte(uint8_t b, const char *label)
00018 {
00019         dprintf(" gsm: %s: %u tries remaining\n", label, b & 0xf);
00020         dprintf(" gsm: %s: secret code %sinitialized\n", label,
00021                 (b & 0x80) ? "" : "not ");
00022 }
00023 
00024 static int set_df_fci(struct _sim *s, const uint8_t *fci, size_t fci_len)
00025 {
00026         memset(&s->s_df_fci, 0, sizeof(s->s_df_fci));
00027         memset(&s->s_ef_fci, 0, sizeof(s->s_ef_fci));
00028 
00029         if ( fci_len < sizeof(s->s_df_fci) ) {
00030                 dprintf("sim_apdu: DF/MF FCI incomplete\n");
00031                 return 0;
00032         }
00033         memcpy(&s->s_df_fci, fci, sizeof(s->s_df_fci));
00034         fci += sizeof(s->s_df_fci);
00035         fci_len -= sizeof(s->s_df_fci);
00036 
00037         s->s_df_fci.d_free = sys_be16(s->s_df_fci.d_free);
00038         s->s_df_fci.d_id = sys_be16(s->s_df_fci.d_id);
00039         dprintf("sim_apdu: DF 0x%.4x selected\n", s->s_df);
00040 
00041         dprintf(" df: %u bytes free\n", s->s_df_fci.d_free);
00042 
00043         if ( fci_len < s->s_df_fci.d_opt_len ) {
00044                 dprintf("sim_apdu: DF/MF FCI optional data incomplete\n");
00045                 return 0;
00046         }
00047 
00048         if ( fci_len < sizeof(struct df_gsm) ) {
00049                 dprintf("sim_apdu: DF/MF FCI GSM data incomplete\n");
00050                 return 0;
00051         }
00052 
00053         memcpy(&s->s_df_gsm, fci, sizeof(s->s_df_gsm));
00054         fci += sizeof(s->s_df_gsm);
00055         fci_len -= sizeof(s->s_df_gsm);
00056 
00057         if ( fci_len ) {
00058                 dprintf("sim_apdu: %u bytes remaining data in FCI:\n", fci_len);
00059                 hex_dump(fci, fci_len, 16);
00060         }
00061 
00062 
00063 
00064         dprintf(" gsm: %u child DF's\n", s->s_df_gsm.g_num_df);
00065         dprintf(" gsm: %u child EF's\n", s->s_df_gsm.g_num_ef);
00066         dprintf(" gsm: %u locks n chains n shit\n", s->s_df_gsm.g_chv);
00067         chv_byte(s->s_df_gsm.g_chv1, "CHV1");
00068         chv_byte(s->s_df_gsm.g_chv1u, "CHV1 Unblock");
00069         chv_byte(s->s_df_gsm.g_chv2, "CHV2");
00070         chv_byte(s->s_df_gsm.g_chv2u, "CHV2 Unblock");
00071 
00072         return 1;
00073 }
00074 
00075 static void access_nibble(uint8_t n, const char *label)
00076 {
00077         switch(n) {
00078         case 0:
00079                 dprintf(" ef: access %s: ALW\n", label);
00080                 return;
00081         case 1:
00082                 dprintf(" ef: access %s: CHV1\n", label);
00083                 return;
00084         case 2:
00085                 dprintf(" ef: access %s: CHV2\n", label);
00086                 return;
00087         case 4:
00088         case 0xe:
00089                 dprintf(" ef: access %s: ADM\n", label);
00090                 return;
00091         case 0xf:
00092                 dprintf(" ef: access %s: NEV\n", label);
00093                 return;
00094         default:
00095                 dprintf(" ef: access %s: RFU %.1x\n", label, n);
00096                 return;
00097         }
00098 }
00099 
00100 static int set_ef_fci(struct _sim *s, const uint8_t *fci, size_t fci_len)
00101 {
00102         if ( fci_len < sizeof(s->s_ef_fci) ) {
00103                 dprintf("sim_apdu: EF FCI incomplete\n");
00104                 return 0;
00105         }
00106         memcpy(&s->s_ef_fci, fci, sizeof(s->s_ef_fci));
00107         fci += sizeof(s->s_ef_fci);
00108         fci_len -= sizeof(s->s_ef_fci);
00109 
00110         s->s_ef_fci.e_size = sys_be16(s->s_ef_fci.e_size);
00111         s->s_ef_fci.e_id = sys_be16(s->s_ef_fci.e_id);
00112         dprintf("sim_apdu: EF 0x%.4x selected (parent DF = 0x%.4x)\n",
00113                 s->s_ef, s->s_df);
00114 
00115         switch(s->s_ef_fci.e_struct) {
00116         case EF_TRANSPARENT:
00117                 dprintf(" ef: transparent\n");
00118                 break;
00119         case EF_LINEAR:
00120                 dprintf(" ef: linear, rec_len = %u bytes\n",
00121                         s->s_ef_fci.e_reclen);
00122                 break;
00123         case EF_CYCLIC:
00124                 dprintf(" ef: cyclic, rec_len = %u bytes\n",
00125                         s->s_ef_fci.e_reclen);
00126                 if ( 0x40 & s->s_ef_fci.e_increase )
00127                         dprintf(" ef: INCREASE permitted\n");
00128                 break;
00129         }
00130         dprintf(" ef: %u bytes\n", s->s_ef_fci.e_size);
00131         access_nibble(s->s_ef_fci.e_access[0] >> 4, "READ, SEEK");
00132         access_nibble(s->s_ef_fci.e_access[0] & 0xf, "UPDATE");
00133         access_nibble(s->s_ef_fci.e_access[1] >> 4, "INCREASE");
00134         access_nibble(s->s_ef_fci.e_access[2] >> 4, "INVALIDATE");
00135         access_nibble(s->s_ef_fci.e_access[2] & 0xf, "REHABILITATE");
00136         if ( s->s_ef_fci.e_status & 0x1 )
00137                 dprintf(" ef: INVALIDATED\n");
00138 
00139         if ( fci_len < s->s_ef_fci.e_opt_len - EF_FCI_MIN_OPT_LEN) {
00140                 dprintf("sim_apdu: EF FCI optional data incomplete\n");
00141                 return 0;
00142         }
00143 
00144         if ( fci_len ) {
00145                 dprintf("sim_apdu: %u bytes remaining data in FCI:\n", fci_len);
00146                 hex_dump(fci, fci_len, 16);
00147         }
00148 
00149         return 1;
00150 }
00151 
00152 static int set_fci(struct _sim *s, uint16_t id)
00153 {
00154         const uint8_t *fci;
00155         size_t fci_len;
00156         struct fci f;
00157 
00158         memset(&s->s_ef_fci, 0, sizeof(s->s_ef_fci));
00159 
00160         fci = xfr_rx_data(s->s_xfr, &fci_len);
00161         if ( NULL == fci )
00162                 return 0;
00163 
00164         if ( fci_len < sizeof(f) )
00165                 return 0;
00166 
00167         memcpy(&f, fci, sizeof(f));
00168         f.f_id = sys_be16(f.f_id);
00169 
00170         switch(f.f_id & SIM_TYPE_MASK) {
00171         case SIM_TYPE_DF:
00172         case SIM_MF:
00173                 s->s_df = f.f_id;
00174                 s->s_ef = SIM_FILE_INVALID;
00175                 if ( !set_df_fci(s, fci, fci_len) )
00176                         return 0;
00177                 break;
00178         case SIM_TYPE_EF:
00179         case SIM_TYPE_ROOT_EF:
00180                 s->s_ef = f.f_id;
00181                 if ( !set_ef_fci(s, fci, fci_len) )
00182                         return 0;
00183                 break;
00184         default:
00185                 dprintf("sim_apdu: unknown file type selected\n");
00186                 return (id == f.f_id);
00187         }
00188 
00189         return (id == f.f_id);
00190 }
00191 
00192 static int _sim_select(struct _sim *s, uint16_t id)
00193 {
00194         if ( !_apdu_select(s, id) )
00195                 return 0;
00196 
00197         return set_fci(s, id);
00198 }
00199 
00200 static const uint8_t *_sim_read_binary(struct _sim *s, size_t *len)
00201 {
00202         if ( !_apdu_read_binary(s, 0, s->s_ef_fci.e_size) )
00203                 return 0;
00204 
00205         return xfr_rx_data(s->s_xfr, len);
00206 }
00207 
00208 static const uint8_t *_sim_read_record(struct _sim *s, uint8_t rec, size_t *len)
00209 {
00210         if ( !_apdu_read_record(s, rec, s->s_ef_fci.e_reclen) )
00211                 return 0;
00212 
00213         return xfr_rx_data(s->s_xfr, len);
00214 }
00215 
00216 static void read_iccid(struct _sim *s)
00217 {
00218         const uint8_t *ptr;
00219         size_t len, i;
00220 
00221         _sim_select(s, SIM_EF_ICCID);
00222         ptr = _sim_read_binary(s, &len);
00223 
00224         printf("ICCID: ");
00225         for(i = 0; i < len && ptr[i] != 0xff; i++) {
00226                 if ( i && !(i % 2) )
00227                         printf("-");
00228                 printf("%.1x", ptr[i] & 0xf);
00229                 if ( (ptr[i] >> 4) != 0xf )
00230                         printf("%.1x", ptr[i] >> 4);
00231         }
00232         printf("\n");
00233 }
00234 
00235 static void read_imsi(struct _sim *s)
00236 {
00237         const uint8_t *ptr;
00238         size_t len, i;
00239 
00240         _sim_select(s, SIM_DF_GSM);
00241         _sim_select(s, SIM_EF_IMSI);
00242         ptr = _sim_read_binary(s, &len);
00243 
00244         printf("IMSI: ");
00245         for(i = 0; i < len && ptr[i] != 0xff; i++) {
00246                 if ( i && !(i % 2) )
00247                         printf("-");
00248                 printf("%.1x", ptr[i] & 0xf);
00249                 if ( (ptr[i] >> 4) != 0xf )
00250                         printf("%.1x", ptr[i] >> 4);
00251         }
00252         printf("\n");
00253 }
00254 
00255 int sim_sms_save(sim_t s, const char *fn)
00256 {
00257         const uint8_t *ptr;
00258         size_t num_rec, i, len;
00259         FILE *f;
00260 
00261         if ( !_sim_select(s, SIM_DF_TELECOM) )
00262                 return 0;
00263 
00264         if ( !_sim_select(s, SIM_EF_SMS) )
00265                 return 0;
00266 
00267         f = fopen(fn, "w");
00268         if ( NULL == f )
00269                 return 0;
00270 
00271         printf("Saving SMS messages to '%s'", fn);
00272         fflush(stdout);
00273         num_rec = s->s_ef_fci.e_size / s->s_ef_fci.e_reclen;
00274         for(i = 1; i <= num_rec; i++) {
00275                 ptr = _sim_read_record(s, i, &len);
00276                 if ( NULL == ptr )
00277                         continue;
00278                 fwrite(ptr, len, 1, f);
00279                 printf(".");
00280                 fflush(stdout);
00281         }
00282         printf("\n");
00283 
00284         fclose(f);
00285         return 1;
00286 }
00287 
00288 int sim_sms_restore(sim_t s, const char *fn)
00289 {
00290         FILE *f;
00291         uint8_t buf[176];
00292         unsigned int i;
00293         struct _sms sms;
00294 
00295         f = fopen(fn, "r");
00296         if ( NULL == f )
00297                 return 0;
00298 
00299         printf("Reading SMS messages from '%s':\n", fn);
00300         for(i = 1; fread(buf, sizeof(buf), 1, f) == 1; i++) {
00301                 _sms_decode(&sms, buf);
00302         }
00303 
00304         fclose(f);
00305         return 1;
00306 }
00307 
00308 sim_t sim_new(chipcard_t cc)
00309 {
00310         struct _sim *s;
00311         const uint8_t *atr;
00312         size_t atr_len;
00313 
00314         s = calloc(1, sizeof(*s));
00315         if ( NULL == s )
00316                 goto err;
00317 
00318         s->s_cc = cc;
00319 
00320         s->s_xfr = xfr_alloc(502, 502);
00321         if ( NULL == s->s_xfr )
00322                 goto err_free;
00323 
00324         atr = chipcard_slot_on(s->s_cc, CHIPCARD_AUTO_VOLTAGE, &atr_len);
00325         if ( NULL == atr )
00326                 goto err_free_xfr;
00327 
00328         printf(" o Found SIM with %u byte ATR:\n", atr_len);
00329         hex_dump(atr, atr_len, 16);
00330 
00331         if ( !_sim_select(s, SIM_MF) )
00332                 goto err_free_xfr;
00333 
00334         read_iccid(s);
00335         read_imsi(s);
00336 
00337         return s;
00338 
00339 err_free_xfr:
00340         xfr_free(s->s_xfr);
00341 err_free:
00342         free(s);
00343 err:
00344         return NULL;
00345 }
00346 
00347 void sim_free(sim_t s)
00348 {
00349         if ( s ) {
00350                 if ( s->s_xfr )
00351                         xfr_free(s->s_xfr);
00352                 if ( s->s_cc )
00353                         chipcard_slot_off(s->s_cc);
00354         }
00355         free(s);
00356 }