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.log
tool/tests/parse_name.o tool/tests/parse_name.o
tool/tests/parse_name.trs 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/ coverage/
lib/error.gcno lib/error.gcno
lib/version.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 = 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 if ENABLE_COV
cov-reset: cov-reset:
+44 -1
View File
@@ -1,6 +1,49 @@
yubico-piv-tool NEWS -- History of user-visible changes. -*- outline -*- 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) * 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. # 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_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
@@ -34,9 +34,9 @@ AC_CONFIG_MACRO_DIR([m4])
# Interfaces changed/added/removed: CURRENT++ REVISION=0 # Interfaces changed/added/removed: CURRENT++ REVISION=0
# Interfaces added: AGE++ # Interfaces added: AGE++
# Interfaces removed: AGE=0 # Interfaces removed: AGE=0
AC_SUBST([LT_CURRENT], 2) AC_SUBST([LT_CURRENT], 4)
AC_SUBST([LT_REVISION], 1) AC_SUBST([LT_REVISION], 1)
AC_SUBST([LT_AGE], 1) AC_SUBST([LT_AGE], 3)
AM_INIT_AUTOMAKE([-Wall -Werror foreign]) AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AM_SILENT_RULES([yes]) AM_SILENT_RULES([yes])
@@ -52,8 +52,6 @@ PKG_PROG_PKG_CONFIG
PKG_CHECK_MODULES(OPENSSL, libcrypto) PKG_CHECK_MODULES(OPENSSL, libcrypto)
#PKG_CHECK_MODULES([LIBNSPR], [nspr], [], [])
gl_LD_VERSION_SCRIPT gl_LD_VERSION_SCRIPT
gl_VALGRIND_TESTS gl_VALGRIND_TESTS
@@ -190,10 +188,24 @@ AC_ARG_ENABLE([ykcs11-debug],
AS_IF([test "x$enable_ykcs11_debug" != xno], AS_IF([test "x$enable_ykcs11_debug" != xno],
[AC_DEFINE([YKCS11_DBG], [1], [Regular debug flag]) [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], [true],
[AC_DEFINE([YKCS11_DBG], [0], [Regular debug flag]) [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_MAJOR, `echo $PACKAGE_VERSION | sed 's/\(.*\)\..*\..*/\1/g'`)
AC_SUBST(YKPIV_VERSION_MINOR, `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 Mac PCSC
LIBS: ${PCSC_MACOSX_LIBS} 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 #define MAX_READERS 16
struct ykpiv_state { struct ykpiv_state {
SCARDCONTEXT context; SCARDCONTEXT context;
SCARDHANDLE card; SCARDHANDLE card;
unsigned long n_readers; int verbose;
char readers[MAX_READERS][READER_LEN];
unsigned long tot_readers_len;
int verbose;
}; };
union u_APDU { union u_APDU {
+188 -5
View File
@@ -5,15 +5,15 @@
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above * * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following * copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided * disclaimer in the documentation and/or other materials provided
* with the distribution. * with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -258,7 +258,7 @@ ykpiv_rc ykpiv_transfer_data(ykpiv_state *state, const unsigned char *templ,
rc = SCardBeginTransaction(state->card); rc = SCardBeginTransaction(state->card);
if(rc != SCARD_S_SUCCESS) { if(rc != SCARD_S_SUCCESS) {
if(state->verbose) { 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; 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, ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
unsigned char *data, unsigned long *len) { unsigned char *data, unsigned long *len) {
int sw; 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, ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
unsigned char *indata, size_t len) { unsigned char *indata, size_t len) {
unsigned char data[2048]; unsigned char data[3072];
unsigned char *dataptr = data; unsigned char *dataptr = data;
unsigned char templ[] = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff}; unsigned char templ[] = {0, YKPIV_INS_PUT_DATA, 0x3f, 0xff};
int sw; int sw;
@@ -781,3 +843,124 @@ ykpiv_rc ykpiv_save_object(ykpiv_state *state, int object_id,
return YKPIV_GENERIC_ERROR; 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_WRONG_PIN = -10,
YKPIV_INVALID_OBJECT = -11, YKPIV_INVALID_OBJECT = -11,
YKPIV_ALGORITHM_ERROR = -12, YKPIV_ALGORITHM_ERROR = -12,
YKPIV_PIN_LOCKED = -13,
} ykpiv_rc; } ykpiv_rc;
const char *ykpiv_strerror(ykpiv_rc err); const char *ykpiv_strerror(ykpiv_rc err);
@@ -85,12 +86,29 @@ extern "C"
unsigned char algorithm, unsigned char key); unsigned char algorithm, unsigned char key);
ykpiv_rc ykpiv_get_version(ykpiv_state *state, char *version, size_t len); 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_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, ykpiv_rc ykpiv_fetch_object(ykpiv_state *state, int object_id,
unsigned char *data, unsigned long *len); unsigned char *data, unsigned long *len);
ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key, ykpiv_rc ykpiv_set_mgmkey2(ykpiv_state *state, const unsigned char *new_key,
const unsigned char touch); const unsigned char touch);
ykpiv_rc ykpiv_save_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 *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_3DES 0x03
#define YKPIV_ALGO_RSA1024 0x06 #define YKPIV_ALGO_RSA1024 0x06
@@ -103,6 +121,26 @@ extern "C"
#define YKPIV_KEY_SIGNATURE 0x9c #define YKPIV_KEY_SIGNATURE 0x9c
#define YKPIV_KEY_KEYMGM 0x9d #define YKPIV_KEY_KEYMGM 0x9d
#define YKPIV_KEY_CARDAUTH 0x9e #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_CAPABILITY 0x5fc107
#define YKPIV_OBJ_CHUID 0x5fc102 #define YKPIV_OBJ_CHUID 0x5fc102
@@ -158,11 +196,13 @@ extern "C"
#define YKPIV_INS_ATTEST 0xf9 #define YKPIV_INS_ATTEST 0xf9
#define YKPIV_PINPOLICY_TAG 0xaa #define YKPIV_PINPOLICY_TAG 0xaa
#define YKPIV_PINPOLICY_DEFAULT 0
#define YKPIV_PINPOLICY_NEVER 1 #define YKPIV_PINPOLICY_NEVER 1
#define YKPIV_PINPOLICY_ONCE 2 #define YKPIV_PINPOLICY_ONCE 2
#define YKPIV_PINPOLICY_ALWAYS 3 #define YKPIV_PINPOLICY_ALWAYS 3
#define YKPIV_TOUCHPOLICY_TAG 0xab #define YKPIV_TOUCHPOLICY_TAG 0xab
#define YKPIV_TOUCHPOLICY_DEFAULT 0
#define YKPIV_TOUCHPOLICY_NEVER 1 #define YKPIV_TOUCHPOLICY_NEVER 1
#define YKPIV_TOUCHPOLICY_ALWAYS 2 #define YKPIV_TOUCHPOLICY_ALWAYS 2
+35 -21
View File
@@ -28,36 +28,50 @@
YKPIV_0.1.0 YKPIV_0.1.0
{ {
global: global:
ykpiv_check_version; ykpiv_check_version;
ykpiv_strerror_name; ykpiv_strerror_name;
ykpiv_strerror; ykpiv_strerror;
ykpiv_init; ykpiv_init;
ykpiv_done; ykpiv_done;
ykpiv_connect; ykpiv_connect;
ykpiv_disconnect; ykpiv_disconnect;
ykpiv_transfer_data; ykpiv_transfer_data;
ykpiv_authenticate; ykpiv_authenticate;
ykpiv_set_mgmkey; ykpiv_set_mgmkey;
ykpiv_sign_data; ykpiv_sign_data;
ykpiv_get_version; ykpiv_get_version;
ykpiv_verify; ykpiv_verify;
ykpiv_fetch_object; ykpiv_fetch_object;
ykpiv_save_object; ykpiv_save_object;
ykpiv_hex_decode; ykpiv_hex_decode;
local: local:
*; *;
}; };
YKPIV_0.2.0 YKPIV_0.2.0
{ {
global: global:
ykpiv_decipher_data; ykpiv_decipher_data;
} YKPIV_0.1.0; } YKPIV_0.1.0;
YKPIV_1.1.0 YKPIV_1.1.0
{ {
global: global:
ykpiv_set_mgmkey2; ykpiv_set_mgmkey2;
ykpiv_list_readers; ykpiv_list_readers;
} YKPIV_0.1.0; } 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. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PACKAGE=yubico-piv-tool PACKAGE=yubico-piv-tool
OPENSSLVERSION=1.0.1p OPENSSLVERSION=1.0.1r
CFLAGS="-mmacosx-version-min=10.6"
all: usage mac all: usage mac
@@ -47,7 +48,7 @@ doit:
curl -L -O "https://www.openssl.org/source/openssl-$(OPENSSLVERSION).tar.gz" && \ curl -L -O "https://www.openssl.org/source/openssl-$(OPENSSLVERSION).tar.gz" && \
tar xfz openssl-$(OPENSSLVERSION).tar.gz && \ tar xfz openssl-$(OPENSSLVERSION).tar.gz && \
cd openssl-$(OPENSSLVERSION) && \ 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 && \ make all install_sw && \
cp LICENSE $(PWD)/tmp$(ARCH)/root/licenses/openssl.txt && \ cp LICENSE $(PWD)/tmp$(ARCH)/root/licenses/openssl.txt && \
rm -rf $(PWD)/tmp/root/ssl/ && \ rm -rf $(PWD)/tmp/root/ssl/ && \
@@ -60,16 +61,16 @@ doit:
cp ../$(PACKAGE)-$(VERSION).tar.gz . && \ cp ../$(PACKAGE)-$(VERSION).tar.gz . && \
tar xfz $(PACKAGE)-$(VERSION).tar.gz && \ tar xfz $(PACKAGE)-$(VERSION).tar.gz && \
cd $(PACKAGE)-$(VERSION)/ && \ 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) && \ make install $(CHECK) && \
chmod u+w $(PWD)/tmp/root/lib/libcrypto.1.0.0.dylib && \ 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 @loader_path/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 @loader_path/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 -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 @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 @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 @executable_path/../lib/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 @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/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 ; \ 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 \ 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!"; \ 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 bin_PROGRAMS = yubico-piv-tool
yubico_piv_tool_SOURCES = yubico-piv-tool.c yubico-piv-tool.h2m 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 yubico_piv_tool_LDADD += libpiv_cmd.la libpiv_util.la
noinst_LTLIBRARIES = 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_cmd_la_CFLAGS =
libpiv_util_la_SOURCES = util.c util.h 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 $^ $(GENGETOPT) --input $^
BUILT_SOURCES = cmdline.c cmdline.h BUILT_SOURCES = cmdline.c cmdline.h
@@ -54,8 +54,7 @@ MAINTAINERCLEANFILES = $(BUILT_SOURCES)
dist_man_MANS = yubico-piv-tool.1 dist_man_MANS = yubico-piv-tool.1
MAINTAINERCLEANFILES += $(dist_man_MANS) MAINTAINERCLEANFILES += $(dist_man_MANS)
yubico-piv-tool.1: $(yubico_piv_tool_SOURCES) \ yubico-piv-tool.1: $(yubico_piv_tool_SOURCES) $(libpiv_cmd_la_SOURCES)
$(top_srcdir)/configure.ac
$(HELP2MAN) --no-info \ $(HELP2MAN) --no-info \
--name="Yubico PIV tool" \ --name="Yubico PIV tool" \
--include=$(srcdir)/yubico-piv-tool.h2m \ --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", "reset","pin-retries","import-key","import-certificate","set-chuid",
"request-certificate","verify-pin","change-pin","change-puk","unblock-pin", "request-certificate","verify-pin","change-pin","change-puk","unblock-pin",
"selfsign-certificate","delete-certificate","read-certificate","status", "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 " text "
Multiple actions may be given at once and will be executed in order Multiple actions may be given at once and will be executed in order
for example --action=verify-pin --action=request-certificate\n" 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 " text "
The subject must be written as: The subject must be written as:
/CN=host.example.com/OU=test/O=example.com/\n" /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 "pin" P "Pin/puk code for verification" string optional
option "new-pin" N "New pin/puk code for changing" string optional dependon="pin" 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 "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 "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 option "sign" - "Sign data" flag off hidden
+2 -1
View File
@@ -37,8 +37,9 @@ AM_CPPFLAGS += $(OPENSSL_CFLAGS)
AM_LDFLAGS = -no-install AM_LDFLAGS = -no-install
parse_name_LDADD = ../libpiv_util.la $(OPENSSL_LIBS) 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) TESTS = basic.sh $(check_PROGRAMS)
if ENABLE_COV 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; return NULL;
} }
void dump_hex(const unsigned char *buf, unsigned int len, FILE *output, bool space) { size_t read_data(unsigned char *buf, size_t len, FILE* input, enum enum_format format) {
unsigned int i; char raw_buf[3072 * 2];
for (i = 0; i < len; i++) { size_t raw_len = sizeof(raw_buf);
fprintf(output, "%02x%s", buf[i], space == true ? " " : ""); 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) { int get_length(const unsigned char *buffer, int *len) {
@@ -276,33 +344,94 @@ int key_to_object_id(int key) {
int object; int object;
switch(key) { switch(key) {
case 0x9a: case YKPIV_KEY_AUTHENTICATION:
object = YKPIV_OBJ_AUTHENTICATION; object = YKPIV_OBJ_AUTHENTICATION;
break; break;
case 0x9c: case YKPIV_KEY_CARDMGM:
object = YKPIV_OBJ_SIGNATURE; object = YKPIV_OBJ_SIGNATURE;
break; break;
case 0x9d: case YKPIV_KEY_KEYMGM:
object = YKPIV_OBJ_KEY_MANAGEMENT; object = YKPIV_OBJ_KEY_MANAGEMENT;
break; break;
case 0x9e: case YKPIV_KEY_CARDAUTH:
object = YKPIV_OBJ_CARD_AUTH; object = YKPIV_OBJ_CARD_AUTH;
break; 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: default:
object = 0; object = 0;
} }
return object; 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); int real_len = BN_num_bytes(bn);
*in_ptr += set_length(*in_ptr, element_len);
if(real_len > element_len) { if(real_len > element_len) {
return false; return false;
} }
memset(*in_ptr, 0, (size_t)(element_len - real_len)); memset(in_ptr, 0, (size_t)(element_len - real_len));
*in_ptr += element_len - real_len; in_ptr += element_len - real_len;
*in_ptr += BN_bn2bin(bn, *in_ptr); BN_bn2bin(bn, in_ptr);
return true; return true;
} }
+5 -2
View File
@@ -31,6 +31,8 @@
#ifndef YUBICO_PIV_TOOL_INTERNAL_H #ifndef YUBICO_PIV_TOOL_INTERNAL_H
#define YUBICO_PIV_TOOL_INTERNAL_H #define YUBICO_PIV_TOOL_INTERNAL_H
#include <stdbool.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include "cmdline.h" #include "cmdline.h"
@@ -38,7 +40,8 @@
#define INPUT 1 #define INPUT 1
#define OUTPUT 2 #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 set_length(unsigned char*, int);
int get_length(const unsigned char*, int*); int get_length(const unsigned char*, int*);
X509_NAME *parse_name(const char*); X509_NAME *parse_name(const char*);
@@ -46,7 +49,7 @@ unsigned char get_algorithm(EVP_PKEY*);
FILE *open_file(const char*, int); FILE *open_file(const char*, int);
int get_object_id(enum enum_slot slot); int get_object_id(enum enum_slot slot);
int key_to_object_id(int key); 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*, bool prepare_rsa_signature(const unsigned char*, unsigned int, unsigned char*,
unsigned int*, int); unsigned int*, int);
bool read_pw(const char*, char*, size_t, int); bool read_pw(const char*, char*, size_t, int);
+353 -202
View File
@@ -5,15 +5,15 @@
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
* met: * met:
* *
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* * Redistributions in binary form must reproduce the above * * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following * copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided * disclaimer in the documentation and/or other materials provided
* with the distribution. * with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -63,6 +63,17 @@ unsigned const char chuid_tmpl[] = {
}; };
#define CHUID_GUID_OFFS 29 #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 MAX_OID_LEN 19
#define KEY_LEN 24 #define KEY_LEN 24
@@ -71,7 +82,7 @@ static void print_version(ykpiv_state *state, const char *output_file_name) {
char version[7]; char version[7];
FILE *output_file = open_file(output_file_name, OUTPUT); FILE *output_file = open_file(output_file_name, OUTPUT);
if(!output_file) { if(!output_file) {
fprintf(stderr, "Failed opening output_file_name\n"); return;
} }
if(ykpiv_get_version(state, version, sizeof(version)) == YKPIV_OK) { 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, static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
const char *input_file_name, const char *slot, char *password, const char *input_file_name, const char *slot, char *password,
enum enum_pin_policy pin_policy, enum enum_touch_policy touch_policy) { enum enum_pin_policy pin_policy, enum enum_touch_policy touch_policy) {
int key = 0; int key = 0;
FILE *input_file = NULL; FILE *input_file = NULL;
EVP_PKEY *private_key = NULL; EVP_PKEY *private_key = NULL;
PKCS12 *p12 = NULL; PKCS12 *p12 = NULL;
X509 *cert = NULL; X509 *cert = NULL;
bool ret = false; bool ret = false;
ykpiv_rc rc = YKPIV_GENERIC_ERROR;
sscanf(slot, "%2x", &key); 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 algorithm = get_algorithm(private_key);
unsigned char pp = YKPIV_PINPOLICY_DEFAULT;
unsigned char tp = YKPIV_TOUCHPOLICY_DEFAULT;
if(algorithm == 0) { if(algorithm == 0) {
goto import_out; 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) || if(pin_policy != pin_policy__NULL) {
!(e[1] == 0x01 && e[2] == 0x00 && e[3] == 0x01)) { pp = get_pin_policy(pin_policy);
fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n"); }
goto import_out;
}
*in_ptr++ = 0x01; if(touch_policy != touch_policy__NULL) {
if(set_component_with_len(&in_ptr, rsa_private_key->p, element_len) == false) { tp = get_touch_policy(touch_policy);
fprintf(stderr, "Failed setting p component.\n"); }
goto import_out;
}
*in_ptr++ = 0x02; if(YKPIV_IS_RSA(algorithm)) {
if(set_component_with_len(&in_ptr, rsa_private_key->q, element_len) == false) { RSA *rsa_private_key = EVP_PKEY_get1_RSA(private_key);
fprintf(stderr, "Failed setting q component.\n"); unsigned char e[4];
goto import_out; unsigned char p[128];
} unsigned char q[128];
unsigned char dmp1[128];
unsigned char dmq1[128];
unsigned char iqmp[128];
*in_ptr++ = 0x03; int element_len = 128;
if(set_component_with_len(&in_ptr, rsa_private_key->dmp1, element_len) == false) { if(algorithm == YKPIV_ALGO_RSA1024) {
fprintf(stderr, "Failed setting dmp1 component.\n"); element_len = 64;
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;
}
} }
if(pin_policy != pin_policy__NULL) { if((set_component(e, rsa_private_key->e, 3) == false) ||
*in_ptr++ = YKPIV_PINPOLICY_TAG; !(e[0] == 0x01 && e[1] == 0x00 && e[2] == 0x01)) {
*in_ptr++ = 1; fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n");
*in_ptr++ = get_pin_policy(pin_policy); goto import_out;
}
if(touch_policy != touch_policy__NULL) {
*in_ptr++ = YKPIV_TOUCHPOLICY_TAG;
*in_ptr++ = 1;
*in_ptr++ = get_touch_policy(touch_policy);
} }
if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, if(set_component(p, rsa_private_key->p, element_len) == false) {
&recv_len, &sw) != YKPIV_OK) { fprintf(stderr, "Failed setting p component.\n");
return false; goto import_out;
} 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(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: import_out:
if(private_key) { if(private_key) {
EVP_PKEY_free(private_key); EVP_PKEY_free(private_key);
} }
if(p12) { if(p12) {
PKCS12_free(p12); PKCS12_free(p12);
} }
if(cert) { if(cert) {
X509_free(cert); X509_free(cert);
} }
if(input_file != stdin) { if(input_file != stdin) {
fclose(input_file); fclose(input_file);
} }
return ret; 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; unsigned char *certptr = certdata;
int object = get_object_id(slot); int object = get_object_id(slot);
ykpiv_rc res; ykpiv_rc res;
if(cert_len > 2048) { if(4 + cert_len + 5 > 3072) { /* 4 is prefix size, 5 is postfix size */
fprintf(stderr, "Certificate to large, maximum 2048 bytes (was %d bytes).\n", cert_len); fprintf(stderr, "Certificate is to large to fit in buffer.\n");
goto import_cert_out; goto import_cert_out;
} }
*certptr++ = 0x70; *certptr++ = 0x70;
certptr += set_length(certptr, cert_len); certptr += set_length(certptr, cert_len);
if (compress) { if (compress) {
@@ -587,20 +604,36 @@ import_cert_out:
return ret; return ret;
} }
static bool set_chuid(ykpiv_state *state, int verbose) { static bool set_dataobject(ykpiv_state *state, int verbose, int type) {
unsigned char chuid[sizeof(chuid_tmpl)]; unsigned char obj[1024];
ykpiv_rc res; ykpiv_rc res;
size_t offs, rand_len, len;
const unsigned char *tmpl;
int id;
memcpy(chuid, chuid_tmpl, sizeof(chuid)); if(type == CHUID) {
if(RAND_pseudo_bytes(chuid + CHUID_GUID_OFFS, 0x10) == -1) { 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"); fprintf(stderr, "error: no randomness.\n");
return false; return false;
} }
if(verbose) { if(verbose) {
fprintf(stderr, "Setting the CHUID to: "); fprintf(stderr, "Setting the %s to: ", type == CHUID ? "CHUID" : "CCC");
dump_hex(chuid, sizeof(chuid), stderr, true); 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)); fprintf(stderr, "Failed communicating with device: %s\n", ykpiv_strerror(res));
return false; return false;
} }
@@ -689,7 +722,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
memcpy(digest, oid, oid_len); memcpy(digest, oid, oid_len);
/* XXX: this should probably use X509_REQ_digest() but that's buggy */ /* 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, 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"); fprintf(stderr, "Failed doing digest of request.\n");
goto request_out; goto request_out;
} }
@@ -748,7 +781,7 @@ request_out:
static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_format, 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 *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 *input_file = NULL;
FILE *output_file = NULL; FILE *output_file = NULL;
bool ret = false; 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"); fprintf(stderr, "Failed to set the certificate public key.\n");
goto selfsign_out; 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"); fprintf(stderr, "Failed to set certificate serial.\n");
goto selfsign_out; 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"); fprintf(stderr, "Failed to set certificate notBefore.\n");
goto selfsign_out; 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"); fprintf(stderr, "Failed to set certificate notAfter.\n");
goto selfsign_out; 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); memcpy(digest, oid, oid_len);
/* XXX: this should probably use X509_digest() but that looks buggy */ /* XXX: this should probably use X509_digest() but that looks buggy */
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_CINF), md, x509->cert_info, 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"); fprintf(stderr, "Failed doing digest of certificate.\n");
goto selfsign_out; 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. */ * since they're very similar in what data they use. */
static bool change_pin(ykpiv_state *state, enum enum_action action, const char *pin, static bool change_pin(ykpiv_state *state, enum enum_action action, const char *pin,
const char *new_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 pinbuf[9] = {0};
char new_pinbuf[9] = {0}; char new_pinbuf[9] = {0};
const char *name = action == action_arg_changeMINUS_pin ? "pin" : "puk"; const char *name = action == action_arg_changeMINUS_pin ? "pin" : "puk";
const char *new_name = action == action_arg_changeMINUS_puk ? "new puk" : "new pin"; 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 pin_len;
size_t new_len; size_t new_len;
int tries;
ykpiv_rc res;
if(!pin) { if(!pin) {
if (!read_pw(name, pinbuf, sizeof(pinbuf), false)) { 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) { if(action == action_arg_unblockMINUS_pin) {
templ[1] = YKPIV_INS_RESET_RETRY; op = ykpiv_unblock_pin;
} }
else if(action == action_arg_changeMINUS_puk) { else if(action == action_arg_changeMINUS_puk) {
templ[3] = 0x81; op = ykpiv_change_puk;
} }
memcpy(indata, pin, pin_len); res = op(state, pin, pin_len, new_pin, new_len, &tries);
if(pin_len < 8) { switch (res) {
memset(indata + pin_len, 0xff, 8 - pin_len); case YKPIV_OK:
} return true;
memcpy(indata + 8, new_pin, new_len);
if(new_len < 8) { case YKPIV_WRONG_PIN:
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;
fprintf(stderr, "Failed verifying %s code, now %d tries left before blocked.\n", fprintf(stderr, "Failed verifying %s code, now %d tries left before blocked.\n",
name, tries); name, tries);
} else if(sw == 0x6983) { return false;
case YKPIV_PIN_LOCKED:
if(action == action_arg_changeMINUS_pin) { if(action == action_arg_changeMINUS_pin) {
fprintf(stderr, "The pin code is blocked, use the unblock-pin action to unblock it.\n"); fprintf(stderr, "The pin code is blocked, use the unblock-pin action to unblock it.\n");
} else { } else {
fprintf(stderr, "The puk code is blocked, you will have to reinitialize the application.\n"); fprintf(stderr, "The puk code is blocked, you will have to reinitialize the application.\n");
} }
} else { return false;
fprintf(stderr, "Failed changing/unblocking code, error: %x\n", sw);
} default:
return false; 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) { 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) { enum enum_key_format key_format, const char *output_file_name) {
FILE *output_file; FILE *output_file;
int object = get_object_id(slot); int object = get_object_id(slot);
unsigned char data[2048]; unsigned char data[3072];
const unsigned char *ptr = data; const unsigned char *ptr = data;
unsigned long len = sizeof(data); unsigned long len = sizeof(data);
int cert_len; 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); output_file = open_file(output, OUTPUT);
if(!output_file) { if(!output_file) {
if(input_file && input_file != stdin) {
fclose(input_file);
}
return false; return false;
} }
@@ -1127,7 +1157,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output,
if(verbosity) { if(verbosity) {
fprintf(stderr, "file hashed as: "); 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); EVP_MD_CTX_destroy(mdctx);
} }
@@ -1146,7 +1176,7 @@ static bool sign_file(ykpiv_state *state, const char *input, const char *output,
if(verbosity) { if(verbosity) {
fprintf(stderr, "file signed as: "); 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); fwrite(buf, 1, len, output_file);
ret = true; ret = true;
@@ -1167,7 +1197,8 @@ out:
static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_MD *md, static void print_cert_info(ykpiv_state *state, enum enum_slot slot, const EVP_MD *md,
FILE *output) { FILE *output) {
int object = get_object_id(slot); int object = get_object_id(slot);
unsigned char data[2048]; int slot_name;
unsigned char data[3072];
const unsigned char *ptr = data; const unsigned char *ptr = data;
unsigned long len = sizeof(data); unsigned long len = sizeof(data);
int cert_len; 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; BIO *bio = NULL;
if(ykpiv_fetch_object(state, object, data, &len) != YKPIV_OK) { if(ykpiv_fetch_object(state, object, data, &len) != YKPIV_OK) {
fprintf(output, "No data available.\n");
return; 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) { if(*ptr++ == 0x70) {
unsigned int md_len = sizeof(data); unsigned int md_len = sizeof(data);
ASN1_TIME *not_before, *not_after; 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"); fprintf(output, "\n");
X509_digest(x509, md, data, &md_len); X509_digest(x509, md, data, &md_len);
fprintf(output, "\tFingerprint:\t"); 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); bio = BIO_new_fp(output, BIO_NOCLOSE | BIO_FP_TEXT);
not_before = X509_get_notBefore(x509); not_before = X509_get_notBefore(x509);
@@ -1266,10 +1305,12 @@ cert_out:
} }
static bool status(ykpiv_state *state, enum enum_hash hash, 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; const EVP_MD *md;
unsigned char chuid[2048]; unsigned char buf[3072];
long unsigned len = sizeof(chuid); long unsigned len = sizeof(buf);
int i;
FILE *output_file = open_file(output_file_name, OUTPUT); FILE *output_file = open_file(output_file_name, OUTPUT);
if(!output_file) { if(!output_file) {
return false; return false;
@@ -1281,20 +1322,26 @@ static bool status(ykpiv_state *state, enum enum_hash hash,
} }
fprintf(output_file, "CHUID:\t"); 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"); fprintf(output_file, "No data available\n");
} else { } else {
dump_hex(chuid, len, output_file, false); dump_data(buf, len, output_file, false, format_arg_hex);
} }
fprintf(output_file, "Slot 9a:\t"); len = sizeof(buf);
print_cert_info(state, slot_arg_9a, md, output_file); fprintf(output_file, "CCC:\t");
fprintf(output_file, "Slot 9c:\t"); if(ykpiv_fetch_object(state, YKPIV_OBJ_CAPABILITY, buf, &len) != YKPIV_OK) {
print_cert_info(state, slot_arg_9c, md, output_file); fprintf(output_file, "No data available\n");
fprintf(output_file, "Slot 9d:\t"); } else {
print_cert_info(state, slot_arg_9d, md, output_file); dump_data(buf, len, output_file, false, format_arg_hex);
fprintf(output_file, "Slot 9e:\t"); }
print_cert_info(state, slot_arg_9e, md, output_file);
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; int tries;
@@ -1360,7 +1407,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot,
EVP_DigestFinal_ex(mdctx, data, &data_len); EVP_DigestFinal_ex(mdctx, data, &data_len);
if(verbose) { if(verbose) {
fprintf(stderr, "Test data hashes as: "); 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(len == sizeof(secret)) {
if(verbose) { if(verbose) {
fprintf(stderr, "Generated nonce: "); 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: "); 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) { if(memcmp(secret, secret2, sizeof(secret)) == 0) {
fprintf(stderr, "Successfully performed RSA decryption!\n"); fprintf(stderr, "Successfully performed RSA decryption!\n");
@@ -1558,9 +1605,9 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
} }
if(verbose) { if(verbose) {
fprintf(stderr, "ECDH host generated: "); 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: "); 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) { if(memcmp(secret, secret2, key_len) == 0) {
fprintf(stderr, "Successfully performed ECDH exchange with card.\n"); fprintf(stderr, "Successfully performed ECDH exchange with card.\n");
@@ -1618,11 +1665,6 @@ static bool attest(ykpiv_state *state, const char *slot,
return false; 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) { if(ykpiv_transfer_data(state, templ, NULL, 0, data, &len, &sw) != YKPIV_OK) {
fprintf(stderr, "Failed to communicate.\n"); fprintf(stderr, "Failed to communicate.\n");
goto attest_out; goto attest_out;
@@ -1660,7 +1702,73 @@ attest_out:
if(x509) { if(x509) {
X509_free(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; return ret;
} }
@@ -1671,12 +1779,16 @@ int main(int argc, char *argv[]) {
enum enum_action action; enum enum_action action;
unsigned int i; unsigned int i;
int ret = EXIT_SUCCESS; int ret = EXIT_SUCCESS;
bool authed = false;
char pwbuf[128];
char *password;
if(cmdline_parser(argc, argv, &args_info) != 0) { if(cmdline_parser(argc, argv, &args_info) != 0) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
verbosity = args_info.verbose_arg + (int)args_info.verbose_given; verbosity = args_info.verbose_arg + (int)args_info.verbose_given;
password = args_info.password_arg;
for(i = 0; i < args_info.action_given; i++) { for(i = 0; i < args_info.action_given; i++) {
action = *(args_info.action_arg + i); action = *(args_info.action_arg + i);
@@ -1709,12 +1821,21 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
break; 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_pin:
case action_arg_changeMINUS_puk: case action_arg_changeMINUS_puk:
case action_arg_unblockMINUS_pin: case action_arg_unblockMINUS_pin:
case action_arg_verifyMINUS_pin: case action_arg_verifyMINUS_pin:
case action_arg_setMINUS_mgmMINUS_key: case action_arg_setMINUS_mgmMINUS_key:
case action_arg_setMINUS_chuid: case action_arg_setMINUS_chuid:
case action_arg_setMINUS_ccc:
case action_arg_version: case action_arg_version:
case action_arg_reset: case action_arg_reset:
case action_arg_status: case action_arg_status:
@@ -1736,20 +1857,60 @@ int main(int argc, char *argv[]) {
} }
for(i = 0; i < args_info.action_given; i++) { for(i = 0; i < args_info.action_given; i++) {
bool needs_auth = false;
action = *(args_info.action_arg + i); action = *(args_info.action_arg + i);
switch(action) { 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_generate:
case action_arg_setMINUS_mgmMINUS_key: case action_arg_setMINUS_mgmMINUS_key:
case action_arg_pinMINUS_retries: case action_arg_pinMINUS_retries:
case action_arg_importMINUS_key:
case action_arg_importMINUS_certificate:
case action_arg_setMINUS_chuid: case action_arg_setMINUS_chuid:
case action_arg_setMINUS_ccc:
case action_arg_deleteMINUS_certificate: case action_arg_deleteMINUS_certificate:
if(verbosity) { case action_arg_writeMINUS_object:
fprintf(stderr, "Authenticating since action '%s' needs that.\n", cmdline_parser_action_values[action]); 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; break;
case action_arg_version: case action_arg_version:
case action_arg_reset: case action_arg_reset:
@@ -1765,44 +1926,20 @@ int main(int argc, char *argv[]) {
case action_arg_testMINUS_decipher: case action_arg_testMINUS_decipher:
case action_arg_listMINUS_readers: case action_arg_listMINUS_readers:
case action_arg_attest: case action_arg_attest:
case action_arg_readMINUS_object:
case action__NULL: case action__NULL:
default: default:
if(verbosity) { if(verbosity) {
fprintf(stderr, "Action '%s' does not need authentication.\n", cmdline_parser_action_values[action]); 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 setup.. */
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
for(i = 0; i < args_info.action_given; i++) { for(i = 0; i < args_info.action_given; i++) {
char new_keybuf[KEY_LEN*2+1] = {0}; char new_keybuf[KEY_LEN*2+1] = {0};
char *new_mgm_key = args_info.new_key_arg; char *new_mgm_key = args_info.new_key_arg;
@@ -1855,7 +1992,7 @@ int main(int argc, char *argv[]) {
break; break;
case action_arg_reset: case action_arg_reset:
if(reset(state) == false) { if(reset(state) == false) {
fprintf(stderr, "Reset failed, are pincodes blocked?\n"); fprintf(stderr, "Reset failed, are pincodes blocked?\n");
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
} else { } else {
fprintf(stderr, "Successfully reset the application.\n"); fprintf(stderr, "Successfully reset the application.\n");
@@ -1871,25 +2008,27 @@ int main(int argc, char *argv[]) {
} }
break; break;
case action_arg_importMINUS_key: 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) { args_info.pin_policy_arg, args_info.touch_policy_arg) == false) {
fprintf(stderr, "Unable to import private key\n");
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
} else { } else {
fprintf(stderr, "Successfully imported a new private key.\n"); fprintf(stderr, "Successfully imported a new private key.\n");
} }
break; break;
case action_arg_importMINUS_certificate: 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; ret = EXIT_FAILURE;
} else { } else {
fprintf(stderr, "Successfully imported a new certificate.\n"); fprintf(stderr, "Successfully imported a new certificate.\n");
} }
break; break;
case action_arg_setMINUS_ccc:
case action_arg_setMINUS_chuid: 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; ret = EXIT_FAILURE;
} else { } else {
fprintf(stderr, "Successfully set new CHUID.\n"); fprintf(stderr, "Successfully set new %s.\n", action == action_arg_setMINUS_chuid ? "CHUID" : "CCC");
} }
break; break;
case action_arg_requestMINUS_certificate: case action_arg_requestMINUS_certificate:
@@ -1925,6 +2064,7 @@ int main(int argc, char *argv[]) {
case action_arg_selfsignMINUS_certificate: case action_arg_selfsignMINUS_certificate:
if(selfsign_certificate(state, args_info.key_format_arg, args_info.input_arg, 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.slot_orig, args_info.subject_arg, args_info.hash_arg,
args_info.serial_arg, args_info.valid_days_arg,
args_info.output_arg) == false) { args_info.output_arg) == false) {
ret = EXIT_FAILURE; ret = EXIT_FAILURE;
} else { } else {
@@ -1943,7 +2083,7 @@ int main(int argc, char *argv[]) {
} }
break; break;
case action_arg_status: 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; ret = EXIT_FAILURE;
} }
break; break;
@@ -1963,6 +2103,17 @@ int main(int argc, char *argv[]) {
if(list_readers(state) == false) { if(list_readers(state) == false) {
ret = EXIT_FAILURE; 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; break;
case action_arg_attest: case action_arg_attest:
if(attest(state, args_info.slot_orig, args_info.key_format_arg, 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. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PACKAGE=yubico-piv-tool PACKAGE=yubico-piv-tool
OPENSSLVERSION=1.0.1p OPENSSLVERSION=1.0.1r
all: usage 32bit 64bit all: usage 32bit 64bit
@@ -53,17 +53,14 @@ doit:
rm -rf $(PWD)/tmp$(ARCH)/root/ssl/ && \ rm -rf $(PWD)/tmp$(ARCH)/root/ssl/ && \
rm $(PWD)/tmp$(ARCH)/root/bin/openssl.exe && \ rm $(PWD)/tmp$(ARCH)/root/bin/openssl.exe && \
rm $(PWD)/tmp$(ARCH)/root/bin/c_rehash && \ 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/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 .. && \ cd .. && \
cp ../$(PACKAGE)-$(VERSION).tar.gz . && \ cp ../$(PACKAGE)-$(VERSION).tar.gz . && \
tar xfa $(PACKAGE)-$(VERSION).tar.gz && \ tar xfa $(PACKAGE)-$(VERSION).tar.gz && \
cd $(PACKAGE)-$(VERSION)/ && \ 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 && \ 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) && \ make install $(CHECK) && \
rm -rf $(PWD)/tmp$(ARCH)/root/lib/pkgconfig/ && \
cp COPYING $(PWD)/tmp$(ARCH)/root/licenses/$(PACKAGE).txt && \ cp COPYING $(PWD)/tmp$(ARCH)/root/licenses/$(PACKAGE).txt && \
cd .. && \ cd .. && \
cd root && \ cd root && \
+90 -55
View File
@@ -8,9 +8,29 @@
// TODO: this is mostly from OpenSC, how to give credit? // TODO: this is mostly from OpenSC, how to give credit?
typedef enum { typedef enum {
PIV_DATA_OBJ_X509_PIV_AUTH = 0, // PIV authentication PIV_DATA_OBJ_X509_PIV_AUTH = 0, // PIV authentication
PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication PIV_DATA_OBJ_X509_CARD_AUTH, // Card authentication
PIV_DATA_OBJ_X509_DS, // Certificate for digital signature PIV_DATA_OBJ_X509_DS, // Digital signature
PIV_DATA_OBJ_X509_KM, // Certificate for key management 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_CCC, // Card capability container
PIV_DATA_OBJ_CHUI, // Cardholder unique id PIV_DATA_OBJ_CHUI, // Cardholder unique id
PIV_DATA_OBJ_CHF, // Cardholder fingerprints PIV_DATA_OBJ_CHF, // Cardholder fingerprints
@@ -19,73 +39,88 @@ typedef enum {
PIV_DATA_OBJ_PI, // Cardholder printed information PIV_DATA_OBJ_PI, // Cardholder printed information
PIV_DATA_OBJ_DISCOVERY, // Discovery object PIV_DATA_OBJ_DISCOVERY, // Discovery object
PIV_DATA_OBJ_HISTORY, // History 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_IRIS_IMAGE, // Cardholder iris images
PIV_DATA_OBJ_BITGT, // Biometric information templates group template PIV_DATA_OBJ_BITGT, // Biometric information templates group template
PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer
PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data 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_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_CARD_AUTH, // Certificate for card authentication
PIV_CERT_OBJ_X509_DS, // Certificate for digital signature PIV_CERT_OBJ_X509_DS, // Certificate for digital signature
PIV_CERT_OBJ_X509_KM, // Certificate for key management 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_CERT_OBJ_LAST,
PIV_PVTK_OBJ_PIV_AUTH, // Private key for PIV authentication PIV_PVTK_OBJ_PIV_AUTH, // Private key for PIV authentication
PIV_PVTK_OBJ_CARD_AUTH, // Private Key for card authentication PIV_PVTK_OBJ_CARD_AUTH, // Private key for card authentication
PIV_PVTK_OBJ_DS, // Private Key for digital signature PIV_PVTK_OBJ_DS, // Private key for digital signature
PIV_PVTK_OBJ_KM, // Private Key for key management 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_PVTK_OBJ_LAST,
PIV_PUBK_OBJ_PIV_AUTH, // Public key for PIV authentication PIV_PUBK_OBJ_PIV_AUTH, // Public key for PIV authentication
PIV_PUBK_OBJ_CARD_AUTH, // Public Key for card authentication PIV_PUBK_OBJ_CARD_AUTH, // Public key for card authentication
PIV_PUBK_OBJ_DS, // Public Key for digital signature PIV_PUBK_OBJ_DS, // Public key for digital signature
PIV_PUBK_OBJ_KM, // Public Key for key management 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_PUBK_OBJ_LAST
} piv_obj_id_t; } 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_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_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_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_X509_RETIRED1, 1, 0, 0, "X.509 Certificate for Retired Key 1", 0, 0, get_doa, 4},
{PIV_DATA_OBJ_CHUI, 1, 0, 0, "Card Holder Unique Identifier", 0, 0, get_doa, 5}, {PIV_DATA_OBJ_X509_RETIRED2, 1, 0, 0, "X.509 Certificate for Retired Key 2", 0, 0, get_doa, 5},
{PIV_DATA_OBJ_CHF, 1, 1, 0, "Card Holder Fingerprints", 0, 0, get_doa, 6}, {PIV_DATA_OBJ_X509_RETIRED3, 1, 0, 0, "X.509 Certificate for Retired Key 3", 0, 0, get_doa, 6},
{PIV_DATA_OBJ_SEC_OBJ, 1, 0, 0, "Security Object", 0, 0, get_doa, 7}, {PIV_DATA_OBJ_X509_RETIRED4, 1, 0, 0, "X.509 Certificate for Retired Key 4", 0, 0, get_doa, 7},
{PIV_DATA_OBJ_CHFI, 1, 1, 0, "Cardholder Facial Images", 0, 0, get_doa, 8}, {PIV_DATA_OBJ_X509_RETIRED5, 1, 0, 0, "X.509 Certificate for Retired Key 5", 0, 0, get_doa, 8},
{PIV_DATA_OBJ_PI, 1, 1, 0, "Printed Information", 0, 0, get_doa, 9}, {PIV_DATA_OBJ_X509_RETIRED6, 1, 0, 0, "X.509 Certificate for Retired Key 6", 0, 0, get_doa, 9},
{PIV_DATA_OBJ_DISCOVERY, 1, 0, 0, "Discovery Object", 0, 0, get_doa, 10}, {PIV_DATA_OBJ_X509_RETIRED7, 1, 0, 0, "X.509 Certificate for Retired Key 7", 0, 0, get_doa, 10},
{PIV_DATA_OBJ_HISTORY, 1, 0, 0, "Key History Object", 0, 0, get_doa, 11}, {PIV_DATA_OBJ_X509_RETIRED8, 1, 0, 0, "X.509 Certificate for Retired Key 8", 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_X509_RETIRED9, 1, 0, 0, "X.509 Certificate for Retired Key 9", 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_X509_RETIRED10, 1, 0, 0, "X.509 Certificate for Retired Key 10", 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_X509_RETIRED11, 1, 0, 0, "X.509 Certificate for Retired Key 11", 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_X509_RETIRED12, 1, 0, 0, "X.509 Certificate for Retired Key 12", 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_X509_RETIRED13, 1, 0, 0, "X.509 Certificate for Retired Key 13", 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_X509_RETIRED14, 1, 0, 0, "X.509 Certificate for Retired Key 14", 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_X509_RETIRED15, 1, 0, 0, "X.509 Certificate for Retired Key 15", 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_X509_RETIRED16, 1, 0, 0, "X.509 Certificate for Retired Key 16", 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_X509_RETIRED17, 1, 0, 0, "X.509 Certificate for Retired Key 17", 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_X509_RETIRED18, 1, 0, 0, "X.509 Certificate for Retired Key 18", 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_X509_RETIRED19, 1, 0, 0, "X.509 Certificate for Retired Key 19", 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_X509_RETIRED20, 1, 0, 0, "X.509 Certificate for Retired Key 20", 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_CCC, 1, 0, 0, "Card Capability Container", 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_CHUI, 1, 0, 0, "Card Holder Unique Identifier", 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_CHF, 1, 1, 0, "Card Holder Fingerprints", 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_SEC_OBJ, 1, 0, 0, "Security Object", 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_CHFI, 1, 1, 0, "Cardholder Facial Images", 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_PI, 1, 1, 0, "Printed Information", 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_DISCOVERY, 1, 0, 0, "Discovery Object", 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_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_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_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}, {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_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_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_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_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_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_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_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_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_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_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_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[] = { 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.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"}, {"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"}, {"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"}, {"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.1.219.0", 3, "\x5F\xC1\x07", "\xDB\x00"}, {"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.48.0", 3, "\x5F\xC1\x02", "\x30\x00"}, {"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.96.16", 3, "\x5F\xC1\x03", "\x60\x10"}, {"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.144.0", 3, "\x5F\xC1\x06", "\x90\x00"}, {"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.96.48", 3, "\x5F\xC1\x08", "\x60\x30"}, {"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.48.1", 3, "\x5F\xC1\x09", "\x30\x01"}, {"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.96.80", 1, "\x7E", "\x60\x50"}, {"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.96.96", 3, "\x5F\xC1\x0C", "\x60\x60"}, {"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
/* 800-73-3, 21 new objects, 20 history certificates */ {"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.1", 3, "\x5F\xC1\x0D", "\x10\x01"}, {"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.2", 3, "\x5F\xC1\x0E", "\x10\x02"}, {"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.3", 3, "\x5F\xC1\x0F", "\x10\x03"}, {"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.4", 3, "\x5F\xC1\x10", "\x10\x04"}, {"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.5", 3, "\x5F\xC1\x11", "\x10\x05"}, {"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.7", 3, "\x5F\xC1\x13", "\x10\x07"}, {"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.8", 3, "\x5F\xC1\x14", "\x10\x08"}, {"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.9", 3, "\x5F\xC1\x15", "\x10\x09"}, {"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.10", 3, "\x5F\xC1\x16", "\x10\x0A"}, {"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.11", 3, "\x5F\xC1\x17", "\x10\x0B"}, {"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.2.16.12", 3, "\x5F\xC1\x18", "\x10\x0C"}, {"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.16.13", 3, "\x5F\xC1\x19", "\x10\x0D"}, {"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.16.14", 3, "\x5F\xC1\x1A", "\x10\x0E"}, {"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.16.15", 3, "\x5F\xC1\x1B", "\x10\x0F"}, {"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.16.16", 3, "\x5F\xC1\x1C", "\x10\x10"}, {"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.16.17", 3, "\x5F\xC1\x1D", "\x10\x11"}, {"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.16.18", 3, "\x5F\xC1\x1E", "\x10\x12"}, {"2.16.840.1.101.3.7.2.96.80", 1, "\x7E", "\x60\x50"}, // Discovery Object
{"2.16.840.1.101.3.7.2.16.19", 3, "\x5F\xC1\x1F", "\x10\x13"}, {"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.20", 3, "\x5F\xC1\x20", "\x10\x14"}, {"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.21", 3, "\x5F\xC1\x21", "\x10\x15"}, {"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.22", 2, "\x7F\x61", "\x10\x16"}, {"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.23", 3, "\x5F\xC1\x22", "\x10\x17"}, {"2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"}, // Pairing Code Reference Data Container
{"2.16.840.1.101.3.7.2.16.24", 3, "\x5F\xC1\x23", "\x10\x18"},
{"", 0, "", ""} {"", 0, "", ""}
}; };
static piv_cert_obj_t cert_objects[] = { 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}, {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, 0}, {1, 1, 0, 0, 0},
{1, 1, 0, 0, 1}, {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} {1, 1, 0, 0, 0}
}; };
static piv_pubk_obj_t pubkey_objects[] = { 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}, {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); return do_get_rsa_modulus_length(key);
} }
static CK_ULONG get_public_exponent(EVP_PKEY *key) { static CK_RV get_public_exponent(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
return do_get_public_exponent(key); 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) { 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 ? case CKA_OBJECT_ID: // TODO: how about just storing the OID in DER ?
DBG("OID"); 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); asn1_encode_oid(tmp, tmp, &len);
data = tmp; data = tmp;
break; break;
@@ -374,15 +497,15 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_ISSUER: case CKA_ISSUER:
DBG("ISSUER TODO"); // Default empty DBG("ISSUER TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_SERIAL_NUMBER: case CKA_SERIAL_NUMBER:
DBG("SERIAL NUMBER TODO"); // Default empty DBG("SERIAL NUMBER TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_SUBJECT: case CKA_SUBJECT:
DBG("SUBJECT TODO"); // Required DBG("SUBJECT TODO"); // Required
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_ID: case CKA_ID:
DBG("ID"); DBG("ID");
@@ -393,11 +516,11 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_START_DATE: case CKA_START_DATE:
DBG("START DATE TODO"); // Default empty DBG("START DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_END_DATE: case CKA_END_DATE:
DBG("END DATE TODO"); // Default empty DBG("END DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_MODIFIABLE: case CKA_MODIFIABLE:
DBG("MODIFIABLE"); DBG("MODIFIABLE");
@@ -477,7 +600,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_SUBJECT: case CKA_SUBJECT:
DBG("SUBJECT TODO"); // Default empty DBG("SUBJECT TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_ID: case CKA_ID:
DBG("ID"); DBG("ID");
@@ -488,7 +611,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_SENSITIVE: case CKA_SENSITIVE:
DBG("SENSITIVE TODO"); // Default empty DBG("SENSITIVE TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_DECRYPT: case CKA_DECRYPT:
DBG("DECRYPT"); // Default empy DBG("DECRYPT"); // Default empy
@@ -513,7 +636,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_SIGN_RECOVER: case CKA_SIGN_RECOVER:
DBG("SIGN RECOVER TODO"); // Default empty DBG("SIGN RECOVER TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_DERIVE: case CKA_DERIVE:
DBG("DERIVE"); // Default false DBG("DERIVE"); // Default false
@@ -524,11 +647,11 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_START_DATE: case CKA_START_DATE:
DBG("START DATE TODO"); // Default empty DBG("START DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_END_DATE: case CKA_END_DATE:
DBG("END DATE TODO"); // Default empty DBG("END DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_MODULUS: case CKA_MODULUS:
DBG("MODULUS"); DBG("MODULUS");
@@ -608,10 +731,9 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
if (ul_tmp != CKK_RSA) if (ul_tmp != CKK_RSA)
return CKR_ATTRIBUTE_VALUE_INVALID; 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 (get_public_exponent(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
if (ul_tmp == 0)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
data = (CK_BYTE_PTR) &ul_tmp; data = b_tmp;
break; break;
/* case CKA_PRIVATE_EXPONENT: */ /* 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_EXTRACTABLE: */
case CKA_LOCAL: case CKA_LOCAL:
DBG("LOCAL TODO"); // Required DBG("LOCAL TODO"); // Required
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
/* case CKA_NEVER_EXTRACTABLE: */ /* case CKA_NEVER_EXTRACTABLE: */
/*case CKA_ALWAYS_SENSITIVE:*/ /*case CKA_ALWAYS_SENSITIVE:*/
@@ -719,7 +841,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_SUBJECT: case CKA_SUBJECT:
DBG("SUBJECT TODO"); // Default empty DBG("SUBJECT TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_ID: case CKA_ID:
DBG("ID"); DBG("ID");
@@ -758,11 +880,11 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_START_DATE: case CKA_START_DATE:
DBG("START DATE TODO"); // Default empty DBG("START DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_END_DATE: case CKA_END_DATE:
DBG("END DATE TODO"); // Default empty DBG("END DATE TODO"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_EC_POINT: case CKA_EC_POINT:
DBG("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) if (ul_tmp != CKK_RSA)
return CKR_ATTRIBUTE_VALUE_INVALID; 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; return CKR_FUNCTION_FAILED;
data = b_tmp; data = b_tmp;
break; break;
@@ -842,15 +964,14 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
if (ul_tmp != CKK_RSA) if (ul_tmp != CKK_RSA)
return CKR_ATTRIBUTE_VALUE_INVALID; 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 (get_public_exponent(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
if (ul_tmp == 0)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
data = (CK_BYTE_PTR) &ul_tmp; data = b_tmp;
break; break;
case CKA_LOCAL: case CKA_LOCAL:
DBG("LOCAL TODO"); // Required DBG("LOCAL TODO"); // Required
return CKR_FUNCTION_FAILED; return CKR_ATTRIBUTE_TYPE_INVALID;
case CKA_MODIFIABLE: case CKA_MODIFIABLE:
DBG("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) { CK_ULONG piv_2_ykpiv(piv_obj_id_t id) {
// TODO: add retired keys
switch(id) { switch(id) {
case PIV_CERT_OBJ_X509_PIV_AUTH: case PIV_CERT_OBJ_X509_PIV_AUTH:
return YKPIV_OBJ_AUTHENTICATION; return YKPIV_OBJ_AUTHENTICATION;
@@ -897,6 +1017,66 @@ CK_ULONG piv_2_ykpiv(piv_obj_id_t id) {
case PIV_CERT_OBJ_X509_KM: case PIV_CERT_OBJ_X509_KM:
return YKPIV_OBJ_KEY_MANAGEMENT; 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: case PIV_PVTK_OBJ_PIV_AUTH:
return YKPIV_KEY_AUTHENTICATION; return YKPIV_KEY_AUTHENTICATION;
@@ -909,6 +1089,66 @@ CK_ULONG piv_2_ykpiv(piv_obj_id_t id) {
case PIV_PVTK_OBJ_KM: case PIV_PVTK_OBJ_KM:
return YKPIV_KEY_KEYMGM; 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: default:
return 0ul; return 0ul;
} }
@@ -1063,6 +1303,8 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n,
case CKA_TOKEN: case CKA_TOKEN:
case CKA_LABEL: case CKA_LABEL:
case CKA_SUBJECT: case CKA_SUBJECT:
case CKA_ISSUER:
case CKA_CERTIFICATE_TYPE:
// Ignore other attributes // Ignore other attributes
break; 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) has_params == CK_FALSE)
return CKR_TEMPLATE_INCOMPLETE; 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; 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; return CKR_OK;
} }
CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, 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 *p, CK_ULONG_PTR p_len,
CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) { 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_ULONG i;
CK_BBOOL has_id = CK_FALSE; 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_dp = CK_FALSE;
CK_BBOOL has_dq = CK_FALSE; CK_BBOOL has_dq = CK_FALSE;
CK_BBOOL has_qinv = 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; *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: case CKA_PRIME_1:
has_p = CK_TRUE; has_p = CK_TRUE;
*p = (CK_BYTE_PTR)templ[i].pValue; *p = (CK_BYTE_PTR)templ[i].pValue;
p_len = templ[i].ulValueLen; *p_len = templ[i].ulValueLen;
break; break;
case CKA_PRIME_2: case CKA_PRIME_2:
has_q = CK_TRUE; has_q = CK_TRUE;
*q = (CK_BYTE_PTR)templ[i].pValue; *q = (CK_BYTE_PTR)templ[i].pValue;
q_len = templ[i].ulValueLen; *q_len = templ[i].ulValueLen;
break; break;
case CKA_EXPONENT_1: case CKA_EXPONENT_1:
has_dp = CK_TRUE; has_dp = CK_TRUE;
*dp = (CK_BYTE_PTR)templ[i].pValue; *dp = (CK_BYTE_PTR)templ[i].pValue;
dp_len = templ[i].ulValueLen; *dp_len = templ[i].ulValueLen;
break; break;
case CKA_EXPONENT_2: case CKA_EXPONENT_2:
has_dq = CK_TRUE; has_dq = CK_TRUE;
*dq = (CK_BYTE_PTR)templ[i].pValue; *dq = (CK_BYTE_PTR)templ[i].pValue;
dq_len = templ[i].ulValueLen; *dq_len = templ[i].ulValueLen;
break; break;
case CKA_COEFFICIENT: case CKA_COEFFICIENT:
has_qinv = CK_TRUE; has_qinv = CK_TRUE;
*qinv = (CK_BYTE_PTR)templ[i].pValue; *qinv = (CK_BYTE_PTR)templ[i].pValue;
qinv_len = templ[i].ulValueLen; *qinv_len = templ[i].ulValueLen;
break; 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) has_qinv == CK_FALSE)
return CKR_TEMPLATE_INCOMPLETE; return CKR_TEMPLATE_INCOMPLETE;
if (p_len != 64 && p_len != 128) if (*p_len != 64 && *p_len != 128)
return CKR_ATTRIBUTE_VALUE_INVALID; return CKR_ATTRIBUTE_VALUE_INVALID;
*value_len = p_len;
if (q_len != p_len || dp_len != p_len || if (*q_len != *p_len || *dp_len > *p_len ||
dq_len != p_len || qinv_len != p_len) *dq_len > *p_len || *qinv_len > *p_len)
return CKR_ATTRIBUTE_VALUE_INVALID; return CKR_ATTRIBUTE_VALUE_INVALID;
return CKR_OK; 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_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_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_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 *p, CK_ULONG_PTR p_len,
CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); 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); CK_RV check_delete_cert(CK_OBJECT_HANDLE hObject, CK_BYTE_PTR id);
#endif #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; CK_ULONG e = 0;
RSA *rsa; RSA *rsa;
rsa = EVP_PKEY_get1_RSA(key); rsa = EVP_PKEY_get1_RSA(key);
if (rsa == NULL) 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_free(rsa);
rsa = NULL; 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_RV do_store_pubk(X509 *cert, EVP_PKEY **key);
CK_KEY_TYPE do_get_key_type(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_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_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_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_get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len);
CK_RV do_delete_pubk(EVP_PKEY **key); CK_RV do_delete_pubk(EVP_PKEY **key);
+8
View File
@@ -239,6 +239,9 @@ extern "C" {
#define __PASTE(x,y) x##y #define __PASTE(x,y) x##y
#if defined _WIN32 || _WIN64
#pragma pack(push, cryptoki, 1)
#endif
/* packing defines */ /* packing defines */
//#include "pkcs11p.h" // TODO: msc specific? //#include "pkcs11p.h" // TODO: msc specific?
@@ -309,6 +312,11 @@ struct CK_FUNCTION_LIST {
/* unpack */ /* unpack */
//#include "pkcs11u.h" // TODO: msc specific? //#include "pkcs11u.h" // TODO: msc specific?
#if defined _WIN32 || _WIN64
#pragma pack(pop, cryptoki)
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+25 -20
View File
@@ -108,7 +108,9 @@ typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
/* pack */ /* pack */
//#include "pkcs11p.h" // TODO: msc specific? #if defined _WIN32 || _WIN64
#pragma pack(push, cryptoki, 1)
#endif
typedef struct CK_VERSION { typedef struct CK_VERSION {
CK_BYTE major; /* integer portion of version number */ 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 * PKCS #11 interface. Most of these are place holders for other mechanism
* and will change in the future. * and will change in the future.
*/ */
#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001UL #define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001UL
#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002UL #define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002UL
#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003UL #define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003UL
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004UL #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_128_BIT_RC2_CBC 0x80000005UL
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006UL #define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006UL
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007UL #define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007UL
#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008UL #define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008UL
#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009UL #define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009UL
#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aUL #define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aUL
#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bUL #define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bUL
#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371UL #define CKM_TLS_MASTER_KEY_DERIVE 0x80000371UL
#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372UL #define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372UL
#define CKM_TLS_PRF_GENERAL 0x80000373UL #define CKM_TLS_PRF_GENERAL 0x80000373UL
/* define used to pass in the database key for DSA private keys */ /* define used to pass in the database key for DSA private keys */
#define CKA_NETSCAPE_DB 0xD5A0DB00UL #define CKA_NETSCAPE_DB 0xD5A0DB00UL
#define CKA_NETSCAPE_TRUST 0x80000001UL #define CKA_NETSCAPE_TRUST 0x80000001UL
/* undo packing */
//#include "pkcs11u.h" // TODO: msc specific?
// YUBICO specific attributes // YUBICO specific attributes
#define CKA_TOUCH_PIN_DEFAULT 0x00000000U #define CKA_TOUCH_PIN_DEFAULT 0x00000000U
#define CKA_TOUCH_ALWAYS 0x00000001U #define CKA_TOUCH_ALWAYS 0x00000001U
#define CKA_PIN_ONCE 0x00000002U #define CKA_PIN_ONCE 0x00000002U
#define CKA_PIN_ALWAYS 0x00000004U #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 #endif
+594 -31
View File
@@ -3,54 +3,617 @@
#include <string.h> #include <string.h>
#define MANUFACTURER_ID "Yubico (www.yubico.com)" #include <openssl/rsa.h>
#define YKCS11_DESCRIPTION "PKCS#11 PIV Library (SP-800-73)" #include <openssl/ec.h>
#define CRYPTOKI_VERSION_MAJ 2 #include <openssl/bn.h>
#define CRYPTOKI_VERSION_MIN 40 #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; #define asrt(c, e, m) _asrt(__LINE__, c, e, m);
CK_FUNCTION_LIST_PTR funcs;
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"); fprintf(stderr, "Get function list failed\n");
exit(EXIT_FAILURE); 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) { static void test_lib_info() {
fprintf(stderr, "unexpected manufacturer ID %s\n", info.manufacturerID);
exit(EXIT_FAILURE);
}
if (info.cryptokiVersion.major != CRYPTOKI_VERSION_MAJ || const CK_CHAR_PTR MANUFACTURER_ID = "Yubico (www.yubico.com)";
info.cryptokiVersion.minor != CRYPTOKI_VERSION_MIN ) { const CK_CHAR_PTR YKCS11_DESCRIPTION = "PKCS#11 PIV Library (SP-800-73)";
fprintf(stderr, "unexpected Cryptoki version %d.%d\n", info.cryptokiVersion.major, info.cryptokiVersion.minor); const CK_ULONG CRYPTOKI_VERSION_MAJ = 2;
exit(EXIT_FAILURE); 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) { CK_INFO info;
fprintf(stderr, "unexpected description %s\n", info.libraryDescription);
exit(EXIT_FAILURE); 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) { 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; 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? int tries = 0; // TODO: this is effectively disregarded, should we add a better value in ykpiv_verify?
unsigned char key[24]; unsigned char key[24];
size_t key_len = sizeof(key); size_t key_len = sizeof(key);
unsigned char *term_pin;
ykpiv_rc res;
if (user == CKU_USER) { 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"); DBG("Failed to login");
return CKR_PIN_INCORRECT; return CKR_PIN_INCORRECT;
} }
@@ -58,7 +73,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa,
switch(key_len) { switch(key_len) {
case 2048: case 2048:
if (rsa == CK_TRUE) if (rsa == CK_TRUE)
in_data[4] = YKPIV_ALGO_RSA2048; *in_ptr++ = YKPIV_ALGO_RSA2048;
else else
return CKR_FUNCTION_FAILED; 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) { 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; unsigned char *certptr;
CK_ULONG cert_len; 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) if ((rv = do_check_cert(in, &cert_len)) != CKR_OK)
return rv; return rv;
if (cert_len > 2100) if (cert_len > 3072)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
certptr = certdata; 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; 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_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id,
CK_BYTE_PTR dp, CK_BYTE_PTR dq, CK_BYTE_PTR qinv, CK_BYTE_PTR p, CK_ULONG p_len,
CK_BYTE_PTR ec_data, CK_ULONG elem_len, CK_ULONG vendor_defined) { 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]; CK_BYTE pin_policy;
unsigned char *in_ptr = key_data; CK_BYTE touch_policy;
unsigned char templ[] = {0, YKPIV_INS_IMPORT_KEY, 0, key_id}; CK_BYTE algo;
unsigned char data[0xff]; ykpiv_rc rc;
unsigned long recv_len = sizeof(data);
int sw;
if (elem_len == 128) // TODO: add a flag to check algo type ? if (p == NULL) {
templ[2] = YKPIV_ALGO_RSA2048; if (ec_data_len == 32 || ec_data_len == 31)
else if (elem_len == 64) algo = YKPIV_ALGO_ECCP256;
templ[2] = YKPIV_ALGO_RSA1024; else
else if(elem_len == 32) algo = YKPIV_ALGO_ECCP384;
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;
} }
else if (templ[2] == YKPIV_ALGO_ECCP256) { else if (ec_data == NULL) {
*in_ptr++ = 0x06; if (p_len == 64)
in_ptr += set_length(in_ptr, elem_len); algo = YKPIV_ALGO_RSA1024;
memcpy(in_ptr, ec_data, (size_t)(elem_len)); else
in_ptr += elem_len; algo = YKPIV_ALGO_RSA2048;
} }
else
// 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)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
if (sw != 0x9000) pin_policy = YKPIV_PINPOLICY_DEFAULT;
return CKR_DEVICE_ERROR; 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) { 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_cert = COMMON_token_import_cert;
v.token_import_private_key = COMMON_token_import_private_key; v.token_import_private_key = COMMON_token_import_private_key;
v.token_delete_cert = COMMON_token_delete_cert; v.token_delete_cert = COMMON_token_delete_cert;
v.token_change_pin = YUBICO_token_change_pin;
break; break;
case UNKNOWN: 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_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_model_f)(ykpiv_state *, CK_UTF8CHAR_PTR, CK_ULONG);
typedef CK_RV (*get_t_flags_f)(CK_FLAGS_PTR); 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_serial_f)(CK_CHAR_PTR, CK_ULONG);
typedef CK_RV (*get_t_mechanisms_num_f)(CK_ULONG_PTR); 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); 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_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_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 (*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 // Common token functions below
typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG); 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_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_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, typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE,
CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, 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_BYTE_PTR, CK_ULONG,
CK_ULONG);
typedef CK_RV (*t_delete_cert_f)(ykpiv_state *, 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 // 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_cert_f token_import_cert;
t_import_private_key_f token_import_private_key; t_import_private_key_f token_import_private_key;
t_delete_cert_f token_delete_cert; t_delete_cert_f token_delete_cert;
t_change_pin_f token_change_pin;
} token_vendor_t; } token_vendor_t;
token_vendor_t get_token_vendor(vendor_id_t vid); 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++) for (i = 0; i < len; i++)
if (readers[i] == '\0' && i != len - 1) { 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? if (slots[*n_slots].vid == UNKNOWN) { // TODO: distinguish between tokenless and unsupported?
// Unknown slot, just save what info we have // Unknown slot, just save what info we have
memset(&slots[*n_slots].info, 0, sizeof(CK_SLOT_INFO)); memset(&slots[*n_slots].info, 0, sizeof(CK_SLOT_INFO));
memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription)); memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription));
if (strlen(p) <= sizeof(slots[*n_slots].info.slotDescription)) if (strlen((char *)p) <= sizeof(slots[*n_slots].info.slotDescription))
strncpy(slots[*n_slots].info.slotDescription, p, strlen(p)); memcpy(slots[*n_slots].info.slotDescription, p, strlen((char *)p));
else 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 { else {
// Supported slot // 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)); memset(slots[*n_slots].info.slotDescription, ' ', sizeof(slots[*n_slots].info.slotDescription));
s = slots[*n_slots].info.slotDescription; s = slots[*n_slots].info.slotDescription;
l = sizeof(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)); memset(slots[*n_slots].info.manufacturerID, ' ', sizeof(slots[*n_slots].info.manufacturerID));
s = 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)++; (*n_slots)++;
p += i + 1; p = readers + i + 1;
} }
return CKR_OK; return CKR_OK;
@@ -92,7 +92,7 @@ failure:
CK_RV create_token(ykpiv_state *state, CK_BYTE_PTR p, ykcs11_slot_t *slot) { 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; CK_TOKEN_INFO_PTR t_info;
slot->token = malloc(sizeof(ykcs11_token_t)); // TODO: free 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) if (ykpiv_connect(state, (char *)p) != YKPIV_OK)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
memset(t_info->model, ' ', sizeof(t_info->model)); 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; return CKR_FUNCTION_FAILED;
ykpiv_disconnect(state); }
memset(t_info->serialNumber, ' ', sizeof(t_info->serialNumber)); 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; 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; return CKR_FUNCTION_FAILED;
}
t_info->ulMaxSessionCount = CK_UNAVAILABLE_INFORMATION; 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; t_info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
//ykpiv_get_version(piv_state, buf, sizeof(buf)); // Ignore hardware version, report firmware version
//if (token_vendor.get_token_version(buf, strlen(buf), &ver) != CKR_OK) // TODO: fix this if (token.get_token_version(state, &t_info->firmwareVersion) != CKR_OK) {
// return CKR_FUNCTION_FAILED; ykpiv_disconnect(state);
return CKR_FUNCTION_FAILED;
//t_info->hardwareVersion = ver; // version number of hardware // TODO: fix }
//t_info->firmwareVersion = ver; // version number of firmware // TODO: fix
memset(t_info->utcTime, ' ', sizeof(t_info->utcTime)); // No clock present, clear 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->objects = NULL;
slot->token->n_objects = 0; slot->token->n_objects = 0;
ykpiv_disconnect(state);
return CKR_OK; return CKR_OK;
} }
@@ -170,8 +175,8 @@ void destroy_token(ykcs11_slot_t *slot) {
CK_BBOOL is_valid_key_id(CK_BYTE id) { CK_BBOOL is_valid_key_id(CK_BYTE id) {
// Valid ids are 0, 1, 2, 3 // Valid ids are [0, 23] aka [0x00, 0x17]
if (id > 3) if (id > 23)
return CK_FALSE; return CK_FALSE;
return CK_TRUE; return CK_TRUE;
+78 -22
View File
@@ -51,7 +51,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
) )
{ {
CK_BYTE readers[2048]; CK_BYTE readers[2048];
CK_ULONG len = sizeof(readers); size_t len = sizeof(readers);
DIN; DIN;
@@ -114,7 +114,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)(
CK_INFO_PTR pInfo 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; DIN;
@@ -421,7 +421,36 @@ CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)(
) )
{ {
DIN; 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; DOUT;
return CKR_OK; return CKR_OK;
} }
@@ -438,7 +467,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
CK_RV rv; CK_RV rv;
piv_obj_id_t *cert_ids; piv_obj_id_t *cert_ids;
CK_ULONG i; 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); CK_ULONG cert_len = sizeof(cert_data);
DIN; // TODO: pApplication and Notify DIN; // TODO: pApplication and Notify
@@ -479,7 +508,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
} }
if ((flags & CKF_SERIAL_SESSION) == 0) { 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; 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.state = CKS_RO_PUBLIC_SESSION; // Nobody has logged in, default RW session
} }
session.info.slotID = slotID;
session.info.flags = flags; session.info.flags = flags;
session.info.ulDeviceError = 0; session.info.ulDeviceError = 0;
@@ -731,8 +761,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
return CKR_SESSION_HANDLE_INVALID; return CKR_SESSION_HANDLE_INVALID;
} }
if ((session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these? if (userType == CKU_SO && (session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these?
DBG("Tried to log-in to a read-only session"); DBG("Tried to log-in SO user to a read-only session");
return CKR_SESSION_READ_ONLY_EXISTS; return CKR_SESSION_READ_ONLY_EXISTS;
} }
@@ -858,6 +888,13 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
CK_BYTE_PTR dp; CK_BYTE_PTR dp;
CK_BYTE_PTR dq; CK_BYTE_PTR dq;
CK_BYTE_PTR qinv; 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; CK_ULONG vendor_defined;
token_vendor_t token; token_vendor_t token;
CK_BBOOL is_new; CK_BBOOL is_new;
@@ -972,6 +1009,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
DBG("Unable to store certificate data"); DBG("Unable to store certificate data");
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
} }
*phObject = cert_id;
break; break;
@@ -980,11 +1018,17 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
// Try to parse the key as EC // Try to parse the key as EC
is_rsa = CK_FALSE; 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) { if (rv != CKR_OK) {
// Try to parse the key as RSA // Try to parse the key as RSA
is_rsa = CK_TRUE; 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) { if (rv != CKR_OK) {
DBG("Private key template not valid"); DBG("Private key template not valid");
return rv; return rv;
@@ -997,9 +1041,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
if (is_rsa == CK_TRUE) { if (is_rsa == CK_TRUE) {
DBG("Key is RSA"); DBG("Key is RSA");
rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv, rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object),
NULL, p, p_len,
value_len, vendor_defined); q, q_len,
dp, dp_len,
dq, dq_len,
qinv, qinv_len,
NULL, 0,
vendor_defined);
if (rv != CKR_OK) { if (rv != CKR_OK) {
DBG("Unable to import RSA private key"); DBG("Unable to import RSA private key");
return rv; return rv;
@@ -1007,14 +1056,22 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(
} }
else { else {
DBG("Key is ECDSA"); DBG("Key is ECDSA");
rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL, rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object),
value, NULL, 0,
value_len, vendor_defined); NULL, 0,
NULL, 0,
NULL, 0,
NULL, 0,
ec_data, ec_data_len,
vendor_defined);
if (rv != CKR_OK) { if (rv != CKR_OK) {
DBG("Unable to import ECDSA private key"); DBG("Unable to import ECDSA private key");
return rv; return rv;
} }
} }
*phObject = PIV_PVTK_OBJ_PIV_AUTH + id;
break; break;
default: default:
@@ -1627,8 +1684,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
return CKR_OPERATION_ACTIVE; return CKR_OPERATION_ACTIVE;
} }
if (pMechanism == NULL_PTR || if (pMechanism == NULL_PTR)
hKey == NULL_PTR)
return CKR_ARGUMENTS_BAD; return CKR_ARGUMENTS_BAD;
DBG("Trying to sign some data with mechanism %lu and key %lu", pMechanism->mechanism, hKey); 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); DBG("Sending %lu bytes to sign", ulDataLen);
#if YKCS11_DBG == 1 #if YKCS11_DBG == 1
dump_hex(pData, ulDataLen, stderr, CK_TRUE); dump_data(pData, ulDataLen, stderr, CK_TRUE, format_arg_hex);
#endif #endif
if (is_hashed_mechanism(op_info.mechanism.mechanism) == CK_TRUE) { 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("Using key %lx", op_info.op.sign.key_id);
DBG("After padding and transformation there are %lu bytes", op_info.buf_len); DBG("After padding and transformation there are %lu bytes", op_info.buf_len);
#if YKCS11_DBG == 1 #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 #endif
*pulSignatureLen = sizeof(op_info.buf); *pulSignatureLen = sizeof(op_info.buf);
@@ -1848,7 +1904,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
DBG("Got %lu bytes back", *pulSignatureLen); DBG("Got %lu bytes back", *pulSignatureLen);
#if YKCS11_DBG == 1 #if YKCS11_DBG == 1
dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); dump_data(pSignature, *pulSignatureLen, stderr, CK_TRUE, format_arg_hex);
#endif #endif
if (!is_RSA_mechanism(op_info.mechanism.mechanism)) { 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); DBG("After removing DER encoding %lu", *pulSignatureLen);
#if YKCS11_DBG == 1 #if YKCS11_DBG == 1
dump_hex(pSignature, *pulSignatureLen, stderr, CK_TRUE); dump_data(pSignature, *pulSignatureLen, stderr, CK_TRUE, format_arg_hex);
#endif #endif
} }
@@ -2090,7 +2146,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(
CK_ULONG pvtk_id; CK_ULONG pvtk_id;
CK_ULONG pubk_id; CK_ULONG pubk_id;
piv_obj_id_t *obj_ptr; piv_obj_id_t *obj_ptr;
CK_BYTE cert_data[2100]; CK_BYTE cert_data[3072];
CK_ULONG cert_len; CK_ULONG cert_len;
DIN; 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? 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_PIV_AUTH, // PIV authentication
PIV_DATA_OBJ_X509_CARD_AUTH, // Certificate for card authentication PIV_DATA_OBJ_X509_CARD_AUTH, // card authentication
PIV_DATA_OBJ_X509_DS, // Certificate for digital signature PIV_DATA_OBJ_X509_DS, // digital signature
PIV_DATA_OBJ_X509_KM, // Certificate for key management 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_CCC, // Card capability container
PIV_DATA_OBJ_CHUI, // Cardholder unique id PIV_DATA_OBJ_CHUI, // Cardholder unique id
PIV_DATA_OBJ_CHF, // Cardholder fingerprints PIV_DATA_OBJ_CHF, // Cardholder fingerprints
PIV_DATA_OBJ_SEC_OBJ, // Security object PIV_DATA_OBJ_SEC_OBJ, // Security object
PIV_DATA_OBJ_CHFI, // Cardholder facial images PIV_DATA_OBJ_CHFI, // Cardholder facial images
//PIV_DATA_OBJ_PI, // Cardholder printed information //PIV_DATA_OBJ_PI, // Cardholder printed information
//PIV_DATA_OBJ_DISCOVERY, // Discovery object //PIV_DATA_OBJ_DISCOVERY, // Discovery object
//PIV_DATA_OBJ_HISTORY, // History object //PIV_DATA_OBJ_HISTORY, // History object
/* PIV_DATA_OBJ_RETIRED_X509_1, // Retired certificate for KM 1 //PIV_DATA_OBJ_IRIS_IMAGE, // Cardholder iris images
PIV_DATA_OBJ_RETIRED_X509_2, // Retired certificate for KM 2 //PIV_DATA_OBJ_BITGT, // Biometric information templates group template
PIV_DATA_OBJ_RETIRED_X509_3, // Retired certificate for KM 3 //PIV_DATA_OBJ_SM_SIGNER, // Secure messaging signer
PIV_DATA_OBJ_RETIRED_X509_4, // Retired certificate for KM 4 //PIV_DATA_OBJ_PC_REF_DATA, // Pairing code reference data
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
}; };
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) { 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}; char buf[16];
unsigned int i = 0;
while (i < len && v_str[i] != '.') { if (version == NULL)
v.major *= 10; return CKR_ARGUMENTS_BAD;
v.major += v_str[i++] - '0';
}
i++; if (ykpiv_get_version(state, buf, sizeof(buf)) != YKPIV_OK)
return CKR_FUNCTION_FAILED;
while (i < len && v_str[i] != '.') { version->major = (buf[0] - '0');
v.minor *= 10; version->minor = (buf[2] - '0') * 100 + (buf[4] - '0');
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;
return CKR_OK; 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, 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) { piv_obj_id_t *obj, CK_ULONG_PTR len, CK_ULONG_PTR num_certs) {
CK_BYTE buf[2048]; CK_BYTE buf[2048];
CK_ULONG buf_len; 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 certs[24];
piv_obj_id_t pvtkeys[4]; piv_obj_id_t pvtkeys[24];
piv_obj_id_t pubkeys[4]; piv_obj_id_t pubkeys[24];
CK_ULONG n_cert = 0; CK_ULONG n_cert = 0;
CK_ULONG token_objects_num = neo_token_objects_num;
if (state == NULL || len == NULL_PTR) if (state == NULL || len == NULL_PTR)
return CKR_ARGUMENTS_BAD; 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) if (num_only == CK_FALSE && obj == NULL)
return CKR_ARGUMENTS_BAD; 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); buf_len = sizeof(buf);
if (ykpiv_fetch_object(state, YKPIV_OBJ_AUTHENTICATION, buf, &buf_len) == YKPIV_OK) { if (ykpiv_fetch_object(state, YKPIV_OBJ_AUTHENTICATION, buf, &buf_len) == YKPIV_OK) {
certs[n_cert] = PIV_CERT_OBJ_X509_PIV_AUTH; 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)"); 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); DBG("The total number of objects for this token is %lu", (n_cert * 3) + token_objects_num);
if (num_only == CK_TRUE) { 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) if (*len < (n_cert * 3) + token_objects_num)
return CKR_BUFFER_TOO_SMALL; return CKR_BUFFER_TOO_SMALL;
// Copy mandatory data objects // Copy data objects
memcpy(obj, token_objects, token_objects_num * sizeof(piv_obj_id_t)); 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 // Copy certificates
if (n_cert > 0) { 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; 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_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_flags(CK_FLAGS_PTR flags);
CK_RV YUBICO_get_token_serial(CK_CHAR_PTR str, CK_ULONG len); 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_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_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_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_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_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_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 #endif