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}},
};