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