?? pcsc_funcs.c
字號:
/* * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file implements wrapper functions for accessing GSM SIM and 3GPP USIM * cards through PC/SC smartcard library. These functions are used to implement * authentication routines for EAP-SIM and EAP-AKA. */#include "includes.h"#include <winscard.h>#include "common.h"#include "pcsc_funcs.h"/* See ETSI GSM 11.11 and ETSI TS 102 221 for details. * SIM commands: * Command APDU: CLA INS P1 P2 P3 Data * CLA (class of instruction): A0 for GSM, 00 for USIM * INS (instruction) * P1 P2 P3 (parameters, P3 = length of Data) * Response APDU: Data SW1 SW2 * SW1 SW2 (Status words) * Commands (INS P1 P2 P3): * SELECT: A4 00 00 02 <file_id, 2 bytes> * GET RESPONSE: C0 00 00 <len> * RUN GSM ALG: 88 00 00 00 <RAND len = 10> * RUN UMTS ALG: 88 00 81 <len=0x22> data: 0x10 | RAND | 0x10 | AUTN * P1 = ID of alg in card * P2 = ID of secret key * READ BINARY: B0 <offset high> <offset low> <len> * READ RECORD: B2 <record number> <mode> <len> * P2 (mode) = '02' (next record), '03' (previous record), * '04' (absolute mode) * VERIFY CHV: 20 00 <CHV number> 08 * CHANGE CHV: 24 00 <CHV number> 10 * DISABLE CHV: 26 00 01 08 * ENABLE CHV: 28 00 01 08 * UNBLOCK CHV: 2C 00 <00=CHV1, 02=CHV2> 10 * SLEEP: FA 00 00 00 *//* GSM SIM commands */#define SIM_CMD_SELECT 0xa0, 0xa4, 0x00, 0x00, 0x02#define SIM_CMD_RUN_GSM_ALG 0xa0, 0x88, 0x00, 0x00, 0x10#define SIM_CMD_GET_RESPONSE 0xa0, 0xc0, 0x00, 0x00#define SIM_CMD_READ_BIN 0xa0, 0xb0, 0x00, 0x00#define SIM_CMD_READ_RECORD 0xa0, 0xb2, 0x00, 0x00#define SIM_CMD_VERIFY_CHV1 0xa0, 0x20, 0x00, 0x01, 0x08/* USIM commands */#define USIM_CLA 0x00#define USIM_CMD_RUN_UMTS_ALG 0x00, 0x88, 0x00, 0x81, 0x22#define USIM_CMD_GET_RESPONSE 0x00, 0xc0, 0x00, 0x00#define SIM_RECORD_MODE_ABSOLUTE 0x04#define USIM_FSP_TEMPL_TAG 0x62#define USIM_TLV_FILE_DESC 0x82#define USIM_TLV_FILE_ID 0x83#define USIM_TLV_DF_NAME 0x84#define USIM_TLV_PROPR_INFO 0xA5#define USIM_TLV_LIFE_CYCLE_STATUS 0x8A#define USIM_TLV_FILE_SIZE 0x80#define USIM_TLV_TOTAL_FILE_SIZE 0x81#define USIM_TLV_PIN_STATUS_TEMPLATE 0xC6#define USIM_TLV_SHORT_FILE_ID 0x88#define USIM_PS_DO_TAG 0x90#define AKA_RAND_LEN 16#define AKA_AUTN_LEN 16#define AKA_AUTS_LEN 14#define RES_MAX_LEN 16#define IK_LEN 16#define CK_LEN 16typedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types;struct scard_data { SCARDCONTEXT ctx; SCARDHANDLE card; DWORD protocol; sim_types sim_type; int pin1_required;};#ifdef __MINGW32_VERSION/* MinGW does not yet support WinScard, so load the needed functions * dynamically from winscard.dll for now. */static HINSTANCE dll = NULL; /* winscard.dll */static const SCARD_IO_REQUEST *dll_g_rgSCardT0Pci, *dll_g_rgSCardT1Pci;#undef SCARD_PCI_T0#define SCARD_PCI_T0 (dll_g_rgSCardT0Pci)#undef SCARD_PCI_T1#define SCARD_PCI_T1 (dll_g_rgSCardT1Pci)static WINSCARDAPI LONG WINAPI(*dll_SCardEstablishContext)(IN DWORD dwScope, IN LPCVOID pvReserved1, IN LPCVOID pvReserved2, OUT LPSCARDCONTEXT phContext);#define SCardEstablishContext dll_SCardEstablishContextstatic long (*dll_SCardReleaseContext)(long hContext);#define SCardReleaseContext dll_SCardReleaseContextstatic WINSCARDAPI LONG WINAPI(*dll_SCardListReadersA)(IN SCARDCONTEXT hContext, IN LPCSTR mszGroups, OUT LPSTR mszReaders, IN OUT LPDWORD pcchReaders);#undef SCardListReaders#define SCardListReaders dll_SCardListReadersAstatic WINSCARDAPI LONG WINAPI(*dll_SCardConnectA)(IN SCARDCONTEXT hContext, IN LPCSTR szReader, IN DWORD dwShareMode, IN DWORD dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT LPDWORD pdwActiveProtocol);#undef SCardConnect#define SCardConnect dll_SCardConnectAstatic WINSCARDAPI LONG WINAPI(*dll_SCardDisconnect)(IN SCARDHANDLE hCard, IN DWORD dwDisposition);#define SCardDisconnect dll_SCardDisconnectstatic WINSCARDAPI LONG WINAPI(*dll_SCardTransmit)(IN SCARDHANDLE hCard, IN LPCSCARD_IO_REQUEST pioSendPci, IN LPCBYTE pbSendBuffer, IN DWORD cbSendLength, IN OUT LPSCARD_IO_REQUEST pioRecvPci, OUT LPBYTE pbRecvBuffer, IN OUT LPDWORD pcbRecvLength);#define SCardTransmit dll_SCardTransmitstatic WINSCARDAPI LONG WINAPI(*dll_SCardBeginTransaction)(IN SCARDHANDLE hCard);#define SCardBeginTransaction dll_SCardBeginTransactionstatic WINSCARDAPI LONG WINAPI(*dll_SCardEndTransaction)(IN SCARDHANDLE hCard, IN DWORD dwDisposition);#define SCardEndTransaction dll_SCardEndTransactionstatic int mingw_load_symbols(void){ char *sym; if (dll) return 0; dll = LoadLibrary("winscard"); if (dll == NULL) { wpa_printf(MSG_DEBUG, "WinSCard: Could not load winscard.dll " "library"); return -1; }#define LOADSYM(s) \ sym = #s; \ dll_ ## s = (void *) GetProcAddress(dll, sym); \ if (dll_ ## s == NULL) \ goto fail; LOADSYM(SCardEstablishContext); LOADSYM(SCardReleaseContext); LOADSYM(SCardListReadersA); LOADSYM(SCardConnectA); LOADSYM(SCardDisconnect); LOADSYM(SCardTransmit); LOADSYM(SCardBeginTransaction); LOADSYM(SCardEndTransaction); LOADSYM(g_rgSCardT0Pci); LOADSYM(g_rgSCardT1Pci);#undef LOADSYM return 0;fail: wpa_printf(MSG_DEBUG, "WinSCard: Could not get address for %s from " "winscard.dll", sym); FreeLibrary(dll); dll = NULL; return -1;}static void mingw_unload_symbols(void){ if (dll == NULL) return; FreeLibrary(dll); dll = NULL;}#else /* __MINGW32_VERSION */#define mingw_load_symbols() 0#define mingw_unload_symbols() do { } while (0)#endif /* __MINGW32_VERSION */static int _scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len, sim_types sim_type, unsigned char *aid, size_t aidlen);static int scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len);static int scard_verify_pin(struct scard_data *scard, const char *pin);static int scard_get_record_len(struct scard_data *scard, unsigned char recnum, unsigned char mode);static int scard_read_record(struct scard_data *scard, unsigned char *data, size_t len, unsigned char recnum, unsigned char mode);static int scard_parse_fsp_templ(unsigned char *buf, size_t buf_len, int *ps_do, int *file_len){ unsigned char *pos, *end; if (ps_do) *ps_do = -1; if (file_len) *file_len = -1; pos = buf; end = pos + buf_len; if (*pos != USIM_FSP_TEMPL_TAG) { wpa_printf(MSG_DEBUG, "SCARD: file header did not " "start with FSP template tag"); return -1; } pos++; if (pos >= end) return -1; if ((pos + pos[0]) < end) end = pos + 1 + pos[0]; pos++; wpa_hexdump(MSG_DEBUG, "SCARD: file header FSP template", pos, end - pos); while (pos + 1 < end) { wpa_printf(MSG_MSGDUMP, "SCARD: file header TLV " "0x%02x len=%d", pos[0], pos[1]); if (pos + 2 + pos[1] > end) break; if (pos[0] == USIM_TLV_FILE_SIZE && (pos[1] == 1 || pos[1] == 2) && file_len) { if (pos[1] == 1) *file_len = (int) pos[2]; else *file_len = ((int) pos[2] << 8) | (int) pos[3]; wpa_printf(MSG_DEBUG, "SCARD: file_size=%d", *file_len); } if (pos[0] == USIM_TLV_PIN_STATUS_TEMPLATE && pos[1] >= 2 && pos[2] == USIM_PS_DO_TAG && pos[3] >= 1 && ps_do) { wpa_printf(MSG_DEBUG, "SCARD: PS_DO=0x%02x", pos[4]); *ps_do = (int) pos[4]; } pos += 2 + pos[1]; if (pos == end) return 0; } return -1;}static int scard_pin_needed(struct scard_data *scard, unsigned char *hdr, size_t hlen){ if (scard->sim_type == SCARD_GSM_SIM) { if (hlen > SCARD_CHV1_OFFSET && !(hdr[SCARD_CHV1_OFFSET] & SCARD_CHV1_FLAG)) return 1; return 0; } if (scard->sim_type == SCARD_USIM) { int ps_do; if (scard_parse_fsp_templ(hdr, hlen, &ps_do, NULL)) return -1; /* TODO: there could be more than one PS_DO entry because of * multiple PINs in key reference.. */ if (ps_do > 0 && (ps_do & 0x80)) return 1; return 0; } return -1;}static int scard_get_aid(struct scard_data *scard, unsigned char *aid, size_t maxlen){ int rlen, rec; struct efdir { unsigned char appl_template_tag; /* 0x61 */ unsigned char appl_template_len; unsigned char appl_id_tag; /* 0x4f */ unsigned char aid_len; unsigned char rid[5]; unsigned char appl_code[2]; /* 0x1002 for 3G USIM */ } *efdir; unsigned char buf[100]; size_t blen; efdir = (struct efdir *) buf; blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_EF_DIR, buf, &blen)) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read EF_DIR"); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR select", buf, blen); for (rec = 1; rec < 10; rec++) { rlen = scard_get_record_len(scard, rec, SIM_RECORD_MODE_ABSOLUTE); if (rlen < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to get EF_DIR " "record length"); return -1; } blen = sizeof(buf); if (rlen > (int) blen) { wpa_printf(MSG_DEBUG, "SCARD: Too long EF_DIR record"); return -1; } if (scard_read_record(scard, buf, rlen, rec, SIM_RECORD_MODE_ABSOLUTE) < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read " "EF_DIR record %d", rec); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR record", buf, rlen); if (efdir->appl_template_tag != 0x61) { wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " "template tag 0x%x", efdir->appl_template_tag); continue; } if (efdir->appl_template_len > rlen - 2) { wpa_printf(MSG_DEBUG, "SCARD: Too long application " "template (len=%d rlen=%d)", efdir->appl_template_len, rlen); continue; } if (efdir->appl_id_tag != 0x4f) { wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " "identifier tag 0x%x", efdir->appl_id_tag); continue; } if (efdir->aid_len < 1 || efdir->aid_len > 16) { wpa_printf(MSG_DEBUG, "SCARD: Invalid AID length %d", efdir->aid_len); continue; } wpa_hexdump(MSG_DEBUG, "SCARD: AID from EF_DIR record", efdir->rid, efdir->aid_len); if (efdir->appl_code[0] == 0x10 && efdir->appl_code[1] == 0x02) { wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app found from " "EF_DIR record %d", rec); break; } } if (rec >= 10) { wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app not found " "from EF_DIR records"); return -1; } if (efdir->aid_len > maxlen) { wpa_printf(MSG_DEBUG, "SCARD: Too long AID");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -