From a9ddf3e3b231787edae6bb8c75c7082e2f2547c2 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 27 Oct 2015 17:33:30 +0100 Subject: [PATCH] Added support for touch and change policy during key import. --- ykcs11/mechanisms.c | 1 + ykcs11/objects.c | 16 ++++++++++++++-- ykcs11/objects.h | 4 ++-- ykcs11/pkcs11t.h | 7 +++++++ ykcs11/token_vendors.c | 28 ++++++++++++++++++++++++---- ykcs11/token_vendors.h | 2 +- ykcs11/ykcs11.c | 9 +++++---- ykcs11/ykcs11.h | 2 +- 8 files changed, 55 insertions(+), 14 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index ce1ef72..b7b4886 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -163,6 +163,7 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info) { case CKM_RSA_X_509: case CKM_ECDSA: // No hash required for this mechanism + op_info->op.sign.md_ctx = NULL; return CKR_OK; case CKM_SHA1_RSA_PKCS: diff --git a/ykcs11/objects.c b/ykcs11/objects.c index fa7f09b..99e6519 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -1063,7 +1063,7 @@ CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, } 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_BYTE_PTR *value, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) { CK_ULONG i; CK_BBOOL has_id = CK_FALSE; @@ -1073,6 +1073,8 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR ec_params; CK_ULONG ec_params_len; + *vendor_defined = 0; + for (i = 0; i < n; i++) { switch (templ[i].type) { case CKA_CLASS: @@ -1108,6 +1110,10 @@ CK_RV check_create_ec_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, break; + case CKA_VENDOR_DEFINED: + *vendor_defined = *((CK_ULONG_PTR)templ[i].pValue); + break; + case CKA_TOKEN: case CKA_LABEL: case CKA_SUBJECT: @@ -1138,7 +1144,7 @@ CK_RV check_create_ec_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 *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len) { + CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined) { CK_ULONG i; CK_BBOOL has_id = CK_FALSE; @@ -1154,6 +1160,8 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_ULONG dq_len; CK_ULONG qinv_len; + *vendor_defined = 0; + for (i = 0; i < n; i++) { switch (templ[i].type) { case CKA_CLASS: @@ -1217,6 +1225,10 @@ CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, break; + case CKA_VENDOR_DEFINED: + *vendor_defined = *((CK_ULONG_PTR)templ[i].pValue); + break; + case CKA_TOKEN: case CKA_LABEL: case CKA_SUBJECT: diff --git a/ykcs11/objects.h b/ykcs11/objects.h index 892cb54..860f3a8 100644 --- a/ykcs11/objects.h +++ b/ykcs11/objects.h @@ -15,10 +15,10 @@ CK_RV store_cert(piv_obj_id_t cert_id, CK_BYTE_PTR data, CK_ULONG len); CK_RV check_create_cert(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *value, CK_ULONG_PTR cert_len); 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_BYTE_PTR *value, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); CK_RV check_create_rsa_key(CK_ATTRIBUTE_PTR templ, CK_ULONG n, CK_BYTE_PTR id, CK_BYTE_PTR *p, CK_BYTE_PTR *q, CK_BYTE_PTR *dp, - CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len); + CK_BYTE_PTR *dq, CK_BYTE_PTR *qinv, CK_ULONG_PTR value_len, CK_ULONG_PTR vendor_defined); #endif diff --git a/ykcs11/pkcs11t.h b/ykcs11/pkcs11t.h index f793cfe..bcdd9e0 100644 --- a/ykcs11/pkcs11t.h +++ b/ykcs11/pkcs11t.h @@ -1183,4 +1183,11 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; /* undo packing */ //#include "pkcs11u.h" // TODO: msc specific? +// YUBICO specific attributes +#define CKA_TOUCH_PIN_DEFAULT 0x00000000U +#define CKA_TOUCH_ALWAYS 0x00000001U +#define CKA_PIN_ONCE 0x00000002U +#define CKA_PIN_ALWAYS 0x00000004U + + #endif diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 4cd4bf7..99dfd7e 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -151,7 +151,7 @@ static CK_RV COMMON_token_import_cert(ykpiv_state *state, CK_ULONG cert_id, CK_B CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYTE_PTR p, CK_BYTE_PTR q, CK_BYTE_PTR dp, CK_BYTE_PTR dq, CK_BYTE_PTR qinv, - CK_BYTE_PTR ec_data, CK_ULONG elem_len) { + CK_BYTE_PTR ec_data, CK_ULONG elem_len, CK_ULONG vendor_defined) { unsigned char key_data[1024]; unsigned char *in_ptr = key_data; @@ -193,17 +193,37 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT memcpy(in_ptr, qinv, (size_t)(elem_len)); in_ptr += elem_len; } - else if(templ[2] == YKPIV_ALGO_ECCP256) { + else if (templ[2] == YKPIV_ALGO_ECCP256) { *in_ptr++ = 0x06; in_ptr += set_length(in_ptr, elem_len); memcpy(in_ptr, ec_data, (size_t)(elem_len)); in_ptr += elem_len; } - if(ykpiv_transfer_data(state, templ, key_data, in_ptr - key_data, data, &recv_len, &sw) != YKPIV_OK) + // 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; - if(sw != 0x9000) + if (sw != 0x9000) return CKR_DEVICE_ERROR; return CKR_OK; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index ed555b9..c59f376 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -24,7 +24,7 @@ typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULON typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, - CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG); + CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG); // TODO: replace all the common calls with functions defined in .c that use libykpiv diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index fa67b6c..c026e28 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -854,6 +854,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( CK_BYTE_PTR dp; CK_BYTE_PTR dq; CK_BYTE_PTR qinv; + CK_ULONG vendor_defined; token_vendor_t token; CK_BBOOL is_new; CK_BBOOL is_rsa; @@ -974,11 +975,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( // Try to parse the key as EC is_rsa = CK_FALSE; - rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len); + rv = check_create_ec_key(pTemplate, ulCount, &id, &value, &value_len, &vendor_defined); if (rv != CKR_OK) { // Try to parse the key as RSA is_rsa = CK_TRUE; - rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len); + rv = check_create_rsa_key(pTemplate, ulCount, &id, &p, &q, &dp, &dq, &qinv, &value_len, &vendor_defined); if (rv != CKR_OK) { DBG(("Private key template not valid")); return rv; @@ -993,7 +994,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( DBG(("Key is RSA")); rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), p, q, dp, dq, qinv, NULL, - value_len); + value_len, vendor_defined); if (rv != CKR_OK) { DBG(("Unable to import RSA private key")); return rv; @@ -1003,7 +1004,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)( DBG(("Key is ECDSA")); rv = token.token_import_private_key(piv_state, piv_2_ykpiv(object), NULL, NULL, NULL, NULL, NULL, value, - value_len); + value_len, vendor_defined); if (rv != CKR_OK) { DBG(("Unable to import ECDSA private key")); return rv; diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 057c155..0793432 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -6,7 +6,7 @@ #include "openssl_types.h" #include "vendors.h" -#define YKCS11_OP_BUFSIZE 4096 +#define YKCS11_OP_BUFSIZE 4096 typedef struct { vendor_id_t vid;