2 * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
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.
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.
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.
24 #include <arpa/inet.h>
25 #include <osmocore/talloc.h>
26 #include <osmocore/utils.h>
28 #include <osmocom/bb/common/logging.h>
29 #include <osmocom/bb/common/osmocom_data.h>
30 #include <osmocom/bb/common/l1ctl.h>
33 static int sim_process_job(struct osmocom_ms *ms);
39 uint32_t new_handle = 1;
41 static struct gsm1111_df_name {
44 } gsm1111_df_name[] = {
47 { 0x7f10, "DFtelecom" },
48 { 0x7f22, "DFis-41" },
49 { 0x7f23, "DFfp-cts" },
50 { 0x5f50, "DFgraphics" },
51 { 0x5f30, "DFiridium" },
52 { 0x5f31, "DFglobst" },
55 { 0x5f40, "DFeia/tia-553" },
57 { 0x5f70, "DFsolsa" },
62 static const char *get_df_name(uint16_t fid)
67 for (i = 0; gsm1111_df_name[i].file; i++)
68 if (gsm1111_df_name[i].file == fid)
70 if (gsm1111_df_name[i].file)
71 return gsm1111_df_name[i].name;
73 sprintf(text, "0x%04x", fid);
77 static struct gsm_sim_handler *sim_get_handler(struct gsm_sim *sim,
80 struct gsm_sim_handler *handler;
82 llist_for_each_entry(handler, &sim->handlers, entry)
83 if (handler->handle == handle)
93 static const struct value_string sim_job_names[] = {
94 { SIM_JOB_READ_BINARY, "SIM_JOB_READ_BINARY" },
95 { SIM_JOB_UPDATE_BINARY, "SIM_JOB_UPDATE_BINARY" },
96 { SIM_JOB_READ_RECORD, "SIM_JOB_READ_RECORD" },
97 { SIM_JOB_UPDATE_RECORD, "SIM_JOB_UPDATE_RECORD" },
98 { SIM_JOB_SEEK_RECORD, "SIM_JOB_SEEK_RECORD" },
99 { SIM_JOB_INCREASE, "SIM_JOB_INCREASE" },
100 { SIM_JOB_INVALIDATE, "SIM_JOB_INVALIDATE" },
101 { SIM_JOB_REHABILITATE, "SIM_JOB_REHABILITATE" },
102 { SIM_JOB_RUN_GSM_ALGO, "SIM_JOB_RUN_GSM_ALGO" },
103 { SIM_JOB_PIN1_UNLOCK, "SIM_JOB_PIN1_UNLOCK" },
104 { SIM_JOB_PIN1_CHANGE, "SIM_JOB_PIN1_CHANGE" },
105 { SIM_JOB_PIN1_DISABLE, "SIM_JOB_PIN1_DISABLE" },
106 { SIM_JOB_PIN1_ENABLE, "SIM_JOB_PIN1_ENABLE" },
107 { SIM_JOB_PIN1_UNBLOCK, "SIM_JOB_PIN1_UNBLOCK" },
108 { SIM_JOB_PIN2_UNLOCK, "SIM_JOB_PIN2_UNLOCK" },
109 { SIM_JOB_PIN2_CHANGE, "SIM_JOB_PIN2_CHANGE" },
110 { SIM_JOB_PIN2_UNBLOCK, "SIM_JOB_PIN2_UNBLOCK" },
111 { SIM_JOB_OK, "SIM_JOB_OK" },
112 { SIM_JOB_ERROR, "SIM_JOB_ERROR" },
116 static const char *get_job_name(int value)
118 return get_value_string(sim_job_names, value);
121 /* allocate sim client message (upper layer) */
122 struct msgb *gsm_sim_msgb_alloc(uint32_t handle, uint8_t job_type)
127 msg = msgb_alloc_headroom(SIM_ALLOC_SIZE+SIM_ALLOC_HEADROOM,
128 SIM_ALLOC_HEADROOM, "SIM");
132 nsh = (struct sim_hdr *) msgb_put(msg, sizeof(*nsh));
133 nsh->handle = handle;
134 nsh->job_type = job_type;
139 /* reply to job, after it is done. reuse the msgb in the job */
140 void gsm_sim_reply(struct osmocom_ms *ms, uint8_t result_type, uint8_t *result,
143 struct gsm_sim *sim = &ms->sim;
144 struct msgb *msg = sim->job_msg;
147 uint16_t payload_len;
148 struct gsm_sim_handler *handler;
150 LOGP(DSIM, LOGL_INFO, "sending result to callback function "
151 "(type=%d)\n", result_type);
153 /* if no handler, or no callback, just free the job */
154 sh = (struct sim_hdr *)msg->data;
155 handler = sim_get_handler(sim, sh->handle);
156 if (!handler || !handler->cb) {
157 LOGP(DSIM, LOGL_INFO, "no callback or no handler, "
158 "dropping result\n");
159 msgb_free(sim->job_msg);
161 sim->job_state = SIM_JST_IDLE;
165 payload = msg->data + sizeof(*sh);
166 payload_len = msg->len - sizeof(*sh);
169 msg->tail -= payload_len;
170 msg->len -= payload_len;
173 sh->job_type = result_type;
175 memcpy(msgb_put(msg, result_len), result, result_len);
178 sim->job_state = SIM_JST_IDLE;
180 handler->cb(ms, msg);
183 /* send APDU to card reader */
184 static int sim_apdu_send(struct osmocom_ms *ms, uint8_t *data, uint16_t length)
186 LOGP(DSIM, LOGL_INFO, "sending APDU (class 0x%02x, ins 0x%02x)\n",
188 l1ctl_tx_sim_req(ms, data, length);
192 /* dequeue messages (RSL-SAP) */
193 int gsm_sim_job_dequeue(struct osmocom_ms *ms)
195 struct gsm_sim *sim = &ms->sim;
198 struct gsm_sim_handler *handler;
200 /* already have a job */
205 while ((msg = msgb_dequeue(&sim->jobs))) {
206 /* resolve handler */
207 sh = (struct sim_hdr *) msg->data;
208 LOGP(DSIM, LOGL_INFO, "got new job: %s (handle=%08x)\n",
209 get_job_name(sh->job_type), sh->handle);
210 handler = sim_get_handler(sim, sh->handle);
212 LOGP(DSIM, LOGL_INFO, "no handler, ignoring job\n");
213 /* does not exist anymore */
219 sim->job_state = SIM_JST_IDLE;
221 sim->job_handle = sh->handle;
223 /* process current job, message is freed there */
225 return 1; /* work done */
237 static int gsm1111_tx_select(struct osmocom_ms *ms, uint16_t fid)
239 uint8_t buffer[5 + 2];
241 LOGP(DSIM, LOGL_INFO, "SELECT (file=0x%04x)\n", fid);
242 buffer[0] = GSM1111_CLASS_GSM;
243 buffer[1] = GSM1111_INST_SELECT;
247 buffer[5] = fid >> 8;
250 return sim_apdu_send(ms, buffer, 5 + 2);
255 static int gsm1111_tx_status(struct osmocom_ms *ms)
259 LOGP(DSIM, LOGL_INFO, "STATUS\n");
260 buffer[0] = GSM1111_CLASS_GSM;
261 buffer[1] = GSM1111_INST_STATUS;
266 return sim_apdu_send(ms, buffer, 5);
271 static int gsm1111_tx_read_binary(struct osmocom_ms *ms, uint16_t offset,
276 LOGP(DSIM, LOGL_INFO, "READ BINARY (offset=%d len=%d)\n", offset,
278 buffer[0] = GSM1111_CLASS_GSM;
279 buffer[1] = GSM1111_INST_READ_BINARY;
280 buffer[2] = offset >> 8;
284 return sim_apdu_send(ms, buffer, 5);
288 static int gsm1111_tx_update_binary(struct osmocom_ms *ms, uint16_t offset,
289 uint8_t *data, uint8_t length)
291 uint8_t buffer[5 + length];
293 LOGP(DSIM, LOGL_INFO, "UPDATE BINARY (offset=%d len=%d)\n", offset,
295 buffer[0] = GSM1111_CLASS_GSM;
296 buffer[1] = GSM1111_INST_UPDATE_BINARY;
297 buffer[2] = offset >> 8;
300 memcpy(buffer + 5, data, length);
302 return sim_apdu_send(ms, buffer, 5 + length);
306 static int gsm1111_tx_read_record(struct osmocom_ms *ms, uint8_t rec_no,
307 uint8_t mode, uint8_t length)
311 LOGP(DSIM, LOGL_INFO, "READ RECORD (rec_no=%d mode=%d len=%d)\n",
312 rec_no, mode, length);
313 buffer[0] = GSM1111_CLASS_GSM;
314 buffer[1] = GSM1111_INST_READ_RECORD;
319 return sim_apdu_send(ms, buffer, 5);
323 static int gsm1111_tx_update_record(struct osmocom_ms *ms, uint8_t rec_no,
324 uint8_t mode, uint8_t *data, uint8_t length)
326 uint8_t buffer[5 + length];
328 LOGP(DSIM, LOGL_INFO, "UPDATE RECORD (rec_no=%d mode=%d len=%d)\n",
329 rec_no, mode, length);
330 buffer[0] = GSM1111_CLASS_GSM;
331 buffer[1] = GSM1111_INST_UPDATE_RECORD;
335 memcpy(buffer + 5, data, length);
337 return sim_apdu_send(ms, buffer, 5 + length);
341 static int gsm1111_tx_seek(struct osmocom_ms *ms, uint8_t type_mode,
342 uint8_t *pattern, uint8_t length)
344 uint8_t buffer[5 + length];
345 uint8_t type = type_mode >> 4;
346 uint8_t mode = type_mode & 0x0f;
348 LOGP(DSIM, LOGL_INFO, "SEEK (type=%d mode=%d len=%d)\n", type, mode,
350 buffer[0] = GSM1111_CLASS_GSM;
351 buffer[1] = GSM1111_INST_SEEK;
353 buffer[3] = type_mode;
355 memcpy(buffer + 5, pattern, length);
357 return sim_apdu_send(ms, buffer, 5 + length);
361 static int gsm1111_tx_increase(struct osmocom_ms *ms, uint32_t value)
363 uint8_t buffer[5 + 3];
365 LOGP(DSIM, LOGL_INFO, "INCREASE (value=%d)\n", value);
366 buffer[0] = GSM1111_CLASS_GSM;
367 buffer[1] = GSM1111_INST_INCREASE;
371 buffer[5] = value >> 16;
372 buffer[6] = value >> 8;
375 return sim_apdu_send(ms, buffer, 5 + 3);
379 static int gsm1111_tx_verify_chv(struct osmocom_ms *ms, uint8_t chv_no,
380 uint8_t *chv, uint8_t length)
382 uint8_t buffer[5 + 8];
385 LOGP(DSIM, LOGL_INFO, "VERIFY CHV (CHV%d)\n", chv_no);
386 buffer[0] = GSM1111_CLASS_GSM;
387 buffer[1] = GSM1111_INST_VERIFY_CHV;
391 for (i = 0; i < 8; i++) {
393 buffer[5 + i] = chv[i];
395 buffer[5 + i] = 0xff;
398 return sim_apdu_send(ms, buffer, 5 + 8);
402 static int gsm1111_tx_change_chv(struct osmocom_ms *ms, uint8_t chv_no,
403 uint8_t *chv_old, uint8_t length_old, uint8_t *chv_new,
406 uint8_t buffer[5 + 16];
409 LOGP(DSIM, LOGL_INFO, "CHANGE CHV (CHV%d)\n", chv_no);
410 buffer[0] = GSM1111_CLASS_GSM;
411 buffer[1] = GSM1111_INST_CHANGE_CHV;
415 for (i = 0; i < 8; i++) {
417 buffer[5 + i] = chv_old[i];
419 buffer[5 + i] = 0xff;
421 buffer[13 + i] = chv_new[i];
423 buffer[13 + i] = 0xff;
426 return sim_apdu_send(ms, buffer, 5 + 16);
430 static int gsm1111_tx_disable_chv(struct osmocom_ms *ms, uint8_t *chv,
433 uint8_t buffer[5 + 8];
436 LOGP(DSIM, LOGL_INFO, "DISABLE CHV (CHV1)\n");
437 buffer[0] = GSM1111_CLASS_GSM;
438 buffer[1] = GSM1111_INST_DISABLE_CHV;
442 for (i = 0; i < 8; i++) {
444 buffer[5 + i] = chv[i];
446 buffer[5 + i] = 0xff;
449 return sim_apdu_send(ms, buffer, 5 + 8);
453 static int gsm1111_tx_enable_chv(struct osmocom_ms *ms, uint8_t *chv,
456 uint8_t buffer[5 + 8];
459 LOGP(DSIM, LOGL_INFO, "ENABLE CHV (CHV1)\n");
460 buffer[0] = GSM1111_CLASS_GSM;
461 buffer[1] = GSM1111_INST_ENABLE_CHV;
465 for (i = 0; i < 8; i++) {
467 buffer[5 + i] = chv[i];
469 buffer[5 + i] = 0xff;
472 return sim_apdu_send(ms, buffer, 5 + 8);
476 static int gsm1111_tx_unblock_chv(struct osmocom_ms *ms, uint8_t chv_no,
477 uint8_t *chv_unblk, uint8_t length_unblk, uint8_t *chv_new,
480 uint8_t buffer[5 + 16];
483 LOGP(DSIM, LOGL_INFO, "UNBLOCK CHV (CHV%d)\n", (chv_no == 2) ? 2 : 1);
484 buffer[0] = GSM1111_CLASS_GSM;
485 buffer[1] = GSM1111_INST_UNBLOCK_CHV;
487 buffer[3] = (chv_no == 1) ? 0 : chv_no;
489 for (i = 0; i < 8; i++) {
490 if (i < length_unblk)
491 buffer[5 + i] = chv_unblk[i];
493 buffer[5 + i] = 0xff;
495 buffer[13 + i] = chv_new[i];
497 buffer[13 + i] = 0xff;
500 return sim_apdu_send(ms, buffer, 5 + 16);
504 static int gsm1111_tx_invalidate(struct osmocom_ms *ms)
508 LOGP(DSIM, LOGL_INFO, "INVALIDATE\n");
509 buffer[0] = GSM1111_CLASS_GSM;
510 buffer[1] = GSM1111_INST_INVALIDATE;
515 return sim_apdu_send(ms, buffer, 5);
519 static int gsm1111_tx_rehabilitate(struct osmocom_ms *ms)
523 LOGP(DSIM, LOGL_INFO, "REHABILITATE\n");
524 buffer[0] = GSM1111_CLASS_GSM;
525 buffer[1] = GSM1111_INST_REHABLILITATE;
530 return sim_apdu_send(ms, buffer, 5);
534 static int gsm1111_tx_run_gsm_algo(struct osmocom_ms *ms, uint8_t *rand)
536 uint8_t buffer[5 + 16];
538 LOGP(DSIM, LOGL_INFO, "RUN GSM ALGORITHM\n");
539 buffer[0] = GSM1111_CLASS_GSM;
540 buffer[1] = GSM1111_INST_RUN_GSM_ALGO;
544 memcpy(buffer + 5, rand, 16);
546 return sim_apdu_send(ms, buffer, 5 + 16);
551 static int gsm1111_tx_sleep(struct osmocom_ms *ms)
555 LOGP(DSIM, LOGL_INFO, "\n");
556 buffer[0] = GSM1111_CLASS_GSM;
557 buffer[1] = GSM1111_INST_SLEEP;
562 return sim_apdu_send(ms, buffer, 5);
567 static int gsm1111_tx_get_response(struct osmocom_ms *ms, uint8_t length)
571 LOGP(DSIM, LOGL_INFO, "GET RESPONSE (len=%d)\n", length);
572 buffer[0] = GSM1111_CLASS_GSM;
573 buffer[1] = GSM1111_INST_GET_RESPONSE;
578 return sim_apdu_send(ms, buffer, 5);
583 static int gsm1111_tx_terminal_profile(struct osmocom_ms *ms, uint8_t *data,
586 uint8_t buffer[5 + length];
588 LOGP(DSIM, LOGL_INFO, "TERMINAL PROFILE (len=%d)\n", length);
589 buffer[0] = GSM1111_CLASS_GSM;
590 buffer[1] = GSM1111_INST_TERMINAL_PROFILE;
594 memcpy(buffer + 5, data, length);
596 return sim_apdu_send(ms, buffer, 5 + length);
600 static int gsm1111_tx_envelope(struct osmocom_ms *ms, uint8_t *data,
603 uint8_t buffer[5 + length];
605 LOGP(DSIM, LOGL_INFO, "ENVELOPE (len=%d)\n", length);
606 buffer[0] = GSM1111_CLASS_GSM;
607 buffer[1] = GSM1111_INST_ENVELOPE;
611 memcpy(buffer + 5, data, length);
613 return sim_apdu_send(ms, buffer, 5 + length);
617 static int gsm1111_tx_fetch(struct osmocom_ms *ms, uint8_t length)
621 LOGP(DSIM, LOGL_INFO, "FETCH (len=%d)\n", length);
622 buffer[0] = GSM1111_CLASS_GSM;
623 buffer[1] = GSM1111_INST_FETCH;
628 return sim_apdu_send(ms, buffer, 5);
632 static int gsm1111_tx_terminal_response(struct osmocom_ms *ms, uint8_t *data,
635 uint8_t buffer[5 + length];
637 LOGP(DSIM, LOGL_INFO, "TERMINAL RESPONSE (len=%d)\n", length);
638 buffer[0] = GSM1111_CLASS_GSM;
639 buffer[1] = GSM1111_INST_TERMINAL_RESPONSE;
643 memcpy(buffer + 5, data, length);
645 return sim_apdu_send(ms, buffer, 5 + length);
654 static int sim_process_job(struct osmocom_ms *ms)
656 struct gsm_sim *sim = &ms->sim;
657 uint8_t *payload, *payload2;
658 uint16_t payload_len, payload_len2;
667 sh = (struct sim_hdr *)sim->job_msg->data;
668 payload = sim->job_msg->data + sizeof(*sh);
669 payload_len = sim->job_msg->len - sizeof(*sh);
671 /* do reset before sim reading */
674 // FIXME: send reset command to L1
677 /* navigate to right DF */
678 switch (sh->job_type) {
679 case SIM_JOB_READ_BINARY:
680 case SIM_JOB_UPDATE_BINARY:
681 case SIM_JOB_READ_RECORD:
682 case SIM_JOB_UPDATE_RECORD:
683 case SIM_JOB_SEEK_RECORD:
684 case SIM_JOB_INCREASE:
685 case SIM_JOB_INVALIDATE:
686 case SIM_JOB_REHABILITATE:
687 case SIM_JOB_RUN_GSM_ALGO:
690 while (sh->path[i] && sim->path[i]) {
691 if (sh->path[i] != sh->path[i])
695 /* if path in message is shorter or if paths are different */
697 LOGP(DSIM, LOGL_INFO, "go MF\n");
698 sim->job_state = SIM_JST_SELECT_MFDF;
701 return gsm1111_tx_select(ms, 0x3f00);
703 /* if path in message is longer */
705 LOGP(DSIM, LOGL_INFO, "requested path is longer, go "
706 "child %s\n", get_df_name(sh->path[i]));
707 sim->job_state = SIM_JST_SELECT_MFDF;
709 sim->path[i] = sh->path[i];
710 sim->path[i + 1] = 0;
711 return gsm1111_tx_select(ms, sh->path[i]);
713 /* if paths are equal, continue */
716 /* set state and trigger SIM process */
717 switch (sh->job_type) {
718 case SIM_JOB_READ_BINARY:
719 case SIM_JOB_UPDATE_BINARY:
720 case SIM_JOB_READ_RECORD:
721 case SIM_JOB_UPDATE_RECORD:
722 case SIM_JOB_SEEK_RECORD:
723 case SIM_JOB_INCREASE:
724 case SIM_JOB_INVALIDATE:
725 case SIM_JOB_REHABILITATE:
726 sim->job_state = SIM_JST_SELECT_EF;
727 sim->file = sh->file;
728 return gsm1111_tx_select(ms, sh->file);
729 case SIM_JOB_RUN_GSM_ALGO:
730 if (payload_len != 16) {
731 LOGP(DSIM, LOGL_ERROR, "random not 16 bytes\n");
734 sim->job_state = SIM_JST_RUN_GSM_ALGO;
735 return gsm1111_tx_run_gsm_algo(ms, payload);
736 case SIM_JOB_PIN1_UNLOCK:
737 payload_len = strlen((char *)payload);
738 if (payload_len < 4 || payload_len > 8) {
739 LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
742 sim->job_state = SIM_JST_PIN1_UNLOCK;
743 return gsm1111_tx_verify_chv(ms, 0x01, payload, payload_len);
744 case SIM_JOB_PIN2_UNLOCK:
745 payload_len = strlen((char *)payload);
746 if (payload_len < 4 || payload_len > 8) {
747 LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
750 sim->job_state = SIM_JST_PIN2_UNLOCK;
751 return gsm1111_tx_verify_chv(ms, 0x02, payload, payload_len);
752 case SIM_JOB_PIN1_CHANGE:
753 payload_len = strlen((char *)payload);
754 payload2 = payload + payload_len + 1;
755 payload_len2 = strlen((char *)payload2);
756 if (payload_len < 4 || payload_len > 8) {
757 LOGP(DSIM, LOGL_ERROR, "key1 not in range 4..8\n");
760 if (payload_len2 < 4 || payload_len2 > 8) {
761 LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
764 sim->job_state = SIM_JST_PIN1_CHANGE;
765 return gsm1111_tx_change_chv(ms, 0x01, payload, payload_len,
766 payload2, payload_len2);
767 case SIM_JOB_PIN2_CHANGE:
768 payload_len = strlen((char *)payload);
769 payload2 = payload + payload_len + 1;
770 payload_len2 = strlen((char *)payload2);
771 if (payload_len < 4 || payload_len > 8) {
772 LOGP(DSIM, LOGL_ERROR, "key1 not in range 4..8\n");
775 if (payload_len2 < 4 || payload_len2 > 8) {
776 LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
779 sim->job_state = SIM_JST_PIN2_CHANGE;
780 return gsm1111_tx_change_chv(ms, 0x02, payload, payload_len,
781 payload2, payload_len2);
782 case SIM_JOB_PIN1_DISABLE:
783 payload_len = strlen((char *)payload);
784 if (payload_len < 4 || payload_len > 8) {
785 LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
788 sim->job_state = SIM_JST_PIN1_DISABLE;
789 return gsm1111_tx_disable_chv(ms, payload, payload_len);
790 case SIM_JOB_PIN1_ENABLE:
791 payload_len = strlen((char *)payload);
792 if (payload_len < 4 || payload_len > 8) {
793 LOGP(DSIM, LOGL_ERROR, "key not in range 4..8\n");
796 sim->job_state = SIM_JST_PIN1_ENABLE;
797 return gsm1111_tx_enable_chv(ms, payload, payload_len);
798 case SIM_JOB_PIN1_UNBLOCK:
799 payload_len = strlen((char *)payload);
800 payload2 = payload + payload_len + 1;
801 payload_len2 = strlen((char *)payload2);
802 if (payload_len != 8) {
803 LOGP(DSIM, LOGL_ERROR, "key1 not 8 digits\n");
806 if (payload_len2 < 4 || payload_len2 > 8) {
807 LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
810 sim->job_state = SIM_JST_PIN1_UNBLOCK;
811 /* NOTE: CHV1 is coded 0x00 here */
812 return gsm1111_tx_unblock_chv(ms, 0x00, payload, payload_len,
813 payload2, payload_len2);
814 case SIM_JOB_PIN2_UNBLOCK:
815 payload_len = strlen((char *)payload);
816 payload2 = payload + payload_len + 1;
817 payload_len2 = strlen((char *)payload2);
818 if (payload_len != 8) {
819 LOGP(DSIM, LOGL_ERROR, "key1 not 8 digits\n");
822 if (payload_len2 < 4 || payload_len2 > 8) {
823 LOGP(DSIM, LOGL_ERROR, "key2 not in range 4..8\n");
826 sim->job_state = SIM_JST_PIN2_UNBLOCK;
827 return gsm1111_tx_unblock_chv(ms, 0x02, payload, payload_len,
828 payload2, payload_len2);
831 LOGP(DSIM, LOGL_ERROR, "unknown job %x, please fix\n", sh->job_type);
832 cause = SIM_CAUSE_REQUEST_ERROR;
833 gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
838 /* receive SIM response */
839 int sim_apdu_resp(struct osmocom_ms *ms, struct msgb *msg)
841 struct gsm_sim *sim = &ms->sim;
843 uint16_t payload_len;
844 uint8_t *data = msg->data;
845 int length = msg->len, ef_len;
848 uint8_t pin_cause[2];
850 struct gsm1111_response_ef *ef;
851 struct gsm1111_response_mfdf *mfdf;
852 struct gsm1111_response_mfdf_gsm *mfdf_gsm;
855 /* ignore, if current job already gone */
857 LOGP(DSIM, LOGL_ERROR, "received APDU but no job, "
863 sh = (struct sim_hdr *)sim->job_msg->data;
864 payload = sim->job_msg->data + sizeof(*sh);
865 payload_len = sim->job_msg->len - sizeof(*sh);
872 sw1 = data[length - 2];
873 sw2 = data[length - 1];
875 LOGP(DSIM, LOGL_INFO, "received APDU (len=%d sw1=0x%02x sw2=0x%02x)\n",
879 case GSM1111_STAT_SECURITY:
880 LOGP(DSIM, LOGL_NOTICE, "SIM Security\n");
882 if (sw2 != GSM1111_SEC_NO_ACCESS && sw2 != GSM1111_SEC_BLOCKED)
885 /* select the right remaining counter an cause */
886 // FIXME: read status to replace "*_remain"-counters
887 switch (sim->job_state) {
888 case SIM_JST_PIN1_UNBLOCK:
889 if (sw2 == GSM1111_SEC_NO_ACCESS) {
890 pin_cause[0] = SIM_CAUSE_PIN1_BLOCKED;
891 pin_cause[1] = --sim->unblk1_remain;
893 pin_cause[0] = SIM_CAUSE_PUC_BLOCKED;
897 case SIM_JST_PIN2_UNLOCK:
898 case SIM_JST_PIN2_CHANGE:
899 if (sw2 == GSM1111_SEC_NO_ACCESS && sim->chv2_remain) {
900 pin_cause[0] = SIM_CAUSE_PIN2_REQUIRED;
901 pin_cause[1] = sim->chv2_remain--;
903 pin_cause[0] = SIM_CAUSE_PIN2_BLOCKED;
904 pin_cause[1] = sim->unblk2_remain;
907 case SIM_JST_PIN2_UNBLOCK:
908 if (sw2 == GSM1111_SEC_NO_ACCESS) {
909 pin_cause[0] = SIM_CAUSE_PIN2_BLOCKED;
910 pin_cause[1] = --sim->unblk2_remain;
912 pin_cause[0] = SIM_CAUSE_PUC_BLOCKED;
915 case SIM_JST_PIN1_UNLOCK:
916 case SIM_JST_PIN1_CHANGE:
917 case SIM_JST_PIN1_DISABLE:
918 case SIM_JST_PIN1_ENABLE:
920 if (sw2 == GSM1111_SEC_NO_ACCESS && sim->chv1_remain) {
921 pin_cause[0] = SIM_CAUSE_PIN1_REQUIRED;
922 pin_cause[1] = sim->chv1_remain--;
924 pin_cause[0] = SIM_CAUSE_PIN1_BLOCKED;
925 pin_cause[1] = sim->unblk1_remain;
929 gsm_sim_reply(ms, SIM_JOB_ERROR, pin_cause, 2);
932 case GSM1111_STAT_MEM_PROBLEM:
934 LOGP(DSIM, LOGL_NOTICE, "memory of SIM failed\n");
936 cause = SIM_CAUSE_SIM_ERROR;
937 gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
941 LOGP(DSIM, LOGL_NOTICE, "memory of SIM is bad (write took %d "
942 "times to succeed)\n", sw2);
944 case GSM1111_STAT_NORMAL:
945 case GSM1111_STAT_PROACTIVE:
946 case GSM1111_STAT_DL_ERROR:
947 case GSM1111_STAT_RESPONSE:
948 case GSM1111_STAT_RESPONSE_TOO:
949 LOGP(DSIM, LOGL_INFO, "command successfull\n");
952 LOGP(DSIM, LOGL_INFO, "command failed\n");
954 cause = SIM_CAUSE_REQUEST_ERROR;
955 gsm_sim_reply(ms, SIM_JOB_ERROR, &cause, 1);
961 switch (sim->job_state) {
962 /* step 1: after selecting MF / DF, request the response */
963 case SIM_JST_SELECT_MFDF:
964 /* not enough data */
966 LOGP(DSIM, LOGL_NOTICE, "expecting minimum 22 bytes\n");
969 /* request response */
970 sim->job_state = SIM_JST_SELECT_MFDF_RESP;
971 gsm1111_tx_get_response(ms, sw2);
974 /* step 2: after getting response of selecting MF / DF, continue
977 case SIM_JST_SELECT_MFDF_RESP:
979 LOGP(DSIM, LOGL_NOTICE, "expecting minimum 22 bytes\n");
982 mfdf = (struct gsm1111_response_mfdf *)data;
983 mfdf_gsm = (struct gsm1111_response_mfdf_gsm *)(data + 13);
984 sim->chv1_remain = mfdf_gsm->chv1_remain;
985 sim->chv2_remain = mfdf_gsm->chv2_remain;
986 sim->unblk1_remain = mfdf_gsm->unblk1_remain;
987 sim->unblk2_remain = mfdf_gsm->unblk2_remain;
988 /* if MF was selected */
989 if (sim->path[0] == 0) {
990 /* if MF was selected, but MF is not indicated */
991 if (ntohs(mfdf->file_id) != 0x3f00) {
992 LOGP(DSIM, LOGL_NOTICE, "Not MF\n");
995 /* if MF was selected, but type is not indicated */
996 if (mfdf->tof != GSM1111_TOF_MF) {
997 LOGP(DSIM, LOGL_NOTICE, "MF %02x != %02x "
998 "%04x\n", mfdf->tof, GSM1111_TOF_MF,
1004 return sim_process_job(ms);
1006 /* if DF was selected, but this DF is not indicated */
1008 while (sim->path[i + 1])
1010 if (ntohs(mfdf->file_id) != sim->path[i]) {
1011 LOGP(DSIM, LOGL_NOTICE, "Path %04x != %04x\n",
1012 ntohs(mfdf->file_id), sim->path[i]);
1015 /* if DF was selected, but type is not indicated */
1016 if (mfdf->tof != GSM1111_TOF_DF) {
1017 LOGP(DSIM, LOGL_NOTICE, "TOF error\n");
1022 return sim_process_job(ms);
1023 /* step 1: after selecting EF, request response of SELECT */
1024 case SIM_JST_SELECT_EF:
1025 /* not enough data */
1027 LOGP(DSIM, LOGL_NOTICE, "expecting minimum 14 bytes\n");
1030 /* request response */
1031 sim->job_state = SIM_JST_SELECT_EF_RESP;
1032 gsm1111_tx_get_response(ms, sw2);
1035 /* step 2: after getting response of selecting EF, do file command */
1036 case SIM_JST_SELECT_EF_RESP:
1038 LOGP(DSIM, LOGL_NOTICE, "expecting minimum 14 bytes\n");
1041 ef = (struct gsm1111_response_ef *)data;
1042 /* if EF was selected, but type is not indicated */
1043 if (ntohs(ef->file_id) != sim->file) {
1044 LOGP(DSIM, LOGL_NOTICE, "EF ID %04x != %04x\n",
1045 ntohs(ef->file_id), sim->file);
1048 /* get length of file */
1049 ef_len = ntohs(ef->file_size);
1050 /* do file command */
1051 sim->job_state = SIM_JST_WAIT_FILE;
1052 switch (sh->job_type) {
1053 case SIM_JOB_READ_BINARY:
1054 // FIXME: do chunks when greater or equal 256 bytes */
1055 gsm1111_tx_read_binary(ms, 0, ef_len);
1057 case SIM_JOB_UPDATE_BINARY:
1058 // FIXME: do chunks when greater or equal 256 bytes */
1059 if (ef_len < payload_len) {
1060 LOGP(DSIM, LOGL_NOTICE, "selected file is "
1061 "smaller (%d) than data to update "
1062 "(%d)\n", ef_len, payload_len);
1065 gsm1111_tx_update_binary(ms, 0, payload, payload_len);
1067 case SIM_JOB_READ_RECORD:
1068 gsm1111_tx_read_record(ms, sh->rec_no, sh->rec_mode,
1071 case SIM_JOB_UPDATE_RECORD:
1072 if (ef_len != payload_len) {
1073 LOGP(DSIM, LOGL_NOTICE, "selected file length "
1074 "(%d) does not equal record to update "
1075 "(%d)\n", ef_len, payload_len);
1078 gsm1111_tx_update_record(ms, sh->rec_no, sh->rec_mode,
1079 payload, payload_len);
1081 case SIM_JOB_SEEK_RECORD:
1082 gsm1111_tx_seek(ms, sh->seek_type_mode, data, length);
1084 case SIM_JOB_INCREASE:
1086 LOGP(DSIM, LOGL_ERROR, "expecting uint32_t as "
1087 "value lenght, but got %d bytes\n",
1091 gsm1111_tx_increase(ms, *((uint32_t *)data));
1093 case SIM_JOB_INVALIDATE:
1094 gsm1111_tx_invalidate(ms);
1096 case SIM_JOB_REHABILITATE:
1097 gsm1111_tx_rehabilitate(ms);
1102 /* step 3: after processing file command, job is done */
1103 case SIM_JST_WAIT_FILE:
1104 /* reply job with data */
1105 gsm_sim_reply(ms, SIM_JOB_OK, data, length);
1108 /* step 1: after running GSM algorithm, request response */
1109 case SIM_JST_RUN_GSM_ALGO:
1110 /* not enough data */
1112 LOGP(DSIM, LOGL_NOTICE, "expecting minimum 12 bytes\n");
1115 /* request response */
1116 sim->job_state = SIM_JST_RUN_GSM_ALGO_RESP;
1117 gsm1111_tx_get_response(ms, sw2);
1120 /* step 2: after processing GSM command, job is done */
1121 case SIM_JST_RUN_GSM_ALGO_RESP:
1122 /* reply job with data */
1123 gsm_sim_reply(ms, SIM_JOB_OK, data, length);
1126 case SIM_JST_PIN1_UNLOCK:
1127 case SIM_JST_PIN1_CHANGE:
1128 case SIM_JST_PIN1_DISABLE:
1129 case SIM_JST_PIN1_ENABLE:
1130 case SIM_JST_PIN1_UNBLOCK:
1131 case SIM_JST_PIN2_UNLOCK:
1132 case SIM_JST_PIN2_CHANGE:
1133 case SIM_JST_PIN2_UNBLOCK:
1134 /* reply job with data */
1135 gsm_sim_reply(ms, SIM_JOB_OK, data, length);
1140 LOGP(DSIM, LOGL_ERROR, "unknown state %u, please fix!\n",
1149 /* open access to sim */
1150 uint32_t sim_open(struct osmocom_ms *ms,
1151 void (*cb)(struct osmocom_ms *ms, struct msgb *msg))
1153 struct gsm_sim *sim = &ms->sim;
1154 struct gsm_sim_handler *handler;
1156 /* create handler and attach */
1157 handler = talloc_zero(l23_ctx, struct gsm_sim_handler);
1160 handler->handle = new_handle++;
1162 llist_add_tail(&handler->entry, &sim->handlers);
1164 return handler->handle;
1167 /* close access to sim */
1168 void sim_close(struct osmocom_ms *ms, uint32_t handle)
1170 struct gsm_sim *sim = &ms->sim;
1171 struct gsm_sim_handler *handler;
1173 handler = sim_get_handler(sim, handle);
1178 llist_del(&handler->entry);
1179 talloc_free(handler);
1183 void sim_job(struct osmocom_ms *ms, struct msgb *msg)
1185 struct gsm_sim *sim = &ms->sim;
1187 msgb_enqueue(&sim->jobs, msg);
1194 int gsm_sim_init(struct osmocom_ms *ms)
1196 struct gsm_sim *sim = &ms->sim;
1198 /* current path is undefined, forching MF */
1199 sim->path[0] = 0x0bad;
1203 INIT_LLIST_HEAD(&sim->handlers);
1204 INIT_LLIST_HEAD(&sim->jobs);
1206 LOGP(DSIM, LOGL_INFO, "init SIM client\n");
1211 int gsm_sim_exit(struct osmocom_ms *ms)
1213 struct gsm_sim *sim = &ms->sim;
1214 struct gsm_sim_handler *handler, *handler2;
1217 LOGP(DSIM, LOGL_INFO, "exit SIM client\n");
1219 /* remove pending job msg */
1221 msgb_free(sim->job_msg);
1222 sim->job_msg = NULL;
1224 /* flush handlers */
1225 llist_for_each_entry_safe(handler, handler2, &sim->handlers, entry)
1226 sim_close(ms, handler->handle);
1228 while ((msg = msgb_dequeue(&sim->jobs)))