Merge branch 'master' into attestation2

This commit is contained in:
Klas Lindfors
2016-03-10 15:34:25 +01:00
32 changed files with 2405 additions and 689 deletions
+4
View File
@@ -73,6 +73,10 @@ tool/tests/parse_name
tool/tests/parse_name.log
tool/tests/parse_name.o
tool/tests/parse_name.trs
tool/tests/test_inout
tool/tests/test_inout.log
tool/tests/test_inout.o
tool/tests/test_inout.trs
coverage/
lib/error.gcno
lib/version.gcno
+2 -1
View File
@@ -31,7 +31,8 @@ ACLOCAL_AMFLAGS = -I m4
EXTRA_DIST = windows.mk mac.mk tool/tests/basic.sh tools/fasc.pl
EXTRA_DIST += doc/Certificate_Authority.adoc doc/OS_X_code_signing.adoc doc/SSH_with_PIV_and_PKCS11.adoc doc/Windows_certificate.adoc doc/YKCS11_release_notes.adoc doc/YubiKey_PIV_introduction.adoc
EXTRA_DIST += doc/Android_code_signing.adoc doc/Certificate_Authority.adoc doc/OS_X_code_signing.adoc doc/SSH_with_PIV_and_PKCS11.adoc doc/Windows_certificate.adoc doc/YKCS11_release_notes.adoc doc/YubiKey_PIV_introduction.adoc
if ENABLE_COV
cov-reset:
+44 -1
View File
@@ -1,6 +1,49 @@
yubico-piv-tool NEWS -- History of user-visible changes. -*- outline -*-
* Version 1.1.3 (unreleased)
* Version 1.3.1 (unreleased)
* Version 1.3.0 (released 2016-02-19)
** Fixed extraction of RSA modulus and exponent for pkcs11.
** Implemented C_SetPIN for pkcs11.
** Add generic write and read object actions for the tool.
Supports hex/binary/base64 formats
** Add ykpiv_change_pin(), ykpiv_change_puk() and ykpiv_unblock_pin()
** Print CCC with status action.
** Address bugs with pkcs11 on windows.
** Add --valid-days and --serial to tool for selfsign-certificate action.
** Ask for password for pkcs12 if none is given.
* Version 1.2.2 (released 2015-12-08)
** Fix old buffer overflow in change-pin functionality.
* Version 1.2.1 (released 2015-12-08)
** Fix issue with big certificates and status.
* Version 1.2.0 (released 2015-12-07)
** On OSX use @loader_path instead of @executable_path for ykcs11.
** Add ykpiv_import_private_key to libykpiv.
** Raise buffer sizes to support bigger objects.
** Change behavior of action status, only list populated slots.
** Add retired keys to ykcs11.
** In ykcs11 support login with non null terminated pin.
** Add a new action set-ccc to yubico-piv-tool to set the CCC.
* Version 1.1.2 (released 2015-11-13)
+21 -7
View File
@@ -26,7 +26,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
AC_INIT([yubico-piv-tool], [1.1.3])
AC_INIT([yubico-piv-tool], [1.3.1])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
@@ -34,9 +34,9 @@ AC_CONFIG_MACRO_DIR([m4])
# Interfaces changed/added/removed: CURRENT++ REVISION=0
# Interfaces added: AGE++
# Interfaces removed: AGE=0
AC_SUBST([LT_CURRENT], 2)
AC_SUBST([LT_CURRENT], 4)
AC_SUBST([LT_REVISION], 1)
AC_SUBST([LT_AGE], 1)
AC_SUBST([LT_AGE], 3)
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AM_SILENT_RULES([yes])
@@ -52,8 +52,6 @@ PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES(OPENSSL, libcrypto)
#PKG_CHECK_MODULES([LIBNSPR], [nspr], [], [])
gl_LD_VERSION_SCRIPT
gl_VALGRIND_TESTS
@@ -190,10 +188,24 @@ AC_ARG_ENABLE([ykcs11-debug],
AS_IF([test "x$enable_ykcs11_debug" != xno],
[AC_DEFINE([YKCS11_DBG], [1], [Regular debug flag])
AC_DEFINE([YKCS11_DINOUT], [1], [Function accessed/left debug flag])],
AC_DEFINE([YKCS11_DINOUT], [1], [Function accessed/left debug flag])
ykcs11_debug="ENABLED"],
[true],
[AC_DEFINE([YKCS11_DBG], [0], [Regular debug flag])
AC_DEFINE([YKCS11_DINOUT], [0], [Function accessed/left debug flag])])
AC_DEFINE([YKCS11_DINOUT], [0], [Function accessed/left debug flag])
ykcs11_debug="DISABLED"])
AC_ARG_ENABLE([hardware-tests],
[AS_HELP_STRING([--enable-hardware-tests],
[enables tests that require a YubiKey to be plugged in])],
[enable_hardware_tests="$enableval"],
[enable_hardware_tests="no"])
AS_IF([test "x$enable_hardware_tests" != xno],
[AC_DEFINE([HW_TESTS], [1], [Flag for hardware tests])
hw_tests="ENABLED"],
[true],
[hw_tests="DISABLED"])
AC_SUBST(YKPIV_VERSION_MAJOR, `echo $PACKAGE_VERSION | sed 's/\(.*\)\..*\..*/\1/g'`)
AC_SUBST(YKPIV_VERSION_MINOR, `echo $PACKAGE_VERSION | sed 's/.*\.\(.*\)\..*/\1/g'`)
@@ -238,4 +250,6 @@ AC_MSG_NOTICE([summary of build options:
Mac PCSC
LIBS: ${PCSC_MACOSX_LIBS}
YKCS11 debug: ${ykcs11_debug}
Hardware tests: ${hw_tests}
])
+73
View File
@@ -0,0 +1,73 @@
Load and use Android code signing certificate
---------------------------------------------
This is a step-by-step guide on how to load and use an android code signing
key and certificate.
Prerequisites
-------------
* a YubiKey with the PIV application
* the yubico-piv-tool software
* the OpenSC software
* jarsigner and keytool from the JDK (OpenJDK 8 used here)
Steps
-----
1. Import the key and cert, do one of the below:
a. Import the key and cert (PEM format) in slot 9a:
+
----
$ yubico-piv-tool -s 9a -a import-key -i key.pem
$ yubico-piv-tool -s 9a -a import-certificate -i cert.pem
----
b. Import the key and cert (PKCS12 format) in slot 9a:
+
----
$ yubico-piv-tool -s 9a -a import-key -a import-cert -i key.p12 -K PKCS12
----
2. Create a java pkcs11 configuration file:
+
----
cat > /tmp/pkcs11_java.cfg
name = OpenSC-PKCS11
description = SunPKCS11 via OpenSC
library = /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
slotListIndex = 1
----
3. Check that keytool can see the key:
+
----
$ keytool -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /tmp/pkcs11_java.cfg \
-keystore NONE -storetype PKCS11 -list
Enter keystore password:
Keystore type: PKCS11
Keystore provider: SunPKCS11-OpenSC-PKCS11
Your keystore contains 1 entry
Certificate for PIV Authentication, PrivateKeyEntry,
Certificate fingerprint (SHA1): 26:D7:CB:71:6D:42:3C:AB:58:69:E0:9D:F0:16:DF:84:7E:1C:5A:9A
----
+
Password here is the PIN of the key (default 123456).
4. Sign the apk with jarsigner:
+
----
$ jarsigner -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /tmp/pkcs11_java.cfg \
-keystore NONE -storetype PKCS11 app.apk "Certificate for PIV Authentication"
Enter Passphrase for keystore:
jar signed.
----
5. Verify the signature with jarsigner:
+
----
$ jarsigner -verify app.apk
----
+3 -6
View File
@@ -46,12 +46,9 @@
#define MAX_READERS 16
struct ykpiv_state {
SCARDCONTEXT context;
SCARDHANDLE card;
unsigned long n_readers;
char readers[MAX_READERS][READER_LEN];
unsigned long tot_readers_len;
int verbose;
SCARDCONTEXT context;
SCARDHANDLE card;
int verbose;
};
union u_APDU {
+185 -2
View File
@@ -258,7 +258,7 @@ ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
rc = SCardBeginTransaction(state->card);
if(rc != SCARD_S_SUCCESS) {
if(state->verbose) {
fprintf(stderr, "error: Failed to being pcsc transaction, rc=%08lx\n", rc);
fprintf(stderr, "error: Failed to begin pcsc transaction, rc=%08lx\n", rc);
}
return YKPIV_PCSC_ERROR;
}
@@ -716,6 +716,68 @@ ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries) {
}
}
#define CHREF_ACT_CHANGE_PIN 0
#define CHREF_ACT_UNBLOCK_PIN 1
#define CHREF_ACT_CHANGE_PUK 2
static ykpiv_rc _change_pin_internal(ykpiv_state *state, int action, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) {
int sw;
unsigned char templ[] = {0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80};
unsigned char indata[0x10];
unsigned char data[0xff];
unsigned long recv_len = sizeof(data);
ykpiv_rc res;
if (current_pin_len > 8) {
return YKPIV_SIZE_ERROR;
}
if (new_pin_len > 8) {
return YKPIV_SIZE_ERROR;
}
if(action == CHREF_ACT_UNBLOCK_PIN) {
templ[1] = YKPIV_INS_RESET_RETRY;
}
else if(action == CHREF_ACT_CHANGE_PUK) {
templ[3] = 0x81;
}
memcpy(indata, current_pin, current_pin_len);
if(current_pin_len < 8) {
memset(indata + current_pin_len, 0xff, 8 - current_pin_len);
}
memcpy(indata + 8, new_pin, new_pin_len);
if(new_pin_len < 8) {
memset(indata + 8 + new_pin_len, 0xff, 8 - new_pin_len);
}
res = ykpiv_transfer_data(state, templ, indata, sizeof(indata), data, &recv_len, &sw);
if(res != YKPIV_OK) {
return res;
} else if(sw != 0x9000) {
if((sw >> 8) == 0x63) {
*tries = sw & 0xf;
return YKPIV_WRONG_PIN;
} else if(sw == 0x6983) {
return YKPIV_PIN_LOCKED;
} else {
if(state->verbose) {
fprintf(stderr, "Failed changing pin, token response code: %x.\n", sw);
}
return YKPIV_GENERIC_ERROR;
}
}
return YKPIV_OK;
}
ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len, const char * new_pin, size_t new_pin_len, int *tries) {
return _change_pin_internal(state, CHREF_ACT_CHANGE_PIN, current_pin, current_pin_len, new_pin, new_pin_len, tries);
}
ykpiv_rc ykpiv_change_puk(ykpiv_state *state, const char * current_puk, size_t current_puk_len, const char * new_puk, size_t new_puk_len, int *tries) {
return _change_pin_internal(state, CHREF_ACT_CHANGE_PUK, current_puk, current_puk_len, new_puk, new_puk_len, tries);
}
ykpiv_rc ykpiv_unblock_pin(ykpiv_state *state, const char * puk, size_t puk_len, const char * new_pin, size_t new_pin_len, int *tries) {
return _change_pin_internal(state, CHREF_ACT_CHANGE_PUK, puk, puk_len, new_pin, new_pin_len, tries);
}
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
unsigned char *data, unsigned long *len) {
int sw;
@@ -751,7 +813,7 @@ ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
unsigned char *indata, size_t len) {
unsigned char data[2048];
unsigned char data[3072];
unsigned char *dataptr = data;
unsigned char templ[] = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff};
int sw;
@@ -781,3 +843,124 @@ ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
return YKPIV_GENERIC_ERROR;
}
}
ykpiv_rc ykpiv_import_private_key(ykpiv_state *state, const unsigned char key, unsigned char algorithm,
const unsigned char *p, size_t p_len,
const unsigned char *q, size_t q_len,
const unsigned char *dp, size_t dp_len,
const unsigned char *dq, size_t dq_len,
const unsigned char *qinv, size_t qinv_len,
const unsigned char *ec_data, unsigned char ec_data_len,
const unsigned char pin_policy, const unsigned char touch_policy) {
unsigned char key_data[1024];
unsigned char *in_ptr = key_data;
unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key};
unsigned char data[256];
unsigned long recv_len = sizeof(data);
unsigned elem_len;
int sw;
const unsigned char *params[5];
size_t lens[5];
size_t padding;
unsigned char n_params;
int i;
int param_tag;
if (state == NULL)
return YKPIV_GENERIC_ERROR;
if (key == YKPIV_KEY_CARDMGM ||
key < YKPIV_KEY_RETIRED1 ||
(key > YKPIV_KEY_RETIRED20 && key < YKPIV_KEY_AUTHENTICATION) ||
key > YKPIV_KEY_CARDAUTH) {
return YKPIV_KEY_ERROR;
}
if (pin_policy != YKPIV_PINPOLICY_DEFAULT &&
pin_policy != YKPIV_PINPOLICY_NEVER &&
pin_policy != YKPIV_PINPOLICY_ONCE &&
pin_policy != YKPIV_PINPOLICY_ALWAYS)
return YKPIV_GENERIC_ERROR;
if (touch_policy != YKPIV_TOUCHPOLICY_DEFAULT &&
touch_policy != YKPIV_TOUCHPOLICY_NEVER &&
touch_policy != YKPIV_TOUCHPOLICY_ALWAYS)
return YKPIV_GENERIC_ERROR;
if (algorithm == YKPIV_ALGO_RSA1024 || algorithm == YKPIV_ALGO_RSA2048) {
if (algorithm == YKPIV_ALGO_RSA1024)
elem_len = 64;
if (algorithm == YKPIV_ALGO_RSA2048)
elem_len = 128;
if (p == NULL || q == NULL || dp == NULL ||
dq == NULL || qinv == NULL)
return YKPIV_GENERIC_ERROR;
params[0] = p;
lens[0] = p_len;
params[1] = q;
lens[1] = q_len;
params[2] = dp;
lens[2] = dp_len;
params[3] = dq;
lens[3] = dq_len;
params[4] = qinv;
lens[4] = qinv_len;
param_tag = 0x01;
n_params = 5;
}
else if (algorithm == YKPIV_ALGO_ECCP256 || algorithm == YKPIV_ALGO_ECCP384) {
if (algorithm == YKPIV_ALGO_ECCP256)
elem_len = 32;
if (algorithm == YKPIV_ALGO_ECCP384)
elem_len = 48;
if (ec_data == NULL)
return YKPIV_GENERIC_ERROR;
params[0] = ec_data;
lens[0] = ec_data_len;
param_tag = 0x06;
n_params = 1;
}
else
return YKPIV_ALGORITHM_ERROR;
for (i = 0; i < n_params; i++) {
*in_ptr++ = param_tag + i;
in_ptr += set_length(in_ptr, elem_len);
padding = elem_len - lens[i];
memset(in_ptr, 0, padding);
in_ptr += padding;
memcpy(in_ptr, params[i], lens[i]);
in_ptr += lens[i];
}
if (pin_policy != YKPIV_PINPOLICY_DEFAULT) {
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = pin_policy;
}
if (touch_policy != YKPIV_TOUCHPOLICY_DEFAULT) {
*in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = touch_policy;
}
if (ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK)
return YKPIV_GENERIC_ERROR;
if (sw == 0x6982)
return YKPIV_AUTHENTICATION_ERROR;
if (sw != 0x9000)
return YKPIV_GENERIC_ERROR;
return YKPIV_OK;
}
+40
View File
@@ -57,6 +57,7 @@ extern "C"
YKPIV_WRONG_PIN = -10,
YKPIV_INVALID_OBJECT = -11,
YKPIV_ALGORITHM_ERROR = -12,
YKPIV_PIN_LOCKED = -13,
} ykpiv_rc;
const char *ykpiv_strerror(ykpiv_rc err);
@@ -85,12 +86,29 @@ extern "C"
unsigned char algorithm, unsigned char key);
ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len);
ykpiv_rc ykpiv_verify(ykpiv_state *state, const char *pin, int *tries);
ykpiv_rc ykpiv_change_pin(ykpiv_state *state, const char * current_pin, size_t current_pin_len,
const char * new_pin, size_t new_pin_len,
int *tries);
ykpiv_rc ykpiv_change_puk(ykpiv_state *state, const char * current_puk, size_t current_puk_len,
const char * new_puk, size_t new_puk_len,
int *tries);
ykpiv_rc ykpiv_unblock_pin(ykpiv_state *state, const char * puk, size_t puk_len,
const char * new_pin, size_t new_pin_len,
int *tries);
ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
unsigned char *data, unsigned long *len);
ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key,
const unsigned char touch);
ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
unsigned char *indata, size_t len);
ykpiv_rc ykpiv_import_private_key(ykpiv_state *state, const unsigned char key, unsigned char algorithm,
const unsigned char *p, size_t p_len,
const unsigned char *q, size_t q_len,
const unsigned char *dp, size_t dp_len,
const unsigned char *dq, size_t dq_len,
const unsigned char *qinv, size_t qinv_len,
const unsigned char *ec_data, unsigned char ec_data_len,
const unsigned char pin_policy, const unsigned char touch_policy);
#define YKPIV_ALGO_3DES 0x03
#define YKPIV_ALGO_RSA1024 0x06
@@ -103,6 +121,26 @@ extern "C"
#define YKPIV_KEY_SIGNATURE 0x9c
#define YKPIV_KEY_KEYMGM 0x9d
#define YKPIV_KEY_CARDAUTH 0x9e
#define YKPIV_KEY_RETIRED1 0x82
#define YKPIV_KEY_RETIRED2 0x83
#define YKPIV_KEY_RETIRED3 0x84
#define YKPIV_KEY_RETIRED4 0x85
#define YKPIV_KEY_RETIRED5 0x86
#define YKPIV_KEY_RETIRED6 0x87
#define YKPIV_KEY_RETIRED7 0x88
#define YKPIV_KEY_RETIRED8 0x89
#define YKPIV_KEY_RETIRED9 0x8a
#define YKPIV_KEY_RETIRED10 0x8b
#define YKPIV_KEY_RETIRED11 0x8c
#define YKPIV_KEY_RETIRED12 0x8d
#define YKPIV_KEY_RETIRED13 0x8e
#define YKPIV_KEY_RETIRED14 0x8f
#define YKPIV_KEY_RETIRED15 0x90
#define YKPIV_KEY_RETIRED16 0x91
#define YKPIV_KEY_RETIRED17 0x92
#define YKPIV_KEY_RETIRED18 0x93
#define YKPIV_KEY_RETIRED19 0x94
#define YKPIV_KEY_RETIRED20 0x95
#define YKPIV_OBJ_CAPABILITY 0x5fc107
#define YKPIV_OBJ_CHUID 0x5fc102
@@ -158,11 +196,13 @@ extern "C"
#define YKPIV_INS_ATTEST 0xf9
#define YKPIV_PINPOLICY_TAG 0xaa
#define YKPIV_PINPOLICY_DEFAULT 0
#define YKPIV_PINPOLICY_NEVER 1
#define YKPIV_PINPOLICY_ONCE 2
#define YKPIV_PINPOLICY_ALWAYS 3
#define YKPIV_TOUCHPOLICY_TAG 0xab
#define YKPIV_TOUCHPOLICY_DEFAULT 0
#define YKPIV_TOUCHPOLICY_NEVER 1
#define YKPIV_TOUCHPOLICY_ALWAYS 2
+35 -21
View File
@@ -28,36 +28,50 @@
YKPIV_0.1.0
{
global:
ykpiv_check_version;
ykpiv_strerror_name;
ykpiv_strerror;
ykpiv_init;
ykpiv_done;
ykpiv_connect;
ykpiv_disconnect;
ykpiv_transfer_data;
ykpiv_authenticate;
ykpiv_set_mgmkey;
ykpiv_sign_data;
ykpiv_get_version;
ykpiv_verify;
ykpiv_fetch_object;
ykpiv_save_object;
ykpiv_hex_decode;
ykpiv_check_version;
ykpiv_strerror_name;
ykpiv_strerror;
ykpiv_init;
ykpiv_done;
ykpiv_connect;
ykpiv_disconnect;
ykpiv_transfer_data;
ykpiv_authenticate;
ykpiv_set_mgmkey;
ykpiv_sign_data;
ykpiv_get_version;
ykpiv_verify;
ykpiv_fetch_object;
ykpiv_save_object;
ykpiv_hex_decode;
local:
*;
*;
};
YKPIV_0.2.0
{
global:
ykpiv_decipher_data;
ykpiv_decipher_data;
} YKPIV_0.1.0;
YKPIV_1.1.0
{
global:
ykpiv_set_mgmkey2;
ykpiv_list_readers;
} YKPIV_0.1.0;
ykpiv_set_mgmkey2;
ykpiv_list_readers;
} YKPIV_0.2.0;
YKPIV_1.2.0
{
global:
ykpiv_import_private_key;
} YKPIV_1.1.0;
YKPIV_1.3.0
{
global:
ykpiv_change_pin;
ykpiv_change_puk;
ykpiv_unblock_pin;
} YKPIV_1.2.0;
+10 -9
View File
@@ -26,7 +26,8 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PACKAGE=yubico-piv-tool
OPENSSLVERSION=1.0.1p
OPENSSLVERSION=1.0.1r
CFLAGS="-mmacosx-version-min=10.6"
all: usage mac
@@ -47,7 +48,7 @@ doit:
curl -L -O "https://www.openssl.org/source/openssl-$(OPENSSLVERSION).tar.gz" && \
tar xfz openssl-$(OPENSSLVERSION).tar.gz && \
cd openssl-$(OPENSSLVERSION) && \
./Configure darwin64-x86_64-cc shared no-ssl2 no-ssl3 no-engines --prefix=$(PWD)/tmp/root && \
./Configure darwin64-x86_64-cc shared no-ssl2 no-ssl3 no-engines --prefix=$(PWD)/tmp/root $(CFLAGS) && \
make all install_sw && \
cp LICENSE $(PWD)/tmp$(ARCH)/root/licenses/openssl.txt && \
rm -rf $(PWD)/tmp/root/ssl/ && \
@@ -60,16 +61,16 @@ doit:
cp ../$(PACKAGE)-$(VERSION).tar.gz . && \
tar xfz $(PACKAGE)-$(VERSION).tar.gz && \
cd $(PACKAGE)-$(VERSION)/ && \
PKG_CONFIG_PATH=$(PWD)/tmp/root/lib/pkgconfig ./configure --prefix=$(PWD)/tmp/root && \
CFLAGS=$(CFLAGS) PKG_CONFIG_PATH=$(PWD)/tmp/root/lib/pkgconfig ./configure --prefix=$(PWD)/tmp/root && \
make install $(CHECK) && \
chmod u+w $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib && \
install_name_tool -id @executable_path/../lib/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib && \
install_name_tool -id @executable_path/../lib/libykpiv.1.dylib $(PWD)/tmp/root/lib/libykpiv.1.dylib && \
install_name_tool -id @executable_path/../lib/libykcs11.1.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \
install_name_tool -change $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib @executable_path/../lib/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libykpiv.1.dylib && \
install_name_tool -change $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib @executable_path/../lib/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \
install_name_tool -id @loader_path/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib && \
install_name_tool -id @loader_path/libykpiv.1.dylib $(PWD)/tmp/root/lib/libykpiv.1.dylib && \
install_name_tool -id @loader_path/libykcs11.1.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \
install_name_tool -change $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib @loader_path/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libykpiv.1.dylib && \
install_name_tool -change $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib @loader_path/libcrypto.1.0.0.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \
install_name_tool -change $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib @executable_path/../lib/libcrypto.1.0.0.dylib $(PWD)/tmp/root/bin/yubico-piv-tool && \
install_name_tool -change $(PWD)/tmp/root/lib/libykpiv.1.dylib @executable_path/../lib/libykpiv.1.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \
install_name_tool -change $(PWD)/tmp/root/lib/libykpiv.1.dylib @loader_path/libykpiv.1.dylib $(PWD)/tmp/root/lib/libykcs11.1.dylib && \
install_name_tool -change $(PWD)/tmp/root/lib/libykpiv.1.dylib @executable_path/../lib/libykpiv.1.dylib $(PWD)/tmp/root/bin/yubico-piv-tool ; \
if otool -L $(PWD)/tmp/root/lib/*.dylib $(PWD)/tmp/root/bin/* | grep '$(PWD)/tmp/root' | grep -q compatibility; then \
echo "something is incorrectly linked!"; \
+4 -5
View File
@@ -33,7 +33,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/lib -I$(top_builddir)/lib
bin_PROGRAMS = yubico-piv-tool
yubico_piv_tool_SOURCES = yubico-piv-tool.c yubico-piv-tool.h2m
yubico_piv_tool_LDADD = $(OPENSSL_LIBS) ../lib/libykpiv.la
yubico_piv_tool_LDADD = $(OPENSSL_LIBS) $(top_builddir)/lib/libykpiv.la
yubico_piv_tool_LDADD += libpiv_cmd.la libpiv_util.la
noinst_LTLIBRARIES = libpiv_cmd.la libpiv_util.la
@@ -41,9 +41,9 @@ libpiv_cmd_la_SOURCES = cmdline.ggo cmdline.c cmdline.h
libpiv_cmd_la_CFLAGS =
libpiv_util_la_SOURCES = util.c util.h
libpiv_util_la_LIBADD = $(OPENSSL_LIBS)
libpiv_util_la_LIBADD = $(top_builddir)/lib/libykpiv.la $(OPENSSL_LIBS)
cmdline.c cmdline.h: cmdline.ggo Makefile.am
cmdline.c cmdline.h: cmdline.ggo Makefile.am $(top_srcdir)/configure.ac
$(GENGETOPT) --input $^
BUILT_SOURCES = cmdline.c cmdline.h
@@ -54,8 +54,7 @@ MAINTAINERCLEANFILES = $(BUILT_SOURCES)
dist_man_MANS = yubico-piv-tool.1
MAINTAINERCLEANFILES += $(dist_man_MANS)
yubico-piv-tool.1: $(yubico_piv_tool_SOURCES) \
$(top_srcdir)/configure.ac
yubico-piv-tool.1: $(yubico_piv_tool_SOURCES) $(libpiv_cmd_la_SOURCES)
$(HELP2MAN) --no-info \
--name="Yubico PIV tool" \
--include=$(srcdir)/yubico-piv-tool.h2m \
+6 -1
View File
@@ -32,7 +32,8 @@ option "action" a "Action to take" values="version","generate","set-mgm-key",
"reset","pin-retries","import-key","import-certificate","set-chuid",
"request-certificate","verify-pin","change-pin","change-puk","unblock-pin",
"selfsign-certificate","delete-certificate","read-certificate","status",
"test-signature","test-decipher","list-readers","attest" enum multiple
"test-signature","test-decipher","list-readers","set-ccc","write-object",
"read-object","attest" enum multiple
text "
Multiple actions may be given at once and will be executed in order
for example --action=verify-pin --action=request-certificate\n"
@@ -56,8 +57,12 @@ option "subject" S "The subject to use for certificate request" string optional
text "
The subject must be written as:
/CN=host.example.com/OU=test/O=example.com/\n"
option "serial" - "Serial number of the self-signed certificate" int optional default="1"
option "valid-days" - "Time (in days) until the self-signed certificate expires" int optional default="365"
option "pin" P "Pin/puk code for verification" string optional
option "new-pin" N "New pin/puk code for changing" string optional dependon="pin"
option "pin-policy" - "Set pin policy for action generate or import-key" values="never","once","always" enum optional
option "touch-policy" - "Set touch policy for action generate, import-key or set-mgm-key" values="never","always" enum optional
option "id" - "Id of object for write/read object" int optional
option "format" f "Format of data for write/read object" values="hex","base64","binary" enum optional default="hex"
option "sign" - "Sign data" flag off hidden
+2 -1
View File
@@ -37,8 +37,9 @@ AM_CPPFLAGS += $(OPENSSL_CFLAGS)
AM_LDFLAGS = -no-install
parse_name_LDADD = ../libpiv_util.la $(OPENSSL_LIBS)
test_inout_LDADD = ../libpiv_util.la
check_PROGRAMS = parse_name
check_PROGRAMS = parse_name test_inout
TESTS = basic.sh $(check_PROGRAMS)
if ENABLE_COV
+63
View File
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2015 Yubico AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include "util.h"
#ifdef _WIN32
#define pipe(fds) _pipe(fds,4096, 0)
#endif
static void test_inout(enum enum_format format) {
const unsigned char buf[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
unsigned char buf2[sizeof(buf)];
int pipefd[2];
FILE *tmp1, *tmp2;
assert(pipe(pipefd) == 0);
tmp1 = fdopen(pipefd[1], "w");
dump_data(buf, sizeof(buf), tmp1, false, format);
fclose(tmp1);
tmp2 = fdopen(pipefd[0], "r");
read_data(buf2, sizeof(buf2), tmp2, format);
assert(memcmp(buf, buf2, sizeof(buf)) == 0);
fclose(tmp2);
}
int main(void) {
test_inout(format_arg_base64);
test_inout(format_arg_hex);
test_inout(format_arg_binary);
exit(0);
}
+143 -14
View File
@@ -148,12 +148,80 @@ parse_err:
return NULL;
}
void dump_hex(const unsigned char *buf, unsigned int len, FILE *output, bool space) {
unsigned int i;
for (i = 0; i < len; i++) {
fprintf(output, "%02x%s", buf[i], space == true ? " " : "");
size_t read_data(unsigned char *buf, size_t len, FILE* input, enum enum_format format) {
char raw_buf[3072 * 2];
size_t raw_len = sizeof(raw_buf);
raw_len = fread(raw_buf, 1, raw_len, input);
switch(format) {
case format_arg_hex:
if(raw_buf[raw_len - 1] == '\n') {
raw_len -= 1;
}
if(ykpiv_hex_decode(raw_buf, raw_len, buf, &len) != YKPIV_OK) {
return 0;
}
return len;
case format_arg_base64:
{
int read;
BIO *b64 = BIO_new(BIO_f_base64());
BIO *bio = BIO_new_mem_buf(raw_buf, raw_len);
BIO_push(b64, bio);
read = BIO_read(b64, buf, len);
BIO_free_all(b64);
if(read <= 0) {
return 0;
} else {
return (size_t)read;
}
}
break;
case format_arg_binary:
if(raw_len > len) {
return 0;
}
memcpy(buf, raw_buf, raw_len);
return raw_len;
case format__NULL:
default:
return 0;
}
}
void dump_data(const unsigned char *buf, unsigned int len, FILE *output, bool space, enum enum_format format) {
switch(format) {
case format_arg_hex:
{
char tmp[3072 * 3 + 1];
unsigned int i;
unsigned int step = 2;
if(space) step += 1;
if(len > 3072) {
return;
}
for (i = 0; i < len; i++) {
sprintf(tmp + i * step, "%02x%s", buf[i], space == true ? " " : "");
}
fprintf(output, "%s\n", tmp);
}
return;
case format_arg_base64:
{
BIO *b64 = BIO_new(BIO_f_base64());
BIO *bio = BIO_new_fp(output, BIO_NOCLOSE);
BIO_push(b64, bio);
BIO_write(b64, buf, (int)len);
BIO_flush(b64);
BIO_free_all(b64);
}
return;
case format_arg_binary:
fwrite(buf, 1, len, output);
return;
case format__NULL:
default:
return;
}
fprintf(output, "\n");
}
int get_length(const unsigned char *buffer, int *len) {
@@ -276,33 +344,94 @@ int key_to_object_id(int key) {
int object;
switch(key) {
case 0x9a:
case YKPIV_KEY_AUTHENTICATION:
object = YKPIV_OBJ_AUTHENTICATION;
break;
case 0x9c:
case YKPIV_KEY_CARDMGM:
object = YKPIV_OBJ_SIGNATURE;
break;
case 0x9d:
case YKPIV_KEY_KEYMGM:
object = YKPIV_OBJ_KEY_MANAGEMENT;
break;
case 0x9e:
case YKPIV_KEY_CARDAUTH:
object = YKPIV_OBJ_CARD_AUTH;
break;
case YKPIV_KEY_RETIRED1:
object = YKPIV_OBJ_RETIRED1;
break;
case YKPIV_KEY_RETIRED2:
object = YKPIV_OBJ_RETIRED2;
break;
case YKPIV_KEY_RETIRED3:
object = YKPIV_OBJ_RETIRED3;
break;
case YKPIV_KEY_RETIRED4:
object = YKPIV_OBJ_RETIRED4;
break;
case YKPIV_KEY_RETIRED5:
object = YKPIV_OBJ_RETIRED5;
break;
case YKPIV_KEY_RETIRED6:
object = YKPIV_OBJ_RETIRED6;
break;
case YKPIV_KEY_RETIRED7:
object = YKPIV_OBJ_RETIRED7;
break;
case YKPIV_KEY_RETIRED8:
object = YKPIV_OBJ_RETIRED8;
break;
case YKPIV_KEY_RETIRED9:
object = YKPIV_OBJ_RETIRED9;
break;
case YKPIV_KEY_RETIRED10:
object = YKPIV_OBJ_RETIRED10;
break;
case YKPIV_KEY_RETIRED11:
object = YKPIV_OBJ_RETIRED11;
break;
case YKPIV_KEY_RETIRED12:
object = YKPIV_OBJ_RETIRED12;
break;
case YKPIV_KEY_RETIRED13:
object = YKPIV_OBJ_RETIRED13;
break;
case YKPIV_KEY_RETIRED14:
object = YKPIV_OBJ_RETIRED14;
break;
case YKPIV_KEY_RETIRED15:
object = YKPIV_OBJ_RETIRED15;
break;
case YKPIV_KEY_RETIRED16:
object = YKPIV_OBJ_RETIRED16;
break;
case YKPIV_KEY_RETIRED17:
object = YKPIV_OBJ_RETIRED17;
break;
case YKPIV_KEY_RETIRED18:
object = YKPIV_OBJ_RETIRED18;
break;
case YKPIV_KEY_RETIRED19:
object = YKPIV_OBJ_RETIRED19;
break;
case YKPIV_KEY_RETIRED20:
object = YKPIV_OBJ_RETIRED20;
break;
default:
object = 0;
}
return object;
}
bool set_component_with_len(unsigned char **in_ptr, const BIGNUM *bn, int element_len) {
bool set_component(unsigned char *in_ptr, const BIGNUM *bn, int element_len) {
int real_len = BN_num_bytes(bn);
*in_ptr += set_length(*in_ptr, element_len);
if(real_len > element_len) {
return false;
}
memset(*in_ptr, 0, (size_t)(element_len - real_len));
*in_ptr += element_len - real_len;
*in_ptr += BN_bn2bin(bn, *in_ptr);
memset(in_ptr, 0, (size_t)(element_len - real_len));
in_ptr += element_len - real_len;
BN_bn2bin(bn, in_ptr);
return true;
}
+5 -2
View File
@@ -31,6 +31,8 @@
#ifndef YUBICO_PIV_TOOL_INTERNAL_H
#define YUBICO_PIV_TOOL_INTERNAL_H
#include <stdbool.h>
#include <openssl/x509.h>
#include "cmdline.h"
@@ -38,7 +40,8 @@
#define INPUT 1
#define OUTPUT 2
void dump_hex(unsigned const char*, unsigned int, FILE*, bool);
size_t read_data(unsigned char*, size_t, FILE*, enum enum_format);
void dump_data(unsigned const char*, unsigned int, FILE*, bool, enum enum_format);
int set_length(unsigned char*, int);
int get_length(const unsigned char*, int*);
X509_NAME *parse_name(const char*);
@@ -46,7 +49,7 @@ unsigned char get_algorithm(EVP_PKEY*);
FILE *open_file(const char*, int);
int get_object_id(enum enum_slot slot);
int key_to_object_id(int key);
bool set_component_with_len(unsigned char**, const BIGNUM*, int);
bool set_component(unsigned char *in_ptr, const BIGNUM *bn, int element_len);
bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*,
unsigned int*, int);
bool read_pw(const char*, char*, size_t, int);
+350 -199
View File
@@ -63,6 +63,17 @@ unsigned const char chuid_tmpl[] = {
};
#define CHUID_GUID_OFFS 29
unsigned const char ccc_tmpl[] = {
0xf0, 0x15, 0xa0, 0x00, 0x00, 0x01, 0x16, 0xff, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x01, 0x21,
0xf2, 0x01, 0x21, 0xf3, 0x00, 0xf4, 0x01, 0x00, 0xf5, 0x01, 0x10, 0xf6, 0x00,
0xf7, 0x00, 0xfa, 0x00, 0xfb, 0x00, 0xfc, 0x00, 0xfd, 0x00, 0xfe, 0x00
};
#define CCC_ID_OFFS 9
#define CHUID 0
#define CCC 1
#define MAX_OID_LEN 19
#define KEY_LEN 24
@@ -71,7 +82,7 @@ static void print_version(ykpiv_state *state, const char *output_file_name) {
char version[7];
FILE *output_file = open_file(output_file_name, OUTPUT);
if(!output_file) {
fprintf(stderr, "Failed opening output_file_name\n");
return;
}
if(ykpiv_get_version(state, version, sizeof(version)) == YKPIV_OK) {
@@ -316,14 +327,15 @@ static bool set_pin_retries(ykpiv_state *state, int pin_retries, int puk_retries
}
static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
const char *input_file_name, const char *slot, char *password,
enum enum_pin_policy pin_policy, enum enum_touch_policy touch_policy) {
const char *input_file_name, const char *slot, char *password,
enum enum_pin_policy pin_policy, enum enum_touch_policy touch_policy) {
int key = 0;
FILE *input_file = NULL;
EVP_PKEY *private_key = NULL;
PKCS12 *p12 = NULL;
X509 *cert = NULL;
bool ret = false;
ykpiv_rc rc = YKPIV_GENERIC_ERROR;
sscanf(slot, "%2x", &key);
@@ -360,119 +372,123 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
{
unsigned char algorithm = get_algorithm(private_key);
unsigned char pp = YKPIV_PINPOLICY_DEFAULT;
unsigned char tp = YKPIV_TOUCHPOLICY_DEFAULT;
if(algorithm == 0) {
goto import_out;
}
{
unsigned char data[0xff];
unsigned long recv_len = sizeof(data);
unsigned char in_data[1024];
unsigned char *in_ptr = in_data;
unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, algorithm, key};
int sw;
if(YKPIV_IS_RSA(algorithm)) {
RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key);
unsigned char e[4];
unsigned char *e_ptr = e;
int element_len = 128;
if(algorithm == YKPIV_ALGO_RSA1024) {
element_len = 64;
}
if((set_component_with_len(&e_ptr, rsa_private_key->e, 3) == false) ||
!(e[1] == 0x01 && e[2] == 0x00 && e[3] == 0x01)) {
fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n");
goto import_out;
}
if(pin_policy != pin_policy__NULL) {
pp = get_pin_policy(pin_policy);
}
*in_ptr++ = 0x01;
if(set_component_with_len(&in_ptr, rsa_private_key->p, element_len) == false) {
fprintf(stderr, "Failed setting p component.\n");
goto import_out;
}
if(touch_policy != touch_policy__NULL) {
tp = get_touch_policy(touch_policy);
}
*in_ptr++ = 0x02;
if(set_component_with_len(&in_ptr, rsa_private_key->q, element_len) == false) {
fprintf(stderr, "Failed setting q component.\n");
goto import_out;
}
if(YKPIV_IS_RSA(algorithm)) {
RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key);
unsigned char e[4];
unsigned char p[128];
unsigned char q[128];
unsigned char dmp1[128];
unsigned char dmq1[128];
unsigned char iqmp[128];
*in_ptr++ = 0x03;
if(set_component_with_len(&in_ptr, rsa_private_key->dmp1, element_len) == false) {
fprintf(stderr, "Failed setting dmp1 component.\n");
goto import_out;
}
*in_ptr++ = 0x04;
if(set_component_with_len(&in_ptr, rsa_private_key->dmq1, element_len) == false) {
fprintf(stderr, "Failed setting dmq1 component.\n");
goto import_out;
}
*in_ptr++ = 0x05;
if(set_component_with_len(&in_ptr, rsa_private_key->iqmp, element_len) == false) {
fprintf(stderr, "Failed setting iqmp component.\n");
goto import_out;
}
} else if(YKPIV_IS_EC(algorithm)) {
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(private_key);
const BIGNUM *s = EC_KEY_get0_private_key(ec);
int element_len = 32;
if(algorithm == YKPIV_ALGO_ECCP384) {
element_len = 48;
}
*in_ptr++ = 0x06;
if(set_component_with_len(&in_ptr, s, element_len) == false) {
fprintf(stderr, "Failed setting ec private key.\n");
goto import_out;
}
int element_len = 128;
if(algorithm == YKPIV_ALGO_RSA1024) {
element_len = 64;
}
if(pin_policy != pin_policy__NULL) {
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 1;
*in_ptr++ = get_pin_policy(pin_policy);
}
if(touch_policy != touch_policy__NULL) {
*in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
*in_ptr++ = 1;
*in_ptr++ = get_touch_policy(touch_policy);
if((set_component(e, rsa_private_key->e, 3) == false) ||
!(e[0] == 0x01 && e[1] == 0x00 && e[2] == 0x01)) {
fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n");
goto import_out;
}
if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data,
&recv_len, &sw) != YKPIV_OK) {
return false;
} else if(sw == 0x6a80) {
fprintf(stderr, "Failed import.");
if(pin_policy != pin_policy__NULL) {
fprintf(stderr, "Maybe pin-policy is not supported on this key?\n");
} else if(touch_policy != touch_policy__NULL) {
fprintf(stderr, "Maybe touch-policy is not supported on this key?\n");
} else {
fprintf(stderr, "Maybe algorithm is not supported on this key?\n");
}
} else if(sw != 0x9000) {
fprintf(stderr, "Failed import command with code %x.\n", sw);
} else {
ret = true;
if(set_component(p, rsa_private_key->p, element_len) == false) {
fprintf(stderr, "Failed setting p component.\n");
goto import_out;
}
if(set_component(q, rsa_private_key->q, element_len) == false) {
fprintf(stderr, "Failed setting q component.\n");
goto import_out;
}
if(set_component(dmp1, rsa_private_key->dmp1, element_len) == false) {
fprintf(stderr, "Failed setting dmp1 component.\n");
goto import_out;
}
if(set_component(dmq1, rsa_private_key->dmq1, element_len) == false) {
fprintf(stderr, "Failed setting dmq1 component.\n");
goto import_out;
}
if(set_component(iqmp, rsa_private_key->iqmp, element_len) == false) {
fprintf(stderr, "Failed setting iqmp component.\n");
goto import_out;
}
rc = ykpiv_import_private_key(state, key, algorithm,
p, element_len,
q, element_len,
dmp1, element_len,
dmq1, element_len,
iqmp, element_len,
NULL, 0,
pp, tp);
}
else if(YKPIV_IS_EC(algorithm)) {
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(private_key);
const BIGNUM *s = EC_KEY_get0_private_key(ec);
unsigned char s_ptr[48];
int element_len = 32;
if(algorithm == YKPIV_ALGO_ECCP384) {
element_len = 48;
}
if(set_component(s_ptr, s, element_len) == false) {
fprintf(stderr, "Failed setting ec private key.\n");
goto import_out;
}
rc = ykpiv_import_private_key(state, key, algorithm,
NULL, 0,
NULL, 0,
NULL, 0,
NULL, 0,
NULL, 0,
s_ptr, element_len,
pp, tp);
}
ret = true;
if(rc != YKPIV_OK) {
ret = false;
}
}
import_out:
if(private_key) {
EVP_PKEY_free(private_key);
}
if(p12) {
PKCS12_free(p12);
}
if(cert) {
X509_free(cert);
}
if(input_file != stdin) {
fclose(input_file);
}
return ret;
}
@@ -536,15 +552,16 @@ static bool import_cert(ykpiv_state *state, enum enum_key_format cert_format,
}
{
unsigned char certdata[2100];
unsigned char certdata[3072];
unsigned char *certptr = certdata;
int object = get_object_id(slot);
ykpiv_rc res;
if(cert_len > 2048) {
fprintf(stderr, "Certificate to large, maximum 2048 bytes (was %d bytes).\n", cert_len);
if(4 + cert_len + 5 > 3072) { /* 4 is prefix size, 5 is postfix size */
fprintf(stderr, "Certificate is to large to fit in buffer.\n");
goto import_cert_out;
}
*certptr++ = 0x70;
certptr += set_length(certptr, cert_len);
if (compress) {
@@ -587,20 +604,36 @@ import_cert_out:
return ret;
}
static bool set_chuid(ykpiv_state *state, int verbose) {
unsigned char chuid[sizeof(chuid_tmpl)];
static bool set_dataobject(ykpiv_state *state, int verbose, int type) {
unsigned char obj[1024];
ykpiv_rc res;
size_t offs, rand_len, len;
const unsigned char *tmpl;
int id;
memcpy(chuid, chuid_tmpl, sizeof(chuid));
if(RAND_pseudo_bytes(chuid + CHUID_GUID_OFFS, 0x10) == -1) {
if(type == CHUID) {
offs = CHUID_GUID_OFFS;
len = sizeof(chuid_tmpl);
rand_len = 0x10;
tmpl = chuid_tmpl;
id = YKPIV_OBJ_CHUID;
} else {
offs = CCC_ID_OFFS;
rand_len = 0xe;
len = sizeof(ccc_tmpl);
tmpl = ccc_tmpl;
id = YKPIV_OBJ_CAPABILITY;
}
memcpy(obj, tmpl, len);
if(RAND_pseudo_bytes(obj + offs, rand_len) == -1) {
fprintf(stderr, "error: no randomness.\n");
return false;
}
if(verbose) {
fprintf(stderr, "Setting the CHUID to: ");
dump_hex(chuid, sizeof(chuid), stderr, true);
fprintf(stderr, "Setting the %s to: ", type == CHUID ? "CHUID" : "CCC");
dump_data(obj, len, stderr, true, format_arg_hex);
}
if((res = ykpiv_save_object(state, YKPIV_OBJ_CHUID, chuid, sizeof(chuid))) != YKPIV_OK) {
if((res = ykpiv_save_object(state, id, obj, len)) != YKPIV_OK) {
fprintf(stderr, "Failed communicating with device: %s\n", ykpiv_strerror(res));
return false;
}
@@ -689,7 +722,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
memcpy(digest, oid, oid_len);
/* XXX: this should probably use X509_REQ_digest() but that's buggy */
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ_INFO), md, req->req_info,
digest + oid_len, &digest_len)) {
digest + oid_len, &digest_len)) {
fprintf(stderr, "Failed doing digest of request.\n");
goto request_out;
}
@@ -748,7 +781,7 @@ request_out:
static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_format,
const char *input_file_name, const char *slot, char *subject, enum enum_hash hash,
const char *output_file_name) {
int serial, int validDays, const char *output_file_name) {
FILE *input_file = NULL;
FILE *output_file = NULL;
bool ret = false;
@@ -814,7 +847,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
fprintf(stderr, "Failed to set the certificate public key.\n");
goto selfsign_out;
}
if(!ASN1_INTEGER_set(X509_get_serialNumber(x509), 1)) {
if(!ASN1_INTEGER_set(X509_get_serialNumber(x509), serial)) {
fprintf(stderr, "Failed to set certificate serial.\n");
goto selfsign_out;
}
@@ -822,7 +855,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
fprintf(stderr, "Failed to set certificate notBefore.\n");
goto selfsign_out;
}
if(!X509_gmtime_adj(X509_get_notAfter(x509), 31536000L)) {
if(!X509_gmtime_adj(X509_get_notAfter(x509), 60L * 60L * 24L * validDays)) {
fprintf(stderr, "Failed to set certificate notAfter.\n");
goto selfsign_out;
}
@@ -856,7 +889,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
memcpy(digest, oid, oid_len);
/* XXX: this should probably use X509_digest() but that looks buggy */
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_CINF), md, x509->cert_info,
digest + oid_len, &digest_len)) {
digest + oid_len, &digest_len)) {
fprintf(stderr, "Failed doing digest of certificate.\n");
goto selfsign_out;
}
@@ -936,17 +969,16 @@ static bool verify_pin(ykpiv_state *state, const char *pin) {
* since they're very similar in what data they use. */
static bool change_pin(ykpiv_state *state, enum enum_action action, const char *pin,
const char *new_pin) {
unsigned char templ[] = {0, YKPIV_INS_CHANGE_REFERENCE, 0, 0x80};
unsigned char indata[0x10];
unsigned char data[0xff];
unsigned long recv_len = sizeof(data);
char pinbuf[9] = {0};
char new_pinbuf[9] = {0};
const char *name = action == action_arg_changeMINUS_pin ? "pin" : "puk";
const char *new_name = action == action_arg_changeMINUS_puk ? "new puk" : "new pin";
int sw;
int (*op)(ykpiv_state *state, const char * puk, size_t puk_len,
const char * new_pin, size_t new_pin_len, int *tries) = ykpiv_change_pin;
size_t pin_len;
size_t new_len;
int tries;
ykpiv_rc res;
if(!pin) {
if (!read_pw(name, pinbuf, sizeof(pinbuf), false)) {
@@ -969,38 +1001,33 @@ static bool change_pin(ykpiv_state *state, enum enum_action action, const char *
}
if(action == action_arg_unblockMINUS_pin) {
templ[1] = YKPIV_INS_RESET_RETRY;
op = ykpiv_unblock_pin;
}
else if(action == action_arg_changeMINUS_puk) {
templ[3] = 0x81;
op = ykpiv_change_puk;
}
memcpy(indata, pin, pin_len);
if(pin_len < 8) {
memset(indata + pin_len, 0xff, 8 - pin_len);
}
memcpy(indata + 8, new_pin, new_len);
if(new_len < 8) {
memset(indata + 8 + new_len, 0xff, 16 - new_len);
}
if(ykpiv_transfer_data(state, templ, indata, sizeof(indata), data, &recv_len, &sw) != YKPIV_OK) {
return false;
} else if(sw != 0x9000) {
if((sw >> 8) == 0x63) {
int tries = sw & 0xf;
res = op(state, pin, pin_len, new_pin, new_len, &tries);
switch (res) {
case YKPIV_OK:
return true;
case YKPIV_WRONG_PIN:
fprintf(stderr, "Failed verifying %s code, now %d tries left before blocked.\n",
name, tries);
} else if(sw == 0x6983) {
name, tries);
return false;
case YKPIV_PIN_LOCKED:
if(action == action_arg_changeMINUS_pin) {
fprintf(stderr, "The pin code is blocked, use the unblock-pin action to unblock it.\n");
} else {
fprintf(stderr, "The puk code is blocked, you will have to reinitialize the application.\n");
}
} else {
fprintf(stderr, "Failed changing/unblocking code, error: %x\n", sw);
}
return false;
return false;
default:
fprintf(stderr, "Failed changing/unblocking code, error: %x\n", res);
return false;
}
return true;
}
static bool delete_certificate(ykpiv_state *state, enum enum_slot slot) {
@@ -1019,7 +1046,7 @@ static bool read_certificate(ykpiv_state *state, enum enum_slot slot,
enum enum_key_format key_format, const char *output_file_name) {
FILE *output_file;
int object = get_object_id(slot);
unsigned char data[2048];
unsigned char data[3072];
const unsigned char *ptr = data;
unsigned long len = sizeof(data);
int cert_len;
@@ -1100,6 +1127,9 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output,
output_file = open_file(output, OUTPUT);
if(!output_file) {
if(input_file && input_file != stdin) {
fclose(input_file);
}
return false;
}
@@ -1127,7 +1157,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output,
if(verbosity) {
fprintf(stderr, "file hashed as: ");
dump_hex(hashed, hash_len, stderr, true);
dump_data(hashed, hash_len, stderr, true, format_arg_hex);
}
EVP_MD_CTX_destroy(mdctx);
}
@@ -1146,7 +1176,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output,
if(verbosity) {
fprintf(stderr, "file signed as: ");
dump_hex(buf, len, stderr, true);
dump_data(buf, len, stderr, true, format_arg_hex);
}
fwrite(buf, 1, len, output_file);
ret = true;
@@ -1167,7 +1197,8 @@ out:
static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_MD *md,
FILE *output) {
int object = get_object_id(slot);
unsigned char data[2048];
int slot_name;
unsigned char data[3072];
const unsigned char *ptr = data;
unsigned long len = sizeof(data);
int cert_len;
@@ -1176,10 +1207,18 @@ static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_M
BIO *bio = NULL;
if(ykpiv_fetch_object(state, object, data, &len) != YKPIV_OK) {
fprintf(output, "No data available.\n");
return;
}
if (slot == slot_arg_9a)
slot_name = 0x9a;
else if (slot >= slot_arg_9c && slot <= slot_arg_9e)
slot_name = 0x9b + slot;
else
slot_name = 0x82 + (slot - slot_arg_82);
fprintf(output, "Slot %x:\t", slot_name);
if(*ptr++ == 0x70) {
unsigned int md_len = sizeof(data);
ASN1_TIME *not_before, *not_after;
@@ -1237,7 +1276,7 @@ static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_M
fprintf(output, "\n");
X509_digest(x509, md, data, &md_len);
fprintf(output, "\tFingerprint:\t");
dump_hex(data, md_len, output, false);
dump_data(data, md_len, output, false, format_arg_hex);
bio = BIO_new_fp(output, BIO_NOCLOSE | BIO_FP_TEXT);
not_before = X509_get_notBefore(x509);
@@ -1266,10 +1305,12 @@ cert_out:
}
static bool status(ykpiv_state *state, enum enum_hash hash,
const char *output_file_name) {
enum enum_slot slot,
const char *output_file_name) {
const EVP_MD *md;
unsigned char chuid[2048];
long unsigned len = sizeof(chuid);
unsigned char buf[3072];
long unsigned len = sizeof(buf);
int i;
FILE *output_file = open_file(output_file_name, OUTPUT);
if(!output_file) {
return false;
@@ -1281,20 +1322,26 @@ static bool status(ykpiv_state *state, enum enum_hash hash,
}
fprintf(output_file, "CHUID:\t");
if(ykpiv_fetch_object(state, YKPIV_OBJ_CHUID, chuid, &len) != YKPIV_OK) {
if(ykpiv_fetch_object(state, YKPIV_OBJ_CHUID, buf, &len) != YKPIV_OK) {
fprintf(output_file, "No data available\n");
} else {
dump_hex(chuid, len, output_file, false);
dump_data(buf, len, output_file, false, format_arg_hex);
}
fprintf(output_file, "Slot 9a:\t");
print_cert_info(state, slot_arg_9a, md, output_file);
fprintf(output_file, "Slot 9c:\t");
print_cert_info(state, slot_arg_9c, md, output_file);
fprintf(output_file, "Slot 9d:\t");
print_cert_info(state, slot_arg_9d, md, output_file);
fprintf(output_file, "Slot 9e:\t");
print_cert_info(state, slot_arg_9e, md, output_file);
len = sizeof(buf);
fprintf(output_file, "CCC:\t");
if(ykpiv_fetch_object(state, YKPIV_OBJ_CAPABILITY, buf, &len) != YKPIV_OK) {
fprintf(output_file, "No data available\n");
} else {
dump_data(buf, len, output_file, false, format_arg_hex);
}
if (slot == slot__NULL)
for (i = 0; i < 24; i++) {
print_cert_info(state, i, md, output_file);
}
else
print_cert_info(state, slot, md, output_file);
{
int tries;
@@ -1360,7 +1407,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot,
EVP_DigestFinal_ex(mdctx, data, &data_len);
if(verbose) {
fprintf(stderr, "Test data hashes as: ");
dump_hex(data, data_len, stderr, true);
dump_data(data, data_len, stderr, true, format_arg_hex);
}
}
@@ -1516,9 +1563,9 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
if(len == sizeof(secret)) {
if(verbose) {
fprintf(stderr, "Generated nonce: ");
dump_hex(secret, sizeof(secret), stderr, true);
dump_data(secret, sizeof(secret), stderr, true, format_arg_hex);
fprintf(stderr, "Decrypted nonce: ");
dump_hex(secret2, sizeof(secret2), stderr, true);
dump_data(secret2, sizeof(secret2), stderr, true, format_arg_hex);
}
if(memcmp(secret, secret2, sizeof(secret)) == 0) {
fprintf(stderr, "Successfully performed RSA decryption!\n");
@@ -1558,9 +1605,9 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
}
if(verbose) {
fprintf(stderr, "ECDH host generated: ");
dump_hex(secret, len, stderr, true);
dump_data(secret, len, stderr, true, format_arg_hex);
fprintf(stderr, "ECDH card generated: ");
dump_hex(secret2, len, stderr, true);
dump_data(secret2, len, stderr, true, format_arg_hex);
}
if(memcmp(secret, secret2, key_len) == 0) {
fprintf(stderr, "Successfully performed ECDH exchange with card.\n");
@@ -1618,11 +1665,6 @@ static bool attest(ykpiv_state *state, const char *slot,
return false;
}
output_file = open_file(output_file_name, OUTPUT);
if(!output_file) {
return false;
}
if(ykpiv_transfer_data(state, templ, NULL, 0, data, &len, &sw) != YKPIV_OK) {
fprintf(stderr, "Failed to communicate.\n");
goto attest_out;
@@ -1660,7 +1702,73 @@ attest_out:
if(x509) {
X509_free(x509);
}
return ret;
}
static bool write_object(ykpiv_state *state, int id,
const char *input_file_name, int verbosity, enum enum_format format) {
bool ret = false;
FILE *input_file = NULL;
unsigned char data[3072];
size_t len = sizeof(data);
ykpiv_rc res;
input_file = open_file(input_file_name, INPUT);
if(!input_file) {
return false;
}
if(isatty(fileno(input_file))) {
fprintf(stderr, "Please paste the data...\n");
}
len = read_data(data, len, input_file, format);
if(len == 0) {
fprintf(stderr, "Failed reading data\n");
goto write_out;
}
if(verbosity) {
fprintf(stderr, "Writing %lu bytes of data to object %x.\n", len, id);
}
if((res = ykpiv_save_object(state, id, data, len)) != YKPIV_OK) {
fprintf(stderr, "Failed writing data to device: %s\n", ykpiv_strerror(res));
} else {
ret = true;
}
write_out:
if(input_file != stdin) {
fclose(input_file);
}
return ret;
}
static bool read_object(ykpiv_state *state, int id, const char *output_file_name,
enum enum_format format) {
FILE *output_file = NULL;
unsigned char data[3072];
unsigned long len = sizeof(data);
bool ret = false;
output_file = open_file(output_file_name, OUTPUT);
if(!output_file) {
return false;
}
if(ykpiv_fetch_object(state, id, data, &len) != YKPIV_OK) {
fprintf(stderr, "Failed fetching object.\n");
goto read_out;
}
dump_data(data, len, output_file, false, format);
ret = true;
read_out:
if(output_file != stdout) {
fclose(output_file);
}
return ret;
}
@@ -1671,12 +1779,16 @@ int main(int argc, char *argv[]) {
enum enum_action action;
unsigned int i;
int ret = EXIT_SUCCESS;
bool authed = false;
char pwbuf[128];
char *password;
if(cmdline_parser(argc, argv, &args_info) != 0) {
return EXIT_FAILURE;
}
verbosity = args_info.verbose_arg + (int)args_info.verbose_given;
password = args_info.password_arg;
for(i = 0; i < args_info.action_given; i++) {
action = *(args_info.action_arg + i);
@@ -1709,12 +1821,21 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}
break;
case action_arg_writeMINUS_object:
case action_arg_readMINUS_object:
if(!args_info.id_given) {
fprintf(stderr, "The '%s' action needs the --id argument.\n",
cmdline_parser_action_values[action]);
return EXIT_FAILURE;
}
break;
case action_arg_changeMINUS_pin:
case action_arg_changeMINUS_puk:
case action_arg_unblockMINUS_pin:
case action_arg_verifyMINUS_pin:
case action_arg_setMINUS_mgmMINUS_key:
case action_arg_setMINUS_chuid:
case action_arg_setMINUS_ccc:
case action_arg_version:
case action_arg_reset:
case action_arg_status:
@@ -1736,20 +1857,60 @@ int main(int argc, char *argv[]) {
}
for(i = 0; i < args_info.action_given; i++) {
bool needs_auth = false;
action = *(args_info.action_arg + i);
switch(action) {
case action_arg_importMINUS_key:
case action_arg_importMINUS_certificate:
if(args_info.key_format_arg == key_format_arg_PKCS12 && !password) {
if(verbosity) {
fprintf(stderr, "Asking for password since '%s' needs it.\n", cmdline_parser_action_values[action]);
}
if(!read_pw("Password", pwbuf, sizeof(pwbuf), false)) {
fprintf(stderr, "Failed to get password.\n");
return false;
}
password = pwbuf;
}
case action_arg_generate:
case action_arg_setMINUS_mgmMINUS_key:
case action_arg_pinMINUS_retries:
case action_arg_importMINUS_key:
case action_arg_importMINUS_certificate:
case action_arg_setMINUS_chuid:
case action_arg_setMINUS_ccc:
case action_arg_deleteMINUS_certificate:
if(verbosity) {
fprintf(stderr, "Authenticating since action '%s' needs that.\n", cmdline_parser_action_values[action]);
case action_arg_writeMINUS_object:
if(!authed) {
unsigned char key[KEY_LEN];
size_t key_len = sizeof(key);
char keybuf[KEY_LEN*2+1];
char *key_ptr = args_info.key_arg;
if(verbosity) {
fprintf(stderr, "Authenticating since action '%s' needs that.\n", cmdline_parser_action_values[action]);
}
if(args_info.key_given && args_info.key_orig == NULL) {
if(!read_pw("management key", keybuf, sizeof(keybuf), false)) {
fprintf(stderr, "Failed to read management key from stdin,\n");
return EXIT_FAILURE;
}
key_ptr = keybuf;
}
if(ykpiv_hex_decode(key_ptr, strlen(key_ptr), key, &key_len) != YKPIV_OK) {
fprintf(stderr, "Failed decoding key!\n");
return EXIT_FAILURE;
}
if(ykpiv_authenticate(state, key) != YKPIV_OK) {
fprintf(stderr, "Failed authentication with the application.\n");
return EXIT_FAILURE;
}
if(verbosity) {
fprintf(stderr, "Successful application authentication.\n");
}
authed = true;
} else {
if(verbosity) {
fprintf(stderr, "Skipping authentication for '%s' since it's already done.\n", cmdline_parser_action_values[action]);
}
}
needs_auth = true;
break;
case action_arg_version:
case action_arg_reset:
@@ -1765,44 +1926,20 @@ int main(int argc, char *argv[]) {
case action_arg_testMINUS_decipher:
case action_arg_listMINUS_readers:
case action_arg_attest:
case action_arg_readMINUS_object:
case action__NULL:
default:
if(verbosity) {
fprintf(stderr, "Action '%s' does not need authentication.\n", cmdline_parser_action_values[action]);
}
continue;
}
if(needs_auth) {
unsigned char key[KEY_LEN];
size_t key_len = sizeof(key);
char keybuf[KEY_LEN*2+1];
char *key_ptr = args_info.key_arg;
if(args_info.key_given && args_info.key_orig == NULL) {
if(!read_pw("management key", keybuf, sizeof(keybuf), false)) {
fprintf(stderr, "Failed to read management key from stdin,\n");
return EXIT_FAILURE;
}
key_ptr = keybuf;
}
if(ykpiv_hex_decode(key_ptr, strlen(key_ptr), key, &key_len) != YKPIV_OK) {
fprintf(stderr, "Failed decoding key!\n");
return EXIT_FAILURE;
}
if(ykpiv_authenticate(state, key) != YKPIV_OK) {
fprintf(stderr, "Failed authentication with the application.\n");
return EXIT_FAILURE;
}
if(verbosity) {
fprintf(stderr, "Successful application authentication.\n");
}
break;
}
}
/* openssl setup.. */
OpenSSL_add_all_algorithms();
for(i = 0; i < args_info.action_given; i++) {
char new_keybuf[KEY_LEN*2+1] = {0};
char *new_mgm_key = args_info.new_key_arg;
@@ -1855,7 +1992,7 @@ int main(int argc, char *argv[]) {
break;
case action_arg_reset:
if(reset(state) == false) {
fprintf(stderr, "Reset failed, are pincodes blocked?\n");
fprintf(stderr, "Reset failed, are pincodes blocked?\n");
ret = EXIT_FAILURE;
} else {
fprintf(stderr, "Successfully reset the application.\n");
@@ -1871,25 +2008,27 @@ int main(int argc, char *argv[]) {
}
break;
case action_arg_importMINUS_key:
if(import_key(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_orig, args_info.password_arg,
if(import_key(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_orig, password,
args_info.pin_policy_arg, args_info.touch_policy_arg) == false) {
fprintf(stderr, "Unable to import private key\n");
ret = EXIT_FAILURE;
} else {
fprintf(stderr, "Successfully imported a new private key.\n");
}
break;
case action_arg_importMINUS_certificate:
if(import_cert(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_arg, args_info.password_arg) == false) {
if(import_cert(state, args_info.key_format_arg, args_info.input_arg, args_info.slot_arg, password) == false) {
ret = EXIT_FAILURE;
} else {
fprintf(stderr, "Successfully imported a new certificate.\n");
}
break;
case action_arg_setMINUS_ccc:
case action_arg_setMINUS_chuid:
if(set_chuid(state, verbosity) == false) {
if(set_dataobject(state, verbosity, action == action_arg_setMINUS_chuid ? CHUID : CCC) == false) {
ret = EXIT_FAILURE;
} else {
fprintf(stderr, "Successfully set new CHUID.\n");
fprintf(stderr, "Successfully set new %s.\n", action == action_arg_setMINUS_chuid ? "CHUID" : "CCC");
}
break;
case action_arg_requestMINUS_certificate:
@@ -1925,6 +2064,7 @@ int main(int argc, char *argv[]) {
case action_arg_selfsignMINUS_certificate:
if(selfsign_certificate(state, args_info.key_format_arg, args_info.input_arg,
args_info.slot_orig, args_info.subject_arg, args_info.hash_arg,
args_info.serial_arg, args_info.valid_days_arg,
args_info.output_arg) == false) {
ret = EXIT_FAILURE;
} else {
@@ -1943,7 +2083,7 @@ int main(int argc, char *argv[]) {
}
break;
case action_arg_status:
if(status(state, args_info.hash_arg, args_info.output_arg) == false) {
if(status(state, args_info.hash_arg, args_info.slot_arg, args_info.output_arg) == false) {
ret = EXIT_FAILURE;
}
break;
@@ -1963,6 +2103,17 @@ int main(int argc, char *argv[]) {
if(list_readers(state) == false) {
ret = EXIT_FAILURE;
}
case action_arg_writeMINUS_object:
if(write_object(state, args_info.id_arg, args_info.input_arg, verbosity,
args_info.format_arg) == false) {
ret = EXIT_FAILURE;
}
break;
case action_arg_readMINUS_object:
if(read_object(state, args_info.id_arg, args_info.output_arg,
args_info.format_arg) == false) {
ret = EXIT_FAILURE;
}
break;
case action_arg_attest:
if(attest(state, args_info.slot_orig, args_info.key_format_arg,
+2 -5
View File
@@ -26,7 +26,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PACKAGE=yubico-piv-tool
OPENSSLVERSION=1.0.1p
OPENSSLVERSION=1.0.1r
all: usage 32bit 64bit
@@ -53,17 +53,14 @@ doit:
rm -rf $(PWD)/tmp$(ARCH)/root/ssl/ && \
rm $(PWD)/tmp$(ARCH)/root/bin/openssl.exe && \
rm $(PWD)/tmp$(ARCH)/root/bin/c_rehash && \
rm $(PWD)/tmp$(ARCH)/root/bin/ssleay32.dll && \
rm -rf $(PWD)/tmp$(ARCH)/root/lib/engines/ && \
rm -rf $(PWD)/tmp$(ARCH)/root/lib/libssl* && \
rm $(PWD)/tmp$(ARCH)/root/lib/pkgconfig/libssl.pc && \
rm $(PWD)/tmp$(ARCH)/root/lib/pkgconfig/openssl.pc && \
cd .. && \
cp ../$(PACKAGE)-$(VERSION).tar.gz . && \
tar xfa $(PACKAGE)-$(VERSION).tar.gz && \
cd $(PACKAGE)-$(VERSION)/ && \
CC=$(HOST)-gcc PKG_CONFIG_PATH=$(PWD)/tmp$(ARCH)/root/lib/pkgconfig lt_cv_deplibs_check_method=pass_all ./configure --host=$(HOST) --build=x86_64-unknown-linux-gnu --prefix=$(PWD)/tmp$(ARCH)/root LDFLAGS=-L$(PWD)/tmp$(ARCH)/root/lib CPPFLAGS=-I$(PWD)/tmp$(ARCH)/root/include && \
make install $(CHECK) && \
rm -rf $(PWD)/tmp$(ARCH)/root/lib/pkgconfig/ && \
cp COPYING $(PWD)/tmp$(ARCH)/root/licenses/$(PACKAGE).txt && \
cd .. && \
cd root && \
+90 -55
View File
@@ -8,9 +8,29 @@
// TODO: this is mostly from OpenSC, how to give credit?
typedef enum {
PIV_DATA_OBJ_X509_PIV_AUTH = 0, // PIV authentication
PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication
PIV_DATA_OBJ_X509_DS, // Certificate for digital signature
PIV_DATA_OBJ_X509_KM, // Certificate for key management
PIV_DATA_OBJ_X509_CARD_AUTH, // Card authentication
PIV_DATA_OBJ_X509_DS, // Digital signature
PIV_DATA_OBJ_X509_KM, // Key management
PIV_DATA_OBJ_X509_RETIRED1, // Retired key 1
PIV_DATA_OBJ_X509_RETIRED2, // Retired key 2
PIV_DATA_OBJ_X509_RETIRED3, // Retired key 3
PIV_DATA_OBJ_X509_RETIRED4, // Retired key 4
PIV_DATA_OBJ_X509_RETIRED5, // Retired key 5
PIV_DATA_OBJ_X509_RETIRED6, // Retired key 6
PIV_DATA_OBJ_X509_RETIRED7, // Retired key 7
PIV_DATA_OBJ_X509_RETIRED8, // Retired key 8
PIV_DATA_OBJ_X509_RETIRED9, // Retired key 9
PIV_DATA_OBJ_X509_RETIRED10, // Retired key 10
PIV_DATA_OBJ_X509_RETIRED11, // Retired key 11
PIV_DATA_OBJ_X509_RETIRED12, // Retired key 12
PIV_DATA_OBJ_X509_RETIRED13, // Retired key 13
PIV_DATA_OBJ_X509_RETIRED14, // Retired key 14
PIV_DATA_OBJ_X509_RETIRED15, // Retired key 15
PIV_DATA_OBJ_X509_RETIRED16, // Retired key 16
PIV_DATA_OBJ_X509_RETIRED17, // Retired key 17
PIV_DATA_OBJ_X509_RETIRED18, // Retired key 18
PIV_DATA_OBJ_X509_RETIRED19, // Retired key 19
PIV_DATA_OBJ_X509_RETIRED20, // Retired key 20
PIV_DATA_OBJ_CCC, // Card capability container
PIV_DATA_OBJ_CHUI, // Cardholder unique id
PIV_DATA_OBJ_CHF, // Cardholder fingerprints
@@ -19,73 +39,88 @@ typedef enum {
PIV_DATA_OBJ_PI, // Cardholder printed information
PIV_DATA_OBJ_DISCOVERY, // Discovery object
PIV_DATA_OBJ_HISTORY, // History object
PIV_DATA_OBJ_RETIRED_X509_1, // Retired certificate for KM 1
PIV_DATA_OBJ_RETIRED_X509_2, // Retired certificate for KM 2
PIV_DATA_OBJ_RETIRED_X509_3, // Retired certificate for KM 3
PIV_DATA_OBJ_RETIRED_X509_4, // Retired certificate for KM 4
PIV_DATA_OBJ_RETIRED_X509_5, // Retired certificate for KM 5
PIV_DATA_OBJ_RETIRED_X509_6, // Retired certificate for KM 6
PIV_DATA_OBJ_RETIRED_X509_7, // Retired certificate for KM 7
PIV_DATA_OBJ_RETIRED_X509_8, // Retired certificate for KM 8
PIV_DATA_OBJ_RETIRED_X509_9, // Retired certificate for KM 9
PIV_DATA_OBJ_RETIRED_X509_10, // Retired certificate for KM 10
PIV_DATA_OBJ_RETIRED_X509_11, // Retired certificate for KM 11
PIV_DATA_OBJ_RETIRED_X509_12, // Retired certificate for KM 12
PIV_DATA_OBJ_RETIRED_X509_13, // Retired certificate for KM 13
PIV_DATA_OBJ_RETIRED_X509_14, // Retired certificate for KM 14
PIV_DATA_OBJ_RETIRED_X509_15, // Retired certificate for KM 15
PIV_DATA_OBJ_RETIRED_X509_16, // Retired certificate for KM 16
PIV_DATA_OBJ_RETIRED_X509_17, // Retired certificate for KM 17
PIV_DATA_OBJ_RETIRED_X509_18, // Retired certificate for KM 18
PIV_DATA_OBJ_RETIRED_X509_19, // Retired certificate for KM 19
PIV_DATA_OBJ_RETIRED_X509_20, // Retired certificate for KM 20
PIV_DATA_OBJ_IRIS_IMAGE, // Cardholder iris images
PIV_DATA_OBJ_BITGT, // Biometric information templates group template
PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer
PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data
/* PIV_DATA_OBJ_9B03, // NON-STANDARD TODO: remove?
PIV_DATA_OBJ_9A06, // NON-STANDARD
PIV_DATA_OBJ_9C06, // NON-STANDARD
PIV_DATA_OBJ_9D06, // NON-STANDARD
PIV_DATA_OBJ_9E06, // NON-STANDARD
PIV_DATA_OBJ_8206, // NON-STANDARD
PIV_DATA_OBJ_8306, // NON-STANDARD
PIV_DATA_OBJ_8406, // NON-STANDARD
PIV_DATA_OBJ_8506, // NON-STANDARD
PIV_DATA_OBJ_8606, // NON-STANDARD
PIV_DATA_OBJ_8706, // NON-STANDARD
PIV_DATA_OBJ_8806, // NON-STANDARD
PIV_DATA_OBJ_8906, // NON-STANDARD
PIV_DATA_OBJ_8A06, // NON-STANDARD
PIV_DATA_OBJ_8B06, // NON-STANDARD
PIV_DATA_OBJ_8C06, // NON-STANDARD
PIV_DATA_OBJ_8D06, // NON-STANDARD
PIV_DATA_OBJ_8E06, // NON-STANDARD
PIV_DATA_OBJ_8F06, // NON-STANDARD
PIV_DATA_OBJ_9006, // NON-STANDARD
PIV_DATA_OBJ_9106, // NON-STANDARD
PIV_DATA_OBJ_9206, // NON-STANDARD
PIV_DATA_OBJ_9306, // NON-STANDARD
PIV_DATA_OBJ_9406, // NON-STANDARD
PIV_DATA_OBJ_9506, // NON-STANDARD*/
PIV_DATA_OBJ_LAST,
PIV_CERT_OBJ_X509_PIV_AUTH, // PIV authentication
PIV_CERT_OBJ_X509_PIV_AUTH, // Certificate for PIV authentication
PIV_CERT_OBJ_X509_CARD_AUTH, // Certificate for card authentication
PIV_CERT_OBJ_X509_DS, // Certificate for digital signature
PIV_CERT_OBJ_X509_KM, // Certificate for key management
PIV_CERT_OBJ_X509_RETIRED1, // Certificate for retired key 1
PIV_CERT_OBJ_X509_RETIRED2, // Certificate for retired key 2
PIV_CERT_OBJ_X509_RETIRED3, // Certificate for retired key 3
PIV_CERT_OBJ_X509_RETIRED4, // Certificate for retired key 4
PIV_CERT_OBJ_X509_RETIRED5, // Certificate for retired key 5
PIV_CERT_OBJ_X509_RETIRED6, // Certificate for retired key 6
PIV_CERT_OBJ_X509_RETIRED7, // Certificate for retired key 7
PIV_CERT_OBJ_X509_RETIRED8, // Certificate for retired key 8
PIV_CERT_OBJ_X509_RETIRED9, // Certificate for retired key 9
PIV_CERT_OBJ_X509_RETIRED10, // Certificate for retired key 10
PIV_CERT_OBJ_X509_RETIRED11, // Certificate for retired key 11
PIV_CERT_OBJ_X509_RETIRED12, // Certificate for retired key 12
PIV_CERT_OBJ_X509_RETIRED13, // Certificate for retired key 13
PIV_CERT_OBJ_X509_RETIRED14, // Certificate for retired key 14
PIV_CERT_OBJ_X509_RETIRED15, // Certificate for retired key 15
PIV_CERT_OBJ_X509_RETIRED16, // Certificate for retired key 16
PIV_CERT_OBJ_X509_RETIRED17, // Certificate for retired key 17
PIV_CERT_OBJ_X509_RETIRED18, // Certificate for retired key 18
PIV_CERT_OBJ_X509_RETIRED19, // Certificate for retired key 19
PIV_CERT_OBJ_X509_RETIRED20, // Certificate for retired key 20
PIV_CERT_OBJ_LAST,
PIV_PVTK_OBJ_PIV_AUTH, // Private key for PIV authentication
PIV_PVTK_OBJ_CARD_AUTH, // Private Key for card authentication
PIV_PVTK_OBJ_DS, // Private Key for digital signature
PIV_PVTK_OBJ_KM, // Private Key for key management
PIV_PVTK_OBJ_CARD_AUTH, // Private key for card authentication
PIV_PVTK_OBJ_DS, // Private key for digital signature
PIV_PVTK_OBJ_KM, // Private key for key management
PIV_PVTK_OBJ_RETIRED1, // Private key for retired key 1
PIV_PVTK_OBJ_RETIRED2, // Private key for retired key 2
PIV_PVTK_OBJ_RETIRED3, // Private key for retired key 3
PIV_PVTK_OBJ_RETIRED4, // Private key for retired key 4
PIV_PVTK_OBJ_RETIRED5, // Private key for retired key 5
PIV_PVTK_OBJ_RETIRED6, // Private key for retired key 6
PIV_PVTK_OBJ_RETIRED7, // Private key for retired key 7
PIV_PVTK_OBJ_RETIRED8, // Private key for retired key 8
PIV_PVTK_OBJ_RETIRED9, // Private key for retired key 9
PIV_PVTK_OBJ_RETIRED10, // Private key for retired key 10
PIV_PVTK_OBJ_RETIRED11, // Private key for retired key 11
PIV_PVTK_OBJ_RETIRED12, // Private key for retired key 12
PIV_PVTK_OBJ_RETIRED13, // Private key for retired key 13
PIV_PVTK_OBJ_RETIRED14, // Private key for retired key 14
PIV_PVTK_OBJ_RETIRED15, // Private key for retired key 15
PIV_PVTK_OBJ_RETIRED16, // Private key for retired key 16
PIV_PVTK_OBJ_RETIRED17, // Private key for retired key 17
PIV_PVTK_OBJ_RETIRED18, // Private key for retired key 18
PIV_PVTK_OBJ_RETIRED19, // Private key for retired key 19
PIV_PVTK_OBJ_RETIRED20, // Private key for retired key 20
PIV_PVTK_OBJ_LAST,
PIV_PUBK_OBJ_PIV_AUTH, // Public key for PIV authentication
PIV_PUBK_OBJ_CARD_AUTH, // Public Key for card authentication
PIV_PUBK_OBJ_DS, // Public Key for digital signature
PIV_PUBK_OBJ_KM, // Public Key for key management
PIV_PUBK_OBJ_CARD_AUTH, // Public key for card authentication
PIV_PUBK_OBJ_DS, // Public key for digital signature
PIV_PUBK_OBJ_KM, // Public key for key management
PIV_PUBK_OBJ_RETIRED1, // Public key for retired key 1
PIV_PUBK_OBJ_RETIRED2, // Public key for retired key 2
PIV_PUBK_OBJ_RETIRED3, // Public key for retired key 3
PIV_PUBK_OBJ_RETIRED4, // Public key for retired key 4
PIV_PUBK_OBJ_RETIRED5, // Public key for retired key 5
PIV_PUBK_OBJ_RETIRED6, // Public key for retired key 6
PIV_PUBK_OBJ_RETIRED7, // Public key for retired key 7
PIV_PUBK_OBJ_RETIRED8, // Public key for retired key 8
PIV_PUBK_OBJ_RETIRED9, // Public key for retired key 9
PIV_PUBK_OBJ_RETIRED10, // Public key for retired key 10
PIV_PUBK_OBJ_RETIRED11, // Public key for retired key 11
PIV_PUBK_OBJ_RETIRED12, // Public key for retired key 12
PIV_PUBK_OBJ_RETIRED13, // Public key for retired key 13
PIV_PUBK_OBJ_RETIRED14, // Public key for retired key 14
PIV_PUBK_OBJ_RETIRED15, // Public key for retired key 15
PIV_PUBK_OBJ_RETIRED16, // Public key for retired key 16
PIV_PUBK_OBJ_RETIRED17, // Public key for retired key 17
PIV_PUBK_OBJ_RETIRED18, // Public key for retired key 18
PIV_PUBK_OBJ_RETIRED19, // Public key for retired key 19
PIV_PUBK_OBJ_RETIRED20, // Public key for retired key 20
PIV_PUBK_OBJ_LAST
} piv_obj_id_t;
+355 -114
View File
@@ -24,34 +24,34 @@ static piv_obj_t piv_objects[] = {
{PIV_DATA_OBJ_X509_CARD_AUTH, 1, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, get_doa, 1},
{PIV_DATA_OBJ_X509_DS, 1, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, get_doa, 2},
{PIV_DATA_OBJ_X509_KM, 1, 0, 0, "X.509 Certificate for Key Management", 0, 0, get_doa, 3},
{PIV_DATA_OBJ_CCC, 1, 0, 0, "Card Capability Container", 0, 0, get_doa, 4},
{PIV_DATA_OBJ_CHUI, 1, 0, 0, "Card Holder Unique Identifier", 0, 0, get_doa, 5},
{PIV_DATA_OBJ_CHF, 1, 1, 0, "Card Holder Fingerprints", 0, 0, get_doa, 6},
{PIV_DATA_OBJ_SEC_OBJ, 1, 0, 0, "Security Object", 0, 0, get_doa, 7},
{PIV_DATA_OBJ_CHFI, 1, 1, 0, "Cardholder Facial Images", 0, 0, get_doa, 8},
{PIV_DATA_OBJ_PI, 1, 1, 0, "Printed Information", 0, 0, get_doa, 9},
{PIV_DATA_OBJ_DISCOVERY, 1, 0, 0, "Discovery Object", 0, 0, get_doa, 10},
{PIV_DATA_OBJ_HISTORY, 1, 0, 0, "Key History Object", 0, 0, get_doa, 11},
{PIV_DATA_OBJ_RETIRED_X509_1, 1, 0, 0, "Retired X.509 Certificate for Key Management 1", 0, 0, get_doa, 12},
{PIV_DATA_OBJ_RETIRED_X509_2, 1, 0, 0, "Retired X.509 Certificate for Key Management 2", 0, 0, get_doa, 13},
{PIV_DATA_OBJ_RETIRED_X509_3, 1, 0, 0, "Retired X.509 Certificate for Key Management 3", 0, 0, get_doa, 14},
{PIV_DATA_OBJ_RETIRED_X509_4, 1, 0, 0, "Retired X.509 Certificate for Key Management 4", 0, 0, get_doa, 15},
{PIV_DATA_OBJ_RETIRED_X509_5, 1, 0, 0, "Retired X.509 Certificate for Key Management 5", 0, 0, get_doa, 16},
{PIV_DATA_OBJ_RETIRED_X509_6, 1, 0, 0, "Retired X.509 Certificate for Key Management 6", 0, 0, get_doa, 17},
{PIV_DATA_OBJ_RETIRED_X509_7, 1, 0, 0, "Retired X.509 Certificate for Key Management 7", 0, 0, get_doa, 18},
{PIV_DATA_OBJ_RETIRED_X509_8, 1, 0, 0, "Retired X.509 Certificate for Key Management 8", 0, 0, get_doa, 19},
{PIV_DATA_OBJ_RETIRED_X509_9, 1, 0, 0, "Retired X.509 Certificate for Key Management 9", 0, 0, get_doa, 20},
{PIV_DATA_OBJ_RETIRED_X509_10, 1, 0, 0, "Retired X.509 Certificate for Key Management 10", 0, 0, get_doa, 21},
{PIV_DATA_OBJ_RETIRED_X509_11, 1, 0, 0, "Retired X.509 Certificate for Key Management 11", 0, 0, get_doa, 22},
{PIV_DATA_OBJ_RETIRED_X509_12, 1, 0, 0, "Retired X.509 Certificate for Key Management 12", 0, 0, get_doa, 23},
{PIV_DATA_OBJ_RETIRED_X509_13, 1, 0, 0, "Retired X.509 Certificate for Key Management 13", 0, 0, get_doa, 24},
{PIV_DATA_OBJ_RETIRED_X509_14, 1, 0, 0, "Retired X.509 Certificate for Key Management 14", 0, 0, get_doa, 25},
{PIV_DATA_OBJ_RETIRED_X509_15, 1, 0, 0, "Retired X.509 Certificate for Key Management 15", 0, 0, get_doa, 26},
{PIV_DATA_OBJ_RETIRED_X509_16, 1, 0, 0, "Retired X.509 Certificate for Key Management 16", 0, 0, get_doa, 27},
{PIV_DATA_OBJ_RETIRED_X509_17, 1, 0, 0, "Retired X.509 Certificate for Key Management 17", 0, 0, get_doa, 28},
{PIV_DATA_OBJ_RETIRED_X509_18, 1, 0, 0, "Retired X.509 Certificate for Key Management 18", 0, 0, get_doa, 29},
{PIV_DATA_OBJ_RETIRED_X509_19, 1, 0, 0, "Retired X.509 Certificate for Key Management 19", 0, 0, get_doa, 30},
{PIV_DATA_OBJ_RETIRED_X509_20, 1, 0, 0, "Retired X.509 Certificate for Key Management 20", 0, 0, get_doa, 31},
{PIV_DATA_OBJ_X509_RETIRED1, 1, 0, 0, "X.509 Certificate for Retired Key 1", 0, 0, get_doa, 4},
{PIV_DATA_OBJ_X509_RETIRED2, 1, 0, 0, "X.509 Certificate for Retired Key 2", 0, 0, get_doa, 5},
{PIV_DATA_OBJ_X509_RETIRED3, 1, 0, 0, "X.509 Certificate for Retired Key 3", 0, 0, get_doa, 6},
{PIV_DATA_OBJ_X509_RETIRED4, 1, 0, 0, "X.509 Certificate for Retired Key 4", 0, 0, get_doa, 7},
{PIV_DATA_OBJ_X509_RETIRED5, 1, 0, 0, "X.509 Certificate for Retired Key 5", 0, 0, get_doa, 8},
{PIV_DATA_OBJ_X509_RETIRED6, 1, 0, 0, "X.509 Certificate for Retired Key 6", 0, 0, get_doa, 9},
{PIV_DATA_OBJ_X509_RETIRED7, 1, 0, 0, "X.509 Certificate for Retired Key 7", 0, 0, get_doa, 10},
{PIV_DATA_OBJ_X509_RETIRED8, 1, 0, 0, "X.509 Certificate for Retired Key 8", 0, 0, get_doa, 11},
{PIV_DATA_OBJ_X509_RETIRED9, 1, 0, 0, "X.509 Certificate for Retired Key 9", 0, 0, get_doa, 12},
{PIV_DATA_OBJ_X509_RETIRED10, 1, 0, 0, "X.509 Certificate for Retired Key 10", 0, 0, get_doa, 13},
{PIV_DATA_OBJ_X509_RETIRED11, 1, 0, 0, "X.509 Certificate for Retired Key 11", 0, 0, get_doa, 14},
{PIV_DATA_OBJ_X509_RETIRED12, 1, 0, 0, "X.509 Certificate for Retired Key 12", 0, 0, get_doa, 15},
{PIV_DATA_OBJ_X509_RETIRED13, 1, 0, 0, "X.509 Certificate for Retired Key 13", 0, 0, get_doa, 16},
{PIV_DATA_OBJ_X509_RETIRED14, 1, 0, 0, "X.509 Certificate for Retired Key 14", 0, 0, get_doa, 17},
{PIV_DATA_OBJ_X509_RETIRED15, 1, 0, 0, "X.509 Certificate for Retired Key 15", 0, 0, get_doa, 18},
{PIV_DATA_OBJ_X509_RETIRED16, 1, 0, 0, "X.509 Certificate for Retired Key 16", 0, 0, get_doa, 19},
{PIV_DATA_OBJ_X509_RETIRED17, 1, 0, 0, "X.509 Certificate for Retired Key 17", 0, 0, get_doa, 20},
{PIV_DATA_OBJ_X509_RETIRED18, 1, 0, 0, "X.509 Certificate for Retired Key 18", 0, 0, get_doa, 21},
{PIV_DATA_OBJ_X509_RETIRED19, 1, 0, 0, "X.509 Certificate for Retired Key 19", 0, 0, get_doa, 22},
{PIV_DATA_OBJ_X509_RETIRED20, 1, 0, 0, "X.509 Certificate for Retired Key 20", 0, 0, get_doa, 23},
{PIV_DATA_OBJ_CCC, 1, 0, 0, "Card Capability Container", 0, 0, get_doa, 24},
{PIV_DATA_OBJ_CHUI, 1, 0, 0, "Card Holder Unique Identifier", 0, 0, get_doa, 25},
{PIV_DATA_OBJ_CHF, 1, 1, 0, "Card Holder Fingerprints", 0, 0, get_doa, 26},
{PIV_DATA_OBJ_SEC_OBJ, 1, 0, 0, "Security Object", 0, 0, get_doa, 27},
{PIV_DATA_OBJ_CHFI, 1, 1, 0, "Cardholder Facial Images", 0, 0, get_doa, 28},
{PIV_DATA_OBJ_PI, 1, 1, 0, "Printed Information", 0, 0, get_doa, 29},
{PIV_DATA_OBJ_DISCOVERY, 1, 0, 0, "Discovery Object", 0, 0, get_doa, 30},
{PIV_DATA_OBJ_HISTORY, 1, 0, 0, "Key History Object", 0, 0, get_doa, 31},
{PIV_DATA_OBJ_IRIS_IMAGE, 1, 1, 0, "Cardholder Iris Images", 0, 0, get_doa, 32},
{PIV_DATA_OBJ_BITGT, 1, 0, 0, "Biometric Information Templates Group Template", 0, 0, get_doa, 33},
{PIV_DATA_OBJ_SM_SIGNER, 1, 0, 0, "Secure Messaging Certificate Signer", 0, 0, get_doa, 34},
@@ -62,63 +62,142 @@ static piv_obj_t piv_objects[] = {
{PIV_CERT_OBJ_X509_CARD_AUTH, 1, 0, 0, "X.509 Certificate for Card Authentication", 0, 0, get_coa, 1},
{PIV_CERT_OBJ_X509_DS, 1, 0, 0, "X.509 Certificate for Digital Signature", 0, 0, get_coa, 2},
{PIV_CERT_OBJ_X509_KM, 1, 0, 0, "X.509 Certificate for Key Management", 0, 0, get_coa, 3},
{PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4},
{PIV_CERT_OBJ_X509_RETIRED1, 1, 0, 0, "X.509 Certificate for Retired Key 1", 0, 0, get_coa, 4},
{PIV_CERT_OBJ_X509_RETIRED2, 1, 0, 0, "X.509 Certificate for Retired Key 2", 0, 0, get_coa, 5},
{PIV_CERT_OBJ_X509_RETIRED3, 1, 0, 0, "X.509 Certificate for Retired Key 3", 0, 0, get_coa, 6},
{PIV_CERT_OBJ_X509_RETIRED4, 1, 0, 0, "X.509 Certificate for Retired Key 4", 0, 0, get_coa, 7},
{PIV_CERT_OBJ_X509_RETIRED5, 1, 0, 0, "X.509 Certificate for Retired Key 5", 0, 0, get_coa, 8},
{PIV_CERT_OBJ_X509_RETIRED6, 1, 0, 0, "X.509 Certificate for Retired Key 6", 0, 0, get_coa, 9},
{PIV_CERT_OBJ_X509_RETIRED7, 1, 0, 0, "X.509 Certificate for Retired Key 7", 0, 0, get_coa, 10},
{PIV_CERT_OBJ_X509_RETIRED8, 1, 0, 0, "X.509 Certificate for Retired Key 8", 0, 0, get_coa, 11},
{PIV_CERT_OBJ_X509_RETIRED9, 1, 0, 0, "X.509 Certificate for Retired Key 9", 0, 0, get_coa, 12},
{PIV_CERT_OBJ_X509_RETIRED10, 1, 0, 0, "X.509 Certificate for Retired Key 10", 0, 0, get_coa, 13},
{PIV_CERT_OBJ_X509_RETIRED11, 1, 0, 0, "X.509 Certificate for Retired Key 11", 0, 0, get_coa, 14},
{PIV_CERT_OBJ_X509_RETIRED12, 1, 0, 0, "X.509 Certificate for Retired Key 12", 0, 0, get_coa, 15},
{PIV_CERT_OBJ_X509_RETIRED13, 1, 0, 0, "X.509 Certificate for Retired Key 13", 0, 0, get_coa, 16},
{PIV_CERT_OBJ_X509_RETIRED14, 1, 0, 0, "X.509 Certificate for Retired Key 14", 0, 0, get_coa, 17},
{PIV_CERT_OBJ_X509_RETIRED15, 1, 0, 0, "X.509 Certificate for Retired Key 15", 0, 0, get_coa, 18},
{PIV_CERT_OBJ_X509_RETIRED16, 1, 0, 0, "X.509 Certificate for Retired Key 16", 0, 0, get_coa, 19},
{PIV_CERT_OBJ_X509_RETIRED17, 1, 0, 0, "X.509 Certificate for Retired Key 17", 0, 0, get_coa, 20},
{PIV_CERT_OBJ_X509_RETIRED18, 1, 0, 0, "X.509 Certificate for Retired Key 18", 0, 0, get_coa, 21},
{PIV_CERT_OBJ_X509_RETIRED19, 1, 0, 0, "X.509 Certificate for Retired Key 19", 0, 0, get_coa, 22},
{PIV_CERT_OBJ_X509_RETIRED20, 1, 0, 0, "X.509 Certificate for Retired Key 20", 0, 0, get_coa, 23},
{PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 24},
{PIV_PVTK_OBJ_PIV_AUTH, 1, 1, 0, "Private key for PIV Authentication", 0, 0, get_proa, 0}, // 9a
{PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Private key for Card Authentication", 0, 0, get_proa, 1}, // 9e
{PIV_PVTK_OBJ_DS, 1, 1, 0, "Private key for Digital Signature", 0, 0, get_proa, 2}, // 9c
{PIV_PVTK_OBJ_KM, 1, 1, 0, "Private key for Key Management", 0, 0, get_proa, 3}, // 9d
{PIV_PVTK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4},
{PIV_PVTK_OBJ_RETIRED1, 1, 1, 0, "Private key for Retired Key 1", 0, 0, get_proa, 4},
{PIV_PVTK_OBJ_RETIRED2, 1, 1, 0, "Private key for Retired Key 2", 0, 0, get_proa, 5},
{PIV_PVTK_OBJ_RETIRED3, 1, 1, 0, "Private key for Retired Key 3", 0, 0, get_proa, 6},
{PIV_PVTK_OBJ_RETIRED4, 1, 1, 0, "Private key for Retired Key 4", 0, 0, get_proa, 7},
{PIV_PVTK_OBJ_RETIRED5, 1, 1, 0, "Private key for Retired Key 5", 0, 0, get_proa, 8},
{PIV_PVTK_OBJ_RETIRED6, 1, 1, 0, "Private key for Retired Key 6", 0, 0, get_proa, 9},
{PIV_PVTK_OBJ_RETIRED7, 1, 1, 0, "Private key for Retired Key 7", 0, 0, get_proa, 10},
{PIV_PVTK_OBJ_RETIRED8, 1, 1, 0, "Private key for Retired Key 8", 0, 0, get_proa, 11},
{PIV_PVTK_OBJ_RETIRED9, 1, 1, 0, "Private key for Retired Key 9", 0, 0, get_proa, 12},
{PIV_PVTK_OBJ_RETIRED10, 1, 1, 0, "Private key forRretired Key 10", 0, 0, get_proa, 13},
{PIV_PVTK_OBJ_RETIRED11, 1, 1, 0, "Private key forRretired Key 11", 0, 0, get_proa, 14},
{PIV_PVTK_OBJ_RETIRED12, 1, 1, 0, "Private key forRretired Key 12", 0, 0, get_proa, 15},
{PIV_PVTK_OBJ_RETIRED13, 1, 1, 0, "Private key forRretired Key 13", 0, 0, get_proa, 16},
{PIV_PVTK_OBJ_RETIRED14, 1, 1, 0, "Private key forRretired Key 14", 0, 0, get_proa, 17},
{PIV_PVTK_OBJ_RETIRED15, 1, 1, 0, "Private key forRretired Key 15", 0, 0, get_proa, 18},
{PIV_PVTK_OBJ_RETIRED16, 1, 1, 0, "Private key forRretired Key 16", 0, 0, get_proa, 19},
{PIV_PVTK_OBJ_RETIRED17, 1, 1, 0, "Private key forRretired Key 17", 0, 0, get_proa, 20},
{PIV_PVTK_OBJ_RETIRED18, 1, 1, 0, "Private key forRretired Key 18", 0, 0, get_proa, 21},
{PIV_PVTK_OBJ_RETIRED19, 1, 1, 0, "Private key forRretired Key 19", 0, 0, get_proa, 22},
{PIV_PVTK_OBJ_RETIRED20, 1, 1, 0, "Private key forRretired Key 20", 0, 0, get_proa, 23},
{PIV_PVTK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 24},
{PIV_PUBK_OBJ_PIV_AUTH, 1, 0, 0, "Public key for PIV Authentication", 0, 0, get_puoa, 0},
{PIV_PUBK_OBJ_CARD_AUTH, 1, 0, 0, "Public key for Card Authentication", 0, 0, get_puoa, 1},
{PIV_PUBK_OBJ_DS, 1, 0, 0, "Public key for Digital Signature", 0, 0, get_puoa, 2},
{PIV_PUBK_OBJ_KM, 1, 0, 0, "Public key for Key Management", 0, 0, get_puoa, 3},
{PIV_PUBK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4}
{PIV_PUBK_OBJ_RETIRED1, 1, 0, 0, "Public key for Retired Key 1", 0, 0, get_puoa, 4},
{PIV_PUBK_OBJ_RETIRED2, 1, 0, 0, "Public key for Retired Key 2", 0, 0, get_puoa, 5},
{PIV_PUBK_OBJ_RETIRED3, 1, 0, 0, "Public key for Retired Key 3", 0, 0, get_puoa, 6},
{PIV_PUBK_OBJ_RETIRED4, 1, 0, 0, "Public key for Retired Key 4", 0, 0, get_puoa, 7},
{PIV_PUBK_OBJ_RETIRED5, 1, 0, 0, "Public key for Retired Key 5", 0, 0, get_puoa, 8},
{PIV_PUBK_OBJ_RETIRED6, 1, 0, 0, "Public key for Retired Key 6", 0, 0, get_puoa, 9},
{PIV_PUBK_OBJ_RETIRED7, 1, 0, 0, "Public key for Retired Key 7", 0, 0, get_puoa, 10},
{PIV_PUBK_OBJ_RETIRED8, 1, 0, 0, "Public key for Retired Key 8", 0, 0, get_puoa, 11},
{PIV_PUBK_OBJ_RETIRED9, 1, 0, 0, "Public key for Retired Key 9", 0, 0, get_puoa, 12},
{PIV_PUBK_OBJ_RETIRED10, 1, 0, 0, "Public key for Retired Key 10", 0, 0, get_puoa, 13},
{PIV_PUBK_OBJ_RETIRED11, 1, 0, 0, "Public key for Retired Key 11", 0, 0, get_puoa, 14},
{PIV_PUBK_OBJ_RETIRED12, 1, 0, 0, "Public key for Retired Key 12", 0, 0, get_puoa, 15},
{PIV_PUBK_OBJ_RETIRED13, 1, 0, 0, "Public key for Retired Key 13", 0, 0, get_puoa, 16},
{PIV_PUBK_OBJ_RETIRED14, 1, 0, 0, "Public key for Retired Key 14", 0, 0, get_puoa, 17},
{PIV_PUBK_OBJ_RETIRED15, 1, 0, 0, "Public key for Retired Key 15", 0, 0, get_puoa, 18},
{PIV_PUBK_OBJ_RETIRED16, 1, 0, 0, "Public key for Retired Key 16", 0, 0, get_puoa, 19},
{PIV_PUBK_OBJ_RETIRED17, 1, 0, 0, "Public key for Retired Key 17", 0, 0, get_puoa, 20},
{PIV_PUBK_OBJ_RETIRED18, 1, 0, 0, "Public key for Retired Key 18", 0, 0, get_puoa, 21},
{PIV_PUBK_OBJ_RETIRED19, 1, 0, 0, "Public key for Retired Key 19", 0, 0, get_puoa, 22},
{PIV_PUBK_OBJ_RETIRED20, 1, 0, 0, "Public key for Retired Key 20", 0, 0, get_puoa, 23},
{PIV_PUBK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 24}
};
static piv_data_obj_t data_objects[] = {
{"2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01"},
{"2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00"},
{"2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00"},
{"2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02"},
{"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00"},
{"2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00"},
{"2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10"},
{"2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00"},
{"2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30"},
{"2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01"},
{"2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50"},
{"2.16.840.1.101.3.7.2.96.96", 3, "\x5F\xC1\x0C", "\x60\x60"},
/* 800-73-3, 21 new objects, 20 history certificates */
{"2.16.840.1.101.3.7.2.16.1", 3, "\x5F\xC1\x0D", "\x10\x01"},
{"2.16.840.1.101.3.7.2.16.2", 3, "\x5F\xC1\x0E", "\x10\x02"},
{"2.16.840.1.101.3.7.2.16.3", 3, "\x5F\xC1\x0F", "\x10\x03"},
{"2.16.840.1.101.3.7.2.16.4", 3, "\x5F\xC1\x10", "\x10\x04"},
{"2.16.840.1.101.3.7.2.16.5", 3, "\x5F\xC1\x11", "\x10\x05"},
{"2.16.840.1.101.3.7.2.16.7", 3, "\x5F\xC1\x13", "\x10\x07"},
{"2.16.840.1.101.3.7.2.16.8", 3, "\x5F\xC1\x14", "\x10\x08"},
{"2.16.840.1.101.3.7.2.16.9", 3, "\x5F\xC1\x15", "\x10\x09"},
{"2.16.840.1.101.3.7.2.16.10", 3, "\x5F\xC1\x16", "\x10\x0A"},
{"2.16.840.1.101.3.7.2.16.11", 3, "\x5F\xC1\x17", "\x10\x0B"},
{"2.16.840.1.101.3.7.2.16.12", 3, "\x5F\xC1\x18", "\x10\x0C"},
{"2.16.840.1.101.3.7.2.16.13", 3, "\x5F\xC1\x19", "\x10\x0D"},
{"2.16.840.1.101.3.7.2.16.14", 3, "\x5F\xC1\x1A", "\x10\x0E"},
{"2.16.840.1.101.3.7.2.16.15", 3, "\x5F\xC1\x1B", "\x10\x0F"},
{"2.16.840.1.101.3.7.2.16.16", 3, "\x5F\xC1\x1C", "\x10\x10"},
{"2.16.840.1.101.3.7.2.16.17", 3, "\x5F\xC1\x1D", "\x10\x11"},
{"2.16.840.1.101.3.7.2.16.18", 3, "\x5F\xC1\x1E", "\x10\x12"},
{"2.16.840.1.101.3.7.2.16.19", 3, "\x5F\xC1\x1F", "\x10\x13"},
{"2.16.840.1.101.3.7.2.16.20", 3, "\x5F\xC1\x20", "\x10\x14"},
{"2.16.840.1.101.3.7.2.16.21", 3, "\x5F\xC1\x21", "\x10\x15"},
{"2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16"},
{"2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17"},
{"2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"},
{"2.16.840.1.101.3.7.2.1.1", 3, "\x5F\xC1\x05", "\x01\x01"}, // PIV Authentication
{"2.16.840.1.101.3.7.2.5.0", 3, "\x5F\xC1\x01", "\x05\x00"}, // Card Authentication
{"2.16.840.1.101.3.7.2.1.0", 3, "\x5F\xC1\x0A", "\x01\x00"}, // Digital Signature
{"2.16.840.1.101.3.7.2.1.2", 3, "\x5F\xC1\x0B", "\x01\x02"}, // Key Management
{"2.16.840.1.101.3.7.2.16.1", 3, "\x5F\xC1\x0D", "\x10\x01"}, // Retired Key 1
{"2.16.840.1.101.3.7.2.16.2", 3, "\x5F\xC1\x0E", "\x10\x02"}, // Retired Key 2
{"2.16.840.1.101.3.7.2.16.3", 3, "\x5F\xC1\x0F", "\x10\x03"}, // Retired Key 3
{"2.16.840.1.101.3.7.2.16.4", 3, "\x5F\xC1\x10", "\x10\x04"}, // Retired Key 4
{"2.16.840.1.101.3.7.2.16.5", 3, "\x5F\xC1\x11", "\x10\x05"}, // Retired Key 5
{"2.16.840.1.101.3.7.2.16.6", 3, "\x5F\xC1\x12", "\x10\x06"}, // Retired Key 6
{"2.16.840.1.101.3.7.2.16.7", 3, "\x5F\xC1\x13", "\x10\x07"}, // Retired Key 7
{"2.16.840.1.101.3.7.2.16.8", 3, "\x5F\xC1\x14", "\x10\x08"}, // Retired Key 8
{"2.16.840.1.101.3.7.2.16.9", 3, "\x5F\xC1\x15", "\x10\x09"}, // Retired Key 9
{"2.16.840.1.101.3.7.2.16.10", 3, "\x5F\xC1\x16", "\x10\x0A"}, // Retired Key 10
{"2.16.840.1.101.3.7.2.16.11", 3, "\x5F\xC1\x17", "\x10\x0B"}, // Retired Key 11
{"2.16.840.1.101.3.7.2.16.12", 3, "\x5F\xC1\x18", "\x10\x0C"}, // Retired Key 12
{"2.16.840.1.101.3.7.2.16.13", 3, "\x5F\xC1\x19", "\x10\x0D"}, // Retired Key 13
{"2.16.840.1.101.3.7.2.16.14", 3, "\x5F\xC1\x1A", "\x10\x0E"}, // Retired Key 14
{"2.16.840.1.101.3.7.2.16.15", 3, "\x5F\xC1\x1B", "\x10\x0F"}, // Retired Key 15
{"2.16.840.1.101.3.7.2.16.16", 3, "\x5F\xC1\x1C", "\x10\x10"}, // Retired Key 16
{"2.16.840.1.101.3.7.2.16.17", 3, "\x5F\xC1\x1D", "\x10\x11"}, // Retired Key 17
{"2.16.840.1.101.3.7.2.16.18", 3, "\x5F\xC1\x1E", "\x10\x12"}, // Retired Key 18
{"2.16.840.1.101.3.7.2.16.19", 3, "\x5F\xC1\x1F", "\x10\x13"}, // Retired Key 19
{"2.16.840.1.101.3.7.2.16.20", 3, "\x5F\xC1\x20", "\x10\x14"}, // Retired Key 20
{"2.16.840.1.101.3.7.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00"}, // CCC
{"2.16.840.1.101.3.7.2.48.0", 3, "\x5F\xC1\x02", "\x30\x00"}, // CHUID
{"2.16.840.1.101.3.7.2.96.16", 3, "\x5F\xC1\x03", "\x60\x10"}, // CHFP
{"2.16.840.1.101.3.7.2.144.0", 3, "\x5F\xC1\x06", "\x90\x00"}, // Security Object
{"2.16.840.1.101.3.7.2.96.48", 3, "\x5F\xC1\x08", "\x60\x30"}, // CHFI
{"2.16.840.1.101.3.7.2.48.1", 3, "\x5F\xC1\x09", "\x30\x01"}, // Printed Information
{"2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50"}, // Discovery Object
{"2.16.840.1.101.3.7.2.96.96", 3, "\x5F\xC1\x0C", "\x60\x60"}, // Key History Object
{"2.16.840.1.101.3.7.2.16.21", 3, "\x5F\xC1\x21", "\x10\x15"}, // CHII
{"2.16.840.1.101.3.7.2.16.22", 2, "\x7F\x61", "\x10\x16"}, // Biometric Information
{"2.16.840.1.101.3.7.2.16.23", 3, "\x5F\xC1\x22", "\x10\x17"}, // Secure Messaging Certificate Signer
{"2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"}, // Pairing Code Reference Data Container
{"", 0, "", ""}
};
static piv_cert_obj_t cert_objects[] = {
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
{NULL},
@@ -131,10 +210,50 @@ static piv_pvtk_obj_t pvtkey_objects[] = {
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 1},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0},
{1, 1, 0, 0, 0}
};
static piv_pubk_obj_t pubkey_objects[] = {
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
{NULL, 1, 1, 0, 0},
@@ -221,8 +340,12 @@ static CK_ULONG get_modulus_bits(EVP_PKEY *key) {
return do_get_rsa_modulus_length(key);
}
static CK_ULONG get_public_exponent(EVP_PKEY *key) {
return do_get_public_exponent(key);
static CK_RV get_public_exponent(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
return do_get_public_exponent(key, data, len);
}
static CK_RV get_modulus(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
return do_get_modulus(key, data, len);
}
static CK_RV get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
@@ -285,7 +408,7 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ?
DBG("OID");
strcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid);
memcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid, sizeof(tmp));
asn1_encode_oid(tmp, tmp, &len);
data = tmp;
break;
@@ -374,15 +497,15 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_ISSUER:
DBG("ISSUER TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_SERIAL_NUMBER:
DBG("SERIAL NUMBER TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_SUBJECT:
DBG("SUBJECT TODO"); // Required
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_ID:
DBG("ID");
@@ -393,11 +516,11 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_START_DATE:
DBG("START DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_END_DATE:
DBG("END DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_MODIFIABLE:
DBG("MODIFIABLE");
@@ -477,7 +600,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_SUBJECT:
DBG("SUBJECT TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_ID:
DBG("ID");
@@ -488,7 +611,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_SENSITIVE:
DBG("SENSITIVE TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_DECRYPT:
DBG("DECRYPT"); // Default empy
@@ -513,7 +636,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_SIGN_RECOVER:
DBG("SIGN RECOVER TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_DERIVE:
DBG("DERIVE"); // Default false
@@ -524,11 +647,11 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_START_DATE:
DBG("START DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_END_DATE:
DBG("END DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_MODULUS:
DBG("MODULUS");
@@ -608,10 +731,9 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
if (ul_tmp != CKK_RSA)
return CKR_ATTRIBUTE_VALUE_INVALID;
ul_tmp = get_public_exponent(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk
if (ul_tmp == 0)
if (get_public_exponent(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED;
data = (CK_BYTE_PTR) &ul_tmp;
data = b_tmp;
break;
/* case CKA_PRIVATE_EXPONENT: */
@@ -628,7 +750,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
/* case CKA_EXTRACTABLE: */
case CKA_LOCAL:
DBG("LOCAL TODO"); // Required
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
/* case CKA_NEVER_EXTRACTABLE: */
/*case CKA_ALWAYS_SENSITIVE:*/
@@ -719,7 +841,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_SUBJECT:
DBG("SUBJECT TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_ID:
DBG("ID");
@@ -758,11 +880,11 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_START_DATE:
DBG("START DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_END_DATE:
DBG("END DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_EC_POINT:
DBG("EC_POINT");
@@ -809,7 +931,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
if (ul_tmp != CKK_RSA)
return CKR_ATTRIBUTE_VALUE_INVALID;
if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
if (get_modulus(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED;
data = b_tmp;
break;
@@ -842,15 +964,14 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
if (ul_tmp != CKK_RSA)
return CKR_ATTRIBUTE_VALUE_INVALID;
ul_tmp = get_public_exponent(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk
if (ul_tmp == 0)
if (get_public_exponent(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED;
data = (CK_BYTE_PTR) &ul_tmp;
data = b_tmp;
break;
case CKA_LOCAL:
DBG("LOCAL TODO"); // Required
return CKR_FUNCTION_FAILED;
return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_MODIFIABLE:
DBG("MODIFIABLE");
@@ -883,7 +1004,6 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
}
CK_ULONG piv_2_ykpiv(piv_obj_id_t id) {
// TODO: add retired keys
switch(id) {
case PIV_CERT_OBJ_X509_PIV_AUTH:
return YKPIV_OBJ_AUTHENTICATION;
@@ -897,6 +1017,66 @@ CK_ULONG piv_2_ykpiv(piv_obj_id_t id) {
case PIV_CERT_OBJ_X509_KM:
return YKPIV_OBJ_KEY_MANAGEMENT;
case PIV_CERT_OBJ_X509_RETIRED1:
return YKPIV_OBJ_RETIRED1;
case PIV_CERT_OBJ_X509_RETIRED2:
return YKPIV_OBJ_RETIRED2;
case PIV_CERT_OBJ_X509_RETIRED3:
return YKPIV_OBJ_RETIRED3;
case PIV_CERT_OBJ_X509_RETIRED4:
return YKPIV_OBJ_RETIRED4;
case PIV_CERT_OBJ_X509_RETIRED5:
return YKPIV_OBJ_RETIRED5;
case PIV_CERT_OBJ_X509_RETIRED6:
return YKPIV_OBJ_RETIRED6;
case PIV_CERT_OBJ_X509_RETIRED7:
return YKPIV_OBJ_RETIRED7;
case PIV_CERT_OBJ_X509_RETIRED8:
return YKPIV_OBJ_RETIRED8;
case PIV_CERT_OBJ_X509_RETIRED9:
return YKPIV_OBJ_RETIRED9;
case PIV_CERT_OBJ_X509_RETIRED10:
return YKPIV_OBJ_RETIRED10;
case PIV_CERT_OBJ_X509_RETIRED11:
return YKPIV_OBJ_RETIRED11;
case PIV_CERT_OBJ_X509_RETIRED12:
return YKPIV_OBJ_RETIRED12;
case PIV_CERT_OBJ_X509_RETIRED13:
return YKPIV_OBJ_RETIRED13;
case PIV_CERT_OBJ_X509_RETIRED14:
return YKPIV_OBJ_RETIRED14;
case PIV_CERT_OBJ_X509_RETIRED15:
return YKPIV_OBJ_RETIRED15;
case PIV_CERT_OBJ_X509_RETIRED16:
return YKPIV_OBJ_RETIRED16;
case PIV_CERT_OBJ_X509_RETIRED17:
return YKPIV_OBJ_RETIRED17;
case PIV_CERT_OBJ_X509_RETIRED18:
return YKPIV_OBJ_RETIRED18;
case PIV_CERT_OBJ_X509_RETIRED19:
return YKPIV_OBJ_RETIRED19;
case PIV_CERT_OBJ_X509_RETIRED20:
return YKPIV_OBJ_RETIRED20;
case PIV_PVTK_OBJ_PIV_AUTH:
return YKPIV_KEY_AUTHENTICATION;
@@ -909,6 +1089,66 @@ CK_ULONG piv_2_ykpiv(piv_obj_id_t id) {
case PIV_PVTK_OBJ_KM:
return YKPIV_KEY_KEYMGM;
case PIV_PVTK_OBJ_RETIRED1:
return YKPIV_KEY_RETIRED1;
case PIV_PVTK_OBJ_RETIRED2:
return YKPIV_KEY_RETIRED2;
case PIV_PVTK_OBJ_RETIRED3:
return YKPIV_KEY_RETIRED3;
case PIV_PVTK_OBJ_RETIRED4:
return YKPIV_KEY_RETIRED4;
case PIV_PVTK_OBJ_RETIRED5:
return YKPIV_KEY_RETIRED5;
case PIV_PVTK_OBJ_RETIRED6:
return YKPIV_KEY_RETIRED6;
case PIV_PVTK_OBJ_RETIRED7:
return YKPIV_KEY_RETIRED7;
case PIV_PVTK_OBJ_RETIRED8:
return YKPIV_KEY_RETIRED8;
case PIV_PVTK_OBJ_RETIRED9:
return YKPIV_KEY_RETIRED9;
case PIV_PVTK_OBJ_RETIRED10:
return YKPIV_KEY_RETIRED10;
case PIV_PVTK_OBJ_RETIRED11:
return YKPIV_KEY_RETIRED11;
case PIV_PVTK_OBJ_RETIRED12:
return YKPIV_KEY_RETIRED12;
case PIV_PVTK_OBJ_RETIRED13:
return YKPIV_KEY_RETIRED13;
case PIV_PVTK_OBJ_RETIRED14:
return YKPIV_KEY_RETIRED14;
case PIV_PVTK_OBJ_RETIRED15:
return YKPIV_KEY_RETIRED15;
case PIV_PVTK_OBJ_RETIRED16:
return YKPIV_KEY_RETIRED16;
case PIV_PVTK_OBJ_RETIRED17:
return YKPIV_KEY_RETIRED17;
case PIV_PVTK_OBJ_RETIRED18:
return YKPIV_KEY_RETIRED18;
case PIV_PVTK_OBJ_RETIRED19:
return YKPIV_KEY_RETIRED19;
case PIV_PVTK_OBJ_RETIRED20:
return YKPIV_KEY_RETIRED20;
default:
return 0ul;
}
@@ -1063,6 +1303,8 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n,
case CKA_TOKEN:
case CKA_LABEL:
case CKA_SUBJECT:
case CKA_ISSUER:
case CKA_CERTIFICATE_TYPE:
// Ignore other attributes
break;
@@ -1150,18 +1392,23 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
has_params == CK_FALSE)
return CKR_TEMPLATE_INCOMPLETE;
if (*value_len != 32)
if (*value_len == 32 || *value_len == 31) {
if (ec_params_len != 10 || memcmp(ec_params, PRIME256V1, ec_params_len) != 0)
return CKR_ATTRIBUTE_VALUE_INVALID;
}
else /*if () TODO: P384*/
return CKR_ATTRIBUTE_VALUE_INVALID;
if (*value_len == 32 && (ec_params_len != 10 || memcmp(ec_params, PRIME256V1, ec_params_len)) != 0)
return CKR_TEMPLATE_INCONSISTENT;
return CKR_OK;
}
CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp,
CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) {
CK_BYTE_PTR *p, CK_ULONG_PTR p_len,
CK_BYTE_PTR *q, CK_ULONG_PTR q_len,
CK_BYTE_PTR *dp, CK_ULONG_PTR dp_len,
CK_BYTE_PTR *dq, CK_ULONG_PTR dq_len,
CK_BYTE_PTR *qinv, CK_ULONG_PTR qinv_len,
CK_ULONG_PTR vendor_defined) {
CK_ULONG i;
CK_BBOOL has_id = CK_FALSE;
@@ -1171,11 +1418,6 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BBOOL has_dp = CK_FALSE;
CK_BBOOL has_dq = CK_FALSE;
CK_BBOOL has_qinv = CK_FALSE;
CK_ULONG p_len = 0;
CK_ULONG q_len = 0;
CK_ULONG dp_len = 0;
CK_ULONG dq_len = 0;
CK_ULONG qinv_len = 0;
*vendor_defined = 0;
@@ -1210,35 +1452,35 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
case CKA_PRIME_1:
has_p = CK_TRUE;
*p = (CK_BYTE_PTR)templ[i].pValue;
p_len = templ[i].ulValueLen;
*p_len = templ[i].ulValueLen;
break;
case CKA_PRIME_2:
has_q = CK_TRUE;
*q = (CK_BYTE_PTR)templ[i].pValue;
q_len = templ[i].ulValueLen;
*q_len = templ[i].ulValueLen;
break;
case CKA_EXPONENT_1:
has_dp = CK_TRUE;
*dp = (CK_BYTE_PTR)templ[i].pValue;
dp_len = templ[i].ulValueLen;
*dp_len = templ[i].ulValueLen;
break;
case CKA_EXPONENT_2:
has_dq = CK_TRUE;
*dq = (CK_BYTE_PTR)templ[i].pValue;
dq_len = templ[i].ulValueLen;
*dq_len = templ[i].ulValueLen;
break;
case CKA_COEFFICIENT:
has_qinv = CK_TRUE;
*qinv = (CK_BYTE_PTR)templ[i].pValue;
qinv_len = templ[i].ulValueLen;
*qinv_len = templ[i].ulValueLen;
break;
@@ -1269,13 +1511,12 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
has_qinv == CK_FALSE)
return CKR_TEMPLATE_INCOMPLETE;
if (p_len != 64 && p_len != 128)
if (*p_len != 64 && *p_len != 128)
return CKR_ATTRIBUTE_VALUE_INVALID;
*value_len = p_len;
if (q_len != p_len || dp_len != p_len ||
dq_len != p_len || qinv_len != p_len)
if (*q_len != *p_len || *dp_len > *p_len ||
*dq_len > *p_len || *qinv_len > *p_len)
return CKR_ATTRIBUTE_VALUE_INVALID;
return CKR_OK;
+6 -2
View File
@@ -18,8 +18,12 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR *value, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined);
CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id,
CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp,
CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined);
CK_BYTE_PTR *p, CK_ULONG_PTR p_len,
CK_BYTE_PTR *q, CK_ULONG_PTR q_len,
CK_BYTE_PTR *dp, CK_ULONG_PTR dp_len,
CK_BYTE_PTR *dq, CK_ULONG_PTR dq_len,
CK_BYTE_PTR *qinv, CK_ULONG_PTR qinv_len,
CK_ULONG_PTR vendor_defined);
CK_RV check_delete_cert(CK_OBJECT_HANDLE hObject, CK_BYTE_PTR id);
#endif
+30 -3
View File
@@ -317,16 +317,43 @@ CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) {
}
CK_ULONG do_get_public_exponent(EVP_PKEY *key) {
CK_RV do_get_modulus(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
RSA *rsa;
rsa = EVP_PKEY_get1_RSA(key);
if (rsa == NULL)
return CKR_FUNCTION_FAILED;
if ((CK_ULONG)BN_num_bytes(rsa->n) > *len) {
RSA_free(rsa);
rsa = NULL;
return CKR_BUFFER_TOO_SMALL;
}
*len = (CK_ULONG)BN_bn2bin(rsa->n, data);
RSA_free(rsa);
rsa = NULL;
return CKR_OK;
}
CK_RV do_get_public_exponent(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
CK_ULONG e = 0;
RSA *rsa;
rsa = EVP_PKEY_get1_RSA(key);
if (rsa == NULL)
return 0;
return CKR_FUNCTION_FAILED;
BN_bn2bin(rsa->e, (unsigned char *)&e);
if ((CK_ULONG)BN_num_bytes(rsa->e) > *len) {
RSA_free(rsa);
rsa = NULL;
return CKR_BUFFER_TOO_SMALL;
}
*len = (CK_ULONG)BN_bn2bin(rsa->e, data);
RSA_free(rsa);
rsa = NULL;
+2 -1
View File
@@ -20,8 +20,9 @@ CK_RV do_delete_cert(X509 **cert);
CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key);
CK_KEY_TYPE do_get_key_type(EVP_PKEY *key);
CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key);
CK_ULONG do_get_public_exponent(EVP_PKEY *key);
CK_RV do_get_public_exponent(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len);
CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len);
CK_RV do_get_modulus(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len);
CK_RV do_encode_rsa_public_key(CK_BYTE_PTR data, CK_ULONG len, RSA **key);
CK_RV do_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len);
CK_RV do_delete_pubk(EVP_PKEY **key);
+8
View File
@@ -239,6 +239,9 @@ extern "C" {
#define __PASTE(x,y) x##y
#if defined _WIN32 || _WIN64
#pragma pack(push, cryptoki, 1)
#endif
/* packing defines */
//#include "pkcs11p.h" // TODO: msc specific?
@@ -309,6 +312,11 @@ struct CK_FUNCTION_LIST {
/* unpack */
//#include "pkcs11u.h" // TODO: msc specific?
#if defined _WIN32 || _WIN64
#pragma pack(pop, cryptoki)
#endif
#ifdef __cplusplus
}
#endif
+25 -20
View File
@@ -108,7 +108,9 @@ typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
/* pack */
//#include "pkcs11p.h" // TODO: msc specific?
#if defined _WIN32 || _WIN64
#pragma pack(push, cryptoki, 1)
#endif
typedef struct CK_VERSION {
CK_BYTE major; /* integer portion of version number */
@@ -1163,33 +1165,36 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
* PKCS #11 interface. Most of these are place holders for other mechanism
* and will change in the future.
*/
#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001UL
#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002UL
#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003UL
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004UL
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005UL
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006UL
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007UL
#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008UL
#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009UL
#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aUL
#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bUL
#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371UL
#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372UL
#define CKM_TLS_PRF_GENERAL 0x80000373UL
#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001UL
#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002UL
#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003UL
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004UL
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005UL
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006UL
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007UL
#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008UL
#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009UL
#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aUL
#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bUL
#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371UL
#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372UL
#define CKM_TLS_PRF_GENERAL 0x80000373UL
/* define used to pass in the database key for DSA private keys */
#define CKA_NETSCAPE_DB 0xD5A0DB00UL
#define CKA_NETSCAPE_TRUST 0x80000001UL
/* undo packing */
//#include "pkcs11u.h" // TODO: msc specific?
#define CKA_NETSCAPE_DB 0xD5A0DB00UL
#define CKA_NETSCAPE_TRUST 0x80000001UL
// YUBICO specific attributes
#define CKA_TOUCH_PIN_DEFAULT 0x00000000U
#define CKA_TOUCH_ALWAYS 0x00000001U
#define CKA_PIN_ONCE 0x00000002U
#define CKA_PIN_ALWAYS 0x00000004U
#define CKA_PIN_NEVER 0x00000008U
#define CKA_TOUCH_NEVER 0x00000016U
/* undo packing */
#if defined _WIN32 || _WIN64
#pragma pack(pop, cryptoki)
#endif
#endif
+594 -31
View File
@@ -3,54 +3,617 @@
#include <string.h>
#define MANUFACTURER_ID "Yubico (www.yubico.com)"
#define YKCS11_DESCRIPTION "PKCS#11 PIV Library (SP-800-73)"
#define CRYPTOKI_VERSION_MAJ 2
#define CRYPTOKI_VERSION_MIN 40
#include <openssl/rsa.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
void dump_hex(const unsigned char *buf, unsigned int len, FILE *output, int space) {
unsigned int i;
for (i = 0; i < len; i++) {
fprintf(output, "%02x%s", buf[i], space == 1 ? " " : "");
}
fprintf(output, "\n");
}
static void lib_info() {
CK_FUNCTION_LIST_PTR funcs;
CK_INFO info;
CK_FUNCTION_LIST_PTR funcs;
#define asrt(c, e, m) _asrt(__LINE__, c, e, m);
if (C_GetFunctionList(&funcs) != CKR_OK) {
static void _asrt(int line, CK_ULONG check, CK_ULONG expected, CK_CHAR_PTR msg) {
if (check == expected)
return;
fprintf(stderr, "<%s>:%d check failed with value %lu (0x%lx), expected %lu (0x%lx)\n",
msg, line, check, check, expected, expected);
exit(EXIT_FAILURE);
}
static void get_functions(CK_FUNCTION_LIST_PTR_PTR funcs) {
if (C_GetFunctionList(funcs) != CKR_OK) {
fprintf(stderr, "Get function list failed\n");
exit(EXIT_FAILURE);
}
if (funcs->C_GetInfo(&info) != CKR_OK) {
fprintf(stderr, "GetInfo failed\n");
exit(EXIT_FAILURE);
}
}
if (strcmp(info.manufacturerID, MANUFACTURER_ID) != 0) {
fprintf(stderr, "unexpected manufacturer ID %s\n", info.manufacturerID);
exit(EXIT_FAILURE);
}
static void test_lib_info() {
if (info.cryptokiVersion.major != CRYPTOKI_VERSION_MAJ ||
info.cryptokiVersion.minor != CRYPTOKI_VERSION_MIN ) {
fprintf(stderr, "unexpected Cryptoki version %d.%d\n", info.cryptokiVersion.major, info.cryptokiVersion.minor);
exit(EXIT_FAILURE);
}
const CK_CHAR_PTR MANUFACTURER_ID = "Yubico (www.yubico.com)";
const CK_CHAR_PTR YKCS11_DESCRIPTION = "PKCS#11 PIV Library (SP-800-73)";
const CK_ULONG CRYPTOKI_VERSION_MAJ = 2;
const CK_ULONG CRYPTOKI_VERSION_MIN = 40;
if (info.libraryVersion.major != YKCS11_VERSION_MAJOR ||
info.libraryVersion.minor != ((YKCS11_VERSION_MINOR * 100) + YKCS11_VERSION_PATCH )) {
fprintf(stderr, "unexpected YKCS11 version %d.%d\n", info.libraryVersion.major, info.libraryVersion.minor);
exit(EXIT_FAILURE);
}
if (strcmp(info.libraryDescription, YKCS11_DESCRIPTION) != 0) {
fprintf(stderr, "unexpected description %s\n", info.libraryDescription);
exit(EXIT_FAILURE);
}
CK_INFO info;
asrt(funcs->C_GetInfo(&info), CKR_OK, "GET_INFO");
asrt(strcmp(info.manufacturerID, MANUFACTURER_ID), 0, "MANUFACTURER");
asrt(info.cryptokiVersion.major, CRYPTOKI_VERSION_MAJ, "CK_MAJ");
asrt(info.cryptokiVersion.minor, CRYPTOKI_VERSION_MIN, "CK_MIN");
asrt(info.libraryVersion.major, YKCS11_VERSION_MAJOR, "LIB_MAJ");
asrt(info.libraryVersion.minor, ((YKCS11_VERSION_MINOR * 10) + YKCS11_VERSION_PATCH ), "LIB_MIN");
asrt(strcmp(info.libraryDescription, YKCS11_DESCRIPTION), 0, "LIB_DESC");
}
#ifdef HW_TESTS
static void test_initalize() {
asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");
}
static void test_token_info() {
const CK_CHAR_PTR TOKEN_LABEL = "YubiKey PIV";
const CK_CHAR_PTR TOKEN_MODEL = "YubiKey "; // Skip last 3 characters (version dependent)
const CK_CHAR_PTR TOKEN_SERIAL = "1234";
const CK_FLAGS TOKEN_FLAGS = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED;
const CK_VERSION HW = {0, 0};
const CK_CHAR_PTR TOKEN_TIME = " ";
CK_TOKEN_INFO info;
asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
asrt(funcs->C_GetTokenInfo(0, &info), CKR_OK, "GetTokeninfo");
asrt(strncmp(info.label, TOKEN_LABEL, strlen(TOKEN_LABEL)), 0, "TOKEN_LABEL");
// Skip manufacturer id (not used)
asrt(strncmp(info.model, TOKEN_MODEL, strlen(TOKEN_MODEL)), 0, "TOKEN_MODEL");
asrt(strncmp(info.serialNumber, TOKEN_SERIAL, strlen(TOKEN_SERIAL)), 0, "SERIAL_NUMBER");
asrt(info.flags, TOKEN_FLAGS, "TOKEN_FLAGS");
asrt(info.ulMaxSessionCount, CK_UNAVAILABLE_INFORMATION, "MAX_SESSION_COUNT");
asrt(info.ulSessionCount, CK_UNAVAILABLE_INFORMATION, "SESSION_COUNT");
asrt(info.ulMaxRwSessionCount, CK_UNAVAILABLE_INFORMATION, "MAX_RW_SESSION_COUNT");
asrt(info.ulRwSessionCount, CK_UNAVAILABLE_INFORMATION, "RW_SESSION_COUNT");
asrt(info.ulMaxPinLen, 8, "MAX_PIN_LEN");
asrt(info.ulMinPinLen, 6, "MIN_PIN_LEN");
asrt(info.ulTotalPublicMemory, CK_UNAVAILABLE_INFORMATION, "TOTAL_PUB_MEM");
asrt(info.ulFreePublicMemory, CK_UNAVAILABLE_INFORMATION, "FREE_PUB_MEM");
asrt(info.ulTotalPrivateMemory, CK_UNAVAILABLE_INFORMATION, "TOTAL_PVT_MEM");
asrt(info.ulFreePrivateMemory, CK_UNAVAILABLE_INFORMATION, "FREE_PVT_MEM");
asrt(info.hardwareVersion.major, HW.major, "HW_MAJ");
asrt(info.hardwareVersion.minor, HW.minor, "HW_MIN");
if (info.firmwareVersion.major != 4 && info.firmwareVersion.major != 0)
asrt(info.firmwareVersion.major, 4, "FW_MAJ");
asrt(strcmp(info.utcTime, TOKEN_TIME), 0, "TOKEN_TIME");
asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");
}
static void test_mechanism_list_and_info() {
CK_MECHANISM_TYPE_PTR mechs;
CK_ULONG n_mechs;
CK_MECHANISM_INFO info;
CK_ULONG i;
static const CK_MECHANISM_TYPE token_mechanisms[] = {
CKM_RSA_PKCS_KEY_PAIR_GEN,
CKM_RSA_PKCS,
CKM_RSA_PKCS_PSS,
CKM_RSA_X_509,
CKM_SHA1_RSA_PKCS,
CKM_SHA256_RSA_PKCS,
CKM_SHA384_RSA_PKCS,
CKM_SHA512_RSA_PKCS,
CKM_SHA1_RSA_PKCS_PSS,
CKM_SHA256_RSA_PKCS_PSS,
CKM_SHA384_RSA_PKCS_PSS,
CKM_SHA512_RSA_PKCS_PSS,
CKM_EC_KEY_PAIR_GEN,
CKM_ECDSA,
CKM_ECDSA_SHA1,
CKM_ECDSA_SHA256,
CKM_SHA_1,
CKM_SHA256,
CKM_SHA384,
CKM_SHA512
};
static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH token_mechanisms
{1024, 2048, CKF_HW | CKF_GENERATE_KEY_PAIR},
{1024, 2048, CKF_HW | CKF_DECRYPT | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_DECRYPT | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{1024, 2048, CKF_HW | CKF_SIGN},
{256, 384, CKF_HW | CKF_GENERATE_KEY_PAIR},
{256, 384, CKF_HW | CKF_SIGN},
{256, 384, CKF_HW | CKF_SIGN},
{256, 384, CKF_HW | CKF_SIGN},
{0, 0, CKF_DIGEST},
{0, 0, CKF_DIGEST},
{0, 0, CKF_DIGEST},
{0, 0, CKF_DIGEST}
};
asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
asrt(funcs->C_GetMechanismList(0, NULL, &n_mechs), CKR_OK, "GetMechanismList");
mechs = malloc(n_mechs * sizeof(CK_MECHANISM_TYPE));
asrt(funcs->C_GetMechanismList(0, mechs, &n_mechs), CKR_OK, "GetMechanismList");
asrt(memcmp(token_mechanisms, mechs, sizeof(token_mechanisms)), 0, "CHECK MECHS");
for (i = 0; i < n_mechs; i++) {
asrt(funcs->C_GetMechanismInfo(0, mechs[i], &info), CKR_OK, "GET MECH INFO");
asrt(memcmp(token_mechanism_infos + i, &info, sizeof(CK_MECHANISM_INFO)), 0, "CHECK MECH INFO");
}
asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");
}
static void test_session() {
CK_SESSION_HANDLE session;
CK_SESSION_INFO info;
asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession2");
asrt(funcs->C_GetSessionInfo(session, &info), CKR_OK, "GetSessionInfo");
asrt(info.state, CKS_RW_PUBLIC_SESSION, "CHECK STATE");
asrt(info.flags, CKF_SERIAL_SESSION | CKF_RW_SESSION, "CHECK FLAGS");
asrt(info.ulDeviceError, 0, "CHECK DEVICE ERROR");
asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession3");
asrt(funcs->C_CloseAllSessions(0), CKR_OK, "CloseAllSessions");
asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");
}
static void test_login() {
CK_SESSION_HANDLE session;
CK_SESSION_INFO info;
asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
asrt(funcs->C_Logout(session), CKR_OK, "Logout USER");
asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO");
asrt(funcs->C_Logout(session), CKR_OK, "Logout SO");
asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");
}
// Import a newly generated P256 pvt key and a certificate
// to every slot and use the key to sign some data
static void test_import_and_sign_all_10() {
EVP_PKEY *evp;
EC_KEY *eck;
const EC_POINT *ecp;
const BIGNUM *bn;
char pvt[32];
X509 *cert;
ASN1_TIME *tm;
CK_BYTE i, j;
CK_BYTE some_data[32];
CK_ULONG class_k = CKO_PRIVATE_KEY;
CK_ULONG class_c = CKO_CERTIFICATE;
CK_ULONG kt = CKK_ECDSA;
CK_BYTE id = 0;
CK_BYTE params[] = {0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
CK_BYTE sig[64];
CK_ULONG recv_len;
CK_BYTE value_c[3100];
CK_ULONG cert_len;
CK_BYTE der_encoded[80];
CK_BYTE_PTR der_ptr;
CK_BYTE_PTR r_ptr;
CK_BYTE_PTR s_ptr;
CK_ULONG r_len;
CK_ULONG s_len;
unsigned char *p;
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_CLASS, &class_k, sizeof(class_k)},
{CKA_KEY_TYPE, &kt, sizeof(kt)},
{CKA_ID, &id, sizeof(id)},
{CKA_EC_PARAMS, &params, sizeof(params)},
{CKA_VALUE, pvt, sizeof(pvt)}
};
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_CLASS, &class_c, sizeof(class_c)},
{CKA_ID, &id, sizeof(id)},
{CKA_VALUE, value_c, sizeof(value_c)}
};
CK_OBJECT_HANDLE obj[24];
CK_SESSION_HANDLE session;
CK_MECHANISM mech = {CKM_ECDSA, NULL};
evp = EVP_PKEY_new();
if (evp == NULL)
exit(EXIT_FAILURE);
eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (eck == NULL)
exit(EXIT_FAILURE);
asrt(EC_KEY_generate_key(eck), 1, "GENERATE ECK");
bn = EC_KEY_get0_private_key(eck);
asrt(BN_bn2bin(bn, pvt), 32, "EXTRACT PVT");
if (EVP_PKEY_set1_EC_KEY(evp, eck) == 0)
exit(EXIT_FAILURE);
cert = X509_new();
if (cert == NULL)
exit(EXIT_FAILURE);
if (X509_set_pubkey(cert, evp) == 0)
exit(EXIT_FAILURE);
tm = ASN1_TIME_new();
if (tm == NULL)
exit(EXIT_FAILURE);
ASN1_TIME_set_string(tm, "000001010000Z");
X509_set_notBefore(cert, tm);
X509_set_notAfter(cert, tm);
cert->sig_alg->algorithm = OBJ_nid2obj(8);
cert->cert_info->signature->algorithm = OBJ_nid2obj(8);
ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
ASN1_BIT_STRING_set(cert->signature, "\x00", 1);
p = value_c;
if ((cert_len = (CK_ULONG) i2d_X509(cert, &p)) == 0 || cert_len > sizeof(value_c))
exit(EXIT_FAILURE);
publicKeyTemplate[2].ulValueLen = cert_len;
asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO");
for (i = 0; i < 24; i++) {
id = i;
asrt(funcs->C_CreateObject(session, publicKeyTemplate, 3, obj + i), CKR_OK, "IMPORT CERT");
asrt(funcs->C_CreateObject(session, privateKeyTemplate, 5, obj + i), CKR_OK, "IMPORT KEY");
}
asrt(funcs->C_Logout(session), CKR_OK, "Logout SO");
for (i = 0; i < 24; i++) {
for (j = 0; j < 10; j++) {
if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1)
exit(EXIT_FAILURE);
asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
asrt(funcs->C_SignInit(session, &mech, obj[i]), CKR_OK, "SignInit");
recv_len = sizeof(sig);
asrt(funcs->C_Sign(session, some_data, sizeof(some_data), sig, &recv_len), CKR_OK, "Sign");
r_len = 32;
s_len = 32;
der_ptr = der_encoded;
*der_ptr++ = 0x30;
*der_ptr++ = 0xff; // placeholder, fix below
r_ptr = sig;
*der_ptr++ = 0x02;
*der_ptr++ = r_len;
if (*r_ptr >= 0x80) {
*(der_ptr - 1) = *(der_ptr - 1) + 1;
*der_ptr++ = 0x00;
}
else if (*r_ptr == 0x00 && *(r_ptr + 1) < 0x80) {
r_len--;
*(der_ptr - 1) = *(der_ptr - 1) - 1;
r_ptr++;
}
memcpy(der_ptr, r_ptr, r_len);
der_ptr+= r_len;
s_ptr = sig + 32;
*der_ptr++ = 0x02;
*der_ptr++ = s_len;
if (*s_ptr >= 0x80) {
*(der_ptr - 1) = *(der_ptr - 1) + 1;
*der_ptr++ = 0x00;
}
else if (*s_ptr == 0x00 && *(s_ptr + 1) < 0x80) {
s_len--;
*(der_ptr - 1) = *(der_ptr - 1) - 1;
s_ptr++;
}
memcpy(der_ptr, s_ptr, s_len);
der_ptr+= s_len;
der_encoded[1] = der_ptr - der_encoded - 2;
dump_hex(der_encoded, der_encoded[1] + 2, stderr, 1);
asrt(ECDSA_verify(0, some_data, sizeof(some_data), der_encoded, der_encoded[1] + 2, eck), 1, "ECDSA VERIFICATION");
}
}
asrt(funcs->C_Logout(session), CKR_OK, "Logout USER");
asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");
}
// Import a newly generated RSA1024 pvt key and a certificate
// to every slot and use the key to sign some data
static void test_import_and_sign_all_10_RSA() {
EVP_PKEY *evp;
RSA *rsak;
X509 *cert;
ASN1_TIME *tm;
CK_BYTE i, j;
CK_BYTE some_data[32];
CK_BYTE e[] = {0x01, 0x00, 0x01};
CK_BYTE p[64];
CK_BYTE q[64];
CK_BYTE dp[64];
CK_BYTE dq[64];
CK_BYTE qinv[64];
BIGNUM *e_bn;
CK_ULONG class_k = CKO_PRIVATE_KEY;
CK_ULONG class_c = CKO_CERTIFICATE;
CK_ULONG kt = CKK_RSA;
CK_BYTE id = 0;
CK_BYTE sig[64];
CK_ULONG recv_len;
CK_BYTE value_c[3100];
CK_ULONG cert_len;
CK_BYTE der_encoded[80];
CK_BYTE_PTR der_ptr;
CK_BYTE_PTR r_ptr;
CK_BYTE_PTR s_ptr;
CK_ULONG r_len;
CK_ULONG s_len;
unsigned char *px;
CK_ATTRIBUTE privateKeyTemplate[] = {
{CKA_CLASS, &class_k, sizeof(class_k)},
{CKA_KEY_TYPE, &kt, sizeof(kt)},
{CKA_ID, &id, sizeof(id)},
{CKA_PUBLIC_EXPONENT, e, sizeof(e)},
{CKA_PRIME_1, p, sizeof(p)},
{CKA_PRIME_2, q, sizeof(q)},
{CKA_EXPONENT_1, dp, sizeof(dp)},
{CKA_EXPONENT_2, dq, sizeof(dq)},
{CKA_COEFFICIENT, qinv, sizeof(qinv)}
};
CK_ATTRIBUTE publicKeyTemplate[] = {
{CKA_CLASS, &class_c, sizeof(class_c)},
{CKA_ID, &id, sizeof(id)},
{CKA_VALUE, value_c, sizeof(value_c)}
};
CK_OBJECT_HANDLE obj[24];
CK_SESSION_HANDLE session;
CK_MECHANISM mech = {CKM_RSA_PKCS, NULL};
evp = EVP_PKEY_new();
if (evp == NULL)
exit(EXIT_FAILURE);
rsak = RSA_new();
if (rsak == NULL)
exit(EXIT_FAILURE);
e_bn = BN_bin2bn(e, 3, NULL);
if (e_bn == NULL)
exit(EXIT_FAILURE);
asrt(RSA_generate_key_ex(rsak, 1024, e_bn, NULL), 1, "GENERATE RSAK");
asrt(BN_bn2bin(rsak->p, p), 64, "GET P");
asrt(BN_bn2bin(rsak->q, q), 64, "GET Q");
asrt(BN_bn2bin(rsak->dmp1, dp), 64, "GET DP");
asrt(BN_bn2bin(rsak->dmq1, dp), 64, "GET DQ");
asrt(BN_bn2bin(rsak->iqmp, qinv), 64, "GET QINV");
if (EVP_PKEY_set1_RSA(evp, rsak) == 0)
exit(EXIT_FAILURE);
cert = X509_new();
if (cert == NULL)
exit(EXIT_FAILURE);
if (X509_set_pubkey(cert, evp) == 0)
exit(EXIT_FAILURE);
tm = ASN1_TIME_new();
if (tm == NULL)
exit(EXIT_FAILURE);
ASN1_TIME_set_string(tm, "000001010000Z");
X509_set_notBefore(cert, tm);
X509_set_notAfter(cert, tm);
cert->sig_alg->algorithm = OBJ_nid2obj(8);
cert->cert_info->signature->algorithm = OBJ_nid2obj(8);
ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
ASN1_BIT_STRING_set(cert->signature, "\x00", 1);
px = value_c;
if ((cert_len = (CK_ULONG) i2d_X509(cert, &px)) == 0 || cert_len > sizeof(value_c))
exit(EXIT_FAILURE);
publicKeyTemplate[2].ulValueLen = cert_len;
asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO");
for (i = 0; i < 24; i++) {
id = i;
asrt(funcs->C_CreateObject(session, publicKeyTemplate, 3, obj + i), CKR_OK, "IMPORT CERT");
asrt(funcs->C_CreateObject(session, privateKeyTemplate, 9, obj + i), CKR_OK, "IMPORT KEY");
}
asrt(funcs->C_Logout(session), CKR_OK, "Logout SO");
for (i = 0; i < 24; i++) {
for (j = 0; j < 10; j++) {
if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1)
exit(EXIT_FAILURE);
asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
asrt(funcs->C_SignInit(session, &mech, obj[i]), CKR_OK, "SignInit");
recv_len = sizeof(sig);
asrt(funcs->C_Sign(session, some_data, sizeof(some_data), sig, &recv_len), CKR_OK, "Sign");
/* r_len = 32; */
/* s_len = 32; */
/* der_ptr = der_encoded; */
/* *der_ptr++ = 0x30; */
/* *der_ptr++ = 0xff; // placeholder, fix below */
/* r_ptr = sig; */
/* *der_ptr++ = 0x02; */
/* *der_ptr++ = r_len; */
/* if (*r_ptr >= 0x80) { */
/* *(der_ptr - 1) = *(der_ptr - 1) + 1; */
/* *der_ptr++ = 0x00; */
/* } */
/* else if (*r_ptr == 0x00 && *(r_ptr + 1) < 0x80) { */
/* r_len--; */
/* *(der_ptr - 1) = *(der_ptr - 1) - 1; */
/* r_ptr++; */
/* } */
/* memcpy(der_ptr, r_ptr, r_len); */
/* der_ptr+= r_len; */
/* s_ptr = sig + 32; */
/* *der_ptr++ = 0x02; */
/* *der_ptr++ = s_len; */
/* if (*s_ptr >= 0x80) { */
/* *(der_ptr - 1) = *(der_ptr - 1) + 1; */
/* *der_ptr++ = 0x00; */
/* } */
/* else if (*s_ptr == 0x00 && *(s_ptr + 1) < 0x80) { */
/* s_len--; */
/* *(der_ptr - 1) = *(der_ptr - 1) - 1; */
/* s_ptr++; */
/* } */
/* memcpy(der_ptr, s_ptr, s_len); */
/* der_ptr+= s_len; */
/* der_encoded[1] = der_ptr - der_encoded - 2; */
/* dump_hex(der_encoded, der_encoded[1] + 2, stderr, 1); */
/* asrt(ECDSA_verify(0, some_data, sizeof(some_data), der_encoded, der_encoded[1] + 2, eck), 1, "ECDSA VERIFICATION"); */
}
}
asrt(funcs->C_Logout(session), CKR_OK, "Logout USER");
asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");
}
#endif
int main(void) {
lib_info();
get_functions(&funcs);
test_lib_info();
#ifdef HW_TESTS
test_initalize();
test_token_info();
test_mechanism_list_and_info();
test_session();
test_login();
test_import_and_sign_all_10();
test_import_and_sign_all_10_RSA();
#else
fprintf(stderr, "HARDWARE TESTS DISABLED!, skipping...\n");
#endif
return EXIT_SUCCESS;
+79 -75
View File
@@ -12,9 +12,24 @@ static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CH
int tries = 0; // TODO: this is effectively disregarded, should we add a better value in ykpiv_verify?
unsigned char key[24];
size_t key_len = sizeof(key);
unsigned char *term_pin;
ykpiv_rc res;
if (user == CKU_USER) {
if (ykpiv_verify(state, (char *)pin, &tries) != YKPIV_OK) {
// add null termination for the pin
term_pin = malloc(pin_len + 1);
if (term_pin == NULL) {
return CKR_HOST_MEMORY;
}
memcpy(term_pin, pin, pin_len);
term_pin[pin_len] = 0;
res = ykpiv_verify(state, (char *)term_pin, &tries);
OPENSSL_cleanse(term_pin, pin_len);
free(term_pin);
if (res != YKPIV_OK) {
DBG("Failed to login");
return CKR_PIN_INCORRECT;
}
@@ -58,7 +73,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa,
switch(key_len) {
case 2048:
if (rsa == CK_TRUE)
in_data[4] = YKPIV_ALGO_RSA2048;
*in_ptr++ = YKPIV_ALGO_RSA2048;
else
return CKR_FUNCTION_FAILED;
@@ -143,7 +158,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa,
static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_BYTE_PTR in) {
unsigned char certdata[2100];
unsigned char certdata[3072];
unsigned char *certptr;
CK_ULONG cert_len;
@@ -153,7 +168,7 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B
if ((rv = do_check_cert(in, &cert_len)) != CKR_OK)
return rv;
if (cert_len > 2100)
if (cert_len > 3072)
return CKR_FUNCTION_FAILED;
certptr = certdata;
@@ -176,85 +191,73 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B
return CKR_OK;
}
CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYTE_PTR p, CK_BYTE_PTR q,
CK_BYTE_PTR dp, CK_BYTE_PTR dq, CK_BYTE_PTR qinv,
CK_BYTE_PTR ec_data, CK_ULONG elem_len, CK_ULONG vendor_defined) {
CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id,
CK_BYTE_PTR p, CK_ULONG p_len,
CK_BYTE_PTR q, CK_ULONG q_len,
CK_BYTE_PTR dp, CK_ULONG dp_len,
CK_BYTE_PTR dq, CK_ULONG dq_len,
CK_BYTE_PTR qinv, CK_ULONG qinv_len,
CK_BYTE_PTR ec_data, CK_ULONG ec_data_len,
CK_ULONG vendor_defined) {
unsigned char key_data[1024];
unsigned char *in_ptr = key_data;
unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, 0, key_id};
unsigned char data[0xff];
unsigned long recv_len = sizeof(data);
int sw;
CK_BYTE pin_policy;
CK_BYTE touch_policy;
CK_BYTE algo;
ykpiv_rc rc;
if (elem_len == 128) // TODO: add a flag to check algo type ?
templ[2] = YKPIV_ALGO_RSA2048;
else if (elem_len == 64)
templ[2] = YKPIV_ALGO_RSA1024;
else if(elem_len == 32)
templ[2] = YKPIV_ALGO_ECCP256;
if (templ[2] == YKPIV_ALGO_RSA1024 ||templ[2] == YKPIV_ALGO_RSA2048) {
*in_ptr++ = 0x01;
in_ptr += set_length(in_ptr, elem_len);
memcpy(in_ptr, p, (size_t)(elem_len));
in_ptr += elem_len;
*in_ptr++ = 0x02;
in_ptr += set_length(in_ptr, elem_len);
memcpy(in_ptr, q, (size_t)(elem_len));
in_ptr += elem_len;
*in_ptr++ = 0x03;
in_ptr += set_length(in_ptr, elem_len);
memcpy(in_ptr, dp, (size_t)(elem_len));
in_ptr += elem_len;
*in_ptr++ = 0x04;
in_ptr += set_length(in_ptr, elem_len);
memcpy(in_ptr, dq, (size_t)(elem_len));
in_ptr += elem_len;
*in_ptr++ = 0x05;
in_ptr += set_length(in_ptr, elem_len);
memcpy(in_ptr, qinv, (size_t)(elem_len));
in_ptr += elem_len;
if (p == NULL) {
if (ec_data_len == 32 || ec_data_len == 31)
algo = YKPIV_ALGO_ECCP256;
else
algo = YKPIV_ALGO_ECCP384;
}
else if (templ[2] == YKPIV_ALGO_ECCP256) {
*in_ptr++ = 0x06;
in_ptr += set_length(in_ptr, elem_len);
memcpy(in_ptr, ec_data, (size_t)(elem_len));
in_ptr += elem_len;
else if (ec_data == NULL) {
if (p_len == 64)
algo = YKPIV_ALGO_RSA1024;
else
algo = YKPIV_ALGO_RSA2048;
}
// PIN policy and touch
if (vendor_defined != 0) {
if (vendor_defined & CKA_PIN_ONCE) {
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_PINPOLICY_ONCE;
}
else if (vendor_defined & CKA_PIN_ALWAYS) {
*in_ptr++ = YKPIV_PINPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_PINPOLICY_ALWAYS;
}
if (vendor_defined & CKA_TOUCH_ALWAYS) {
*in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
*in_ptr++ = 0x01;
*in_ptr++ = YKPIV_TOUCHPOLICY_ALWAYS;
}
}
if (ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK)
else
return CKR_FUNCTION_FAILED;
if (sw != 0x9000)
return CKR_DEVICE_ERROR;
pin_policy = YKPIV_PINPOLICY_DEFAULT;
touch_policy = YKPIV_TOUCHPOLICY_DEFAULT;
if (vendor_defined != 0) {
if (vendor_defined & CKA_PIN_ONCE) {
pin_policy = YKPIV_PINPOLICY_ONCE;
}
else if (vendor_defined & CKA_PIN_ALWAYS) {
pin_policy = YKPIV_PINPOLICY_ALWAYS;
}
else if (vendor_defined & CKA_PIN_NEVER) {
pin_policy = YKPIV_PINPOLICY_NEVER;
}
else
return CKR_ATTRIBUTE_VALUE_INVALID;
return CKR_OK;
if (vendor_defined & CKA_TOUCH_ALWAYS) {
touch_policy = YKPIV_TOUCHPOLICY_ALWAYS;
}
else if (vendor_defined & CKA_TOUCH_NEVER) {
touch_policy = YKPIV_TOUCHPOLICY_NEVER;
}
else
return CKR_ATTRIBUTE_VALUE_INVALID;
}
rc = ykpiv_import_private_key(state, key_id, algo,
p, p_len,
q, q_len,
dp, dp_len,
dq, dq_len,
qinv, qinv_len,
ec_data, ec_data_len,
pin_policy, touch_policy);
if (rc != YKPIV_OK)
return CKR_FUNCTION_FAILED;
return CKR_OK;
}
CK_RV COMMON_token_delete_cert(ykpiv_state *state, CK_ULONG cert_id) {
@@ -287,6 +290,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
v.token_import_cert = COMMON_token_import_cert;
v.token_import_private_key = COMMON_token_import_private_key;
v.token_delete_cert = COMMON_token_delete_cert;
v.token_change_pin = YUBICO_token_change_pin;
break;
case UNKNOWN:
+11 -3
View File
@@ -10,7 +10,7 @@ typedef CK_RV (*get_t_label_f)(CK_UTF8CHAR_PTR, CK_ULONG);
typedef CK_RV (*get_t_manufacturer_f)(CK_UTF8CHAR_PTR, CK_ULONG);
typedef CK_RV (*get_t_model_f)(ykpiv_state *, CK_UTF8CHAR_PTR, CK_ULONG);
typedef CK_RV (*get_t_flags_f)(CK_FLAGS_PTR);
typedef CK_RV (*get_t_version_f)(CK_UTF8CHAR_PTR, CK_ULONG, CK_VERSION_PTR);
typedef CK_RV (*get_t_version_f)(ykpiv_state *, CK_VERSION_PTR);
typedef CK_RV (*get_t_serial_f)(CK_CHAR_PTR, CK_ULONG);
typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR);
typedef CK_RV (*get_t_mechanism_list_f)(CK_MECHANISM_TYPE_PTR, CK_ULONG);
@@ -18,13 +18,20 @@ typedef CK_RV (*get_t_mechanism_info_f)(CK_MECHANISM_TYPE, CK_MECHANISM_INFO_PTR
typedef CK_RV (*get_t_objects_num_f)(ykpiv_state *, CK_ULONG_PTR, CK_ULONG_PTR);
typedef CK_RV (*get_t_object_list_f)(ykpiv_state *, piv_obj_id_t *, CK_ULONG);
typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG_PTR);
typedef CK_RV (*t_change_pin_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG, CK_UTF8CHAR_PTR, CK_ULONG);
// Common token functions below
typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG);
typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG, CK_ULONG);
typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR);
typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR,
CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG);
typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE,
CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG,
CK_ULONG);
typedef CK_RV (*t_delete_cert_f)(ykpiv_state *, CK_ULONG);
// TODO: replace all the common calls with functions defined in .c that use libykpiv
@@ -47,6 +54,7 @@ typedef struct {
t_import_cert_f token_import_cert;
t_import_private_key_f token_import_private_key;
t_delete_cert_f token_delete_cert;
t_change_pin_f token_change_pin;
} token_vendor_t;
token_vendor_t get_token_vendor(vendor_id_t vid);
+26 -21
View File
@@ -29,16 +29,16 @@ CK_RV parse_readers(ykpiv_state *state, const CK_BYTE_PTR readers, const CK_ULON
for (i = 0; i < len; i++)
if (readers[i] == '\0' && i != len - 1) {
slots[*n_slots].vid = get_vendor_id(p);
slots[*n_slots].vid = get_vendor_id((char *)p);
if (slots[*n_slots].vid == UNKNOWN) { // TODO: distinguish between tokenless and unsupported?
// Unknown slot, just save what info we have
memset(&slots[*n_slots].info, 0, sizeof(CK_SLOT_INFO));
memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription));
if (strlen(p) <= sizeof(slots[*n_slots].info.slotDescription))
strncpy(slots[*n_slots].info.slotDescription, p, strlen(p));
if (strlen((char *)p) <= sizeof(slots[*n_slots].info.slotDescription))
memcpy(slots[*n_slots].info.slotDescription, p, strlen((char *)p));
else
strncpy(slots[*n_slots].info.slotDescription, p, sizeof(slots[*n_slots].info.slotDescription));
memcpy(slots[*n_slots].info.slotDescription, p, sizeof(slots[*n_slots].info.slotDescription));
}
else {
// Supported slot
@@ -49,7 +49,7 @@ CK_RV parse_readers(ykpiv_state *state, const CK_BYTE_PTR readers, const CK_ULON
memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription));
s = slots[*n_slots].info.slotDescription;
l = sizeof(slots[*n_slots].info.slotDescription);
strncpy((char *)s, (char*)p, l);
memcpy((char *)s, (char*)p, l);
memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID));
s = slots[*n_slots].info.manufacturerID;
@@ -76,7 +76,7 @@ CK_RV parse_readers(ykpiv_state *state, const CK_BYTE_PTR readers, const CK_ULON
}
}
(*n_slots)++;
p += i + 1;
p = readers + i + 1;
}
return CKR_OK;
@@ -92,7 +92,7 @@ failure:
CK_RV create_token(ykpiv_state *state, CK_BYTE_PTR p, ykcs11_slot_t *slot) {
token_vendor_t token;
token_vendor_t token;
CK_TOKEN_INFO_PTR t_info;
slot->token = malloc(sizeof(ykcs11_token_t)); // TODO: free
@@ -114,17 +114,23 @@ CK_RV create_token(ykpiv_state *state, CK_BYTE_PTR p, ykcs11_slot_t *slot) {
if (ykpiv_connect(state, (char *)p) != YKPIV_OK)
return CKR_FUNCTION_FAILED;
memset(t_info->model, ' ', sizeof(t_info->model));
if(token.get_token_model(state, t_info->model, sizeof(t_info->model)) != CKR_OK)
if(token.get_token_model(state, t_info->model, sizeof(t_info->model)) != CKR_OK) {
ykpiv_disconnect(state);
return CKR_FUNCTION_FAILED;
ykpiv_disconnect(state);
}
memset(t_info->serialNumber, ' ', sizeof(t_info->serialNumber));
if(token.get_token_serial(t_info->serialNumber, sizeof(t_info->serialNumber)) != CKR_OK)
if(token.get_token_serial(t_info->serialNumber, sizeof(t_info->serialNumber)) != CKR_OK) {
ykpiv_disconnect(state);
return CKR_FUNCTION_FAILED;
}
if (token.get_token_flags(&t_info->flags) != CKR_OK)
if (token.get_token_flags(&t_info->flags) != CKR_OK) {
ykpiv_disconnect(state);
return CKR_FUNCTION_FAILED;
}
t_info->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION;
@@ -146,20 +152,19 @@ CK_RV create_token(ykpiv_state *state, CK_BYTE_PTR p, ykcs11_slot_t *slot) {
t_info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
//ykpiv_get_version(piv_state, buf, sizeof(buf));
//if (token_vendor.get_token_version(buf, strlen(buf), &ver) != CKR_OK) // TODO: fix this
// return CKR_FUNCTION_FAILED;
//t_info->hardwareVersion = ver; // version number of hardware // TODO: fix
//t_info->firmwareVersion = ver; // version number of firmware // TODO: fix
// Ignore hardware version, report firmware version
if (token.get_token_version(state, &t_info->firmwareVersion) != CKR_OK) {
ykpiv_disconnect(state);
return CKR_FUNCTION_FAILED;
}
memset(t_info->utcTime, ' ', sizeof(t_info->utcTime)); // No clock present, clear
// TODO: also get token objects here? (and destroy on failure)
slot->token->objects = NULL;
slot->token->n_objects = 0;
ykpiv_disconnect(state);
return CKR_OK;
}
@@ -170,8 +175,8 @@ void destroy_token(ykcs11_slot_t *slot) {
CK_BBOOL is_valid_key_id(CK_BYTE id) {
// Valid ids are 0, 1, 2, 3
if (id > 3)
// Valid ids are [0, 23] aka [0x00, 0x17]
if (id > 23)
return CK_FALSE;
return CK_TRUE;
+78 -22
View File
@@ -51,7 +51,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
)
{
CK_BYTE readers[2048];
CK_ULONG len = sizeof(readers);
size_t len = sizeof(readers);
DIN;
@@ -114,7 +114,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)(
CK_INFO_PTR pInfo
)
{
CK_VERSION ver = {YKCS11_VERSION_MAJOR, (YKCS11_VERSION_MINOR * 100) + YKCS11_VERSION_PATCH};
CK_VERSION ver = {YKCS11_VERSION_MAJOR, (YKCS11_VERSION_MINOR * 10) + YKCS11_VERSION_PATCH};
DIN;
@@ -421,7 +421,36 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)(
)
{
DIN;
DBG("TODO!!!");
CK_RV rv;
token_vendor_t token;
if (piv_state == NULL) {
DBG("libykpiv is not initialized or already finalized");
return CKR_CRYPTOKI_NOT_INITIALIZED;
}
if (session.handle == CK_INVALID_HANDLE) {
DBG("User called SetPIN on closed session");
return CKR_SESSION_CLOSED;
}
if (hSession != YKCS11_SESSION_ID) {
DBG("Unknown session %lu", hSession);
return CKR_SESSION_HANDLE_INVALID;
}
CK_USER_TYPE user_type = CKU_USER;
if (session.info.state == CKS_RW_SO_FUNCTIONS) {
user_type = CKU_SO;
}
token = get_token_vendor(session.slot->token->vid);
rv = token.token_change_pin(piv_state, user_type, pOldPin, ulOldLen, pNewPin, ulNewLen);
if (rv != CKR_OK) {
DBG("Pin change failed %lx", rv);
return rv;
}
DOUT;
return CKR_OK;
}
@@ -438,7 +467,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
CK_RV rv;
piv_obj_id_t *cert_ids;
CK_ULONG i;
CK_BYTE cert_data[2100]; // Max cert value for ykpiv
CK_BYTE cert_data[3072]; // Max cert value for ykpiv
CK_ULONG cert_len = sizeof(cert_data);
DIN; // TODO: pApplication and Notify
@@ -479,7 +508,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
}
if ((flags & CKF_SERIAL_SESSION) == 0) {
DBG("Open session called without CKF_SERIAL_SESSION set"); // Reuired by spes
DBG("Open session called without CKF_SERIAL_SESSION set"); // Required by specs
return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
}
@@ -507,6 +536,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
session.info.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default RW session
}
session.info.slotID = slotID;
session.info.flags = flags;
session.info.ulDeviceError = 0;
@@ -731,8 +761,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
return CKR_SESSION_HANDLE_INVALID;
}
if ((session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these?
DBG("Tried to log-in to a read-only session");
if (userType == CKU_SO && (session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these?
DBG("Tried to log-in SO user to a read-only session");
return CKR_SESSION_READ_ONLY_EXISTS;
}
@@ -858,6 +888,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
CK_BYTE_PTR dp;
CK_BYTE_PTR dq;
CK_BYTE_PTR qinv;
CK_ULONG p_len;
CK_ULONG q_len;
CK_ULONG dp_len;
CK_ULONG dq_len;
CK_ULONG qinv_len;
CK_BYTE_PTR ec_data;
CK_ULONG ec_data_len;
CK_ULONG vendor_defined;
token_vendor_t token;
CK_BBOOL is_new;
@@ -972,6 +1009,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
DBG("Unable to store certificate data");
return CKR_FUNCTION_FAILED;
}
*phObject = cert_id;
break;
@@ -980,11 +1018,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
// Try to parse the key as EC
is_rsa = CK_FALSE;
rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &vendor_defined);
rv = check_create_ec_key(pTemplate, ulCount, &id, &ec_data, &ec_data_len, &vendor_defined);
if (rv != CKR_OK) {
// Try to parse the key as RSA
is_rsa = CK_TRUE;
rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len, &vendor_defined);
rv = check_create_rsa_key(pTemplate, ulCount, &id,
&p, &p_len,
&q, &q_len,
&dp, &dp_len,
&dq, &dq_len,
&qinv, &qinv_len,
&vendor_defined);
if (rv != CKR_OK) {
DBG("Private key template not valid");
return rv;
@@ -997,9 +1041,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
if (is_rsa == CK_TRUE) {
DBG("Key is RSA");
rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv,
NULL,
value_len, vendor_defined);
rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object),
p, p_len,
q, q_len,
dp, dp_len,
dq, dq_len,
qinv, qinv_len,
NULL, 0,
vendor_defined);
if (rv != CKR_OK) {
DBG("Unable to import RSA private key");
return rv;
@@ -1007,14 +1056,22 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
}
else {
DBG("Key is ECDSA");
rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL,
value,
value_len, vendor_defined);
rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object),
NULL, 0,
NULL, 0,
NULL, 0,
NULL, 0,
NULL, 0,
ec_data, ec_data_len,
vendor_defined);
if (rv != CKR_OK) {
DBG("Unable to import ECDSA private key");
return rv;
}
}
*phObject = PIV_PVTK_OBJ_PIV_AUTH + id;
break;
default:
@@ -1627,8 +1684,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
return CKR_OPERATION_ACTIVE;
}
if (pMechanism == NULL_PTR ||
hKey == NULL_PTR)
if (pMechanism == NULL_PTR)
return CKR_ARGUMENTS_BAD;
DBG("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey);
@@ -1785,7 +1841,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
DBG("Sending %lu bytes to sign", ulDataLen);
#if YKCS11_DBG == 1
dump_hex(pData, ulDataLen, stderr, CK_TRUE);
dump_data(pData, ulDataLen, stderr, CK_TRUE, format_arg_hex);
#endif
if (is_hashed_mechanism(op_info.mechanism.mechanism) == CK_TRUE) {
@@ -1827,7 +1883,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
DBG("Using key %lx", op_info.op.sign.key_id);
DBG("After padding and transformation there are %lu bytes", op_info.buf_len);
#if YKCS11_DBG == 1
dump_hex(op_info.buf, op_info.buf_len, stderr, CK_TRUE);
dump_data(op_info.buf, op_info.buf_len, stderr, CK_TRUE, format_arg_hex);
#endif
*pulSignatureLen = sizeof(op_info.buf);
@@ -1848,7 +1904,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
DBG("Got %lu bytes back", *pulSignatureLen);
#if YKCS11_DBG == 1
dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE);
dump_data(pSignature, *pulSignatureLen, stderr, CK_TRUE, format_arg_hex);
#endif
if (!is_RSA_mechanism(op_info.mechanism.mechanism)) {
@@ -1858,7 +1914,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
DBG("After removing DER encoding %lu", *pulSignatureLen);
#if YKCS11_DBG == 1
dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE);
dump_data(pSignature, *pulSignatureLen, stderr, CK_TRUE, format_arg_hex);
#endif
}
@@ -2090,7 +2146,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(
CK_ULONG pvtk_id;
CK_ULONG pubk_id;
piv_obj_id_t *obj_ptr;
CK_BYTE cert_data[2100];
CK_BYTE cert_data[3072];
CK_ULONG cert_len;
DIN;
+100 -61
View File
@@ -66,43 +66,44 @@ static const CK_MECHANISM_INFO token_mechanism_infos[] = { // KEEP ALIGNED WITH
static const piv_obj_id_t token_objects[] = { // TODO: is there a way to get this from the token?
PIV_DATA_OBJ_X509_PIV_AUTH, // PIV authentication
PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication
PIV_DATA_OBJ_X509_DS, // Certificate for digital signature
PIV_DATA_OBJ_X509_KM, // Certificate for key management
PIV_DATA_OBJ_X509_CARD_AUTH, // card authentication
PIV_DATA_OBJ_X509_DS, // digital signature
PIV_DATA_OBJ_X509_KM, // key management
PIV_DATA_OBJ_X509_RETIRED1, // Retired key 1
PIV_DATA_OBJ_X509_RETIRED2, // Retired key 2
PIV_DATA_OBJ_X509_RETIRED3, // Retired key 3
PIV_DATA_OBJ_X509_RETIRED4, // Retired key 4
PIV_DATA_OBJ_X509_RETIRED5, // Retired key 5
PIV_DATA_OBJ_X509_RETIRED6, // Retired key 6
PIV_DATA_OBJ_X509_RETIRED7, // Retired key 7
PIV_DATA_OBJ_X509_RETIRED8, // Retired key 8
PIV_DATA_OBJ_X509_RETIRED9, // Retired key 9
PIV_DATA_OBJ_X509_RETIRED10, // Retired key 10
PIV_DATA_OBJ_X509_RETIRED11, // Retired key 11
PIV_DATA_OBJ_X509_RETIRED12, // Retired key 12
PIV_DATA_OBJ_X509_RETIRED13, // Retired key 13
PIV_DATA_OBJ_X509_RETIRED14, // Retired key 14
PIV_DATA_OBJ_X509_RETIRED15, // Retired key 15
PIV_DATA_OBJ_X509_RETIRED16, // Retired key 16
PIV_DATA_OBJ_X509_RETIRED17, // Retired key 17
PIV_DATA_OBJ_X509_RETIRED18, // Retired key 18
PIV_DATA_OBJ_X509_RETIRED19, // Retired key 19
PIV_DATA_OBJ_X509_RETIRED20, // Retired key 20
PIV_DATA_OBJ_CCC, // Card capability container
PIV_DATA_OBJ_CHUI, // Cardholder unique id
PIV_DATA_OBJ_CHF, // Cardholder fingerprints
PIV_DATA_OBJ_SEC_OBJ, // Security object
PIV_DATA_OBJ_CHFI, // Cardholder facial images
//PIV_DATA_OBJ_PI, // Cardholder printed information
//PIV_DATA_OBJ_DISCOVERY, // Discovery object
//PIV_DATA_OBJ_HISTORY, // History object
/* PIV_DATA_OBJ_RETIRED_X509_1, // Retired certificate for KM 1
PIV_DATA_OBJ_RETIRED_X509_2, // Retired certificate for KM 2
PIV_DATA_OBJ_RETIRED_X509_3, // Retired certificate for KM 3
PIV_DATA_OBJ_RETIRED_X509_4, // Retired certificate for KM 4
PIV_DATA_OBJ_RETIRED_X509_5, // Retired certificate for KM 5
PIV_DATA_OBJ_RETIRED_X509_6, // Retired certificate for KM 6
PIV_DATA_OBJ_RETIRED_X509_7, // Retired certificate for KM 7
PIV_DATA_OBJ_RETIRED_X509_8, // Retired certificate for KM 8
PIV_DATA_OBJ_RETIRED_X509_9, // Retired certificate for KM 9
PIV_DATA_OBJ_RETIRED_X509_10, // Retired certificate for KM 10
PIV_DATA_OBJ_RETIRED_X509_11, // Retired certificate for KM 11
PIV_DATA_OBJ_RETIRED_X509_12, // Retired certificate for KM 12
PIV_DATA_OBJ_RETIRED_X509_13, // Retired certificate for KM 13
PIV_DATA_OBJ_RETIRED_X509_14, // Retired certificate for KM 14
PIV_DATA_OBJ_RETIRED_X509_15, // Retired certificate for KM 15
PIV_DATA_OBJ_RETIRED_X509_16, // Retired certificate for KM 16
PIV_DATA_OBJ_RETIRED_X509_17, // Retired certificate for KM 17
PIV_DATA_OBJ_RETIRED_X509_18, // Retired certificate for KM 18
PIV_DATA_OBJ_RETIRED_X509_19, // Retired certificate for KM 19
PIV_DATA_OBJ_RETIRED_X509_20, // Retired certificate for KM 20*/
//PIV_DATA_OBJ_IRIS_IMAGE, // Cardholder iris images
//PIV_DATA_OBJ_BITGT, // Biometric information templates group template
//PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer
//PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data
//PIV_DATA_OBJ_PI, // Cardholder printed information
//PIV_DATA_OBJ_DISCOVERY, // Discovery object
//PIV_DATA_OBJ_HISTORY, // History object
//PIV_DATA_OBJ_IRIS_IMAGE, // Cardholder iris images
//PIV_DATA_OBJ_BITGT, // Biometric information templates group template
//PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer
//PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data
};
static const CK_ULONG token_objects_num = sizeof(token_objects) / sizeof(piv_obj_id_t);
static const CK_ULONG neo_token_objects_num = sizeof(token_objects) / sizeof(piv_obj_id_t) - 20;
static const CK_ULONG yk4_token_objects_num = sizeof(token_objects) / sizeof(piv_obj_id_t);
CK_RV YUBICO_get_token_label(CK_UTF8CHAR_PTR str, CK_ULONG len) {
@@ -152,32 +153,18 @@ CK_RV YUBICO_get_token_flags(CK_FLAGS_PTR flags) {
}
CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG len, CK_VERSION_PTR version) {
CK_RV YUBICO_get_token_version(ykpiv_state *state, CK_VERSION_PTR version) {
CK_VERSION v = {0, 0};
unsigned int i = 0;
char buf[16];
while (i < len && v_str[i] != '.') {
v.major *= 10;
v.major += v_str[i++] - '0';
}
if (version == NULL)
return CKR_ARGUMENTS_BAD;
i++;
if (ykpiv_get_version(state, buf, sizeof(buf)) != YKPIV_OK)
return CKR_FUNCTION_FAILED;
while (i < len && v_str[i] != '.') {
v.minor *= 10;
v.minor += v_str[i++] - '0';
}
i++;
while (i < len && v_str[i] != '.') {
v.minor *= 10;
v.minor += v_str[i++] - '0';
}
version->major = v.major;
version->minor = v.minor;
version->major = (buf[0] - '0');
version->minor = (buf[2] - '0') * 100 + (buf[4] - '0');
return CKR_OK;
}
@@ -225,13 +212,16 @@ CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_P
static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
piv_obj_id_t *obj, CK_ULONG_PTR len, CK_ULONG_PTR num_certs) {
CK_BYTE buf[2048];
CK_ULONG buf_len;
CK_BYTE buf[2048];
CK_ULONG buf_len;
CK_BYTE major;
CK_ULONG i;
piv_obj_id_t certs[4]; // TODO: this can be > 4 if there are retired keys
piv_obj_id_t pvtkeys[4];
piv_obj_id_t pubkeys[4];
CK_ULONG n_cert = 0;
piv_obj_id_t certs[24];
piv_obj_id_t pvtkeys[24];
piv_obj_id_t pubkeys[24];
CK_ULONG n_cert = 0;
CK_ULONG token_objects_num = neo_token_objects_num;
if (state == NULL || len == NULL_PTR)
return CKR_ARGUMENTS_BAD;
@@ -239,6 +229,11 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
if (num_only == CK_FALSE && obj == NULL)
return CKR_ARGUMENTS_BAD;
if (ykpiv_get_version(state, (char *) buf, sizeof(buf)) != YKPIV_OK)
return CKR_FUNCTION_FAILED;
major = buf[0] - '0';
buf_len = sizeof(buf);
if (ykpiv_fetch_object(state, YKPIV_OBJ_AUTHENTICATION, buf, &buf_len) == YKPIV_OK) {
certs[n_cert] = PIV_CERT_OBJ_X509_PIV_AUTH;
@@ -275,6 +270,20 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
DBG("Found KMK cert (9d)");
}
if (major >= 4) {
for (i = 0; i < 20; i++) {
buf_len = sizeof(buf);
if (ykpiv_fetch_object(state, YKPIV_OBJ_RETIRED1 + i, buf, &buf_len) == YKPIV_OK) {
certs[n_cert] = PIV_CERT_OBJ_X509_RETIRED1 + i;
pvtkeys[n_cert] = PIV_PVTK_OBJ_RETIRED1 + i;
pubkeys[n_cert] = PIV_PUBK_OBJ_RETIRED1 + i;
n_cert++;
DBG("Found RETIRED cert (%lx)", 0x82 + i);
}
}
token_objects_num = yk4_token_objects_num;
}
DBG("The total number of objects for this token is %lu", (n_cert * 3) + token_objects_num);
if (num_only == CK_TRUE) {
@@ -289,8 +298,16 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
if (*len < (n_cert * 3) + token_objects_num)
return CKR_BUFFER_TOO_SMALL;
// Copy mandatory data objects
memcpy(obj, token_objects, token_objects_num * sizeof(piv_obj_id_t));
// Copy data objects
if (major >= 4) {
// YK4: just copy all the objects
memcpy(obj, token_objects, token_objects_num * sizeof(piv_obj_id_t));
}
else {
// NEO: remove retired keys
memcpy(obj, token_objects, 4 * sizeof(piv_obj_id_t));
memcpy(obj + 4, token_objects + 24, (neo_token_objects_num - 4) * sizeof(piv_obj_id_t));
}
// Copy certificates
if (n_cert > 0) {
@@ -317,3 +334,25 @@ CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_
return CKR_OK;
}
CK_RV YUBICO_token_change_pin(ykpiv_state *state, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen) {
int tries;
ykpiv_rc res;
if (user_type != CKU_USER) {
DBG("TODO implement other users pin change");
return CKR_FUNCTION_FAILED;
}
res = ykpiv_change_pin(state, pOldPin, ulOldLen, pNewPin, ulNewLen, &tries);
switch (res) {
case YKPIV_OK:
return CKR_OK;
case YKPIV_SIZE_ERROR:
return CKR_PIN_LEN_RANGE;
case YKPIV_WRONG_PIN:
return CKR_PIN_INCORRECT;
case YKPIV_PIN_LOCKED:
return CKR_PIN_LOCKED;
default:
return CKR_FUNCTION_FAILED;
}
}
+3 -1
View File
@@ -10,12 +10,14 @@ CK_RV YUBICO_get_token_manufacturer(CK_UTF8CHAR_PTR str, CK_ULONG len);
CK_RV YUBICO_get_token_model(ykpiv_state *state, CK_UTF8CHAR_PTR str, CK_ULONG len);
CK_RV YUBICO_get_token_flags(CK_FLAGS_PTR flags);
CK_RV YUBICO_get_token_serial(CK_CHAR_PTR str, CK_ULONG len);
CK_RV YUBICO_get_token_version(CK_UTF8CHAR_PTR v_str, CK_ULONG v_str_len, CK_VERSION_PTR version);
CK_RV YUBICO_get_token_version(ykpiv_state *state, CK_VERSION_PTR version);
CK_RV YUBICO_get_token_mechanisms_num(CK_ULONG_PTR num);
CK_RV YUBICO_get_token_mechanism_list(CK_MECHANISM_TYPE_PTR mec, CK_ULONG num);
CK_RV YUBICO_get_token_mechanism_info(CK_MECHANISM_TYPE mec, CK_MECHANISM_INFO_PTR info);
CK_RV YUBICO_get_token_objects_num(ykpiv_state *state, CK_ULONG_PTR num, CK_ULONG_PTR num_certs);
CK_RV YUBICO_get_token_object_list(ykpiv_state *state, piv_obj_id_t *obj, CK_ULONG num);
CK_RV YUBICO_get_token_raw_certificate(ykpiv_state *state, piv_obj_id_t obj, CK_BYTE_PTR data, CK_ULONG_PTR len);
CK_RV YUBICO_token_change_pin(ykpiv_state *state, CK_USER_TYPE user_type, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen,
CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen);
#endif