14e867904c8295537803c1c8a076e130df5674b58mikesamuel/* 24e867904c8295537803c1c8a076e130df5674b58mikesamuel * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM 34e867904c8295537803c1c8a076e130df5674b58mikesamuel * Copyright (c) 2004-2007, 2012, Jouni Malinen <j@w1.fi> 44e867904c8295537803c1c8a076e130df5674b58mikesamuel * 54e867904c8295537803c1c8a076e130df5674b58mikesamuel * This software may be distributed under the terms of the BSD license. 64e867904c8295537803c1c8a076e130df5674b58mikesamuel * See README for more details. 74e867904c8295537803c1c8a076e130df5674b58mikesamuel * 84e867904c8295537803c1c8a076e130df5674b58mikesamuel * This file implements wrapper functions for accessing GSM SIM and 3GPP USIM 94e867904c8295537803c1c8a076e130df5674b58mikesamuel * cards through PC/SC smartcard library. These functions are used to implement 104e867904c8295537803c1c8a076e130df5674b58mikesamuel * authentication routines for EAP-SIM and EAP-AKA. 114e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 124e867904c8295537803c1c8a076e130df5674b58mikesamuel 134e867904c8295537803c1c8a076e130df5674b58mikesamuel#include "includes.h" 144e867904c8295537803c1c8a076e130df5674b58mikesamuel#ifdef __APPLE__ 154e867904c8295537803c1c8a076e130df5674b58mikesamuel#include <PCSC/winscard.h> 164e867904c8295537803c1c8a076e130df5674b58mikesamuel#else 174e867904c8295537803c1c8a076e130df5674b58mikesamuel#include <winscard.h> 184e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif 194e867904c8295537803c1c8a076e130df5674b58mikesamuel 204e867904c8295537803c1c8a076e130df5674b58mikesamuel#include "common.h" 214e867904c8295537803c1c8a076e130df5674b58mikesamuel#include "pcsc_funcs.h" 224e867904c8295537803c1c8a076e130df5674b58mikesamuel 234e867904c8295537803c1c8a076e130df5674b58mikesamuel 244e867904c8295537803c1c8a076e130df5674b58mikesamuel/* See ETSI GSM 11.11 and ETSI TS 102 221 for details. 254e867904c8295537803c1c8a076e130df5674b58mikesamuel * SIM commands: 26T&���aZ'�?!�������uJ�"�(�#� * Command APDU: CLA INS P1 P2 P3 Data 27I���=� * CLA (class of instruction): A0 for GSM, 00 for USIM 284e867904c8295537803c1c8a076e130df5674b58mikesamuel * INS (instruction) 294e867904c8295537803c1c8a076e130df5674b58mikesamuel * P1 P2 P3 (parameters, P3 = length of Data) 304e867904c8295537803c1c8a076e130df5674b58mikesamuel * Response APDU: Data SW1 SW2 31s#ӓ[�V�LI+/f���{G�c��Ո��e �x� �@"� * SW1 SW2 (Status words) 32U��Uq�P��X��WV*US/�[ѫ�iTʧo����ĭ�&�՛�,�@������ * Commands (INS P1 P2 P3): 334e867904c8295537803c1c8a076e130df5674b58mikesamuel * SELECT: A4 00 00 02 <file_id, 2 bytes> 344e867904c8295537803c1c8a076e130df5674b58mikesamuel * GET RESPONSE: C0 00 00 <len> 354e867904c8295537803c1c8a076e130df5674b58mikesamuel * RUN GSM ALG: 88 00 00 00 <RAND len = 10> 364e867904c8295537803c1c8a076e130df5674b58mikesamuel * RUN UMTS ALG: 88 00 81 <len=0x22> data: 0x10 | RAND | 0x10 | AUTN 37b��-�����l�M�gnQ * P1 = ID of alg in card 384e867904c8295537803c1c8a076e130df5674b58mikesamuel * P2 = ID of secret key 394e867904c8295537803c1c8a076e130df5674b58mikesamuel * READ BINARY: B0 <offset high> <offset low> <len> 404e867904c8295537803c1c8a076e130df5674b58mikesamuel * READ RECORD: B2 <record number> <mode> <len> 41qsWE& * P2 (mode) = '02' (next record), '03' (previous record), 424e867904c8295537803c1c8a076e130df5674b58mikesamuel * '04' (absolute mode) 437J� * VERIFY CHV: 20 00 <CHV number> 08 444e867904c8295537803c1c8a076e130df5674b58mikesamuel * CHANGE CHV: 24 00 <CHV number> 10 454�w * DISABLE CHV: 26 00 01 08 464e867904c8295537803c1c8a076e130df5674b58mikesamuel * ENABLE CHV: 28 00 01 08 474e867904c8295537803c1c8a076e130df5674b58mikesamuel * UNBLOCK CHV: 2C 00 <00=CHV1, 02=CHV2> 10 484e867904c8295537803c1c8a076e130df5674b58mikesamuel * SLEEP: FA 00 00 00 494e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 504e867904c8295537803c1c8a076e130df5674b58mikesamuel 514e867904c8295537803c1c8a076e130df5674b58mikesamuel/* GSM SIM commands */ 52h����->�z���_���ڥ�l�:,������i���+|��q���]j=���#define SIM_CMD_SELECT 0xa0, 0xa4, 0x00, 0x00, 0x02 534e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SIM_CMD_RUN_GSM_ALG 0xa0, 0x88, 0x00, 0x00, 0x10 544e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SIM_CMD_GET_RESPONSE 0xa0, 0xc0, 0x00, 0x00 55J����C���O�$�W�c�&�/!B+U�\�=����p���#define SIM_CMD_READ_BIN 0xa0, 0xb0, 0x00, 0x00 564e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SIM_CMD_READ_RECORD 0xa0, 0xb2, 0x00, 0x00 574e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SIM_CMD_VERIFY_CHV1 0xa0, 0x20, 0x00, 0x01, 0x08 584e867904c8295537803c1c8a076e130df5674b58mikesamuel 594e867904c8295537803c1c8a076e130df5674b58mikesamuel/* USIM commands */ 60n�|%�H�ς�#define USIM_CLA 0x00 61zh���.L�� k:ɕ��T�JNZiG���̐{*�as�w��D�Q��xo��ҩ�"�:)w�\�^� %�JiӰ}C����θ�fԹT�J�J�:�}��*:Hl��-Z#define USIM_CMD_RUN_UMTS_ALG 0x00, 0x88, 0x00, 0x81, 0x22 62vG��Xi#define USIM_CMD_GET_RESPONSE 0x00, 0xc0, 0x00, 0x00 634e867904c8295537803c1c8a076e130df5674b58mikesamuel 64D�/�������т��#define SIM_RECORD_MODE_ABSOLUTE 0x04 654e867904c8295537803c1c8a076e130df5674b58mikesamuel 664e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_FSP_TEMPL_TAG 0x62 674e867904c8295537803c1c8a076e130df5674b58mikesamuel 684e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_FILE_DESC 0x82 694e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_FILE_ID 0x83 70Zz]?%?�$K,�� ���I�K��O�JM.adGR��X��\�Z�X��������� ���$�XPK/#define USIM_TLV_DF_NAME 0x84 71H21$��,#�(#define USIM_TLV_PROPR_INFO 0xA5 724e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_LIFE_CYCLE_STATUS 0x8A 734e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_FILE_SIZE 0x80 744e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_TOTAL_FILE_SIZE 0x81 754e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_PIN_STATUS_TEMPLATE 0xC6 764e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_SHORT_FILE_ID 0x88 774e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_SECURITY_ATTR_8B 0x8B 784e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_TLV_SECURITY_ATTR_8C 0x8C 79w�>z�?�ws�С#define USIM_TLV_SECURITY_ATTR_AB 0xAB 80Q<"�P���F 814e867904c8295537803c1c8a076e130df5674b58mikesamuel#define USIM_PS_DO_TAG 0x90 824e867904c8295537803c1c8a076e130df5674b58mikesamuel 834e867904c8295537803c1c8a076e130df5674b58mikesamuel#define AKA_RAND_LEN 16 844e867904c8295537803c1c8a076e130df5674b58mikesamuel#define AKA_AUTN_LEN 16 854e867904c8295537803c1c8a076e130df5674b58mikesamuel#define AKA_AUTS_LEN 14 864e867904c8295537803c1c8a076e130df5674b58mikesamuel#define RES_MAX_LEN 16 874e867904c8295537803c1c8a076e130df5674b58mikesamuel#define IK_LEN 16 884e867904c8295537803c1c8a076e130df5674b58mikesamuel#define CK_LEN 16 894e867904c8295537803c1c8a076e130df5674b58mikesamuel 902l��Ⱦ�~�pډb�T�/�[�g��TsE�W�a��F)j�[�,ѓ��"<���-*T, 914e867904c8295537803c1c8a076e130df5674b58mikesamuel/* GSM files 92K��.��;D�&m��l�|�<f�L�]F_��|�.�pӤ-FM><���jK� �Qt��� �:��k * File type in first octet: 934e867904c8295537803c1c8a076e130df5674b58mikesamuel * 3F = Master File 944e867904c8295537803c1c8a076e130df5674b58mikesamuel * 7F = Dedicated File 954e867904c8295537803c1c8a076e130df5674b58mikesamuel * 2F = Elementary File under the Master File 964e867904c8295537803c1c8a076e130df5674b58mikesamuel * 6F = Elementary File under a Dedicated File 974e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 984e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_MF 0x3F00 994e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_GSM_DF 0x7F20 1004e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_UMTS_DF 0x7F50 1014e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_GSM_EF_IMSI 0x6F07 1024e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_GSM_EF_AD 0x6FAD 1034e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_EF_DIR 0x2F00 1044e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_EF_ICCID 0x2FE2 1054e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_EF_CK 0x6FE1 1064e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_FILE_EF_IK 0x6FE2 1074e867904c8295537803c1c8a076e130df5674b58mikesamuel 1084e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_CHV1_OFFSET 13 1094e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_CHV1_FLAG 0x80 110ZH�� �r��s�������s���p=�nz� 1114e867904c8295537803c1c8a076e130df5674b58mikesamuel 1124e867904c8295537803c1c8a076e130df5674b58mikesamueltypedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types; 113eg6uz�f 1146jM��|���Y���},struct scard_data { 1154e867904c8295537803c1c8a076e130df5674b58mikesamuel SCARDCONTEXT ctx; 1164e867904c8295537803c1c8a076e130df5674b58mikesamuel SCARDHANDLE card; 1174e867904c8295537803c1c8a076e130df5674b58mikesamuel#ifdef __APPLE__ 1184e867904c8295537803c1c8a076e130df5674b58mikesamuel uint32_t protocol; 1194e867904c8295537803c1c8a076e130df5674b58mikesamuel#else 1204e867904c8295537803c1c8a076e130df5674b58mikesamuel DWORD protocol; 1214e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif 1224e867904c8295537803c1c8a076e130df5674b58mikesamuel sim_types sim_type; 1235�� int pin1_required; 1244e867904c8295537803c1c8a076e130df5674b58mikesamuel}; 1254e867904c8295537803c1c8a076e130df5674b58mikesamuel 126O��#ifdef __MINGW32_VERSION 1274e867904c8295537803c1c8a076e130df5674b58mikesamuel/* MinGW does not yet support WinScard, so load the needed functions 1284e867904c8295537803c1c8a076e130df5674b58mikesamuel * dynamically from winscard.dll for now. */ 1294e867904c8295537803c1c8a076e130df5674b58mikesamuel 130zu�� �-ǭ�B���static HINSTANCE dll = NULL; /* winscard.dll */ 1314e867904c8295537803c1c8a076e130df5674b58mikesamuel 132O{^D�߆�e�Uestatic const SCARD_IO_REQUEST *dll_g_rgSCardT0Pci, *dll_g_rgSCardT1Pci; 133fz���Y��#undef SCARD_PCI_T0 134d����C#define SCARD_PCI_T0 (dll_g_rgSCardT0Pci) 1354e867904c8295537803c1c8a076e130df5674b58mikesamuel#undef SCARD_PCI_T1 1364e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCARD_PCI_T1 (dll_g_rgSCardT1Pci) 1374e867904c8295537803c1c8a076e130df5674b58mikesamuel 138u'�B ���[,'�l:YVo�) 1394e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic WINSCARDAPI LONG WINAPI 1404e867904c8295537803c1c8a076e130df5674b58mikesamuel(*dll_SCardEstablishContext)(IN DWORD dwScope, 1414e867904c8295537803c1c8a076e130df5674b58mikesamuel IN LPCVOID pvReserved1, 1424e867904c8295537803c1c8a076e130df5674b58mikesamuel IN LPCVOID pvReserved2, 1434e867904c8295537803c1c8a076e130df5674b58mikesamuel OUT LPSCARDCONTEXT phContext); 1444e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCardEstablishContext dll_SCardEstablishContext 1454e867904c8295537803c1c8a076e130df5674b58mikesamuel 1464e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic long (*dll_SCardReleaseContext)(long hContext); 1474e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCardReleaseContext dll_SCardReleaseContext 148n��ǐ� 1494e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic WINSCARDAPI LONG WINAPI 1504e867904c8295537803c1c8a076e130df5674b58mikesamuel(*dll_SCardListReadersA)(IN SCARDCONTEXT hContext, 1514e867904c8295537803c1c8a076e130df5674b58mikesamuel IN LPCSTR mszGroups, 1524e867904c8295537803c1c8a076e130df5674b58mikesamuel OUT LPSTR mszReaders, 1534e867904c8295537803c1c8a076e130df5674b58mikesamuel IN OUT LPDWORD pcchReaders); 1544e867904c8295537803c1c8a076e130df5674b58mikesamuel#undef SCardListReaders 155XaZ���)��P�@j�]�Y+�h�ɭ�X�e�i(�Ec;M�y.b+m��ۻ��f/Uht$j���H#define SCardListReaders dll_SCardListReadersA 1564e867904c8295537803c1c8a076e130df5674b58mikesamuel 1574e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic WINSCARDAPI LONG WINAPI 1584e867904c8295537803c1c8a076e130df5674b58mikesamuel(*dll_SCardConnectA)(IN SCARDCONTEXT hContext, 1594e867904c8295537803c1c8a076e130df5674b58mikesamuel IN LPCSTR szReader, 160J�N� IN DWORD dwShareMode, 161qɹ�i�fԕ��̓s�.��$� IN DWORD dwPreferredProtocols, 1624e867904c8295537803c1c8a076e130df5674b58mikesamuel OUT LPSCARDHANDLE phCard, 1634e867904c8295537803c1c8a076e130df5674b58mikesamuel OUT LPDWORD pdwActiveProtocol); 1644e867904c8295537803c1c8a076e130df5674b58mikesamuel#undef SCardConnect 165E�[��߉wCE����I�nûT���u��Qj�R���iK��@#define SCardConnect dll_SCardConnectA 1664e867904c8295537803c1c8a076e130df5674b58mikesamuel 1674e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic WINSCARDAPI LONG WINAPI 1684e867904c8295537803c1c8a076e130df5674b58mikesamuel(*dll_SCardDisconnect)(IN SCARDHANDLE hCard, 1694e867904c8295537803c1c8a076e130df5674b58mikesamuel IN DWORD dwDisposition); 170Q��e��P��^��u�O��E��hE�!=v�#define SCardDisconnect dll_SCardDisconnect 1714e867904c8295537803c1c8a076e130df5674b58mikesamuel 1724e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic WINSCARDAPI LONG WINAPI 1734e867904c8295537803c1c8a076e130df5674b58mikesamuel(*dll_SCardTransmit)(IN SCARDHANDLE hCard, 1744e867904c8295537803c1c8a076e130df5674b58mikesamuel IN LPCSCARD_IO_REQUEST pioSendPci, 175c��"-d���?���څ`�I�*v�j��Jd IN LPCBYTE pbSendBuffer, 176hVF�B��L���Z�����G�U͈��@�p�Q��KS%%ڪA�>n IN DWORD cbSendLength, 177U�vW�Qj�%�\�N" IN OUT LPSCARD_IO_REQUEST pioRecvPci, 1784e867904c8295537803c1c8a076e130df5674b58mikesamuel OUT LPBYTE pbRecvBuffer, 179oP� IN OUT LPDWORD pcbRecvLength); 1804e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCardTransmit dll_SCardTransmit 1814e867904c8295537803c1c8a076e130df5674b58mikesamuel 1824e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic WINSCARDAPI LONG WINAPI 1834e867904c8295537803c1c8a076e130df5674b58mikesamuel(*dll_SCardBeginTransaction)(IN SCARDHANDLE hCard); 1844e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCardBeginTransaction dll_SCardBeginTransaction 1854e867904c8295537803c1c8a076e130df5674b58mikesamuel 1864e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic WINSCARDAPI LONG WINAPI 1874e867904c8295537803c1c8a076e130df5674b58mikesamuel(*dll_SCardEndTransaction)(IN SCARDHANDLE hCard, IN DWORD dwDisposition); 1884e867904c8295537803c1c8a076e130df5674b58mikesamuel#define SCardEndTransaction dll_SCardEndTransaction 189s�� 1904e867904c8295537803c1c8a076e130df5674b58mikesamuel 1914e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int mingw_load_symbols(void) 1924e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 1938D����q�t�N���: char *sym; 1944e867904c8295537803c1c8a076e130df5674b58mikesamuel 1954e867904c8295537803c1c8a076e130df5674b58mikesamuel if (dll) 196Ofȴ/����h�C�ϧ=@gfC�o��aK}�-��Gna��u��f�#��x�k�G� return 0; 1974e867904c8295537803c1c8a076e130df5674b58mikesamuel 1984e867904c8295537803c1c8a076e130df5674b58mikesamuel dll = LoadLibrary("winscard"); 1994e867904c8295537803c1c8a076e130df5674b58mikesamuel if (dll == NULL) { 2006�x�⡊-�����]� wpa_printf(MSG_DEBUG, "WinSCard: Could not load winscard.dll " 2014e867904c8295537803c1c8a076e130df5674b58mikesamuel "library"); 202c��� ] return -1; 2034e867904c8295537803c1c8a076e130df5674b58mikesamuel } 2044e867904c8295537803c1c8a076e130df5674b58mikesamuel 2054e867904c8295537803c1c8a076e130df5674b58mikesamuel#define LOADSYM(s) \ 2064e867904c8295537803c1c8a076e130df5674b58mikesamuel sym = #s; \ 2074e867904c8295537803c1c8a076e130df5674b58mikesamuel dll_ ## s = (void *) GetProcAddress(dll, sym); \ 2084e867904c8295537803c1c8a076e130df5674b58mikesamuel if (dll_ ## s == NULL) \ 2094e867904c8295537803c1c8a076e130df5674b58mikesamuel goto fail; 2104e867904c8295537803c1c8a076e130df5674b58mikesamuel 2114e867904c8295537803c1c8a076e130df5674b58mikesamuel LOADSYM(SCardEstablishContext); 2124e867904c8295537803c1c8a076e130df5674b58mikesamuel LOADSYM(SCardReleaseContext); 213F��Viy���ۻw�M�L=l�����=d��N=&�\�� LOADSYM(SCardListReadersA); 214j�Bl��\W�� LOADSYM(SCardConnectA); 2154e867904c8295537803c1c8a076e130df5674b58mikesamuel LOADSYM(SCardDisconnect); 216Cz'KE����W��;�����\��a LOADSYM(SCardTransmit); 217n@$��dR LOADSYM(SCardBeginTransaction); 218s���/�)�� LOADSYM(SCardEndTransaction); 2194e867904c8295537803c1c8a076e130df5674b58mikesamuel LOADSYM(g_rgSCardT0Pci); 2204e867904c8295537803c1c8a076e130df5674b58mikesamuel LOADSYM(g_rgSCardT1Pci); 221Y���xp�����띆b�DӘ����|��^��J��!�χ�$ig\��<��-�@w!ԗ㷄�����*.J�/J;�w�)J[NQ�� 2224e867904c8295537803c1c8a076e130df5674b58mikesamuel#undef LOADSYM 223n��)���O�PK��l� H PK 224P���o��������_�__Q��|����)�*_�����_���B:�@�B} return 0; 2254e867904c8295537803c1c8a076e130df5674b58mikesamuel 2264e867904c8295537803c1c8a076e130df5674b58mikesamuelfail: 2274e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "WinSCard: Could not get address for %s from " 228z��F�!��"��L��h#v��e�,W\�bt%]l� "winscard.dll", sym); 229Bg��ԕ� FreeLibrary(dll); 2304e867904c8295537803c1c8a076e130df5674b58mikesamuel dll = NULL; 231Ol]��%���T��}�= return -1; 2324e867904c8295537803c1c8a076e130df5674b58mikesamuel} 2334e867904c8295537803c1c8a076e130df5674b58mikesamuel 2344e867904c8295537803c1c8a076e130df5674b58mikesamuel 2354e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic void mingw_unload_symbols(void) 236ft�$[{ 2374e867904c8295537803c1c8a076e130df5674b58mikesamuel if (dll == NULL) 2384e867904c8295537803c1c8a076e130df5674b58mikesamuel return; 239Q���^�K� 2404e867904c8295537803c1c8a076e130df5674b58mikesamuel FreeLibrary(dll); 2414e867904c8295537803c1c8a076e130df5674b58mikesamuel dll = NULL; 2424e867904c8295537803c1c8a076e130df5674b58mikesamuel} 243p����q�Ul���*�R�>!Z��� 2444e867904c8295537803c1c8a076e130df5674b58mikesamuel#else /* __MINGW32_VERSION */ 2454e867904c8295537803c1c8a076e130df5674b58mikesamuel 2464e867904c8295537803c1c8a076e130df5674b58mikesamuel#define mingw_load_symbols() 0 2474e867904c8295537803c1c8a076e130df5674b58mikesamuel#define mingw_unload_symbols() do { } while (0) 2484e867904c8295537803c1c8a076e130df5674b58mikesamuel 2494e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif /* __MINGW32_VERSION */ 2504e867904c8295537803c1c8a076e130df5674b58mikesamuel 2514e867904c8295537803c1c8a076e130df5674b58mikesamuel 2524e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int _scard_select_file(struct scard_data *scard, unsigned short file_id, 253VBqŚI� unsigned char *buf, size_t *buf_len, 254M��e�ߖy�'�%�|bL����f~��} sim_types sim_type, unsigned char *aid, 255Lu]Ym�m�U�{�a��i�a�?��*�>W�.=�C���m�] size_t aidlen); 256K�$�A�o�����}static int scard_select_file(struct scard_data *scard, unsigned short file_id, 2574e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *buf, size_t *buf_len); 2584e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int scard_verify_pin(struct scard_data *scard, const char *pin); 2594e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int scard_get_record_len(struct scard_data *scard, 2604e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char recnum, unsigned char mode); 2614e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int scard_read_record(struct scard_data *scard, 2624e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *data, size_t len, 2634e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char recnum, unsigned char mode); 264x���j!��'��*o�ˊ 2654e867904c8295537803c1c8a076e130df5674b58mikesamuel 266UZH�(�iistatic int scard_parse_fsp_templ(unsigned char *buf, size_t buf_len, 2674e867904c8295537803c1c8a076e130df5674b58mikesamuel int *ps_do, int *file_len) 2684e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 2694e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *pos, *end; 2704e867904c8295537803c1c8a076e130df5674b58mikesamuel 2714e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ps_do) 2724e867904c8295537803c1c8a076e130df5674b58mikesamuel *ps_do = -1; 2734e867904c8295537803c1c8a076e130df5674b58mikesamuel if (file_len) 2744e867904c8295537803c1c8a076e130df5674b58mikesamuel *file_len = -1; 2754e867904c8295537803c1c8a076e130df5674b58mikesamuel 2764e867904c8295537803c1c8a076e130df5674b58mikesamuel pos = buf; 2774e867904c8295537803c1c8a076e130df5674b58mikesamuel end = pos + buf_len; 2784e867904c8295537803c1c8a076e130df5674b58mikesamuel if (*pos != USIM_FSP_TEMPL_TAG) { 2794e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: file header did not " 2804e867904c8295537803c1c8a076e130df5674b58mikesamuel "start with FSP template tag"); 2814e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 2824e867904c8295537803c1c8a076e130df5674b58mikesamuel } 2834e867904c8295537803c1c8a076e130df5674b58mikesamuel pos++; 2844e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pos >= end) 2854e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 2864e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pos[0] < end - pos) 287u� end = pos + 1 + pos[0]; 2884e867904c8295537803c1c8a076e130df5674b58mikesamuel pos++; 2894e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: file header FSP template", 2904e867904c8295537803c1c8a076e130df5674b58mikesamuel pos, end - pos); 2914e867904c8295537803c1c8a076e130df5674b58mikesamuel 2924e867904c8295537803c1c8a076e130df5674b58mikesamuel while (end - pos >= 2) { 2934e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char type, len; 2944e867904c8295537803c1c8a076e130df5674b58mikesamuel 2954e867904c8295537803c1c8a076e130df5674b58mikesamuel type = pos[0]; 2964e867904c8295537803c1c8a076e130df5674b58mikesamuel len = pos[1]; 2974e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_MSGDUMP, "SCARD: file header TLV 0x%02x len=%d", 2984e867904c8295537803c1c8a076e130df5674b58mikesamuel type, len); 2992M�\�"CC��> pos += 2; 3001aot�A�N�v��Î�-v�#���� ��k�:�mv�����/:p_f'>������(*��F�XQ� 3014e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len > (unsigned int) (end - pos)) 3024e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3034e867904c8295537803c1c8a076e130df5674b58mikesamuel 3044e867904c8295537803c1c8a076e130df5674b58mikesamuel switch (type) { 3054e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_FILE_DESC: 306h{��* wpa_hexdump(MSG_MSGDUMP, "SCARD: File Descriptor TLV", 3074e867904c8295537803c1c8a076e130df5674b58mikesamuel pos, len); 3084e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3094e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_FILE_ID: 3104e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_MSGDUMP, "SCARD: File Identifier TLV", 3114e867904c8295537803c1c8a076e130df5674b58mikesamuel pos, len); 3124e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 313j�l�_��dw��y����;��B^��Ɯ�mXC���mv��)����N���q�F}�H{G�"BA����%ݰ case USIM_TLV_DF_NAME: 3144e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_MSGDUMP, "SCARD: DF name (AID) TLV", 3154e867904c8295537803c1c8a076e130df5674b58mikesamuel pos, len); 3164e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3174e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_PROPR_INFO: 3184e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_MSGDUMP, "SCARD: Proprietary " 3194e867904c8295537803c1c8a076e130df5674b58mikesamuel "information TLV", pos, len); 320CS�r������* break; 3214e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_LIFE_CYCLE_STATUS: 3224e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_MSGDUMP, "SCARD: Life Cycle Status " 323PbbL<�����IV "Integer TLV", pos, len); 3244e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3254e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_FILE_SIZE: 3269��y����}� wpa_hexdump(MSG_MSGDUMP, "SCARD: File size TLV", 3279�(�ڒ� Hg��pn�)'Q��� c�' pos, len); 3284e867904c8295537803c1c8a076e130df5674b58mikesamuel if ((len == 1 || len == 2) && file_len) { 329L2dD��� if (len == 1) 330DώbjJO *file_len = (int) pos[0]; 3314e867904c8295537803c1c8a076e130df5674b58mikesamuel else 3324e867904c8295537803c1c8a076e130df5674b58mikesamuel *file_len = WPA_GET_BE16(pos); 3334e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: file_size=%d", 3344e867904c8295537803c1c8a076e130df5674b58mikesamuel *file_len); 3354e867904c8295537803c1c8a076e130df5674b58mikesamuel } 3364e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3374e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_TOTAL_FILE_SIZE: 3384e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_MSGDUMP, "SCARD: Total file size TLV", 3394e867904c8295537803c1c8a076e130df5674b58mikesamuel pos, len); 3404e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3414e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_PIN_STATUS_TEMPLATE: 3424e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_MSGDUMP, "SCARD: PIN Status Template " 343PKPK "DO TLV", pos, len); 3444e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len >= 2 && pos[0] == USIM_PS_DO_TAG && 3454e867904c8295537803c1c8a076e130df5674b58mikesamuel pos[1] >= 1 && ps_do) { 3464e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: PS_DO=0x%02x", 3474e867904c8295537803c1c8a076e130df5674b58mikesamuel pos[2]); 3484e867904c8295537803c1c8a076e130df5674b58mikesamuel *ps_do = (int) pos[2]; 3494e867904c8295537803c1c8a076e130df5674b58mikesamuel } 3504e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3514e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_SHORT_FILE_ID: 352H�*� wpa_hexdump(MSG_MSGDUMP, "SCARD: Short File " 353Wq�S*�[� "Identifier (SFI) TLV", pos, len); 3544e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3552c%Q�� case USIM_TLV_SECURITY_ATTR_8B: 3564e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_SECURITY_ATTR_8C: 3574e867904c8295537803c1c8a076e130df5674b58mikesamuel case USIM_TLV_SECURITY_ATTR_AB: 3588xҴ��<j�F� wpa_hexdump(MSG_MSGDUMP, "SCARD: Security attribute " 3594e867904c8295537803c1c8a076e130df5674b58mikesamuel "TLV", pos, len); 3604e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 3616mW�٬�#�� default: 3624e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_MSGDUMP, "SCARD: Unrecognized TLV", 3634e867904c8295537803c1c8a076e130df5674b58mikesamuel pos, len); 3644e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 365_��X&���� } 3664e867904c8295537803c1c8a076e130df5674b58mikesamuel 3674e867904c8295537803c1c8a076e130df5674b58mikesamuel pos += len; 3684e867904c8295537803c1c8a076e130df5674b58mikesamuel 3694e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pos == end) 3704e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 3714e867904c8295537803c1c8a076e130df5674b58mikesamuel } 3724e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 3734e867904c8295537803c1c8a076e130df5674b58mikesamuel} 3744e867904c8295537803c1c8a076e130df5674b58mikesamuel 375S8J-.M�"�I"w 376Qs�"� ��n!G+(`GJV��XRD���H��(~D�k���ostatic int scard_pin_needed(struct scard_data *scard, 3774e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *hdr, size_t hlen) 3784e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 3794e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_GSM_SIM) { 380cҿ�sܡ����G�PW� if (hlen > SCARD_CHV1_OFFSET && 381PlJJ����&#xS�[B��ↆ)�T !(hdr[SCARD_CHV1_OFFSET] & SCARD_CHV1_FLAG)) 3824e867904c8295537803c1c8a076e130df5674b58mikesamuel return 1; 3834e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 3844e867904c8295537803c1c8a076e130df5674b58mikesamuel } 3854e867904c8295537803c1c8a076e130df5674b58mikesamuel 3864e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_USIM) { 3874e867904c8295537803c1c8a076e130df5674b58mikesamuel int ps_do; 3884e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_parse_fsp_templ(hdr, hlen, &ps_do, NULL)) 3894e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 3904e867904c8295537803c1c8a076e130df5674b58mikesamuel /* TODO: there could be more than one PS_DO entry because of 3914e867904c8295537803c1c8a076e130df5674b58mikesamuel * multiple PINs in key reference.. */ 3924e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ps_do > 0 && (ps_do & 0x80)) 3934e867904c8295537803c1c8a076e130df5674b58mikesamuel return 1; 3944e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 3954e867904c8295537803c1c8a076e130df5674b58mikesamuel } 3964e867904c8295537803c1c8a076e130df5674b58mikesamuel 3974e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 3984e867904c8295537803c1c8a076e130df5674b58mikesamuel} 3994e867904c8295537803c1c8a076e130df5674b58mikesamuel 400naWBI��I�'QaXv��s�)lG������ 4014e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int scard_get_aid(struct scard_data *scard, unsigned char *aid, 4024e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t maxlen) 4034e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 4044e867904c8295537803c1c8a076e130df5674b58mikesamuel int rlen, rec; 4054e867904c8295537803c1c8a076e130df5674b58mikesamuel struct efdir { 4064e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char appl_template_tag; /* 0x61 */ 4074e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char appl_template_len; 408o0᠌n�ȸ���We\Ƭ�+ J�ճx� unsigned char appl_id_tag; /* 0x4f */ 4094e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char aid_len; 410Vorg/dom unsigned char rid[5]; 411J;�:Bu�o>��T%_ unsigned char appl_code[2]; /* 0x1002 for 3G USIM */ 4124e867904c8295537803c1c8a076e130df5674b58mikesamuel } *efdir; 4134e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char buf[127], *aid_pos; 414Ndzi��Й���ߞ=ɯ�� �ⱈ�;ч�a� '�uM�uL�!B��M��ŇY>� ��y]�-����"z� `Q�C����uE�bEݨf+z=��]tV��yUS����&�A�(=EUSV��-�ؐ�j�-�e��)*v�ֶj size_t blen; 4154e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned int aid_len = 0; 4164e867904c8295537803c1c8a076e130df5674b58mikesamuel 4171�e%� efdir = (struct efdir *) buf; 418dbU���_��ySWN&~ө aid_pos = &buf[4]; 4194e867904c8295537803c1c8a076e130df5674b58mikesamuel blen = sizeof(buf); 4204e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_select_file(scard, SCARD_FILE_EF_DIR, buf, &blen)) { 4214e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Failed to read EF_DIR"); 4224e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 4234e867904c8295537803c1c8a076e130df5674b58mikesamuel } 4244e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR select", buf, blen); 4254e867904c8295537803c1c8a076e130df5674b58mikesamuel 4264e867904c8295537803c1c8a076e130df5674b58mikesamuel for (rec = 1; rec < 10; rec++) { 427S#��zF�%�e�e�ˠ rlen = scard_get_record_len(scard, rec, 4284e867904c8295537803c1c8a076e130df5674b58mikesamuel SIM_RECORD_MODE_ABSOLUTE); 4294e867904c8295537803c1c8a076e130df5674b58mikesamuel if (rlen < 0) { 4304e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Failed to get EF_DIR " 4314e867904c8295537803c1c8a076e130df5674b58mikesamuel "record length"); 4324e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 4334e867904c8295537803c1c8a076e130df5674b58mikesamuel } 4344e867904c8295537803c1c8a076e130df5674b58mikesamuel blen = sizeof(buf); 4354e867904c8295537803c1c8a076e130df5674b58mikesamuel if (rlen > (int) blen) { 4364e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Too long EF_DIR record"); 4374e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 4384e867904c8295537803c1c8a076e130df5674b58mikesamuel } 4394e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_read_record(scard, buf, rlen, rec, 4404e867904c8295537803c1c8a076e130df5674b58mikesamuel SIM_RECORD_MODE_ABSOLUTE) < 0) { 441BөK� wpa_printf(MSG_DEBUG, "SCARD: Failed to read " 4424e867904c8295537803c1c8a076e130df5674b58mikesamuel "EF_DIR record %d", rec); 4434e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 444DWi\đ } 4454e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR record", buf, rlen); 446QbS&*g��JKD��%�� 4474e867904c8295537803c1c8a076e130df5674b58mikesamuel if (efdir->appl_template_tag != 0x61) { 4484e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " 4494e867904c8295537803c1c8a076e130df5674b58mikesamuel "template tag 0x%x", 45082f|���pt[ efdir->appl_template_tag); 4514e867904c8295537803c1c8a076e130df5674b58mikesamuel continue; 4524e867904c8295537803c1c8a076e130df5674b58mikesamuel } 4534e867904c8295537803c1c8a076e130df5674b58mikesamuel 4544e867904c8295537803c1c8a076e130df5674b58mikesamuel if (efdir->appl_template_len > rlen - 2) { 455b��ۡ$K��U�ѝ> wpa_printf(MSG_DEBUG, "SCARD: Too long application " 4564e867904c8295537803c1c8a076e130df5674b58mikesamuel "template (len=%d rlen=%d)", 457faY���e� efdir->appl_template_len, rlen); 4584e867904c8295537803c1c8a076e130df5674b58mikesamuel continue; 4594e867904c8295537803c1c8a076e130df5674b58mikesamuel } 4604e867904c8295537803c1c8a076e130df5674b58mikesamuel 4614e867904c8295537803c1c8a076e130df5674b58mikesamuel if (efdir->appl_id_tag != 0x4f) { 4624e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " 4634e867904c8295537803c1c8a076e130df5674b58mikesamuel "identifier tag 0x%x", efdir->appl_id_tag); 4644e867904c8295537803c1c8a076e130df5674b58mikesamuel continue; 4654e867904c8295537803c1c8a076e130df5674b58mikesamuel } 4664e867904c8295537803c1c8a076e130df5674b58mikesamuel 4674e867904c8295537803c1c8a076e130df5674b58mikesamuel aid_len = efdir->aid_len; 4684e867904c8295537803c1c8a076e130df5674b58mikesamuel if (aid_len < 1 || aid_len > 16) { 4694e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Invalid AID length %u", 4704e867904c8295537803c1c8a076e130df5674b58mikesamuel aid_len); 4714e867904c8295537803c1c8a076e130df5674b58mikesamuel continue; 4724e867904c8295537803c1c8a076e130df5674b58mikesamuel } 4734e867904c8295537803c1c8a076e130df5674b58mikesamuel 474E�fG��xE��ly� wpa_hexdump(MSG_DEBUG, "SCARD: AID from EF_DIR record", 4751Z��?^�Ɔ_b.�WH�,s���.�ߤ�ٛt(��o��&�>��D aid_pos, aid_len); 4764e867904c8295537803c1c8a076e130df5674b58mikesamuel 4774e867904c8295537803c1c8a076e130df5674b58mikesamuel if (efdir->appl_code[0] == 0x10 && 4784e867904c8295537803c1c8a076e130df5674b58mikesamuel efdir->appl_code[1] == 0x02) { 479MK;���tQ� wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app found from " 4804e867904c8295537803c1c8a076e130df5674b58mikesamuel "EF_DIR record %d", rec); 4814e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 482O�hTu L���|v�db'��x(��N�#�eq)�)��%��Jb } 483A� } 4844e867904c8295537803c1c8a076e130df5674b58mikesamuel 4854e867904c8295537803c1c8a076e130df5674b58mikesamuel if (rec >= 10) { 4864e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app not found " 487p���,���������gQz��<b���<��~&^D "from EF_DIR records"); 4884e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 489y� b�.�|���ȵ�r-W��q��]n���s,|�L!��B.<��!�b}<�WPE } 4904e867904c8295537803c1c8a076e130df5674b58mikesamuel 4914e867904c8295537803c1c8a076e130df5674b58mikesamuel if (aid_len > maxlen) { 4924e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Too long AID"); 4934e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 4944e867904c8295537803c1c8a076e130df5674b58mikesamuel } 495v�W���@�^*VFc*^��*�i���U���m� 4964e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(aid, aid_pos, aid_len); 4974e867904c8295537803c1c8a076e130df5674b58mikesamuel 498IV�������; return aid_len; 4994e867904c8295537803c1c8a076e130df5674b58mikesamuel} 5004e867904c8295537803c1c8a076e130df5674b58mikesamuel 501ZSK���m�sf�L���Z 502IBJ��/** 5034e867904c8295537803c1c8a076e130df5674b58mikesamuel * scard_init - Initialize SIM/USIM connection using PC/SC 5044e867904c8295537803c1c8a076e130df5674b58mikesamuel * @reader: Reader name prefix to search for 5054e867904c8295537803c1c8a076e130df5674b58mikesamuel * Returns: Pointer to private data structure, or %NULL on failure 5064e867904c8295537803c1c8a076e130df5674b58mikesamuel * 507lbi���z��B�/�٧ * This function is used to initialize SIM/USIM connection. PC/SC is used to 5084e867904c8295537803c1c8a076e130df5674b58mikesamuel * open connection to the SIM/USIM card. In addition, local flag is set if a 509_w����ZԻ���P�|^�/ؖz,K�mK�Q,cbY��� * PIN is needed to access some of the card functions. Once the connection is 5104e867904c8295537803c1c8a076e130df5674b58mikesamuel * not needed anymore, scard_deinit() can be used to close it. 5114e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 5124e867904c8295537803c1c8a076e130df5674b58mikesamuelstruct scard_data * scard_init(const char *reader) 5134e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 5144e867904c8295537803c1c8a076e130df5674b58mikesamuel long ret; 5154e867904c8295537803c1c8a076e130df5674b58mikesamuel#ifdef __APPLE__ 516X�eǻS??�'dש�It!E���,Ao�d�+�kd��� uint32_t len; 5174e867904c8295537803c1c8a076e130df5674b58mikesamuel#else 5184e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned long len; 5194e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif 5204e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned long pos; 5214e867904c8295537803c1c8a076e130df5674b58mikesamuel struct scard_data *scard; 5224e867904c8295537803c1c8a076e130df5674b58mikesamuel#ifdef CONFIG_NATIVE_WINDOWS 5234e867904c8295537803c1c8a076e130df5674b58mikesamuel TCHAR *readers = NULL; 5249��q�:ǔ��#else /* CONFIG_NATIVE_WINDOWS */ 5254e867904c8295537803c1c8a076e130df5674b58mikesamuel char *readers = NULL; 5264e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif /* CONFIG_NATIVE_WINDOWS */ 5274e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char buf[100]; 5284e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t blen; 529z���ʈ��f int transaction = 0; 5304e867904c8295537803c1c8a076e130df5674b58mikesamuel int pin_needed; 5314e867904c8295537803c1c8a076e130df5674b58mikesamuel 5324e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: initializing smart card interface"); 533D��� if (mingw_load_symbols()) 5344e867904c8295537803c1c8a076e130df5674b58mikesamuel return NULL; 5354�A��η scard = os_zalloc(sizeof(*scard)); 5364e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard == NULL) 537Bk}):M�J�|tXpO return NULL; 5384e867904c8295537803c1c8a076e130df5674b58mikesamuel 5394e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, 540E�<�� _`WR_E &scard->ctx); 5415��ڼô�@Xo"��˂�:`� if (ret != SCARD_S_SUCCESS) { 5422���Ӕ�l���|�|��ϧ���`�oЛ �җ� wpa_printf(MSG_DEBUG, "SCARD: Could not establish smart card " 5434e867904c8295537803c1c8a076e130df5674b58mikesamuel "context (err=%ld)", ret); 5444e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 5454e867904c8295537803c1c8a076e130df5674b58mikesamuel } 5464e867904c8295537803c1c8a076e130df5674b58mikesamuel 5474e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = SCardListReaders(scard->ctx, NULL, NULL, &len); 5486�d[� if (ret != SCARD_S_SUCCESS) { 549Z] wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed " 5504e867904c8295537803c1c8a076e130df5674b58mikesamuel "(err=%ld)", ret); 5514e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 552l�-<��� } 5534e867904c8295537803c1c8a076e130df5674b58mikesamuel 5544e867904c8295537803c1c8a076e130df5674b58mikesamuel#ifdef UNICODE 5554e867904c8295537803c1c8a076e130df5674b58mikesamuel len *= 2; 5564e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif /* UNICODE */ 5577�U���� readers = os_malloc(len); 5586���S�I�[ �濢�R~ if (readers == NULL) { 5594e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_INFO, "SCARD: malloc failed\n"); 5604e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 5614e867904c8295537803c1c8a076e130df5674b58mikesamuel } 5624e867904c8295537803c1c8a076e130df5674b58mikesamuel 5634e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = SCardListReaders(scard->ctx, NULL, readers, &len); 5644e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) { 5654e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed(2) " 5664e867904c8295537803c1c8a076e130df5674b58mikesamuel "(err=%ld)", ret); 5674e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 5684e867904c8295537803c1c8a076e130df5674b58mikesamuel } 5694e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len < 3) { 5704e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: No smart card readers " 5714e867904c8295537803c1c8a076e130df5674b58mikesamuel "available."); 572D�&����Z�A goto failed; 5734e867904c8295537803c1c8a076e130df5674b58mikesamuel } 574W)����jE wpa_hexdump_ascii(MSG_DEBUG, "SCARD: Readers", (u8 *) readers, len); 575dfªhI /* 5764e867904c8295537803c1c8a076e130df5674b58mikesamuel * readers is a list of available readers. The last entry is terminated 5774e867904c8295537803c1c8a076e130df5674b58mikesamuel * with double null. 578o�"Ӿ�b�d���G��O ���`�M�{�Z���� */ 579Paj�L�M�bNh�k��e',�CAY��L pos = 0; 5804e867904c8295537803c1c8a076e130df5674b58mikesamuel#ifdef UNICODE 5814e867904c8295537803c1c8a076e130df5674b58mikesamuel /* TODO */ 5824e867904c8295537803c1c8a076e130df5674b58mikesamuel#else /* UNICODE */ 5834e867904c8295537803c1c8a076e130df5674b58mikesamuel while (pos < len) { 5844e867904c8295537803c1c8a076e130df5674b58mikesamuel if (reader == NULL || 5854e867904c8295537803c1c8a076e130df5674b58mikesamuel os_strncmp(&readers[pos], reader, os_strlen(reader)) == 0) 5864e867904c8295537803c1c8a076e130df5674b58mikesamuel break; 5874e867904c8295537803c1c8a076e130df5674b58mikesamuel while (pos < len && readers[pos]) 5884e867904c8295537803c1c8a076e130df5674b58mikesamuel pos++; 5895��� pos++; /* skip separating null */ 590X��u������ɖ��i�O�;` if (pos < len && readers[pos] == '\0') 5914e867904c8295537803c1c8a076e130df5674b58mikesamuel pos = len; /* double null terminates list */ 5924e867904c8295537803c1c8a076e130df5674b58mikesamuel } 5934e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif /* UNICODE */ 5944e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pos >= len) { 5957�%~ wpa_printf(MSG_WARNING, "SCARD: No reader with prefix '%s' " 5964e867904c8295537803c1c8a076e130df5674b58mikesamuel "found", reader); 597kZ goto failed; 5984e867904c8295537803c1c8a076e130df5674b58mikesamuel } 599p����S�y��gc�;��L���t��q. �k� 6004e867904c8295537803c1c8a076e130df5674b58mikesamuel#ifdef UNICODE 6014e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", &readers[pos]); 6021IaiRBU�]�wk�gĵ�D#else /* UNICODE */ 603Tᄒ������ˌH���) wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", &readers[pos]); 6044e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif /* UNICODE */ 6054e867904c8295537803c1c8a076e130df5674b58mikesamuel 6064e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = SCardConnect(scard->ctx, &readers[pos], SCARD_SHARE_SHARED, 6074e867904c8295537803c1c8a076e130df5674b58mikesamuel SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, 6084e867904c8295537803c1c8a076e130df5674b58mikesamuel &scard->card, &scard->protocol); 609OmՐ<���{�%A]u��;�֙*�v��] if (ret != SCARD_S_SUCCESS) { 6104e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret == (long) SCARD_E_NO_SMARTCARD) 6114e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_INFO, "No smart card inserted."); 612G�ʈ else 613X��q��b+�[���Mj����"� wpa_printf(MSG_WARNING, "SCardConnect err=%lx", ret); 6144e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 6154e867904c8295537803c1c8a076e130df5674b58mikesamuel } 6164e867904c8295537803c1c8a076e130df5674b58mikesamuel 6174e867904c8295537803c1c8a076e130df5674b58mikesamuel os_free(readers); 6184e867904c8295537803c1c8a076e130df5674b58mikesamuel readers = NULL; 6194e867904c8295537803c1c8a076e130df5674b58mikesamuel 6206f�K��;�_T\�\l��w�u�!�a!+�,BH���]�q���� wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)", 6214e867904c8295537803c1c8a076e130df5674b58mikesamuel (unsigned int) scard->card, (unsigned long) scard->protocol, 6224e867904c8295537803c1c8a076e130df5674b58mikesamuel scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1"); 6237��sm(��ɾE���x���KL�o� � 6244e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = SCardBeginTransaction(scard->card); 6254e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) { 6264e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Could not begin transaction: " 6274e867904c8295537803c1c8a076e130df5674b58mikesamuel "0x%x", (unsigned int) ret); 6284e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 629M�A���P�ppc�>#��� } 6304e867904c8295537803c1c8a076e130df5674b58mikesamuel transaction = 1; 6314e867904c8295537803c1c8a076e130df5674b58mikesamuel 632Cn���RY�bc��`Ƞ @L��`�����sA�����Կ�ԏR����Կ���@��L���?zj�b=���O���Vk�Ԛ���A��Q�o��mz}�^ߢ�R� blen = sizeof(buf); 6334e867904c8295537803c1c8a076e130df5674b58mikesamuel 634qsQ�n#H�;@b� ݣC�N wpa_printf(MSG_DEBUG, "SCARD: verifying USIM support"); 6354e867904c8295537803c1c8a076e130df5674b58mikesamuel if (_scard_select_file(scard, SCARD_FILE_MF, buf, &blen, 636R����� SCARD_USIM, NULL, 0)) { 6374e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: USIM is not supported. Trying to use GSM SIM"); 6384e867904c8295537803c1c8a076e130df5674b58mikesamuel scard->sim_type = SCARD_GSM_SIM; 6394e867904c8295537803c1c8a076e130df5674b58mikesamuel } else { 6404e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: USIM is supported"); 6414e867904c8295537803c1c8a076e130df5674b58mikesamuel scard->sim_type = SCARD_USIM; 6425Pm�籕�'�Z-�Y�E�zɄ�B�n�� } 6434e867904c8295537803c1c8a076e130df5674b58mikesamuel 6444e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_GSM_SIM) { 6454e867904c8295537803c1c8a076e130df5674b58mikesamuel blen = sizeof(buf); 646x=㸜]d���?p�C��$�n�kݪ� if (scard_select_file(scard, SCARD_FILE_MF, buf, &blen)) { 6474e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Failed to read MF"); 6484e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 6494e867904c8295537803c1c8a076e130df5674b58mikesamuel } 6504e867904c8295537803c1c8a076e130df5674b58mikesamuel 6514e867904c8295537803c1c8a076e130df5674b58mikesamuel blen = sizeof(buf); 6524e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_select_file(scard, SCARD_FILE_GSM_DF, buf, &blen)) { 6534e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Failed to read GSM DF"); 6546�'�Q��;�jѪ�rQS� ;Z�+a��,r��< goto failed; 6554e867904c8295537803c1c8a076e130df5674b58mikesamuel } 6564e867904c8295537803c1c8a076e130df5674b58mikesamuel } else { 657VO"��#��h�� unsigned char aid[32]; 6584e867904c8295537803c1c8a076e130df5674b58mikesamuel int aid_len; 6594e867904c8295537803c1c8a076e130df5674b58mikesamuel 6604e867904c8295537803c1c8a076e130df5674b58mikesamuel aid_len = scard_get_aid(scard, aid, sizeof(aid)); 6614e867904c8295537803c1c8a076e130df5674b58mikesamuel if (aid_len < 0) { 6624e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Failed to find AID for " 663e�fT��`���U�!x\��� "3G USIM app - try to use standard 3G RID"); 664j�?���w%�����x"��Gb~�c�[lBo��:����� os_memcpy(aid, "\xa0\x00\x00\x00\x87", 5); 665Z#{�kb��Y���Q�M�� ��`͘��$V����E�&�p aid_len = 5; 666lU�/ } 6679�=FiS�� wpa_hexdump(MSG_DEBUG, "SCARD: 3G USIM AID", aid, aid_len); 6684e867904c8295537803c1c8a076e130df5674b58mikesamuel 6694�� /* Select based on AID = 3G RID from EF_DIR. This is usually 6704e867904c8295537803c1c8a076e130df5674b58mikesamuel * starting with A0 00 00 00 87. */ 6714e867904c8295537803c1c8a076e130df5674b58mikesamuel blen = sizeof(buf); 6724e867904c8295537803c1c8a076e130df5674b58mikesamuel if (_scard_select_file(scard, 0, buf, &blen, scard->sim_type, 6734e867904c8295537803c1c8a076e130df5674b58mikesamuel aid, aid_len)) { 674B�� ���e� �x�t�`w�a� ��n� L��ܝ wpa_printf(MSG_INFO, "SCARD: Failed to read 3G USIM " 6754e867904c8295537803c1c8a076e130df5674b58mikesamuel "app"); 676_rHm wpa_hexdump(MSG_INFO, "SCARD: 3G USIM AID", 6774e867904c8295537803c1c8a076e130df5674b58mikesamuel aid, aid_len); 6784e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 6794e867904c8295537803c1c8a076e130df5674b58mikesamuel } 680AX��k?� } 6814e867904c8295537803c1c8a076e130df5674b58mikesamuel 682G�� �Da���}�����&VSq,�^�u��u��u��� ,�bC�g[�,���ӣ������=���Vb��� /* Verify whether CHV1 (PIN1) is needed to access the card. */ 6834e867904c8295537803c1c8a076e130df5674b58mikesamuel pin_needed = scard_pin_needed(scard, buf, blen); 6842x����}T��W�� if (pin_needed < 0) { 685a�i wpa_printf(MSG_DEBUG, "SCARD: Failed to determine whether PIN " 6864e867904c8295537803c1c8a076e130df5674b58mikesamuel "is needed"); 6874e867904c8295537803c1c8a076e130df5674b58mikesamuel goto failed; 6884e867904c8295537803c1c8a076e130df5674b58mikesamuel } 6894e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pin_needed) { 6904e867904c8295537803c1c8a076e130df5674b58mikesamuel scard->pin1_required = 1; 6914e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "PIN1 needed for SIM access (retry " 6924e867904c8295537803c1c8a076e130df5674b58mikesamuel "counter=%d)", scard_get_pin_retry_counter(scard)); 693uJCZ��k���eq\�&��& �:� } 6944e867904c8295537803c1c8a076e130df5674b58mikesamuel 6954e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); 6964e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) { 6974e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Could not end transaction: " 698_���!��٫�q��BwPn��ټc�AV�P;����bT�NLT��:�~'�J]������d��uN�� "0x%x", (unsigned int) ret); 6994e867904c8295537803c1c8a076e130df5674b58mikesamuel } 700p#T�� p�?�E�_-�yHn�<&y�������YP�i��B?�O��"�n��~����� �u 7014e867904c8295537803c1c8a076e130df5674b58mikesamuel return scard; 7024e867904c8295537803c1c8a076e130df5674b58mikesamuel 703ca�RN��failed: 7044e867904c8295537803c1c8a076e130df5674b58mikesamuel if (transaction) 7054e867904c8295537803c1c8a076e130df5674b58mikesamuel SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); 7064e867904c8295537803c1c8a076e130df5674b58mikesamuel os_free(readers); 7074e867904c8295537803c1c8a076e130df5674b58mikesamuel scard_deinit(scard); 7084e867904c8295537803c1c8a076e130df5674b58mikesamuel return NULL; 7094e867904c8295537803c1c8a076e130df5674b58mikesamuel} 7104e867904c8295537803c1c8a076e130df5674b58mikesamuel 7114e867904c8295537803c1c8a076e130df5674b58mikesamuel 7124e867904c8295537803c1c8a076e130df5674b58mikesamuel/** 713O� * scard_set_pin - Set PIN (CHV1/PIN1) code for accessing SIM/USIM commands 7144e867904c8295537803c1c8a076e130df5674b58mikesamuel * @scard: Pointer to private data from scard_init() 715H�p��= �M�q�>ݝA�=�܃�d�$e * @pin: PIN code as an ASCII string (e.g., "1234") 7164e867904c8295537803c1c8a076e130df5674b58mikesamuel * Returns: 0 on success, -1 on failure 7174e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 7184e867904c8295537803c1c8a076e130df5674b58mikesamuelint scard_set_pin(struct scard_data *scard, const char *pin) 719r$���"H:�{ 7204e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard == NULL) 7214e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 7224e867904c8295537803c1c8a076e130df5674b58mikesamuel 7234e867904c8295537803c1c8a076e130df5674b58mikesamuel /* Verify whether CHV1 (PIN1) is needed to access the card. */ 7244e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->pin1_required) { 7254e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pin == NULL) { 7264e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "No PIN configured for SIM " 7274e867904c8295537803c1c8a076e130df5674b58mikesamuel "access"); 728e���� return -1; 729o��� } 7304e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_verify_pin(scard, pin)) { 7314e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_INFO, "PIN verification failed for " 7324e867904c8295537803c1c8a076e130df5674b58mikesamuel "SIM access"); 7334e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 734r�;?��Q�G��q��Â�i,�(=)��c } 7354e867904c8295537803c1c8a076e130df5674b58mikesamuel } 736Xv?oM��{*�����g 7374e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 738g�"����U�K�W�<} 739s�O/?���\;\���o�[����� 740vu?� �i�����ź�R�BGs�����#��vFr��CK�m�qJ}.k�*/��D�d�Mi[�,E;=��~�.)M���%e/$)MKj�� 7417��@�K/** 742H"V(� ~Vi���eҳBUW����Oʫ��_`����%{ * scard_deinit - Deinitialize SIM/USIM connection 7434e867904c8295537803c1c8a076e130df5674b58mikesamuel * @scard: Pointer to private data from scard_init() 7444e867904c8295537803c1c8a076e130df5674b58mikesamuel * 7454e867904c8295537803c1c8a076e130df5674b58mikesamuel * This function closes the SIM/USIM connect opened with scard_init(). 7464e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 7474e867904c8295537803c1c8a076e130df5674b58mikesamuelvoid scard_deinit(struct scard_data *scard) 7484e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 749aB�h��a��[鬷uv�LW����k�i�a�"���$�q long ret; 7504e867904c8295537803c1c8a076e130df5674b58mikesamuel 751nr��gF�rH� if (scard == NULL) 7524e867904c8295537803c1c8a076e130df5674b58mikesamuel return; 7534e867904c8295537803c1c8a076e130df5674b58mikesamuel 7544e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: deinitializing smart card interface"); 755ivQ if (scard->card) { 7564e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = SCardDisconnect(scard->card, SCARD_UNPOWER_CARD); 7574e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) { 7584e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Failed to disconnect " 7594e867904c8295537803c1c8a076e130df5674b58mikesamuel "smart card (err=%ld)", ret); 7604e867904c8295537803c1c8a076e130df5674b58mikesamuel } 7614e867904c8295537803c1c8a076e130df5674b58mikesamuel } 762tq��a)���'A 7634e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->ctx) { 764BIOd����`����?a ret = SCardReleaseContext(scard->ctx); 7652y7�Q}�&� if (ret != SCARD_S_SUCCESS) { 7664e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "Failed to release smart card " 767q0e��Ƴ��N�,N�X+k��D�e "context (err=%ld)", ret); 7684e867904c8295537803c1c8a076e130df5674b58mikesamuel } 7694e867904c8295537803c1c8a076e130df5674b58mikesamuel } 770o0��×�a��� os_free(scard); 7714e867904c8295537803c1c8a076e130df5674b58mikesamuel mingw_unload_symbols(); 7724e867904c8295537803c1c8a076e130df5674b58mikesamuel} 7734e867904c8295537803c1c8a076e130df5674b58mikesamuel 7744e867904c8295537803c1c8a076e130df5674b58mikesamuel 7754e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic long scard_transmit(struct scard_data *scard, 7764e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *_send, size_t send_len, 7774e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *_recv, size_t *recv_len) 778rQ#����=l�^#��B�V@�Ȧ{ 7794e867904c8295537803c1c8a076e130df5674b58mikesamuel long ret; 780Jr��#ifdef __APPLE__ 781EJ�W�LS�!Q����� uint32_t rlen; 7824e867904c8295537803c1c8a076e130df5674b58mikesamuel#else 7834e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned long rlen; 7844e867904c8295537803c1c8a076e130df5674b58mikesamuel#endif 7854e867904c8295537803c1c8a076e130df5674b58mikesamuel 7864e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send", 7874e867904c8295537803c1c8a076e130df5674b58mikesamuel _send, send_len); 7884e867904c8295537803c1c8a076e130df5674b58mikesamuel rlen = *recv_len; 7894e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = SCardTransmit(scard->card, 7904e867904c8295537803c1c8a076e130df5674b58mikesamuel scard->protocol == SCARD_PROTOCOL_T1 ? 7914e867904c8295537803c1c8a076e130df5674b58mikesamuel SCARD_PCI_T1 : SCARD_PCI_T0, 792X#�IɆM�)�`��\ _send, (unsigned long) send_len, 7934e867904c8295537803c1c8a076e130df5674b58mikesamuel NULL, _recv, &rlen); 794d� *recv_len = rlen; 795R�J� �{�l#J�!���'<�oA�� if (ret == SCARD_S_SUCCESS) { 7964e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: scard_transmit: recv", 7974e867904c8295537803c1c8a076e130df5674b58mikesamuel _recv, rlen); 7984e867904c8295537803c1c8a076e130df5674b58mikesamuel } else { 7994e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " 800Rj+��vHVOAv@��U�fX�n���iP����ٰI=Zԋ �^��~\�^ "(err=0x%lx)", ret); 8014e867904c8295537803c1c8a076e130df5674b58mikesamuel } 8024e867904c8295537803c1c8a076e130df5674b58mikesamuel return ret; 8034e867904c8295537803c1c8a076e130df5674b58mikesamuel} 8044e867904c8295537803c1c8a076e130df5674b58mikesamuel 8054e867904c8295537803c1c8a076e130df5674b58mikesamuel 8064e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int _scard_select_file(struct scard_data *scard, unsigned short file_id, 807dD+ �V� unsigned char *buf, size_t *buf_len, 8084e867904c8295537803c1c8a076e130df5674b58mikesamuel sim_types sim_type, unsigned char *aid, 8094e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t aidlen) 8104e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 8114e867904c8295537803c1c8a076e130df5674b58mikesamuel long ret; 8124e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char resp[3]; 8134e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char cmd[50] = { SIM_CMD_SELECT }; 814Ge�*� int cmdlen; 815Hj8�� ��<�եGt�`ij unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; 8164e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t len, rlen; 8174e867904c8295537803c1c8a076e130df5674b58mikesamuel 818L/� if (sim_type == SCARD_USIM) { 8194e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[0] = USIM_CLA; 8204e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[3] = 0x04; 821nB1o��Ǩ��+�QEz��H��"�D�ؙ�Ĺ��v+nbb�%Hc�Zz% get_resp[0] = USIM_CLA; 8224e867904c8295537803c1c8a076e130df5674b58mikesamuel } 8234e867904c8295537803c1c8a076e130df5674b58mikesamuel 8244e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: select file %04x", file_id); 825BkimˑV��J� if (aid) { 8264e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: select file by AID", 8274e867904c8295537803c1c8a076e130df5674b58mikesamuel aid, aidlen); 828A���p�F*u if (5 + aidlen > sizeof(cmd)) 829q��:�y���B���@e.(Wl return -1; 8302�UѴ��V��^&V�?�锈�HB�� cmd[2] = 0x04; /* Select by AID */ 8314e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[4] = aidlen; /* len */ 832I�͖�FK�(��r���D�xVT�J���ywFTWXN� os_memcpy(cmd + 5, aid, aidlen); 8334e867904c8295537803c1c8a076e130df5674b58mikesamuel cmdlen = 5 + aidlen; 8344e867904c8295537803c1c8a076e130df5674b58mikesamuel } else { 8354e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[5] = file_id >> 8; 8364e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[6] = file_id & 0xff; 8374e867904c8295537803c1c8a076e130df5674b58mikesamuel cmdlen = 7; 8384e867904c8295537803c1c8a076e130df5674b58mikesamuel } 8394e867904c8295537803c1c8a076e130df5674b58mikesamuel len = sizeof(resp); 8404e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, cmd, cmdlen, resp, &len); 8414e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) { 8424e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " 8434e867904c8295537803c1c8a076e130df5674b58mikesamuel "(err=0x%lx)", ret); 8444e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 8454e867904c8295537803c1c8a076e130df5674b58mikesamuel } 8464e867904c8295537803c1c8a076e130df5674b58mikesamuel 8474e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len != 2) { 8484e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: unexpected resp len " 8494e867904c8295537803c1c8a076e130df5674b58mikesamuel "%d (expected 2)", (int) len); 850kn��e�P.���b�;�N��Z���k$�L�s�� return -1; 851TXVLi���GP��#X� |q/J�}X } 8524e867904c8295537803c1c8a076e130df5674b58mikesamuel 8534e867904c8295537803c1c8a076e130df5674b58mikesamuel if (resp[0] == 0x98 && resp[1] == 0x04) { 8544e867904c8295537803c1c8a076e130df5674b58mikesamuel /* Security status not satisfied (PIN_WLAN) */ 8554e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: Security status not satisfied " 8564e867904c8295537803c1c8a076e130df5674b58mikesamuel "(PIN_WLAN)"); 8574e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 8584e867904c8295537803c1c8a076e130df5674b58mikesamuel } 8596nbAܞ&I���X���r���gJ�B��ݏ��= �D�<t��>}����� +!�b,����P�� 8604e867904c8295537803c1c8a076e130df5674b58mikesamuel if (resp[0] == 0x6e) { 8618<�s?p���������,�B�HY wpa_printf(MSG_DEBUG, "SCARD: used CLA not supported"); 8624e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 8634e867904c8295537803c1c8a076e130df5674b58mikesamuel } 8644e867904c8295537803c1c8a076e130df5674b58mikesamuel 8654e867904c8295537803c1c8a076e130df5674b58mikesamuel if (resp[0] != 0x6c && resp[0] != 0x9f && resp[0] != 0x61) { 8664e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: unexpected response 0x%02x " 867X�� "(expected 0x61, 0x6c, or 0x9f)", resp[0]); 8684e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 8694e867904c8295537803c1c8a076e130df5674b58mikesamuel } 8704e867904c8295537803c1c8a076e130df5674b58mikesamuel /* Normal ending of command; resp[1] bytes available */ 8714e867904c8295537803c1c8a076e130df5674b58mikesamuel get_resp[4] = resp[1]; 8724e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: trying to get response (%d bytes)", 8732NA� resp[1]); 8744e867904c8295537803c1c8a076e130df5674b58mikesamuel 8754e867904c8295537803c1c8a076e130df5674b58mikesamuel rlen = *buf_len; 8764e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &rlen); 8774e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret == SCARD_S_SUCCESS) { 8784e867904c8295537803c1c8a076e130df5674b58mikesamuel *buf_len = resp[1] < rlen ? resp[1] : rlen; 8794e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 8804e867904c8295537803c1c8a076e130df5674b58mikesamuel } 8814e867904c8295537803c1c8a076e130df5674b58mikesamuel 8824e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: SCardTransmit err=0x%lx\n", ret); 8834e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 8844e867904c8295537803c1c8a076e130df5674b58mikesamuel} 885w[��D�a� 8864e867904c8295537803c1c8a076e130df5674b58mikesamuel 887o�������]sU,�C"��-���jC��static int scard_select_file(struct scard_data *scard, unsigned short file_id, 8884e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *buf, size_t *buf_len) 8894e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 8904e867904c8295537803c1c8a076e130df5674b58mikesamuel return _scard_select_file(scard, file_id, buf, buf_len, 8914e867904c8295537803c1c8a076e130df5674b58mikesamuel scard->sim_type, NULL, 0); 892MUE�����q!} 8934e867904c8295537803c1c8a076e130df5674b58mikesamuel 8944����?��o��,��~�?��� !���F>��,�Ǒ����'b|��B>� 8954e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int scard_get_record_len(struct scard_data *scard, unsigned char recnum, 8964e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char mode) 897tF���Ң�T�̜TF~�{ 8984e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char buf[255]; 8994e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; 9004e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t blen; 9014e867904c8295537803c1c8a076e130df5674b58mikesamuel long ret; 902JН��z:o ��� 9034e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_USIM) 904s`Wy�]���ڵF cmd[0] = USIM_CLA; 9054e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[2] = recnum; 906XS�{����y�s�����&�~������^S>�}x����z蘗!.�f�p��� cmd[3] = mode; 9074e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[4] = sizeof(buf); 9084e867904c8295537803c1c8a076e130df5674b58mikesamuel 9094e867904c8295537803c1c8a076e130df5674b58mikesamuel blen = sizeof(buf); 9104e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); 9116��T�h-�.��y[d{Ñ if (ret != SCARD_S_SUCCESS) { 9124e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: failed to determine file " 9134e867904c8295537803c1c8a076e130df5674b58mikesamuel "length for record %d", recnum); 9140�i�-���Q�t[�*��Ӛ�bO��.��X��y�\` return -1; 915I��ڻq{��ۉ۰�Nw��_'q�-U>b��|�;〨� } 9164e867904c8295537803c1c8a076e130df5674b58mikesamuel 9174e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: file length determination response", 9184e867904c8295537803c1c8a076e130df5674b58mikesamuel buf, blen); 919B�K��✏Bu< 9204e867904c8295537803c1c8a076e130df5674b58mikesamuel if (blen < 2 || (buf[0] != 0x6c && buf[0] != 0x67)) { 9214e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: unexpected response to file " 9224e867904c8295537803c1c8a076e130df5674b58mikesamuel "length determination"); 9234e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 9244e867904c8295537803c1c8a076e130df5674b58mikesamuel } 925y���"pc.vBrF|�B.v =m�$]��"{x��˯t�{����l�vI� �%����<�}��������vH�!i���I 9264e867904c8295537803c1c8a076e130df5674b58mikesamuel return buf[1]; 9274e867904c8295537803c1c8a076e130df5674b58mikesamuel} 9284e867904c8295537803c1c8a076e130df5674b58mikesamuel 9294e867904c8295537803c1c8a076e130df5674b58mikesamuel 9304e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int scard_read_record(struct scard_data *scard, 9314e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *data, size_t len, 9324e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char recnum, unsigned char mode) 9334e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 9344e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; 9354e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t blen = len + 3; 936A���&�(�BOs�h�p�{h�Xp !� unsigned char *buf; 9374e867904c8295537803c1c8a076e130df5674b58mikesamuel long ret; 9384e867904c8295537803c1c8a076e130df5674b58mikesamuel 9394e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_USIM) 9404e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[0] = USIM_CLA; 9414e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[2] = recnum; 9424e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[3] = mode; 9434e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[4] = len; 9444e867904c8295537803c1c8a076e130df5674b58mikesamuel 9454e867904c8295537803c1c8a076e130df5674b58mikesamuel buf = os_malloc(blen); 9464e867904c8295537803c1c8a076e130df5674b58mikesamuel if (buf == NULL) 9474e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 9484e867904c8295537803c1c8a076e130df5674b58mikesamuel 9494e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); 9504e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) { 9514e867904c8295537803c1c8a076e130df5674b58mikesamuel os_free(buf); 9524e867904c8295537803c1c8a076e130df5674b58mikesamuel return -2; 953t�<�}�;�^]����d���z߷�CḰ�PK%�]�� PK } 9544e867904c8295537803c1c8a076e130df5674b58mikesamuel if (blen != len + 2) { 9554e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " 956m��ɰ���olɫ�i�z "length %ld (expected %ld)", 957e�D���~�w� (long) blen, (long) len + 2); 9584e867904c8295537803c1c8a076e130df5674b58mikesamuel os_free(buf); 9594e867904c8295537803c1c8a076e130df5674b58mikesamuel return -3; 9604e867904c8295537803c1c8a076e130df5674b58mikesamuel } 9614e867904c8295537803c1c8a076e130df5674b58mikesamuel 9624e867904c8295537803c1c8a076e130df5674b58mikesamuel if (buf[len] != 0x90 || buf[len + 1] != 0x00) { 9634e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " 9644e867904c8295537803c1c8a076e130df5674b58mikesamuel "status %02x %02x (expected 90 00)", 9654e867904c8295537803c1c8a076e130df5674b58mikesamuel buf[len], buf[len + 1]); 9664e867904c8295537803c1c8a076e130df5674b58mikesamuel os_free(buf); 9674e867904c8295537803c1c8a076e130df5674b58mikesamuel return -4; 9684e867904c8295537803c1c8a076e130df5674b58mikesamuel } 9694e867904c8295537803c1c8a076e130df5674b58mikesamuel 9704e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(data, buf, len); 9714e867904c8295537803c1c8a076e130df5674b58mikesamuel os_free(buf); 9724e867904c8295537803c1c8a076e130df5674b58mikesamuel 9734e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 9744e867904c8295537803c1c8a076e130df5674b58mikesamuel} 9754e867904c8295537803c1c8a076e130df5674b58mikesamuel 9764e867904c8295537803c1c8a076e130df5674b58mikesamuel 9774e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int scard_read_file(struct scard_data *scard, 9784e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *data, size_t len) 979tY� �x�Nds��gI�����iZ{ 9804e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char cmd[5] = { SIM_CMD_READ_BIN /* , len */ }; 981S�s��?� size_t blen = len + 3; 9824e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *buf; 9834e867904c8295537803c1c8a076e130df5674b58mikesamuel long ret; 9844e867904c8295537803c1c8a076e130df5674b58mikesamuel 9854e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[4] = len; 9864e867904c8295537803c1c8a076e130df5674b58mikesamuel 9874e867904c8295537803c1c8a076e130df5674b58mikesamuel buf = os_malloc(blen); 9884e867904c8295537803c1c8a076e130df5674b58mikesamuel if (buf == NULL) 9894e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 990_�H�K�Q����^������Q�xGq�vL�\�,�ϙU 991e�p���]}�ь�^>�\tT�j͜R� if (scard->sim_type == SCARD_USIM) 9924e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[0] = USIM_CLA; 9934e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); 9945��x��'��������q�I���:��e�e���� �ԨQ�_pڥ�C��q&�+:Vq���g��|h���bW���/������-�J{lΩz=�f��f̛�T��� ˴���Suê��r� if (ret != SCARD_S_SUCCESS) { 9954e867904c8295537803c1c8a076e130df5674b58mikesamuel os_free(buf); 996UGyꁠc}�+�c�����a<�+��=��# return -2; 9974e867904c8295537803c1c8a076e130df5674b58mikesamuel } 9984e867904c8295537803c1c8a076e130df5674b58mikesamuel if (blen != len + 2) { 9994e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " 10004e867904c8295537803c1c8a076e130df5674b58mikesamuel "length %ld (expected %ld)", 10014e867904c8295537803c1c8a076e130df5674b58mikesamuel (long) blen, (long) len + 2); 10024e867904c8295537803c1c8a076e130df5674b58mikesamuel os_free(buf); 10034e867904c8295537803c1c8a076e130df5674b58mikesamuel return -3; 10044e867904c8295537803c1c8a076e130df5674b58mikesamuel } 10054e867904c8295537803c1c8a076e130df5674b58mikesamuel 1006eG�ٽ"���}�r��< �e���|X�GdxT}Gfߕ�~Bh�Yy���� if (buf[len] != 0x90 || buf[len + 1] != 0x00) { 10074e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " 10084e867904c8295537803c1c8a076e130df5674b58mikesamuel "status %02x %02x (expected 90 00)", 10094e867904c8295537803c1c8a076e130df5674b58mikesamuel buf[len], buf[len + 1]); 1010qQ��� os_free(buf); 10114e867904c8295537803c1c8a076e130df5674b58mikesamuel return -4; 10124e867904c8295537803c1c8a076e130df5674b58mikesamuel } 10134e867904c8295537803c1c8a076e130df5674b58mikesamuel 10144e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(data, buf, len); 1015B#Re��CaJ���dGȽ>�Ÿ#P�q��aLU�� �g�E:X os_free(buf); 10164e867904c8295537803c1c8a076e130df5674b58mikesamuel 10174e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 10184e867904c8295537803c1c8a076e130df5674b58mikesamuel} 10194e867904c8295537803c1c8a076e130df5674b58mikesamuel 10204e867904c8295537803c1c8a076e130df5674b58mikesamuel 10214e867904c8295537803c1c8a076e130df5674b58mikesamuelstatic int scard_verify_pin(struct scard_data *scard, const char *pin) 10224P�T'=T#.U~ �*uu���a�b��uHS*a�{ 10234e867904c8295537803c1c8a076e130df5674b58mikesamuel long ret; 1024PK#� H\?' unsigned char resp[3]; 10254e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 }; 10264e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t len; 10274e867904c8295537803c1c8a076e130df5674b58mikesamuel 10284e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: verifying PIN"); 1029ui%���J��A"��N�y��@��s 10304e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pin == NULL || os_strlen(pin) > 8) 10314e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 1032j��O���lnr﴾�X 10334e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_USIM) 10344e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[0] = USIM_CLA; 10354e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(cmd + 5, pin, os_strlen(pin)); 1036Bf�X ��H����Ee����F]t���"풤�+�� os_memset(cmd + 5 + os_strlen(pin), 0xff, 8 - os_strlen(pin)); 10374e867904c8295537803c1c8a076e130df5674b58mikesamuel 10384e867904c8295537803c1c8a076e130df5674b58mikesamuel len = sizeof(resp); 10394e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); 1040IA�g�S@MԌ�<Ө�� if (ret != SCARD_S_SUCCESS) 1041l�]�T@_��稊v�ľ�^ return -2; 1042l%�(G��� 10434e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len != 2 || resp[0] != 0x90 || resp[1] != 0x00) { 1044p��@{��Q>�|#�F��OjA#' wpa_printf(MSG_WARNING, "SCARD: PIN verification failed"); 10454e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 10462c� �&S%�� �L�rF/ } 10474e867904c8295537803c1c8a076e130df5674b58mikesamuel 10484e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: PIN verified successfully"); 10494e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 1050ptU����} 1051D�i��W���HWqMz�U�I;�bBo� 10524e867904c8295537803c1c8a076e130df5674b58mikesamuel 1053n�P�int scard_get_pin_retry_counter(struct scard_data *scard) 10544e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 1055o[�����b��J�'h long ret; 1056hX�¼F��E����������汿 unsigned char resp[3]; 10574e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char cmd[5] = { SIM_CMD_VERIFY_CHV1 }; 1058a����\���XV��� size_t len; 10594e867904c8295537803c1c8a076e130df5674b58mikesamuel u16 val; 10604e867904c8295537803c1c8a076e130df5674b58mikesamuel 10614e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: fetching PIN retry counter"); 10624e867904c8295537803c1c8a076e130df5674b58mikesamuel 1063e��xx�v��zlH�Hy㥘S�l,��f���ɽ���?��*^�f������U� if (scard->sim_type == SCARD_USIM) 10644e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[0] = USIM_CLA; 10654e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[4] = 0; /* Empty data */ 10664e867904c8295537803c1c8a076e130df5674b58mikesamuel 10674e867904c8295537803c1c8a076e130df5674b58mikesamuel len = sizeof(resp); 10684e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); 10694e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) 10704e867904c8295537803c1c8a076e130df5674b58mikesamuel return -2; 10714e867904c8295537803c1c8a076e130df5674b58mikesamuel 1072H� if (len != 2) { 10734e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: failed to fetch PIN retry " 10744e867904c8295537803c1c8a076e130df5674b58mikesamuel "counter"); 10754e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 10764e867904c8295537803c1c8a076e130df5674b58mikesamuel } 10774e867904c8295537803c1c8a076e130df5674b58mikesamuel 10784e867904c8295537803c1c8a076e130df5674b58mikesamuel val = WPA_GET_BE16(resp); 1079gsO�q� if (val == 0x63c0 || val == 0x6983) { 1080ny�Ґ�V(B���[X�ֻKݳ iX��!|!}}�l��*�� wpa_printf(MSG_DEBUG, "SCARD: PIN has been blocked"); 10814e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 10824e867904c8295537803c1c8a076e130df5674b58mikesamuel } 10834e867904c8295537803c1c8a076e130df5674b58mikesamuel 10844e867904c8295537803c1c8a076e130df5674b58mikesamuel if (val >= 0x63c0 && val <= 0x63cf) 10854e867904c8295537803c1c8a076e130df5674b58mikesamuel return val & 0x000f; 10864e867904c8295537803c1c8a076e130df5674b58mikesamuel 10875f����D��l%�n�!ռ��C�ިC�V� wpa_printf(MSG_DEBUG, "SCARD: Unexpected PIN retry counter response " 10884e867904c8295537803c1c8a076e130df5674b58mikesamuel "value 0x%x", val); 10894e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 10904e867904c8295537803c1c8a076e130df5674b58mikesamuel} 10914e867904c8295537803c1c8a076e130df5674b58mikesamuel 10924e867904c8295537803c1c8a076e130df5674b58mikesamuel 10934e867904c8295537803c1c8a076e130df5674b58mikesamuel/** 10949��"�t�f��@�HTY�y * scard_get_imsi - Read IMSI from SIM/USIM card 10954e867904c8295537803c1c8a076e130df5674b58mikesamuel * @scard: Pointer to private data from scard_init() 10964e867904c8295537803c1c8a076e130df5674b58mikesamuel * @imsi: Buffer for IMSI 10974e867904c8295537803c1c8a076e130df5674b58mikesamuel * @len: Length of imsi buffer; set to IMSI length on success 10984e867904c8295537803c1c8a076e130df5674b58mikesamuel * Returns: 0 on success, -1 if IMSI file cannot be selected, -2 if IMSI file 10994e867904c8295537803c1c8a076e130df5674b58mikesamuel * selection returns invalid result code, -3 if parsing FSP template file fails 11004e867904c8295537803c1c8a076e130df5674b58mikesamuel * (USIM only), -4 if IMSI does not fit in the provided imsi buffer (len is set 1101N�o������R�I�P�wUIlP*T��j�R]]��� * to needed length), -5 if reading IMSI file fails. 11024e867904c8295537803c1c8a076e130df5674b58mikesamuel * 11034e867904c8295537803c1c8a076e130df5674b58mikesamuel * This function can be used to read IMSI from the SIM/USIM card. If the IMSI 11044e867904c8295537803c1c8a076e130df5674b58mikesamuel * file is PIN protected, scard_set_pin() must have been used to set the 11054e867904c8295537803c1c8a076e130df5674b58mikesamuel * correct PIN code before calling scard_get_imsi(). 11064e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 11074e867904c8295537803c1c8a076e130df5674b58mikesamuelint scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) 1108AV�J/䠗���Ja/�r��f���Т�<{ 11094e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char buf[100]; 11104e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t blen, imsilen, i; 11114e867904c8295537803c1c8a076e130df5674b58mikesamuel char *pos; 11124e867904c8295537803c1c8a076e130df5674b58mikesamuel 11134e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: reading IMSI from (GSM) EF-IMSI"); 11144e867904c8295537803c1c8a076e130df5674b58mikesamuel blen = sizeof(buf); 1115WD����F�����Ip����x�� if (scard_select_file(scard, SCARD_FILE_GSM_EF_IMSI, buf, &blen)) 11164e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 11174e867904c8295537803c1c8a076e130df5674b58mikesamuel if (blen < 4) { 11183Z$!�'Mq A��ac�>�,V=n������~� wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-IMSI " 11194e867904c8295537803c1c8a076e130df5674b58mikesamuel "header (len=%ld)", (long) blen); 11204e867904c8295537803c1c8a076e130df5674b58mikesamuel return -2; 11214e867904c8295537803c1c8a076e130df5674b58mikesamuel } 1122QDZ�˻Q��x����XS,㝐����a:�'�mh 11234e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_GSM_SIM) { 11244e867904c8295537803c1c8a076e130df5674b58mikesamuel blen = WPA_GET_BE16(&buf[2]); 11254e867904c8295537803c1c8a076e130df5674b58mikesamuel } else { 11264e867904c8295537803c1c8a076e130df5674b58mikesamuel int file_size; 11274e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) 11284e867904c8295537803c1c8a076e130df5674b58mikesamuel return -3; 1129sq�+�ۊ�!�s�G�.�AwI��Xg blen = file_size; 1130Xvs`�R�J� } 11314e867904c8295537803c1c8a076e130df5674b58mikesamuel if (blen < 2 || blen > sizeof(buf)) { 1132aI��� wpa_printf(MSG_DEBUG, "SCARD: invalid IMSI file length=%ld", 11334e867904c8295537803c1c8a076e130df5674b58mikesamuel (long) blen); 11344e867904c8295537803c1c8a076e130df5674b58mikesamuel return -3; 1135z�����v� } 11364e867904c8295537803c1c8a076e130df5674b58mikesamuel 1137x����b imsilen = (blen - 2) * 2 + 1; 11384e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%ld imsilen=%ld", 11394e867904c8295537803c1c8a076e130df5674b58mikesamuel (long) blen, (long) imsilen); 11404e867904c8295537803c1c8a076e130df5674b58mikesamuel if (blen < 2 || imsilen > *len) { 11414e867904c8295537803c1c8a076e130df5674b58mikesamuel *len = imsilen; 11424e867904c8295537803c1c8a076e130df5674b58mikesamuel return -4; 11434e867904c8295537803c1c8a076e130df5674b58mikesamuel } 11444e867904c8295537803c1c8a076e130df5674b58mikesamuel 11454e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_read_file(scard, buf, blen)) 1146sK��B�~mHk���&b\�!�� return -5; 1147b��^@)���JTP�"r�(Z 11484e867904c8295537803c1c8a076e130df5674b58mikesamuel pos = imsi; 11494e867904c8295537803c1c8a076e130df5674b58mikesamuel *pos++ = '0' + (buf[1] >> 4 & 0x0f); 11504e867904c8295537803c1c8a076e130df5674b58mikesamuel for (i = 2; i < blen; i++) { 11514e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char digit; 11524e867904c8295537803c1c8a076e130df5674b58mikesamuel 11534e867904c8295537803c1c8a076e130df5674b58mikesamuel digit = buf[i] & 0x0f; 11544e867904c8295537803c1c8a076e130df5674b58mikesamuel if (digit < 10) 11554e867904c8295537803c1c8a076e130df5674b58mikesamuel *pos++ = '0' + digit; 11564e867904c8295537803c1c8a076e130df5674b58mikesamuel else 11574e867904c8295537803c1c8a076e130df5674b58mikesamuel imsilen--; 11584e867904c8295537803c1c8a076e130df5674b58mikesamuel 11594e867904c8295537803c1c8a076e130df5674b58mikesamuel digit = buf[i] >> 4 & 0x0f; 11604e867904c8295537803c1c8a076e130df5674b58mikesamuel if (digit < 10) 11614e867904c8295537803c1c8a076e130df5674b58mikesamuel *pos++ = '0' + digit; 11624e867904c8295537803c1c8a076e130df5674b58mikesamuel else 11634e867904c8295537803c1c8a076e130df5674b58mikesamuel imsilen--; 11644e867904c8295537803c1c8a076e130df5674b58mikesamuel } 11654e867904c8295537803c1c8a076e130df5674b58mikesamuel *len = imsilen; 11664e867904c8295537803c1c8a076e130df5674b58mikesamuel 11674e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 11684e867904c8295537803c1c8a076e130df5674b58mikesamuel} 11694e867904c8295537803c1c8a076e130df5674b58mikesamuel 11704e867904c8295537803c1c8a076e130df5674b58mikesamuel 11714e867904c8295537803c1c8a076e130df5674b58mikesamuel/** 11724e867904c8295537803c1c8a076e130df5674b58mikesamuel * scard_get_mnc_len - Read length of MNC in the IMSI from SIM/USIM card 11736rf/R`�g��Uk����� * @scard: Pointer to private data from scard_init() 11744e867904c8295537803c1c8a076e130df5674b58mikesamuel * Returns: length (>0) on success, -1 if administrative data file cannot be 11754e867904c8295537803c1c8a076e130df5674b58mikesamuel * selected, -2 if administrative data file selection returns invalid result 11764e867904c8295537803c1c8a076e130df5674b58mikesamuel * code, -3 if parsing FSP template file fails (USIM only), -4 if length of 11774e867904c8295537803c1c8a076e130df5674b58mikesamuel * the file is unexpected, -5 if reading file fails, -6 if MNC length is not 11784e867904c8295537803c1c8a076e130df5674b58mikesamuel * in range (i.e. 2 or 3), -7 if MNC length is not available. 11794e867904c8295537803c1c8a076e130df5674b58mikesamuel * 11804e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 11814e867904c8295537803c1c8a076e130df5674b58mikesamuelint scard_get_mnc_len(struct scard_data *scard) 11823X��;�C��Ͳ$DL�Ȩ���/��Y���.�W�_${ 11834e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char buf[100]; 11844e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t blen; 1185pF4�`� �� int file_size; 11864e867904c8295537803c1c8a076e130df5674b58mikesamuel 11874e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: reading MNC len from (GSM) EF-AD"); 1188c���� blen = sizeof(buf); 11894e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_select_file(scard, SCARD_FILE_GSM_EF_AD, buf, &blen)) 11904e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 11914e867904c8295537803c1c8a076e130df5674b58mikesamuel if (blen < 4) { 11924e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-AD " 1193ZgMc�_ꢸ����=�ۊ��%}����Wz�� "header (len=%ld)", (long) blen); 11944e867904c8295537803c1c8a076e130df5674b58mikesamuel return -2; 11954e867904c8295537803c1c8a076e130df5674b58mikesamuel } 11964e867904c8295537803c1c8a076e130df5674b58mikesamuel 11974e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_GSM_SIM) { 11984e867904c8295537803c1c8a076e130df5674b58mikesamuel file_size = WPA_GET_BE16(&buf[2]); 11994e867904c8295537803c1c8a076e130df5674b58mikesamuel } else { 1200zp��Ea� if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) 12014e867904c8295537803c1c8a076e130df5674b58mikesamuel return -3; 1202E������X[kZ)Tj�P*��j�d�`H��N}�t���A�� } 12034e867904c8295537803c1c8a076e130df5674b58mikesamuel if (file_size == 3) { 12044e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: MNC length not available"); 12054e867904c8295537803c1c8a076e130df5674b58mikesamuel return -7; 12064e867904c8295537803c1c8a076e130df5674b58mikesamuel } 12074e867904c8295537803c1c8a076e130df5674b58mikesamuel if (file_size < 4 || file_size > (int) sizeof(buf)) { 12084e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: invalid file length=%ld", 12094e867904c8295537803c1c8a076e130df5674b58mikesamuel (long) file_size); 12104e867904c8295537803c1c8a076e130df5674b58mikesamuel return -4; 12114e867904c8295537803c1c8a076e130df5674b58mikesamuel } 12124e867904c8295537803c1c8a076e130df5674b58mikesamuel 12134e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard_read_file(scard, buf, file_size)) 1214Z"^���� return -5; 12154e867904c8295537803c1c8a076e130df5674b58mikesamuel buf[3] = buf[3] & 0x0f; /* upper nibble reserved for future use */ 1216_;�� }R���;��ݏ�sS if (buf[3] < 2 || buf[3] > 3) { 12174e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: invalid MNC length=%ld", 1218U�b/�{Q؇=�$��������P (long) buf[3]); 12194e867904c8295537803c1c8a076e130df5674b58mikesamuel return -6; 12204e867904c8295537803c1c8a076e130df5674b58mikesamuel } 12214e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: MNC length=%ld", (long) buf[3]); 1222F��� return buf[3]; 1223o�������"��%_�q�NB��S�E��} 12244e867904c8295537803c1c8a076e130df5674b58mikesamuel 12254e867904c8295537803c1c8a076e130df5674b58mikesamuel 12265N%=�dCM��ݵ���[Xƻ}&)v�/** 12274e867904c8295537803c1c8a076e130df5674b58mikesamuel * scard_gsm_auth - Run GSM authentication command on SIM card 12280�Q * @scard: Pointer to private data from scard_init() 12294e867904c8295537803c1c8a076e130df5674b58mikesamuel * @_rand: 16-byte RAND value from HLR/AuC 12304e867904c8295537803c1c8a076e130df5674b58mikesamuel * @sres: 4-byte buffer for SRES 12314e867904c8295537803c1c8a076e130df5674b58mikesamuel * @kc: 8-byte buffer for Kc 12320?�'vq. * Returns: 0 on success, -1 if SIM/USIM connection has not been initialized, 12334e867904c8295537803c1c8a076e130df5674b58mikesamuel * -2 if authentication command execution fails, -3 if unknown response code 12344e867904c8295537803c1c8a076e130df5674b58mikesamuel * for authentication command is received, -4 if reading of response fails, 12354e867904c8295537803c1c8a076e130df5674b58mikesamuel * -5 if if response data is of unexpected length 12364e867904c8295537803c1c8a076e130df5674b58mikesamuel * 1237R� * This function performs GSM authentication using SIM/USIM card and the 12384e867904c8295537803c1c8a076e130df5674b58mikesamuel * provided RAND value from HLR/AuC. If authentication command can be completed 12394e867904c8295537803c1c8a076e130df5674b58mikesamuel * successfully, SRES and Kc values will be written into sres and kc buffers. 12404e867904c8295537803c1c8a076e130df5674b58mikesamuel */ 12414e867904c8295537803c1c8a076e130df5674b58mikesamuelint scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, 12424e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *sres, unsigned char *kc) 12434e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 12444e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char cmd[5 + 1 + 16] = { SIM_CMD_RUN_GSM_ALG }; 12454e867904c8295537803c1c8a076e130df5674b58mikesamuel int cmdlen; 12464e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; 12474e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char resp[3], buf[12 + 3 + 2]; 12484e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t len; 1249a#m�Q�j�j, long ret; 12504e867904c8295537803c1c8a076e130df5674b58mikesamuel 1251v���ax�G��x�CPau~i��w�G�Q�m<�|nU if (scard == NULL) 12524e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 12534e867904c8295537803c1c8a076e130df5674b58mikesamuel 1254s6=j��l��+d�j� wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - RAND", _rand, 16); 1255v���� ��!�I� if (scard->sim_type == SCARD_GSM_SIM) { 12564e867904c8295537803c1c8a076e130df5674b58mikesamuel cmdlen = 5 + 16; 1257E�(p?Ey\ os_memcpy(cmd + 5, _rand, 16); 12584e867904c8295537803c1c8a076e130df5674b58mikesamuel } else { 1259_��<�/q�-�;&���$����p��<~�/�*ca��s�u�"��J~�p<�Ŋ cmdlen = 5 + 1 + 16; 12604e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[0] = USIM_CLA; 12614e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[3] = 0x80; 12624e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[4] = 17; 12634e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[5] = 16; 12644e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(cmd + 6, _rand, 16); 12654e867904c8295537803c1c8a076e130df5674b58mikesamuel get_resp[0] = USIM_CLA; 12664e867904c8295537803c1c8a076e130df5674b58mikesamuel } 12674e867904c8295537803c1c8a076e130df5674b58mikesamuel len = sizeof(resp); 12684e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, cmd, cmdlen, resp, &len); 12694e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) 12704e867904c8295537803c1c8a076e130df5674b58mikesamuel return -2; 12714e867904c8295537803c1c8a076e130df5674b58mikesamuel 12724e867904c8295537803c1c8a076e130df5674b58mikesamuel if ((scard->sim_type == SCARD_GSM_SIM && 12734e867904c8295537803c1c8a076e130df5674b58mikesamuel (len != 2 || resp[0] != 0x9f || resp[1] != 0x0c)) || 12744e867904c8295537803c1c8a076e130df5674b58mikesamuel (scard->sim_type == SCARD_USIM && 12754e867904c8295537803c1c8a076e130df5674b58mikesamuel (len != 2 || resp[0] != 0x61 || resp[1] != 0x0e))) { 12764e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: unexpected response for GSM " 12774e867904c8295537803c1c8a076e130df5674b58mikesamuel "auth request (len=%ld resp=%02x %02x)", 12784e867904c8295537803c1c8a076e130df5674b58mikesamuel (long) len, resp[0], resp[1]); 12794e867904c8295537803c1c8a076e130df5674b58mikesamuel return -3; 1280ckzm�#�/E��� } 12814e867904c8295537803c1c8a076e130df5674b58mikesamuel get_resp[4] = resp[1]; 12824e867904c8295537803c1c8a076e130df5674b58mikesamuel 12834e867904c8295537803c1c8a076e130df5674b58mikesamuel len = sizeof(buf); 1284E�r�q& ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); 12854e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS) 12863l � return -4; 12874e867904c8295537803c1c8a076e130df5674b58mikesamuel 1288cإ�SJ�cXv�g�{� if (scard->sim_type == SCARD_GSM_SIM) { 1289w�EC� if (len != 4 + 8 + 2) { 12904e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: unexpected data " 12914e867904c8295537803c1c8a076e130df5674b58mikesamuel "length for GSM auth (len=%ld, expected 14)", 12924e867904c8295537803c1c8a076e130df5674b58mikesamuel (long) len); 12934e867904c8295537803c1c8a076e130df5674b58mikesamuel return -5; 12944e867904c8295537803c1c8a076e130df5674b58mikesamuel } 1295EZ��p os_memcpy(sres, buf, 4); 1296D�n��� os_memcpy(kc, buf + 4, 8); 1297PK���� } else { 12984e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len != 1 + 4 + 1 + 8 + 2) { 12994e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: unexpected data " 13004e867904c8295537803c1c8a076e130df5674b58mikesamuel "length for USIM auth (len=%ld, " 13014e867904c8295537803c1c8a076e130df5674b58mikesamuel "expected 16)", (long) len); 13024e867904c8295537803c1c8a076e130df5674b58mikesamuel return -5; 13034e867904c8295537803c1c8a076e130df5674b58mikesamuel } 13044e867904c8295537803c1c8a076e130df5674b58mikesamuel if (buf[0] != 4 || buf[5] != 8) { 13054e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: unexpected SREC/Kc " 13064e867904c8295537803c1c8a076e130df5674b58mikesamuel "length (%d %d, expected 4 8)", 1307P�P���r�� �|��&�� ���ǎ� buf[0], buf[5]); 13088� Z�.�nqDy } 13094e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(sres, buf + 1, 4); 13104e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(kc, buf + 6, 8); 1311L�?�(�aң���(�o<� } 13127org/dom 13134e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - SRES", sres, 4); 13144e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - Kc", kc, 8); 13154e867904c8295537803c1c8a076e130df5674b58mikesamuel 13164e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 13174e867904c8295537803c1c8a076e130df5674b58mikesamuel} 1318A�/Cx��w����xK>�F�V��.���vB�|�c�����_ 13194e867904c8295537803c1c8a076e130df5674b58mikesamuel 13204e867904c8295537803c1c8a076e130df5674b58mikesamuel/** 13214e867904c8295537803c1c8a076e130df5674b58mikesamuel * scard_umts_auth - Run UMTS authentication command on USIM card 13224e867904c8295537803c1c8a076e130df5674b58mikesamuel * @scard: Pointer to private data from scard_init() 1323J%K��j����o�gE�(��xwb����H`T�J��=�$gfT * @_rand: 16-byte RAND value from HLR/AuC 1324YI * @autn: 16-byte AUTN value from HLR/AuC 1325BV�.Y�M�s���j�W�٬Xo&�va * @res: 16-byte buffer for RES 13264e867904c8295537803c1c8a076e130df5674b58mikesamuel * @res_len: Variable that will be set to RES length 13274e867904c8295537803c1c8a076e130df5674b58mikesamuel * @ik: 16-byte buffer for IK 13284e867904c8295537803c1c8a076e130df5674b58mikesamuel * @ck: 16-byte buffer for CK 13294e867904c8295537803c1c8a076e130df5674b58mikesamuel * @auts: 14-byte buffer for AUTS 13304e867904c8295537803c1c8a076e130df5674b58mikesamuel * Returns: 0 on success, -1 on failure, or -2 if USIM reports synchronization 13314e867904c8295537803c1c8a076e130df5674b58mikesamuel * failure 13324e867904c8295537803c1c8a076e130df5674b58mikesamuel * 13334e867904c8295537803c1c8a076e130df5674b58mikesamuel * This function performs AKA authentication using USIM card and the provided 13344e867904c8295537803c1c8a076e130df5674b58mikesamuel * RAND and AUTN values from HLR/AuC. If authentication command can be 13354e867904c8295537803c1c8a076e130df5674b58mikesamuel * completed successfully, RES, IK, and CK values will be written into provided 13364e867904c8295537803c1c8a076e130df5674b58mikesamuel * buffers and res_len is set to length of received RES value. If USIM reports 13374e867904c8295537803c1c8a076e130df5674b58mikesamuel * synchronization failure, the received AUTS value will be written into auts 1338lE�Q�� * buffer. In this case, RES, IK, and CK are not valid. 1339xT�>���M��[ */ 13404e867904c8295537803c1c8a076e130df5674b58mikesamuelint scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, 13414e867904c8295537803c1c8a076e130df5674b58mikesamuel const unsigned char *autn, 13424e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *res, size_t *res_len, 13434e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char *ik, unsigned char *ck, unsigned char *auts) 13444e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 13454e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char cmd[5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN] = 1346c�J�T/h�<ːa��*���t���'�������R�� { USIM_CMD_RUN_UMTS_ALG }; 1347H7��Ƥ�u Yώg�={�?~~��F� U�����d�o������ �/ʝ �۽`���n{|@�}^w}Wl unsigned char get_resp[5] = { USIM_CMD_GET_RESPONSE }; 13484e867904c8295537803c1c8a076e130df5674b58mikesamuel unsigned char resp[3], buf[64], *pos, *end; 13494e867904c8295537803c1c8a076e130df5674b58mikesamuel size_t len; 13504e867904c8295537803c1c8a076e130df5674b58mikesamuel long ret; 13514e867904c8295537803c1c8a076e130df5674b58mikesamuel 13524e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard == NULL) 13534e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 13544e867904c8295537803c1c8a076e130df5674b58mikesamuel 13554e867904c8295537803c1c8a076e130df5674b58mikesamuel if (scard->sim_type == SCARD_GSM_SIM) { 13564e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_ERROR, "SCARD: Non-USIM card - cannot do UMTS " 13574e867904c8295537803c1c8a076e130df5674b58mikesamuel "auth"); 13584e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 13594e867904c8295537803c1c8a076e130df5674b58mikesamuel } 13604e867904c8295537803c1c8a076e130df5674b58mikesamuel 13614e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - RAND", _rand, AKA_RAND_LEN); 13627��%-PK�S�K - PK wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - AUTN", autn, AKA_AUTN_LEN); 1363nF� cmd[5] = AKA_RAND_LEN; 1364Z��ln�'P>V��w�iv�D����o�q�ܳސB��_ os_memcpy(cmd + 6, _rand, AKA_RAND_LEN); 13654e867904c8295537803c1c8a076e130df5674b58mikesamuel cmd[6 + AKA_RAND_LEN] = AKA_AUTN_LEN; 13664e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(cmd + 6 + AKA_RAND_LEN + 1, autn, AKA_AUTN_LEN); 13674e867904c8295537803c1c8a076e130df5674b58mikesamuel 1368A�Ñű��g�ۼꍯ��ϰ.S� len = sizeof(resp); 13694e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); 1370RaV��`]��TH,y*��,Z�\K��It�'���Lb�It!�D?O[��.��H�oJ;��کիU�#p��(YЬT����@�{)�q� if (ret != SCARD_S_SUCCESS) 13712qoi`j��� �+�y:���� L return -1; 13724e867904c8295537803c1c8a076e130df5674b58mikesamuel 13734e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len <= sizeof(resp)) 13744e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: UMTS alg response", resp, len); 1375MO� 13764e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len == 2 && resp[0] == 0x98 && resp[1] == 0x62) { 13774e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: UMTS auth failed - " 13784e867904c8295537803c1c8a076e130df5674b58mikesamuel "MAC != XMAC"); 1379D�� return -1; 13804nɰ��� } else if (len != 2 || resp[0] != 0x61) { 13814e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_WARNING, "SCARD: unexpected response for UMTS " 13824e867904c8295537803c1c8a076e130df5674b58mikesamuel "auth request (len=%ld resp=%02x %02x)", 13834e867904c8295537803c1c8a076e130df5674b58mikesamuel (long) len, resp[0], resp[1]); 13844e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 1385i�% } 13864e867904c8295537803c1c8a076e130df5674b58mikesamuel get_resp[4] = resp[1]; 13874e867904c8295537803c1c8a076e130df5674b58mikesamuel 1388jH�~bֱh�F��� len = sizeof(buf); 13894e867904c8295537803c1c8a076e130df5674b58mikesamuel ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); 13904e867904c8295537803c1c8a076e130df5674b58mikesamuel if (ret != SCARD_S_SUCCESS || len > sizeof(buf)) 13914e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 13924e867904c8295537803c1c8a076e130df5674b58mikesamuel 1393t[Ӊ���i wpa_hexdump(MSG_DEBUG, "SCARD: UMTS get response result", buf, len); 13944e867904c8295537803c1c8a076e130df5674b58mikesamuel if (len >= 2 + AKA_AUTS_LEN && buf[0] == 0xdc && 13954e867904c8295537803c1c8a076e130df5674b58mikesamuel buf[1] == AKA_AUTS_LEN) { 1396R��:�Q�����tz����p>��S�K�bA׳b\ Pc{�)A��c r��\D�#T wpa_printf(MSG_DEBUG, "SCARD: UMTS Synchronization-Failure"); 13974e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(auts, buf + 2, AKA_AUTS_LEN); 13984e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: AUTS", auts, AKA_AUTS_LEN); 13994e867904c8295537803c1c8a076e130df5674b58mikesamuel return -2; 14004e867904c8295537803c1c8a076e130df5674b58mikesamuel } else if (len >= 6 + IK_LEN + CK_LEN && buf[0] == 0xdb) { 14014e867904c8295537803c1c8a076e130df5674b58mikesamuel pos = buf + 1; 14024e867904c8295537803c1c8a076e130df5674b58mikesamuel end = buf + len; 14034e867904c8295537803c1c8a076e130df5674b58mikesamuel 14044e867904c8295537803c1c8a076e130df5674b58mikesamuel /* RES */ 14054e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pos[0] > RES_MAX_LEN || pos[0] > end - pos) { 14064e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Invalid RES"); 14074e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 14084e867904c8295537803c1c8a076e130df5674b58mikesamuel } 14094e867904c8295537803c1c8a076e130df5674b58mikesamuel *res_len = *pos++; 14104e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(res, pos, *res_len); 14114e867904c8295537803c1c8a076e130df5674b58mikesamuel pos += *res_len; 14124e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: RES", res, *res_len); 1413xwTc��L] 14144e867904c8295537803c1c8a076e130df5674b58mikesamuel /* CK */ 14154e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pos[0] != CK_LEN || CK_LEN > end - pos) { 14164e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Invalid CK"); 14174e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 14184e867904c8295537803c1c8a076e130df5674b58mikesamuel } 14194e867904c8295537803c1c8a076e130df5674b58mikesamuel pos++; 14204e867904c8295537803c1c8a076e130df5674b58mikesamuel os_memcpy(ck, pos, CK_LEN); 1421J��(�b�cd�F\|����H�-h pos += CK_LEN; 14224e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: CK", ck, CK_LEN); 14234e867904c8295537803c1c8a076e130df5674b58mikesamuel 14244e867904c8295537803c1c8a076e130df5674b58mikesamuel /* IK */ 14254e867904c8295537803c1c8a076e130df5674b58mikesamuel if (pos[0] != IK_LEN || IK_LEN > end - pos) { 14264e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Invalid IK"); 1427mG��=�C�uOAʑ���>����� return -1; 14284e867904c8295537803c1c8a076e130df5674b58mikesamuel } 14294e867904c8295537803c1c8a076e130df5674b58mikesamuel pos++; 14308�Y��⣠�a� Vi��ʚ� os_memcpy(ik, pos, IK_LEN); 14314e867904c8295537803c1c8a076e130df5674b58mikesamuel pos += IK_LEN; 14324e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_hexdump(MSG_DEBUG, "SCARD: IK", ik, IK_LEN); 1433E�D̏��.Wo��k:ًFǑ:ϊvz*�jK�Aؗ��a�*�Î�#�:�*J�"]� 1434riW`�}�\м��� �+ if (end > pos) { 1435n���rIhT�Zut�� wpa_hexdump(MSG_DEBUG, 14364e867904c8295537803c1c8a076e130df5674b58mikesamuel "SCARD: Ignore extra data in end", 14374e867904c8295537803c1c8a076e130df5674b58mikesamuel pos, end - pos); 14384e867904c8295537803c1c8a076e130df5674b58mikesamuel } 14394e867904c8295537803c1c8a076e130df5674b58mikesamuel 14404e867904c8295537803c1c8a076e130df5674b58mikesamuel return 0; 14416iH�QF�x �-[��x�(b��<�j ��㮎���<o'FF���b�F��H(s�C��/�C��y͐k���#=+]��I } 14424e867904c8295537803c1c8a076e130df5674b58mikesamuel 14434e867904c8295537803c1c8a076e130df5674b58mikesamuel wpa_printf(MSG_DEBUG, "SCARD: Unrecognized response"); 14444e867904c8295537803c1c8a076e130df5674b58mikesamuel return -1; 14455A���ح��} 14464e867904c8295537803c1c8a076e130df5674b58mikesamuel 14474e867904c8295537803c1c8a076e130df5674b58mikesamuel 1448y�:�ά�b�/wu�%�X�l/�;�p`��ɕ.rq)kEb��int scard_supports_umts(struct scard_data *scard) 14494e867904c8295537803c1c8a076e130df5674b58mikesamuel{ 14504e867904c8295537803c1c8a076e130df5674b58mikesamuel return scard->sim_type == SCARD_USIM; 14514e867904c8295537803c1c8a076e130df5674b58mikesamuel} 1452cRk*<�)�^�cZ��L�