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