diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in index 86a2a729..142033b4 100755 --- a/MacOSX/build-package.in +++ b/MacOSX/build-package.in @@ -88,4 +88,12 @@ pkgbuild --nopayload --identifier org.opensc-project.mac.uninstall --scripts Mac # Create .dmg rm -f OpenSC-@PACKAGE_VERSION@.dmg TIMESTAMP=$(date +%Y.%m.%d) -hdiutil create -srcfolder Uninstall_OpenSC.pkg -srcfolder OpenSC-@PACKAGE_VERSION@.pkg -volname "OpenSC @PACKAGE_VERSION@ for Mac OS X 10.9+ (${TIMESTAMP})" OpenSC-@PACKAGE_VERSION@.dmg +i=0 +while ! hdiutil create -srcfolder Uninstall_OpenSC.pkg -srcfolder OpenSC-@PACKAGE_VERSION@.pkg -volname "OpenSC @PACKAGE_VERSION@ for Mac OS X 10.9+ (${TIMESTAMP})" OpenSC-@PACKAGE_VERSION@.dmg +do + i=$[$i+1] + if [ $i -gt 2 ] + then + exit 1 + fi +done diff --git a/README.md b/README.md index 714ad043..69836176 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,5 @@ Jenkins CI: Travis CI: [![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png)](https://travis-ci.org/OpenSC/OpenSC) +AppVeyor CI: +[![Build status](https://ci.appveyor.com/api/projects/status/94wjbxyfb0u3cvg9?svg=true)](https://ci.appveyor.com/project/LudovicRousseau/opensc) diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..cb227013 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,71 @@ +platform: + - x86 + - x64 + +environment: + matrix: + - VSVER: 14 + - VSVER: 12 + - VSVER: 10 + +matrix: + allow_failures: + # not included in AppVeyor right now + - platform: x64 + VSVER: 10 + # does not currently work + - VSVER: 14 + - VSVER: 12 + - VSVER: 10 + +install: + - date /T & time /T + - set PATH=C:\cygwin\bin;%PATH% + - ps: >- + If(!(Test-Path -Path "C:\cccl-1.0" )) { + git clone -q --depth=1 git://github.com/swig/cccl.git "C:\cccl-1.0" + } + - bash -c "cp C:/cccl-1.0/cccl /usr/bin" + - ps: >- + If ($env:Platform -Match "x86") { + $env:JAVA_HOME="C:/Program Files (x86)/Java/jdk1.8.0" + $env:VCVARS_PLATFORM="x86" + $env:ENV_PLATFORM="x86" + $env:OPENSSL="https://slproweb.com/download/Win32OpenSSL-1_0_2d.exe" + $env:NMAKE_FLAGS="" + } Else { + $env:JAVA_HOME="C:/Program Files/Java/jdk1.8.0" + $env:VCVARS_PLATFORM="amd64" + $env:ENV_PLATFORM="x64" + $env:OPENSSL="https://slproweb.com/download/Win64OpenSSL-1_0_2d.exe" + $env:NMAKE_FLAGS="BUILD_ON=WIN64 BUILD_FOR=WIN64" + } + - ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) + - echo "Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS%" + - call "%VSCOMNTOOLS%\..\..\VC\vcvarsall.bat" %VCVARS_PLATFORM% + - call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /%ENV_PLATFORM% /Release + - appveyor DownloadFile %OPENSSL% -FileName C:\WinOpenSSL.exe + - C:\WinOpenSSL.exe /SILENT /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART /DIR="C:\OpenSSL" + - appveyor DownloadFile "http://prdownloads.sourceforge.net/libpng/zlib128-dll.zip" + - 7z x zlib128-dll.zip -oC:\zlib-1.2.8-dll + - bash -c "which cl.exe" + - bash -c "cl.exe /? 2>&1 | head -n 2" + - bash -c "which csc.exe" + - bash -c "csc.exe /? | head -n 2" + - bash -c "which cccl" + - bash -c "cccl --version" + - uname -a + +build_script: + - set CCCL_OPTIONS=--cccl-muffle /W3 /D_CRT_SECURE_NO_DEPRECATE /Dsnprintf=_snprintf + - set CC=cccl + - set CXX=cccl + - set LD=cccl + - bash -c "exec 0> /tmp/oscout 2>&1 && ./configure >> /tmp/oscout 2>&1" + #- nmake /f Makefile.mak %NMAKE_FLAGS% diff --git a/doc/tools/pkcs15-tool.1.xml b/doc/tools/pkcs15-tool.1.xml index 82ad7b91..79b0e506 100644 --- a/doc/tools/pkcs15-tool.1.xml +++ b/doc/tools/pkcs15-tool.1.xml @@ -154,6 +154,18 @@ If this option is not given, keys will be printed to standard output. + + + + + Changes how prints the content + to standard output. By default, when is not given, it will + print the content in hex notation. If is set, it will print + the binary data directly. This does not affect the output that is written to the + file specified by the option. Data written to a file will + always be in raw binary. + + cert, @@ -168,7 +180,12 @@ data Reads data object with OID, applicationName or label. - + The content is printed to standard output in hex notation, unless + the option is given. + If an output file is given with the option, + the content is additionally written to the file. + Output to the file is always written in raw binary mode, the + only affects standard output behavior. diff --git a/etc/opensc.conf.in b/etc/opensc.conf.in index c14107a8..a270308d 100644 --- a/etc/opensc.conf.in +++ b/etc/opensc.conf.in @@ -431,6 +431,12 @@ app default { # Default: false # use_file_caching = true; # + # set a path for caching + # so you do not use the env variables and for pam_pkcs11 + # (with certificate check) where $HOME is not set + # Default: path in user home + # file_cache_dir = /var/lib/opensc/cache + # # Use PIN caching? # Default: true # use_pin_caching = false; diff --git a/src/common/libscdl.c b/src/common/libscdl.c index a78f9e2f..bc1d6b87 100644 --- a/src/common/libscdl.c +++ b/src/common/libscdl.c @@ -24,7 +24,7 @@ #include "libscdl.h" -#ifdef WIN32 +#ifdef _WIN32 #include void *sc_dlopen(const char *filename) { diff --git a/src/libopensc/apdu.c b/src/libopensc/apdu.c index 39c0294b..451c7063 100644 --- a/src/libopensc/apdu.c +++ b/src/libopensc/apdu.c @@ -581,7 +581,7 @@ int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu) * bytes using command chaining */ size_t len = apdu->datalen; const u8 *buf = apdu->data; - size_t max_send_size = card->max_send_size; + size_t max_send_size = sc_get_max_send_size(card); while (len != 0) { size_t plen; diff --git a/src/libopensc/card-dnie.c b/src/libopensc/card-dnie.c index 90cb4241..0b25b845 100644 --- a/src/libopensc/card-dnie.c +++ b/src/libopensc/card-dnie.c @@ -871,7 +871,7 @@ static int dnie_compose_and_send_apdu(sc_card_t *card, const u8 *path, size_t pa apdu.lc = pathlen; apdu.data = path; apdu.datalen = pathlen; - apdu.le = card->max_recv_size; + apdu.le = sc_get_max_recv_size(card); if (p1 == 3) apdu.cse= SC_APDU_CASE_1; diff --git a/src/libopensc/card-masktech.c b/src/libopensc/card-masktech.c index 9cd501e9..ee8f6d30 100644 --- a/src/libopensc/card-masktech.c +++ b/src/libopensc/card-masktech.c @@ -32,13 +32,13 @@ #include "iso7816.h" static struct sc_atr_table masktech_atrs[] = { - {"3B:89:80:01:4D:54:43:4F:53:70:02:02:05:3B", NULL, NULL, + {"3B:89:80:01:4D:54:43:4F:53:70:02:00:04:31", + "FF:FF:FF:FF:FF:FF:FF:FF:FF:FC:FF:FC:F4:F5" , NULL, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, - {"3B:88:80:01:00:00:00:00:77:81:81:00:7E", NULL, NULL, + {"3B:88:80:01:00:00:00:00:77:81:80:00:6E", "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:EE:FF:EE", NULL, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, - {"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:02:05:41", NULL, NULL, - SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, - {"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:01:02:45", NULL, NULL, + {"3B:9D:13:81:31:60:35:80:31:C0:69:4D:54:43:4F:53:73:02:00:00:40", + "FF:FF:FF:FF:FF:FF:FD:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FC:F0:F0", NULL, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, {NULL, NULL, NULL, 0, 0, NULL} }; diff --git a/src/libopensc/card-myeid.c b/src/libopensc/card-myeid.c index 9d6417f1..ead6ba9a 100644 --- a/src/libopensc/card-myeid.c +++ b/src/libopensc/card-myeid.c @@ -170,7 +170,7 @@ static int myeid_init(struct sc_card *card) #endif /* State that we have an RNG */ - card->caps |= SC_CARD_CAP_RNG; + card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO; card->max_recv_size = 255; card->max_send_size = 255; @@ -524,42 +524,6 @@ static int myeid_delete_file(struct sc_card *card, const struct sc_path *path) LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); } -static int myeid_pin_info(sc_card_t *card, struct sc_pin_cmd_data *data, - int *tries_left) -{ - sc_apdu_t apdu; - int r; - - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, data->pin_reference); - - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - - if (r == SC_ERROR_PIN_CODE_INCORRECT) { - data->pin1.tries_left = apdu.sw2 & 0xF; - r = SC_SUCCESS; - } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { - data->pin1.tries_left = 0; - r = SC_SUCCESS; - } - LOG_TEST_RET(card->ctx, r, "Check SW error"); - - if (r == SC_SUCCESS) - { - data->pin1.pad_length = data->pin2.pad_length = 8; - data->pin1.pad_char = data->pin2.pad_char = 0xFF; - } - - - if (tries_left != NULL) { - *tries_left = data->pin1.tries_left; - } - - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); -} - static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) { @@ -567,11 +531,6 @@ static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, LOG_FUNC_CALLED(card->ctx); - if (data->cmd == SC_PIN_CMD_GET_INFO) - { - return myeid_pin_info(card, data, tries_left); - } - sc_log(card->ctx, "ref (%d), pin1 len(%d), pin2 len (%d)\n", data->pin_reference, data->pin1.len, data->pin2.len); diff --git a/src/libopensc/card-piv.c b/src/libopensc/card-piv.c index c12c9bd4..218d74d3 100644 --- a/src/libopensc/card-piv.c +++ b/src/libopensc/card-piv.c @@ -2895,7 +2895,7 @@ static int piv_init(sc_card_t *card) _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); _sc_card_add_ec_alg(card, 384, flags, ext_flags, NULL); - card->caps |= SC_CARD_CAP_RNG; + card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO; /* * 800-73-3 cards may have a history object and/or a discovery object @@ -2912,6 +2912,27 @@ static int piv_init(sc_card_t *card) } +static int piv_check_sw(struct sc_card *card, unsigned int sw1, unsigned int sw2) +{ + struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); + + const u8 *yubikey_neo_atr = + (const u8*)"\x3B\xFC\x13\x00\x00\x81\x31\xFE\x15\x59\x75\x62\x69\x6B\x65\x79\x4E\x45\x4F\x72\x33\xE1"; + if (card->atr.len != 22 || memcmp(card->atr.value, yubikey_neo_atr, 22) != 0) + return iso_drv->ops->check_sw(card, sw1, sw2); + + /* Handle here the Yubikey NEO, which returns 0x0X rather than 0xCX to + * indicate the number of remaining PIN retries. Perhaps they misread the + * spec and thought 0xCX meant "clear" or "don't care", not a literal 0xC! */ + if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0x00U && sw2 != 0) { + sc_log(card->ctx, "Verification failed (remaining tries: %d)", (sw2 & 0x0f)); + return SC_ERROR_PIN_CODE_INCORRECT; + } + + return iso_drv->ops->check_sw(card, sw1, sw2); +} + + static int piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left) { @@ -2952,6 +2973,7 @@ static struct sc_card_driver * sc_get_driver(void) piv_ops.restore_security_env = piv_restore_security_env; piv_ops.compute_signature = piv_compute_signature; piv_ops.decipher = piv_decipher; + piv_ops.check_sw = piv_check_sw; piv_ops.card_ctl = piv_card_ctl; piv_ops.pin_cmd = piv_pin_cmd; diff --git a/src/libopensc/card-sc-hsm.c b/src/libopensc/card-sc-hsm.c index e4fab7bd..f23475ff 100644 --- a/src/libopensc/card-sc-hsm.c +++ b/src/libopensc/card-sc-hsm.c @@ -137,37 +137,6 @@ static int sc_hsm_match_card(struct sc_card *card) -static int sc_hsm_pin_info(sc_card_t *card, struct sc_pin_cmd_data *data, - int *tries_left) -{ - sc_apdu_t apdu; - int r; - - sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, data->pin_reference); - - r = sc_transmit_apdu(card, &apdu); - LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - - r = sc_check_sw(card, apdu.sw1, apdu.sw2); - - if (r == SC_ERROR_PIN_CODE_INCORRECT) { - data->pin1.tries_left = apdu.sw2 & 0xF; - r = SC_SUCCESS; - } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { - data->pin1.tries_left = 0; - r = SC_SUCCESS; - } - LOG_TEST_RET(card->ctx, r, "Check SW error"); - - if (tries_left != NULL) { - *tries_left = data->pin1.tries_left; - } - - LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); -} - - - /* * Encode 16 hexadecimals of SO-PIN into binary form * Caller must check length of sopin and provide an 8 byte buffer @@ -206,9 +175,6 @@ 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; int r; - if (data->cmd == SC_PIN_CMD_GET_INFO) { - return sc_hsm_pin_info(card, data, tries_left); - } if ((data->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) { if (data->pin1.len != 16) return SC_ERROR_INVALID_PIN_LENGTH; @@ -249,7 +215,7 @@ static int sc_hsm_read_binary(sc_card_t *card, cmdbuff[2] = (idx >> 8) & 0xFF; cmdbuff[3] = idx & 0xFF; - assert(count <= card->max_recv_size); + assert(count <= sc_get_max_recv_size(card)); sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB1, 0x00, 0x00); apdu.data = cmdbuff; apdu.datalen = 4; @@ -867,7 +833,7 @@ static int sc_hsm_init_token(sc_card_t *card, sc_cardctl_pkcs11_init_token_t *pa memset(&ip, 0, sizeof(ip)); ip.dkek_shares = -1; ip.options[0] = 0x00; - ip.options[0] = 0x01; + ip.options[1] = 0x01; r = sc_hsm_encode_sopin(params->so_pin, ip.init_code); LOG_TEST_RET(ctx, r, "SO PIN wrong format"); @@ -1058,7 +1024,7 @@ static int sc_hsm_init(struct sc_card *card) _sc_card_add_ec_alg(card, 256, flags, ext_flags, NULL); _sc_card_add_ec_alg(card, 320, flags, ext_flags, NULL); - card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT; + card->caps |= SC_CARD_CAP_RNG|SC_CARD_CAP_APDU_EXT|SC_CARD_CAP_ISO7816_PIN_INFO; 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 diff --git a/src/libopensc/card-sc-hsm.h b/src/libopensc/card-sc-hsm.h index 12d18673..325f73fd 100644 --- a/src/libopensc/card-sc-hsm.h +++ b/src/libopensc/card-sc-hsm.h @@ -50,6 +50,9 @@ #define ID_USER_PIN 0x81 /* User PIN identifier */ #define ID_SO_PIN 0x88 /* Security officer PIN identifier */ +#define INIT_RRC_ENABLED 0x01 /* Bit 1 of initialization options */ +#define INIT_TRANSPORT_PIN 0x02 /* Bit 2 of initialization options */ + /* Information the driver maintains between calls */ typedef struct sc_hsm_private_data { const sc_security_env_t *env; diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 50da8ff8..1c7ae2fc 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -135,6 +135,54 @@ static void sc_card_free(sc_card_t *card) free(card); } +size_t sc_get_max_recv_size(const sc_card_t *card) +{ + size_t max_recv_size; + assert(card != NULL && card->reader != NULL); + max_recv_size = card->max_recv_size; + + /* initialize max_recv_size to a meaningfull value */ + if (card->caps & SC_CARD_CAP_APDU_EXT) { + if (!max_recv_size) + max_recv_size = 65536; + } else { + if (!max_recv_size) + max_recv_size = 256; + } + + /* Override card limitations with reader limitations. */ + if (card->reader->max_recv_size != 0 + && (card->reader->max_recv_size < card->max_recv_size)) + max_recv_size = card->reader->max_recv_size; + + return max_recv_size; +} + +size_t sc_get_max_send_size(const sc_card_t *card) +{ + size_t max_send_size; + + assert(card != NULL && card->reader != NULL); + + max_send_size = card->max_send_size; + + /* initialize max_send_size to a meaningfull value */ + if (card->caps & SC_CARD_CAP_APDU_EXT) { + if (!max_send_size) + max_send_size = 65535; + } else { + if (!max_send_size) + max_send_size = 255; + } + + /* Override card limitations with reader limitations. */ + if (card->reader->max_send_size != 0 + && (card->reader->max_send_size < card->max_send_size)) + max_send_size = card->reader->max_send_size; + + return max_send_size; +} + int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) { sc_card_t *card; @@ -252,25 +300,8 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) card->name = card->driver->name; /* initialize max_send_size/max_recv_size to a meaningfull value */ - if (card->caps & SC_CARD_CAP_APDU_EXT) { - if (!card->max_send_size) - card->max_send_size = 65535; - if (!card->max_recv_size) - card->max_recv_size = 65536; - } else { - if (!card->max_send_size) - card->max_send_size = 255; - if (!card->max_recv_size) - card->max_recv_size = 256; - } - - /* Override card limitations with reader limitations. */ - if (reader->max_recv_size != 0 - && (reader->max_recv_size < card->max_recv_size)) - card->max_recv_size = reader->max_recv_size; - if (reader->max_send_size != 0 - && (reader->max_send_size < card->max_send_size)) - card->max_send_size = reader->max_send_size; + card->max_recv_size = sc_get_max_recv_size(card); + card->max_send_size = sc_get_max_send_size(card); sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", card->name, card->type, card->flags, card->max_send_size, card->max_recv_size); @@ -489,7 +520,7 @@ int sc_delete_file(sc_card_t *card, const sc_path_t *path) int sc_read_binary(sc_card_t *card, unsigned int idx, unsigned char *buf, size_t count, unsigned long flags) { - size_t max_le = card->max_recv_size; + size_t max_le = sc_get_max_recv_size(card); int r; assert(card != NULL && card->ops != NULL && buf != NULL); @@ -539,7 +570,7 @@ int sc_read_binary(sc_card_t *card, unsigned int idx, int sc_write_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { - size_t max_lc = card->max_send_size; + size_t max_lc = sc_get_max_send_size(card); int r; assert(card != NULL && card->ops != NULL && buf != NULL); @@ -582,7 +613,7 @@ int sc_write_binary(sc_card_t *card, unsigned int idx, int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { - size_t max_lc = card->max_send_size; + size_t max_lc = sc_get_max_send_size(card); int r; assert(card != NULL && card->ops != NULL && buf != NULL); diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c index 15312f7e..c7154344 100644 --- a/src/libopensc/ctx.c +++ b/src/libopensc/ctx.c @@ -880,9 +880,18 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize) { char *homedir; const char *cache_dir; + scconf_block *conf_block = NULL; #ifdef _WIN32 char temp_path[PATH_MAX]; #endif + conf_block = sc_get_conf_block(ctx, "framework", "pkcs15", 1); + cache_dir = scconf_get_str(conf_block, "file_cache_dir", NULL); + if (cache_dir != NULL) { + if (bufsize <= strlen(cache_dir)) + return SC_ERROR_BUFFER_TOO_SMALL; + strcpy(buf, cache_dir); + return SC_SUCCESS; + } #ifndef _WIN32 cache_dir = ".eid/cache"; diff --git a/src/libopensc/internal-winscard.h b/src/libopensc/internal-winscard.h index 2389d0c5..c55856cd 100644 --- a/src/libopensc/internal-winscard.h +++ b/src/libopensc/internal-winscard.h @@ -21,7 +21,7 @@ typedef unsigned __int8 uint8_t; #include #endif // allow unicode built where SCARD_READERSTATE is defined as SCARD_READERSTATEW and SCardGetStatusChange renamed to SCardGetStatusChangeW -#ifdef WIN32 +#ifdef _WIN32 #ifdef UNICODE #define SCARD_READERSTATE SCARD_READERSTATEA #undef SCardGetStatusChange @@ -201,6 +201,8 @@ typedef LONG (PCSC_API *SCardGetAttrib_t)(SCARDHANDLE hCard, DWORD dwAttrId,\ #define PCSCv2_PART10_PROPERTY_sFirmwareID 8 #define PCSCv2_PART10_PROPERTY_bPPDUSupport 9 #define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10 +#define PCSCv2_PART10_PROPERTY_wIdVendor 11 +#define PCSCv2_PART10_PROPERTY_wIdProduct 12 /* structures used (but not defined) in PCSC Part 10: * "IFDs with Secure Pin Entry Capabilities" */ diff --git a/src/libopensc/iso7816.c b/src/libopensc/iso7816.c index 39b71868..f44f7065 100644 --- a/src/libopensc/iso7816.c +++ b/src/libopensc/iso7816.c @@ -35,15 +35,15 @@ static void fixup_transceive_length(const struct sc_card *card, { assert(card != NULL && apdu != NULL); - if (apdu->lc > card->max_send_size) { + if (apdu->lc > sc_get_max_send_size(card)) { /* The lower layers will automatically do chaining */ apdu->flags |= SC_APDU_FLAGS_CHAINING; } - if (apdu->le > card->max_recv_size) { + if (apdu->le > sc_get_max_recv_size(card)) { /* The lower layers will automatically do a GET RESPONSE, if possible. * All other workarounds must be carried out by the upper layers. */ - apdu->le = card->max_recv_size; + apdu->le = sc_get_max_recv_size(card); } } @@ -526,7 +526,7 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct apdu.p2 = 0; /* first record, return FCI */ apdu.resp = buf; apdu.resplen = sizeof(buf); - apdu.le = card->max_recv_size < 256 ? card->max_recv_size : 256; + apdu.le = sc_get_max_recv_size(card) < 256 ? sc_get_max_recv_size(card) : 256; } else { apdu.p2 = 0x0C; /* first record, return nothing */ @@ -719,8 +719,8 @@ iso7816_get_response(struct sc_card *card, size_t *count, u8 *buf) size_t rlen; /* request at most max_recv_size bytes */ - if (*count > card->max_recv_size) - rlen = card->max_recv_size; + if (*count > sc_get_max_recv_size(card)) + rlen = sc_get_max_recv_size(card); else rlen = *count; @@ -969,6 +969,7 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len) { int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0; + int cse = SC_APDU_CASE_3_SHORT; switch (data->pin_type) { case SC_AC_CHV: @@ -1034,11 +1035,16 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu, p1 |= 0x01; } break; + case SC_PIN_CMD_GET_INFO: + ins = 0x20; + /* No data to send or to receive */ + cse = SC_APDU_CASE_1; + break; default: return SC_ERROR_NOT_SUPPORTED; } - sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, ins, p1, data->pin_reference); + sc_format_apdu(card, apdu, cse, ins, p1, data->pin_reference); apdu->lc = len; apdu->datalen = len; apdu->data = buf; @@ -1058,6 +1064,16 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l if (tries_left) *tries_left = -1; + /* Many cards do support PIN status queries, but some cards don't and + * mistakenly count the command as a failed PIN attempt, so for now we + * whitelist cards with this flag. In future this may be reduced to a + * blacklist, subject to testing more cards. */ + if (data->cmd == SC_PIN_CMD_GET_INFO && + !(card->caps & SC_CARD_CAP_ISO7816_PIN_INFO)) { + sc_log(card->ctx, "Card does not support PIN status queries"); + return SC_ERROR_NOT_SUPPORTED; + } + /* See if we've been called from another card driver, which is * passing an APDU to us (this allows to write card drivers * whose PIN functions behave "mostly like ISO" except in some @@ -1071,7 +1087,7 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l } apdu = data->apdu; - if (!(data->flags & SC_PIN_CMD_USE_PINPAD)) { + if (!(data->flags & SC_PIN_CMD_USE_PINPAD) || data->cmd == SC_PIN_CMD_GET_INFO) { /* Transmit the APDU to the card */ r = sc_transmit_apdu(card, apdu); @@ -1101,12 +1117,23 @@ iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_l data->apdu = NULL; LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); - if (apdu->sw1 == 0x63) { - if ((apdu->sw2 & 0xF0) == 0xC0 && tries_left != NULL) - *tries_left = apdu->sw2 & 0x0F; - return SC_ERROR_PIN_CODE_INCORRECT; + r = sc_check_sw(card, apdu->sw1, apdu->sw2); + + if (data->cmd == SC_PIN_CMD_GET_INFO) { + if (r == SC_ERROR_PIN_CODE_INCORRECT) { + data->pin1.tries_left = apdu->sw2 & 0xF; + r = SC_SUCCESS; + } else if (r == SC_ERROR_AUTH_METHOD_BLOCKED) { + data->pin1.tries_left = 0; + r = SC_SUCCESS; + } + + if (tries_left != NULL) { + *tries_left = data->pin1.tries_left; + } } - return sc_check_sw(card, apdu->sw1, apdu->sw2); + + return r; } diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index e9a4d19a..979ef6d1 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -439,6 +439,9 @@ struct sc_reader_operations { /* Card has on-board random number source. */ #define SC_CARD_CAP_RNG 0x00000004 +/* Card supports ISO7816 PIN status queries using an empty VERIFY */ +#define SC_CARD_CAP_ISO7816_PIN_INFO 0x00000008 + /* Use the card's ACs in sc_pkcs15init_authenticate(), * instead of relying on the ACL info in the profile files. */ #define SC_CARD_CAP_USE_FCI_AC 0x00000010 @@ -910,6 +913,30 @@ int sc_lock(struct sc_card *card); */ int sc_unlock(struct sc_card *card); +/** + * @brief Calculate the maximum size of R-APDU payload (Ne). + * + * Takes card limitations into account such as extended length support as well + * as the reader's limitation for data transfer. + * + * @param card Initialized card object with its reader + * + * @return maximum Ne + */ +size_t sc_get_max_recv_size(const sc_card_t *card); + +/** + * @brief Calculate the maximum size of C-APDU payload (Nc). + * + * Takes card limitations into account such as extended length support as well + * as the reader's limitation for data transfer. + * + * @param card + * + * @return maximum Nc + */ +size_t sc_get_max_send_size(const sc_card_t *card); + /********************************************************************/ /* ISO 7816-4 related functions */ diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index ba9d6125..f7c49ef2 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -424,8 +424,9 @@ fix_starcos_pkcs15_card(struct sc_pkcs15_card *p15card) if (strcmp(p15card->card->driver->short_name,"cardos") == 0) { /* D-Trust cards (D-TRUST, D-SIGN) */ - if (strstr(p15card->tokeninfo->label,"D-TRUST") != NULL - || strstr(p15card->tokeninfo->label,"D-SIGN") != NULL) { + if (p15card->tokeninfo->label + && (strstr(p15card->tokeninfo->label,"D-TRUST") != NULL + || strstr(p15card->tokeninfo->label,"D-SIGN") != NULL)) { /* D-TRUST Card 2.0 2cc (standard cards, which always add * SHA1 prefix itself */ diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index b850db20..de137959 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -880,6 +880,46 @@ err: return max_data; } +static int part10_get_vendor_product(struct sc_reader *reader, + SCARDHANDLE card_handle, int *id_vendor, int *id_product) +{ + u8 rbuf[256]; + DWORD rcount = sizeof rbuf; + struct pcsc_private_data *priv; + /* 0 means no limitations */ + int this_vendor = -1, this_product = -1; + + if (!reader) + return SC_ERROR_INVALID_ARGUMENTS; + priv = GET_PRIV_DATA(reader); + if (!priv) + return SC_ERROR_INVALID_ARGUMENTS; + + if (priv->get_tlv_properties && priv->gpriv) { + if (SCARD_S_SUCCESS != priv->gpriv->SCardControl(card_handle, + priv->get_tlv_properties, NULL, 0, rbuf, sizeof(rbuf), + &rcount)) { + sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, + "PC/SC v2 part 10: Get TLV properties failed!"); + return SC_ERROR_TRANSMIT_FAILED; + } + + this_vendor = part10_find_property_by_tag(rbuf, rcount, + PCSCv2_PART10_PROPERTY_wIdVendor); + this_product = part10_find_property_by_tag(rbuf, rcount, + PCSCv2_PART10_PROPERTY_wIdProduct); + } + + sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "id_vendor=%04x id_product=%04x", this_vendor, this_product); + + if (id_vendor) + *id_vendor = this_vendor; + if (id_product) + *id_product = this_product; + + return SC_SUCCESS; +} + static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) { sc_context_t *ctx = reader->ctx; struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data; @@ -889,7 +929,6 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) PCSC_TLV_STRUCTURE *pcsc_tlv; LONG rv; const char *log_disabled = "but it's disabled in configuration file"; - const char *broken_readers[] = {"HP USB Smart Card Keyboard"}; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); @@ -957,14 +996,6 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) } } - /* Ignore advertised pinpad capability on readers known to be broken. Trac #340 */ - for (i = 0; i < sizeof(broken_readers)/sizeof(broken_readers[0]); i++) { - if (strstr(reader->name, broken_readers[i]) && (reader->capabilities & SC_READER_CAP_PIN_PAD)) { - sc_log(ctx, "%s has a broken pinpad, ignoring", reader->name); - reader->capabilities &= ~SC_READER_CAP_PIN_PAD; - } - } - /* Detect display */ if (priv->pin_properties_ioctl) { rcount = sizeof(rbuf); @@ -1004,10 +1035,15 @@ static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) } } - /* Set reader max_send_size and max_recv_size based on detected max_data */ if (priv->get_tlv_properties) { - reader->max_send_size = part10_detect_max_data(reader, card_handle); + /* Set reader max_send_size and max_recv_size based on + * detected max_data */ + reader->max_send_size = part10_detect_max_data(reader, + card_handle); reader->max_recv_size = reader->max_send_size; + + /* debug the product and vendor ID of the reader */ + part10_get_vendor_product(reader, card_handle, NULL, NULL); } } diff --git a/src/pkcs11/Makefile.am b/src/pkcs11/Makefile.am index c8ed808e..aac6739c 100644 --- a/src/pkcs11/Makefile.am +++ b/src/pkcs11/Makefile.am @@ -12,7 +12,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src OPENSC_PKCS11_INC = sc-pkcs11.h pkcs11.h pkcs11-opensc.h OPENSC_PKCS11_SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \ mechanism.c openssl.c framework-pkcs15.c \ - framework-pkcs15init.c debug.c opensc-pkcs11.exports \ + framework-pkcs15init.c debug.c pkcs11.exports \ pkcs11-display.c pkcs11-display.h OPENSC_PKCS11_LIBS = \ $(top_builddir)/src/libopensc/libopensc.la \ @@ -23,23 +23,23 @@ OPENSC_PKCS11_LIBS = \ opensc_pkcs11_la_SOURCES = $(OPENSC_PKCS11_SRC) $(OPENSC_PKCS11_INC) opensc_pkcs11_la_LIBADD = $(OPENSC_PKCS11_LIBS) opensc_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) \ - -export-symbols "$(srcdir)/opensc-pkcs11.exports" \ + -export-symbols "$(srcdir)/pkcs11.exports" \ -module -shared -avoid-version -no-undefined onepin_opensc_pkcs11_la_SOURCES = $(OPENSC_PKCS11_SRC) $(OPENSC_PKCS11_INC) onepin_opensc_pkcs11_la_CFLAGS = -DMODULE_APP_NAME=\"onepin-opensc-pkcs11\" onepin_opensc_pkcs11_la_LIBADD = $(OPENSC_PKCS11_LIBS) onepin_opensc_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) \ - -export-symbols "$(srcdir)/opensc-pkcs11.exports" \ + -export-symbols "$(srcdir)/pkcs11.exports" \ -module -shared -avoid-version -no-undefined -pkcs11_spy_la_SOURCES = pkcs11-spy.c pkcs11-display.c pkcs11-display.h pkcs11-spy.exports +pkcs11_spy_la_SOURCES = pkcs11-spy.c pkcs11-display.c pkcs11-display.h pkcs11.exports pkcs11_spy_la_LIBADD = \ $(top_builddir)/src/common/libpkcs11.la \ $(top_builddir)/src/common/libscdl.la \ $(OPTIONAL_OPENSSL_LIBS) pkcs11_spy_la_LDFLAGS = $(AM_LDFLAGS) \ - -export-symbols "$(srcdir)/pkcs11-spy.exports" \ + -export-symbols "$(srcdir)/pkcs11.exports" \ -module -shared -avoid-version -no-undefined if WIN32 diff --git a/src/pkcs11/Makefile.mak b/src/pkcs11/Makefile.mak index e3cdfbda..7fcdb930 100644 --- a/src/pkcs11/Makefile.mak +++ b/src/pkcs11/Makefile.mak @@ -16,14 +16,14 @@ all: versioninfo-pkcs11.res $(TARGET1) $(TARGET2) $(TARGET3) versioninfo-pkcs11- $(TARGET1): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib echo LIBRARY $* > $*.def echo EXPORTS >> $*.def - type opensc-pkcs11.exports >> $*.def + type pkcs11.exports >> $*.def link $(LINKFLAGS) /dll /def:$*.def /implib:$*.lib /out:$(TARGET1) $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib $(OPENSSL_LIB) gdi32.lib if EXIST $(TARGET1).manifest mt -manifest $(TARGET1).manifest -outputresource:$(TARGET1);2 $(TARGET2): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib echo LIBRARY $* > $*.def echo EXPORTS >> $*.def - type opensc-pkcs11.exports >> $*.def + type pkcs11.exports >> $*.def del pkcs11-global.obj cl $(CODE_OPTIMIZATION) $(COPTS) /DMODULE_APP_NAME=\"onepin-opensc-pkcs11\" /c pkcs11-global.c link $(LINKFLAGS) /dll /def:$*.def /implib:$*.lib /out:$(TARGET2) $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib $(OPENSSL_LIB) gdi32.lib @@ -32,6 +32,6 @@ $(TARGET2): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib $(TARGET3): $(OBJECTS3) ..\libopensc\opensc.lib echo LIBRARY $* > $*.def echo EXPORTS >> $*.def - type $*.exports >> $*.def + type pkcs11.exports >> $*.def link $(LINKFLAGS) /dll /def:$*.def /implib:$*.lib /out:$(TARGET3) $(OBJECTS3) ..\libopensc\opensc.lib ..\common\libpkcs11.lib ..\common\libscdl.lib $(OPENSSL_LIB) gdi32.lib advapi32.lib if EXIST $(TARGET3).manifest mt -manifest $(TARGET3).manifest -outputresource:$(TARGET3);2 diff --git a/src/pkcs11/opensc-pkcs11.exports b/src/pkcs11/opensc-pkcs11.exports deleted file mode 100644 index 562ecea2..00000000 --- a/src/pkcs11/opensc-pkcs11.exports +++ /dev/null @@ -1 +0,0 @@ -C_GetFunctionList diff --git a/src/pkcs11/pkcs11-spy.exports b/src/pkcs11/pkcs11-spy.exports deleted file mode 100644 index 562ecea2..00000000 --- a/src/pkcs11/pkcs11-spy.exports +++ /dev/null @@ -1 +0,0 @@ -C_GetFunctionList diff --git a/src/pkcs11/pkcs11.exports b/src/pkcs11/pkcs11.exports new file mode 100644 index 00000000..edc62c26 --- /dev/null +++ b/src/pkcs11/pkcs11.exports @@ -0,0 +1,3 @@ +C_GetFunctionList +C_Initialize +C_Finalize diff --git a/src/tools/pkcs15-tool.c b/src/tools/pkcs15-tool.c index 4b0cbd85..92d51c9c 100644 --- a/src/tools/pkcs15-tool.c +++ b/src/tools/pkcs15-tool.c @@ -50,6 +50,7 @@ static char * opt_auth_id = NULL; static char * opt_reader = NULL; static char * opt_cert = NULL; static char * opt_data = NULL; +static int opt_raw = 0; static char * opt_pubkey = NULL; static char * opt_outfile = NULL; static char * opt_bind_to_aid = NULL; @@ -82,6 +83,7 @@ enum { OPT_LIST_APPLICATIONS, OPT_LIST_SKEYS, OPT_NO_PROMPT, + OPT_RAW, }; #define NELEMENTS(x) (sizeof(x)/sizeof((x)[0])) @@ -94,6 +96,7 @@ static const struct option options[] = { { "read-certificate", required_argument, NULL, 'r' }, { "list-certificates", no_argument, NULL, 'c' }, { "read-data-object", required_argument, NULL, 'R' }, + { "raw", no_argument, NULL, OPT_RAW }, { "list-data-objects", no_argument, NULL, 'C' }, { "list-pins", no_argument, NULL, OPT_LIST_PINS }, { "list-secret-keys", no_argument, NULL, OPT_LIST_SKEYS }, @@ -130,6 +133,7 @@ static const char *option_help[] = { "Reads certificate with ID ", "Lists certificates", "Reads data object with OID, applicationName or label ", + "Outputs raw 8 bit data to stdout. File output will not be affected by this, it always uses raw mode.", "Lists data objects", "Lists PIN codes", "Lists secret keys", @@ -346,18 +350,28 @@ print_data_object(const char *kind, const u8*data, size_t data_len) } for (i=0; i < data_len; i++) fprintf(outf, "%c", data[i]); - printf("Dumping (%lu bytes) to file <%s>: <", - (unsigned long) data_len, opt_outfile); - for (i=0; i < data_len; i++) - printf(" %02X", data[i]); - printf(" >\n"); + if (opt_raw) { + for (i=0; i < data_len; i++) + printf("%c", data[i]); + } else { + printf("Dumping (%lu bytes) to file <%s>: <", + (unsigned long) data_len, opt_outfile); + for (i=0; i < data_len; i++) + printf(" %02X", data[i]); + printf(" >\n"); + } fclose(outf); } else { - printf("%s (%lu bytes): <", - kind, (unsigned long) data_len); - for (i=0; i < data_len; i++) - printf(" %02X", data[i]); - printf(" >\n"); + if (opt_raw) { + for (i=0; i < data_len; i++) + printf("%c", data[i]); + } else { + printf("%s (%lu bytes): <", + kind, (unsigned long) data_len); + for (i=0; i < data_len; i++) + printf(" %02X", data[i]); + printf(" >\n"); + } } return 0; } @@ -1564,11 +1578,47 @@ static int read_and_cache_file(const sc_path_t *path) printf("out of memory!"); return -1; } - r = sc_read_binary(card, 0, buf, size, 0); - if (r < 0) { - fprintf(stderr, "sc_read_binary() failed: %s\n", sc_strerror(r)); - free(buf); - return -1; + if (tfile->ef_structure == SC_FILE_EF_LINEAR_VARIABLE_TLV) { + int i; + size_t l, record_len; + unsigned char *head = buf; + + for (i=1; ; i++) { + l = size - (head - buf); + if (l > 256) { l = 256; } + r = sc_read_record(p15card->card, i, head, l, SC_RECORD_BY_REC_NR); + if (r == SC_ERROR_RECORD_NOT_FOUND) { + r = 0; + break; + } + if (r < 0) { + free(buf); + return -1; + } + if (r < 2) + break; + record_len = head[1]; + if (record_len != 0xff) { + memmove(head,head+2,r-2); + head += (r-2); + } + else { + if (r < 4) + break; + memmove(head,head+4,r-4); + head += (r-4); + } + } + r = head - buf; + + } else { + + r = sc_read_binary(card, 0, buf, size, 0); + if (r < 0) { + fprintf(stderr, "sc_read_binary() failed: %s\n", sc_strerror(r)); + free(buf); + return -1; + } } r = sc_pkcs15_cache_file(p15card, path, buf, r); if (r) { @@ -1895,6 +1945,9 @@ int main(int argc, char * const argv[]) do_read_data_object = 1; action_count++; break; + case OPT_RAW: + opt_raw = 1; + break; case 'C': do_list_data_objects = 1; action_count++; diff --git a/src/tools/sc-hsm-tool.c b/src/tools/sc-hsm-tool.c index 22680c33..8fa26c18 100644 --- a/src/tools/sc-hsm-tool.c +++ b/src/tools/sc-hsm-tool.c @@ -461,27 +461,75 @@ static void print_info(sc_card_t *card, sc_file_t *file) struct sc_pin_cmd_data data; sc_cardctl_sc_hsm_dkek_t dkekinfo; - u8 major, minor; + u8 major, minor, opt; major = file->prop_attr[file->prop_attr_len - 2]; minor = file->prop_attr[file->prop_attr_len - 1]; printf("Version : %d.%d\n", (int)major, (int)minor); - /* Try to update PIN info from card */ - memset(&data, 0, sizeof(data)); - data.cmd = SC_PIN_CMD_GET_INFO; - data.pin_type = SC_AC_CHV; - data.pin_reference = ID_USER_PIN; + if (file->prop_attr_len > 2) { /* Version >= 2.0 */ + opt = file->prop_attr[file->prop_attr_len - 4]; + if (opt != 0) { + printf("Config options :\n"); + if (opt & INIT_RRC_ENABLED) { + printf(" User PIN reset with SO-PIN enabled\n"); + } + if (opt & INIT_TRANSPORT_PIN) { + printf(" Transport-PIN mode enabled\n"); + } + } - r = sc_pin_cmd(card, &data, &tries_left); + /* Try to update SO-PIN info from card */ + memset(&data, 0, sizeof(data)); + data.cmd = SC_PIN_CMD_GET_INFO; + data.pin_type = SC_AC_CHV; + data.pin_reference = ID_SO_PIN; - if (r == SC_ERROR_REF_DATA_NOT_USABLE) { - printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n"); - } else { - if (tries_left == 0) { - printf("User PIN locked\n"); + r = sc_pin_cmd(card, &data, &tries_left); + if (r == SC_ERROR_DATA_OBJECT_NOT_FOUND) { + printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n"); } else { - printf("User PIN tries left : %d\n", tries_left); + if (tries_left == 0) { + printf("SO-PIN locked\n"); + } else { + printf("SO-PIN tries left : %d\n", tries_left); + } + /* Try to update PIN info from card */ + memset(&data, 0, sizeof(data)); + data.cmd = SC_PIN_CMD_GET_INFO; + data.pin_type = SC_AC_CHV; + data.pin_reference = ID_USER_PIN; + + r = sc_pin_cmd(card, &data, &tries_left); + if (r == SC_ERROR_CARD_CMD_FAILED) { + printf("Public key authentication active.\n"); + } else if (r == SC_ERROR_REF_DATA_NOT_USABLE) { + printf("Transport-PIN active. Please change to user selected PIN first.\n"); + } else { + if (tries_left == 0) { + printf("User PIN locked\n"); + } else { + printf("User PIN tries left : %d\n", tries_left); + } + } + } + } else { /* Version < 2.0 */ + /* Try to update PIN info from card */ + memset(&data, 0, sizeof(data)); + data.cmd = SC_PIN_CMD_GET_INFO; + data.pin_type = SC_AC_CHV; + data.pin_reference = ID_USER_PIN; + + r = sc_pin_cmd(card, &data, &tries_left); + + if (r == SC_ERROR_REF_DATA_NOT_USABLE) { + printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n"); + } else { + if (tries_left == 0) { + printf("User PIN locked\n"); + } else { + printf("User PIN tries left : %d\n", tries_left); + } } } diff --git a/win32/customactions.cpp b/win32/customactions.cpp index 988e1ffd..5da7ec91 100644 --- a/win32/customactions.cpp +++ b/win32/customactions.cpp @@ -78,14 +78,12 @@ MD_REGISTRATION minidriver_registration[] = { 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, /* from card-masktech.c */ /* note: the card name MUST be unique */ - {TEXT("MaskTech smart card (a)"), {0x3b,0x89,0x80,0x01,0x4d,0x54,0x43,0x4f,0x53,0x70,0x02,0x02,0x05,0x3b}, - 14, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("MaskTech smart card (b)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x37,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x02,0x05,0x41}, - 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("MaskTech smart card (c)"), {0x3B,0x88,0x80,0x01,0x00,0x00,0x00,0x00,0x77,0x81,0x81,0x00,0x7E}, - 13, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, - {TEXT("MaskTech smart card (d)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x37,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x01,0x02,0x45}, - 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, + {TEXT("MaskTech smart card (a)"), {0x3b,0x89,0x80,0x01,0x4d,0x54,0x43,0x4f,0x53,0x70,0x02,0x00,0x04,0x31}, + 14, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xff,0xfc,0xf4,0xf5}}, + {TEXT("MaskTech smart card (b)"), {0x3B,0x9D,0x13,0x81,0x31,0x60,0x35,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x00,0x00,0x40}, + 21, {0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0xf0,0xf0}}, + {TEXT("MaskTech smart card (c)"), {0x3B,0x88,0x80,0x01,0x00,0x00,0x00,0x00,0x77,0x81,0x80,0x00,0x6E}, + 13, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xee,0xff,0xee}}, };