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 }