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
This commit is contained in:
@@ -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 <reader.h>])
|
||||
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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <winscard.h>
|
||||
#include <time.h>
|
||||
|
||||
#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 <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PCSCLITE_H
|
||||
#include <pcsclite.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_READER_H
|
||||
#include <reader.h>
|
||||
#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);
|
||||
}
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <npa/scutil.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
* APDU encrypted and authenticated to the card using sm_transmit_apdu. */
|
||||
#include <npa/npa.h>
|
||||
#include <npa/scutil.h>
|
||||
#include <openssl/pace.h>
|
||||
#include <string.h>
|
||||
|
||||
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");
|
||||
|
||||
@@ -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",
|
||||
|
||||
402
npa/src/npa.c
402
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)
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include <npa/sm.h>
|
||||
#include <libopensc/opensc.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/eac.h>
|
||||
#include <openssl/pace.h>
|
||||
|
||||
@@ -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 <tt>enum s_type</tt> from \c <openssl/pace.h> */
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user