[layer23] SIM client accepts status code 61xx as a positive result
[osmocom-bb.git] / src / host / layer23 / src / mobile / sim.c
1 /*
2  * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
3  *
4  * All Rights Reserved
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  */
21
22 #include <stdint.h>
23 #include <errno.h>
24 #include <arpa/inet.h>
25 #include <osmocore/talloc.h>
26 #include <osmocore/utils.h>
27
28 #include <osmocom/bb/common/logging.h>
29 #include <osmocom/bb/common/osmocom_data.h>
30
31 extern void *l23_ctx;
32 static int sim_process_job(struct osmocom_ms *ms);
33
34 /*
35  * support
36  */
37
38 uint32_t new_handle = 1;
39
40 static struct gsm1111_df_name {
41         uint16_t file;
42         const char *name;
43 } gsm1111_df_name[] = {
44         { 0x3f00, "MF" },
45         { 0x7f20, "DFgsm" },
46         { 0x7f10, "DFtelecom" },
47         { 0x7f22, "DFis-41" },
48         { 0x7f23, "DFfp-cts" },
49         { 0x5f50, "DFgraphics" },
50         { 0x5f30, "DFiridium" },
51         { 0x5f31, "DFglobst" },
52         { 0x5f32, "DFico" },
53         { 0x5f33, "DFaces" },
54         { 0x5f40, "DFeia/tia-553" },
55         { 0x5f60, "DFcts" },
56         { 0x5f70, "DFsolsa" },
57         { 0x5f3c, "DFmexe" },
58         { 0, NULL }
59 };
60
61 static const char *get_df_name(uint16_t fid)
62 {
63         int i;
64         static char text[7];
65
66         for (i = 0; gsm1111_df_name[i].file; i++)
67                 if (gsm1111_df_name[i].file == fid)
68                         break;
69         if (gsm1111_df_name[i].file)
70                 return gsm1111_df_name[i].name;
71
72         sprintf(text, "0x%04x", fid);
73         return text;
74 }
75
76 static struct gsm_sim_handler *sim_get_handler(struct gsm_sim *sim,
77         uint32_t handle)
78 {
79         struct gsm_sim_handler *handler;
80
81         llist_for_each_entry(handler, &sim->handlers, entry)
82                 if (handler->handle == handle)
83                         return handler;
84
85         return NULL;
86 }
87
88 /*
89  * messages
90  */
91
92 static const struct value_string sim_job_names[] = {
93         { SIM_JOB_READ_BINARY,          "SIM_JOB_READ_BINARY" },
94         { SIM_JOB_UPDATE_BINARY,        "SIM_JOB_UPDATE_BINARY" },
95         { SIM_JOB_READ_RECORD,          "SIM_JOB_READ_RECORD" },
96         { SIM_JOB_UPDATE_RECORD,        "SIM_JOB_UPDATE_RECORD" },
97         { SIM_JOB_SEEK_RECORD,          "SIM_JOB_SEEK_RECORD" },
98         { SIM_JOB_INCREASE,             "SIM_JOB_INCREASE" },
99         { SIM_JOB_INVALIDATE,           "SIM_JOB_INVALIDATE" },
100         { SIM_JOB_REHABILITATE,         "SIM_JOB_REHABILITATE" },
101         { SIM_JOB_RUN_GSM_ALGO,         "SIM_JOB_RUN_GSM_ALGO" },
102         { SIM_JOB_PIN1_UNLOCK,          "SIM_JOB_PIN1_UNLOCK" },
103         { SIM_JOB_PIN1_CHANGE,          "SIM_JOB_PIN1_CHANGE" },
104         { SIM_JOB_PIN1_DISABLE,         "SIM_JOB_PIN1_DISABLE" },
105         { SIM_JOB_PIN1_ENABLE,          "SIM_JOB_PIN1_ENABLE" },
106         { SIM_JOB_PIN1_UNBLOCK,         "SIM_JOB_PIN1_UNBLOCK" },
107         { SIM_JOB_PIN2_UNLOCK,          "SIM_JOB_PIN2_UNLOCK" },
108         { SIM_JOB_PIN2_CHANGE,          "SIM_JOB_PIN2_CHANGE" },
109         { SIM_JOB_PIN2_UNBLOCK,         "SIM_JOB_PIN2_UNBLOCK" },
110         { SIM_JOB_OK,                   "SIM_JOB_OK" },
111         { SIM_JOB_ERROR,                "SIM_JOB_ERROR" },
112         { 0,                            NULL }
113 };
114
115 static const char *get_job_name(int value)
116 {
117         return get_value_string(sim_job_names, value);
118 }
119
120 /* allocate sim client message (upper layer) */
121 struct msgb *gsm_sim_msgb_alloc(uint32_t handle, uint8_t job_type)
122 {
123         struct msgb *msg;
124         struct sim_hdr *nsh;
125
126         msg = msgb_alloc_headroom(SIM_ALLOC_SIZE+SIM_ALLOC_HEADROOM,
127                 SIM_ALLOC_HEADROOM, "SIM");
128         if (!msg)
129                 return NULL;
130
131         nsh = (struct sim_hdr *) msgb_put(msg, sizeof(*nsh));
132         nsh->handle = handle;
133         nsh->job_type = job_type;
134
135         return msg;
136 }
137
138 /* reply to job, after it is done. reuse the msgb in the job */
139 void gsm_sim_reply(struct osmocom_ms *ms, uint8_t result_type, uint8_t *result,
140         uint16_t result_len)
141 {
142         struct gsm_sim *sim = &ms->sim;
143         struct msgb *msg = sim->job_msg;
144         struct sim_hdr *sh;
145         uint8_t *payload;
146         uint16_t payload_len;
147         struct gsm_sim_handler *handler;
148
149         LOGP(DSIM, LOGL_INFO, "sending result to callback function\n");
150
151         /* if no handler, or no callback, just free the job */
152         sh = (struct sim_hdr *)msg->data;
153         handler = sim_get_handler(sim, sh->handle);
154         if (!handler && !handler->cb) {
155                 LOGP(DSIM, LOGL_INFO, "no callback or no handler, "
156                         "dropping result\n");
157                 msgb_free(sim->job_msg);
158                 sim->job_msg = NULL;
159                 sim->job_state = SIM_JST_IDLE;
160                 return;
161         }
162
163         payload = msg->data + sizeof(*sh);
164         payload_len = msg->len - sizeof(*sh);
165
166         /* remove data */
167         msg->tail -= payload_len;
168         msg->len -= payload_len;
169
170         /* add reply data */
171         sh->job_type = result_type;
172         if (result_len)
173                 memcpy(msgb_put(msg, result_len), result, result_len);
174
175         /* callback */
176         sim->job_state = SIM_JST_IDLE;
177         sim->job_msg = NULL;
178         handler->cb(ms, msg);
179 }
180
181 /* send APDU to card reader */
182 static int sim_apdu_send(struct osmocom_ms *ms, uint8_t *data, uint16_t length)
183 {
184         // FIXME: send apdu to layer 1
185         LOGP(DSIM, LOGL_INFO, "sending APDU (class 0x%02x, ins 0x%02x)\n",
186                 data[0], data[1]);
187         printf("process stops here, because no APDU is exchanged with layer 1\n");
188         return 0;
189 }
190
191 /* dequeue messages (RSL-SAP) */
192 int gsm_sim_job_dequeue(struct osmocom_ms *ms)
193 {
194         struct gsm_sim *sim = &ms->sim;
195         struct sim_hdr *sh;
196         struct msgb *msg;
197         struct gsm_sim_handler *handler;
198
199         /* already have a job */
200         if (sim->job_msg)
201                 return 0;
202
203         /* get next job */
204         while ((msg = msgb_dequeue(&sim->jobs))) {
205                 /* resolve handler */
206                 sh = (struct sim_hdr *) msg->data;
207                 LOGP(DSIM, LOGL_INFO, "got new job: %s (handle=%08x)\n",
208                         get_job_name(sh->job_type), sh->handle);
209                 handler = sim_get_handler(sim, sh->handle);
210                 if (!handler) {
211                         LOGP(DSIM, LOGL_INFO, "no handler, ignoring job\n");
212                         /* does not exist anymore */
213                         msgb_free(msg);
214                         continue;
215                 }
216
217                 /* init job */
218                 sim->job_state = SIM_JST_IDLE;
219                 sim->job_msg = msg;
220                 sim->job_handle = sh->handle;
221
222                 /* process current job, message is freed there */
223                 sim_process_job(ms);
224                 return 1; /* work done */
225         }
226         
227         return 0;
228 }
229
230
231 /*
232  * SIM commands
233  */
234
235 /* 9.2.1 */
236 static int gsm1111_tx_select(struct osmocom_ms *ms, uint16_t fid)
237 {
238         uint8_t buffer[5 + 2];
239
240         LOGP(DSIM, LOGL_INFO, "SELECT (file=0x%04x)\n", fid);
241         buffer[0] = GSM1111_CLASS_GSM;
242         buffer[1] = GSM1111_INST_SELECT;
243         buffer[2] = 0x00;
244         buffer[3] = 0x00;
245         buffer[4] = 2;
246         buffer[5] = fid >> 8;
247         buffer[6] = fid;
248
249         return sim_apdu_send(ms, buffer, 5 + 2);
250 }
251
252 #if 0
253 /* 9.2.2 */
254 static int gsm1111_tx_status(struct osmocom_ms *ms)
255 {
256         uint8_t buffer[5];
257
258         LOGP(DSIM, LOGL_INFO, "STATUS\n");
259         buffer[0] = GSM1111_CLASS_GSM;
260         buffer[1] = GSM1111_INST_STATUS;
261         buffer[2] = 0x00;
262         buffer[3] = 0x00;
263         buffer[4] = 0;
264
265         return sim_apdu_send(ms, buffer, 5);
266 }
267 #endif
268
269 /* 9.2.3 */
270 static int gsm1111_tx_read_binary(struct osmocom_ms *ms, uint16_t offset,
271         uint8_t length)
272 {
273         uint8_t buffer[5];
274
275         LOGP(DSIM, LOGL_INFO, "READ BINARY (offset=%d len=%d)\n", offset,
276                 length);
277         buffer[0] = GSM1111_CLASS_GSM;
278         buffer[1] = GSM1111_INST_READ_BINARY;
279         buffer[2] = offset >> 8;
280         buffer[3] = offset;
281         buffer[4] = length;
282
283         return sim_apdu_send(ms, buffer, 5);
284 }
285
286 /* 9.2.4 */
287 static int gsm1111_tx_update_binary(struct osmocom_ms *ms, uint16_t offset,
288         uint8_t *data, uint8_t length)
289 {
290         uint8_t buffer[5 + length];
291
292         LOGP(DSIM, LOGL_INFO, "UPDATE BINARY (offset=%d len=%d)\n", offset,
293                 length);
294         buffer[0] = GSM1111_CLASS_GSM;
295         buffer[1] = GSM1111_INST_UPDATE_BINARY;
296         buffer[2] = offset >> 8;
297         buffer[3] = offset;
298         buffer[4] = length;
299         memcpy(buffer + 5, data, length);
300
301         return sim_apdu_send(ms, buffer, 5 + length);
302 }
303
304 /* 9.2.5 */
305 static int gsm1111_tx_read_record(struct osmocom_ms *ms, uint8_t rec_no,
306         uint8_t mode, uint8_t length)
307 {
308         uint8_t buffer[5];
309
310         LOGP(DSIM, LOGL_INFO, "READ RECORD (rec_no=%d mode=%d len=%d)\n",
311                 rec_no, mode, length);
312         buffer[0] = GSM1111_CLASS_GSM;
313         buffer[1] = GSM1111_INST_READ_RECORD;
314         buffer[2] = rec_no;
315         buffer[3] = mode;
316         buffer[4] = length;
317
318         return sim_apdu_send(ms, buffer, 5);
319 }
320
321 /* 9.2.6 */
322 static int gsm1111_tx_update_record(struct osmocom_ms *ms, uint8_t rec_no,
323         uint8_t mode, uint8_t *data, uint8_t length)
324 {
325         uint8_t buffer[5 + length];
326
327         LOGP(DSIM, LOGL_INFO, "UPDATE RECORD (rec_no=%d mode=%d len=%d)\n",
328                 rec_no, mode, length);
329         buffer[0] = GSM1111_CLASS_GSM;
330         buffer[1] = GSM1111_INST_UPDATE_RECORD;
331         buffer[2] = rec_no;
332         buffer[3] = mode;
333         buffer[4] = length;
334         memcpy(buffer + 5, data, length);
335
336         return sim_apdu_send(ms, buffer, 5 + length);
337 }
338
339 /* 9.2.7 */
340 static int gsm1111_tx_seek(struct osmocom_ms *ms, uint8_t type_mode,
341         uint8_t *pattern, uint8_t length)
342 {
343         uint8_t buffer[5 + length];
344         uint8_t type = type_mode >> 4;
345         uint8_t mode = type_mode & 0x0f;
346
347         LOGP(DSIM, LOGL_INFO, "SEEK (type=%d mode=%d len=%d)\n", type, mode,
348                 length);
349         buffer[0] = GSM1111_CLASS_GSM;
350         buffer[1] = GSM1111_INST_SEEK;
351         buffer[2] = 0x00;
352         buffer[3] = type_mode;
353         buffer[4] = length;
354         memcpy(buffer + 5, pattern, length);
355
356         return sim_apdu_send(ms, buffer, 5 + length);
357 }
358
359 /* 9.2.8 */
360 static int gsm1111_tx_increase(struct osmocom_ms *ms, uint32_t value)
361 {
362         uint8_t buffer[5 + 3];
363
364         LOGP(DSIM, LOGL_INFO, "INCREASE (value=%d)\n", value);
365         buffer[0] = GSM1111_CLASS_GSM;
366         buffer[1] = GSM1111_INST_INCREASE;
367         buffer[2] = 0x00;
368         buffer[3] = 0x00;
369         buffer[4] = 3;
370         buffer[5] = value >> 16;
371         buffer[6] = value >> 8;
372         buffer[7] = value;
373
374         return sim_apdu_send(ms, buffer, 5 + 3);
375 }
376
377 /* 9.2.9 */
378 static int gsm1111_tx_verify_chv(struct osmocom_ms *ms, uint8_t chv_no,
379         uint8_t *chv, uint8_t length)
380 {
381         uint8_t buffer[5 + 8];
382         int i;
383
384         LOGP(DSIM, LOGL_INFO, "VERIFY CHV (CHV%d)\n", chv_no);
385         buffer[0] = GSM1111_CLASS_GSM;
386         buffer[1] = GSM1111_INST_VERIFY_CHV;
387         buffer[2] = 0x00;
388         buffer[3] = chv_no;
389         buffer[4] = 8;
390         for (i = 0; i < 8; i++) {
391                 if (i < length)
392                         buffer[5 + i] = chv[i];
393                 else
394                         buffer[5 + i] = 0xff;
395         }
396
397         return sim_apdu_send(ms, buffer, 5 + 8);
398 }
399
400 /* 9.2.10 */
401 static int gsm1111_tx_change_chv(struct osmocom_ms *ms, uint8_t chv_no,
402         uint8_t *chv_old, uint8_t length_old, uint8_t *chv_new,
403         uint8_t length_new)
404 {
405         uint8_t buffer[5 + 16];
406         int i;
407
408         LOGP(DSIM, LOGL_INFO, "CHANGE CHV (CHV%d)\n", chv_no);
409         buffer[0] = GSM1111_CLASS_GSM;
410         buffer[1] = GSM1111_INST_CHANGE_CHV;
411         buffer[2] = 0x00;
412         buffer[3] = chv_no;
413         buffer[4] = 8;
414         for (i = 0; i < 8; i++) {
415                 if (i < length_old)
416                         buffer[5 + i] = chv_old[i];
417                 else
418                         buffer[5 + i] = 0xff;
419                 if (i < length_new)
420                         buffer[13 + i] = chv_new[i];
421                 else
422                         buffer[13 + i] = 0xff;
423         }
424
425         return sim_apdu_send(ms, buffer, 5 + 16);
426 }
427
428 /* 9.2.11 */
429 static int gsm1111_tx_disable_chv(struct osmocom_ms *ms, uint8_t *chv,
430         uint8_t length)
431 {
432         uint8_t buffer[5 + 8];
433         int i;
434
435         LOGP(DSIM, LOGL_INFO, "DISABLE CHV (CHV1)\n");
436         buffer[0] = GSM1111_CLASS_GSM;
437         buffer[1] = GSM1111_INST_DISABLE_CHV;
438         buffer[2] = 0x00;
439         buffer[3] = 0x01;
440         buffer[4] = 8;
441         for (i = 0; i < 8; i++) {
442                 if (i < length)
443                         buffer[5 + i] = chv[i];
444                 else
445                         buffer[5 + i] = 0xff;
446         }
447
448         return sim_apdu_send(ms, buffer, 5 + 8);
449 }
450
451 /* 9.2.12 */
452 static int gsm1111_tx_enable_chv(struct osmocom_ms *ms, uint8_t *chv,
453         uint8_t length)
454 {
455         uint8_t buffer[5 + 8];
456         int i;
457
458         LOGP(DSIM, LOGL_INFO, "ENABLE CHV (CHV1)\n");
459         buffer[0] = GSM1111_CLASS_GSM;
460         buffer[1] = GSM1111_INST_ENABLE_CHV;
461         buffer[2] = 0x00;
462         buffer[3] = 0x01;
463         buffer[4] = 8;
464         for (i = 0; i < 8; i++) {
465                 if (i < length)
466                         buffer[5 + i] = chv[i];
467                 else
468                         buffer[5 + i] = 0xff;
469         }
470
471         return sim_apdu_send(ms, buffer, 5 + 8);
472 }
473
474 /* 9.2.13 */
475 static int gsm1111_tx_unblock_chv(struct osmocom_ms *ms, uint8_t chv_no,
476         uint8_t *chv_unblk, uint8_t length_unblk, uint8_t *chv_new,
477         uint8_t length_new)
478 {
479         uint8_t buffer[5 + 16];
480         int i;
481
482         LOGP(DSIM, LOGL_INFO, "UNBLOCK CHV (CHV%d)\n", (chv_no == 2) ? 2 : 1);
483         buffer[0] = GSM1111_CLASS_GSM;
484         buffer[1] = GSM1111_INST_UNBLOCK_CHV;
485         buffer[2] = 0x00;
486         buffer[3] = (chv_no == 1) ? 0 : chv_no;
487         buffer[4] = 8;
488         for (i = 0; i < 8; i++) {
489                 if (i < length_unblk)
490                         buffer[5 + i] = chv_unblk[i];
491                 else
492                         buffer[5 + i] = 0xff;
493                 if (i < length_new)
494                         buffer[13 + i] = chv_new[i];
495                 else
496                         buffer[13 + i] = 0xff;
497         }
498
499         return sim_apdu_send(ms, buffer, 5 + 16);
500 }
501
502 /* 9.2.14 */
503 static int gsm1111_tx_invalidate(struct osmocom_ms *ms)
504 {
505         uint8_t buffer[5];
506
507         LOGP(DSIM, LOGL_INFO, "INVALIDATE\n");
508         buffer[0] = GSM1111_CLASS_GSM;
509         buffer[1] = GSM1111_INST_INVALIDATE;
510         buffer[2] = 0x00;
511         buffer[3] = 0x00;
512         buffer[4] = 0;
513
514         return sim_apdu_send(ms, buffer, 5);
515 }
516
517 /* 9.2.15 */
518 static int gsm1111_tx_rehabilitate(struct osmocom_ms *ms)
519 {
520         uint8_t buffer[5];
521
522         LOGP(DSIM, LOGL_INFO, "REHABILITATE\n");
523         buffer[0] = GSM1111_CLASS_GSM;
524         buffer[1] = GSM1111_INST_REHABLILITATE;
525         buffer[2] = 0x00;
526         buffer[3] = 0x00;
527         buffer[4] = 0;
528
529         return sim_apdu_send(ms, buffer, 5);
530 }
531
532 /* 9.2.16 */
533 static int gsm1111_tx_run_gsm_algo(struct osmocom_ms *ms, uint8_t *rand)
534 {
535         uint8_t buffer[5 + 16];
536
537         LOGP(DSIM, LOGL_INFO, "RUN GSM ALGORITHM\n");
538         buffer[0] = GSM1111_CLASS_GSM;
539         buffer[1] = GSM1111_INST_RUN_GSM_ALGO;
540         buffer[2] = 0x00;
541         buffer[3] = 0x00;
542         buffer[4] = 16;
543         memcpy(buffer + 5, rand, 16);
544
545         return sim_apdu_send(ms, buffer, 5 + 16);
546 }
547
548 #if 0
549 /* 9.2.17 */
550 static int gsm1111_tx_sleep(struct osmocom_ms *ms)
551 {
552         uint8_t buffer[5];
553
554         LOGP(DSIM, LOGL_INFO, "\n");
555         buffer[0] = GSM1111_CLASS_GSM;
556         buffer[1] = GSM1111_INST_SLEEP;
557         buffer[2] = 0x00;
558         buffer[3] = 0x00;
559         buffer[4] = 0;
560
561         return sim_apdu_send(ms, buffer, 5);
562 }
563 #endif
564
565 /* 9.2.18 */
566 static int gsm1111_tx_get_response(struct osmocom_ms *ms, uint8_t length)
567 {
568         uint8_t buffer[5];
569
570         LOGP(DSIM, LOGL_INFO, "GET RESPONSE (len=%d)\n", length);
571         buffer[0] = GSM1111_CLASS_GSM;
572         buffer[1] = GSM1111_INST_GET_RESPONSE;
573         buffer[2] = 0x00;
574         buffer[3] = 0x00;
575         buffer[4] = length;
576
577         return sim_apdu_send(ms, buffer, 5);
578 }
579
580 #if 0
581 /* 9.2.19 */
582 static int gsm1111_tx_terminal_profile(struct osmocom_ms *ms, uint8_t *data,
583         uint8_t length)
584 {
585         uint8_t buffer[5 + length];
586
587         LOGP(DSIM, LOGL_INFO, "TERMINAL PROFILE (len=%d)\n", length);
588         buffer[0] = GSM1111_CLASS_GSM;
589         buffer[1] = GSM1111_INST_TERMINAL_PROFILE;
590         buffer[2] = 0x00;
591         buffer[3] = 0x00;
592         buffer[4] = length;
593         memcpy(buffer + 5, data, length);
594
595         return sim_apdu_send(ms, buffer, 5 + length);
596 }
597
598 /* 9.2.20 */
599 static int gsm1111_tx_envelope(struct osmocom_ms *ms, uint8_t *data,
600         uint8_t length)
601 {
602         uint8_t buffer[5 + length];
603
604         LOGP(DSIM, LOGL_INFO, "ENVELOPE (len=%d)\n", length);
605         buffer[0] = GSM1111_CLASS_GSM;
606         buffer[1] = GSM1111_INST_ENVELOPE;
607         buffer[2] = 0x00;
608         buffer[3] = 0x00;
609         buffer[4] = length;
610         memcpy(buffer + 5, data, length);
611
612         return sim_apdu_send(ms, buffer, 5 + length);
613 }
614
615 /* 9.2.21 */
616 static int gsm1111_tx_fetch(struct osmocom_ms *ms, uint8_t length)
617 {
618         uint8_t buffer[5];
619
620         LOGP(DSIM, LOGL_INFO, "FETCH (len=%d)\n", length);
621         buffer[0] = GSM1111_CLASS_GSM;
622         buffer[1] = GSM1111_INST_FETCH;
623         buffer[2] = 0x00;
624         buffer[3] = 0x00;
625         buffer[4] = length;
626
627         return sim_apdu_send(ms, buffer, 5);
628 }
629
630 /* 9.2.22 */
631 static int gsm1111_tx_terminal_response(struct osmocom_ms *ms, uint8_t *data,
632         uint8_t length)
633 {
634         uint8_t buffer[5 + length];
635
636         LOGP(DSIM, LOGL_INFO, "TERMINAL RESPONSE (len=%d)\n", length);
637         buffer[0] = GSM1111_CLASS_GSM;
638         buffer[1] = GSM1111_INST_TERMINAL_RESPONSE;
639         buffer[2] = 0x00;
640         buffer[3] = 0x00;
641         buffer[4] = length;
642         memcpy(buffer + 5, data, length);
643
644         return sim_apdu_send(ms, buffer, 5 + length);
645 }
646 #endif
647
648 /*
649  * SIM state machine
650  */
651
652 /* process job */
653 static int sim_process_job(struct osmocom_ms *ms)
654 {
655         struct gsm_sim *sim = &ms->sim;
656         uint8_t *payload;
657         uint16_t payload_len;
658         struct sim_hdr *sh;
659         uint8_t cause;
660         int i;
661
662         /* no current */
663         if (!sim->job_msg)
664                 return 0;
665
666         sh = (struct sim_hdr *)sim->job_msg->data;
667         payload = sim->job_msg->data + sizeof(*sh);
668         payload_len = sim->job_msg->len - sizeof(*sh);
669
670         /* do reset before sim reading */
671         if (!sim->reset) {
672                 sim->reset = 1;
673                 // FIXME: send reset command to L1
674         }
675
676         /* check MF / DF */
677         i = 0;
678         while (sh->path[i] && sim->path[i]) {
679                 if (sh->path[i] != sh->path[i])
680                         break;
681                 i++;
682         }
683         /* if path in message is shorter or if paths are different */
684         if (sim->path[i]) {
685                 LOGP(DSIM, LOGL_INFO, "wrong DF, go MF\n");
686                 sim->job_state = SIM_JST_SELECT_MFDF;
687                 /* go MF */
688                 sim->path[0] = 0;
689                 return gsm1111_tx_select(ms, 0x3f00);
690         }
691         /* if path in message is longer */
692         if (sh->path[i]) {
693                 LOGP(DSIM, LOGL_INFO, "requested path is longer, go child %s\n",
694                         get_df_name(sh->path[i]));
695                 sim->job_state = SIM_JST_SELECT_MFDF;
696                 /* select child */
697                 sim->path[i] = sh->path[i];
698                 sim->path[i + 1] = 0;
699                 return gsm1111_tx_select(ms, sh->path[i]);
700         }
701         /* if paths are equal, continue */
702
703         /* set state and trigger SIM process */
704         switch (sh->job_type) {
705         case SIM_JOB_READ_BINARY:
706         case SIM_JOB_UPDATE_BINARY:
707         case SIM_JOB_READ_RECORD:
708         case SIM_JOB_UPDATE_RECORD:
709         case SIM_JOB_SEEK_RECORD:
710         case SIM_JOB_INCREASE:
711         case SIM_JOB_INVALIDATE:
712         case SIM_JOB_REHABILITATE:
713                 sim->job_state = SIM_JST_SELECT_EF;
714                 return gsm1111_tx_select(ms, sh->file);
715         case SIM_JOB_RUN_GSM_ALGO:
716                 if (payload_len != 16) {
717                         LOGP(DSIM, LOGL_ERROR, "random not 16 bytes\n");
718                         break;
719                 }
720                 sim->job_state = SIM_JST_RUN_GSM_ALGO;
721                 return gsm1111_tx_run_gsm_algo(ms, payload);
722         case SIM_JOB_PIN1_UNLOCK:
723                 if (payload_len < 4 || payload_len > 8) {
724                         LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
725                         break;
726                 }
727                 sim->job_state = SIM_JST_PIN1_UNLOCK;
728                 memcpy(sim->pin1, payload, payload_len);
729                 sim->pin1_len = payload_len;
730                 return gsm1111_tx_verify_chv(ms, 0x01, payload, payload_len);
731         case SIM_JOB_PIN2_UNLOCK:
732                 if (payload_len < 4 || payload_len > 8) {
733                         LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
734                         break;
735                 }
736                 sim->job_state = SIM_JST_PIN2_UNLOCK;
737                 memcpy(sim->pin2, payload, payload_len);
738                 sim->pin2_len = payload_len;
739                 return gsm1111_tx_verify_chv(ms, 0x02, payload, payload_len);
740         case SIM_JOB_PIN1_CHANGE:
741                 if (!sim->pin1_len) {
742                         LOGP(DSIM, LOGL_ERROR, "no pin set\n");
743                         break;
744                 }
745                 if (payload_len < 4 || payload_len > 8 || !sim->pin1_len) {
746                         LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
747                         break;
748                 }
749                 sim->job_state = SIM_JST_PIN1_CHANGE;
750                 return gsm1111_tx_change_chv(ms, 0x01, sim->pin1, sim->pin1_len,
751                         payload, payload_len);
752         case SIM_JOB_PIN2_CHANGE:
753                 if (!sim->pin2_len) {
754                         LOGP(DSIM, LOGL_ERROR, "no pin set\n");
755                         break;
756                 }
757                 if (payload_len < 4 || payload_len > 8) {
758                         LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
759                         break;
760                 }
761                 sim->job_state = SIM_JST_PIN2_CHANGE;
762                 return gsm1111_tx_change_chv(ms, 0x02, sim->pin1, sim->pin1_len,
763                         payload, payload_len);
764         case SIM_JOB_PIN1_DISABLE:
765                 if (!sim->pin1_len) {
766                         LOGP(DSIM, LOGL_ERROR, "no pin set\n");
767                         break;
768                 }
769                 sim->job_state = SIM_JST_PIN1_DISABLE;
770                 return gsm1111_tx_disable_chv(ms, sim->pin1, sim->pin1_len);
771         case SIM_JOB_PIN1_ENABLE:
772                 if (!sim->pin1_len) {
773                         LOGP(DSIM, LOGL_ERROR, "no pin set\n");
774                         break;
775                 }
776                 sim->job_state = SIM_JST_PIN1_ENABLE;
777                 return gsm1111_tx_enable_chv(ms, sim->pin1, sim->pin1_len);
778         case SIM_JOB_PIN1_UNBLOCK:
779                 if (payload_len < 12 || payload_len > 16) {
780                         LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
781                         break;
782                 }
783                 sim->job_state = SIM_JST_PIN1_UNLOCK;
784                 memcpy(sim->pin1, payload + 8, payload_len - 8);
785                 sim->pin1_len = payload_len;
786                 /* NOTE: CHV1 is coded 0x00 here */
787                 return gsm1111_tx_unblock_chv(ms, 0x00, payload, 8, payload + 8,
788                         payload_len - 8);
789         case SIM_JOB_PIN2_UNBLOCK:
790                 if (payload_len < 12 || payload_len > 16) {
791                         LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
792                         break;
793                 }
794                 sim->job_state = SIM_JST_PIN2_UNLOCK;
795                 memcpy(sim->pin2, payload + 8, payload_len - 8);
796                 sim->pin2_len = payload_len;
797                 return gsm1111_tx_unblock_chv(ms, 0x02, payload, 8, payload + 8,
798                         payload_len - 8);
799         }
800
801         LOGP(DSIM, LOGL_ERROR, "unknown job %x, please fix\n", sh->job_type);
802         cause = SIM_CAUSE_REQUEST_ERROR;
803         gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
804
805         return 0;
806 }
807
808 /* receive SIM response */
809 static int sim_apdu_receive(struct osmocom_ms *ms, struct msgb *msg)
810 {
811         struct gsm_sim *sim = &ms->sim;
812         uint8_t *payload;
813         uint16_t payload_len;
814         uint8_t *data = msg->data;
815         int length = msg->len, ef_len;
816         uint8_t sw1, sw2;
817         uint8_t cause;
818         struct sim_hdr *sh;
819         struct gsm1111_response_ef *ef;
820         struct gsm1111_response_mfdf *mfdf;
821         struct gsm1111_response_mfdf_gsm *mfdf_gsm;
822         int i;
823
824         /* ignore, if current job already gone */
825         if (!sim->job_msg) {
826                 LOGP(DSIM, LOGL_ERROR, "received APDU but no job, "
827                         "please fix!\n");
828                 msgb_free(msg);
829                 return 0;
830         }
831
832         sh = (struct sim_hdr *)sim->job_msg->data;
833         payload = sim->job_msg->data + sizeof(*sh);
834         payload_len = sim->job_msg->len - sizeof(*sh);
835
836         /* process status */
837         if (length < 2) {
838                 msgb_free(msg);
839                 return 0;
840         }
841         sw1 = data[length - 2];
842         sw2 = data[length - 1];
843         length -= 2;
844         LOGP(DSIM, LOGL_INFO, "received APDU (len=%d sw1=0x%02x sw2=0x%02x)\n",
845                 length, sw1, sw2);
846
847         switch (sw1) {
848         case GSM1111_STAT_MEM_PROBLEM:
849                 if (sw2 >= 0x40) {
850                         LOGP(DSIM, LOGL_NOTICE, "memory of SIM failed\n");
851                         sim_error:
852                         cause = SIM_CAUSE_SIM_ERROR;
853                         gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
854                         msgb_free(msg);
855                         return 0;
856                 }
857                 LOGP(DSIM, LOGL_NOTICE, "memory of SIM is bad (write took %d "
858                         "times to succeed)\n", sw2);
859                 /* fall through */
860         case GSM1111_STAT_NORMAL:
861         case GSM1111_STAT_PROACTIVE:
862         case GSM1111_STAT_DL_ERROR:
863         case GSM1111_STAT_RESPONSE:
864         case GSM1111_STAT_RESPONSE_TOO:
865                 LOGP(DSIM, LOGL_INFO, "command successfull\n");
866                 switch (sh->job_type) {
867                 case SIM_JOB_PIN1_CHANGE:
868                         memcpy(sim->pin1, payload, payload_len);
869                         sim->pin1_len = payload_len;
870                         break;
871                 case SIM_JOB_PIN2_CHANGE:
872                         memcpy(sim->pin2, payload, payload_len);
873                         sim->pin2_len = payload_len;
874                         break;
875                 }
876                 break;
877         default:
878                 LOGP(DSIM, LOGL_INFO, "command failed\n");
879                 switch (sh->job_type) {
880                 case SIM_JOB_PIN1_UNLOCK:
881                 case SIM_JOB_PIN1_UNBLOCK:
882                         sim->pin1_len = 0;
883                         break;
884                 case SIM_JOB_PIN2_UNLOCK:
885                 case SIM_JOB_PIN2_UNBLOCK:
886                         sim->pin2_len = 0;
887                         break;
888                 }
889                 request_error:
890                 cause = SIM_CAUSE_REQUEST_ERROR;
891                 gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
892                 msgb_free(msg);
893                 return 0;
894         }
895
896
897         switch (sim->job_state) {
898         /* step 1: after selecting MF / DF, request the response */
899         case SIM_JST_SELECT_MFDF:
900                 /* not enough data */
901                 if (sw2 < 22) {
902                         LOGP(DSIM, LOGL_NOTICE, "expecting minimum 22 bytes\n");
903                         goto sim_error;
904                 }
905                 /* request response */
906                 sim->job_state = SIM_JST_SELECT_MFDF_RESP;
907                 gsm1111_tx_get_response(ms, sw2);
908                 msgb_free(msg);
909                 return 0;
910         /* step 2: after getting response of selecting MF / DF, continue
911          * to "process_job".
912          */
913         case SIM_JST_SELECT_MFDF_RESP:
914                 if (length < 22) {
915                         LOGP(DSIM, LOGL_NOTICE, "expecting minimum 22 bytes\n");
916                         goto sim_error;
917                 }
918                 mfdf = (struct gsm1111_response_mfdf *)data;
919                 mfdf_gsm = (struct gsm1111_response_mfdf_gsm *)(data + 13);
920                 /* if MF was selected, but MF is not indicated */
921                 if (ntohs(mfdf->file_id) != 0x3f00 && sim->path[0] == 0) {
922                         goto sim_error;
923                 }
924                 /* if MF was selected, but type is not indicated */
925                 if (mfdf->tof != GSM1111_TOF_MF && sim->path[0]) {
926                         goto sim_error;
927                 }
928                 /* if DF was selected, but this DF is not indicated */
929                 i = 0;
930                 while (sim->path[i + 1])
931                         i++;
932                 if (ntohs(mfdf->file_id) != sim->path[i]) {
933                         goto sim_error;
934                 }
935                 /* if DF was selected, but type is not indicated */
936                 if (mfdf->tof != GSM1111_TOF_DF) {
937                         goto sim_error;
938                 }
939                 /* now continue */
940                 msgb_free(msg);
941                 return sim_process_job(ms);
942         /* step 1: after selecting EF, request response of SELECT */
943         case SIM_JST_SELECT_EF:
944                 /* not enough data */
945                 if (sw2 < 14) {
946                         LOGP(DSIM, LOGL_NOTICE, "expecting minimum 14 bytes\n");
947                         goto sim_error;
948                 }
949                 /* request response */
950                 sim->job_state = SIM_JST_SELECT_EF_RESP;
951                 gsm1111_tx_get_response(ms, sw2);
952                 msgb_free(msg);
953                 return 0;
954         /* step 2: after getting response of selecting EF, do file command */
955         case SIM_JST_SELECT_EF_RESP:
956                 if (length < 14) {
957                         LOGP(DSIM, LOGL_NOTICE, "expecting minimum 14 bytes\n");
958                         goto sim_error;
959                 }
960                 ef = (struct gsm1111_response_ef *)data;
961                 /* if EF was selected, but type is not indicated */
962                 if (ntohs(ef->file_id) != sim->file) {
963                         goto sim_error;
964                 }
965                 /* get length of file */
966                 ef_len = ntohs(ef->file_size);
967                 /* do file command */
968                 sim->job_state = SIM_JST_WAIT_FILE;
969                 switch (sh->job_type) {
970                 case SIM_JOB_READ_BINARY:
971                         // FIXME: do chunks when greater or equal 256 bytes */
972                         gsm1111_tx_read_binary(ms, 0, ef_len);
973                         break;
974                 case SIM_JOB_UPDATE_BINARY:
975                         // FIXME: do chunks when greater or equal 256 bytes */
976                         if (ef_len < length) {
977                                 LOGP(DSIM, LOGL_NOTICE, "selected file is "
978                                         "smaller (%d) than data to update "
979                                         "(%d)\n", ef_len, length);
980                                 goto request_error;
981                         }
982                         gsm1111_tx_update_binary(ms, 0, data, length);
983                         break;
984                 case SIM_JOB_READ_RECORD:
985                         gsm1111_tx_read_record(ms, sh->rec_no, sh->rec_mode,
986                                 ef_len);
987                         break;
988                 case SIM_JOB_UPDATE_RECORD:
989                         if (ef_len != length) {
990                                 LOGP(DSIM, LOGL_NOTICE, "selected file length "
991                                         "(%d) does not equal record to update "
992                                         "(%d)\n", ef_len, length);
993                                 goto request_error;
994                         }
995                         gsm1111_tx_update_record(ms, sh->rec_no, sh->rec_mode,
996                                 data, length);
997                         break;
998                 case SIM_JOB_SEEK_RECORD:
999                         gsm1111_tx_seek(ms, sh->seek_type_mode, data, length);
1000                         break;
1001                 case SIM_JOB_INCREASE:
1002                         if (length != 4) {
1003                                 LOGP(DSIM, LOGL_ERROR, "expecting uint32_t as "
1004                                         "value lenght, but got %d bytes\n",
1005                                         length);
1006                                 goto request_error;
1007                         }
1008                         gsm1111_tx_increase(ms, *((uint32_t *)data));
1009                         break;
1010                 case SIM_JOB_INVALIDATE:
1011                         gsm1111_tx_invalidate(ms);
1012                         break;
1013                 case SIM_JOB_REHABILITATE:
1014                         gsm1111_tx_rehabilitate(ms);
1015                         break;
1016                 }
1017                 msgb_free(msg);
1018                 return 0;
1019         /* step 3: after processing file command, job is done */
1020         case SIM_JST_WAIT_FILE:
1021                 /* reply job with data */
1022                 gsm_sim_reply(ms, SIM_JOB_OK, data, length);
1023                 msgb_free(msg);
1024                 return 0;
1025         /* step 1: after running GSM algorithm, request response */
1026         case SIM_JST_RUN_GSM_ALGO:
1027                 /* not enough data */
1028                 if (sw2 < 12) {
1029                         LOGP(DSIM, LOGL_NOTICE, "expecting minimum 12 bytes\n");
1030                         goto sim_error;
1031                 }
1032                 /* request response */
1033                 sim->job_state = SIM_JST_RUN_GSM_ALGO_RESP;
1034                 gsm1111_tx_get_response(ms, sw2);
1035                 msgb_free(msg);
1036                 return 0;
1037         /* step 2: after processing GSM command, job is done */
1038         case SIM_JST_RUN_GSM_ALGO_RESP:
1039                 /* reply job with data */
1040                 gsm_sim_reply(ms, SIM_JOB_OK, data, length);
1041                 msgb_free(msg);
1042                 return 0;
1043         case SIM_JST_PIN1_UNLOCK:
1044         case SIM_JST_PIN1_CHANGE:
1045         case SIM_JST_PIN1_DISABLE:
1046         case SIM_JST_PIN1_ENABLE:
1047         case SIM_JST_PIN1_UNBLOCK:
1048         case SIM_JST_PIN2_UNLOCK:
1049         case SIM_JST_PIN2_CHANGE:
1050         case SIM_JST_PIN2_UNBLOCK:
1051                 /* reply job with data */
1052                 gsm_sim_reply(ms, SIM_JOB_OK, data, length);
1053                 msgb_free(msg);
1054                 return 0;
1055         }
1056
1057         LOGP(DSIM, LOGL_ERROR, "unknown state %u, please fix!\n",
1058                 sim->job_state);
1059         goto request_error;
1060 }
1061
1062 /*
1063  * API
1064  */
1065
1066 /* open access to sim */
1067 uint32_t sim_open(struct osmocom_ms *ms,
1068         void (*cb)(struct osmocom_ms *ms, struct msgb *msg))
1069 {
1070         struct gsm_sim *sim = &ms->sim;
1071         struct gsm_sim_handler *handler;
1072
1073         /* create handler and attach */
1074         handler = talloc_zero(l23_ctx, struct gsm_sim_handler);
1075         if (!handler)
1076                 return 0;
1077         handler->handle = new_handle++;
1078         handler->cb = cb;
1079         llist_add_tail(&handler->entry, &sim->handlers);
1080
1081         return handler->handle;
1082 }
1083
1084 /* close access to sim */
1085 void sim_close(struct osmocom_ms *ms, uint32_t handle)
1086 {
1087         struct gsm_sim *sim = &ms->sim;
1088         struct gsm_sim_handler *handler;
1089
1090         handler = sim_get_handler(sim, handle);
1091         if (!handle)
1092                 return;
1093
1094         /* kill ourself */
1095         llist_del(&handler->entry);
1096         talloc_free(handler);
1097 }
1098
1099 /* send job */
1100 void sim_job(struct osmocom_ms *ms, struct msgb *msg)
1101 {
1102         struct gsm_sim *sim = &ms->sim;
1103
1104         msgb_enqueue(&sim->jobs, msg);
1105 }
1106
1107 /*
1108  * init
1109  */
1110
1111 int gsm_sim_init(struct osmocom_ms *ms)
1112 {
1113         struct gsm_sim *sim = &ms->sim;
1114
1115         /* current path is root (MF), no file selected */
1116         sim->path[0] = 0;
1117         sim->file = 0;
1118
1119         INIT_LLIST_HEAD(&sim->handlers);
1120         INIT_LLIST_HEAD(&sim->jobs);
1121
1122         LOGP(DSIM, LOGL_INFO, "init SIM client\n");
1123
1124         return 0;
1125 }
1126
1127 int gsm_sim_exit(struct osmocom_ms *ms)
1128 {
1129         struct gsm_sim *sim = &ms->sim;
1130         struct gsm_sim_handler *handler, *handler2;
1131         struct msgb *msg;
1132
1133         LOGP(DSIM, LOGL_INFO, "exit SIM client\n");
1134
1135         /* remove pending job msg */
1136         if (sim->job_msg) {
1137                 msgb_free(sim->job_msg);
1138                 sim->job_msg = NULL;
1139         }
1140         /* flush handlers */
1141         llist_for_each_entry_safe(handler, handler2, &sim->handlers, entry)
1142                 sim_close(ms, handler->handle);
1143         /* flush jobs */
1144         while ((msg = msgb_dequeue(&sim->jobs)))
1145                 msgb_free(msg);
1146
1147         return 0;
1148 }
1149
1150
1151
1152