Merge branch 'master' into gnuk

This commit is contained in:
Nguyễn Hồng Quân 2015-09-13 22:09:59 +08:00
commit 76b6b483c7
28 changed files with 472 additions and 185 deletions

View File

@ -88,4 +88,12 @@ pkgbuild --nopayload --identifier org.opensc-project.mac.uninstall --scripts Mac
# Create .dmg # Create .dmg
rm -f OpenSC-@PACKAGE_VERSION@.dmg rm -f OpenSC-@PACKAGE_VERSION@.dmg
TIMESTAMP=$(date +%Y.%m.%d) 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

View File

@ -12,3 +12,5 @@ Jenkins CI:
Travis CI: Travis CI:
[![Build Status](https://api.travis-ci.org/OpenSC/OpenSC.png)](https://travis-ci.org/OpenSC/OpenSC) [![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)

71
appveyor.yml Normal file
View File

@ -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</dev/null && find C:/zlib-1.2.8-dll"
- bash -c "exec 0</dev/null && find C:/OpenSSL"
- bash -c "exec 0</dev/null && ./bootstrap"
- bash -c "exec 0</dev/null && ./configure OPENSSL_LIBS='-LC:/OpenSSL/lib -llibeay32' OPENSSL_CFLAGS='-IC:/OpenSSL/include' ZLIB_CFLAGS='-IC:/zlib-1.2.8-dll/include' ZLIB_LIBS='-LC:/zlib-1.2.8-dll/lib -lzdll' LDFLAGS='-LC:/OpenSSL/bin -LC:/zlib-1.2.5-dll' --with-cygwin-native"
- bash -c "exec 0</dev/null && cp win32/winconfig.h config.h && make"
# nmake doesn't work out of the box, all Makefile.mak have way too many hard coded paths
#- bash -c "exec 0</dev/null && ./bootstrap >> /tmp/oscout 2>&1 && ./configure >> /tmp/oscout 2>&1"
#- nmake /f Makefile.mak %NMAKE_FLAGS%

View File

@ -154,6 +154,18 @@
If this option is not given, keys will be printed to standard output.</para></listitem> If this option is not given, keys will be printed to standard output.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>
<option>--raw</option>
</term>
<listitem><para>Changes how <option>--read-data-object</option> prints the content
to standard output. By default, when <option>--raw</option> is not given, it will
print the content in hex notation. If <option>--raw</option> 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>--output</option> option. Data written to a file will
always be in raw binary.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term> <term>
<option>--read-certificate</option> <replaceable>cert</replaceable>, <option>--read-certificate</option> <replaceable>cert</replaceable>,
@ -168,7 +180,12 @@
<option>-R</option> <replaceable>data</replaceable> <option>-R</option> <replaceable>data</replaceable>
</term> </term>
<listitem><para>Reads data object with OID, applicationName or label. <listitem><para>Reads data object with OID, applicationName or label.
</para></listitem> The content is printed to standard output in hex notation, unless
the <option>--raw</option> option is given.
If an output file is given with the <option>--output</option> option,
the content is additionally written to the file.
Output to the file is always written in raw binary mode, the
<option>--raw</option> only affects standard output behavior.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -431,6 +431,12 @@ app default {
# Default: false # Default: false
# use_file_caching = true; # 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? # Use PIN caching?
# Default: true # Default: true
# use_pin_caching = false; # use_pin_caching = false;

View File

@ -24,7 +24,7 @@
#include "libscdl.h" #include "libscdl.h"
#ifdef WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
void *sc_dlopen(const char *filename) void *sc_dlopen(const char *filename)
{ {

View File

@ -581,7 +581,7 @@ int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu)
* bytes using command chaining */ * bytes using command chaining */
size_t len = apdu->datalen; size_t len = apdu->datalen;
const u8 *buf = apdu->data; 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) { while (len != 0) {
size_t plen; size_t plen;

View File

@ -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.lc = pathlen;
apdu.data = path; apdu.data = path;
apdu.datalen = pathlen; apdu.datalen = pathlen;
apdu.le = card->max_recv_size; apdu.le = sc_get_max_recv_size(card);
if (p1 == 3) if (p1 == 3)
apdu.cse= SC_APDU_CASE_1; apdu.cse= SC_APDU_CASE_1;

View File

@ -32,13 +32,13 @@
#include "iso7816.h" #include "iso7816.h"
static struct sc_atr_table masktech_atrs[] = { 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}, 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}, 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, {"3B:9D:13:81:31:60:35:80:31:C0:69:4D:54:43:4F:53:73:02:00:00:40",
SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, "FF:FF:FF:FF:FF:FF:FD:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FC:F0:F0", NULL,
{"3B:9D:13:81:31:60:37:80:31:C0:69:4D:54:43:4F:53:73:02:01:02:45", NULL, NULL,
SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL}, SC_CARD_TYPE_MASKTECH_GENERIC, 0, NULL},
{NULL, NULL, NULL, 0, 0, NULL} {NULL, NULL, NULL, 0, 0, NULL}
}; };

View File

@ -170,7 +170,7 @@ static int myeid_init(struct sc_card *card)
#endif #endif
/* State that we have an RNG */ /* 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_recv_size = 255;
card->max_send_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)); 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, static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
int *tries_left) 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); 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", sc_log(card->ctx, "ref (%d), pin1 len(%d), pin2 len (%d)\n",
data->pin_reference, data->pin1.len, data->pin2.len); data->pin_reference, data->pin1.len, data->pin2.len);

View File

@ -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, 256, flags, ext_flags, NULL);
_sc_card_add_ec_alg(card, 384, 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 * 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, static int piv_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
int *tries_left) 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.restore_security_env = piv_restore_security_env;
piv_ops.compute_signature = piv_compute_signature; piv_ops.compute_signature = piv_compute_signature;
piv_ops.decipher = piv_decipher; piv_ops.decipher = piv_decipher;
piv_ops.check_sw = piv_check_sw;
piv_ops.card_ctl = piv_card_ctl; piv_ops.card_ctl = piv_card_ctl;
piv_ops.pin_cmd = piv_pin_cmd; piv_ops.pin_cmd = piv_pin_cmd;

View File

@ -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 * Encode 16 hexadecimals of SO-PIN into binary form
* Caller must check length of sopin and provide an 8 byte buffer * 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; sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data;
int r; 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->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) {
if (data->pin1.len != 16) if (data->pin1.len != 16)
return SC_ERROR_INVALID_PIN_LENGTH; 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[2] = (idx >> 8) & 0xFF;
cmdbuff[3] = idx & 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); sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0xB1, 0x00, 0x00);
apdu.data = cmdbuff; apdu.data = cmdbuff;
apdu.datalen = 4; 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)); memset(&ip, 0, sizeof(ip));
ip.dkek_shares = -1; ip.dkek_shares = -1;
ip.options[0] = 0x00; ip.options[0] = 0x00;
ip.options[0] = 0x01; ip.options[1] = 0x01;
r = sc_hsm_encode_sopin(params->so_pin, ip.init_code); r = sc_hsm_encode_sopin(params->so_pin, ip.init_code);
LOG_TEST_RET(ctx, r, "SO PIN wrong format"); 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, 256, flags, ext_flags, NULL);
_sc_card_add_ec_alg(card, 320, 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_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 card->max_recv_size = 0; // Card supports sending with extended length APDU and without limit

View File

@ -50,6 +50,9 @@
#define ID_USER_PIN 0x81 /* User PIN identifier */ #define ID_USER_PIN 0x81 /* User PIN identifier */
#define ID_SO_PIN 0x88 /* Security officer 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 */ /* Information the driver maintains between calls */
typedef struct sc_hsm_private_data { typedef struct sc_hsm_private_data {
const sc_security_env_t *env; const sc_security_env_t *env;

View File

@ -135,6 +135,54 @@ static void sc_card_free(sc_card_t *card)
free(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) int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out)
{ {
sc_card_t *card; 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; card->name = card->driver->name;
/* initialize max_send_size/max_recv_size to a meaningfull value */ /* initialize max_send_size/max_recv_size to a meaningfull value */
if (card->caps & SC_CARD_CAP_APDU_EXT) { card->max_recv_size = sc_get_max_recv_size(card);
if (!card->max_send_size) card->max_send_size = sc_get_max_send_size(card);
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;
sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", 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); 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, int sc_read_binary(sc_card_t *card, unsigned int idx,
unsigned char *buf, size_t count, unsigned long flags) 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; int r;
assert(card != NULL && card->ops != NULL && buf != NULL); 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, int sc_write_binary(sc_card_t *card, unsigned int idx,
const u8 *buf, size_t count, unsigned long flags) 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; int r;
assert(card != NULL && card->ops != NULL && buf != NULL); 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, int sc_update_binary(sc_card_t *card, unsigned int idx,
const u8 *buf, size_t count, unsigned long flags) 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; int r;
assert(card != NULL && card->ops != NULL && buf != NULL); assert(card != NULL && card->ops != NULL && buf != NULL);

View File

@ -880,9 +880,18 @@ int sc_get_cache_dir(sc_context_t *ctx, char *buf, size_t bufsize)
{ {
char *homedir; char *homedir;
const char *cache_dir; const char *cache_dir;
scconf_block *conf_block = NULL;
#ifdef _WIN32 #ifdef _WIN32
char temp_path[PATH_MAX]; char temp_path[PATH_MAX];
#endif #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 #ifndef _WIN32
cache_dir = ".eid/cache"; cache_dir = ".eid/cache";

View File

@ -21,7 +21,7 @@ typedef unsigned __int8 uint8_t;
#include <wintypes.h> #include <wintypes.h>
#endif #endif
// allow unicode built where SCARD_READERSTATE is defined as SCARD_READERSTATEW and SCardGetStatusChange renamed to SCardGetStatusChangeW // allow unicode built where SCARD_READERSTATE is defined as SCARD_READERSTATEW and SCardGetStatusChange renamed to SCardGetStatusChangeW
#ifdef WIN32 #ifdef _WIN32
#ifdef UNICODE #ifdef UNICODE
#define SCARD_READERSTATE SCARD_READERSTATEA #define SCARD_READERSTATE SCARD_READERSTATEA
#undef SCardGetStatusChange #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_sFirmwareID 8
#define PCSCv2_PART10_PROPERTY_bPPDUSupport 9 #define PCSCv2_PART10_PROPERTY_bPPDUSupport 9
#define PCSCv2_PART10_PROPERTY_dwMaxAPDUDataSize 10 #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: /* structures used (but not defined) in PCSC Part 10:
* "IFDs with Secure Pin Entry Capabilities" */ * "IFDs with Secure Pin Entry Capabilities" */

View File

@ -35,15 +35,15 @@ static void fixup_transceive_length(const struct sc_card *card,
{ {
assert(card != NULL && apdu != NULL); 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 */ /* The lower layers will automatically do chaining */
apdu->flags |= SC_APDU_FLAGS_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. /* The lower layers will automatically do a GET RESPONSE, if possible.
* All other workarounds must be carried out by the upper layers. */ * 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.p2 = 0; /* first record, return FCI */
apdu.resp = buf; apdu.resp = buf;
apdu.resplen = sizeof(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 { else {
apdu.p2 = 0x0C; /* first record, return nothing */ 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; size_t rlen;
/* request at most max_recv_size bytes */ /* request at most max_recv_size bytes */
if (*count > card->max_recv_size) if (*count > sc_get_max_recv_size(card))
rlen = card->max_recv_size; rlen = sc_get_max_recv_size(card);
else else
rlen = *count; 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) 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 r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0;
int cse = SC_APDU_CASE_3_SHORT;
switch (data->pin_type) { switch (data->pin_type) {
case SC_AC_CHV: case SC_AC_CHV:
@ -1034,11 +1035,16 @@ iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
p1 |= 0x01; p1 |= 0x01;
} }
break; break;
case SC_PIN_CMD_GET_INFO:
ins = 0x20;
/* No data to send or to receive */
cse = SC_APDU_CASE_1;
break;
default: default:
return SC_ERROR_NOT_SUPPORTED; 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->lc = len;
apdu->datalen = len; apdu->datalen = len;
apdu->data = buf; 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) if (tries_left)
*tries_left = -1; *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 /* See if we've been called from another card driver, which is
* passing an APDU to us (this allows to write card drivers * passing an APDU to us (this allows to write card drivers
* whose PIN functions behave "mostly like ISO" except in some * 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; 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 */ /* Transmit the APDU to the card */
r = sc_transmit_apdu(card, apdu); 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; data->apdu = NULL;
LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu->sw1 == 0x63) { r = sc_check_sw(card, apdu->sw1, apdu->sw2);
if ((apdu->sw2 & 0xF0) == 0xC0 && tries_left != NULL)
*tries_left = apdu->sw2 & 0x0F; if (data->cmd == SC_PIN_CMD_GET_INFO) {
return SC_ERROR_PIN_CODE_INCORRECT; 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;
} }
return sc_check_sw(card, apdu->sw1, apdu->sw2);
if (tries_left != NULL) {
*tries_left = data->pin1.tries_left;
}
}
return r;
} }

View File

@ -439,6 +439,9 @@ struct sc_reader_operations {
/* Card has on-board random number source. */ /* Card has on-board random number source. */
#define SC_CARD_CAP_RNG 0x00000004 #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(), /* Use the card's ACs in sc_pkcs15init_authenticate(),
* instead of relying on the ACL info in the profile files. */ * instead of relying on the ACL info in the profile files. */
#define SC_CARD_CAP_USE_FCI_AC 0x00000010 #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); 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 */ /* ISO 7816-4 related functions */

View File

@ -424,8 +424,9 @@ fix_starcos_pkcs15_card(struct sc_pkcs15_card *p15card)
if (strcmp(p15card->card->driver->short_name,"cardos") == 0) { if (strcmp(p15card->card->driver->short_name,"cardos") == 0) {
/* D-Trust cards (D-TRUST, D-SIGN) */ /* D-Trust cards (D-TRUST, D-SIGN) */
if (strstr(p15card->tokeninfo->label,"D-TRUST") != NULL if (p15card->tokeninfo->label
|| strstr(p15card->tokeninfo->label,"D-SIGN") != NULL) { && (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 /* D-TRUST Card 2.0 2cc (standard cards, which always add
* SHA1 prefix itself */ * SHA1 prefix itself */

View File

@ -880,6 +880,46 @@ err:
return max_data; 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) { static void detect_reader_features(sc_reader_t *reader, SCARDHANDLE card_handle) {
sc_context_t *ctx = reader->ctx; sc_context_t *ctx = reader->ctx;
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data; 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; PCSC_TLV_STRUCTURE *pcsc_tlv;
LONG rv; LONG rv;
const char *log_disabled = "but it's disabled in configuration file"; 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); 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 */ /* Detect display */
if (priv->pin_properties_ioctl) { if (priv->pin_properties_ioctl) {
rcount = sizeof(rbuf); 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) { 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; 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);
} }
} }

View File

@ -12,7 +12,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src
OPENSC_PKCS11_INC = sc-pkcs11.h pkcs11.h pkcs11-opensc.h 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 \ OPENSC_PKCS11_SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \
mechanism.c openssl.c framework-pkcs15.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 pkcs11-display.c pkcs11-display.h
OPENSC_PKCS11_LIBS = \ OPENSC_PKCS11_LIBS = \
$(top_builddir)/src/libopensc/libopensc.la \ $(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_SOURCES = $(OPENSC_PKCS11_SRC) $(OPENSC_PKCS11_INC)
opensc_pkcs11_la_LIBADD = $(OPENSC_PKCS11_LIBS) opensc_pkcs11_la_LIBADD = $(OPENSC_PKCS11_LIBS)
opensc_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) \ opensc_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) \
-export-symbols "$(srcdir)/opensc-pkcs11.exports" \ -export-symbols "$(srcdir)/pkcs11.exports" \
-module -shared -avoid-version -no-undefined -module -shared -avoid-version -no-undefined
onepin_opensc_pkcs11_la_SOURCES = $(OPENSC_PKCS11_SRC) $(OPENSC_PKCS11_INC) 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_CFLAGS = -DMODULE_APP_NAME=\"onepin-opensc-pkcs11\"
onepin_opensc_pkcs11_la_LIBADD = $(OPENSC_PKCS11_LIBS) onepin_opensc_pkcs11_la_LIBADD = $(OPENSC_PKCS11_LIBS)
onepin_opensc_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) \ onepin_opensc_pkcs11_la_LDFLAGS = $(AM_LDFLAGS) \
-export-symbols "$(srcdir)/opensc-pkcs11.exports" \ -export-symbols "$(srcdir)/pkcs11.exports" \
-module -shared -avoid-version -no-undefined -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 = \ pkcs11_spy_la_LIBADD = \
$(top_builddir)/src/common/libpkcs11.la \ $(top_builddir)/src/common/libpkcs11.la \
$(top_builddir)/src/common/libscdl.la \ $(top_builddir)/src/common/libscdl.la \
$(OPTIONAL_OPENSSL_LIBS) $(OPTIONAL_OPENSSL_LIBS)
pkcs11_spy_la_LDFLAGS = $(AM_LDFLAGS) \ pkcs11_spy_la_LDFLAGS = $(AM_LDFLAGS) \
-export-symbols "$(srcdir)/pkcs11-spy.exports" \ -export-symbols "$(srcdir)/pkcs11.exports" \
-module -shared -avoid-version -no-undefined -module -shared -avoid-version -no-undefined
if WIN32 if WIN32

View File

@ -16,14 +16,14 @@ all: versioninfo-pkcs11.res $(TARGET1) $(TARGET2) $(TARGET3) versioninfo-pkcs11-
$(TARGET1): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib $(TARGET1): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib
echo LIBRARY $* > $*.def echo LIBRARY $* > $*.def
echo EXPORTS >> $*.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 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 if EXIST $(TARGET1).manifest mt -manifest $(TARGET1).manifest -outputresource:$(TARGET1);2
$(TARGET2): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib $(TARGET2): $(OBJECTS) ..\libopensc\opensc_a.lib ..\pkcs15init\pkcs15init.lib
echo LIBRARY $* > $*.def echo LIBRARY $* > $*.def
echo EXPORTS >> $*.def echo EXPORTS >> $*.def
type opensc-pkcs11.exports >> $*.def type pkcs11.exports >> $*.def
del pkcs11-global.obj del pkcs11-global.obj
cl $(CODE_OPTIMIZATION) $(COPTS) /DMODULE_APP_NAME=\"onepin-opensc-pkcs11\" /c pkcs11-global.c 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 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 $(TARGET3): $(OBJECTS3) ..\libopensc\opensc.lib
echo LIBRARY $* > $*.def echo LIBRARY $* > $*.def
echo EXPORTS >> $*.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 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 if EXIST $(TARGET3).manifest mt -manifest $(TARGET3).manifest -outputresource:$(TARGET3);2

View File

@ -1 +0,0 @@
C_GetFunctionList

View File

@ -1 +0,0 @@
C_GetFunctionList

View File

@ -0,0 +1,3 @@
C_GetFunctionList
C_Initialize
C_Finalize

View File

@ -50,6 +50,7 @@ static char * opt_auth_id = NULL;
static char * opt_reader = NULL; static char * opt_reader = NULL;
static char * opt_cert = NULL; static char * opt_cert = NULL;
static char * opt_data = NULL; static char * opt_data = NULL;
static int opt_raw = 0;
static char * opt_pubkey = NULL; static char * opt_pubkey = NULL;
static char * opt_outfile = NULL; static char * opt_outfile = NULL;
static char * opt_bind_to_aid = NULL; static char * opt_bind_to_aid = NULL;
@ -82,6 +83,7 @@ enum {
OPT_LIST_APPLICATIONS, OPT_LIST_APPLICATIONS,
OPT_LIST_SKEYS, OPT_LIST_SKEYS,
OPT_NO_PROMPT, OPT_NO_PROMPT,
OPT_RAW,
}; };
#define NELEMENTS(x) (sizeof(x)/sizeof((x)[0])) #define NELEMENTS(x) (sizeof(x)/sizeof((x)[0]))
@ -94,6 +96,7 @@ static const struct option options[] = {
{ "read-certificate", required_argument, NULL, 'r' }, { "read-certificate", required_argument, NULL, 'r' },
{ "list-certificates", no_argument, NULL, 'c' }, { "list-certificates", no_argument, NULL, 'c' },
{ "read-data-object", required_argument, NULL, 'R' }, { "read-data-object", required_argument, NULL, 'R' },
{ "raw", no_argument, NULL, OPT_RAW },
{ "list-data-objects", no_argument, NULL, 'C' }, { "list-data-objects", no_argument, NULL, 'C' },
{ "list-pins", no_argument, NULL, OPT_LIST_PINS }, { "list-pins", no_argument, NULL, OPT_LIST_PINS },
{ "list-secret-keys", no_argument, NULL, OPT_LIST_SKEYS }, { "list-secret-keys", no_argument, NULL, OPT_LIST_SKEYS },
@ -130,6 +133,7 @@ static const char *option_help[] = {
"Reads certificate with ID <arg>", "Reads certificate with ID <arg>",
"Lists certificates", "Lists certificates",
"Reads data object with OID, applicationName or label <arg>", "Reads data object with OID, applicationName or label <arg>",
"Outputs raw 8 bit data to stdout. File output will not be affected by this, it always uses raw mode.",
"Lists data objects", "Lists data objects",
"Lists PIN codes", "Lists PIN codes",
"Lists secret keys", "Lists secret keys",
@ -346,12 +350,21 @@ print_data_object(const char *kind, const u8*data, size_t data_len)
} }
for (i=0; i < data_len; i++) for (i=0; i < data_len; i++)
fprintf(outf, "%c", data[i]); fprintf(outf, "%c", data[i]);
if (opt_raw) {
for (i=0; i < data_len; i++)
printf("%c", data[i]);
} else {
printf("Dumping (%lu bytes) to file <%s>: <", printf("Dumping (%lu bytes) to file <%s>: <",
(unsigned long) data_len, opt_outfile); (unsigned long) data_len, opt_outfile);
for (i=0; i < data_len; i++) for (i=0; i < data_len; i++)
printf(" %02X", data[i]); printf(" %02X", data[i]);
printf(" >\n"); printf(" >\n");
}
fclose(outf); fclose(outf);
} else {
if (opt_raw) {
for (i=0; i < data_len; i++)
printf("%c", data[i]);
} else { } else {
printf("%s (%lu bytes): <", printf("%s (%lu bytes): <",
kind, (unsigned long) data_len); kind, (unsigned long) data_len);
@ -359,6 +372,7 @@ print_data_object(const char *kind, const u8*data, size_t data_len)
printf(" %02X", data[i]); printf(" %02X", data[i]);
printf(" >\n"); printf(" >\n");
} }
}
return 0; return 0;
} }
@ -1564,12 +1578,48 @@ static int read_and_cache_file(const sc_path_t *path)
printf("out of memory!"); printf("out of memory!");
return -1; 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); r = sc_read_binary(card, 0, buf, size, 0);
if (r < 0) { if (r < 0) {
fprintf(stderr, "sc_read_binary() failed: %s\n", sc_strerror(r)); fprintf(stderr, "sc_read_binary() failed: %s\n", sc_strerror(r));
free(buf); free(buf);
return -1; return -1;
} }
}
r = sc_pkcs15_cache_file(p15card, path, buf, r); r = sc_pkcs15_cache_file(p15card, path, buf, r);
if (r) { if (r) {
fprintf(stderr, "Unable to cache file: %s\n", sc_strerror(r)); fprintf(stderr, "Unable to cache file: %s\n", sc_strerror(r));
@ -1895,6 +1945,9 @@ int main(int argc, char * const argv[])
do_read_data_object = 1; do_read_data_object = 1;
action_count++; action_count++;
break; break;
case OPT_RAW:
opt_raw = 1;
break;
case 'C': case 'C':
do_list_data_objects = 1; do_list_data_objects = 1;
action_count++; action_count++;

View File

@ -461,12 +461,59 @@ static void print_info(sc_card_t *card, sc_file_t *file)
struct sc_pin_cmd_data data; struct sc_pin_cmd_data data;
sc_cardctl_sc_hsm_dkek_t dkekinfo; sc_cardctl_sc_hsm_dkek_t dkekinfo;
u8 major, minor; u8 major, minor, opt;
major = file->prop_attr[file->prop_attr_len - 2]; major = file->prop_attr[file->prop_attr_len - 2];
minor = file->prop_attr[file->prop_attr_len - 1]; minor = file->prop_attr[file->prop_attr_len - 1];
printf("Version : %d.%d\n", (int)major, (int)minor); printf("Version : %d.%d\n", (int)major, (int)minor);
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");
}
}
/* 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;
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 {
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 */ /* Try to update PIN info from card */
memset(&data, 0, sizeof(data)); memset(&data, 0, sizeof(data));
data.cmd = SC_PIN_CMD_GET_INFO; data.cmd = SC_PIN_CMD_GET_INFO;
@ -484,6 +531,7 @@ static void print_info(sc_card_t *card, sc_file_t *file)
printf("User PIN tries left : %d\n", tries_left); printf("User PIN tries left : %d\n", tries_left);
} }
} }
}
memset(&dkekinfo, 0, sizeof(dkekinfo)); memset(&dkekinfo, 0, sizeof(dkekinfo));

View File

@ -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}}, 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 */ /* from card-masktech.c */
/* note: the card name MUST be unique */ /* 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}, {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,0xff,0xff,0xff,0xff,0xff}}, 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,0x37,0x80,0x31,0xC0,0x69,0x4D,0x54,0x43,0x4F,0x53,0x73,0x02,0x02,0x05,0x41}, {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,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}}, 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,0x81,0x00,0x7E}, {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,0xff,0xff,0xff}}, 13, {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xee,0xff,0xee}},
{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}},
}; };