From 3cddd24df26085682c819a3c8e9e3ce21a2872da Mon Sep 17 00:00:00 2001 From: kavsrf Date: Mon, 27 Mar 2017 16:01:33 +0300 Subject: smart card tests via DcsCfg --- Library/CommonLib/EfiConsole.c | 124 +++++++++++++++++++++++++++++++++++++++-- Library/CommonLib/EfiUsb.c | 60 ++++++++++++++++++++ 2 files changed, 180 insertions(+), 4 deletions(-) (limited to 'Library') diff --git a/Library/CommonLib/EfiConsole.c b/Library/CommonLib/EfiConsole.c index 3ab1515..0d94235 100644 --- a/Library/CommonLib/EfiConsole.c +++ b/Library/CommonLib/EfiConsole.c @@ -2,7 +2,7 @@ EFI console helpers routines/wrappers Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov, Alex Kolotnikov -Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI This program and the accompanying materials are licensed and made available under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). @@ -27,15 +27,51 @@ UINTN gCELine = 0; VOID PrintBytes( - IN UINT8* Data, - IN UINT32 Size) + IN UINT8* Data, + IN UINTN Size) +{ + UINTN i; + for (i = 0; i < Size; ++i) { + UINTN val = Data[i]; + OUT_PRINT(L"%02X", val); + } +} + +/* +#define DUMP_MAX_LINE_LEN 1024 +typedef struct _DUMP_STATE { + CHAR8 line[DUMP_MAX_LINE_LEN]; + +} DUMP_STATE; + +VOID +DumpBytes( + IN UINT8* Data, + IN UINT32 Size) { UINT32 i; + CHAR8 text[17]; + UINTN addr = 0; for (i = 0; i < Size; ++i) { + if ((addr & 0x0F) == 0) { + SetMem(text, sizeof(text) - 1, ' '); + text[16] = 0; + OUT_PRINT(L"%08X: ", addr); + } UINT32 val = Data[i]; - OUT_PRINT(L"%02X", val); + OUT_PRINT(L"%02X ", val); + if (val > 31 && val < 127) { + text[i & 0x0F] = (CHAR8)(val & 0x0FF); + } + addr++; + if ((addr & 0x0F) == 0) { + OUT_PRINT(L"|%a|", text); + } + } + if (addr & 0x0F) != 0) { } } +*/ ////////////////////////////////////////////////////////////////////////// // Input @@ -353,6 +389,86 @@ AsciiStrToGuid( return res; } +BOOLEAN +AsciiHexToBytes( + OUT UINT8 *b, + IN UINTN *bytesLen, + IN CHAR8 *str + ) +{ + UINT8 low = 0; + UINT8 high = 0; + BOOLEAN res = TRUE; + UINTN cnt = 0; + UINTN len = 0; + CHAR8 *pos = str; + if (b == NULL || str == NULL || bytesLen == NULL) return FALSE; + if (*bytesLen == 0) return TRUE; + len = AsciiStrLen(str); + if (len == 0) return TRUE; + if (len > 2 && str[0] == '0' && str[1] == 'x') { + pos += 2; + } + if ((len & 1) == 0) { + res = AsciiHexToDigit(&high, pos++); + } + res = res && AsciiHexToDigit(&low, pos++); + *b = low | high << 4; + b++; + cnt++; + while (res && (cnt < *bytesLen) && (*pos != 0)) { + res = AsciiHexToDigit(&high, pos++); + res = res && AsciiHexToDigit(&low, pos++); + *b = low | high << 4; + b++; + cnt++; + } + *bytesLen = cnt; + return res; +} + +BOOLEAN +StrHexToBytes( + OUT UINT8 *b, + IN UINTN *bytesLen, + IN CHAR16 *str + ) +{ + UINT8 low = 0; + UINT8 high = 0; + BOOLEAN res = TRUE; + UINTN cnt = 0; + UINTN len = 0; + CHAR16 *pos = str; + if (b == NULL || str == NULL || bytesLen == NULL) return FALSE; + if (*bytesLen == 0) return TRUE; + len = StrLen(str); + if (len == 0) return TRUE; + if (len > 2 && str[0] == '0' && str[1] == 'x') { + pos += 2; + } + if ((len & 1) == 0) { + res = AsciiHexToDigit(&high, (CHAR8*)pos); + pos++; + } + res = res && AsciiHexToDigit(&low, (CHAR8*)pos); + pos++; + *b = low | high << 4; + b++; + cnt++; + while (res && (cnt < *bytesLen) && (*pos != 0)) { + res = AsciiHexToDigit(&high, (CHAR8*)pos); + pos++; + res = res && AsciiHexToDigit(&low, (CHAR8*)pos); + pos++; + *b = low | high << 4; + b++; + cnt++; + } + *bytesLen = cnt; + return res; +} + ////////////////////////////////////////////////////////////////////////// // Console menu ////////////////////////////////////////////////////////////////////////// diff --git a/Library/CommonLib/EfiUsb.c b/Library/CommonLib/EfiUsb.c index b5bdac5..f885cc6 100644 --- a/Library/CommonLib/EfiUsb.c +++ b/Library/CommonLib/EfiUsb.c @@ -16,9 +16,11 @@ https://opensource.org/licenses/LGPL-3.0 #include #include #include +#include EFI_HANDLE* gUSBHandles = NULL; UINTN gUSBCount = 0; +UINTN gUSBSelect = 0; EFI_STATUS InitUsb() { @@ -86,3 +88,61 @@ UsbGetId( *id = buff; return EFI_SUCCESS; } + +////////////////////////////////////////////////////////////////////////// +// Smart card over usb +////////////////////////////////////////////////////////////////////////// + +/** +* Send APDU to smart card +* @param[IN] cmd command to send +* @param[IN] cmdLen size of Apdu command +* @param[OUT] resp smart card response +* @param[OUT] respLen smart card response length +* @param[OUT] statusSc smart card status (0x9000 - OK) +* @return EFI_SUCCESS if send success. Or platform dependent error +*/ +EFI_STATUS +UsbScTransmit( + IN EFI_USB_IO_PROTOCOL *UsbIO, + IN UINT8* cmd, + IN UINTN cmdLen, + OUT UINT8* resp, + OUT UINTN* respLen, + OUT UINT16* statusSc + ) { + CCID_HEADER_OUT* oheader = (CCID_HEADER_OUT*)cmd; + CCID_HEADER_IN* iheader = (CCID_HEADER_IN*)resp; + EFI_STATUS status; + UINT32 usbres; + UINTN len; + UINTN resplen; + // Init CCID HEADER + SetMem(cmd,sizeof(CCID_HEADER_OUT), 0); + oheader->bMessageType = PC_to_RDR_XfrBlock_Message; + oheader->bSeq = 0x99; + oheader->dwLength = (UINT32)(cmdLen - sizeof(CCID_HEADER_OUT)); + len = cmdLen; + // Send APDU + PrintBytes(cmd, len); + OUT_PRINT(L"\n"); + status = UsbIO->UsbBulkTransfer(UsbIO, 2,cmd, &len, 5000, &usbres); + if (EFI_ERROR(status)) { + ERR_PRINT(L"SC send: %r\n", status); + return status; + } + len = *respLen; + SetMem(resp, len, 0); + do { + status = UsbIO->UsbBulkTransfer(UsbIO, 0x81, resp, &len, 5000, &usbres); + } while ((status == EFI_SUCCESS) && ((iheader->bStatus & 0xC0) == 0x80)); // Timeout? => retry + if (EFI_ERROR(status)) { + ERR_PRINT(L"SC resp: %r\n", status); + return status; + } + // Parse response + resplen = iheader->dwLength; + *respLen = iheader->dwLength + sizeof(CCID_HEADER_IN); + *statusSc = (UINT16)(resp[sizeof(CCID_HEADER_IN) + resplen - 1]) | (((UINT16)resp[sizeof(CCID_HEADER_IN) + resplen - 2]) << 8); + return EFI_SUCCESS; +} -- cgit v1.2.3