Merge branch 'master' into gnuk
This commit is contained in:
commit
76b6b483c7
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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%
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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" */
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
C_GetFunctionList
|
|
|
@ -1 +0,0 @@
|
||||||
C_GetFunctionList
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
C_GetFunctionList
|
||||||
|
C_Initialize
|
||||||
|
C_Finalize
|
|
@ -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++;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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}},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue