diff options
-rw-r--r-- | DcsCfg/DcsCfg.h | 5 | ||||
-rw-r--r-- | DcsCfg/DcsCfgCrypt.c | 22 | ||||
-rw-r--r-- | DcsCfg/DcsCfgMain.c | 16 | ||||
-rw-r--r-- | Include/Library/CommonLib.h | 49 | ||||
-rw-r--r-- | Library/CommonLib/EfiConsole.c | 124 | ||||
-rw-r--r-- | Library/CommonLib/EfiUsb.c | 60 |
6 files changed, 269 insertions, 7 deletions
diff --git a/DcsCfg/DcsCfg.h b/DcsCfg/DcsCfg.h index 412e4c4..37fdbca 100644 --- a/DcsCfg/DcsCfg.h +++ b/DcsCfg/DcsCfg.h @@ -135,8 +135,9 @@ extern UINTN UsbIndex; VOID
PrintUsbList();
-VOID
-UsbSelect();
+EFI_STATUS
+UsbScApdu(
+ IN CHAR16* hexString);
//////////////////////////////////////////////////////////////////////////
// Beep
diff --git a/DcsCfg/DcsCfgCrypt.c b/DcsCfg/DcsCfgCrypt.c index 08c2ee6..e4e0e2e 100644 --- a/DcsCfg/DcsCfgCrypt.c +++ b/DcsCfg/DcsCfgCrypt.c @@ -1552,6 +1552,28 @@ PrintUsbList() { UsbIoPrintDevicePaths(L"%HUSB IO handles%N\n");
}
+EFI_STATUS
+UsbScApdu(
+ IN CHAR16* hexString)
+{
+ UINT8 cmd[256];
+ UINTN cmdLen = sizeof(cmd) - sizeof(CCID_HEADER_OUT);
+ UINT8 resp[256];
+ UINTN respLen = sizeof(resp);
+ UINT16 statusSc = 0;
+ EFI_USB_IO_PROTOCOL *UsbIo =NULL;
+ EFI_STATUS res;
+ CE(InitUsb());
+ CE(UsbGetIO(gUSBHandles[UsbIndex], &UsbIo));
+ StrHexToBytes(cmd + sizeof(CCID_HEADER_OUT), &cmdLen, hexString);
+ CE(UsbScTransmit(UsbIo, cmd, cmdLen + sizeof(CCID_HEADER_OUT), resp, &respLen, &statusSc));
+ PrintBytes(resp, respLen);
+ return res;
+err:
+ ERR_PRINT(L"Error(%d) %r\n", gCELine, res);
+ return res;
+}
+
//////////////////////////////////////////////////////////////////////////
// Set DcsInt parameters
diff --git a/DcsCfg/DcsCfgMain.c b/DcsCfg/DcsCfgMain.c index c289bf8..3abd759 100644 --- a/DcsCfg/DcsCfgMain.c +++ b/DcsCfg/DcsCfgMain.c @@ -40,6 +40,8 @@ https://opensource.org/licenses/LGPL-3.0 #define OPT_DISK_END L"-de"
#define OPT_DISK_BOOT L"-db"
#define OPT_USB_LIST L"-ul"
+#define OPT_USB_SELECT L"-us"
+#define OPT_SC_APDU L"-scapdu"
#define OPT_TOUCH_LIST L"-tl"
#define OPT_TOUCH_TEST L"-tt"
#define OPT_GRAPH_LIST L"-gl"
@@ -123,6 +125,8 @@ STATIC CONST SHELL_PARAM_ITEM ParamList[] = { { OPT_VOLUME_DECRYPT,TypeValue },
{ OPT_VOLUME_CHANGEPWD,TypeValue },
{ OPT_USB_LIST, TypeFlag },
+ { OPT_USB_SELECT, TypeValue },
+ { OPT_SC_APDU, TypeValue },
{ OPT_TOUCH_LIST, TypeFlag },
{ OPT_TOUCH_TEST, TypeValue },
{ OPT_GRAPH_LIST, TypeFlag },
@@ -409,6 +413,18 @@ DcsCfgMain( PrintUsbList();
}
+ if (ShellCommandLineGetFlag(Package, OPT_USB_SELECT)) {
+ CHAR16 * opt;
+ opt = (CHAR16*)ShellCommandLineGetValue(Package, OPT_USB_SELECT);
+ UsbIndex = StrDecimalToUintn(opt);
+ }
+
+ if (ShellCommandLineGetFlag(Package, OPT_SC_APDU)) {
+ CHAR16 * opt;
+ opt = (CHAR16*)ShellCommandLineGetValue(Package, OPT_SC_APDU);
+ UsbScApdu(opt);
+ }
+
// Randoms
if (ShellCommandLineGetFlag(Package, OPT_RND_LOAD)) {
CONST CHAR16* opt = NULL;
diff --git a/Include/Library/CommonLib.h b/Include/Library/CommonLib.h index 7966eee..2b46632 100644 --- a/Include/Library/CommonLib.h +++ b/Include/Library/CommonLib.h @@ -262,6 +262,39 @@ UsbGetId( OUT CHAR8** id
);
+#define PC_to_RDR_XfrBlock_Message 0x6F
+
+#pragma pack(1)
+typedef struct _CCID_HEADER_OUT {
+ UINT8 bMessageType; // Type of the message
+ UINT32 dwLength; // Length of data
+ UINT8 bSlot; //
+ UINT8 bSeq; //
+ UINT8 bReserved; //
+ UINT16 wLevelParameter; // 0000h Short APDU level
+} CCID_HEADER_OUT;
+
+typedef struct _CCID_HEADER_IN {
+ UINT8 bMessageType; // Type of the message
+ UINT32 dwLength; // Length of data
+ UINT8 bSlot; //
+ UINT8 bSeq; //
+ UINT8 bStatus; //
+ UINT8 bError; //
+ UINT8 bChainParameter;
+} CCID_HEADER_IN;
+#pragma pack()
+
+EFI_STATUS
+UsbScTransmit(
+ IN EFI_USB_IO_PROTOCOL *UsbIO,
+ IN UINT8* cmd,
+ IN UINTN cmdLen,
+ OUT UINT8* resp,
+ OUT UINTN* respLen,
+ OUT UINT16* statusSc
+ );
+
//////////////////////////////////////////////////////////////////////////
// Touch
//////////////////////////////////////////////////////////////////////////
@@ -292,7 +325,7 @@ TouchGetIO( VOID
PrintBytes(
IN UINT8* Data,
- IN UINT32 Size);
+ IN UINTN Size);
EFI_STATUS
ConsoleGetOutput(
@@ -383,6 +416,20 @@ AsciiStrToGuid( IN CHAR8 *str
);
+BOOLEAN
+AsciiHexToBytes(
+ OUT UINT8 *b,
+ IN UINTN *bytesLen,
+ IN CHAR8 *str
+ );
+
+BOOLEAN
+StrHexToBytes(
+ OUT UINT8 *b,
+ IN UINTN *bytesLen,
+ IN CHAR16 *str
+ );
+
//////////////////////////////////////////////////////////////////////////
// Menu
//////////////////////////////////////////////////////////////////////////
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 <Library/DevicePathLib.h>
#include <Library/PrintLib.h>
#include <Protocol/UsbIo.h>
+#include <Library/BaseMemoryLib.h>
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;
+}
|