First stab at key generation.

This commit is contained in:
Alessio Di Mauro
2015-08-07 17:09:09 +02:00
parent 6f0a9e7a09
commit 5bef13acec
10 changed files with 428 additions and 110 deletions
+3 -3
View File
@@ -1,15 +1,15 @@
#ifndef DEBUG_H #ifndef DEBUG_H
#define DEBUG_H #define DEBUG_H
#define YKCS11_DBG 1 // General debug, must be either 1 or 0
#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0
#define D(x) do { \ #define D(x) do { \
printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \ printf ("debug: %s:%d (%s): ", __FILE__, __LINE__, __FUNCTION__); \
printf x; \ printf x; \
printf ("\n"); \ printf ("\n"); \
} while (0) } while (0)
#define YKCS11_DBG 0 // General debug, must be either 1 or 0
#define YKCS11_DINOUT 0 // Function in/out debug, must be either 1 or 0
#if YKCS11_DBG #if YKCS11_DBG
#include <stdio.h> #include <stdio.h>
#define DBG(x) D(x); #define DBG(x) D(x);
+161 -2
View File
@@ -17,6 +17,13 @@ static const CK_MECHANISM_TYPE sign_mechanisms[] = {
CKM_ECDSA_SHA1 CKM_ECDSA_SHA1
}; };
// Supported mechanisms for key pair generation
static const CK_MECHANISM_TYPE generation_mechanisms[] = {
CKM_RSA_PKCS_KEY_PAIR_GEN,
//CKM_ECDSA_KEY_PAIR_GEN, Deperecated
CKM_EC_KEY_PAIR_GEN
};
CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m) { CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m) {
CK_ULONG i; CK_ULONG i;
@@ -40,9 +47,9 @@ CK_RV check_sign_mechanism(const ykcs11_session_t *s, const CK_MECHANISM_PTR m)
if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK) if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK)
return CKR_MECHANISM_INVALID; return CKR_MECHANISM_INVALID;
// TODO: also check that parametes make sense if any? // TODO: also check that parametes make sense if any? And key size is in [min max]
CKR_OK; return CKR_OK;
} }
@@ -289,3 +296,155 @@ CK_RV apply_sign_mechanism_finalize(op_info_t *op_info) {
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
} }
} }
CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m) {
CK_ULONG i;
CK_BBOOL supported = CK_FALSE;
token_vendor_t token;
CK_MECHANISM_INFO info;
// Check if the mechanism is supported by the module
for (i = 0; i < sizeof(generation_mechanisms) / sizeof(CK_MECHANISM_TYPE); i++) {
if (m->mechanism == generation_mechanisms[i]) {
supported = CK_TRUE;
break;
}
}
if (supported == CK_FALSE)
return CKR_MECHANISM_INVALID;
// Check if the mechanism is supported by the token
token = get_token_vendor(s->slot->token->vid);
if (token.get_token_mechanism_info(m->mechanism, &info) != CKR_OK)
return CKR_MECHANISM_INVALID;
// TODO: also check that parametes make sense if any? And key size is in [min max]
return CKR_OK;
}
CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) {
CK_ULONG i;
CK_BBOOL rsa_mechanism;
op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism);
for (i = 0; i < n; i++) {
switch (templ[i].type) {
case CKA_CLASS:
if (*((CK_ULONG_PTR) templ[i].pValue) != CKO_PUBLIC_KEY)
return CKR_TEMPLATE_INCONSISTENT;
break;
case CKA_KEY_TYPE:
if ((op_info->op.gen.rsa == CK_TRUE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_RSA) ||
(op_info->op.gen.rsa == CK_FALSE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_ECDSA))
return CKR_TEMPLATE_INCONSISTENT;
break;
case CKA_PUBLIC_EXPONENT:
if (op_info->op.gen.rsa == CK_FALSE)
return CKR_MECHANISM_PARAM_INVALID;
// Only support F4
if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, "\x01\x00\x01", 3) != 0)
return CKR_MECHANISM_PARAM_INVALID;
break;
case CKA_MODULUS_BITS:
if (op_info->op.gen.rsa == CK_FALSE)
return CKR_MECHANISM_PARAM_INVALID;
if (*((CK_ULONG_PTR)templ[i].pValue) != 1024 &&
*((CK_ULONG_PTR) templ[i].pValue) != 2048) // TODO: make define?
return CKR_MECHANISM_PARAM_INVALID;
op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); // TODO: check length?
break;
case CKA_ID:
// TODO: get pvt key with attributed id and store it's id into op_info
case CKA_TOKEN:
case CKA_ENCRYPT:
case CKA_VERIFY:
case CKA_WRAP:
// Ignore these attributes for now
break;
default:
return CKR_MECHANISM_PARAM_INVALID;
}
}
return CKR_OK;
}
CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n) {
CK_ULONG i;
CK_BBOOL rsa_mechanism;
op_info->op.gen.rsa = is_RSA_mechanism(op_info->mechanism.mechanism);
for (i = 0; i < n; i++) {
switch (templ[i].type) {
case CKA_CLASS:
if (*((CK_ULONG_PTR)templ[i].pValue) != CKO_PRIVATE_KEY)
return CKR_TEMPLATE_INCONSISTENT;
break;
case CKA_KEY_TYPE:
if ((op_info->op.gen.rsa == CK_TRUE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_RSA) ||
(op_info->op.gen.rsa == CK_FALSE && (*((CK_KEY_TYPE *)templ[i].pValue)) != CKK_ECDSA))
return CKR_TEMPLATE_INCONSISTENT;
break;
case CKA_PUBLIC_EXPONENT:
if (op_info->op.gen.rsa == CK_FALSE)
return CKR_MECHANISM_PARAM_INVALID;
// Only support F4
if (templ[i].ulValueLen != 3 || memcmp((CK_BYTE_PTR)templ[i].pValue, "\x01\x00\x01", 3) != 0)
return CKR_MECHANISM_PARAM_INVALID;
break;
case CKA_MODULUS_BITS:
if (op_info->op.gen.rsa == CK_FALSE)
return CKR_MECHANISM_PARAM_INVALID;
if (*((CK_ULONG_PTR)templ[i].pValue) != 1024 &&
*((CK_ULONG_PTR) templ[i].pValue) != 2048) // TODO: make define?
return CKR_MECHANISM_PARAM_INVALID;
op_info->op.gen.key_len = *((CK_ULONG_PTR) templ[i].pValue); // TODO: check length?
break;
case CKA_SENSITIVE:
case CKA_DECRYPT:
case CKA_UNWRAP:
case CKA_SIGN:
case CKA_PRIVATE:
case CKA_TOKEN:
// Ignore these attributes for now
break;
default:
return CKR_MECHANISM_PARAM_INVALID;
}
}
return CKR_OK;
}
+4
View File
@@ -12,4 +12,8 @@ CK_RV apply_sign_mechanism_init(op_info_t *op_info);
CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len); CK_RV apply_sign_mechanism_update(op_info_t *op_info, CK_BYTE_PTR in, CK_ULONG in_len);
CK_RV apply_sign_mechanism_finalize(op_info_t *op_info); CK_RV apply_sign_mechanism_finalize(op_info_t *op_info);
CK_RV check_generation_mechanism(const ykcs11_session_t *s, CK_MECHANISM_PTR m);
CK_RV check_pubkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n);
CK_RV check_pvtkey_template(op_info_t *op_info, CK_ATTRIBUTE_PTR templ, CK_ULONG n);
#endif #endif
+65 -65
View File
@@ -264,7 +264,7 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
switch (template->type) { switch (template->type) {
case CKA_CLASS: case CKA_CLASS:
DBG(("CLASS\n")); DBG(("CLASS"));
len = 1; len = 1;
tmp[0] = CKO_DATA; tmp[0] = CKO_DATA;
data = tmp; data = tmp;
@@ -272,51 +272,51 @@ CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_TOKEN: case CKA_TOKEN:
// Technically all these objects are token objects // Technically all these objects are token objects
DBG(("TOKEN\n")); DBG(("TOKEN"));
len = 1; len = 1;
tmp[0] = piv_objects[obj].token; tmp[0] = piv_objects[obj].token;
data = tmp; data = tmp;
break; break;
case CKA_PRIVATE: case CKA_PRIVATE:
DBG(("PRIVATE\n")); DBG(("PRIVATE"));
len = 1; len = 1;
tmp[0] = piv_objects[obj].private; tmp[0] = piv_objects[obj].private;
data = tmp; data = tmp;
break; break;
case CKA_LABEL: case CKA_LABEL:
DBG(("LABEL\n")); DBG(("LABEL"));
len = strlen(piv_objects[obj].label) + 1; len = strlen(piv_objects[obj].label) + 1;
data = piv_objects[obj].label; data = piv_objects[obj].label;
break; break;
case CKA_APPLICATION: case CKA_APPLICATION:
DBG(("APPLICATION\n")); DBG(("APPLICATION"));
len = strlen(piv_objects[obj].label) + 1; len = strlen(piv_objects[obj].label) + 1;
data = piv_objects[obj].label; data = piv_objects[obj].label;
break; break;
case CKA_VALUE: // TODO: this can be done with -r and -d|-a case CKA_VALUE: // TODO: this can be done with -r and -d|-a
DBG(("VALUE TODO!!!\n")); DBG(("VALUE TODO!!!"));
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
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\n")); DBG(("OID"));
strcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid); strcpy((char *)tmp, data_objects[piv_objects[obj].sub_id].oid);
asn1_encode_oid(tmp, tmp, &len); asn1_encode_oid(tmp, tmp, &len);
data = tmp; data = tmp;
break; break;
case CKA_MODIFIABLE: case CKA_MODIFIABLE:
DBG(("MODIFIABLE\n")); DBG(("MODIFIABLE"));
len = 1; len = 1;
tmp[0] = piv_objects[obj].modifiable; tmp[0] = piv_objects[obj].modifiable;
data = tmp; data = tmp;
break; break;
default: default:
DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type));
template->ulValueLen = CK_UNAVAILABLE_INFORMATION; template->ulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_ATTRIBUTE_TYPE_INVALID; return CKR_ATTRIBUTE_TYPE_INVALID;
} }
@@ -347,7 +347,7 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
switch (template->type) { // TODO: is this needed here? or is it enough ot have one a "level" above? switch (template->type) { // TODO: is this needed here? or is it enough ot have one a "level" above?
case CKA_CLASS: case CKA_CLASS:
DBG(("CLASS\n")); DBG(("CLASS"));
len = 1; len = 1;
tmp[0] = CKO_CERTIFICATE; tmp[0] = CKO_CERTIFICATE;
data = tmp; data = tmp;
@@ -355,72 +355,72 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_TOKEN: case CKA_TOKEN:
// Technically all these objects are token objects // Technically all these objects are token objects
DBG(("TOKEN\n")); DBG(("TOKEN"));
len = 1; len = 1;
tmp[0] = piv_objects[obj].token; tmp[0] = piv_objects[obj].token;
data = tmp; data = tmp;
break; break;
case CKA_PRIVATE: case CKA_PRIVATE:
DBG(("PRIVATE\n")); DBG(("PRIVATE"));
len = 1; len = 1;
tmp[0] = piv_objects[obj].private; tmp[0] = piv_objects[obj].private;
data = tmp; data = tmp;
break; break;
case CKA_LABEL: case CKA_LABEL:
DBG(("LABEL\n")); DBG(("LABEL"));
len = strlen(piv_objects[obj].label) + 1; len = strlen(piv_objects[obj].label) + 1;
data = piv_objects[obj].label; data = piv_objects[obj].label;
break; break;
case CKA_VALUE: case CKA_VALUE:
DBG(("VALUE TODO\n")); DBG(("VALUE TODO"));
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_CERTIFICATE_TYPE: case CKA_CERTIFICATE_TYPE:
DBG(("CERTIFICATE TYPE\n")); DBG(("CERTIFICATE TYPE"));
len = 1; len = 1;
tmp[0] = CKC_X_509; // Support only X.509 certs tmp[0] = CKC_X_509; // Support only X.509 certs
data = tmp; data = tmp;
break; break;
case CKA_ISSUER: case CKA_ISSUER:
DBG(("ISSUER TODO\n")); // Default empty DBG(("ISSUER TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_SERIAL_NUMBER: case CKA_SERIAL_NUMBER:
DBG(("SERIAL NUMBER TODO\n")); // Default empty DBG(("SERIAL NUMBER TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_SUBJECT: case CKA_SUBJECT:
DBG(("SUBJECT TODO\n")); // Required DBG(("SUBJECT TODO")); // Required
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_ID: case CKA_ID:
DBG(("ID\n")); DBG(("ID"));
len = 1; len = 1;
tmp[0] = piv_objects[obj].sub_id; tmp[0] = piv_objects[obj].sub_id;
data = tmp; data = tmp;
break; break;
case CKA_START_DATE: case CKA_START_DATE:
DBG(("START DATE TODO\n")); // Default empty DBG(("START DATE TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_END_DATE: case CKA_END_DATE:
DBG(("END DATE TODO\n")); // Default empty DBG(("END DATE TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_MODIFIABLE: case CKA_MODIFIABLE:
DBG(("MODIFIABLE\n")); DBG(("MODIFIABLE"));
len = 1; len = 1;
tmp[0] = piv_objects[obj].modifiable; tmp[0] = piv_objects[obj].modifiable;
data = tmp; data = tmp;
break; break;
default: // TODO: there are other attributes for a (x509) certificate default: // TODO: there are other attributes for a (x509) certificate
DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type));
template->ulValueLen = CK_UNAVAILABLE_INFORMATION; template->ulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_ATTRIBUTE_TYPE_INVALID; return CKR_ATTRIBUTE_TYPE_INVALID;
} }
@@ -452,7 +452,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
switch (template->type) { switch (template->type) {
case CKA_CLASS: case CKA_CLASS:
DBG(("CLASS\n")); DBG(("CLASS"));
len = sizeof(CK_ULONG); len = sizeof(CK_ULONG);
ul_tmp = CKO_PRIVATE_KEY; ul_tmp = CKO_PRIVATE_KEY;
data = (CK_BYTE_PTR) &ul_tmp; data = (CK_BYTE_PTR) &ul_tmp;
@@ -460,27 +460,27 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_TOKEN: case CKA_TOKEN:
// Technically all these objects are token objects // Technically all these objects are token objects
DBG(("TOKEN\n")); DBG(("TOKEN"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].token; b_tmp[0] = piv_objects[obj].token;
data = b_tmp; data = b_tmp;
break; break;
case CKA_PRIVATE: case CKA_PRIVATE:
DBG(("PRIVATE\n")); DBG(("PRIVATE"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].private; b_tmp[0] = piv_objects[obj].private;
data = b_tmp; data = b_tmp;
break; break;
case CKA_LABEL: case CKA_LABEL:
DBG(("LABEL\n")); DBG(("LABEL"));
len = strlen(piv_objects[obj].label) + 1; len = strlen(piv_objects[obj].label) + 1;
data = piv_objects[obj].label; data = piv_objects[obj].label;
break; break;
case CKA_KEY_TYPE: case CKA_KEY_TYPE:
DBG(("KEY TYPE\n")); DBG(("KEY TYPE"));
len = sizeof(CK_ULONG); len = sizeof(CK_ULONG);
ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk
if (ul_tmp == CKK_VENDOR_DEFINED) if (ul_tmp == CKK_VENDOR_DEFINED)
@@ -489,62 +489,62 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
break; break;
case CKA_SUBJECT: case CKA_SUBJECT:
DBG(("SUBJECT TODO\n")); // Default empty DBG(("SUBJECT TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_ID: case CKA_ID:
DBG(("ID\n")); DBG(("ID"));
len = sizeof(CK_BYTE); len = sizeof(CK_BYTE);
ul_tmp = piv_objects[obj].sub_id; ul_tmp = piv_objects[obj].sub_id;
data = (CK_BYTE_PTR) &ul_tmp; data = (CK_BYTE_PTR) &ul_tmp;
break; break;
case CKA_SENSITIVE: case CKA_SENSITIVE:
DBG(("SENSITIVE TODO\n")); // Default empty DBG(("SENSITIVE TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_DECRYPT: case CKA_DECRYPT:
DBG(("DECRYPT\n")); // Default empty DBG(("DECRYPT")); // Default empty
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].decrypt; b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].decrypt;
data = b_tmp; data = b_tmp;
break; break;
case CKA_UNWRAP: case CKA_UNWRAP:
DBG(("UNWRAP\n")); // Default empty DBG(("UNWRAP")); // Default empty
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].unwrap; b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].unwrap;
data = b_tmp; data = b_tmp;
break; break;
case CKA_SIGN: case CKA_SIGN:
DBG(("SIGN\n")); // Default empty DBG(("SIGN")); // Default empty
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].sign; b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].sign;
data = b_tmp; data = b_tmp;
break; break;
case CKA_SIGN_RECOVER: case CKA_SIGN_RECOVER:
DBG(("SIGN RECOVER TODO\n")); // Default empty DBG(("SIGN RECOVER TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_DERIVE: case CKA_DERIVE:
DBG(("DERIVE\n")); // Default false DBG(("DERIVE")); // Default false
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].derive; b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].derive;
data = b_tmp; data = b_tmp;
break; break;
case CKA_START_DATE: case CKA_START_DATE:
DBG(("START DATE TODO\n")); // Default empty DBG(("START DATE TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_END_DATE: case CKA_END_DATE:
DBG(("END DATE TODO\n")); // Default empty DBG(("END DATE TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_MODULUS: case CKA_MODULUS:
DBG(("MODULUS\n")); DBG(("MODULUS"));
len = sizeof(b_tmp); len = sizeof(b_tmp);
if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
@@ -554,7 +554,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_EC_POINT: case CKA_EC_POINT:
// We're trying to get the key length, get the ec point of the PUBLIC key // We're trying to get the key length, get the ec point of the PUBLIC key
// TODO: or just give an error and explicitly fetch the pubk len when needed // TODO: or just give an error and explicitly fetch the pubk len when needed
DBG(("EC_POINT\n")); DBG(("EC_POINT"));
len = sizeof(b_tmp); len = sizeof(b_tmp);
if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
@@ -562,7 +562,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
break; break;
case CKA_MODULUS_BITS: case CKA_MODULUS_BITS:
DBG(("MODULUS BITS\n")); DBG(("MODULUS BITS"));
len = sizeof(CK_ULONG); len = sizeof(CK_ULONG);
ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk
if (ul_tmp == 0) if (ul_tmp == 0)
@@ -584,21 +584,21 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
/* case CKA_VALUE_LEN: */ /* case CKA_VALUE_LEN: */
/* case CKA_EXTRACTABLE: */ /* case CKA_EXTRACTABLE: */
case CKA_LOCAL: case CKA_LOCAL:
DBG(("LOCAL TODO\n")); // Required DBG(("LOCAL TODO")); // Required
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
/* case CKA_NEVER_EXTRACTABLE: */ /* case CKA_NEVER_EXTRACTABLE: */
/*case CKA_ALWAYS_SENSITIVE:*/ /*case CKA_ALWAYS_SENSITIVE:*/
case CKA_ALWAYS_AUTHENTICATE: case CKA_ALWAYS_AUTHENTICATE:
DBG(("ALWAYS AUTHENTICATE\n")); DBG(("ALWAYS AUTHENTICATE"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].always_auth; b_tmp[0] = pvtkey_objects[piv_objects[obj].sub_id].always_auth;
data = b_tmp; data = b_tmp;
break; break;
case CKA_MODIFIABLE: case CKA_MODIFIABLE:
DBG(("MODIFIABLE\n")); DBG(("MODIFIABLE"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].modifiable; b_tmp[0] = piv_objects[obj].modifiable;
data = b_tmp; data = b_tmp;
@@ -606,7 +606,7 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
/*case CKA_VENDOR_DEFINED:*/ /*case CKA_VENDOR_DEFINED:*/
default: default:
DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); // TODO: there are other parameters for public keys, plus there is more if the key is RSA DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); // TODO: there are other parameters for public keys, plus there is more if the key is RSA
template->ulValueLen = CK_UNAVAILABLE_INFORMATION; template->ulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_ATTRIBUTE_TYPE_INVALID; return CKR_ATTRIBUTE_TYPE_INVALID;
} }
@@ -638,7 +638,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
switch (template->type) { switch (template->type) {
case CKA_CLASS: case CKA_CLASS:
DBG(("CLASS\n")); DBG(("CLASS"));
len = sizeof(CK_ULONG); len = sizeof(CK_ULONG);
ul_tmp = CKO_PUBLIC_KEY; ul_tmp = CKO_PUBLIC_KEY;
data = (CK_BYTE_PTR) &ul_tmp; data = (CK_BYTE_PTR) &ul_tmp;
@@ -646,21 +646,21 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_TOKEN: case CKA_TOKEN:
// Technically all these objects are token objects // Technically all these objects are token objects
DBG(("TOKEN\n")); DBG(("TOKEN"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].token; b_tmp[0] = piv_objects[obj].token;
data = b_tmp; data = b_tmp;
break; break;
case CKA_PRIVATE: case CKA_PRIVATE:
DBG(("PRIVATE\n")); DBG(("PRIVATE"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].private; b_tmp[0] = piv_objects[obj].private;
data = b_tmp; data = b_tmp;
break; break;
case CKA_LABEL: case CKA_LABEL:
DBG(("LABEL\n")); DBG(("LABEL"));
len = strlen(piv_objects[obj].label) + 1; len = strlen(piv_objects[obj].label) + 1;
data = piv_objects[obj].label; data = piv_objects[obj].label;
break; break;
@@ -668,7 +668,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
// case CKA_VALUE: // TODO: this can be done with -r and -d|-a // case CKA_VALUE: // TODO: this can be done with -r and -d|-a
case CKA_KEY_TYPE: case CKA_KEY_TYPE:
DBG(("KEY TYPE\n")); DBG(("KEY TYPE"));
len = sizeof(CK_ULONG); len = sizeof(CK_ULONG);
ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data);
if (ul_tmp == CKK_VENDOR_DEFINED) // This value is used as an error here if (ul_tmp == CKK_VENDOR_DEFINED) // This value is used as an error here
@@ -677,55 +677,55 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
break; break;
case CKA_SUBJECT: case CKA_SUBJECT:
DBG(("SUBJECT TODO\n")); // Default empty DBG(("SUBJECT TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_ID: case CKA_ID:
DBG(("ID\n")); DBG(("ID"));
len = sizeof(CK_BYTE); len = sizeof(CK_BYTE);
b_tmp[0] = piv_objects[obj].sub_id; b_tmp[0] = piv_objects[obj].sub_id;
data = b_tmp; data = b_tmp;
break; break;
case CKA_ENCRYPT: case CKA_ENCRYPT:
DBG(("ENCRYPT\n")); DBG(("ENCRYPT"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].encrypt; b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].encrypt;
data = b_tmp; data = b_tmp;
break; break;
case CKA_VERIFY: // TODO: what about verify recover ? case CKA_VERIFY: // TODO: what about verify recover ?
DBG(("VERIFY\n")); DBG(("VERIFY"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].verify; b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].verify;
data = b_tmp; data = b_tmp;
break; break;
case CKA_WRAP: case CKA_WRAP:
DBG(("WRAP\n")); DBG(("WRAP"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].wrap; b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].wrap;
data = b_tmp; data = b_tmp;
break; break;
case CKA_DERIVE: case CKA_DERIVE:
DBG(("DERIVE\n")); DBG(("DERIVE"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].derive; b_tmp[0] = pubkey_objects[piv_objects[obj].sub_id].derive;
data = b_tmp; data = b_tmp;
break; break;
case CKA_START_DATE: case CKA_START_DATE:
DBG(("START DATE TODO\n")); // Default empty DBG(("START DATE TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_END_DATE: case CKA_END_DATE:
DBG(("END DATE TODO\n")); // Default empty DBG(("END DATE TODO")); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_EC_POINT: case CKA_EC_POINT:
// We're trying to get the key length, get the ec point of the PUBLIC key // We're trying to get the key length, get the ec point of the PUBLIC key
DBG(("EC_POINT\n")); DBG(("EC_POINT"));
len = sizeof(b_tmp); len = sizeof(b_tmp);
if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
@@ -734,7 +734,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_EC_PARAMS: case CKA_EC_PARAMS:
// Here we want the curve parameters (DER encoded OID) // Here we want the curve parameters (DER encoded OID)
DBG(("EC_PARAMS\n")); DBG(("EC_PARAMS"));
len = sizeof(b_tmp); len = sizeof(b_tmp);
if (get_curve_parameters(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK) if (get_curve_parameters(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
@@ -742,7 +742,7 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
break; break;
case CKA_MODULUS_BITS: case CKA_MODULUS_BITS:
DBG(("MODULUS BITS\n")); DBG(("MODULUS BITS"));
len = sizeof(CK_ULONG); len = sizeof(CK_ULONG);
ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk
if (ul_tmp == 0) if (ul_tmp == 0)
@@ -751,18 +751,18 @@ CK_RV get_puoa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
break; break;
case CKA_LOCAL: case CKA_LOCAL:
DBG(("LOCAL TODO\n")); // Required DBG(("LOCAL TODO")); // Required
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
case CKA_MODIFIABLE: case CKA_MODIFIABLE:
DBG(("MODIFIABLE\n")); DBG(("MODIFIABLE"));
len = sizeof(CK_BBOOL); len = sizeof(CK_BBOOL);
b_tmp[0] = piv_objects[obj].modifiable; b_tmp[0] = piv_objects[obj].modifiable;
data = b_tmp; data = b_tmp;
break; break;
default: default:
DBG(("UNKNOWN ATTRIBUTE %lx\n", template[0].type)); // TODO: there are other parameters for public keys DBG(("UNKNOWN ATTRIBUTE %lx", template[0].type)); // TODO: there are other parameters for public keys
template->ulValueLen = CK_UNAVAILABLE_INFORMATION; template->ulValueLen = CK_UNAVAILABLE_INFORMATION;
return CKR_ATTRIBUTE_TYPE_INVALID; return CKR_ATTRIBUTE_TYPE_INVALID;
} }
@@ -892,7 +892,7 @@ CK_RV get_available_certificate_ids(ykcs11_session_t *s, piv_obj_id_t *cert_ids,
if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE) if (IS_CERT(s->slot->token->objects[i]) == CK_TRUE)
cert_ids[j++] = s->slot->token->objects[i]; cert_ids[j++] = s->slot->token->objects[i];
DBG(("Just to check: %lu %lu\n", j, n_certs)); DBG(("Just to check: %lu %lu", j, n_certs));
return CKR_OK; return CKR_OK;
} }
+1
View File
@@ -1,6 +1,7 @@
#include "openssl_utils.h" #include "openssl_utils.h"
#include <stdbool.h> #include <stdbool.h>
#include "../tool/util.h" // TODO: share this better? #include "../tool/util.h" // TODO: share this better?
#include "debug.h"
CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) { CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) {
+45
View File
@@ -1,6 +1,49 @@
#include "token_vendors.h" #include "token_vendors.h"
#include "yubico_token.h" #include "yubico_token.h"
static CK_RV COMMON_token_generate_key(ykpiv_state *state, CK_BBOOL rsa, CK_BYTE key, CK_ULONG key_len) {
// TODO: make a function in ykpiv for this
unsigned char in_data[5];
unsigned char data[1024];
unsigned char templ[] = {0, YKPIV_INS_GENERATE_ASYMMERTRIC, 0, 0};
unsigned long recv_len = sizeof(data);
unsigned long received = 0;
int sw;
templ[3] = key;
in_data[0] = 0xac;
in_data[1] = 3;
in_data[2] = 0x80;
in_data[3] = 1;
switch(key_len) {
case 2048:
in_data[4] = YKPIV_ALGO_RSA2048;
break;
case 1024:
in_data[4] = YKPIV_ALGO_RSA1024;
break;
case 256:
in_data[4] = YKPIV_ALGO_ECCP256;
break;
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 ||
sw != 0x9000)
return CKR_DEVICE_ERROR;
/* to drop the 90 00 and the 7f 49 at the start */
received += recv_len - 4;
return CKR_OK;
}
token_vendor_t get_token_vendor(vendor_id_t vid) { token_vendor_t get_token_vendor(vendor_id_t vid) {
token_vendor_t v; token_vendor_t v;
@@ -18,6 +61,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
v.get_token_objects_num = YUBICO_get_token_objects_num; v.get_token_objects_num = YUBICO_get_token_objects_num;
v.get_token_object_list = YUBICO_get_token_object_list; v.get_token_object_list = YUBICO_get_token_object_list;
v.get_token_raw_certificate = YUBICO_get_token_raw_certificate; v.get_token_raw_certificate = YUBICO_get_token_raw_certificate;
v.token_generate_key = COMMON_token_generate_key;
break; break;
case UNKNOWN: case UNKNOWN:
@@ -34,6 +78,7 @@ token_vendor_t get_token_vendor(vendor_id_t vid) {
v.get_token_objects_num = NULL; v.get_token_objects_num = NULL;
v.get_token_object_list = NULL; v.get_token_object_list = NULL;
v.get_token_raw_certificate = NULL; v.get_token_raw_certificate = NULL;
v.token_generate_key = NULL;
} }
return v; return v;
+6
View File
@@ -18,7 +18,12 @@ 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); typedef CK_RV (*get_t_raw_certificate_f)(ykpiv_state *, piv_obj_id_t, CK_BYTE_PTR, CK_ULONG);
// Common token functions below
typedef CK_RV (*t_generate_key_f)(ykpiv_state *, CK_BBOOL, CK_BYTE, CK_ULONG);
// TODO: replace all the common call with functions defined in .c that use libykpiv // TODO: replace all the common call with functions defined in .c that use libykpiv
typedef struct { typedef struct {
get_t_label_f get_token_label; get_t_label_f get_token_label;
get_t_manufacturer_f get_token_manufacturer; get_t_manufacturer_f get_token_manufacturer;
@@ -32,6 +37,7 @@ typedef struct {
get_t_objects_num_f get_token_objects_num; get_t_objects_num_f get_token_objects_num;
get_t_object_list_f get_token_object_list; get_t_object_list_f get_token_object_list;
get_t_raw_certificate_f get_token_raw_certificate; get_t_raw_certificate_f get_token_raw_certificate;
t_generate_key_f token_generate_key;
} 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);
+128 -33
View File
@@ -37,9 +37,6 @@ static struct {
op_info_t op_info; op_info_t op_info;
/*static piv_obj_id_t token_objects[PIV_CERT_OBJ_LAST]; // TODO: tidy this up, also build at runtime (during open session)? And include inside a session struct?
static CK_ULONG n_token_objects = 0;*/
extern CK_FUNCTION_LIST function_list; // TODO: check all return values extern CK_FUNCTION_LIST function_list; // TODO: check all return values
/* General Purpose */ /* General Purpose */
@@ -489,14 +486,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(
return CKR_HOST_MEMORY; return CKR_HOST_MEMORY;
} }
// Save a list of all the available objects in the token // TODO: change behavior based on login status // Save a list of all the available objects in the token
rv = token.get_token_object_list(piv_state, session.slot->token->objects, session.slot->token->n_objects); rv = token.get_token_object_list(piv_state, session.slot->token->objects, session.slot->token->n_objects);
if (rv != CKR_OK) { if (rv != CKR_OK) {
DBG(("Unable to retrieve token objects")); DBG(("Unable to retrieve token objects"));
goto failure; goto failure;
} }
// Get a list object ids for available certificates object from the session // Get a list of object ids for available certificates object from the session
rv = get_available_certificate_ids(&session, cert_ids, session.slot->token->n_certs); // TODO: better to get this from token? how? rv = get_available_certificate_ids(&session, cert_ids, session.slot->token->n_certs); // TODO: better to get this from token? how?
if (rv != CKR_OK) { if (rv != CKR_OK) {
DBG(("Unable to retrieve certificate ids from the session")); DBG(("Unable to retrieve certificate ids from the session"));
@@ -537,7 +534,7 @@ failure:
cert_ids = NULL; cert_ids = NULL;
} }
free_certs(); // TODO free_certs(); // TODO: remove the one allocated so far
return rv; return rv;
} }
@@ -659,14 +656,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
return CKR_CRYPTOKI_NOT_INITIALIZED; return CKR_CRYPTOKI_NOT_INITIALIZED;
} }
if (userType != CKU_USER && if (userType != CKU_SO && // TODO: what can SO do?
userType != CKU_SO && userType != CKU_USER &&
userType != CKU_CONTEXT_SPECIFIC) userType != CKU_CONTEXT_SPECIFIC)
return CKR_ARGUMENTS_BAD; return CKR_USER_TYPE_INVALID;
if (ulPinLen < PIV_MIN_PIN_LEN ||
ulPinLen > PIV_MAX_PIN_LEN)
return CKR_ARGUMENTS_BAD;
DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen)); DBG(("user %lu, pin %s, pinlen %lu", userType, pPin, ulPinLen));
@@ -678,11 +671,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
if (hSession != session.handle) if (hSession != session.handle)
return CKR_SESSION_HANDLE_INVALID; return CKR_SESSION_HANDLE_INVALID;
if (userType != CKU_SO && // TODO: what can SO do?
userType != CKU_USER &&
userType != CKU_CONTEXT_SPECIFIC)
return CKR_USER_TYPE_INVALID;
if ((session.info.flags & CKF_RW_SESSION) == 0) { // TODO: make macros for these? if ((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 to a read-only session"));
return CKR_SESSION_READ_ONLY_EXISTS; return CKR_SESSION_READ_ONLY_EXISTS;
@@ -690,17 +678,53 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
switch (userType) { switch (userType) {
case CKU_USER: case CKU_USER:
if (session.info.state == CKS_RW_USER_FUNCTIONS) if (ulPinLen < PIV_MIN_PIN_LEN || ulPinLen > PIV_MAX_PIN_LEN)
return CKR_ARGUMENTS_BAD;
if (session.info.state == CKS_RW_USER_FUNCTIONS) // TODO: make sure to set session default state as not logged
return CKR_USER_ALREADY_LOGGED_IN; return CKR_USER_ALREADY_LOGGED_IN;
if (session.info.state == CKS_RW_SO_FUNCTIONS)
return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
tries = 0; tries = 0;
if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { // TODO: call this from vendors.c if (ykpiv_verify(piv_state, pPin, (int *)&tries) != YKPIV_OK) { // TODO: call this from vendors.c
DBG(("You loose! %lu", tries)); DBG(("You loose! %lu", tries));
return CKR_PIN_INCORRECT; return CKR_PIN_INCORRECT;
} }
if ((session.info.flags & CKF_RW_SESSION) == 0) // TODO: double check with the if line 678 for R/O
session.info.state = CKS_RO_USER_FUNCTIONS;
else
session.info.state = CKS_RW_USER_FUNCTIONS;
break; break;
case CKU_SO: case CKU_SO:
// TODO: check for mgmt key length?
if (session.info.state == CKS_RW_SO_FUNCTIONS)
return CKR_USER_ALREADY_LOGGED_IN;
if (session.info.state == CKS_RO_USER_FUNCTIONS ||
session.info.state == CKS_RW_USER_FUNCTIONS)
return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
/***** TODO: replace this with a token function *****/
unsigned char key[24];
size_t key_len = sizeof(key);
if(ykpiv_hex_decode(pPin, ulPinLen, key, &key_len) != YKPIV_OK) {
DBG(("Failed decoding key"));
return CKR_FUNCTION_FAILED;
}
if(ykpiv_authenticate(piv_state, key) != YKPIV_OK) {
DBG(("Failed to authenticate"));
return CKR_PIN_INCORRECT;
}
/***************************************************/
session.info.state = CKS_RW_SO_FUNCTIONS;
break;
case CKU_CONTEXT_SPECIFIC: case CKU_CONTEXT_SPECIFIC:
default: default:
return CKR_USER_TYPE_INVALID; // TODO: only allow regular user for now return CKR_USER_TYPE_INVALID; // TODO: only allow regular user for now
@@ -708,11 +732,6 @@ CK_DEFINE_FUNCTION(CK_RV, C_Login)(
DBG(("You win! %lu", tries)); DBG(("You win! %lu", tries));
if ((session.info.flags & CKF_RW_SESSION) == 0)
session.info.state = CKS_RO_USER_FUNCTIONS;
else
session.info.state = CKS_RW_USER_FUNCTIONS;
DOUT; DOUT;
return CKR_OK; return CKR_OK;
} }
@@ -804,8 +823,8 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)(
if (pTemplate == NULL_PTR || ulCount == 0) if (pTemplate == NULL_PTR || ulCount == 0)
return CKR_ARGUMENTS_BAD; return CKR_ARGUMENTS_BAD;
if (find_obj.active != CK_TRUE) /*if (find_obj.active != CK_TRUE)
return CKR_OPERATION_NOT_INITIALIZED; return CKR_OPERATION_NOT_INITIALIZED; actually this can be called from many other functions*/
rv_final = CKR_OK; rv_final = CKR_OK;
for (i = 0; i < ulCount; i++) { for (i = 0; i < ulCount; i++) {
@@ -1205,6 +1224,11 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
if (hSession != session.handle) if (hSession != session.handle)
return CKR_SESSION_HANDLE_INVALID; return CKR_SESSION_HANDLE_INVALID;
if (op_info.type != YKCS11_NOOP) {
DBG(("Other operation in process"));
return CKR_OPERATION_ACTIVE;
}
if (pMechanism == NULL_PTR || if (pMechanism == NULL_PTR ||
hKey == NULL_PTR) hKey == NULL_PTR)
return CKR_ARGUMENTS_BAD; return CKR_ARGUMENTS_BAD;
@@ -1213,7 +1237,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
// Check if mechanism is supported // Check if mechanism is supported
if (check_sign_mechanism(&session, pMechanism) != CKR_OK) { if (check_sign_mechanism(&session, pMechanism) != CKR_OK) {
DBG(("Mechanism %lu is not supported either by the token or the slot", pMechanism->mechanism)); DBG(("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism));
return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that
} }
memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM));
@@ -1282,7 +1306,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
DBG(("Key length is %lu bit", op_info.op.sign.key_len)); DBG(("Key length is %lu bit", op_info.op.sign.key_len));
op_info.op.sign.key_id = piv_2_ykpiv(hKey); op_info.op.sign.key_id = piv_2_ykpiv(hKey); // TODO: have to set this!!!
if (op_info.op.sign.key_id == 0) { if (op_info.op.sign.key_id == 0) {
DBG(("Incorrect key %lu", hKey)); DBG(("Incorrect key %lu", hKey));
return CKR_KEY_HANDLE_INVALID; return CKR_KEY_HANDLE_INVALID;
@@ -1319,11 +1343,10 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
{ {
DIN; DIN;
if (op_info.type == YKCS11_NOOP) if (op_info.type != YKCS11_SIGN) {
DBG(("Signature operation not initialized"));
return CKR_OPERATION_NOT_INITIALIZED; return CKR_OPERATION_NOT_INITIALIZED;
}
if (op_info.type != YKCS11_SIGN)
return CKR_OPERATION_ACTIVE;
// TODO: check other conditions // TODO: check other conditions
ykpiv_rc r; // TODO: delete this ykpiv_rc r; // TODO: delete this
@@ -1564,7 +1587,79 @@ CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(
) )
{ {
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 != YKCS11_SESSION_ID) {
DBG(("Session is not open"));
return CKR_SESSION_CLOSED;
}
if (hSession != session.handle)
return CKR_SESSION_HANDLE_INVALID;
if (session.info.state != CKS_RW_SO_FUNCTIONS) {
DBG(("Authentication required to generate keys"));
return CKR_SESSION_READ_ONLY;
}
if (op_info.type != YKCS11_NOOP) {
DBG(("Other operation in process"));
return CKR_OPERATION_ACTIVE;
}
if (pMechanism == NULL_PTR ||
pPublicKeyTemplate == NULL_PTR ||
pPrivateKeyTemplate == NULL_PTR ||
phPublicKey == NULL_PTR ||
phPrivateKey == NULL_PTR)
return CKR_ARGUMENTS_BAD;
DBG(("Trying to generate a key pair with mechanism %lu", pMechanism->mechanism));
DBG(("Found %lu attributes for the public key and %lu attributes for the private key", ulPublicKeyAttributeCount, ulPrivateKeyAttributeCount));
// Check if mechanism is supported
if ((rv = check_generation_mechanism(&session, pMechanism)) != CKR_OK) {
DBG(("Mechanism %lu is not supported either by the token or the module", pMechanism->mechanism));
return rv;
}
memcpy(&op_info.mechanism, pMechanism, sizeof(CK_MECHANISM));
// Check the template for the public key
if ((rv = check_pubkey_template(&op_info, pPublicKeyTemplate, ulPublicKeyAttributeCount)) != CKR_OK) {
DBG(("Invalid public key template"));
return rv;
}
// Check the template for the public key
if ((rv = check_pvtkey_template(&op_info, pPrivateKeyTemplate, ulPrivateKeyAttributeCount)) != CKR_OK) {
DBG(("Invalid private key template"));
return rv;
}
if (op_info.op.gen.key_len == 0) {
op_info.op.gen.key_len = 1024; // TODO: for testing purpose set it to rsa2048;
}
if (op_info.op.gen.key_id == 0) {
op_info.op.gen.key_id = PIV_PVTK_OBJ_KM; // TODO: set default key or error?
}
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) {
DBG(("Unable to generate key pair"));
return rv;
}
// TODO: save return object handlers
DOUT; DOUT;
return CKR_OK; return CKR_OK;
} }
+10 -2
View File
@@ -31,16 +31,23 @@ typedef struct {
typedef enum { typedef enum {
YKCS11_NOOP, YKCS11_NOOP,
YKCS11_GEN,
YKCS11_SIGN, YKCS11_SIGN,
YKCS11_HASH, YKCS11_HASH,
YKCS11_DECRYPT YKCS11_DECRYPT
} ykcs11_op_type_t; } 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
} gen_info_t;
typedef struct { typedef struct {
ykcs11_md_ctx_t *md_ctx; // Digest context ykcs11_md_ctx_t *md_ctx; // Digest context
CK_BYTE_PTR key; // Raw public key (needed for PSS) CK_BYTE_PTR key; // Raw public key (needed for PSS)
CK_BYTE algo; // Algo for ykpiv CK_BYTE algo; // Algo for ykpiv // TODO: infer this from the key length?
CK_ULONG key_id; // Key id for ykpiv CK_ULONG key_id; // Key id for ykpiv // TODO: make this a ULONG and store the id {0, 1, 2, 3}
CK_ULONG key_len; // Length in bits CK_ULONG key_len; // Length in bits
} sign_info_t; } sign_info_t;
@@ -53,6 +60,7 @@ typedef struct {
} decrypt_info_t; } decrypt_info_t;
typedef union { typedef union {
gen_info_t gen;
sign_info_t sign; sign_info_t sign;
hash_info_t hash; hash_info_t hash;
decrypt_info_t decrypt; decrypt_info_t decrypt;
+5 -5
View File
@@ -233,7 +233,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
pvtkeys[n_cert] = PIV_PVTK_OBJ_PIV_AUTH; pvtkeys[n_cert] = PIV_PVTK_OBJ_PIV_AUTH;
pubkeys[n_cert] = PIV_PUBK_OBJ_PIV_AUTH; pubkeys[n_cert] = PIV_PUBK_OBJ_PIV_AUTH;
n_cert++; n_cert++;
DBG(("Found AUTH cert (9a)\n")); DBG(("Found AUTH cert (9a)"));
} }
buf_len = sizeof(buf); buf_len = sizeof(buf);
@@ -242,7 +242,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
pvtkeys[n_cert] = PIV_PVTK_OBJ_CARD_AUTH; pvtkeys[n_cert] = PIV_PVTK_OBJ_CARD_AUTH;
pubkeys[n_cert] = PIV_PUBK_OBJ_CARD_AUTH; pubkeys[n_cert] = PIV_PUBK_OBJ_CARD_AUTH;
n_cert++; n_cert++;
DBG(("Found CARD AUTH cert (9e)\n")); DBG(("Found CARD AUTH cert (9e)"));
} }
buf_len = sizeof(buf); buf_len = sizeof(buf);
@@ -251,7 +251,7 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
pvtkeys[n_cert] = PIV_PVTK_OBJ_DS; pvtkeys[n_cert] = PIV_PVTK_OBJ_DS;
pubkeys[n_cert] = PIV_PUBK_OBJ_DS; pubkeys[n_cert] = PIV_PUBK_OBJ_DS;
n_cert++; n_cert++;
DBG(("Found SIGNATURE cert (9c)\n")); DBG(("Found SIGNATURE cert (9c)"));
} }
buf_len = sizeof(buf); buf_len = sizeof(buf);
@@ -260,10 +260,10 @@ static CK_RV get_objects(ykpiv_state *state, CK_BBOOL num_only,
pvtkeys[n_cert] = PIV_PVTK_OBJ_KM; pvtkeys[n_cert] = PIV_PVTK_OBJ_KM;
pubkeys[n_cert] = PIV_PUBK_OBJ_KM; pubkeys[n_cert] = PIV_PUBK_OBJ_KM;
n_cert++; n_cert++;
DBG(("Found KMK cert (9d)\n")); DBG(("Found KMK cert (9d)"));
} }
DBG(("The total number of objects for this token is %lu\n", (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) {
// We just want the number of objects // We just want the number of objects