vector<RAPDU> ePACard::transceive(const vector<CAPDU> &cmds) { vector<RAPDU> resps; if (!m_kEnc.empty() && !m_kMac.empty()) { unsigned long long start_ssc = m_ssc; size_t i; bool sm = true; vector<CAPDU> sm_cmds; for (i = 0; i < cmds.size(); i++) { if (cmds[i].isSecure()) sm = false; if (sm) { sm_cmds.push_back(applySM(cmds[i])); /* increment SSC, to simulate decryption of the APDU */ m_ssc++; } else sm_cmds.push_back(cmds[i]); } vector<RAPDU> sm_resps = ICard::transceive(sm_cmds); if (cmds.size() > sm_resps.size()) { eCardCore_warn(DEBUG_LEVEL_APDU, "Received too few APDUs"); } m_ssc = start_ssc; sm = true; for (i = 0; i < sm_resps.size() && i < cmds.size(); i++) { if (cmds[i].isSecure()) sm = false; if (sm) { /* increment SSC, to simulate encryption of the APDU */ m_ssc++; resps.push_back(removeSM(sm_resps[i])); } else resps.push_back(sm_resps[i]); } for (i = 0; i < (cmds.size() - sm_resps.size()); i++) { resps.push_back(RAPDU(vector<unsigned char> (), 0x6d00)); } if (!sm) { m_kEnc.clear(); m_kMac.clear(); m_ssc = 0; } } else { resps = ICard::transceive(cmds); } return resps; }
bool ExternalReader::m_libload(void) { bool r = false; if (!m_hLib) { #if defined(WIN32) #if defined(_DEBUG) || defined(DEBUG) m_hLib = LOAD_LIBRARY("externalReaderd.dll"); #else m_hLib = LOAD_LIBRARY("externalReader.dll"); #endif #elif defined(__APPLE__) m_hLib = LOAD_LIBRARY("libexternalReader.dylib"); #else m_hLib = LOAD_LIBRARY("libexternalReader.so"); #endif if (m_hLib) { m_hOpen = (CardReaderOpen_t) GET_FUNCTION(m_hLib, CardReaderOpen); m_hSend = (CardReaderSend_t) GET_FUNCTION(m_hLib, CardReaderSend); m_hGetATR = (CardReaderGetATR_t) GET_FUNCTION(m_hLib, CardReaderGetATR); m_hSupportsPACE = (CardReaderSupportsPACE_t) GET_FUNCTION(m_hLib, CardReaderSupportsPACE); m_hDoPACE = (CardReaderDoPACE_t) GET_FUNCTION(m_hLib, CardReaderDoPACE); m_hClose = (CardReaderClose_t) GET_FUNCTION(m_hLib, CardReaderClose); } else { eCardCore_warn(DEBUG_LEVEL_CARD, "could not load external reader library"); } } if (!m_hLib || !m_hOpen || !m_hSend || !m_hGetATR || !m_hSupportsPACE || !m_hDoPACE || !m_hClose) { eCardCore_warn(DEBUG_LEVEL_CARD, "could not load external reader library functions"); m_libcleanup(); } else { r = true; } return r; }
std::vector<unsigned char> ExternalReader::transceive(const std::vector<unsigned char>& cmd) { std::vector<unsigned char> response; unsigned long nLengthResult = MAX_BUFFER_SIZE; if (ECARD_SUCCESS == m_hSend(m_hCardReader, DATA(cmd), cmd.size(), buffer, &nLengthResult)) { response.clear(); response.insert(response.end(), buffer, buffer+nLengthResult); } else eCardCore_warn(DEBUG_LEVEL_CARD, "external send failed"); return response; }
bool ExternalReader::open(void) { bool r = false; if (!m_hOpen) goto err; if (ECARD_SUCCESS == m_hOpen(&m_hCardReader, "ExternalCardReader")) r = true; else eCardCore_warn(DEBUG_LEVEL_CARD, "external open failed"); err: return r; }
std::vector<unsigned char> ExternalReader::getATRForPresentCard(void) { std::vector<unsigned char> atr; unsigned long nLengthResult = MAX_BUFFER_SIZE; if (!m_hGetATR) goto err; if (ECARD_SUCCESS == m_hGetATR(m_hCardReader, buffer, &nLengthResult)) atr.insert(atr.end(), buffer, buffer+nLengthResult); else eCardCore_warn(DEBUG_LEVEL_CARD, "external get atr failed"); err: return atr; }
PCSCReader::PCSCReader( const string &readerName, vector<ICardDetector *>& detector) : IReader(readerName, detector), m_hCard(0x0), #if defined(_WIN32) m_dwProtocol(SCARD_PROTOCOL_UNDEFINED), #else m_dwProtocol(SCARD_PROTOCOL_UNSET), #endif m_hScardContext(0x0) { DWORD retValue = SCARD_S_SUCCESS; BYTE sendbuf[] = { FUNCTION_GetReadersPACECapabilities, 0x00, /* lengthInputData */ 0x00, /* lengthInputData */ }; if ((retValue = SCardEstablishContext(/*SCARD_SCOPE_USER*/ SCARD_SCOPE_SYSTEM, 0x0, 0x0, &m_hScardContext)) != SCARD_S_SUCCESS) eCardCore_warn(DEBUG_LEVEL_CARD, "SCardEstablishContext failed. 0x%08X (%s:%d)", retValue, __FILE__, __LINE__); #if defined(UNICODE) || defined(_UNICODE) WCHAR *_readerName = new WCHAR[m_readerName.size() + 1]; mbstowcs(_readerName, m_readerName.c_str(), m_readerName.size()); _readerName[m_readerName.size()] = 0; retValue = SCardConnect(m_hScardContext, _readerName, SCARD_SHARE_DIRECT, m_dwProtocol, &m_hCard, &m_dwProtocol); delete [] _readerName; #else retValue = SCardConnect(m_hScardContext, m_readerName.c_str(), SCARD_SHARE_DIRECT, m_dwProtocol, &m_hCard, &m_dwProtocol); #endif if (retValue != SCARD_S_SUCCESS) { eCardCore_warn(DEBUG_LEVEL_CARD, "SCardConnect for %s failed. 0x%08X (%s:%d)", m_readerName.c_str(), retValue, __FILE__, __LINE__); } /* does the reader support PACE? */ m_ioctl_pace = 0; #if ENABLE_PACE BYTE recvbuf[1024]; DWORD recvlen = sizeof(recvbuf); retValue = SCardControl(m_hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, recvbuf, sizeof(recvbuf), &recvlen); if (retValue != SCARD_S_SUCCESS) { eCardCore_warn(DEBUG_LEVEL_CARD, "SCardControl for the reader's features failed. 0x%08X (%s:%d)", retValue, __FILE__, __LINE__); } else { for (size_t i = 0; i + PCSC_TLV_ELEMENT_SIZE <= recvlen; i += PCSC_TLV_ELEMENT_SIZE) if (recvbuf[i] == FEATURE_EXECUTE_PACE) memcpy(&m_ioctl_pace, recvbuf + i + 2, 4); } if (0 == m_ioctl_pace) { eCardCore_info(DEBUG_LEVEL_CARD, "Reader does not support PACE"); } else { /* convert to host byte order to use for SCardControl */ m_ioctl_pace = ntohl(m_ioctl_pace); hexdump(DEBUG_LEVEL_CARD, "Execute PACE Input Data (FUNCTION=GetReadersPACECapabilities)", sendbuf, sizeof sendbuf); recvlen = sizeof(recvbuf); retValue = SCardControl(m_hCard, m_ioctl_pace, sendbuf, sizeof sendbuf, recvbuf, sizeof(recvbuf), &recvlen); hexdump(DEBUG_LEVEL_CARD, "Execute PACE Output Data (FUNCTION=GetReadersPACECapabilities)", recvbuf, recvlen); if (retValue == SCARD_S_SUCCESS && recvlen == 7 && recvbuf[0] == 0 && recvbuf[1] == 0 && recvbuf[2] == 0 && recvbuf[3] == 0) { if (recvbuf[6] & BITMAP_Qualified_Signature) eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports qualified signature"); if (recvbuf[6] & BITMAP_German_eID) eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports German eID"); if (recvbuf[6] & BITMAP_PACE) { eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports PACE"); } else m_ioctl_pace = 0; if (recvbuf[6] & BITMAP_DestroyPACEChannel) eCardCore_info(DEBUG_LEVEL_CARD, "Reader supports DestroyPACEChannel"); } else { eCardCore_warn(DEBUG_LEVEL_CARD, "Error executing GetReadersPACECapabilities"); m_ioctl_pace = 0; } } #endif }
static PaceOutput parse_EstablishPACEChannel_OutputData(BYTE *output, size_t output_length) { size_t parsed = 0; uint8_t lengthCAR, lengthCARprev; uint16_t lengthOutputData, lengthEF_CardAccess, length_IDicc, mse_setat; vector<BYTE> CAR, CARprev, EF_CardAccess, IDicc; uint32_t result; PaceOutput paceoutput; /* Output Data */ if (parsed + sizeof result > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } memcpy(&result, output + parsed, sizeof result); switch (result) { case 0x00000000: break; case 0xD0000001: eCardCore_warn(DEBUG_LEVEL_CARD, "Längen im Input sind inkonsistent"); throw PACEException(); case 0xD0000002: eCardCore_warn(DEBUG_LEVEL_CARD, "Unerwartete Daten im Input"); throw PACEException(); case 0xD0000003: eCardCore_warn(DEBUG_LEVEL_CARD, "Unerwartete Kombination von Daten im Input"); throw PACEException(); case 0xE0000001: eCardCore_warn(DEBUG_LEVEL_CARD, "Syntaxfehler im Aufbau der TLV-Antwortdaten"); throw PACEException(); case 0xE0000002: eCardCore_warn(DEBUG_LEVEL_CARD, "Unerwartete/fehlende Objekte in den TLV-Antwortdaten"); throw PACEException(); case 0xE0000003: eCardCore_warn(DEBUG_LEVEL_CARD, "Der Kartenleser kennt die PIN-ID nicht."); throw PACEException(); case 0xE0000006: eCardCore_warn(DEBUG_LEVEL_CARD, "Fehlerhaftes PACE-Token"); throw PACEException(); case 0xE0000007: eCardCore_warn(DEBUG_LEVEL_CARD, "Zertifikatskette für Terminalauthentisierung kann nicht gebildet werden"); throw PACEException(); case 0xE0000008: eCardCore_warn(DEBUG_LEVEL_CARD, "Unerwartete Datenstruktur in Rückgabe der Chipauthentisierung"); throw PACEException(); case 0xE0000009: eCardCore_warn(DEBUG_LEVEL_CARD, "Passive Authentisierung fehlgeschlagen"); throw PACEException(); case 0xE000000A: eCardCore_warn(DEBUG_LEVEL_CARD, "Fehlerhaftes Chipauthentisierung-Token"); throw PACEException(); case 0xF0100001: eCardCore_warn(DEBUG_LEVEL_CARD, "Kommunikationsabbruch mit Karte."); throw PACEException(); default: eCardCore_warn(DEBUG_LEVEL_CARD, "Reader reported some error: %0X.", result); throw PACEException(); } paceoutput.set_result(result); parsed += sizeof result; /* Output Data */ if (parsed + sizeof lengthOutputData > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } memcpy(&lengthOutputData, output + parsed, sizeof lengthOutputData); parsed += sizeof lengthOutputData; if (lengthOutputData != output_length - parsed) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } /* MSE:Set AT */ if (parsed + sizeof mse_setat > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } memcpy(&mse_setat, output + parsed, sizeof mse_setat); paceoutput.set_status_mse_set_at(mse_setat); parsed += sizeof mse_setat; /* lengthEF_CardAccess */ if (parsed + 2 > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } memcpy(&lengthEF_CardAccess, output + parsed, sizeof lengthEF_CardAccess); parsed += sizeof lengthEF_CardAccess; /* EF.CardAccess */ if (parsed + lengthEF_CardAccess > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } EF_CardAccess.assign(output + parsed, output + parsed + lengthEF_CardAccess); paceoutput.set_ef_cardaccess(EF_CardAccess); parsed += lengthEF_CardAccess; /* lengthCAR */ if (parsed + sizeof lengthCAR > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } memcpy(&lengthCAR, output + parsed, sizeof lengthCAR); parsed += sizeof lengthCAR; /* CAR */ if (parsed + lengthCAR > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } CAR.assign(output + parsed, output + parsed + lengthCAR); paceoutput.set_car_curr(CAR); parsed += lengthCAR; /* lengthCARprev */ if (parsed + sizeof lengthCARprev > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } memcpy(&lengthCARprev, output + parsed, sizeof lengthCARprev); parsed += sizeof lengthCARprev; /* CARprev */ if (parsed + lengthCARprev > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } CARprev.assign(output + parsed, output + parsed + lengthCARprev); paceoutput.set_car_prev(CARprev); parsed += lengthCARprev; /* lengthIDicc */ if (parsed + sizeof length_IDicc > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } memcpy(&length_IDicc , output + parsed, sizeof length_IDicc); parsed += sizeof length_IDicc; /* IDicc */ if (parsed + length_IDicc > output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Malformed Establish PACE Channel output data."); throw PACEException(); } IDicc.assign(output + parsed, output + parsed + length_IDicc); paceoutput.set_id_icc(IDicc); parsed += length_IDicc; if (parsed != output_length) { eCardCore_warn(DEBUG_LEVEL_CARD, "Overrun by %d bytes", output_length - parsed); throw PACEException(); } return paceoutput; }
void PCSCManager::findReaders( void) { long retValue = SCARD_S_SUCCESS; SCARDCONTEXT hScardContext = 0x0; if ((retValue = SCardEstablishContext(SCARD_SCOPE_SYSTEM, 0x0, 0x0, &hScardContext)) != SCARD_S_SUCCESS) { eCardCore_warn(DEBUG_LEVEL_CARD, "SCardEstablishContext failed. 0x%08X (%s:%d)", retValue, __FILE__, __LINE__); return; } DWORD dwSize = 0; if ((retValue = SCardListReaders(hScardContext, NULL, NULL, &dwSize)) != SCARD_S_SUCCESS) { eCardCore_warn(DEBUG_LEVEL_CARD, "SCardListReaders failed. 0x%08X (%s:%d)", retValue, __FILE__, __LINE__); return; } #if defined(WIN32) || defined(WINCE) LPTSTR readers = new TCHAR[dwSize]; #else char *readers = new char[dwSize]; #endif if ((retValue = SCardListReaders(hScardContext, NULL, readers, &dwSize)) != SCARD_S_SUCCESS) { eCardCore_warn(DEBUG_LEVEL_CARD, "SCardListReaders failed. 0x%08X (%s:%d)", retValue, __FILE__, __LINE__); return; } if (0x00 == readers) { eCardCore_warn(DEBUG_LEVEL_CARD, "No readers available. (%s:%d)", __FILE__, __LINE__); return; } #if defined(WIN32) || defined(WINCE) LPTSTR pReader = readers; #else char *pReader = readers; #endif while ('\0' != *pReader) { #if defined(UNICODE) || defined(_UNICODE) int size = wcslen(pReader) + 1; char *pMBBuffer = new char[size]; memset(pMBBuffer, 0, size); wcstombs(pMBBuffer, pReader, wcslen(pReader)); IReader *newReader = new PCSCReader(pMBBuffer, m_cardDetectors); m_readerList.push_back(newReader); delete [] pMBBuffer; pReader = pReader + wcslen(pReader) + 1; #else m_readerList.push_back(new PCSCReader(pReader, m_cardDetectors)); pReader = pReader + strlen(pReader) + 1; #endif } delete [] readers; SCardReleaseContext(hScardContext); }
PaceOutput ExternalReader::establishPACEChannelNative(const PaceInput &input) { PaceOutput paceoutput; if (m_hDoPACE) { enum PinID pinid = PI_UNDEF; switch (input.get_pin_id()) { case PaceInput::pin: pinid = PI_PIN; break; case PaceInput::can: pinid = PI_CAN; break; case PaceInput::mrz: pinid = PI_MRZ; break; case PaceInput::puk: pinid = PI_PUK; break; default: eCardCore_warn(DEBUG_LEVEL_CARD, "Unknown type of secret"); break; } const nPADataBuffer_t pin = { (unsigned char *) DATA(input.get_pin()), input.get_pin().size()}; const nPADataBuffer_t chat = { (unsigned char *) DATA(input.get_chat()), input.get_chat().size()}; const nPADataBuffer_t chat_required = { (unsigned char *) DATA(input.get_chat_required()), input.get_chat_required().size()}; const nPADataBuffer_t chat_optional = { (unsigned char *) DATA(input.get_chat_optional()), input.get_chat_optional().size()}; const nPADataBuffer_t certificate_description = { (unsigned char *) DATA(input.get_certificate_description()), input.get_certificate_description().size()}; const nPADataBuffer_t transaction_info_hidden = { (unsigned char *) DATA(input.get_transaction_info_hidden()), input.get_transaction_info_hidden().size()}; unsigned int result; unsigned short status_mse_set_at; nPADataBuffer_t ef_cardaccess = {NULL, 0}; nPADataBuffer_t car_curr = {NULL, 0}; nPADataBuffer_t car_prev = {NULL, 0}; nPADataBuffer_t id_icc = {NULL, 0}; nPADataBuffer_t chat_used = {NULL, 0}; if (ECARD_SUCCESS == m_hDoPACE(m_hCardReader, pinid, &pin, &chat, &chat_required, &chat_optional, &certificate_description, &transaction_info_hidden, &result, &status_mse_set_at, &ef_cardaccess, &car_curr, &car_prev, &id_icc, &chat_used)) { paceoutput.set_result(result); paceoutput.set_status_mse_set_at(status_mse_set_at); paceoutput.set_ef_cardaccess(buffer2vector(&ef_cardaccess)); paceoutput.set_car_curr(buffer2vector(&car_curr)); paceoutput.set_car_prev(buffer2vector(&car_prev)); paceoutput.set_id_icc(buffer2vector(&id_icc)); paceoutput.set_chat(buffer2vector(&chat_used)); free(car_curr.pDataBuffer); free(car_prev.pDataBuffer); free(ef_cardaccess.pDataBuffer); free(id_icc.pDataBuffer); free(chat_used.pDataBuffer); } else eCardCore_warn(DEBUG_LEVEL_CARD, "external PACE failed"); } return paceoutput; }