From 4f12dc41e9107169871ce719f7354c3df70b7e27 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Fri, 23 Oct 2015 19:43:36 +0200 Subject: [PATCH 1/5] YKCS11: Added raw certificate extraction. --- ykcs11/objects.c | 55 ++++++++++++++++++++++++------------------ ykcs11/openssl_utils.c | 20 +++++++++++++++ ykcs11/openssl_utils.h | 1 + 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/ykcs11/objects.c b/ykcs11/objects.c index 3767ca9..fa7f09b 100644 --- a/ykcs11/objects.c +++ b/ykcs11/objects.c @@ -233,6 +233,10 @@ static CK_RV get_curve_parameters(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR return do_get_curve_parameters(key, data, len); } +static CK_RV get_raw_cert(X509 *cert, CK_BYTE_PTR data, CK_ULONG_PTR len) { + return do_get_raw_cert(cert, data, len); +} + /* Get data object attribute */ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; @@ -319,31 +323,32 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { /* Get certificate object attribute */ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; - CK_BYTE tmp[64]; + CK_BYTE b_tmp[1024]; + CK_ULONG ul_tmp; CK_ULONG len = 0; DBG(("For certificate object %lu, get ", obj)); - switch (template->type) { // TODO: is this needed here? or is it enough ot have one a "level" above? + switch (template->type) { case CKA_CLASS: DBG(("CLASS")); - len = 1; - tmp[0] = CKO_CERTIFICATE; - data = tmp; + len = sizeof(CK_ULONG); + ul_tmp = CKO_CERTIFICATE; + data = (CK_BYTE_PTR) &ul_tmp; break; case CKA_TOKEN: // Technically all these objects are token objects DBG(("TOKEN")); - len = 1; - tmp[0] = piv_objects[obj].token; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].token; + data = b_tmp; break; case CKA_PRIVATE: DBG(("PRIVATE")); - len = 1; - tmp[0] = piv_objects[obj].private; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].private; + data = b_tmp; break; case CKA_LABEL: @@ -353,14 +358,18 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { break; case CKA_VALUE: - DBG(("VALUE TODO")); - return CKR_FUNCTION_FAILED; + DBG(("VALUE")); + len = sizeof(b_tmp); + if (get_raw_cert(cert_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) + return CKR_FUNCTION_FAILED; + data = b_tmp; + break; case CKA_CERTIFICATE_TYPE: DBG(("CERTIFICATE TYPE")); - len = 1; - tmp[0] = CKC_X_509; // Support only X.509 certs - data = tmp; + len = sizeof(CK_ULONG); + ul_tmp = CKC_X_509; // Support only X.509 certs + data = (CK_BYTE_PTR) ul_tmp; break; case CKA_ISSUER: @@ -377,9 +386,9 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_ID: DBG(("ID")); - len = 1; - tmp[0] = piv_objects[obj].sub_id; - data = tmp; + len = sizeof(CK_BYTE); + b_tmp[0] = piv_objects[obj].sub_id; + data = b_tmp; break; case CKA_START_DATE: @@ -392,9 +401,9 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { case CKA_MODIFIABLE: DBG(("MODIFIABLE")); - len = 1; - tmp[0] = piv_objects[obj].modifiable; - data = tmp; + len = sizeof(CK_BBOOL); + b_tmp[0] = piv_objects[obj].modifiable; + data = b_tmp; break; default: // TODO: there are other attributes for a (x509) certificate @@ -666,7 +675,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_BYTE_PTR data; CK_BYTE b_tmp[1024]; - CK_ULONG ul_tmp; // TODO: fix elsewhere too + CK_ULONG ul_tmp; CK_ULONG len = 0; DBG(("For public key object %lu, get ", obj)); diff --git a/ykcs11/openssl_utils.c b/ykcs11/openssl_utils.c index 5d59599..8b68c2d 100644 --- a/ykcs11/openssl_utils.c +++ b/ykcs11/openssl_utils.c @@ -236,6 +236,26 @@ CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len) { return CKR_OK; } +CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { + + CK_BYTE_PTR p; + int len; + + len = i2d_X509(cert, NULL); + + if (len < 0) + return CKR_FUNCTION_FAILED; + + if ((CK_ULONG)len > *out_len) + return CKR_BUFFER_TOO_SMALL; + + p = out; + if ((*out_len = i2d_X509(cert, &p)) == 0) + return CKR_FUNCTION_FAILED; + + return CKR_OK; +} + CK_RV free_cert(X509 *cert) { X509_free((X509 *) cert); diff --git a/ykcs11/openssl_utils.h b/ykcs11/openssl_utils.h index 8ded6f2..09f6482 100644 --- a/ykcs11/openssl_utils.h +++ b/ykcs11/openssl_utils.h @@ -13,6 +13,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert); CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV do_check_cert(CK_BYTE_PTR in, CK_ULONG_PTR cert_len); +CK_RV do_get_raw_cert(X509 *cert, CK_BYTE_PTR out, CK_ULONG_PTR out_len); CK_RV free_cert(X509 *cert); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); From a9ddf3e3b231787edae6bb8c75c7082e2f2547c2 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Tue, 27 Oct 2015 17:33:30 +0100 Subject: [PATCH 2/5] 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; From b7c0e8ea6bb1cdb294213293ba3cd40e2321bb81 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 28 Oct 2015 11:33:20 +0100 Subject: [PATCH 3/5] YKCS11: added support for touch and PIN policy during generate. --- ykcs11/mechanisms.c | 8 ++++++-- ykcs11/token_vendors.c | 44 ++++++++++++++++++++++++++++++++---------- ykcs11/token_vendors.h | 2 +- ykcs11/ykcs11.c | 2 +- ykcs11/ykcs11.h | 8 ++++---- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/ykcs11/mechanisms.c b/ykcs11/mechanisms.c index b7b4886..de642ff 100644 --- a/ykcs11/mechanisms.c +++ b/ykcs11/mechanisms.c @@ -420,7 +420,7 @@ CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG default: DBG(("Invalid attribute %lx in public key template", templ[i].type)); - return CKR_ATTRIBUTE_VALUE_INVALID; + return CKR_ATTRIBUTE_TYPE_INVALID; } } @@ -433,6 +433,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG CK_ULONG i; op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism); + op_info->op.gen.vendor_defined = 0; for (i = 0; i < n; i++) { switch (templ[i].type) { @@ -473,6 +474,9 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG op_info->op.gen.key_id = PIV_PVTK_OBJ_PIV_AUTH + *((CK_BYTE_PTR)templ[i].pValue); break; + case CKA_VENDOR_DEFINED: + op_info->op.gen.vendor_defined = (*((CK_ULONG_PTR)templ[i].pValue)); + case CKA_SENSITIVE: case CKA_DECRYPT: case CKA_UNWRAP: @@ -485,7 +489,7 @@ CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG default: DBG(("Invalid attribute %lx in private key template", templ[i].type)); - return CKR_ATTRIBUTE_VALUE_INVALID; + return CKR_ATTRIBUTE_TYPE_INVALID; } } diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 99dfd7e..0fd7198 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -31,9 +31,11 @@ static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CH return CKR_OK; } -static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE key, CK_ULONG key_len) { +static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, + CK_BYTE key, CK_ULONG key_len, CK_ULONG vendor_defined) { // TODO: make a function in ykpiv for this - unsigned char in_data[5]; + unsigned char in_data[11]; + unsigned char *in_ptr = in_data; unsigned char data[1024]; unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0}; unsigned char *certptr; @@ -45,10 +47,10 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE templ[3] = key; - in_data[0] = 0xac; - in_data[1] = 3; - in_data[2] = 0x80; - in_data[3] = 1; + *in_ptr++ = 0xac; + *in_ptr++ = 3; + *in_ptr++ = 0x80; + *in_ptr++ = 1; switch(key_len) { case 2048: @@ -61,7 +63,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE case 1024: if (rsa == CK_TRUE) - in_data[4] = YKPIV_ALGO_RSA1024; + *in_ptr++ = YKPIV_ALGO_RSA1024; else return CKR_FUNCTION_FAILED; @@ -69,7 +71,7 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE case 256: if (rsa == CK_FALSE) - in_data[4] = YKPIV_ALGO_ECCP256; + *in_ptr++ = YKPIV_ALGO_ECCP256; else return CKR_FUNCTION_FAILED; @@ -78,8 +80,30 @@ static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE default: return CKR_FUNCTION_FAILED; } - //DBG(("Generating key %x with algorithm %u and length %lu", templ[3], in_data[4], key_len)); - if(ykpiv_transfer_data(state, templ, in_data, sizeof(in_data), data, &recv_len, &sw) != YKPIV_OK || + // PIN policy and touch + if (vendor_defined != 0) { + if (vendor_defined & CKA_PIN_ONCE) { + in_data[1] += 3; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ONCE; + } + else if (vendor_defined & CKA_PIN_ALWAYS) { + in_data[1] += 3; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ALWAYS; + } + + if (vendor_defined & CKA_TOUCH_ALWAYS) { + in_data[1] += 3; + *in_ptr++ = YKPIV_TOUCHPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_TOUCHPOLICY_ALWAYS; + } + } + + if(ykpiv_transfer_data(state, templ, in_data, in_ptr - in_data, data, &recv_len, &sw) != YKPIV_OK || sw != 0x9000) return CKR_DEVICE_ERROR; diff --git a/ykcs11/token_vendors.h b/ykcs11/token_vendors.h index c59f376..9513063 100644 --- a/ykcs11/token_vendors.h +++ b/ykcs11/token_vendors.h @@ -21,7 +21,7 @@ typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PT // Common token functions below typedef CK_RV (*t_login_f)(ykpiv_state *, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG); -typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG); +typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG, CK_ULONG); typedef CK_RV (*t_import_cert_f)(ykpiv_state *, CK_ULONG, CK_BYTE_PTR); typedef CK_RV (*t_import_private_key_f)(ykpiv_state *, CK_BYTE, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_BYTE_PTR, CK_ULONG, CK_ULONG); diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index c026e28..4025524 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -2053,7 +2053,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)( token = get_token_vendor(session.slot->token->vid); - if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len)) != CKR_OK) { + if ((rv = token.token_generate_key(piv_state, op_info.op.gen.rsa, piv_2_ykpiv(op_info.op.gen.key_id), op_info.op.gen.key_len, op_info.op.gen.vendor_defined)) != CKR_OK) { DBG(("Unable to generate key pair")); return rv; } diff --git a/ykcs11/ykcs11.h b/ykcs11/ykcs11.h index 0793432..e29b24b 100644 --- a/ykcs11/ykcs11.h +++ b/ykcs11/ykcs11.h @@ -28,7 +28,6 @@ typedef struct { ykcs11_slot_t *slot; } ykcs11_session_t; - typedef enum { YKCS11_NOOP, YKCS11_GEN, @@ -38,9 +37,10 @@ typedef enum { } ykcs11_op_type_t; typedef struct { - CK_BBOOL rsa; // RSA or EC key - CK_BYTE key_id; // Key id - CK_ULONG key_len; // Length in bits + CK_BBOOL rsa; // RSA or EC key + CK_BYTE key_id; // Key id + CK_ULONG key_len; // Length in bits + CK_ULONG vendor_defined; // Additional parameters (touch and PIN policy) } gen_info_t; typedef struct { From 12e05944063f53e15d157282f7030190349eaa39 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 28 Oct 2015 11:36:55 +0100 Subject: [PATCH 4/5] Indent. --- ykcs11/token_vendors.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 0fd7198..6fc452d 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -227,14 +227,14 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT // 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; + *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; + *in_ptr++ = YKPIV_PINPOLICY_TAG; + *in_ptr++ = 0x01; + *in_ptr++ = YKPIV_PINPOLICY_ALWAYS; } if (vendor_defined & CKA_TOUCH_ALWAYS) { @@ -255,7 +255,7 @@ CK_RV COMMON_token_import_private_key(ykpiv_state *state, CK_BYTE key_id, CK_BYT } token_vendor_t get_token_vendor(vendor_id_t vid) { - token_vendor_t v; + token_vendor_t v; switch (vid) { case YUBICO: From e6bca9b332ce537401043b2af3d4b9ba056bd847 Mon Sep 17 00:00:00 2001 From: Alessio Di Mauro Date: Wed, 28 Oct 2015 11:43:41 +0100 Subject: [PATCH 5/5] YKCS11: Suppress some warnings. --- ykcs11/token_vendors.c | 3 +++ ykcs11/ykcs11.c | 3 +++ ykcs11/yubico_token.c | 1 + 3 files changed, 7 insertions(+) diff --git a/ykcs11/token_vendors.c b/ykcs11/token_vendors.c index 6fc452d..c185f7e 100644 --- a/ykcs11/token_vendors.c +++ b/ykcs11/token_vendors.c @@ -4,6 +4,9 @@ #include #include "debug.h" +#include +#include "../tool/util.h" + static CK_RV COMMON_token_login(ykpiv_state *state, CK_USER_TYPE user, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len) { int tries = 0; // TODO: this is effectively disregarded, should we add a better value in ykpiv_verify? diff --git a/ykcs11/ykcs11.c b/ykcs11/ykcs11.c index 4025524..32715c0 100644 --- a/ykcs11/ykcs11.c +++ b/ykcs11/ykcs11.c @@ -10,6 +10,9 @@ #include "openssl_types.h" #include "debug.h" +#include +#include "../tool/util.h" + #define YKCS11_MANUFACTURER "Yubico (www.yubico.com)" #define YKCS11_LIBDESC "PKCS#11 PIV Library (SP-800-73)" diff --git a/ykcs11/yubico_token.c b/ykcs11/yubico_token.c index f2df6e2..11a8897 100644 --- a/ykcs11/yubico_token.c +++ b/ykcs11/yubico_token.c @@ -2,6 +2,7 @@ #include "pkcs11.h" #include #include "debug.h" +#include "objects.h" #define YUBICO_MECHANISMS_NUM 5