From 2ed6a468fca16337be1718cfc015fdcd79d2e49e Mon Sep 17 00:00:00 2001 From: frankmorgner Date: Wed, 25 Jan 2012 15:04:52 +0000 Subject: [PATCH] using patched OpenSC enabled with PACE to use the reader's capabilities sourcecode can be fetched from here https://github.com/frankmorgner/OpenSC git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@696 96b47cad-a561-4643-ad3b-153ac7d7599c --- ccid/configure.ac | 35 --- ccid/src/Makefile.am | 18 +- ccid/src/cats-test.c | 475 ----------------------------------------- ccid/src/ccid.c | 58 ++--- npa/Makefile.am.opensc | 5 +- npa/configure.ac | 6 +- npa/src/example.c | 3 +- npa/src/npa-tool.c | 16 +- npa/src/npa.c | 402 +++++++++++++++++----------------- npa/src/npa/npa.h | 68 +----- 10 files changed, 248 insertions(+), 838 deletions(-) delete mode 100644 ccid/src/cats-test.c diff --git a/ccid/configure.ac b/ccid/configure.ac index 766ff29..1de257c 100644 --- a/ccid/configure.ac +++ b/ccid/configure.ac @@ -102,38 +102,6 @@ AM_COND_IF(WITH_PACE, [AC_DEFINE(BUERGERCLIENT_WORKAROUND, 1, [Always get EF.Car #AM_COND_IF(WITH_PACE, [AC_DEFINE(MODIFY_PIN, 1, [Change the PIN after authentication.])]) -# --disable-cats -AC_ARG_ENABLE(cats, - AS_HELP_STRING([--enable-cats], [Disable tool for CAT-S and CAT-C (pinpad readers with PACE support)]), - [enable_cats="${enableval}"], [enable_cats=no]) -if test "x$enable_cats" != xno ; then - PKG_CHECK_EXISTS([libpcsclite > 1.4.102], - [PKG_CHECK_MODULES([PCSC], [libpcsclite > 1.4.102])], - [AC_MSG_WARN([libpcsclite > 1.4.102 not found by pkg-config])]) - - saved_CPPFLAGS="$CPPFLAGS" - saved_LIBS="$LIBS" - CPPFLAGS="$CPPFLAGS $PCSC_CFLAGS" - LIBS="$LDFLAGS $PCSC_LIBS" - - AC_CHECK_HEADERS(winscard.h, [], [ AC_MSG_ERROR([winscard.h not found, install PC/SC Lite or similar or use ./configure PCSC_CFLAGS=...]) ]) - AC_CHECK_HEADERS(reader.h, [AC_DEFINE(HAVE_READER_H, 1, [use reader.h from PC/SC Lite])], []) - AC_CHECK_HEADERS(pcsclite.h, [AC_DEFINE(HAVE_PCSCLITE_H, 1, [use pcsclite.h from PC/SC Lite])], []) - AC_CHECK_DECL(FEATURE_EXECUTE_PACE, [], - [AC_MSG_WARN([libpcsclite > 1.4.102 patched with pcsclite_trunk.patch not found]) ], - [#include ]) - AC_MSG_CHECKING([for SCardEstablishContext]) - AC_TRY_LINK_FUNC(SCardEstablishContext, [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_ERROR([libpcsclite > 1.4.102 not found, use ./configure PCSC_LIBS=...]) ]) - - CPPFLAGS="$saved_CPPFLAGS" - LIBS="$saved_LIBS" - - enable_cats=yes -fi -AM_CONDITIONAL(WITH_CATS, test "x${enable_cats}" != "xno") - - # Checks for header files. AC_CHECK_HEADERS([arpa/inet.h fcntl.h memory.h stdint.h stdlib.h string.h sys/ioctl.h unistd.h]) @@ -174,12 +142,9 @@ OPENSSL_CFLAGS: ${OPENSSL_CFLAGS} OPENSSL_LIBS: ${OPENSSL_LIBS} LIBPACE_CFLAGS: ${LIBPACE_CFLAGS} LIBPACE_LIBS: ${LIBPACE_LIBS} -PCSC_CFLAGS: ${PCSC_CFLAGS} -PCSC_LIBS: ${PCSC_LIBS} CCID emulator: ${enable_ccid} PACE support: ${enable_pace} -CAT-S/CAT-C Tool: ${enable_cats} EOF diff --git a/ccid/src/Makefile.am b/ccid/src/Makefile.am index 2089f9a..db2240f 100644 --- a/ccid/src/Makefile.am +++ b/ccid/src/Makefile.am @@ -1,15 +1,10 @@ -EXTRA_DIST = $(shell find $(top_srcdir)/src/opensc -path '*/.svn' -prune -o -type f -a -name '*.h' -print) - -AM_CPPFLAGS = -I$(top_srcdir)/src/opensc/src +EXTRA_DIST = $(shell find $(top_srcdir)/src/opensc -path '*/.svn' -prune -o -type f -a -name '*.h' -print) +EXTRA_DIST += $(shell find $(top_srcdir)/src/opensc-npa -path '*/.svn' -prune -o -type f -a -name '*.h' -print) ccid_emulator_SOURCES = ccid.c usbstring.c usb.c binutil.c sslutil.c ccid_emulator_LDADD = $(OPENSSL_LIBS) $(PTHREAD_LIBS) ccid_emulator_CFLAGS = $(OPENSSL_CFLAGS) $(PTHREAD_CFLAGS) -cats_test_SOURCES = cats-test.c pcscutil.c -cats_test_LDADD = $(PCSC_LIBS) -cats_test_CFLAGS = $(PCSC_CFLAGS) - bin_PROGRAMS = @@ -26,15 +21,14 @@ bin_PROGRAMS += ccid-emulator endif -if WITH_CATS -bin_PROGRAMS += cats-test -endif - - if WITH_PACE +AM_CPPFLAGS = -I$(top_srcdir)/src/opensc-npa/src + ccid_emulator_LDADD += $(LIBNPA_LIBS) ccid_emulator_CFLAGS += $(LIBNPA_CFLAGS) else +AM_CPPFLAGS = -I$(top_srcdir)/src/opensc/src + ccid_emulator_SOURCES += scutil.c ccid_emulator_LDADD += $(OPENSC_LIBS) endif diff --git a/ccid/src/cats-test.c b/ccid/src/cats-test.c deleted file mode 100644 index b3deddb..0000000 --- a/ccid/src/cats-test.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2010 Frank Morgner - * - * This file is part of ccid. - * - * ccid is free software: you can redistribute it and/or modify it under the - * terms of the GNU General Public License as published by the Free Software - * Foundation, either version 3 of the License, or (at your option) any later - * version. - * - * ccid is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * ccid. If not, see . - */ -#include -#include -#include -#include -#include -#include - -#pragma comment(lib, "ws2_32.lib") -#pragma comment(lib, "winscard.lib") - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_ARPA_INIT_H -#include -#endif - -#ifdef HAVE_PCSCLITE_H -#include -#endif - -#ifdef HAVE_READER_H -#include -#endif - -#include "pcscutil.h" - - -#ifndef FEATURE_EXECUTE_PACE -#define FEATURE_EXECUTE_PACE 0x20 -#endif - -#ifndef CM_IOCTL_GET_FEATURE_REQUEST -#define CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) -#endif - -#define PCSC_TLV_ELEMENT_SIZE 6 - - -static LONG parse_EstablishPACEChannel_OutputData( - unsigned char output[], unsigned int output_length) -{ - uint8_t lengthCAR, lengthCARprev; - uint16_t lengthOutputData, lengthEF_CardAccess, length_IDicc; - uint32_t result; - size_t parsed = 0; - - if (parsed+4 > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - memcpy(&result, output+parsed, 4); - parsed += 4; - switch (result) { - case 0x00000000: - break; - case 0xD0000001: - fprintf(stderr, "Längen im Input sind inkonsistent\n"); - return SCARD_F_COMM_ERROR; - case 0xD0000002: - fprintf(stderr, "Unerwartete Daten im Input\n"); - return SCARD_F_COMM_ERROR; - case 0xD0000003: - fprintf(stderr, "Unerwartete Kombination von Daten im Input\n"); - return SCARD_F_COMM_ERROR; - case 0xE0000001: - fprintf(stderr, "Syntaxfehler im Aufbau der TLV-Antwortdaten\n"); - return SCARD_F_COMM_ERROR; - case 0xE0000002: - fprintf(stderr, "Unerwartete/fehlende Objekte in den TLV-Antwortdaten\n"); - return SCARD_F_COMM_ERROR; - case 0xE0000003: - fprintf(stderr, "Der Kartenleser kennt die PIN-ID nicht.\n"); - return SCARD_F_COMM_ERROR; - case 0xE0000006: - fprintf(stderr, "Fehlerhaftes PACE-Token\n"); - return SCARD_F_COMM_ERROR; - case 0xE0000007: - fprintf(stderr, "Zertifikatskette für Terminalauthentisierung kann nicht gebildet werden\n"); - return SCARD_F_COMM_ERROR; - case 0xE0000008: - fprintf(stderr, "Unerwartete Datenstruktur in Rückgabe der Chipauthentisierung\n"); - return SCARD_F_COMM_ERROR; - case 0xE0000009: - fprintf(stderr, "Passive Authentisierung fehlgeschlagen\n"); - return SCARD_F_COMM_ERROR; - case 0xE000000A: - fprintf(stderr, "Fehlerhaftes Chipauthentisierung-Token\n"); - return SCARD_F_COMM_ERROR; - case 0xF0100001: - fprintf(stderr, "Kommunikationsabbruch mit Karte.\n"); - return SCARD_F_COMM_ERROR; - default: - fprintf(stderr, "Reader reported some error.\n"); - return SCARD_F_COMM_ERROR; - } - - if (parsed+2 > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - memcpy(&lengthOutputData, output+parsed, 2); - parsed += 2; - if (lengthOutputData != output_length-parsed) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - - if (parsed+2 > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - printf("MSE:Set AT Statusbytes: %02X %02X\n", - output[parsed+0], output[parsed+1]); - parsed += 2; - - if (parsed+2 > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - memcpy(&lengthEF_CardAccess, output+parsed, 2); - parsed += 2; - - if (parsed+lengthEF_CardAccess > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - if (lengthEF_CardAccess) - printb("EF.CardAccess:\n", &output[parsed], lengthEF_CardAccess); - parsed += lengthEF_CardAccess; - - if (parsed+1 > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - lengthCAR = output[parsed]; - parsed += 1; - - if (parsed+lengthCAR > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - if (lengthCAR) - printb("Recent Certificate Authority:\n", - &output[parsed], lengthCAR); - parsed += lengthCAR; - - if (parsed+1 > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - lengthCARprev = output[parsed]; - parsed += 1; - - if (parsed+lengthCARprev > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - if (lengthCARprev) - printb("Previous Certificate Authority:\n", - &output[parsed], lengthCARprev); - parsed += lengthCARprev; - - if (parsed+2 > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - memcpy(&length_IDicc , output+parsed, 2); - parsed += 2; - - if (parsed+length_IDicc > output_length) { - fprintf(stderr, "Malformed Establish PACE Channel output data.\n"); - return SCARD_F_INTERNAL_ERROR; - } - if (length_IDicc) - printb("IDicc:\n", &output[parsed], length_IDicc); - parsed += length_IDicc; - - if (parsed != output_length) { - fprintf(stderr, "Overrun by %d bytes\n", output_length - parsed); - return SCARD_F_INTERNAL_ERROR; - } - - return SCARD_S_SUCCESS; -} - -int -printusageexit(FILE *f, const char *s, int e) -{ - fprintf(f, "Usage: " - "%s secret [secret type] [reader number]\n" - " secret type: MRZ 1, CAN 2, PIN 3 [default], PUK 4\n" - " reader number: 0 [default]\n" - , s); - exit(e); -} - -/* Signature Terminal with - * - "Generate electronic signature" - * - "Generate qualified electronic signature" - */ -unsigned char st_chat[] = { - 0x7f, 0x4c, 0x0e, 0x06, 0x09, 0x04, 0x00, 0x7f, 0x00, 0x07, 0x03, 0x01, - 0x02, 0x03, 0x53, 0x01, 0x03, -}; - -int -main(int argc, char *argv[]) -{ - LONG r; - SCARDCONTEXT hContext; - SCARDHANDLE hCard; - LPSTR readers = NULL; - BYTE sendbuf[16], recvbuf[1024]; - DWORD pace_ctl, modify_ctl, recvlen, protocol; - time_t t_start, t_end; - size_t l, pinlen = 0, chatlen = 0; - char *pin = NULL; - unsigned int readernum = 0, i; - unsigned char secret_type = 0x03; - unsigned char *chat = NULL; - - - if (argc > 1) { - pin = argv[1]; - pinlen = strlen(pin); - if (argc > 2) { - if (sscanf(argv[2], "%hhu", &secret_type) != 1) { - fprintf(stderr, "Could not get type of secret\n"); - exit(2); - } - if (secret_type == 2) { - /* CAN */ - chat = st_chat; - chatlen = sizeof st_chat; - } - } - if (argc > 3) { - if (sscanf(argv[3], "%u", &readernum) != 1) { - fprintf(stderr, "Could not get number of reader\n"); - exit(2); - } - } - if (argc > 4) - printusageexit(stderr, argv[0], 1); - } else - printusageexit(stderr, argv[0], 1); - - - r = pcsc_connect(readernum, SCARD_SHARE_DIRECT, 0, &hContext, &readers, - &hCard, &protocol); - if (r != SCARD_S_SUCCESS) - goto err; - - -#ifdef SIMULATE_BUERGERCLIENT - r = SCardReconnect(hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY, - SCARD_LEAVE_CARD, &protocol); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "Could not reconnect\n"); - goto err; - } - BYTE bufs0[] = { - 0xFF, 0x9A, 0x01, 0x01, - 0xFF, 0x9A, 0x01, 0x03, - 0xFF, 0x9A, 0x01, 0x06, - 0xFF, 0x9A, 0x01, 0x07, - 0x00, 0xA4, 0x02, 0x0C, 0x02, 0x4B, 0x31, - 0x00, 0xA4, 0x04, 0x0C, 0x09, 0xE8, 0x07, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x03, 0x02, - 0x00, 0xA4, 0x00, 0x0C, 0x02, 0x3F, 0x00, - 0x00, 0x22, 0xC1, 0xA4, 0x0F, 0x80, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02, 0x83, 0x01, 0x03, - 0x00, 0xA4, 0x00, 0x0C, 0x02, 0x3F, 0x00, - 0x00, 0xA4, 0x02, 0x0C, 0x02, 0x01, 0x1C, - 0x00, 0xB0, 0x00, 0x00, 0x80, - 0x00, 0xB0, 0x00, 0x80, 0x80, - 0x00, 0xB0, 0x01, 0x00, 0x80, - 0x00, 0xB0, 0x01, 0x80, 0x80, - 0x00, 0xB0, 0x02, 0x00, 0x80, - 0x00, 0xA4, 0x00, 0x0C, 0x02, 0x3F, 0x00, - 0x00, 0x22, 0xC1, 0xA4, 0x0F, 0x80, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x04, 0x02, 0x02, 0x83, 0x01, 0x03, - }; - LPBYTE buf0 = bufs0; - DWORD lens0[] = {4, 4, 4, 4, 7, 14, 7, 20, 7, 7, 5, 5, 5, 5, 5, 7, 20}; - for (l = 0; l < sizeof(lens0)/sizeof(DWORD); l++) { - recvlen = sizeof(recvbuf); - r = pcsc_transmit(protocol, hCard, buf0, lens0[l], recvbuf, &recvlen); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "Simulation of Buergerclient failed\n"); - goto err; - } - buf0 += lens0[l]; - } - r = SCardReconnect(hCard, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, &protocol); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "Could not reconnect\n"); - goto err; - } -#endif - - - /* does the reader support PACE? */ - recvlen = sizeof(recvbuf); - r = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, - recvbuf, sizeof(recvbuf), &recvlen); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "Could not get the reader's features\n"); - goto err; - } - - pace_ctl = 0; - for (i = 0; i <= recvlen-PCSC_TLV_ELEMENT_SIZE; i += PCSC_TLV_ELEMENT_SIZE) { - if (recvbuf[i] == FEATURE_EXECUTE_PACE) { - memcpy(&pace_ctl, recvbuf+i+2, 4); - } - if (recvbuf[i] == FEATURE_MODIFY_PIN_DIRECT) { - memcpy(&modify_ctl, recvbuf+i+2, 4); - } - } - - if (0 == pace_ctl) { - printf("Reader does not support PACE\n"); - goto err; - } - /* convert to host byte order to use for SCardControl */ - pace_ctl = ntohl(pace_ctl); - modify_ctl = ntohl(modify_ctl); - -#define TESTPACE 1 -#ifdef TESTPACE - recvlen = sizeof(recvbuf); - sendbuf[0] = 0x01; /* idxFunction = GetReadersPACECapabilities */ - sendbuf[1] = 0x00; /* lengthInputData */ - sendbuf[2] = 0x00; /* lengthInputData */ - r = SCardControl(hCard, pace_ctl, - sendbuf, 3, - recvbuf, sizeof(recvbuf), &recvlen); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "Could not get reader's PACE capabilities\n"); - goto err; - } - printb("ReadersPACECapabilities ", recvbuf, recvlen); - - - recvlen = sizeof(recvbuf); - sendbuf[0] = 0x02; /* idxFunction = EstabishPACEChannel */ - sendbuf[1] = (5+pinlen+chatlen)&0xff; /* lengthInputData */ - sendbuf[2] = (5+pinlen+chatlen)>>8; /* lengthInputData */ - sendbuf[3] = secret_type; - sendbuf[4] = chatlen; /* length CHAT */ - memcpy(sendbuf+5, chat, chatlen); /* CHAT */ - sendbuf[5+chatlen] = pinlen; /* length PIN */ - memcpy(sendbuf+6+chatlen, pin, pinlen); /* PIN */ - sendbuf[6+pinlen+chatlen] = 0x00; /* length certificate description */ - sendbuf[7+pinlen+chatlen] = 0x00; /* length certificate description */ - - printb("EstablishPACEChannel InBuffer\n", sendbuf, 8+pinlen+chatlen); - t_start = time(NULL); - r = SCardControl(hCard, pace_ctl, - sendbuf, 8+pinlen+chatlen, - recvbuf, sizeof(recvbuf), &recvlen); - t_end = time(NULL); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "Could not establish PACE channel\n"); - goto err; - } - printf("EstablishPACEChannel successfull, received %d bytes\n", - (int)recvlen); - - r = parse_EstablishPACEChannel_OutputData(recvbuf, recvlen); - if (r != SCARD_S_SUCCESS) { - printb("EstablishPACEChannel OutBuffer\n", recvbuf, recvlen); - goto err; - } - - printf("Established PACE channel returned in %.0fs.\n", - difftime(t_end, t_start)); -#endif - - -#ifdef SIMULATE_TA_CA - r = SCardReconnect(hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_ANY, - SCARD_LEAVE_CARD, &protocol); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "Could not reconnect\n"); - goto err; - } - BYTE bufs1[] = { - 0x00, 0x22, 0x81, 0xB6, 0x0F, 0x83, 0x0D, 0x5A, 0x5A, 0x43, 0x56, 0x43, 0x41, 0x41, 0x54, 0x41, 0x30, 0x30, 0x30, 0x31, - 0x00, 0x2A, 0x00, 0xBE, 0xE4, 0x7F, 0x4E, 0x81, 0x9D, 0x5F, 0x29, 0x01, 0x00, 0x42, 0x0D, 0x5A, 0x5A, 0x43, 0x56, 0x43, 0x41, 0x41, 0x54, 0x41, 0x30, 0x30, 0x30, 0x31, 0x7F, 0x49, 0x4F, 0x06, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03, 0x86, 0x41, 0x04, 0x52, 0xDD, 0x32, 0xEA, 0xFE, 0x1F, 0xBB, 0xB4, 0x00, 0x0C, 0xD9, 0xCE, 0x75, 0xF6, 0x66, 0x36, 0xCF, 0xCF, 0x1E, 0xDD, 0x44, 0xF7, 0xB1, 0xED, 0xAE, 0x25, 0xB8, 0x41, 0x93, 0xDA, 0x04, 0xA9, 0x1C, 0x77, 0xEE, 0x87, 0xF5, 0xC8, 0xF9, 0x59, 0xED, 0x27, 0x62, 0x00, 0xDE, 0x33, 0xAB, 0x57, 0x4C, 0xE9, 0x80, 0x11, 0x35, 0xFF, 0x44, 0x97, 0xA3, 0x71, 0x62, 0xB7, 0xC8, 0x54, 0x8A, 0x0C, 0x5F, 0x20, 0x0E, 0x5A, 0x5A, 0x44, 0x56, 0x43, 0x41, 0x41, 0x54, 0x41, 0x30, 0x30, 0x30, 0x30, 0x35, 0x7F, 0x4C, 0x12, 0x06, 0x09, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x03, 0x01, 0x02, 0x02, 0x53, 0x05, 0x70, 0x03, 0x01, 0xFF, 0xB7, 0x5F, 0x25, 0x06, 0x01, 0x00, 0x00, 0x06, 0x01, 0x01, 0x5F, 0x24, 0x06, 0x01, 0x00, 0x01, 0x00, 0x03, 0x01, 0x5F, 0x37, 0x40, 0x6F, 0x13, 0xAE, 0x9A, 0x6F, 0x4E, 0xDD, 0xB7, 0x83, 0x9F, 0xF3, 0xF0, 0x4D, 0x71, 0xE0, 0xDC, 0x37, 0x7B, 0xC4, 0xB0, 0x8F, 0xAD, 0x29, 0x5E, 0xED, 0x24, 0x1B, 0x52, 0x43, 0x28, 0xAD, 0x07, 0x30, 0xEB, 0x55, 0x34, 0x97, 0xB4, 0xFB, 0x66, 0xE9, 0xBB, 0x7A, 0xB9, 0x08, 0x15, 0xF0, 0x42, 0x73, 0xF0, 0x9E, 0x75, 0x1D, 0x7F, 0xD4, 0xB8, 0x61, 0x43, 0x9B, 0x4E, 0xE6, 0x53, 0x81, 0xC3, - 0x00, 0x22, 0x81, 0xB6, 0x10, 0x83, 0x0E, 0x5A, 0x5A, 0x44, 0x56, 0x43, 0x41, 0x41, 0x54, 0x41, 0x30, 0x30, 0x30, 0x30, 0x35, - 0x00, 0x2A, 0x00, 0xBE, 0x00, 0x01, 0x41, 0x7F, 0x4E, 0x81, 0xFA, 0x5F, 0x29, 0x01, 0x00, 0x42, 0x0E, 0x5A, 0x5A, 0x44, 0x56, 0x43, 0x41, 0x41, 0x54, 0x41, 0x30, 0x30, 0x30, 0x30, 0x35, 0x7F, 0x49, 0x4F, 0x06, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03, 0x86, 0x41, 0x04, 0x9B, 0xFE, 0x74, 0x15, 0xD7, 0x3C, 0x4A, 0x78, 0xD6, 0x0B, 0x2C, 0xC1, 0xBC, 0xA1, 0x1B, 0x6D, 0x5E, 0x52, 0x39, 0x69, 0xAC, 0xFB, 0x5B, 0x75, 0x6A, 0x3B, 0xE1, 0x55, 0x1B, 0x22, 0x23, 0x9C, 0x79, 0xAE, 0x36, 0x2B, 0x83, 0x8B, 0x00, 0x66, 0x99, 0x83, 0xC0, 0xCA, 0xF6, 0xED, 0x0C, 0x78, 0x1D, 0x40, 0x1C, 0x95, 0xD2, 0xB3, 0x28, 0x57, 0xDE, 0x8C, 0xE1, 0xB6, 0x19, 0xDA, 0xC4, 0xA7, 0x5F, 0x20, 0x0A, 0x5A, 0x5A, 0x53, 0x49, 0x54, 0x30, 0x30, 0x30, 0x4F, 0x34, 0x7F, 0x4C, 0x12, 0x06, 0x09, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x03, 0x01, 0x02, 0x02, 0x53, 0x05, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5F, 0x25, 0x06, 0x01, 0x00, 0x00, 0x09, 0x02, 0x01, 0x5F, 0x24, 0x06, 0x01, 0x00, 0x00, 0x09, 0x02, 0x06, 0x65, 0x5E, 0x73, 0x2D, 0x06, 0x09, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x03, 0x01, 0x03, 0x02, 0x80, 0x20, 0xB0, 0x2B, 0xAA, 0x51, 0xA9, 0x4F, 0xAC, 0x09, 0x54, 0xDF, 0x20, 0x4D, 0x61, 0xFE, 0x22, 0xDA, 0x1D, 0x40, 0x8D, 0x45, 0xDB, 0x4A, 0xA1, 0xD7, 0x0E, 0x60, 0x0D, 0xAD, 0x4F, 0xAF, 0x67, 0x99, 0x73, 0x2D, 0x06, 0x09, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x03, 0x01, 0x03, 0x01, 0x80, 0x20, 0xC7, 0x2E, 0x13, 0x58, 0x2F, 0x01, 0xBA, 0x06, 0x8D, 0xD1, 0xAA, 0xC2, 0x9A, 0x24, 0x28, 0xC0, 0xC5, 0x4A, 0xB9, 0xC2, 0x04, 0xFD, 0x53, 0xB3, 0xF1, 0x3E, 0x82, 0x90, 0xE2, 0x1E, 0x50, 0xF9, 0x5F, 0x37, 0x40, 0x83, 0xC5, 0xB4, 0x41, 0xFE, 0xC5, 0xB1, 0x8E, 0xFD, 0x1C, 0xAA, 0x4A, 0x11, 0xB8, 0xE1, 0xCE, 0xDE, 0x0A, 0x8B, 0x42, 0xD4, 0x42, 0xF0, 0x0D, 0x7F, 0x60, 0x4E, 0x42, 0x9F, 0x33, 0x9B, 0x4E, 0x3E, 0x6C, 0x06, 0xF9, 0xE7, 0x6A, 0x2D, 0xAA, 0x82, 0xC1, 0x72, 0x2E, 0xE1, 0x37, 0xA8, 0x90, 0x38, 0xB9, 0x69, 0xC6, 0x34, 0x56, 0x15, 0x81, 0xE6, 0xC2, 0x6D, 0x9F, 0x6F, 0xA7, 0x5C, 0x52, - 0x00, 0x22, 0x81, 0xA4, 0x53, 0x80, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03, 0x83, 0x0A, 0x5A, 0x5A, 0x53, 0x49, 0x54, 0x30, 0x30, 0x30, 0x4F, 0x34, 0x91, 0x20, 0x88, 0xE5, 0xF2, 0xC6, 0x11, 0x18, 0x0D, 0x0A, 0xC1, 0x0E, 0xBD, 0xE6, 0xFC, 0x2A, 0x5E, 0x62, 0x41, 0x79, 0xC0, 0xA5, 0x77, 0xC3, 0xE4, 0x88, 0x52, 0xDD, 0x81, 0xA4, 0xCD, 0xF7, 0x90, 0x51, 0x67, 0x17, 0x73, 0x15, 0x06, 0x09, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x03, 0x01, 0x04, 0x02, 0x53, 0x08, 0x32, 0x30, 0x31, 0x30, 0x30, 0x39, 0x32, 0x34, - 0x00, 0x84, 0x00, 0x00, 0x08, - 0x00, 0x82, 0x00, 0x00, 0x40, 0x0C, 0x9E, 0x7D, 0xB7, 0x2C, 0xB0, 0xFA, 0xEA, 0x15, 0xB0, 0x0F, 0xEC, 0xAE, 0x02, 0x57, 0x54, 0x64, 0x46, 0xA9, 0x39, 0x58, 0x62, 0x23, 0x9A, 0xF2, 0x40, 0xC3, 0xC2, 0x9E, 0x85, 0x7F, 0x84, 0x03, 0x34, 0x58, 0x17, 0x76, 0x0F, 0xE1, 0x3F, 0x65, 0x97, 0xF0, 0x4D, 0x2F, 0x73, 0x30, 0xB5, 0x90, 0x65, 0xF6, 0x8D, 0xF7, 0x1E, 0xF7, 0xFD, 0xEC, 0x86, 0x74, 0x3C, 0xDE, 0x28, 0x69, 0xDD, - 0x00, 0xA4, 0x00, 0x0C, 0x02, 0x3F, 0x00, - 0x00, 0xA4, 0x02, 0x0C, 0x02, 0x01, 0x1D, - 0x00, 0xB0, 0x00, 0x00, 0x80, - 0x00, 0xB0, 0x00, 0x80, 0x80, - 0x00, 0xB0, 0x01, 0x00, 0x80, - 0x00, 0xB0, 0x01, 0x80, 0x80, - 0x00, 0xB0, 0x02, 0x00, 0x80, - 0x00, 0xB0, 0x02, 0x80, 0x80, - 0x00, 0xB0, 0x03, 0x00, 0x80, - 0x00, 0xB0, 0x03, 0x80, 0x80, - 0x00, 0xB0, 0x04, 0x00, 0x80, - 0x00, 0xB0, 0x04, 0x80, 0x80, - 0x00, 0xB0, 0x05, 0x00, 0x80, - 0x00, 0xB0, 0x05, 0x80, 0x80, - 0x00, 0xB0, 0x06, 0x00, 0x80, - 0x00, 0xB0, 0x06, 0x80, 0x80, - 0x00, 0xB0, 0x07, 0x00, 0x80, - 0x00, 0xB0, 0x07, 0x80, 0x80, - 0x00, 0x22, 0x41, 0xA4, 0x0C, 0x80, 0x0A, 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x03, 0x02, 0x02, - 0x00, 0x86, 0x00, 0x00, 0x45, 0x7C, 0x43, 0x80, 0x41, 0x04, 0x23, 0x9E, 0x3D, 0x05, 0xEE, 0xB0, 0x59, 0x11, 0x7D, 0x30, 0xF8, 0x6A, 0xEB, 0x5A, 0xE7, 0xD1, 0x2E, 0x0E, 0xBF, 0x75, 0x88, 0x89, 0xC7, 0x91, 0x15, 0xF2, 0xA1, 0x3D, 0xC1, 0xBB, 0x57, 0x0A, 0x5C, 0xAD, 0x91, 0xA3, 0x84, 0x33, 0x7C, 0x09, 0xD1, 0xB7, 0x4B, 0xED, 0x1C, 0x0F, 0xF1, 0x95, 0xA7, 0xC3, 0xEA, 0x3A, 0x2C, 0xED, 0xF8, 0x6D, 0xDE, 0xF7, 0xB9, 0x5D, 0x1F, 0xD1, 0xB3, 0x5D, 0x00, - }; - LPBYTE buf1 = bufs1; - DWORD lens1[] = {20, 233, 21, 328, 88, 5, 69, 7, 7, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 17, 75}; - for (l = 0; l < sizeof(lens1)/sizeof(DWORD); l++) { - recvlen = sizeof(recvbuf); - r = pcsc_transmit(protocol, hCard, buf1, lens1[l], recvbuf, &recvlen); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, - "Simulation of Terminal and Chip Authentication failed\n"); - goto err; - } - buf1 += lens1[l]; - } - r = SCardReconnect(hCard, SCARD_SHARE_DIRECT, 0, SCARD_LEAVE_CARD, &protocol); - if (r != SCARD_S_SUCCESS) { - fprintf(stderr, "Could not reconnect\n"); - goto err; - } -#endif - -#define MODIFY_PIN 1 -#ifdef MODIFY_PIN - if (0 == modify_ctl) { - printf("Reader does not support MODIFY_PIN_DIRECT\n"); - goto err; - } - - BYTE bufs2[] = {0x15, 0x05, 0x82, 0x08, 0x00, 0x00, 0x00, 0x06, 0x06, - 0x01, 0x02, 0x02, 0x09, 0x04, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x00, 0x00, 0x2C, 0x02, 0x03, 0x00}; - recvlen = sizeof(recvbuf); - r = SCardControl(hCard, modify_ctl, bufs2, - sizeof bufs2, recvbuf, sizeof recvbuf, &recvlen); -#endif - -err: - stringify_error(r); - pcsc_disconnect(hContext, hCard, readers); - - exit(r == SCARD_S_SUCCESS ? 0 : 1); -} diff --git a/ccid/src/ccid.c b/ccid/src/ccid.c index b5fd3c6..211f789 100644 --- a/ccid/src/ccid.c +++ b/ccid/src/ccid.c @@ -36,6 +36,7 @@ #include static struct sm_ctx sctx; +#undef BUERGERCLIENT_WORKAROUND #ifdef BUERGERCLIENT_WORKAROUND static char *ef_cardaccess = NULL; static size_t ef_cardaccess_length = 0; @@ -133,6 +134,18 @@ detect_card_presence(void) } +void sm_stop() { +#ifdef WITH_PACE + sm_ctx_clear_free(&sctx); + memset(&sctx, 0, sizeof(sctx)); +#ifdef BUERGERCLIENT_WORKAROUND + free(ef_cardaccess); + ef_cardaccess = NULL; + ef_cardaccess_length = 0; +#endif +#endif +} + int ccid_initialize(int reader_id, const char *cdriver, int verbose) { int i; @@ -143,11 +156,7 @@ int ccid_initialize(int reader_id, const char *cdriver, int verbose) #ifdef WITH_PACE memset(&sctx, 0, sizeof(sctx)); -#ifdef BUERGERCLIENT_WORKAROUND - free(ef_cardaccess); - ef_cardaccess = NULL; - ef_cardaccess_length = 0; -#endif + sm_stop(); #endif return SC_SUCCESS; @@ -162,15 +171,7 @@ void ccid_shutdown() if (ctx) sc_release_context(ctx); -#ifdef WITH_PACE - sm_ctx_clear_free(&sctx); - memset(&sctx, 0, sizeof(sctx)); -#ifdef BUERGERCLIENT_WORKAROUND - free(ef_cardaccess); - ef_cardaccess = NULL; - ef_cardaccess_length = 0; -#endif -#endif + sm_stop(); } static int get_rapdu(sc_apdu_t *apdu, __u8 **buf, size_t *resplen) @@ -409,6 +410,7 @@ perform_PC_to_RDR_IccPowerOn(const __u8 *in, size_t inlen, __u8 **out, size_t *o sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Card is already powered on."); sc_result = SC_SUCCESS; } else { + sm_stop(); sc_result = sc_connect_card(reader, &card); #ifdef BUERGERCLIENT_WORKAROUND if (sc_result >= 0) { @@ -871,7 +873,6 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card, memset(&pace_input, 0, sizeof pace_input); memset(&pace_output, 0, sizeof pace_output); - pace_input.tr_version = EAC_TR_VERSION_2_02; if (!abDataOut || !abDataOutLen) { @@ -959,7 +960,7 @@ perform_PC_to_RDR_Secure_EstablishPACEChannel(sc_card_t *card, #endif sc_result = EstablishPACEChannel(NULL, card, pace_input, &pace_output, - &sctx); + &sctx, EAC_TR_VERSION_2_02); if (sc_result < 0) goto err; @@ -1098,34 +1099,21 @@ perform_PC_to_RDR_Secure_GetReadersPACECapabilities(__u8 **abDataOut, size_t *abDataOutLen) { int sc_result; - __u8 *result; + u8 *BitMap; if (!abDataOut || !abDataOutLen) return SC_ERROR_INVALID_ARGUMENTS; -#ifdef BUERGERCLIENT_WORKAROUND - result = realloc(*abDataOut, 1); -#else - result = realloc(*abDataOut, 2); -#endif - if (!result) + BitMap = realloc(*abDataOut, sizeof *BitMap); + if (!BitMap) return SC_ERROR_OUT_OF_MEMORY; - *abDataOut = result; + *abDataOut = BitMap; -#ifndef BUERGERCLIENT_WORKAROUND - *result = 1; - result++; - -#endif - sc_result = GetReadersPACECapabilities(result); + sc_result = GetReadersPACECapabilities(BitMap); if (sc_result < 0) return sc_result; -#ifdef BUERGERCLIENT_WORKAROUND - *abDataOutLen = 1; -#else - *abDataOutLee = 2; -#endif + *abDataOutLen = sizeof *BitMap; return SC_SUCCESS; } diff --git a/npa/Makefile.am.opensc b/npa/Makefile.am.opensc index 599a0e1..05b2613 100644 --- a/npa/Makefile.am.opensc +++ b/npa/Makefile.am.opensc @@ -24,8 +24,7 @@ libopensc_la_SOURCES = \ \ pkcs15.c pkcs15-cert.c pkcs15-data.c pkcs15-pin.c \ pkcs15-prkey.c pkcs15-pubkey.c pkcs15-sec.c \ - pkcs15-wrap.c pkcs15-algo.c pkcs15-cache.c pkcs15-syn.c \ - pkcs15-gemsafeV1.c \ + pkcs15-algo.c pkcs15-cache.c pkcs15-syn.c \ \ muscle.c muscle-filesystem.c \ \ @@ -45,7 +44,7 @@ libopensc_la_SOURCES = \ pkcs15-tcos.c pkcs15-esteid.c pkcs15-postecert.c pkcs15-gemsafeGPK.c \ pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \ pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c pkcs15-oberthur.c \ - pkcs15-itacns.c \ + pkcs15-itacns.c pkcs15-gemsafeV1.c \ compression.c p15card-helper.c if WIN32 libopensc_la_SOURCES += $(top_builddir)/win32/versioninfo.rc diff --git a/npa/configure.ac b/npa/configure.ac index 16d079b..508fd47 100644 --- a/npa/configure.ac +++ b/npa/configure.ac @@ -45,9 +45,9 @@ saved_CPPFLAGS="$CPPFLAGS" saved_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $OPENSSL_CFLAGS" LIBS="$LDFLAGS $OPENSC_LIBS $OPENSSL_LIBS" -AC_MSG_CHECKING([for sc_bytes2apdu]) -AC_TRY_LINK_FUNC(sc_bytes2apdu, [ AC_MSG_RESULT([yes]) ], - [ AC_MSG_ERROR([libopensc >= 0.12.1 not found, use ./configure OPENSC_LIBS=...]) ]) +AC_MSG_CHECKING([for sc_perform_pace]) +AC_TRY_LINK_FUNC(sc_perform_pace, [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_ERROR([libopensc with PACE (https://github.com/frankmorgner/OpenSC) not found, use ./configure OPENSC_LIBS=...]) ]) AC_CHECK_HEADERS(openssl/evp.h, [], [ AC_MSG_ERROR([openssl/evp.h not found, install OpenSSL or use ./configure OPENSSL_CFLAGS=...]) ]) AC_MSG_CHECKING([for EVP_read_pw_string_min]) diff --git a/npa/src/example.c b/npa/src/example.c index 56aed8f..c5a2ac3 100644 --- a/npa/src/example.c +++ b/npa/src/example.c @@ -23,7 +23,6 @@ * APDU encrypted and authenticated to the card using sm_transmit_apdu. */ #include #include -#include #include static int reader_num = -1; @@ -80,7 +79,7 @@ main (int argc, char **argv) pace_input.pin_length = pin ? strlen(pin) : 0; r = EstablishPACEChannel(NULL, card, pace_input, &pace_output, - &sctx); + &sctx, EAC_TR_VERSION_2_02); if (r < 0) goto err; printf("Established PACE channel with PIN.\n"); diff --git a/npa/src/npa-tool.c b/npa/src/npa-tool.c index d0aad5f..77025b0 100644 --- a/npa/src/npa-tool.c +++ b/npa/src/npa-tool.c @@ -198,7 +198,7 @@ int npa_translate_apdus(struct sm_ctx *sctx, sc_card_t *card, FILE *input) int main (int argc, char **argv) { - int r, oindex = 0; + int r, oindex = 0, tr_version = EAC_TR_VERSION_2_02; size_t channeldatalen; struct sm_ctx sctx, tmpctx; struct establish_pace_channel_input pace_input; @@ -299,7 +299,7 @@ main (int argc, char **argv) } break; case OPT_TRVERSION: - if (sscanf(optarg, "%d", (int *) &pace_input.tr_version) != 1) { + if (sscanf(optarg, "%d", (int *) &tr_version) != 1) { parse_error(argv[0], options, option_help, optarg, oindex); exit(2); } @@ -414,7 +414,7 @@ main (int argc, char **argv) npa_secret_name(pace_input.pin_id), pace_input.pin); r = EstablishPACEChannel(NULL, card, pace_input, &pace_output, - &sctx); + &sctx, tr_version); secret++; } while (0 > r && secret <= maxsecret); @@ -443,7 +443,7 @@ main (int argc, char **argv) pace_input.pin_length = 0; } r = EstablishPACEChannel(NULL, card, pace_input, &pace_output, - &tmpctx); + &tmpctx, tr_version); if (r < 0) goto err; printf("Established PACE channel with CAN.\n"); @@ -457,7 +457,7 @@ main (int argc, char **argv) pace_input.pin_length = 0; } r = EstablishPACEChannel(&tmpctx, card, pace_input, &pace_output, - &sctx); + &sctx, tr_version); if (r < 0) goto err; printf("Established PACE channel with PIN. PIN resumed.\n"); @@ -473,7 +473,7 @@ main (int argc, char **argv) pace_input.pin_length = 0; } r = EstablishPACEChannel(NULL, card, pace_input, &pace_output, - &sctx); + &sctx, tr_version); if (r < 0) goto err; printf("Established PACE channel with PUK.\n"); @@ -494,7 +494,7 @@ main (int argc, char **argv) pace_input.pin_length = 0; } r = EstablishPACEChannel(NULL, card, pace_input, &pace_output, - &sctx); + &sctx, tr_version); if (r < 0) goto err; printf("Established PACE channel with PIN.\n"); @@ -539,7 +539,7 @@ main (int argc, char **argv) } r = EstablishPACEChannel(NULL, card, pace_input, &pace_output, - &sctx); + &sctx, tr_version); if (r < 0) goto err; printf("Established PACE channel with %s.\n", diff --git a/npa/src/npa.c b/npa/src/npa.c index 30134d2..14b7cb3 100644 --- a/npa/src/npa.c +++ b/npa/src/npa.c @@ -973,7 +973,7 @@ get_psec(sc_card_t *card, const char *pin, size_t length_pin, enum s_type pin_id int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card, struct establish_pace_channel_input pace_input, struct establish_pace_channel_output *pace_output, - struct sm_ctx *sctx) + struct sm_ctx *sctx, enum eac_tr_version tr_version) { u8 *p = NULL; EAC_CTX *eac_ctx = NULL; @@ -1075,222 +1075,226 @@ int EstablishPACEChannel(struct sm_ctx *oldnpactx, sc_card_t *card, } } - if (!pace_output->ef_cardaccess_length || !pace_output->ef_cardaccess) { - r = get_ef_card_access(card, &pace_output->ef_cardaccess, - &pace_output->ef_cardaccess_length); - if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess."); + if (card->reader->capabilities & SC_READER_CAP_PACE) { + r = sc_perform_pace(card, &pace_input, pace_output); + } else { + if (!pace_output->ef_cardaccess_length || !pace_output->ef_cardaccess) { + r = get_ef_card_access(card, &pace_output->ef_cardaccess, + &pace_output->ef_cardaccess_length); + if (r < 0) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess."); + goto err; + } + } + bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "EF.CardAccess", pace_output->ef_cardaccess, + pace_output->ef_cardaccess_length); + + eac_ctx = EAC_CTX_new(); + if (!eac_ctx + || !EAC_CTX_init_ef_cardaccess(pace_output->ef_cardaccess, + pace_output->ef_cardaccess_length, eac_ctx)) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse EF.CardAccess."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; goto err; } - } - bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "EF.CardAccess", pace_output->ef_cardaccess, - pace_output->ef_cardaccess_length); - eac_ctx = EAC_CTX_new(); - if (!eac_ctx - || !EAC_CTX_init_ef_cardaccess(pace_output->ef_cardaccess, - pace_output->ef_cardaccess_length, eac_ctx)) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse EF.CardAccess."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } + eac_ctx->tr_version = tr_version; - eac_ctx->tr_version = pace_input.tr_version; + r = npa_mse_set_at(oldnpactx, card, eac_ctx->pace_ctx->protocol, pace_input.pin_id, + chat, &pace_output->mse_set_at_sw1, &pace_output->mse_set_at_sw2); + if (r < 0) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol proberties " + "(MSE: Set AT failed)."); + goto err; + } + enc_nonce = BUF_MEM_new(); + if (!enc_nonce) { + ssl_error(card->ctx); + r = SC_ERROR_OUT_OF_MEMORY; + goto err; + } + r = npa_gen_auth_1_encrypted_nonce(oldnpactx, card, (u8 **) &enc_nonce->data, + &enc_nonce->length); + if (r < 0) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get encrypted nonce from card " + "(General Authenticate step 1 failed)."); + goto err; + } + bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Encrypted nonce from MRTD", (u8 *)enc_nonce->data, enc_nonce->length); + enc_nonce->max = enc_nonce->length; - r = npa_mse_set_at(oldnpactx, card, eac_ctx->pace_ctx->protocol, pace_input.pin_id, - chat, &pace_output->mse_set_at_sw1, &pace_output->mse_set_at_sw2); - if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol proberties " - "(MSE: Set AT failed)."); - goto err; - } - enc_nonce = BUF_MEM_new(); - if (!enc_nonce) { - ssl_error(card->ctx); - r = SC_ERROR_OUT_OF_MEMORY; - goto err; - } - r = npa_gen_auth_1_encrypted_nonce(oldnpactx, card, (u8 **) &enc_nonce->data, - &enc_nonce->length); - if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get encrypted nonce from card " - "(General Authenticate step 1 failed)."); - goto err; - } - bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Encrypted nonce from MRTD", (u8 *)enc_nonce->data, enc_nonce->length); - enc_nonce->max = enc_nonce->length; + sec = get_psec(card, (char *) pace_input.pin, pace_input.pin_length, + pace_input.pin_id); + if (!sec) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encode PACE secret."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } - sec = get_psec(card, (char *) pace_input.pin, pace_input.pin_length, - pace_input.pin_id); - if (!sec) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encode PACE secret."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } + if (!PACE_STEP2_dec_nonce(eac_ctx, sec, enc_nonce)) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not decrypt MRTD's nonce."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } - if (!PACE_STEP2_dec_nonce(eac_ctx, sec, enc_nonce)) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not decrypt MRTD's nonce."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } + mdata_opp = BUF_MEM_new(); + mdata = PACE_STEP3A_generate_mapping_data(eac_ctx); + if (!mdata || !mdata_opp) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate mapping data."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } + r = npa_gen_auth_2_map_nonce(oldnpactx, card, (u8 *) mdata->data, mdata->length, + (u8 **) &mdata_opp->data, &mdata_opp->length); + if (r < 0) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange mapping data with card " + "(General Authenticate step 2 failed)."); + goto err; + } + mdata_opp->max = mdata_opp->length; + bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Mapping data from MRTD", (u8 *) mdata_opp->data, mdata_opp->length); - mdata_opp = BUF_MEM_new(); - mdata = PACE_STEP3A_generate_mapping_data(eac_ctx); - if (!mdata || !mdata_opp) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate mapping data."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } - r = npa_gen_auth_2_map_nonce(oldnpactx, card, (u8 *) mdata->data, mdata->length, - (u8 **) &mdata_opp->data, &mdata_opp->length); - if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange mapping data with card " - "(General Authenticate step 2 failed)."); - goto err; - } - mdata_opp->max = mdata_opp->length; - bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Mapping data from MRTD", (u8 *) mdata_opp->data, mdata_opp->length); + if (!PACE_STEP3A_map_generator(eac_ctx, mdata_opp)) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not map generator."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } - if (!PACE_STEP3A_map_generator(eac_ctx, mdata_opp)) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not map generator."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } + pub = PACE_STEP3B_generate_ephemeral_key(eac_ctx); + pub_opp = BUF_MEM_new(); + if (!pub || !pub_opp) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate ephemeral domain parameter or " + "ephemeral key pair."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } + r = npa_gen_auth_3_perform_key_agreement(oldnpactx, card, (u8 *) pub->data, pub->length, + (u8 **) &pub_opp->data, &pub_opp->length); + if (r < 0) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange ephemeral public key with card " + "(General Authenticate step 3 failed)."); + goto err; + } + pub_opp->max = pub_opp->length; + bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Ephemeral public key from MRTD", (u8 *) pub_opp->data, pub_opp->length); - pub = PACE_STEP3B_generate_ephemeral_key(eac_ctx); - pub_opp = BUF_MEM_new(); - if (!pub || !pub_opp) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate ephemeral domain parameter or " - "ephemeral key pair."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } - r = npa_gen_auth_3_perform_key_agreement(oldnpactx, card, (u8 *) pub->data, pub->length, - (u8 **) &pub_opp->data, &pub_opp->length); - if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange ephemeral public key with card " - "(General Authenticate step 3 failed)."); - goto err; - } - pub_opp->max = pub_opp->length; - bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Ephemeral public key from MRTD", (u8 *) pub_opp->data, pub_opp->length); - - if (!PACE_STEP3B_compute_shared_secret(eac_ctx, pub_opp) - || !PACE_STEP3C_derive_keys(eac_ctx)) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute ephemeral shared secret or " - "derive keys for encryption and authentication."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } - token = PACE_STEP3D_compute_authentication_token(eac_ctx, pub_opp); - token_opp = BUF_MEM_new(); - if (!token || !token_opp) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute authentication token."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } - r = npa_gen_auth_4_mutual_authentication(oldnpactx, card, (u8 *) token->data, token->length, - (u8 **) &token_opp->data, &token_opp->length, - &pace_output->recent_car, &pace_output->recent_car_length, - &pace_output->previous_car, &pace_output->previous_car_length); + if (!PACE_STEP3B_compute_shared_secret(eac_ctx, pub_opp) + || !PACE_STEP3C_derive_keys(eac_ctx)) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute ephemeral shared secret or " + "derive keys for encryption and authentication."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } + token = PACE_STEP3D_compute_authentication_token(eac_ctx, pub_opp); + token_opp = BUF_MEM_new(); + if (!token || !token_opp) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute authentication token."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } + r = npa_gen_auth_4_mutual_authentication(oldnpactx, card, (u8 *) token->data, token->length, + (u8 **) &token_opp->data, &token_opp->length, + &pace_output->recent_car, &pace_output->recent_car_length, + &pace_output->previous_car, &pace_output->previous_car_length); - if (r < 0) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange authentication token with card " - "(General Authenticate step 4 failed)."); - goto err; - } - token_opp->max = token_opp->length; + if (r < 0) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange authentication token with card " + "(General Authenticate step 4 failed)."); + goto err; + } + token_opp->max = token_opp->length; - if (!PACE_STEP3D_verify_authentication_token(eac_ctx, token_opp)) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not verify authentication token."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } + if (!PACE_STEP3D_verify_authentication_token(eac_ctx, token_opp)) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not verify authentication token."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } - /* Initialize secure channel */ - if (!EAC_CTX_set_encryption_ctx(eac_ctx, EAC_ID_PACE)) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize encryption."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } + /* Initialize secure channel */ + if (!EAC_CTX_set_encryption_ctx(eac_ctx, EAC_ID_PACE)) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize encryption."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } - /* Identifier for ICC and PCD */ - comp_pub = EAC_Comp(eac_ctx, EAC_ID_PACE, pub); - comp_pub_opp = EAC_Comp(eac_ctx, EAC_ID_PACE, pub_opp); - if (!comp_pub || !comp_pub_opp) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compress public keys for identification."); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } - p = realloc(pace_output->id_icc, comp_pub_opp->length); - if (!p) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID ICC.\n"); - r = SC_ERROR_OUT_OF_MEMORY; - goto err; - } - pace_output->id_icc = p; - pace_output->id_icc_length = comp_pub_opp->length; - /* Flawfinder: ignore */ - memcpy(pace_output->id_icc, comp_pub_opp->data, comp_pub_opp->length); - bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ID ICC", pace_output->id_icc, - pace_output->id_icc_length); - p = realloc(pace_output->id_pcd, comp_pub->length); - if (!p) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID PCD.\n"); - r = SC_ERROR_OUT_OF_MEMORY; - goto err; - } - pace_output->id_pcd = p; - pace_output->id_pcd_length = comp_pub->length; - /* Flawfinder: ignore */ - memcpy(pace_output->id_pcd, comp_pub->data, comp_pub->length); - bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ID PCD", pace_output->id_pcd, - pace_output->id_pcd_length); + /* Identifier for ICC and PCD */ + comp_pub = EAC_Comp(eac_ctx, EAC_ID_PACE, pub); + comp_pub_opp = EAC_Comp(eac_ctx, EAC_ID_PACE, pub_opp); + if (!comp_pub || !comp_pub_opp) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compress public keys for identification."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } + p = realloc(pace_output->id_icc, comp_pub_opp->length); + if (!p) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID ICC.\n"); + r = SC_ERROR_OUT_OF_MEMORY; + goto err; + } + pace_output->id_icc = p; + pace_output->id_icc_length = comp_pub_opp->length; + /* Flawfinder: ignore */ + memcpy(pace_output->id_icc, comp_pub_opp->data, comp_pub_opp->length); + bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ID ICC", pace_output->id_icc, + pace_output->id_icc_length); + p = realloc(pace_output->id_pcd, comp_pub->length); + if (!p) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID PCD.\n"); + r = SC_ERROR_OUT_OF_MEMORY; + goto err; + } + pace_output->id_pcd = p; + pace_output->id_pcd_length = comp_pub->length; + /* Flawfinder: ignore */ + memcpy(pace_output->id_pcd, comp_pub->data, comp_pub->length); + bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "ID PCD", pace_output->id_pcd, + pace_output->id_pcd_length); - if(pace_output->recent_car && pace_output->recent_car_length - && !EAC_CTX_init_ta(eac_ctx, NULL, 0, NULL, 0, - pace_output->recent_car, pace_output->recent_car_length)) { - sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize TA.\n"); - ssl_error(card->ctx); - r = SC_ERROR_INTERNAL; - goto err; - } - eac_ctx->ta_ctx->flags |= TA_FLAG_SKIP_TIMECHECK; + if(pace_output->recent_car && pace_output->recent_car_length + && !EAC_CTX_init_ta(eac_ctx, NULL, 0, NULL, 0, + pace_output->recent_car, pace_output->recent_car_length)) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize TA.\n"); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } + eac_ctx->ta_ctx->flags |= TA_FLAG_SKIP_TIMECHECK; - sctx->priv_data = npa_sm_ctx_create(eac_ctx, - pace_input.certificate_description, - pace_input.certificate_description_length, - pace_output->id_icc, - pace_output->id_icc_length, - pace_output->recent_car, - pace_output->recent_car_length); - if (!sctx->priv_data) { - r = SC_ERROR_OUT_OF_MEMORY; - goto err; + sctx->priv_data = npa_sm_ctx_create(eac_ctx, + pace_input.certificate_description, + pace_input.certificate_description_length, + pace_output->id_icc, + pace_output->id_icc_length, + pace_output->recent_car, + pace_output->recent_car_length); + if (!sctx->priv_data) { + r = SC_ERROR_OUT_OF_MEMORY; + goto err; + } + sctx->authenticate = npa_sm_authenticate; + sctx->encrypt = npa_sm_encrypt; + sctx->decrypt = npa_sm_decrypt; + sctx->verify_authentication = npa_sm_verify_authentication; + sctx->pre_transmit = npa_sm_pre_transmit; + sctx->post_transmit = npa_sm_post_transmit; + sctx->finish = npa_sm_finish; + sctx->clear_free = npa_sm_clear_free; + sctx->padding_indicator = SM_ISO_PADDING; + sctx->block_length = EVP_CIPHER_block_size(eac_ctx->key_ctx->cipher); + sctx->active = 1; } - sctx->authenticate = npa_sm_authenticate; - sctx->encrypt = npa_sm_encrypt; - sctx->decrypt = npa_sm_decrypt; - sctx->verify_authentication = npa_sm_verify_authentication; - sctx->pre_transmit = npa_sm_pre_transmit; - sctx->post_transmit = npa_sm_post_transmit; - sctx->finish = npa_sm_finish; - sctx->clear_free = npa_sm_clear_free; - sctx->padding_indicator = SM_ISO_PADDING; - sctx->block_length = EVP_CIPHER_block_size(eac_ctx->key_ctx->cipher); - sctx->active = 1; err: if (enc_nonce) diff --git a/npa/src/npa/npa.h b/npa/src/npa/npa.h index 207d165..72c5619 100644 --- a/npa/src/npa/npa.h +++ b/npa/src/npa/npa.h @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -107,70 +106,6 @@ extern "C" { const char *npa_secret_name(enum s_type pin_id); -/** - * Input data for EstablishPACEChannel() - */ -struct establish_pace_channel_input { - /** Version of TR-03110 to use with PACE */ - enum eac_tr_version tr_version; - - /** Type of secret (CAN, MRZ, PIN or PUK). You may use enum s_type from \c */ - unsigned char pin_id; - - /** Length of \a chat */ - size_t chat_length; - /** Card holder authorization template */ - const unsigned char *chat; - - /** Length of \a pin */ - size_t pin_length; - /** Secret */ - const unsigned char *pin; - - /** Length of \a certificate_description */ - size_t certificate_description_length; - /** Certificate description */ - const unsigned char *certificate_description; -}; - -/** - * Output data for EstablishPACEChannel() - */ -struct establish_pace_channel_output { - /** PACE result (TR-03119) */ - unsigned int result; - - /** MSE: Set AT status byte */ - unsigned char mse_set_at_sw1; - /** MSE: Set AT status byte */ - unsigned char mse_set_at_sw2; - - /** Length of \a ef_cardaccess */ - size_t ef_cardaccess_length; - /** EF.CardAccess */ - unsigned char *ef_cardaccess; - - /** Length of \a recent_car */ - size_t recent_car_length; - /** Most recent certificate authority reference */ - unsigned char *recent_car; - - /** Length of \a previous_car */ - size_t previous_car_length; - /** Previous certificate authority reference */ - unsigned char *previous_car; - - /** Length of \a id_icc */ - size_t id_icc_length; - /** ICC identifier */ - unsigned char *id_icc; - - /** Length of \a id_pcd */ - size_t id_pcd_length; - /** PCD identifier */ - unsigned char *id_pcd; -}; - #ifdef BUERGERCLIENT_WORKAROUND int get_ef_card_access(sc_card_t *card, u8 **ef_cardaccess, size_t *length_ef_cardaccess); @@ -203,13 +138,14 @@ int GetReadersPACECapabilities(u8 *bitmap); * @param[in] pace_input * @param[in,out] pace_output * @param[out] sctx + * @param[in] tr_version Version of TR-03110 to use with PACE * * @return \c SC_SUCCESS or error code if an error occurred */ int EstablishPACEChannel(struct sm_ctx *oldpacectx, sc_card_t *card, struct establish_pace_channel_input pace_input, struct establish_pace_channel_output *pace_output, - struct sm_ctx *sctx); + struct sm_ctx *sctx, enum eac_tr_version tr_version); /** * @brief Sends a reset retry counter APDU