X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/1511ea28a8cc647a6fc462e9c182622a43df1318..a9104f7e31d6c134f9772fef6df2156ed06c9e78:/client/pcsc.c diff --git a/client/pcsc.c b/client/pcsc.c new file mode 100644 index 00000000..dd331d0a --- /dev/null +++ b/client/pcsc.c @@ -0,0 +1,177 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 piwi +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// PCSC functions to use alternative Smartcard Readers +//----------------------------------------------------------------------------- + +#include "pcsc.h" + +#include +#include +#include +#include + +#if defined (__APPLE__) +#include +#include +#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag))) +#define SCARD_CLASS_ICC_STATE 9 +#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303) +#elif defined (_WIN32) +#include +#else +#include +#include +#endif + +#include "ui.h" +#include "util.h" +#include "cmdhw.h" + +static SCARDCONTEXT SC_Context; +static SCARDHANDLE SC_Card; +static DWORD SC_Protocol; +static char* AlternativeSmartcardReader = NULL; + + +char *getAlternativeSmartcardReader(void) +{ + return AlternativeSmartcardReader; +} + + +bool pcscCheckForCardReaders(void) +{ + LONG res = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &SC_Context); + if (res != SCARD_S_SUCCESS) { + return false; + } + + DWORD pcchReaders; + res = SCardListReaders(SC_Context, NULL, NULL, &pcchReaders); + if (res != SCARD_S_SUCCESS) { + SCardReleaseContext(SC_Context); + return false; + } + + if (res == SCARD_E_NO_READERS_AVAILABLE || res == SCARD_E_NO_SERVICE) { + SCardReleaseContext(SC_Context); + return false; + } + + return true; +} + + +static char *pickReader(LPTSTR readerlist) +{ + PrintAndLogEx(NORMAL, "Please select one of these:"); + PrintAndLogEx(NORMAL, " [0] PM3 RDV40 Smartcard Slot %s", PM3hasSmartcardSlot() ? "(default)" : "(default, not available)"); + + int num = 1; + for (LPTSTR p = readerlist; *p != '\0'; ) { + PrintAndLogEx(NORMAL, " [%1d] %s", num++, p); + while (*p++ != '\0') ; // advance to next entry + } + + num--; + + if (num == 1) { + printf("Your choice (0 or 1)?"); + } else { + printf("Your choice (0...%d)? ", num); + } + int selection = getch() - '0'; + printf("\n"); + + if (selection == 0) { + PrintAndLogEx(INFO, "Selected RDV40 Smartcard Slot"); + return NULL; + } + + if (selection >= 1 && selection <= num) { + LPTSTR p = readerlist; + for (int i = 1; i < selection; i++) { + while (*p++ != '\0') ; // advance to next entry + } + PrintAndLogEx(INFO, "Selected %s", p); + return p; + } + + PrintAndLogEx(INFO, "Invalid selection. Using RDV40 Smartcard Slot"); + return NULL; + +} + + +char *matchString(LPTSTR readerlist, const char *readername) +{ + return pickReader(readerlist); +} + + +bool pcscSelectAlternativeCardReader(const char *readername) +{ + DWORD readerlist_len; + LONG res = SCardListReaders(SC_Context, NULL, NULL, &readerlist_len); + if (res != SCARD_S_SUCCESS) { + return false; + } + + LPTSTR readerlist = calloc(readerlist_len, sizeof(char)); + res = SCardListReaders(SC_Context, NULL, readerlist, &readerlist_len); + if (res != SCARD_S_SUCCESS) { + free(readerlist); + return false; + } + + char *selected_readername = NULL; + if (readername) { + selected_readername = matchString(readerlist, readername); + } else { + selected_readername = pickReader(readerlist); + } + + if (selected_readername == NULL) { + free(readerlist); + return false; + } + + free(AlternativeSmartcardReader); + AlternativeSmartcardReader = malloc((strlen(selected_readername) + 1) * sizeof(char)); + strcpy(AlternativeSmartcardReader, selected_readername); + + return true; +} + + +bool pcscGetATR(smart_card_atr_t *card) +{ + if (!card) { + return false; + } + + card->atr_len = 0; + memset(card->atr, 0, sizeof(card->atr)); + + LONG res = SCardConnect(SC_Context, AlternativeSmartcardReader, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &SC_Card, &SC_Protocol); + if (res != SCARD_S_SUCCESS) { + return false; + } + + DWORD atr_len = sizeof(card->atr); + res = SCardGetAttrib(SC_Card, SCARD_ATTR_ATR_STRING, card->atr, &atr_len); + if (res != SCARD_S_SUCCESS) { + return false; + } + card->atr_len = atr_len; + + // TODO: LogTrace without device + + return true; +}