From 74ec7b04ffda539819eb8bfd6a0e766e69d8c946 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Thu, 23 Mar 2017 16:45:31 +0100 Subject: [PATCH] sc-hsm: Add support for SoC - eac: allow CA without EF.CardSecurity - sc-hsm: implemented CA based on document PKI - sc-hsm: adds receive limit for SoC card - introduces dedicated card type for SoC card - md: integrate card's PIN pad capabilities - installer: added SC-HSM SoC card to registry - pkcs15-tool: Added support for PIN entry on card - change/unblock PIN: add support for PIN entry on card - added OpenPACE to macOS build - travis-ci: install gengetopt/help2man via brew - sc-hsm: Cache EF.C_DevAut - sc-hsm: Prevent unnecessary applet selection and state resets - sc-hsm: added support for session pin - sc-hsm: avoid multiple AID selection - sc-hsm: Use the information from match_card for all subsequent selections of the applet - sc-hsm: cache optional files as empty files (Decoding the files will reveal that they were not existing prior caching. This avoids selecting the file though we have already tried to cache the file before.) - use dedicated directory for CVC trust anchors - appveyor: added OpenPACE to windows build --- .travis.yml | 3 +- MacOSX/build-package.in | 15 + appveyor.yml | 15 +- configure.ac | 22 +- etc/DESRCACC100001 | Bin 0 -> 441 bytes etc/Makefile.am | 13 +- etc/UTSRCACC100001 | Bin 0 -> 441 bytes src/libopensc/Makefile.am | 4 +- src/libopensc/Makefile.mak | 1 + src/libopensc/card-sc-hsm.c | 626 ++++++++++++++++++++++++++++++---- src/libopensc/card-sc-hsm.h | 3 + src/libopensc/cards.h | 1 + src/libopensc/ctx.c | 2 +- src/libopensc/iso7816.c | 2 + src/libopensc/opensc.h | 7 + src/libopensc/pkcs15-pin.c | 17 +- src/libopensc/pkcs15-sc-hsm.c | 88 ++++- src/libopensc/pkcs15-syn.c | 1 + src/libopensc/types.h | 1 + src/minidriver/Makefile.mak | 2 +- src/minidriver/minidriver.c | 21 +- src/pkcs11/Makefile.mak | 6 +- src/pkcs11/framework-pkcs15.c | 8 +- src/sm/sm-eac.c | 63 +++- src/sm/sm-eac.h | 2 + src/smm/Makefile.mak | 2 +- src/tools/npa-tool.c | 2 +- src/tools/pkcs15-tool.c | 6 +- win32/Make.rules.mak | 7 +- win32/OpenSC.wxs.in | 14 + win32/customactions.cpp | 2 + win32/winconfig.h.in | 4 + 32 files changed, 833 insertions(+), 127 deletions(-) create mode 100644 etc/DESRCACC100001 create mode 100644 etc/UTSRCACC100001 diff --git a/.travis.yml b/.travis.yml index 9942ca5d..28734919 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ addons: - wine - xsltproc - gengetopt + - help2man coverity_scan: project: name: "OpenSC/OpenSC" @@ -51,7 +52,7 @@ before_install: brew update; brew uninstall libtool; brew install libtool; - brew install gengetopt; + brew install gengetopt help2man; fi before_script: diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index 551d6ca0..e0ab9fb3 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -40,9 +40,24 @@ if ! pkg-config libcrypto --atleast-version=1.0.1; then export OPENSSL_LIBS="` env PKG_CONFIG_PATH=$BUILDPATH/openssl_bin/$PREFIX/lib/pkgconfig PKG_CONFIG_SYSROOT_DIR=$BUILDPATH/openssl_bin pkg-config --static --libs libcrypto`" fi +if ! test -e $BUILDPATH/openpace_bin/$PREFIX/lib/pkgconfig; then + if ! test -e openpace; then + git clone --depth=1 https://github.com/frankmorgner/openpace.git + fi + cd openpace + autoreconf -vis + ./configure --disable-shared --prefix=$PREFIX CRYPTO_CFLAGS="$OPENSSL_CFLAGS" CRYPTO_LIBS="$OPENSSL_LIBS" + make DESTDIR=$BUILDPATH/openpace_bin install + cd .. + export OPENPACE_CFLAGS="`env PKG_CONFIG_PATH=$BUILDPATH/openpace_bin/$PREFIX/lib/pkgconfig PKG_CONFIG_SYSROOT_DIR=$BUILDPATH/openpace_bin pkg-config --static --cflags libeac` $OPENSSL_CFLAGS" + export OPENPACE_LIBS="` env PKG_CONFIG_PATH=$BUILDPATH/openpace_bin/$PREFIX/lib/pkgconfig PKG_CONFIG_SYSROOT_DIR=$BUILDPATH/openpace_bin pkg-config --static --libs libeac` $OPENSSL_LIBS" +fi + if ! test -e ${BUILDPATH}/target/$PREFIX/lib/pkgconfig; then ./configure --prefix=$PREFIX \ --sysconfdir=$PREFIX/etc \ + --enable-cvcdir=$PREFIX/etc/cvc \ + --enable-x509dir=$PREFIX/etc/x509 \ --disable-dependency-tracking \ --enable-shared \ --disable-static \ diff --git a/appveyor.yml b/appveyor.yml index a599e528..ae8c3308 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -30,6 +30,7 @@ install: - date /T & time /T - set PATH=C:\cygwin\bin;%PATH% - set OPENSSL_VER=1_0_2e + - set OPENPACE_VER=1.0.1 - set ZLIB_VER_DOT=1.2.8 - ps: $env:PACKAGE_NAME=(git describe --tags) - ps: >- @@ -62,6 +63,11 @@ install: } 7z x zlib.zip -oC:\ Rename-Item -path "c:\zlib-${env:ZLIB_VER_DOT}" -newName "zlib" + If (!(Test-Path openpace.zip )) { + appveyor DownloadFile "https://github.com/frankmorgner/openpace/archive/${env:OPENPACE_VER}.zip" -FileName openpace.zip + } + 7z x openpace.zip -oC:\ + Rename-Item -path "c:\openpace-${env:OPENPACE_VER}" -newName "openpace" } - ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) - echo "Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS%" @@ -72,9 +78,9 @@ install: - set build_script: - # build zlib.lib as a static library - ps: >- if (!($env:Configuration -Like "*Light*")) { + # build zlib.lib as a static library cd C:\zlib (Get-Content win32/Makefile.msc).replace('-MD', '-MT') | Set-Content win32/Makefile.msc If ($env:Platform -Match "x86") { @@ -83,7 +89,12 @@ build_script: nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." OBJA="inffasx64.obj gvmat64.obj inffas8664.obj" zlib.lib } $env:NMAKE_EXTRA="ZLIBSTATIC_DEF=/DENABLE_ZLIB_STATIC ${env:NMAKE_EXTRA}" - cd c:\projects\Opensc + # build libeac.lib as a static library + cd C:\openpace\src + cl /IC:\OpenSSL-${env:OPENSSL_PF}\include /I. /DX509DIR=\`"/\`" /DCVCDIR=\`"/\`" /W3 /D_CRT_SECURE_NO_DEPRECATE /DWIN32_LEAN_AND_MEAN /GS /MT /c ca_lib.c cv_cert.c cvc_lookup.c x509_lookup.c eac_asn1.c eac.c eac_ca.c eac_dh.c eac_ecdh.c eac_kdf.c eac_lib.c eac_print.c eac_util.c misc.c pace.c pace_lib.c pace_mappings.c ri.c ri_lib.c ta.c ta_lib.c objects.c + lib /out:libeac.lib ca_lib.obj cv_cert.obj cvc_lookup.obj x509_lookup.obj eac_asn1.obj eac.obj eac_ca.obj eac_dh.obj eac_ecdh.obj eac_kdf.obj eac_lib.obj eac_print.obj eac_util.obj misc.obj pace.obj pace_lib.obj pace_mappings.obj ri.obj ri_lib.obj ta.obj ta_lib.obj objects.obj + $env:NMAKE_EXTRA="OPENPACE_DEF=/DENABLE_OPENPACE ${env:NMAKE_EXTRA}" + cd C:\projects\OpenSC } - bash -c "exec 0-vwv!fm}boPhv%}-+>!X-!@jM>k)`|6x}B%%!cXgX zd+7gZ+`fM2J@to=_bMNzq+iNZk+9!?%w7o&Lj3N+ePC@W#1>r@ik5N2wUFf$dbzx)u48EmrA_Aed(f?9sK`Ga#uSn zv9gWHe*LMO{V;#-t0HH<#~RgasRv&zd$r`3+L2^t2Fd0h+80+DKCoSo)XvBluYew8 zJ_2mq+H8z0jE#ronHd>_84tv(vN19-GBR++tFSSH7##8D4s&-~Xp0M8+O=lGG36^f zN$D51YA*>rARlIIdot8RVCSax-u3eiuU$B&nk}}1H)oEG-nskNdtXbecPQ_=-}xf( F6aWF^xNiUe literal 0 HcmV?d00001 diff --git a/etc/Makefile.am b/etc/Makefile.am index fcd2286c..e4183e61 100644 --- a/etc/Makefile.am +++ b/etc/Makefile.am @@ -1,7 +1,9 @@ +CV_CERTS = UTSRCACC100001 DESRCACC100001 + MAINTAINERCLEANFILES = $(srcdir)/Makefile.in DISTCLEANFILES = opensc.conf -EXTRA_DIST = Makefile.mak +EXTRA_DIST = $(CV_CERTS) Makefile.mak SUFFIXES = .in @@ -38,3 +40,12 @@ install-exec-hook: opensc.conf uninstall-hook: opensc.conf rm -f "$(DESTDIR)$(sysconfdir)/opensc.conf.new" "$(DESTDIR)$(sysconfdir)/opensc.conf" + +if ENABLE_OPENPACE +install-data-local: + $(MKDIR_P) "$(DESTDIR)$(CVCDIR)" + for cert in $(CV_CERTS); do $(INSTALL_DATA) $(srcdir)/$${cert} "$(DESTDIR)$(CVCDIR)"; done + +uninstall-local: + for cert in $(CV_CERTS); do rm -f "$(DESTDIR)$(CVCDIR)/$${cert}"; done +endif diff --git a/etc/UTSRCACC100001 b/etc/UTSRCACC100001 new file mode 100644 index 0000000000000000000000000000000000000000..4f0621a2cdeac99bbf0e7a7bf1cbc0180fb34e78 GIT binary patch literal 441 zcmb-vwv!fm}boPhv%}-+>!X-!@jM>k)`|6x}B%%!cXgX zd+7gZ+`fM2J@to=_bMNzq+iNZk+9!?%w7o&Lj3N+ePC@W#1>r@ik5N2wUFf$g;rk-=@EU*;*IpEZhF-Y~jgH{VCEr zdeiT`JE_X}p@2~`{E?#4t{k1O|CuJ|d+3=i6Pj~+SKs93=3GOz_BjrHAKDoi;}y_@ z%twHYTbqrMg|YFlJToI>Fyn!ERW?Q@Mn(qCcojBg5Q8J$++m{cgdrv_data; + sc_file_t *file = NULL; + sc_path_t cpath; + + if (file_out == NULL) { // Versions before 0.16 of the SmartCard-HSM do not support P2='0C' + rv = sc_hsm_select_file_ex(card, in_path, forceselect, &file); + if (file != NULL) { + sc_file_free(file); + } + return rv; + } + + if ((in_path->type == SC_PATH_TYPE_FILE_ID) && in_path->aid.len) { + // Split applet selection and file selection into two separate calls + cpath = *in_path; + cpath.len = 0; + cpath.type = SC_PATH_TYPE_DF_NAME; + rv = sc_hsm_select_file_ex(card, &cpath, forceselect, NULL); + LOG_TEST_RET(card->ctx, rv, "Could not select SmartCard-HSM application"); + + if (in_path->len) { + cpath = *in_path; + cpath.aid.len = 0; + rv = sc_hsm_select_file_ex(card, &cpath, forceselect, file_out); + } + return rv; + } + + // Prevent selection of applet unless this is the first time, selection is forced or the device is not authenticated + if (in_path->type == SC_PATH_TYPE_DF_NAME + || (in_path->type == SC_PATH_TYPE_PATH + && in_path->len == sc_hsm_aid.len + && !memcmp(in_path->value, sc_hsm_aid.value, sc_hsm_aid.len)) + || (in_path->type == SC_PATH_TYPE_PATH + && in_path->len == 0 + && in_path->aid.len == sc_hsm_aid.len + && !memcmp(in_path->aid.value, sc_hsm_aid.value, sc_hsm_aid.len))) { + if ((priv->dffcp == NULL) || forceselect) { + rv = (*iso_ops->select_file)(card, in_path, file_out); + LOG_TEST_RET(card->ctx, rv, "Could not select SmartCard-HSM application"); + + if (priv->dffcp != NULL) { + sc_file_free(priv->dffcp); + } + // Cache the FCP returned when selecting the applet + sc_file_dup(&priv->dffcp, *file_out); + } else { + sc_file_dup(file_out, priv->dffcp); + rv = SC_SUCCESS; + } + return rv; + } + + if ((in_path->value[0] == 0x3F) && (in_path->value[1] == 0x00)) { + // The SmartCard-HSM is an applet that is not default selected. Simulate selection of the MF + if (in_path->len == 2) { + file = sc_file_new(); + if (file == NULL) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + file->path = *in_path; + file->id = 0x3F00; + file->type = SC_FILE_TYPE_DF; + file->magic = SC_FILE_MAGIC; + + *file_out = file; + return SC_SUCCESS; + } else { + sc_path_t truncated; + memcpy(&truncated, in_path, sizeof truncated); + truncated.len = in_path->len - 2; + memcpy(truncated.value, in_path->value+2, truncated.len); + return (*iso_ops->select_file)(card, &truncated, file_out); + } + } + return (*iso_ops->select_file)(card, in_path, file_out); +} + + + static int sc_hsm_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out) { - int rv; - sc_file_t *file = NULL; - - if (file_out == NULL) { // Versions before 0.16 of the SmartCard-HSM do not support P2='0C' - rv = sc_hsm_select_file(card, in_path, &file); - sc_file_free(file); - return rv; - } - - if ((in_path->len == 2) && (in_path->value[0] == 0x3F) && (in_path->value[1] == 0x00)) { - // The SmartCard-HSM is an applet that is not default selected. Simulate selection of the MF - file = sc_file_new(); - if (file == NULL) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); - file->path = *in_path; - file->id = 0x3F00; - file->type = SC_FILE_TYPE_DF; - file->magic = SC_FILE_MAGIC; - - *file_out = file; - return SC_SUCCESS; - } - return (*iso_ops->select_file)(card, in_path, file_out); + return sc_hsm_select_file_ex(card, in_path, 0, file_out); } static int sc_hsm_match_card(struct sc_card *card) { + sc_hsm_private_data_t *priv; sc_path_t path; int i, r; @@ -121,10 +185,44 @@ static int sc_hsm_match_card(struct sc_card *card) if (i < 0) return 0; + priv = calloc(1, sizeof(sc_hsm_private_data_t)); + if (!priv) + LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); + + card->drv_data = priv; + sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); - r = sc_hsm_select_file(card, &path, NULL); + r = (*iso_ops->select_file)(card, &path, &priv->dffcp); LOG_TEST_RET(card->ctx, r, "Could not select SmartCard-HSM application"); + if (priv->dffcp) { + if (priv->dffcp->prop_attr && priv->dffcp->prop_attr_len >= 5) { + static char card_name[SC_MAX_APDU_BUFFER_SIZE]; + u8 type = priv->dffcp->prop_attr[2]; + u8 major = priv->dffcp->prop_attr[3]; + u8 minor = priv->dffcp->prop_attr[4]; + char p00[] = "SmartCard-HSM Applet for JCOP"; + char p01[] = "SmartCard-HSM Demo Applet for JCOP"; + char *p = "SmartCard-HSM"; + switch (type) { + case 0x00: + p = p00; + break; + case 0x01: + p = p01; + break; + default: + break; + } + snprintf(card_name, sizeof card_name, "%s version %u.%u", p, major, minor); + card->name = card_name; + + if (priv->dffcp->prop_attr[1] & 0x04) { + card->caps |= SC_CARD_CAP_SESSION_PIN; + } + } + } + // Select Applet to be sure return 1; } @@ -162,6 +260,258 @@ static int sc_hsm_encode_sopin(const u8 *sopin, u8 *sopinbin) } +static int sc_hsm_soc_select_minbioclient(sc_card_t *card) +{ + sc_apdu_t apdu; + struct sc_aid minBioClient_aid = { + { 0xFF,'m','i','n','B','i','o','C','l','i','e','n','t',0x01 }, 14 + }; + + /* Select MinBioClient */ + sc_sm_stop(card); + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C); + apdu.data = minBioClient_aid.value; + apdu.datalen = minBioClient_aid.len; + apdu.lc = minBioClient_aid.len; + LOG_TEST_RET(card->ctx, + sc_transmit_apdu(card, &apdu), + "APDU transmit failed"); + + return sc_check_sw(card, apdu.sw1, apdu.sw2); +} + +static int sc_hsm_soc_change(sc_card_t *card, struct sc_pin_cmd_data *data, + int *tries_left) +{ + sc_apdu_t apdu; + sc_path_t path; + int r; + + /* Select MinBioClient */ + r = sc_hsm_soc_select_minbioclient(card); + LOG_TEST_RET(card->ctx, r, "Could not select MinBioClient application"); + + /* verify PIN */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 0x80); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_GOTO_ERR(card->ctx, r, "Could not verify PIN"); + + /* change PIN */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x24, 0x01, 0x80); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_GOTO_ERR(card->ctx, r, "Could not change PIN"); + +err: + /* Select SC-HSM */ + sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); + LOG_TEST_RET(card->ctx, + sc_hsm_select_file_ex(card, &path, 1, NULL), + "Could not select SmartCard-HSM application"); + + return r; +} + +static int sc_hsm_soc_unblock(sc_card_t *card, struct sc_pin_cmd_data *data, + int *tries_left) +{ + sc_apdu_t apdu; + sc_path_t path; + int r; + + /* Select MinBioClient */ + r = sc_hsm_soc_select_minbioclient(card); + LOG_TEST_RET(card->ctx, r, "Could not select MinBioClient application"); + + /* verify PUK */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 0x81); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_GOTO_ERR(card->ctx, r, "Could not verify PUK"); + + /* reset retry counter */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2c, 0x03, 0x00); + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_GOTO_ERR(card->ctx, r, "APDU transmit failed"); + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + LOG_TEST_GOTO_ERR(card->ctx, r, "Could not unblock PIN"); + +err: + /* Select SC-HSM */ + sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); + LOG_TEST_RET(card->ctx, + sc_hsm_select_file_ex(card, &path, 1, NULL), + "Could not select SmartCard-HSM application"); + + return r; +} + +static int sc_hsm_soc_biomatch(sc_card_t *card, struct sc_pin_cmd_data *data, + int *tries_left) +{ + sc_apdu_t apdu; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + int r; + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0x00, 0x85); + apdu.cla = 0x80; + apdu.data = (unsigned char*)"\x7F\x24\x00"; + apdu.datalen = 3; + apdu.lc = 3; + apdu.resplen = 0; + + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + /* ignore the actual status bytes */ + + /* JCOP's SM accelerator is incapable of using case 1 APDU in SM */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x20, 0x00, 0x81); + apdu.resp = rbuf; + apdu.resplen = sizeof rbuf; + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + /* now check the status bytes */ + r = sc_check_sw(card, apdu.sw1, apdu.sw2); + if (r == SC_SUCCESS) { + LOG_FUNC_RETURN(card->ctx, r); + } + + LOG_FUNC_RETURN(card->ctx, SC_ERROR_PIN_CODE_INCORRECT); +} + + + +#ifdef ENABLE_OPENPACE +#include "sm/sm-eac.h" +#include +#include +#include +#include +#include + +static int sc_hsm_perform_chip_authentication(sc_card_t *card) +{ + int r, protocol; + sc_path_t path; + u8 all_certs[1024]; + EAC_CTX *ctx = NULL; + size_t all_certs_len = sizeof all_certs, left, device_cert_len, issuer_cert_len; + const unsigned char *cert = all_certs, *device_cert, *issuer_cert; + BUF_MEM *comp_pub_key = NULL; + sc_cvc_t cvc_device, cvc_issuer; + /* this is only needed to call sc_pkcs15emu_sc_hsm_decode_cvc */ + sc_pkcs15_card_t p15card; + sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; + /* we know that sc_pkcs15emu_sc_hsm_decode_cvc does not require anything + * else to be initialized than p15card->card */ + p15card.card = card; + + memset(&cvc_device, 0, sizeof(cvc_device)); + memset(&cvc_issuer, 0, sizeof(cvc_issuer)); + + + if (priv->EF_C_DevAut && priv->EF_C_DevAut_len) { + all_certs_len = priv->EF_C_DevAut_len; + cert = priv->EF_C_DevAut; + } else { + /* get issuer and device certificate from the card */ + r = sc_path_set(&path, SC_PATH_TYPE_FILE_ID, (u8 *) "\x2F\x02", 2, 0, 0); + if (r < 0) + goto err; + r = sc_select_file(card, &path, NULL); + if (r < 0) + goto err; + r = sc_read_binary(card, 0, all_certs, all_certs_len, 0); + if (r < 0) + goto err; + + all_certs_len = r; + + /* save EF_C_DevAut for further use */ + cert = realloc(priv->EF_C_DevAut, all_certs_len); + if (cert) { + memcpy((unsigned char *) cert, all_certs, all_certs_len); + priv->EF_C_DevAut = (unsigned char *) cert; + priv->EF_C_DevAut_len = all_certs_len; + } + + cert = all_certs; + } + left = all_certs_len; + + device_cert = cert; + r = sc_pkcs15emu_sc_hsm_decode_cvc(&p15card, &cert, &left, &cvc_device); + if (r < 0) + goto err; + device_cert_len = all_certs_len - left; + + issuer_cert = cert; + r = sc_pkcs15emu_sc_hsm_decode_cvc(&p15card, &cert, &left, &cvc_issuer); + if (r < 0) + goto err; + issuer_cert_len = all_certs_len - device_cert_len - left; + + ctx = EAC_CTX_new(); + if (!ctx) { + r = SC_ERROR_INTERNAL; + goto err; + } + + + /* check all CVCs given of the document's pki */ + if (!TA_STEP2_import_certificate(ctx, issuer_cert, issuer_cert_len) + || !TA_STEP2_import_certificate(ctx, device_cert, device_cert_len)) { + r = SC_ERROR_INTERNAL; + goto err; + } + + if (card->type == SC_CARD_TYPE_SC_HSM_SOC) { + /* SoC cards are known to be implemented on newer JCOPs */ + protocol = NID_id_CA_ECDH_AES_CBC_CMAC_128; + } else { + /* Older cards may not support AES accelerator */ + protocol = NID_id_CA_ECDH_3DES_CBC_CBC; + } + + /* initialize CA domain parameter with the document's public key */ + if (!EAC_CTX_init_ca(ctx, protocol, 8)) { + r = SC_ERROR_INTERNAL; + goto err; + } + EVP_PKEY_free(ctx->ca_ctx->ka_ctx->key); + CRYPTO_add(&ctx->ta_ctx->pub_key->references, 1, CRYPTO_LOCK_EVP_PKEY); + ctx->ca_ctx->ka_ctx->key = ctx->ta_ctx->pub_key; + + /* generate keys for CA */ + comp_pub_key = TA_STEP3_generate_ephemeral_key(ctx); + r = perform_chip_authentication_ex(card, ctx, + cvc_device.publicPoint, cvc_device.publicPointlen); + +err: + if (r < 0) + EAC_CTX_clear_free(ctx); + if (comp_pub_key) + BUF_MEM_free(comp_pub_key); + sc_pkcs15emu_sc_hsm_free_cvc(&cvc_device); + sc_pkcs15emu_sc_hsm_free_cvc(&cvc_issuer); + + return r; +} + +#else + +static int sc_hsm_perform_chip_authentication(sc_card_t *card) +{ + return SC_ERROR_NOT_SUPPORTED; +} +#endif + + static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) @@ -169,43 +519,132 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; sc_apdu_t apdu; u8 cmdbuff[16]; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; int r; + int cmd = data->cmd; + size_t pin2_len = data->pin2.len; - if ((data->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) { - if (data->pin1.len != 16) - return SC_ERROR_INVALID_PIN_LENGTH; - - // Save SO PIN for later use in sc_hsm_init_pin() - r = sc_hsm_encode_sopin(data->pin1.data, priv->sopin); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + if (cmd == SC_PIN_CMD_GET_SESSION_PIN) { + /* First, perform a standard VERIFY */ + data->cmd = SC_PIN_CMD_VERIFY; + /* we assign pin2.len to 0 early on so that in case of an error we are + * not exiting with an undefined session PIN */ + data->pin2.len = 0; } - if ((data->cmd == SC_PIN_CMD_CHANGE) && (data->pin_reference == 0x88)) { - if ((data->pin1.len != 16) || (data->pin2.len != 16)) - return SC_ERROR_INVALID_PIN_LENGTH; - - r = sc_hsm_encode_sopin(data->pin1.data, cmdbuff); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - - r = sc_hsm_encode_sopin(data->pin2.data, cmdbuff + 8); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - - sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 0x00, data->pin_reference); - apdu.data = cmdbuff; - apdu.datalen = sizeof(cmdbuff); - apdu.lc = 16; - apdu.resplen = 0; - data->apdu = &apdu; + if ((card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH) + && (data->cmd == SC_PIN_CMD_CHANGE) + && (data->pin_reference == 0x81) + && (!data->pin1.data || data->pin1.len <= 0)) { + return sc_hsm_soc_change(card, data, tries_left); + } else if ((card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH) + && (data->cmd == SC_PIN_CMD_UNBLOCK) + && (data->pin_reference == 0x81) + && (!data->pin1.data || data->pin1.len <= 0)) { + return sc_hsm_soc_unblock(card, data, tries_left); } - data->pin1.offset = 5; - data->pin1.length_offset = 4; - data->pin2.offset = 5; - data->pin2.length_offset = 4; + /* For contactless cards always establish a secure channel before PIN + * verification */ + if (card->type == SC_CARD_TYPE_SC_HSM_SOC + && (data->cmd != SC_PIN_CMD_GET_INFO) + && card->sm_ctx.sm_mode != SM_MODE_TRANSMIT) { + LOG_TEST_RET(card->ctx, + sc_hsm_perform_chip_authentication(card), + "Could not perform chip authentication"); + } - return (*iso_ops->pin_cmd)(card, data, tries_left); + if ((card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH) + && (data->cmd == SC_PIN_CMD_VERIFY) + && (data->pin_reference == 0x81) + && (!data->pin1.data || data->pin1.len <= 0)) { + r = sc_hsm_soc_biomatch(card, data, tries_left); + } else { + if ((data->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) { + if (data->pin1.len != 16) + return SC_ERROR_INVALID_PIN_LENGTH; + + // Save SO PIN for later use in sc_hsm_init_pin() + r = sc_hsm_encode_sopin(data->pin1.data, priv->sopin); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } + + if ((data->cmd == SC_PIN_CMD_CHANGE) && (data->pin_reference == 0x88)) { + if ((data->pin1.len != 16) || (data->pin2.len != 16)) + return SC_ERROR_INVALID_PIN_LENGTH; + + r = sc_hsm_encode_sopin(data->pin1.data, cmdbuff); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + r = sc_hsm_encode_sopin(data->pin2.data, cmdbuff + 8); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); + + sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x24, 0x00, data->pin_reference); + apdu.data = cmdbuff; + apdu.datalen = sizeof(cmdbuff); + apdu.lc = 16; + apdu.resplen = 0; + data->apdu = &apdu; + } + + if ((data->cmd == SC_PIN_CMD_GET_INFO) + && (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT)) { + /* JCOP's SM accelerator is incapable of using case 1 APDU in SM */ + sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x20, 0x00, data->pin_reference); + apdu.resp = rbuf; + apdu.resplen = sizeof rbuf; + data->apdu = &apdu; + } + + data->pin1.offset = 5; + data->pin1.length_offset = 4; + data->pin2.offset = 5; + data->pin2.length_offset = 4; + + r = (*iso_ops->pin_cmd)(card, data, tries_left); + } + LOG_TEST_RET(card->ctx, r, "Verification failed"); + + if (cmd == SC_PIN_CMD_GET_SESSION_PIN) { + /* reset data->cmd to its original value */ + data->cmd = SC_PIN_CMD_GET_SESSION_PIN; + if (data->pin_reference == 0x81) { + u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE]; + if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, + "Session PIN generation only supported in SM"); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } + sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x5A, 0x01, data->pin_reference); + apdu.cla = 0x80; + apdu.resp = recvbuf; + apdu.resplen = sizeof recvbuf; + apdu.le = 0; + if (sc_transmit_apdu(card, &apdu) != SC_SUCCESS + || sc_check_sw(card, apdu.sw1, apdu.sw2) != SC_SUCCESS) { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, + "Generating session PIN failed"); + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); + } + if (data->pin2.data && pin2_len > 0) { + if (pin2_len >= apdu.resplen) { + memcpy((unsigned char *) data->pin2.data, apdu.resp, + apdu.resplen); + data->pin2.len = apdu.resplen; + } else { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, + "Buffer too small for session PIN"); + } + } + } else { + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, + "Session PIN not supported for this PIN (0x%02X)", + data->pin_reference); + } + } + LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } @@ -215,10 +654,11 @@ static int sc_hsm_logout(sc_card_t * card) sc_path_t path; sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; memset(priv->sopin, 0, sizeof(priv->sopin)); + sc_sm_stop(card); sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); - return sc_hsm_select_file(card, &path, NULL); + return sc_hsm_select_file_ex(card, &path, 1, NULL); } @@ -409,7 +849,6 @@ static int sc_hsm_delete_file(sc_card_t *card, const sc_path_t *path) } - static int sc_hsm_set_security_env(sc_card_t *card, const sc_security_env_t *env, int se_num) @@ -565,6 +1004,7 @@ static int sc_hsm_compute_signature(sc_card_t *card, apdu.lc = datalen; apdu.datalen = datalen; r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { int len; @@ -1029,17 +1469,17 @@ static int sc_hsm_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) static int sc_hsm_init(struct sc_card *card) { - sc_hsm_private_data_t *priv; +#ifdef _WIN32 + char expanded_val[PATH_MAX]; + size_t expanded_len = PATH_MAX; +#endif int flags,ext_flags; + sc_file_t *file; + sc_path_t path; + sc_hsm_private_data_t *priv = card->drv_data; LOG_FUNC_CALLED(card->ctx); - priv = calloc(1, sizeof(sc_hsm_private_data_t)); - if (!priv) - LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); - - card->drv_data = priv; - flags = SC_ALGORITHM_RSA_RAW|SC_ALGORITHM_ONBOARD_KEY_GEN; _sc_card_add_rsa_alg(card, 1024, flags, 0); @@ -1066,8 +1506,56 @@ static int sc_hsm_init(struct sc_card *card) card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT|SC_CARD_CAP_ISO7816_PIN_INFO; + sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); + if (sc_hsm_select_file_ex(card, &path, 0, &file) == SC_SUCCESS + && file->prop_attr && file->prop_attr_len >= 5) { + static char card_name[SC_MAX_APDU_BUFFER_SIZE]; + u8 type = file->prop_attr[2]; + u8 major = file->prop_attr[3]; + u8 minor = file->prop_attr[4]; + char p00[] = "SmartCard-HSM Applet for JCOP"; + char p01[] = "SmartCard-HSM Demo Applet for JCOP"; + char *p = "SmartCard-HSM"; + switch (type) { + case 0x00: + p = p00; + break; + case 0x01: + p = p01; + break; + default: + break; + } + snprintf(card_name, sizeof card_name, "%s version %u.%u", p, major, minor); + card->name = card_name; + + if (file->prop_attr[1] & 0x04) { + card->caps |= SC_CARD_CAP_SESSION_PIN; + } + sc_file_free(file); + } + card->max_send_size = 1431; // 1439 buffer size - 8 byte TLV because of odd ins in UPDATE BINARY - card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit + if (card->type == SC_CARD_TYPE_SC_HSM_SOC) { + card->max_recv_size = 0x0630; // SoC Proxy forces this limit + } else { + card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit + } + + priv->EF_C_DevAut = NULL; + priv->EF_C_DevAut_len = 0; + +#ifdef ENABLE_OPENPACE + EAC_init(); +#ifdef _WIN32 + expanded_len = ExpandEnvironmentStringsA(CVCDIR, expanded_val, sizeof expanded_val); + if (0 < expanded_len && expanded_len < sizeof expanded_val) + EAC_set_cvc_default_dir(expanded_val); +#else + EAC_set_cvc_default_dir(CVCDIR); +#endif +#endif + return 0; } @@ -1076,10 +1564,20 @@ static int sc_hsm_init(struct sc_card *card) static int sc_hsm_finish(sc_card_t * card) { sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; + sc_sm_stop(card); if (priv->serialno) { free(priv->serialno); } + if (priv->dffcp) { + sc_file_free(priv->dffcp); + } + free(priv->EF_C_DevAut); free(priv); + +#ifdef ENABLE_OPENPACE + EAC_cleanup(); +#endif + return SC_SUCCESS; } diff --git a/src/libopensc/card-sc-hsm.h b/src/libopensc/card-sc-hsm.h index 325f73fd..39efb461 100644 --- a/src/libopensc/card-sc-hsm.h +++ b/src/libopensc/card-sc-hsm.h @@ -56,10 +56,13 @@ /* Information the driver maintains between calls */ typedef struct sc_hsm_private_data { const sc_security_env_t *env; + sc_file_t *dffcp; u8 algorithm; int noExtLength; char *serialno; u8 sopin[8]; + u8 *EF_C_DevAut; + size_t EF_C_DevAut_len; } sc_hsm_private_data_t; diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h index 992826cc..691182f3 100644 --- a/src/libopensc/cards.h +++ b/src/libopensc/cards.h @@ -204,6 +204,7 @@ enum { /* SmartCard-HSM */ SC_CARD_TYPE_SC_HSM = 26000, + SC_CARD_TYPE_SC_HSM_SOC = 26001, /* Spanish DNIe card */ SC_CARD_TYPE_DNIE_BASE = 27000, diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index e74619a8..21801712 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -338,7 +338,7 @@ load_parameters(sc_context_t *ctx, scconf_block *block, struct _sc_ctx_options * #ifdef _WIN32 expanded_len = PATH_MAX; expanded_len = ExpandEnvironmentStringsA(val, expanded_val, expanded_len); - if (expanded_len > 0) + if (0 < expanded_len && expanded_len < sizeof expanded_val) val = expanded_val; #endif sc_ctx_log_to_file(ctx, val); diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index f0355a69..b1d2c91d 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -999,6 +999,8 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, switch (data->pin_type) { case SC_AC_CHV: + /* fall through */ + case SC_AC_SESSION: break; default: return SC_ERROR_INVALID_ARGUMENTS; diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 3aff3d2b..c96c410d 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -342,6 +342,7 @@ typedef struct sc_reader { #define SC_PIN_CMD_CHANGE 1 #define SC_PIN_CMD_UNBLOCK 2 #define SC_PIN_CMD_GET_INFO 3 +#define SC_PIN_CMD_GET_SESSION_PIN 4 #define SC_PIN_CMD_USE_PINPAD 0x0001 #define SC_PIN_CMD_NEED_PADDING 0x0002 @@ -475,6 +476,12 @@ struct sc_reader_operations { #define SC_CARD_CAP_ONLY_RAW_HASH 0x00000040 #define SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED 0x00000080 +/* Card (or card driver) supports an protected authentication mechanism */ +#define SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH 0x00000100 + +/* Card (or card driver) supports generating a session PIN */ +#define SC_CARD_CAP_SESSION_PIN 0x00000200 + typedef struct sc_card { struct sc_context *ctx; struct sc_reader *reader; diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index 17c73041..28a39b70 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -270,7 +270,9 @@ _validate_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_auth_info *auth_i return SC_ERROR_BUFFER_TOO_SMALL; /* if we use pinpad, no more checks are needed */ - if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD && !pinlen) + if ((p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD + || p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH) + && !pinlen) return SC_SUCCESS; /* If pin is given, make sure it is within limits */ @@ -391,7 +393,9 @@ _sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *p data.pin_reference = skey_info->key_reference; } - if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD && !pinlen) { + if((p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD + || p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH) + && !pinlen) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) @@ -487,7 +491,8 @@ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card, } if((!oldpin || !newpin) - && p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { + && (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD + || p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) { data.pin1.prompt = "Please enter SO PIN"; @@ -600,7 +605,8 @@ int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card, break; } - if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { + if((p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD + || p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) { data.pin1.prompt = "Please enter PUK"; @@ -743,7 +749,8 @@ sc_pkcs15_pincache_revalidate(struct sc_pkcs15_card *p15card, const sc_pkcs15_ob return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } - if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) + if ((p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD + || p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; r = sc_pkcs15_find_pin_by_auth_id(p15card, &obj->auth_id, &pin_obj); diff --git a/src/libopensc/pkcs15-sc-hsm.c b/src/libopensc/pkcs15-sc-hsm.c index a0dd3bf4..b71c9390 100644 --- a/src/libopensc/pkcs15-sc-hsm.c +++ b/src/libopensc/pkcs15-sc-hsm.c @@ -181,7 +181,7 @@ static const struct sc_asn1_entry c_asn1_req[C_ASN1_REQ_SIZE] = { static int read_file(sc_pkcs15_card_t * p15card, u8 fid[2], - u8 *efbin, size_t *len) + u8 *efbin, size_t *len, int optional) { sc_path_t path; int r; @@ -196,12 +196,24 @@ static int read_file(sc_pkcs15_card_t * p15card, u8 fid[2], /* avoid re-selection of SC-HSM */ path.aid.len = 0; r = sc_select_file(p15card->card, &path, NULL); - LOG_TEST_RET(p15card->card->ctx, r, "Could not select EF"); + if (r < 0) { + sc_log(p15card->card->ctx, "Could not select EF"); + } else { + r = sc_read_binary(p15card->card, 0, efbin, *len, 0); + } - r = sc_read_binary(p15card->card, 0, efbin, *len, 0); - LOG_TEST_RET(p15card->card->ctx, r, "Could not read EF"); - - *len = r; + if (r < 0) { + sc_log(p15card->card->ctx, "Could not read EF"); + if (!optional) { + return r; + } + /* optional files are saved as empty files to avoid card + * transactions. Parsing the file's data will reveal that they were + * missing. */ + *len = 0; + } else { + *len = r; + } if (p15card->opts.use_file_cache) { /* save this with our AID */ @@ -593,7 +605,7 @@ static int sc_pkcs15emu_sc_hsm_add_prkd(sc_pkcs15_card_t * p15card, u8 keyid) { /* Try to select a related EF containing the PKCS#15 description of the key */ len = sizeof efbin; - r = read_file(p15card, fid, efbin, &len); + r = read_file(p15card, fid, efbin, &len, 1); LOG_TEST_RET(card->ctx, r, "Could not read EF.PRKD"); ptr = efbin; @@ -627,7 +639,8 @@ static int sc_pkcs15emu_sc_hsm_add_prkd(sc_pkcs15_card_t * p15card, u8 keyid) { fid[0] = EE_CERTIFICATE_PREFIX; len = sizeof efbin; - r = read_file(p15card, fid, efbin, &len); + r = read_file(p15card, fid, efbin, &len, 0); + LOG_TEST_RET(card->ctx, r, "Could not read EF"); LOG_TEST_RET(card->ctx, r, "Could not read EF"); @@ -683,7 +696,7 @@ static int sc_pkcs15emu_sc_hsm_add_dcod(sc_pkcs15_card_t * p15card, u8 id) { /* Try to select a related EF containing the PKCS#15 description of the data */ len = sizeof efbin; - r = read_file(p15card, fid, efbin, &len); + r = read_file(p15card, fid, efbin, &len, 1); LOG_TEST_RET(card->ctx, r, "Could not read EF.DCOD"); ptr = efbin; @@ -722,7 +735,7 @@ static int sc_pkcs15emu_sc_hsm_add_cd(sc_pkcs15_card_t * p15card, u8 id) { /* Try to select a related EF containing the PKCS#15 description of the data */ len = sizeof efbin; - r = read_file(p15card, fid, efbin, &len); + r = read_file(p15card, fid, efbin, &len, 1); LOG_TEST_RET(card->ctx, r, "Could not read EF.DCOD"); ptr = efbin; @@ -753,7 +766,7 @@ static int sc_pkcs15emu_sc_hsm_read_tokeninfo (sc_pkcs15_card_t * p15card) /* Read token info */ len = sizeof efbin; - r = read_file(p15card, (u8 *) "\x2F\x03", efbin, &len); + r = read_file(p15card, (u8 *) "\x2F\x03", efbin, &len, 1); LOG_TEST_RET(card->ctx, r, "Could not read EF.TokenInfo"); r = sc_pkcs15_parse_tokeninfo(card->ctx, p15card->tokeninfo, efbin, len); @@ -771,6 +784,7 @@ static int sc_pkcs15emu_sc_hsm_read_tokeninfo (sc_pkcs15_card_t * p15card) static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; + sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; sc_file_t *file = NULL; sc_path_t path; u8 filelist[MAX_EXT_APDU_LENGTH]; @@ -780,7 +794,8 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) struct sc_app_info *appinfo; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; - u8 efbin[512]; + struct sc_pin_cmd_data pindata; + u8 efbin[1024]; u8 *ptr; size_t len; @@ -809,11 +824,24 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) sc_file_free(file); /* Read device certificate to determine serial number */ - len = sizeof efbin; - r = read_file(p15card, (u8 *) "\x2F\x02", efbin, &len); - LOG_TEST_RET(card->ctx, r, "Could not select EF.C_DevAut"); + if (priv->EF_C_DevAut && priv->EF_C_DevAut_len) { + ptr = priv->EF_C_DevAut; + len = priv->EF_C_DevAut_len; + } else { + len = sizeof efbin; + r = read_file(p15card, (u8 *) "\x2F\x02", efbin, &len, 1); + LOG_TEST_RET(card->ctx, r, "Could not select EF.C_DevAut"); - ptr = efbin; + /* save EF_C_DevAut for further use */ + ptr = realloc(priv->EF_C_DevAut, len); + if (ptr) { + memcpy(ptr, efbin, len); + priv->EF_C_DevAut = ptr; + priv->EF_C_DevAut_len = len; + } + + ptr = efbin; + } memset(&devcert, 0 ,sizeof(devcert)); r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&ptr, &len, &devcert); @@ -883,7 +911,6 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) if (r < 0) LOG_FUNC_RETURN(card->ctx, r); - memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); @@ -909,6 +936,30 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) LOG_FUNC_RETURN(card->ctx, r); + if (card->type == SC_CARD_TYPE_SC_HSM_SOC) { + /* SC-HSM of this type always has a PIN-Pad */ + r = SC_SUCCESS; + } else { + memset(&pindata, 0, sizeof(pindata)); + pindata.cmd = SC_PIN_CMD_GET_INFO; + pindata.pin_type = SC_AC_CHV; + pindata.pin_reference = 0x85; + + r = sc_pin_cmd(card, &pindata, NULL); + } + if (r == SC_ERROR_DATA_OBJECT_NOT_FOUND) { + memset(&pindata, 0, sizeof(pindata)); + pindata.cmd = SC_PIN_CMD_GET_INFO; + pindata.pin_type = SC_AC_CHV; + pindata.pin_reference = 0x86; + + r = sc_pin_cmd(card, &pindata, NULL); + } + + if (r != SC_ERROR_DATA_OBJECT_NOT_FOUND) + card->caps |= SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH; + + filelistlength = sc_list_files(card, filelist, sizeof(filelist)); LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier"); @@ -941,7 +992,8 @@ int sc_pkcs15emu_sc_hsm_init_ex(sc_pkcs15_card_t *p15card, if (opts && (opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)) { return sc_pkcs15emu_sc_hsm_init(p15card); } else { - if (p15card->card->type != SC_CARD_TYPE_SC_HSM) { + if (p15card->card->type != SC_CARD_TYPE_SC_HSM + && p15card->card->type != SC_CARD_TYPE_SC_HSM_SOC) { return SC_ERROR_WRONG_CARD; } return sc_pkcs15emu_sc_hsm_init(p15card); diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index 0fdcbed0..d72fc313 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -82,6 +82,7 @@ int sc_pkcs15_is_emulation_only(sc_card_t *card) case SC_CARD_TYPE_OPENPGP_V2: case SC_CARD_TYPE_OPENPGP_GNUK: case SC_CARD_TYPE_SC_HSM: + case SC_CARD_TYPE_SC_HSM_SOC: case SC_CARD_TYPE_DNIE_BASE: case SC_CARD_TYPE_DNIE_BLANK: case SC_CARD_TYPE_DNIE_ADMIN: diff --git a/src/libopensc/types.h b/src/libopensc/types.h index 7368422c..e665c54b 100644 --- a/src/libopensc/types.h +++ b/src/libopensc/types.h @@ -148,6 +148,7 @@ struct sc_crt { #define SC_AC_SEN 0x00000020 /* Security Environment. */ #define SC_AC_SCB 0x00000040 /* IAS/ECC SCB byte. */ #define SC_AC_IDA 0x00000080 /* PKCS#15 authentication ID */ +#define SC_AC_SESSION 0x00000100 /* Session PIN */ #define SC_AC_UNKNOWN 0xFFFFFFFE #define SC_AC_NEVER 0xFFFFFFFF diff --git a/src/minidriver/Makefile.mak b/src/minidriver/Makefile.mak index ee8fa274..5ce80ef5 100644 --- a/src/minidriver/Makefile.mak +++ b/src/minidriver/Makefile.mak @@ -14,5 +14,5 @@ $(TARGET): $(OBJECTS) $(LIBS) echo LIBRARY $* > $*.def echo EXPORTS >> $*.def type minidriver.exports >> $*.def - link /dll $(LINKFLAGS) /def:$*.def /out:$(TARGET) $(OBJECTS) $(LIBS) $(ZLIB_LIB) $(OPENSSL_LIB) ws2_32.lib gdi32.lib advapi32.lib Crypt32.lib User32.lib bcrypt.lib DelayImp.lib Rpcrt4.lib /DELAYLOAD:bcrypt.dll + link /dll $(LINKFLAGS) /def:$*.def /out:$(TARGET) $(OBJECTS) $(LIBS) $(ZLIB_LIB) $(OPENPACE_LIB) $(OPENSSL_LIB) ws2_32.lib gdi32.lib advapi32.lib Crypt32.lib User32.lib bcrypt.lib DelayImp.lib Rpcrt4.lib /DELAYLOAD:bcrypt.dll if EXIST $(TARGET).manifest mt -manifest $(TARGET).manifest -outputresource:$(TARGET);2 diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 705b7340..34b12887 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -4774,7 +4774,8 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, return SCARD_F_INTERNAL_ERROR; if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN || dwFlags == CARD_AUTHENTICATE_SESSION_PIN) { - if (! (vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) + if (! (vs->reader->capabilities & SC_READER_CAP_PIN_PAD + || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) return SCARD_E_UNSUPPORTED_FEATURE; } @@ -4783,7 +4784,8 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, /* using a pin pad */ if (NULL == pbPinData) { - if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) + if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD + || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) return SCARD_E_INVALID_PARAMETER; if (!(dwFlags & CARD_PIN_SILENT_CONTEXT) && !(vs->ctx->flags & SC_CTX_FLAG_DISABLE_POPUPS)) { @@ -4809,7 +4811,9 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, /* Do we need to display a prompt to enter PIN on pin pad? */ logprintf(pCardData, 7, "PIN pad=%s, pbPinData=%p, hwndParent=%p\n", - vs->reader->capabilities & SC_READER_CAP_PIN_PAD ? "yes" : "no", pbPinData, vs->hwndParent); + vs->reader->capabilities & SC_READER_CAP_PIN_PAD + || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH + ? "yes" : "no", pbPinData, vs->hwndParent); /* check if the pin is the session pin generated by a previous authentication with a pinpad */ if (pbPinData != NULL && cbPinData == sizeof(MAGIC_SESSION_PIN) && memcmp(MAGIC_SESSION_PIN, pbPinData, sizeof(MAGIC_SESSION_PIN)) == 0) { @@ -4836,7 +4840,9 @@ DWORD WINAPI CardAuthenticateEx(__in PCARD_DATA pCardData, logprintf(pCardData, 2, "Pin code correct.\n"); /* set the session pin according to the minidriver specification */ - if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN && (vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) { + if (dwFlags == CARD_AUTHENTICATE_GENERATE_SESSION_PIN + && (vs->reader->capabilities & SC_READER_CAP_PIN_PAD + || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { /* we set it to a special value for pinpad authentication to force a new pinpad authentication */ if (pcbSessionPin) *pcbSessionPin = sizeof(MAGIC_SESSION_PIN); if (ppbSessionPin) { @@ -4907,7 +4913,8 @@ DWORD WINAPI CardChangeAuthenticatorEx(__in PCARD_DATA pCardData, vs = (VENDOR_SPECIFIC*)(pCardData->pvVendorSpecific); - if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD)) { + if (!(vs->reader->capabilities & SC_READER_CAP_PIN_PAD + || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { if (pbAuthenticatingPinData == NULL || cbAuthenticatingPinData == 0) { logprintf(pCardData, 1, "Invalid current PIN data\n"); return SCARD_E_INVALID_PARAMETER; @@ -5192,7 +5199,9 @@ DWORD WINAPI CardGetProperty(__in PCARD_DATA pCardData, if (p->dwVersion != PIN_INFO_CURRENT_VERSION) return ERROR_REVISION_MISMATCH; - p->PinType = vs->reader->capabilities & SC_READER_CAP_PIN_PAD ? ExternalPinType : AlphaNumericPinType; + p->PinType = vs->reader->capabilities & SC_READER_CAP_PIN_PAD + || vs->p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH + ? ExternalPinType : AlphaNumericPinType; p->dwFlags = 0; switch (dwFlags) { case ROLE_USER: diff --git a/src/pkcs11/Makefile.mak b/src/pkcs11/Makefile.mak index 8fd0ff9e..1aeb9e66 100644 --- a/src/pkcs11/Makefile.mak +++ b/src/pkcs11/Makefile.mak @@ -17,15 +17,15 @@ all: $(TARGET1) $(TARGET2) $(TARGET3) !INCLUDE $(TOPDIR)\win32\Make.rules.mak $(TARGET1): $(OBJECTS) $(LIBS) - link $(LINKFLAGS) /dll /implib:$*.lib /out:$(TARGET1) $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib + link $(LINKFLAGS) /dll /implib:$*.lib /out:$(TARGET1) $(OBJECTS) $(LIBS) $(OPENPACE_LIB) $(OPENSSL_LIB) gdi32.lib if EXIST $(TARGET1).manifest mt -manifest $(TARGET1).manifest -outputresource:$(TARGET1);2 $(TARGET2): $(OBJECTS) $(LIBS) del pkcs11-global.obj cl $(CODE_OPTIMIZATION) $(COPTS) /DMODULE_APP_NAME=\"onepin-opensc-pkcs11\" /c pkcs11-global.c - link $(LINKFLAGS) /dll /implib:$*.lib /out:$(TARGET2) $(OBJECTS) $(LIBS) $(OPENSSL_LIB) gdi32.lib + link $(LINKFLAGS) /dll /implib:$*.lib /out:$(TARGET2) $(OBJECTS) $(LIBS) $(OPENPACE_LIB) $(OPENSSL_LIB) gdi32.lib if EXIST $(TARGET2).manifest mt -manifest $(TARGET2).manifest -outputresource:$(TARGET2);2 $(TARGET3): $(OBJECTS3) $(LIBS3) - link $(LINKFLAGS) /dll /implib:$*.lib /out:$(TARGET3) $(OBJECTS3) $(LIBS3) $(OPENSSL_LIB) gdi32.lib advapi32.lib + link $(LINKFLAGS) /dll /implib:$*.lib /out:$(TARGET3) $(OBJECTS3) $(LIBS3) $(OPENPACE_LIB) $(OPENSSL_LIB) gdi32.lib advapi32.lib if EXIST $(TARGET3).manifest mt -manifest $(TARGET3).manifest -outputresource:$(TARGET3);2 diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 42c50935..19a72869 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -961,7 +961,7 @@ pkcs15_init_slot(struct sc_pkcs15_card *p15card, struct sc_pkcs11_slot *slot, if (auth != NULL) slot->token_info.flags |= CKF_USER_PIN_INITIALIZED; - if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) + if ((p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) || (p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) slot->token_info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH; if (p15card->card->caps & SC_CARD_CAP_RNG && p15card->card->ops->get_challenge != NULL) @@ -1489,7 +1489,8 @@ pkcs15_login(struct sc_pkcs11_slot *slot, CK_USER_TYPE userType, if (pin_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return CKR_FUNCTION_REJECTED; - if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { + if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD + || (p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { /* pPin should be NULL in case of a pin pad reader, but * some apps (e.g. older Netscapes) don't know about it. * So we don't require that pPin == NULL, but set it to @@ -1650,7 +1651,8 @@ pkcs15_change_pin(struct sc_pkcs11_slot *slot, return CKR_USER_PIN_NOT_INITIALIZED; sc_log(context, "Change '%.*s' (ref:%i,type:%i)", (int) sizeof pin_obj->label, pin_obj->label, auth_info->attrs.pin.reference, login_user); - if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { + if ((p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) + || (p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH)) { /* pPin should be NULL in case of a pin pad reader, but * some apps (e.g. older Netscapes) don't know about it. * So we don't require that pPin == NULL, but set it to diff --git a/src/sm/sm-eac.c b/src/sm/sm-eac.c index c51b4b84..a5561055 100644 --- a/src/sm/sm-eac.c +++ b/src/sm/sm-eac.c @@ -1762,13 +1762,11 @@ int perform_chip_authentication(sc_card_t *card, unsigned char **ef_cardsecurity, size_t *ef_cardsecurity_len) { int r; - BUF_MEM *picc_pubkey = NULL, *nonce = NULL, *token = NULL, - *eph_pub_key = NULL; + BUF_MEM *picc_pubkey = NULL; struct iso_sm_ctx *isosmctx; struct npa_sm_ctx *eacsmctx; - if (!card || !card->sm_ctx.info.cmd_data - || !ef_cardsecurity || !ef_cardsecurity_len) { + if (!card || !ef_cardsecurity || !ef_cardsecurity_len) { r = SC_ERROR_INVALID_ARGUMENTS; goto err; } @@ -1779,7 +1777,6 @@ int perform_chip_authentication(sc_card_t *card, } eacsmctx = isosmctx->priv_data; - /* Passive Authentication */ if (!*ef_cardsecurity && !*ef_cardsecurity_len) { r = get_ef_card_security(card, ef_cardsecurity, ef_cardsecurity_len); @@ -1796,8 +1793,42 @@ int perform_chip_authentication(sc_card_t *card, goto err; } + r = perform_chip_authentication_ex(card, eacsmctx->ctx, + (unsigned char *) picc_pubkey->data, picc_pubkey->length); - r = npa_mse_set_at_ca(card, eacsmctx->ctx->ca_ctx->protocol); +err: + BUF_MEM_clear_free(picc_pubkey); + + if (card) + SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); + else + return r; +} + +int perform_chip_authentication_ex(sc_card_t *card, void *eac_ctx, + unsigned char *picc_pubkey, size_t picc_pubkey_len) +{ + int r; + BUF_MEM *picc_pubkey_buf = NULL, *nonce = NULL, *token = NULL, + *eph_pub_key = NULL; + EAC_CTX *ctx = eac_ctx; + + if (!card || !ctx) { + r = SC_ERROR_INVALID_ARGUMENTS; + goto err; + } + + + picc_pubkey_buf = BUF_MEM_create_init(picc_pubkey, picc_pubkey_len); + if (!picc_pubkey_buf) { + sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not verify EF.CardSecurity."); + ssl_error(card->ctx); + r = SC_ERROR_INTERNAL; + goto err; + } + + + r = npa_mse_set_at_ca(card, ctx->ca_ctx->protocol); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol proberties " "(MSE: Set AT failed)."); @@ -1805,7 +1836,7 @@ int perform_chip_authentication(sc_card_t *card, } - eph_pub_key = CA_STEP2_get_eph_pubkey(eacsmctx->ctx); + eph_pub_key = CA_STEP2_get_eph_pubkey(ctx); if (!eph_pub_key) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not derive keys."); ssl_error(card->ctx); @@ -1819,7 +1850,7 @@ int perform_chip_authentication(sc_card_t *card, } - if (!CA_STEP4_compute_shared_secret(eacsmctx->ctx, picc_pubkey)) { + if (!CA_STEP4_compute_shared_secret(ctx, picc_pubkey_buf)) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute shared secret."); ssl_error(card->ctx); r = SC_ERROR_INTERNAL; @@ -1827,7 +1858,7 @@ int perform_chip_authentication(sc_card_t *card, } - if (!CA_STEP6_derive_keys(eacsmctx->ctx, nonce, token)) { + if (!CA_STEP6_derive_keys(ctx, nonce, token)) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not derive keys."); ssl_error(card->ctx); r = SC_ERROR_INTERNAL; @@ -1836,15 +1867,19 @@ int perform_chip_authentication(sc_card_t *card, /* Initialize secure channel */ - if (!EAC_CTX_set_encryption_ctx(eacsmctx->ctx, EAC_ID_CA)) { + if (!EAC_CTX_set_encryption_ctx(ctx, EAC_ID_CA)) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize encryption."); ssl_error(card->ctx); r = SC_ERROR_INTERNAL; goto err; } + if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT) { + r = npa_sm_start(card, ctx, NULL, 0, NULL, 0); + } + err: - BUF_MEM_clear_free(picc_pubkey); + BUF_MEM_clear_free(picc_pubkey_buf); BUF_MEM_clear_free(nonce); BUF_MEM_clear_free(token); BUF_MEM_clear_free(eph_pub_key); @@ -2371,6 +2406,12 @@ int perform_chip_authentication(sc_card_t *card, return SC_ERROR_NOT_SUPPORTED; } +int perform_chip_authentication_ex(sc_card_t *card, void *eac_ctx, + unsigned char *picc_pubkey, size_t picc_pubkey_len) +{ + return SC_ERROR_NOT_SUPPORTED; +} + #endif static const char *MRZ_name = "MRZ"; diff --git a/src/sm/sm-eac.h b/src/sm/sm-eac.h index 755dd2a2..fcb35773 100644 --- a/src/sm/sm-eac.h +++ b/src/sm/sm-eac.h @@ -230,6 +230,8 @@ int perform_terminal_authentication(sc_card_t *card, */ int perform_chip_authentication(sc_card_t *card, unsigned char **ef_cardsecurity, size_t *ef_cardsecurity_len); +int perform_chip_authentication_ex(sc_card_t *card, void *eacsmctx, + unsigned char *picc_pubkey, size_t picc_pubkey_len); /** * @brief Sends a reset retry counter APDU diff --git a/src/smm/Makefile.mak b/src/smm/Makefile.mak index d0eb9921..a50ccbc3 100644 --- a/src/smm/Makefile.mak +++ b/src/smm/Makefile.mak @@ -14,7 +14,7 @@ $(TARGET): $(OBJECTS) $(LIBS) echo LIBRARY $* > $*.def echo EXPORTS >> $*.def type $*.exports >> $*.def - link /dll $(LINKFLAGS) /def:$*.def /out:$(TARGET) $(OBJECTS) $(LIBS) $(ZLIB_LIB) $(OPENSSL_LIB) ws2_32.lib gdi32.lib advapi32.lib Crypt32.lib User32.lib + link /dll $(LINKFLAGS) /def:$*.def /out:$(TARGET) $(OBJECTS) $(LIBS) $(ZLIB_LIB) $(OPENPACE_LIB) $(OPENSSL_LIB) ws2_32.lib gdi32.lib advapi32.lib Crypt32.lib User32.lib if EXIST $(TARGET).manifest mt -manifest $(TARGET).manifest -outputresource:$(TARGET);2 !ELSE diff --git a/src/tools/npa-tool.c b/src/tools/npa-tool.c index a2a74a04..11b55759 100644 --- a/src/tools/npa-tool.c +++ b/src/tools/npa-tool.c @@ -486,7 +486,7 @@ main (int argc, char **argv) } else if (cmdline.puk_given) { pace_input.pin_id = PACE_PUK; pace_input.pin_length = 10; - maxsecret = 9999999999LLU; + maxsecret = 9999999999; if (puk) { if (sscanf(puk, "%llu", &secret) != 1) { fprintf(stderr, "%s is not an unsigned long long.\n", diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 98410355..0f1cfebd 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -1541,7 +1541,8 @@ static int unblock_pin(void) u8 *pin, *puk; int r, pinpad_present = 0; - pinpad_present = p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD; + pinpad_present = p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD + || p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH; if (!(pin_obj = get_pin_info())) return 2; @@ -1638,7 +1639,8 @@ static int change_pin(void) u8 *pincode, *newpin; int r, pinpad_present = 0; - pinpad_present = p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD; + pinpad_present = p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD + || p15card->card->caps & SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH; if (!(pin_obj = get_pin_info())) return 2; diff --git a/win32/Make.rules.mak b/win32/Make.rules.mak index 621beb44..5a10278b 100644 --- a/win32/Make.rules.mak +++ b/win32/Make.rules.mak @@ -80,9 +80,10 @@ CANDLEFLAGS = -dzlib="C:\zlib-dll" $(CANDLEFLAGS) # - set the OPENPACE_LIB below to your OpenPACE lib file #OPENPACE_DEF= /DENABLE_OPENPACE !IF "$(OPENPACE_DEF)" == "/DENABLE_OPENPACE" -OPENPACE_DIR = C:\OpenPACE -OPENPACE_INCL_DIR = /I$(OPENPACE_DIR)\include -OPENPACE_LIB = $(OPENPACE_DIR)\lib\libeac.lib +OPENPACE_DIR = C:\openpace +OPENPACE_INCL_DIR = /I$(OPENPACE_DIR)\src +OPENPACE_LIB = $(OPENPACE_DIR)\src\libeac.lib +CANDLEFLAGS = -dOpenPACE="$(OPENPACE_DIR)" $(CANDLEFLAGS) !ENDIF diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in index 1a024e31..29beecc8 100644 --- a/win32/OpenSC.wxs.in +++ b/win32/OpenSC.wxs.in @@ -280,6 +280,16 @@ + + + + + + + + + + @@ -304,6 +314,10 @@ + + + + diff --git a/win32/customactions.cpp b/win32/customactions.cpp index 2eaa0fda..9c8377c3 100644 --- a/win32/customactions.cpp +++ b/win32/customactions.cpp @@ -74,6 +74,8 @@ MD_REGISTRATION minidriver_registration[] = { 24, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, {TEXT("SmartCard-HSM-CL"), {0x3B,0x8E,0x80,0x01,0x80,0x31,0x81,0x54,0x48,0x53,0x4D,0x31,0x73,0x80,0x21,0x40,0x81,0x07,0x18}, 19, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("SmartCard-HSM-FP"), {0x3B,0x80,0x80,0x01,0x01}, + 5, {0xff,0xff,0xff,0xff,0xff}}, /* from minidriver-westcos.reg */ {TEXT("CEV WESTCOS"), {0x3f,0x69,0x00,0x00,0x00,0x64,0x01,0x00,0x00,0x00,0x80,0x90,0x00}, 13, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xf0,0xff,0xff}}, diff --git a/win32/winconfig.h.in b/win32/winconfig.h.in index 55f74fdb..f1706661 100644 --- a/win32/winconfig.h.in +++ b/win32/winconfig.h.in @@ -118,6 +118,10 @@ #define OPENSC_VS_FF_PRODUCT_NAME "@OPENSC_VS_FF_PRODUCT_NAME@" #endif +#ifndef CVCDIR +#define CVCDIR "%PROGRAMFILES%\\OpenSC Project\\OpenSC\\cvc" +#endif + #ifndef DEFAULT_PKCS11_PROVIDER #define DEFAULT_PKCS11_PROVIDER "@DEFAULT_PKCS11_PROVIDER@" #endif