1 /* 2 * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM 3 * Copyright (c) 2004-2007, Jouni Malinen <j (at) w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 * 8 * This file implements wrapper functions for accessing GSM SIM and 3GPP USIM 9 * cards through PC/SC smartcard library. These functions are used to implement 10 * authentication routines for EAP-SIM and EAP-AKA. 11 */ 12 13 #include "includes.h" 14 #include <winscard.h> 15 16 #include "common.h" 17 #include "pcsc_funcs.h" 18 19 20 /* See ETSI GSM 11.11 and ETSI TS 102 221 for details. 21 * SIM commands: 22 * Command APDU: CLA INS P1 P2 P3 Data 23 * CLA (class of instruction): A0 for GSM, 00 for USIM 24 * INS (instruction) 25 * P1 P2 P3 (parameters, P3 = length of Data) 26 * Response APDU: Data SW1 SW2 27 * SW1 SW2 (Status words) 28 * Commands (INS P1 P2 P3): 29 * SELECT: A4 00 00 02 <file_id, 2 bytes> 30 * GET RESPONSE: C0 00 00 <len> 31 * RUN GSM ALG: 88 00 00 00 <RAND len = 10> 32 * RUN UMTS ALG: 88 00 81 <len=0x22> data: 0x10 | RAND | 0x10 | AUTN 33 * P1 = ID of alg in card 34 * P2 = ID of secret key 35 * READ BINARY: B0 <offset high> <offset low> <len> 36 * READ RECORD: B2 <record number> <mode> <len> 37 * P2 (mode) = '02' (next record), '03' (previous record), 38 * '04' (absolute mode) 39 * VERIFY CHV: 20 00 <CHV number> 08 40 * CHANGE CHV: 24 00 <CHV number> 10 41 * DISABLE CHV: 26 00 01 08 42 * ENABLE CHV: 28 00 01 08 43 * UNBLOCK CHV: 2C 00 <00=CHV1, 02=CHV2> 10 44 * SLEEP: FA 00 00 00 45 */ 46 47 /* GSM SIM commands */ 48 #define SIM_CMD_SELECT 0xa0, 0xa4, 0x00, 0x00, 0x02 49 #define SIM_CMD_RUN_GSM_ALG 0xa0, 0x88, 0x00, 0x00, 0x10 50 #define SIM_CMD_GET_RESPONSE 0xa0, 0xc0, 0x00, 0x00 51 #define SIM_CMD_READ_BIN 0xa0, 0xb0, 0x00, 0x00 52 #define SIM_CMD_READ_RECORD 0xa0, 0xb2, 0x00, 0x00 53 #define SIM_CMD_VERIFY_CHV1 0xa0, 0x20, 0x00, 0x01, 0x08 54 55 /* USIM commands */ 56 #define USIM_CLA 0x00 57 #define USIM_CMD_RUN_UMTS_ALG 0x00, 0x88, 0x00, 0x81, 0x22 58 #define USIM_CMD_GET_RESPONSE 0x00, 0xc0, 0x00, 0x00 59 60 #define SIM_RECORD_MODE_ABSOLUTE 0x04 61 62 #define USIM_FSP_TEMPL_TAG 0x62 63 64 #define USIM_TLV_FILE_DESC 0x82 65 #define USIM_TLV_FILE_ID 0x83 66 #define USIM_TLV_DF_NAME 0x84 67 #define USIM_TLV_PROPR_INFO 0xA5 68 #define USIM_TLV_LIFE_CYCLE_STATUS 0x8A 69 #define USIM_TLV_FILE_SIZE 0x80 70 #define USIM_TLV_TOTAL_FILE_SIZE 0x81 71 #define USIM_TLV_PIN_STATUS_TEMPLATE 0xC6 72 #define USIM_TLV_SHORT_FILE_ID 0x88 73 74 #define USIM_PS_DO_TAG 0x90 75 76 #define AKA_RAND_LEN 16 77 #define AKA_AUTN_LEN 16 78 #define AKA_AUTS_LEN 14 79 #define RES_MAX_LEN 16 80 #define IK_LEN 16 81 #define CK_LEN 16 82 83 84 typedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types; 85 86 struct scard_data { 87 SCARDCONTEXT ctx; 88 SCARDHANDLE card; 89 DWORD protocol; 90 sim_types sim_type; 91 int pin1_required; 92 }; 93 94 #ifdef __MINGW32_VERSION 95 /* MinGW does not yet support WinScard, so load the needed functions 96 * dynamically from winscard.dll for now. */ 97 98 static HINSTANCE dll = NULL; /* winscard.dll */ 99 100 static const SCARD_IO_REQUEST *dll_g_rgSCardT0Pci, *dll_g_rgSCardT1Pci; 101 #undef SCARD_PCI_T0 102 #define SCARD_PCI_T0 (dll_g_rgSCardT0Pci) 103 #undef SCARD_PCI_T1 104 #define SCARD_PCI_T1 (dll_g_rgSCardT1Pci) 105 106 107 static WINSCARDAPI LONG WINAPI 108 (*dll_SCardEstablishContext)(IN DWORD dwScope, 109 IN LPCVOID pvReserved1, 110 IN LPCVOID pvReserved2, 111 OUT LPSCARDCONTEXT phContext); 112 #define SCardEstablishContext dll_SCardEstablishContext 113 114 static long (*dll_SCardReleaseContext)(long hContext); 115 #define SCardReleaseContext dll_SCardReleaseContext 116 117 static WINSCARDAPI LONG WINAPI 118 (*dll_SCardListReadersA)(IN SCARDCONTEXT hContext, 119 IN LPCSTR mszGroups, 120 OUT LPSTR mszReaders, 121 IN OUT LPDWORD pcchReaders); 122 #undef SCardListReaders 123 #define SCardListReaders dll_SCardListReadersA 124 125 static WINSCARDAPI LONG WINAPI 126 (*dll_SCardConnectA)(IN SCARDCONTEXT hContext, 127 IN LPCSTR szReader, 128 IN DWORD dwShareMode, 129 IN DWORD dwPreferredProtocols, 130 OUT LPSCARDHANDLE phCard, 131 OUT LPDWORD pdwActiveProtocol); 132 #undef SCardConnect 133 #define SCardConnect dll_SCardConnectA 134 135 static WINSCARDAPI LONG WINAPI 136 (*dll_SCardDisconnect)(IN SCARDHANDLE hCard, 137 IN DWORD dwDisposition); 138 #define SCardDisconnect dll_SCardDisconnect 139 140 static WINSCARDAPI LONG WINAPI 141 (*dll_SCardTransmit)(IN SCARDHANDLE hCard, 142 IN LPCSCARD_IO_REQUEST pioSendPci, 143 IN LPCBYTE pbSendBuffer, 144 IN DWORD cbSendLength, 145 IN OUT LPSCARD_IO_REQUEST pioRecvPci, 146 OUT LPBYTE pbRecvBuffer, 147 IN OUT LPDWORD pcbRecvLength); 148 #define SCardTransmit dll_SCardTransmit 149 150 static WINSCARDAPI LONG WINAPI 151 (*dll_SCardBeginTransaction)(IN SCARDHANDLE hCard); 152 #define SCardBeginTransaction dll_SCardBeginTransaction 153 154 static WINSCARDAPI LONG WINAPI 155 (*dll_SCardEndTransaction)(IN SCARDHANDLE hCard, IN DWORD dwDisposition); 156 #define SCardEndTransaction dll_SCardEndTransaction 157 158 159 static int mingw_load_symbols(void) 160 { 161 char *sym; 162 163 if (dll) 164 return 0; 165 166 dll = LoadLibrary("winscard"); 167 if (dll == NULL) { 168 wpa_printf(MSG_DEBUG, "WinSCard: Could not load winscard.dll " 169 "library"); 170 return -1; 171 } 172 173 #define LOADSYM(s) \ 174 sym = #s; \ 175 dll_ ## s = (void *) GetProcAddress(dll, sym); \ 176 if (dll_ ## s == NULL) \ 177 goto fail; 178 179 LOADSYM(SCardEstablishContext); 180 LOADSYM(SCardReleaseContext); 181 LOADSYM(SCardListReadersA); 182 LOADSYM(SCardConnectA); 183 LOADSYM(SCardDisconnect); 184 LOADSYM(SCardTransmit); 185 LOADSYM(SCardBeginTransaction); 186 LOADSYM(SCardEndTransaction); 187 LOADSYM(g_rgSCardT0Pci); 188 LOADSYM(g_rgSCardT1Pci); 189 190 #undef LOADSYM 191 192 return 0; 193 194 fail: 195 wpa_printf(MSG_DEBUG, "WinSCard: Could not get address for %s from " 196 "winscard.dll", sym); 197 FreeLibrary(dll); 198 dll = NULL; 199 return -1; 200 } 201 202 203 static void mingw_unload_symbols(void) 204 { 205 if (dll == NULL) 206 return; 207 208 FreeLibrary(dll); 209 dll = NULL; 210 } 211 212 #else /* __MINGW32_VERSION */ 213 214 #define mingw_load_symbols() 0 215 #define mingw_unload_symbols() do { } while (0) 216 217 #endif /* __MINGW32_VERSION */ 218 219 220 static int _scard_select_file(struct scard_data *scard, unsigned short file_id, 221 unsigned char *buf, size_t *buf_len, 222 sim_types sim_type, unsigned char *aid, 223 size_t aidlen); 224 static int scard_select_file(struct scard_data *scard, unsigned short file_id, 225 unsigned char *buf, size_t *buf_len); 226 static int scard_verify_pin(struct scard_data *scard, const char *pin); 227 static int scard_get_record_len(struct scard_data *scard, 228 unsigned char recnum, unsigned char mode); 229 static int scard_read_record(struct scard_data *scard, 230 unsigned char *data, size_t len, 231 unsigned char recnum, unsigned char mode); 232 233 234 static int scard_parse_fsp_templ(unsigned char *buf, size_t buf_len, 235 int *ps_do, int *file_len) 236 { 237 unsigned char *pos, *end; 238 239 if (ps_do) 240 *ps_do = -1; 241 if (file_len) 242 *file_len = -1; 243 244 pos = buf; 245 end = pos + buf_len; 246 if (*pos != USIM_FSP_TEMPL_TAG) { 247 wpa_printf(MSG_DEBUG, "SCARD: file header did not " 248 "start with FSP template tag"); 249 return -1; 250 } 251 pos++; 252 if (pos >= end) 253 return -1; 254 if ((pos + pos[0]) < end) 255 end = pos + 1 + pos[0]; 256 pos++; 257 wpa_hexdump(MSG_DEBUG, "SCARD: file header FSP template", 258 pos, end - pos); 259 260 while (pos + 1 < end) { 261 wpa_printf(MSG_MSGDUMP, "SCARD: file header TLV " 262 "0x%02x len=%d", pos[0], pos[1]); 263 if (pos + 2 + pos[1] > end) 264 break; 265 266 if (pos[0] == USIM_TLV_FILE_SIZE && 267 (pos[1] == 1 || pos[1] == 2) && file_len) { 268 if (pos[1] == 1) 269 *file_len = (int) pos[2]; 270 else 271 *file_len = ((int) pos[2] << 8) | 272 (int) pos[3]; 273 wpa_printf(MSG_DEBUG, "SCARD: file_size=%d", 274 *file_len); 275 } 276 277 if (pos[0] == USIM_TLV_PIN_STATUS_TEMPLATE && 278 pos[1] >= 2 && pos[2] == USIM_PS_DO_TAG && 279 pos[3] >= 1 && ps_do) { 280 wpa_printf(MSG_DEBUG, "SCARD: PS_DO=0x%02x", 281 pos[4]); 282 *ps_do = (int) pos[4]; 283 } 284 285 pos += 2 + pos[1]; 286 287 if (pos == end) 288 return 0; 289 } 290 return -1; 291 } 292 293 294 static int scard_pin_needed(struct scard_data *scard, 295 unsigned char *hdr, size_t hlen) 296 { 297 if (scard->sim_type == SCARD_GSM_SIM) { 298 if (hlen > SCARD_CHV1_OFFSET && 299 !(hdr[SCARD_CHV1_OFFSET] & SCARD_CHV1_FLAG)) 300 return 1; 301 return 0; 302 } 303 304 if (scard->sim_type == SCARD_USIM) { 305 int ps_do; 306 if (scard_parse_fsp_templ(hdr, hlen, &ps_do, NULL)) 307 return -1; 308 /* TODO: there could be more than one PS_DO entry because of 309 * multiple PINs in key reference.. */ 310 if (ps_do > 0 && (ps_do & 0x80)) 311 return 1; 312 return 0; 313 } 314 315 return -1; 316 } 317 318 319 static int scard_get_aid(struct scard_data *scard, unsigned char *aid, 320 size_t maxlen) 321 { 322 int rlen, rec; 323 struct efdir { 324 unsigned char appl_template_tag; /* 0x61 */ 325 unsigned char appl_template_len; 326 unsigned char appl_id_tag; /* 0x4f */ 327 unsigned char aid_len; 328 unsigned char rid[5]; 329 unsigned char appl_code[2]; /* 0x1002 for 3G USIM */ 330 } *efdir; 331 unsigned char buf[100]; 332 size_t blen; 333 334 efdir = (struct efdir *) buf; 335 blen = sizeof(buf); 336 if (scard_select_file(scard, SCARD_FILE_EF_DIR, buf, &blen)) { 337 wpa_printf(MSG_DEBUG, "SCARD: Failed to read EF_DIR"); 338 return -1; 339 } 340 wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR select", buf, blen); 341 342 for (rec = 1; rec < 10; rec++) { 343 rlen = scard_get_record_len(scard, rec, 344 SIM_RECORD_MODE_ABSOLUTE); 345 if (rlen < 0) { 346 wpa_printf(MSG_DEBUG, "SCARD: Failed to get EF_DIR " 347 "record length"); 348 return -1; 349 } 350 blen = sizeof(buf); 351 if (rlen > (int) blen) { 352 wpa_printf(MSG_DEBUG, "SCARD: Too long EF_DIR record"); 353 return -1; 354 } 355 if (scard_read_record(scard, buf, rlen, rec, 356 SIM_RECORD_MODE_ABSOLUTE) < 0) { 357 wpa_printf(MSG_DEBUG, "SCARD: Failed to read " 358 "EF_DIR record %d", rec); 359 return -1; 360 } 361 wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR record", buf, rlen); 362 363 if (efdir->appl_template_tag != 0x61) { 364 wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " 365 "template tag 0x%x", 366 efdir->appl_template_tag); 367 continue; 368 } 369 370 if (efdir->appl_template_len > rlen - 2) { 371 wpa_printf(MSG_DEBUG, "SCARD: Too long application " 372 "template (len=%d rlen=%d)", 373 efdir->appl_template_len, rlen); 374 continue; 375 } 376 377 if (efdir->appl_id_tag != 0x4f) { 378 wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " 379 "identifier tag 0x%x", efdir->appl_id_tag); 380 continue; 381 } 382 383 if (efdir->aid_len < 1 || efdir->aid_len > 16) { 384 wpa_printf(MSG_DEBUG, "SCARD: Invalid AID length %d", 385 efdir->aid_len); 386 continue; 387 } 388 389 wpa_hexdump(MSG_DEBUG, "SCARD: AID from EF_DIR record", 390 efdir->rid, efdir->aid_len); 391 392 if (efdir->appl_code[0] == 0x10 && 393 efdir->appl_code[1] == 0x02) { 394 wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app found from " 395 "EF_DIR record %d", rec); 396 break; 397 } 398 } 399 400 if (rec >= 10) { 401 wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app not found " 402 "from EF_DIR records"); 403 return -1; 404 } 405 406 if (efdir->aid_len > maxlen) { 407 wpa_printf(MSG_DEBUG, "SCARD: Too long AID"); 408 return -1; 409 } 410 411 os_memcpy(aid, efdir->rid, efdir->aid_len); 412 413 return efdir->aid_len; 414 } 415 416 417 /** 418 * scard_init - Initialize SIM/USIM connection using PC/SC 419 * @sim_type: Allowed SIM types (SIM, USIM, or both) 420 * Returns: Pointer to private data structure, or %NULL on failure 421 * 422 * This function is used to initialize SIM/USIM connection. PC/SC is used to 423 * open connection to the SIM/USIM card and the card is verified to support the 424 * selected sim_type. In addition, local flag is set if a PIN is needed to 425 * access some of the card functions. Once the connection is not needed 426 * anymore, scard_deinit() can be used to close it. 427 */ 428 struct scard_data * scard_init(scard_sim_type sim_type) 429 { 430 long ret; 431 unsigned long len; 432 struct scard_data *scard; 433 #ifdef CONFIG_NATIVE_WINDOWS 434 TCHAR *readers = NULL; 435 #else /* CONFIG_NATIVE_WINDOWS */ 436 char *readers = NULL; 437 #endif /* CONFIG_NATIVE_WINDOWS */ 438 unsigned char buf[100]; 439 size_t blen; 440 int transaction = 0; 441 int pin_needed; 442 443 wpa_printf(MSG_DEBUG, "SCARD: initializing smart card interface"); 444 if (mingw_load_symbols()) 445 return NULL; 446 scard = os_zalloc(sizeof(*scard)); 447 if (scard == NULL) 448 return NULL; 449 450 ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, 451 &scard->ctx); 452 if (ret != SCARD_S_SUCCESS) { 453 wpa_printf(MSG_DEBUG, "SCARD: Could not establish smart card " 454 "context (err=%ld)", ret); 455 goto failed; 456 } 457 458 ret = SCardListReaders(scard->ctx, NULL, NULL, &len); 459 if (ret != SCARD_S_SUCCESS) { 460 wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed " 461 "(err=%ld)", ret); 462 goto failed; 463 } 464 465 #ifdef UNICODE 466 len *= 2; 467 #endif /* UNICODE */ 468 readers = os_malloc(len); 469 if (readers == NULL) { 470 wpa_printf(MSG_INFO, "SCARD: malloc failed\n"); 471 goto failed; 472 } 473 474 ret = SCardListReaders(scard->ctx, NULL, readers, &len); 475 if (ret != SCARD_S_SUCCESS) { 476 wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed(2) " 477 "(err=%ld)", ret); 478 goto failed; 479 } 480 if (len < 3) { 481 wpa_printf(MSG_WARNING, "SCARD: No smart card readers " 482 "available."); 483 goto failed; 484 } 485 /* readers is a list of available reader. Last entry is terminated with 486 * double NUL. 487 * TODO: add support for selecting the reader; now just use the first 488 * one.. */ 489 #ifdef UNICODE 490 wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", readers); 491 #else /* UNICODE */ 492 wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", readers); 493 #endif /* UNICODE */ 494 495 ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED, 496 SCARD_PROTOCOL_T0, &scard->card, &scard->protocol); 497 if (ret != SCARD_S_SUCCESS) { 498 if (ret == (long) SCARD_E_NO_SMARTCARD) 499 wpa_printf(MSG_INFO, "No smart card inserted."); 500 else 501 wpa_printf(MSG_WARNING, "SCardConnect err=%lx", ret); 502 goto failed; 503 } 504 505 os_free(readers); 506 readers = NULL; 507 508 wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)", 509 (unsigned int) scard->card, scard->protocol, 510 scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1"); 511 512 ret = SCardBeginTransaction(scard->card); 513 if (ret != SCARD_S_SUCCESS) { 514 wpa_printf(MSG_DEBUG, "SCARD: Could not begin transaction: " 515 "0x%x", (unsigned int) ret); 516 goto failed; 517 } 518 transaction = 1; 519 520 blen = sizeof(buf); 521 522 scard->sim_type = SCARD_GSM_SIM; 523 if (sim_type == SCARD_USIM_ONLY || sim_type == SCARD_TRY_BOTH) { 524 wpa_printf(MSG_DEBUG, "SCARD: verifying USIM support"); 525 if (_scard_select_file(scard, SCARD_FILE_MF, buf, &blen, 526 SCARD_USIM, NULL, 0)) { 527 wpa_printf(MSG_DEBUG, "SCARD: USIM is not supported"); 528 if (sim_type == SCARD_USIM_ONLY) 529 goto failed; 530 wpa_printf(MSG_DEBUG, "SCARD: Trying to use GSM SIM"); 531 scard->sim_type = SCARD_GSM_SIM; 532 } else { 533 wpa_printf(MSG_DEBUG, "SCARD: USIM is supported"); 534 scard->sim_type = SCARD_USIM; 535 } 536 } 537 538 if (scard->sim_type == SCARD_GSM_SIM) { 539 blen = sizeof(buf); 540 if (scard_select_file(scard, SCARD_FILE_MF, buf, &blen)) { 541 wpa_printf(MSG_DEBUG, "SCARD: Failed to read MF"); 542 goto failed; 543 } 544 545 blen = sizeof(buf); 546 if (scard_select_file(scard, SCARD_FILE_GSM_DF, buf, &blen)) { 547 wpa_printf(MSG_DEBUG, "SCARD: Failed to read GSM DF"); 548 goto failed; 549 } 550 } else { 551 unsigned char aid[32]; 552 int aid_len; 553 554 aid_len = scard_get_aid(scard, aid, sizeof(aid)); 555 if (aid_len < 0) { 556 wpa_printf(MSG_DEBUG, "SCARD: Failed to find AID for " 557 "3G USIM app - try to use standard 3G RID"); 558 os_memcpy(aid, "\xa0\x00\x00\x00\x87", 5); 559 aid_len = 5; 560 } 561 wpa_hexdump(MSG_DEBUG, "SCARD: 3G USIM AID", aid, aid_len); 562 563 /* Select based on AID = 3G RID from EF_DIR. This is usually 564 * starting with A0 00 00 00 87. */ 565 blen = sizeof(buf); 566 if (_scard_select_file(scard, 0, buf, &blen, scard->sim_type, 567 aid, aid_len)) { 568 wpa_printf(MSG_INFO, "SCARD: Failed to read 3G USIM " 569 "app"); 570 wpa_hexdump(MSG_INFO, "SCARD: 3G USIM AID", 571 aid, aid_len); 572 goto failed; 573 } 574 } 575 576 /* Verify whether CHV1 (PIN1) is needed to access the card. */ 577 pin_needed = scard_pin_needed(scard, buf, blen); 578 if (pin_needed < 0) { 579 wpa_printf(MSG_DEBUG, "SCARD: Failed to determine whether PIN " 580 "is needed"); 581 goto failed; 582 } 583 if (pin_needed) { 584 scard->pin1_required = 1; 585 wpa_printf(MSG_DEBUG, "PIN1 needed for SIM access"); 586 } 587 588 ret = SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); 589 if (ret != SCARD_S_SUCCESS) { 590 wpa_printf(MSG_DEBUG, "SCARD: Could not end transaction: " 591 "0x%x", (unsigned int) ret); 592 } 593 594 return scard; 595 596 failed: 597 if (transaction) 598 SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); 599 os_free(readers); 600 scard_deinit(scard); 601 return NULL; 602 } 603 604 605 /** 606 * scard_set_pin - Set PIN (CHV1/PIN1) code for accessing SIM/USIM commands 607 * @scard: Pointer to private data from scard_init() 608 * @pin: PIN code as an ASCII string (e.g., "1234") 609 * Returns: 0 on success, -1 on failure 610 */ 611 int scard_set_pin(struct scard_data *scard, const char *pin) 612 { 613 if (scard == NULL) 614 return -1; 615 616 /* Verify whether CHV1 (PIN1) is needed to access the card. */ 617 if (scard->pin1_required) { 618 if (pin == NULL) { 619 wpa_printf(MSG_DEBUG, "No PIN configured for SIM " 620 "access"); 621 return -1; 622 } 623 if (scard_verify_pin(scard, pin)) { 624 wpa_printf(MSG_INFO, "PIN verification failed for " 625 "SIM access"); 626 return -1; 627 } 628 } 629 630 return 0; 631 } 632 633 634 /** 635 * scard_deinit - Deinitialize SIM/USIM connection 636 * @scard: Pointer to private data from scard_init() 637 * 638 * This function closes the SIM/USIM connect opened with scard_init(). 639 */ 640 void scard_deinit(struct scard_data *scard) 641 { 642 long ret; 643 644 if (scard == NULL) 645 return; 646 647 wpa_printf(MSG_DEBUG, "SCARD: deinitializing smart card interface"); 648 if (scard->card) { 649 ret = SCardDisconnect(scard->card, SCARD_UNPOWER_CARD); 650 if (ret != SCARD_S_SUCCESS) { 651 wpa_printf(MSG_DEBUG, "SCARD: Failed to disconnect " 652 "smart card (err=%ld)", ret); 653 } 654 } 655 656 if (scard->ctx) { 657 ret = SCardReleaseContext(scard->ctx); 658 if (ret != SCARD_S_SUCCESS) { 659 wpa_printf(MSG_DEBUG, "Failed to release smart card " 660 "context (err=%ld)", ret); 661 } 662 } 663 os_free(scard); 664 mingw_unload_symbols(); 665 } 666 667 668 static long scard_transmit(struct scard_data *scard, 669 unsigned char *_send, size_t send_len, 670 unsigned char *_recv, size_t *recv_len) 671 { 672 long ret; 673 unsigned long rlen; 674 675 wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send", 676 _send, send_len); 677 rlen = *recv_len; 678 ret = SCardTransmit(scard->card, 679 scard->protocol == SCARD_PROTOCOL_T1 ? 680 SCARD_PCI_T1 : SCARD_PCI_T0, 681 _send, (unsigned long) send_len, 682 NULL, _recv, &rlen); 683 *recv_len = rlen; 684 if (ret == SCARD_S_SUCCESS) { 685 wpa_hexdump(MSG_DEBUG, "SCARD: scard_transmit: recv", 686 _recv, rlen); 687 } else { 688 wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " 689 "(err=0x%lx)", ret); 690 } 691 return ret; 692 } 693 694 695 static int _scard_select_file(struct scard_data *scard, unsigned short file_id, 696 unsigned char *buf, size_t *buf_len, 697 sim_types sim_type, unsigned char *aid, 698 size_t aidlen) 699 { 700 long ret; 701 unsigned char resp[3]; 702 unsigned char cmd[50] = { SIM_CMD_SELECT }; 703 int cmdlen; 704 unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; 705 size_t len, rlen; 706 707 if (sim_type == SCARD_USIM) { 708 cmd[0] = USIM_CLA; 709 cmd[3] = 0x04; 710 get_resp[0] = USIM_CLA; 711 } 712 713 wpa_printf(MSG_DEBUG, "SCARD: select file %04x", file_id); 714 if (aid) { 715 wpa_hexdump(MSG_DEBUG, "SCARD: select file by AID", 716 aid, aidlen); 717 if (5 + aidlen > sizeof(cmd)) 718 return -1; 719 cmd[2] = 0x04; /* Select by AID */ 720 cmd[4] = aidlen; /* len */ 721 os_memcpy(cmd + 5, aid, aidlen); 722 cmdlen = 5 + aidlen; 723 } else { 724 cmd[5] = file_id >> 8; 725 cmd[6] = file_id & 0xff; 726 cmdlen = 7; 727 } 728 len = sizeof(resp); 729 ret = scard_transmit(scard, cmd, cmdlen, resp, &len); 730 if (ret != SCARD_S_SUCCESS) { 731 wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " 732 "(err=0x%lx)", ret); 733 return -1; 734 } 735 736 if (len != 2) { 737 wpa_printf(MSG_WARNING, "SCARD: unexpected resp len " 738 "%d (expected 2)", (int) len); 739 return -1; 740 } 741 742 if (resp[0] == 0x98 && resp[1] == 0x04) { 743 /* Security status not satisfied (PIN_WLAN) */ 744 wpa_printf(MSG_WARNING, "SCARD: Security status not satisfied " 745 "(PIN_WLAN)"); 746 return -1; 747 } 748 749 if (resp[0] == 0x6e) { 750 wpa_printf(MSG_DEBUG, "SCARD: used CLA not supported"); 751 return -1; 752 } 753 754 if (resp[0] != 0x6c && resp[0] != 0x9f && resp[0] != 0x61) { 755 wpa_printf(MSG_WARNING, "SCARD: unexpected response 0x%02x " 756 "(expected 0x61, 0x6c, or 0x9f)", resp[0]); 757 return -1; 758 } 759 /* Normal ending of command; resp[1] bytes available */ 760 get_resp[4] = resp[1]; 761 wpa_printf(MSG_DEBUG, "SCARD: trying to get response (%d bytes)", 762 resp[1]); 763 764 rlen = *buf_len; 765 ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &rlen); 766 if (ret == SCARD_S_SUCCESS) { 767 *buf_len = resp[1] < rlen ? resp[1] : rlen; 768 return 0; 769 } 770 771 wpa_printf(MSG_WARNING, "SCARD: SCardTransmit err=0x%lx\n", ret); 772 return -1; 773 } 774 775 776 static int scard_select_file(struct scard_data *scard, unsigned short file_id, 777 unsigned char *buf, size_t *buf_len) 778 { 779 return _scard_select_file(scard, file_id, buf, buf_len, 780 scard->sim_type, NULL, 0); 781 } 782 783 784 static int scard_get_record_len(struct scard_data *scard, unsigned char recnum, 785 unsigned char mode) 786 { 787 unsigned char buf[255]; 788 unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; 789 size_t blen; 790 long ret; 791 792 if (scard->sim_type == SCARD_USIM) 793 cmd[0] = USIM_CLA; 794 cmd[2] = recnum; 795 cmd[3] = mode; 796 cmd[4] = sizeof(buf); 797 798 blen = sizeof(buf); 799 ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); 800 if (ret != SCARD_S_SUCCESS) { 801 wpa_printf(MSG_DEBUG, "SCARD: failed to determine file " 802 "length for record %d", recnum); 803 return -1; 804 } 805 806 wpa_hexdump(MSG_DEBUG, "SCARD: file length determination response", 807 buf, blen); 808 809 if (blen < 2 || (buf[0] != 0x6c && buf[0] != 0x67)) { 810 wpa_printf(MSG_DEBUG, "SCARD: unexpected response to file " 811 "length determination"); 812 return -1; 813 } 814 815 return buf[1]; 816 } 817 818 819 static int scard_read_record(struct scard_data *scard, 820 unsigned char *data, size_t len, 821 unsigned char recnum, unsigned char mode) 822 { 823 unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; 824 size_t blen = len + 3; 825 unsigned char *buf; 826 long ret; 827 828 if (scard->sim_type == SCARD_USIM) 829 cmd[0] = USIM_CLA; 830 cmd[2] = recnum; 831 cmd[3] = mode; 832 cmd[4] = len; 833 834 buf = os_malloc(blen); 835 if (buf == NULL) 836 return -1; 837 838 ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); 839 if (ret != SCARD_S_SUCCESS) { 840 os_free(buf); 841 return -2; 842 } 843 if (blen != len + 2) { 844 wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " 845 "length %ld (expected %ld)", 846 (long) blen, (long) len + 2); 847 os_free(buf); 848 return -3; 849 } 850 851 if (buf[len] != 0x90 || buf[len + 1] != 0x00) { 852 wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " 853 "status %02x %02x (expected 90 00)", 854 buf[len], buf[len + 1]); 855 os_free(buf); 856 return -4; 857 } 858 859 os_memcpy(data, buf, len); 860 os_free(buf); 861 862 return 0; 863 } 864 865 866 static int scard_read_file(struct scard_data *scard, 867 unsigned char *data, size_t len) 868 { 869 unsigned char cmd[5] = { SIM_CMD_READ_BIN /* , len */ }; 870 size_t blen = len + 3; 871 unsigned char *buf; 872 long ret; 873 874 cmd[4] = len; 875 876 buf = os_malloc(blen); 877 if (buf == NULL) 878 return -1; 879 880 if (scard->sim_type == SCARD_USIM) 881 cmd[0] = USIM_CLA; 882 ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); 883 if (ret != SCARD_S_SUCCESS) { 884 os_free(buf); 885 return -2; 886 } 887 if (blen != len + 2) { 888 wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " 889 "length %ld (expected %ld)", 890 (long) blen, (long) len + 2); 891 os_free(buf); 892 return -3; 893 } 894 895 if (buf[len] != 0x90 || buf[len + 1] != 0x00) { 896 wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " 897 "status %02x %02x (expected 90 00)", 898 buf[len], buf[len + 1]); 899 os_free(buf); 900 return -4; 901 } 902 903 os_memcpy(data, buf, len); 904 os_free(buf); 905 906 return 0; 907 } 908 909 910 static int scard_verify_pin(struct scard_data *scard, const char *pin) 911 { 912 long ret; 913 unsigned char resp[3]; 914 unsigned char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 }; 915 size_t len; 916 917 wpa_printf(MSG_DEBUG, "SCARD: verifying PIN"); 918 919 if (pin == NULL || os_strlen(pin) > 8) 920 return -1; 921 922 if (scard->sim_type == SCARD_USIM) 923 cmd[0] = USIM_CLA; 924 os_memcpy(cmd + 5, pin, os_strlen(pin)); 925 os_memset(cmd + 5 + os_strlen(pin), 0xff, 8 - os_strlen(pin)); 926 927 len = sizeof(resp); 928 ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); 929 if (ret != SCARD_S_SUCCESS) 930 return -2; 931 932 if (len != 2 || resp[0] != 0x90 || resp[1] != 0x00) { 933 wpa_printf(MSG_WARNING, "SCARD: PIN verification failed"); 934 return -1; 935 } 936 937 wpa_printf(MSG_DEBUG, "SCARD: PIN verified successfully"); 938 return 0; 939 } 940 941 942 /** 943 * scard_get_imsi - Read IMSI from SIM/USIM card 944 * @scard: Pointer to private data from scard_init() 945 * @imsi: Buffer for IMSI 946 * @len: Length of imsi buffer; set to IMSI length on success 947 * Returns: 0 on success, -1 if IMSI file cannot be selected, -2 if IMSI file 948 * selection returns invalid result code, -3 if parsing FSP template file fails 949 * (USIM only), -4 if IMSI does not fit in the provided imsi buffer (len is set 950 * to needed length), -5 if reading IMSI file fails. 951 * 952 * This function can be used to read IMSI from the SIM/USIM card. If the IMSI 953 * file is PIN protected, scard_set_pin() must have been used to set the 954 * correct PIN code before calling scard_get_imsi(). 955 */ 956 int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) 957 { 958 unsigned char buf[100]; 959 size_t blen, imsilen, i; 960 char *pos; 961 962 wpa_printf(MSG_DEBUG, "SCARD: reading IMSI from (GSM) EF-IMSI"); 963 blen = sizeof(buf); 964 if (scard_select_file(scard, SCARD_FILE_GSM_EF_IMSI, buf, &blen)) 965 return -1; 966 if (blen < 4) { 967 wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-IMSI " 968 "header (len=%ld)", (long) blen); 969 return -2; 970 } 971 972 if (scard->sim_type == SCARD_GSM_SIM) { 973 blen = (buf[2] << 8) | buf[3]; 974 } else { 975 int file_size; 976 if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) 977 return -3; 978 blen = file_size; 979 } 980 if (blen < 2 || blen > sizeof(buf)) { 981 wpa_printf(MSG_DEBUG, "SCARD: invalid IMSI file length=%ld", 982 (long) blen); 983 return -3; 984 } 985 986 imsilen = (blen - 2) * 2 + 1; 987 wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%ld imsilen=%ld", 988 (long) blen, (long) imsilen); 989 if (blen < 2 || imsilen > *len) { 990 *len = imsilen; 991 return -4; 992 } 993 994 if (scard_read_file(scard, buf, blen)) 995 return -5; 996 997 pos = imsi; 998 *pos++ = '0' + (buf[1] >> 4 & 0x0f); 999 for (i = 2; i < blen; i++) { 1000 unsigned char digit; 1001 1002 digit = buf[i] & 0x0f; 1003 if (digit < 10) 1004 *pos++ = '0' + digit; 1005 else 1006 imsilen--; 1007 1008 digit = buf[i] >> 4 & 0x0f; 1009 if (digit < 10) 1010 *pos++ = '0' + digit; 1011 else 1012 imsilen--; 1013 } 1014 *len = imsilen; 1015 1016 return 0; 1017 } 1018 1019 1020 /** 1021 * scard_get_mnc_len - Read length of MNC in the IMSI from SIM/USIM card 1022 * @scard: Pointer to private data from scard_init() 1023 * Returns: length (>0) on success, -1 if administrative data file cannot be 1024 * selected, -2 if administrative data file selection returns invalid result 1025 * code, -3 if parsing FSP template file fails (USIM only), -4 if length of 1026 * the file is unexpected, -5 if reading file fails, -6 if MNC length is not 1027 * in range (i.e. 2 or 3), -7 if MNC length is not available. 1028 * 1029 */ 1030 int scard_get_mnc_len(struct scard_data *scard) 1031 { 1032 unsigned char buf[100]; 1033 size_t blen; 1034 int file_size; 1035 1036 wpa_printf(MSG_DEBUG, "SCARD: reading MNC len from (GSM) EF-AD"); 1037 blen = sizeof(buf); 1038 if (scard_select_file(scard, SCARD_FILE_GSM_EF_AD, buf, &blen)) 1039 return -1; 1040 if (blen < 4) { 1041 wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-AD " 1042 "header (len=%ld)", (long) blen); 1043 return -2; 1044 } 1045 1046 if (scard->sim_type == SCARD_GSM_SIM) { 1047 file_size = (buf[2] << 8) | buf[3]; 1048 } else { 1049 if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) 1050 return -3; 1051 } 1052 if (file_size == 3) { 1053 wpa_printf(MSG_DEBUG, "SCARD: MNC length not available"); 1054 return -7; 1055 } 1056 if (file_size < 4 || file_size > (int) sizeof(buf)) { 1057 wpa_printf(MSG_DEBUG, "SCARD: invalid file length=%ld", 1058 (long) file_size); 1059 return -4; 1060 } 1061 1062 if (scard_read_file(scard, buf, file_size)) 1063 return -5; 1064 buf[3] = buf[3] & 0x0f; /* upper nibble reserved for future use */ 1065 if (buf[3] < 2 || buf[3] > 3) { 1066 wpa_printf(MSG_DEBUG, "SCARD: invalid MNC length=%ld", 1067 (long) buf[3]); 1068 return -6; 1069 } 1070 wpa_printf(MSG_DEBUG, "SCARD: MNC length=%ld", (long) buf[3]); 1071 return buf[3]; 1072 } 1073 1074 1075 /** 1076 * scard_gsm_auth - Run GSM authentication command on SIM card 1077 * @scard: Pointer to private data from scard_init() 1078 * @_rand: 16-byte RAND value from HLR/AuC 1079 * @sres: 4-byte buffer for SRES 1080 * @kc: 8-byte buffer for Kc 1081 * Returns: 0 on success, -1 if SIM/USIM connection has not been initialized, 1082 * -2 if authentication command execution fails, -3 if unknown response code 1083 * for authentication command is received, -4 if reading of response fails, 1084 * -5 if if response data is of unexpected length 1085 * 1086 * This function performs GSM authentication using SIM/USIM card and the 1087 * provided RAND value from HLR/AuC. If authentication command can be completed 1088 * successfully, SRES and Kc values will be written into sres and kc buffers. 1089 */ 1090 int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, 1091 unsigned char *sres, unsigned char *kc) 1092 { 1093 unsigned char cmd[5 + 1 + 16] = { SIM_CMD_RUN_GSM_ALG }; 1094 int cmdlen; 1095 unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; 1096 unsigned char resp[3], buf[12 + 3 + 2]; 1097 size_t len; 1098 long ret; 1099 1100 if (scard == NULL) 1101 return -1; 1102 1103 wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - RAND", _rand, 16); 1104 if (scard->sim_type == SCARD_GSM_SIM) { 1105 cmdlen = 5 + 16; 1106 os_memcpy(cmd + 5, _rand, 16); 1107 } else { 1108 cmdlen = 5 + 1 + 16; 1109 cmd[0] = USIM_CLA; 1110 cmd[3] = 0x80; 1111 cmd[4] = 17; 1112 cmd[5] = 16; 1113 os_memcpy(cmd + 6, _rand, 16); 1114 } 1115 len = sizeof(resp); 1116 ret = scard_transmit(scard, cmd, cmdlen, resp, &len); 1117 if (ret != SCARD_S_SUCCESS) 1118 return -2; 1119 1120 if ((scard->sim_type == SCARD_GSM_SIM && 1121 (len != 2 || resp[0] != 0x9f || resp[1] != 0x0c)) || 1122 (scard->sim_type == SCARD_USIM && 1123 (len != 2 || resp[0] != 0x61 || resp[1] != 0x0e))) { 1124 wpa_printf(MSG_WARNING, "SCARD: unexpected response for GSM " 1125 "auth request (len=%ld resp=%02x %02x)", 1126 (long) len, resp[0], resp[1]); 1127 return -3; 1128 } 1129 get_resp[4] = resp[1]; 1130 1131 len = sizeof(buf); 1132 ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); 1133 if (ret != SCARD_S_SUCCESS) 1134 return -4; 1135 1136 if (scard->sim_type == SCARD_GSM_SIM) { 1137 if (len != 4 + 8 + 2) { 1138 wpa_printf(MSG_WARNING, "SCARD: unexpected data " 1139 "length for GSM auth (len=%ld, expected 14)", 1140 (long) len); 1141 return -5; 1142 } 1143 os_memcpy(sres, buf, 4); 1144 os_memcpy(kc, buf + 4, 8); 1145 } else { 1146 if (len != 1 + 4 + 1 + 8 + 2) { 1147 wpa_printf(MSG_WARNING, "SCARD: unexpected data " 1148 "length for USIM auth (len=%ld, " 1149 "expected 16)", (long) len); 1150 return -5; 1151 } 1152 if (buf[0] != 4 || buf[5] != 8) { 1153 wpa_printf(MSG_WARNING, "SCARD: unexpected SREC/Kc " 1154 "length (%d %d, expected 4 8)", 1155 buf[0], buf[5]); 1156 } 1157 os_memcpy(sres, buf + 1, 4); 1158 os_memcpy(kc, buf + 6, 8); 1159 } 1160 1161 wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - SRES", sres, 4); 1162 wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - Kc", kc, 8); 1163 1164 return 0; 1165 } 1166 1167 1168 /** 1169 * scard_umts_auth - Run UMTS authentication command on USIM card 1170 * @scard: Pointer to private data from scard_init() 1171 * @_rand: 16-byte RAND value from HLR/AuC 1172 * @autn: 16-byte AUTN value from HLR/AuC 1173 * @res: 16-byte buffer for RES 1174 * @res_len: Variable that will be set to RES length 1175 * @ik: 16-byte buffer for IK 1176 * @ck: 16-byte buffer for CK 1177 * @auts: 14-byte buffer for AUTS 1178 * Returns: 0 on success, -1 on failure, or -2 if USIM reports synchronization 1179 * failure 1180 * 1181 * This function performs AKA authentication using USIM card and the provided 1182 * RAND and AUTN values from HLR/AuC. If authentication command can be 1183 * completed successfully, RES, IK, and CK values will be written into provided 1184 * buffers and res_len is set to length of received RES value. If USIM reports 1185 * synchronization failure, the received AUTS value will be written into auts 1186 * buffer. In this case, RES, IK, and CK are not valid. 1187 */ 1188 int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, 1189 const unsigned char *autn, 1190 unsigned char *res, size_t *res_len, 1191 unsigned char *ik, unsigned char *ck, unsigned char *auts) 1192 { 1193 unsigned char cmd[5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN] = 1194 { USIM_CMD_RUN_UMTS_ALG }; 1195 unsigned char get_resp[5] = { USIM_CMD_GET_RESPONSE }; 1196 unsigned char resp[3], buf[64], *pos, *end; 1197 size_t len; 1198 long ret; 1199 1200 if (scard == NULL) 1201 return -1; 1202 1203 if (scard->sim_type == SCARD_GSM_SIM) { 1204 wpa_printf(MSG_ERROR, "SCARD: Non-USIM card - cannot do UMTS " 1205 "auth"); 1206 return -1; 1207 } 1208 1209 wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - RAND", _rand, AKA_RAND_LEN); 1210 wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - AUTN", autn, AKA_AUTN_LEN); 1211 cmd[5] = AKA_RAND_LEN; 1212 os_memcpy(cmd + 6, _rand, AKA_RAND_LEN); 1213 cmd[6 + AKA_RAND_LEN] = AKA_AUTN_LEN; 1214 os_memcpy(cmd + 6 + AKA_RAND_LEN + 1, autn, AKA_AUTN_LEN); 1215 1216 len = sizeof(resp); 1217 ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); 1218 if (ret != SCARD_S_SUCCESS) 1219 return -1; 1220 1221 if (len <= sizeof(resp)) 1222 wpa_hexdump(MSG_DEBUG, "SCARD: UMTS alg response", resp, len); 1223 1224 if (len == 2 && resp[0] == 0x98 && resp[1] == 0x62) { 1225 wpa_printf(MSG_WARNING, "SCARD: UMTS auth failed - " 1226 "MAC != XMAC"); 1227 return -1; 1228 } else if (len != 2 || resp[0] != 0x61) { 1229 wpa_printf(MSG_WARNING, "SCARD: unexpected response for UMTS " 1230 "auth request (len=%ld resp=%02x %02x)", 1231 (long) len, resp[0], resp[1]); 1232 return -1; 1233 } 1234 get_resp[4] = resp[1]; 1235 1236 len = sizeof(buf); 1237 ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); 1238 if (ret != SCARD_S_SUCCESS || len > sizeof(buf)) 1239 return -1; 1240 1241 wpa_hexdump(MSG_DEBUG, "SCARD: UMTS get response result", buf, len); 1242 if (len >= 2 + AKA_AUTS_LEN && buf[0] == 0xdc && 1243 buf[1] == AKA_AUTS_LEN) { 1244 wpa_printf(MSG_DEBUG, "SCARD: UMTS Synchronization-Failure"); 1245 os_memcpy(auts, buf + 2, AKA_AUTS_LEN); 1246 wpa_hexdump(MSG_DEBUG, "SCARD: AUTS", auts, AKA_AUTS_LEN); 1247 return -2; 1248 } else if (len >= 6 + IK_LEN + CK_LEN && buf[0] == 0xdb) { 1249 pos = buf + 1; 1250 end = buf + len; 1251 1252 /* RES */ 1253 if (pos[0] > RES_MAX_LEN || pos + pos[0] > end) { 1254 wpa_printf(MSG_DEBUG, "SCARD: Invalid RES"); 1255 return -1; 1256 } 1257 *res_len = *pos++; 1258 os_memcpy(res, pos, *res_len); 1259 pos += *res_len; 1260 wpa_hexdump(MSG_DEBUG, "SCARD: RES", res, *res_len); 1261 1262 /* CK */ 1263 if (pos[0] != CK_LEN || pos + CK_LEN > end) { 1264 wpa_printf(MSG_DEBUG, "SCARD: Invalid CK"); 1265 return -1; 1266 } 1267 pos++; 1268 os_memcpy(ck, pos, CK_LEN); 1269 pos += CK_LEN; 1270 wpa_hexdump(MSG_DEBUG, "SCARD: CK", ck, CK_LEN); 1271 1272 /* IK */ 1273 if (pos[0] != IK_LEN || pos + IK_LEN > end) { 1274 wpa_printf(MSG_DEBUG, "SCARD: Invalid IK"); 1275 return -1; 1276 } 1277 pos++; 1278 os_memcpy(ik, pos, IK_LEN); 1279 pos += IK_LEN; 1280 wpa_hexdump(MSG_DEBUG, "SCARD: IK", ik, IK_LEN); 1281 1282 return 0; 1283 } 1284 1285 wpa_printf(MSG_DEBUG, "SCARD: Unrecognized response"); 1286 return -1; 1287 } 1288