Improvement on sign and object handling.

This commit is contained in:
Alessio Di Mauro
2015-07-31 17:14:16 +02:00
parent 175f0ff42b
commit b4152b8f03
5 changed files with 590 additions and 436 deletions
+64 -31
View File
@@ -59,16 +59,16 @@ static piv_obj_t piv_objects[] = {
{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, get_coa, 4}, {PIV_CERT_OBJ_LAST, 1, 0, 0, "", 0, 0, get_coa, 4},
{PIV_PVTK_OBJ_PIV_AUTH, 1, 0, 0, "Private key for PIV Authentication", 0, 0, get_proa, 0}, {PIV_PVTK_OBJ_PIV_AUTH, 1, 0, 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}, {PIV_PVTK_OBJ_CARD_AUTH, 1, 0, 0, "Private key for Card Authentication", 0, 0, get_proa, 1}, // 9e
{PIV_PVTK_OBJ_DS, 1, 0, 0, "Private key for Digital Signature", 0, 0, get_proa, 2}, {PIV_PVTK_OBJ_DS, 1, 0, 0, "Private key for Digital Signature", 0, 0, get_proa, 2}, // 9c
{PIV_PVTK_OBJ_KM, 1, 0, 0, "Prrivate key for Key Management", 0, 0, get_proa, 3}, {PIV_PVTK_OBJ_KM, 1, 0, 0, "Prrivate key for Key Management", 0, 0, get_proa, 3}, // 9d
{PIV_PVTK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4}, {PIV_PVTK_OBJ_LAST, 1, 0, 0, "", 0, 0, NULL, 4},
{PIV_PUBK_OBJ_PIV_AUTH, 1, 0, 0, "Public key for PIV Authentication", 0, 0, get_proa, 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_proa, 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_proa, 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_proa, 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_LAST, 1, 0, 0, "", 0, 0, NULL, 4}
}; };
@@ -238,6 +238,18 @@ static void get_object_key_id(CK_OBJECT_HANDLE obj, CK_UTF8CHAR_PTR key_id) {
} }
*/ */
static CK_KEY_TYPE get_key_type(EVP_PKEY *key) {
return do_get_key_type(key);
}
static CK_KEY_TYPE get_modulus_bits(EVP_PKEY *key) {
return do_get_rsa_modulus_length(key);
}
static CK_RV get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
return do_get_public_key(key, data, len);
}
/* Get data object attribute */ /* Get data object attribute */
CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_RV get_doa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
CK_BYTE_PTR data; CK_BYTE_PTR data;
@@ -527,31 +539,32 @@ CK_RV get_coa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
/* Get private key object attribute */ /* Get private key object attribute */
CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) { CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
CK_BYTE_PTR data; CK_BYTE_PTR data;
CK_BYTE tmp[64]; CK_BYTE b_tmp[1024];
CK_ULONG ul_tmp; // TODO: fix elsewhere too
CK_ULONG len = 0; CK_ULONG len = 0;
fprintf(stderr, "FOR PRIVATE KEY OBJECT %lu, I WANT ", obj); fprintf(stderr, "FOR PRIVATE KEY OBJECT %lu, I WANT ", obj);
switch (template->type) { switch (template->type) {
case CKA_CLASS: case CKA_CLASS:
fprintf(stderr, "CLASS\n"); fprintf(stderr, "CLASS\n");
len = 1; len = sizeof(CK_ULONG);
tmp[0] = CKO_PRIVATE_KEY; ul_tmp = CKO_PRIVATE_KEY;
data = tmp; data = (CK_BYTE_PTR) &ul_tmp;
break; break;
case CKA_TOKEN: case CKA_TOKEN:
// Technically all these objects are token objects // Technically all these objects are token objects
fprintf(stderr, "TOKEN\n"); fprintf(stderr, "TOKEN\n");
len = 1; len = sizeof(CK_BBOOL);
tmp[0] = piv_objects[obj].token; b_tmp[0] = piv_objects[obj].token;
data = tmp; data = b_tmp;
break; break;
case CKA_PRIVATE: case CKA_PRIVATE:
fprintf(stderr, "PRIVATE\n"); fprintf(stderr, "PRIVATE\n");
len = 1; len = sizeof(CK_BBOOL);
tmp[0] = piv_objects[obj].private; b_tmp[0] = piv_objects[obj].private;
data = tmp; data = b_tmp;
break; break;
case CKA_LABEL: case CKA_LABEL:
@@ -585,12 +598,13 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
// case CKA_ISSUER: // case CKA_ISSUER:
// case CKA_SERIAL_NUMBER: // case CKA_SERIAL_NUMBER:
case CKA_KEY_TYPE: case CKA_KEY_TYPE:
fprintf(stderr, "KEY TYPE TODO\n"); fprintf(stderr, "KEY TYPE\n");
len = 1; len = sizeof(CK_ULONG);
tmp[0] = CKK_RSA; // TODO: just an example ul_tmp = get_key_type(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk
data = tmp; if (ul_tmp == CKK_VENDOR_DEFINED)
return CKR_FUNCTION_FAILED;
data = (CK_BYTE_PTR) &ul_tmp;
break; break;
return CKR_FUNCTION_FAILED;
case CKA_SUBJECT: case CKA_SUBJECT:
fprintf(stderr, "SUBJECT TODO\n"); // Default empty fprintf(stderr, "SUBJECT TODO\n"); // Default empty
@@ -598,9 +612,9 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_ID: case CKA_ID:
fprintf(stderr, "ID\n"); fprintf(stderr, "ID\n");
len = 1; len = sizeof(CK_ULONG);
tmp[0] = piv_objects[obj].sub_id; ul_tmp = piv_objects[obj].sub_id;
data = tmp; data = (CK_BYTE_PTR) &ul_tmp;
break; break;
case CKA_SENSITIVE: case CKA_SENSITIVE:
@@ -638,8 +652,27 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
case CKA_END_DATE: case CKA_END_DATE:
fprintf(stderr, "END DATE TODO\n"); // Default empty fprintf(stderr, "END DATE TODO\n"); // Default empty
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
/* case CKA_MODULUS: */
/* case CKA_MODULUS_BITS: */ /*case CKA_MODULUS:*/
case CKA_EC_POINT:
// 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
fprintf(stderr, "EC_POINT\n");
len = sizeof(b_tmp);
if (get_public_key(pubkey_objects[piv_objects[obj].sub_id].data, b_tmp, &len) != CKR_OK)
return CKR_FUNCTION_FAILED;
data = b_tmp;
break;
case CKA_MODULUS_BITS:
fprintf(stderr, "MODULUS BITS\n");
len = sizeof(CK_ULONG);
ul_tmp = get_modulus_bits(pubkey_objects[piv_objects[obj].sub_id].data); // Getting the info from the pubk
if (ul_tmp == 0)
return CKR_FUNCTION_FAILED;
data = (CK_BYTE_PTR) &ul_tmp;
break;
/* case CKA_PUBLIC_EXPONENT: */ /* case CKA_PUBLIC_EXPONENT: */
/* case CKA_PRIVATE_EXPONENT: */ /* case CKA_PRIVATE_EXPONENT: */
/* case CKA_PRIME_1: */ /* case CKA_PRIME_1: */
@@ -661,9 +694,9 @@ CK_RV get_proa(CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_PTR template) {
/* case CKA_ALWAYS_SENSITIVE: */ /* case CKA_ALWAYS_SENSITIVE: */
case CKA_MODIFIABLE: case CKA_MODIFIABLE:
fprintf(stderr, "MODIFIABLE\n"); fprintf(stderr, "MODIFIABLE\n");
len = 1; len = sizeof(CK_BBOOL);
tmp[0] = piv_objects[obj].modifiable; b_tmp[0] = piv_objects[obj].modifiable;
data = tmp; data = b_tmp;
break; break;
/*case CKA_VENDOR_DEFINED:*/ /*case CKA_VENDOR_DEFINED:*/
+72 -9
View File
@@ -7,7 +7,7 @@ CK_RV do_store_cert(CK_BYTE_PTR data, CK_ULONG len, X509 **cert) {
const unsigned char *p = data; // Mandatory temp variable required by OpenSSL const unsigned char *p = data; // Mandatory temp variable required by OpenSSL
int cert_len; int cert_len;
/**cert = X509_new(); /**cert = X509_new();
if (*cert == NULL) if (*cert == NULL)
return CKR_HOST_MEMORY;*/ return CKR_HOST_MEMORY;*/
@@ -50,24 +50,87 @@ CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key) {
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
return CKR_OK; return CKR_OK;
}
CK_KEY_TYPE do_get_key_type(EVP_PKEY *key) {
switch (key->type) {
case EVP_PKEY_RSA:
case EVP_PKEY_RSA2:
return CKK_RSA;
case EVP_PKEY_EC:
return CKK_ECDSA;
default:
return CKK_VENDOR_DEFINED; // Actually an error
}
}
CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) {
CK_ULONG key_len = 0;
RSA *rsa;
rsa = EVP_PKEY_get1_RSA(key);
if (rsa == NULL)
return 0;
return RSA_size(rsa) * 8; // There is also RSA_bits but only in >= 1.1.0
}
/* #include <stdio.h> */
/* #include <openssl/err.h> */
/* ERR_load_crypto_strings(); */
/* //SSL_load_error_strings(); */
/* fprintf(stderr, "ERROR %s\n", ERR_error_string(ERR_get_error(), NULL)); */
CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
RSA *rsa;
EC_KEY *eck;
const EC_GROUP *ecg; // Alternatice solution is to get i2d_PUBKEY and manually offset
const EC_POINT *ecp;
point_conversion_form_t pcf = POINT_CONVERSION_UNCOMPRESSED;
switch(key->type) {
case EVP_PKEY_RSA:
case EVP_PKEY_RSA2:
rsa = EVP_PKEY_get1_RSA(key);
return CKR_FUNCTION_FAILED; // TODO;
break;
case EVP_PKEY_EC:
eck = EVP_PKEY_get1_EC_KEY(key);
ecg = EC_KEY_get0_group(eck);
ecp = EC_KEY_get0_public_key(eck);
if ((*len = EC_POINT_point2oct(ecg, ecp, pcf, data, *len, NULL)) == 0)
return CKR_FUNCTION_FAILED;
break;
default:
return CKR_FUNCTION_FAILED;
}
return CKR_OK;
} }
CK_RV free_key(EVP_PKEY *key) { CK_RV free_key(EVP_PKEY *key) {
EVP_PKEY_free(key); EVP_PKEY_free(key);
return CKR_OK; return CKR_OK;
} }
/* #include <stdio.h> */
/* #include <openssl/err.h> */
/* ERR_load_crypto_strings(); */
/* //SSL_load_error_strings(); */
CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) { CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len) {
fprintf(stderr, "Apply padding to %lu bytes and get %lu\n", in_len, key_len); fprintf(stderr, "Apply padding to %lu bytes and get %lu\n", in_len, key_len);
// TODO: rand must be seeded first
if (out_len < key_len) if (out_len < key_len)
CKR_BUFFER_TOO_SMALL; CKR_BUFFER_TOO_SMALL;
+6 -2
View File
@@ -4,13 +4,17 @@
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/ec.h>
#include "pkcs11t.h" #include "pkcs11t.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);
CK_RV free_cert(X509 *cert); CK_RV free_cert(X509 *cert);
CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key); CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key);
CK_RV free_key(EVP_PKEY *key); CK_KEY_TYPE do_get_key_type(EVP_PKEY *key);
CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key);
CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len);
CK_RV free_key(EVP_PKEY *key);
CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len); CK_RV do_pkcs_t1(CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG out_len, CK_ULONG key_len);
+393 -386
View File
File diff suppressed because it is too large Load Diff
+55 -8
View File
@@ -65,6 +65,7 @@ static struct {
CK_BBOOL active; CK_BBOOL active;
CK_MECHANISM mechanism; CK_MECHANISM mechanism;
CK_ULONG key; CK_ULONG key;
CK_ULONG key_len;
CK_BYTE algo; CK_BYTE algo;
} sign_info; } sign_info;
@@ -913,7 +914,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(
// TODO: do it properly here, just a test now // TODO: do it properly here, just a test now
//find_obj.objects = session.slot->token->objects + 3; //find_obj.objects = session.slot->token->objects + 3;
memmove(find_obj.objects, find_obj.objects + 14, sizeof(piv_obj_id_t) * (find_obj.num - 14)); memmove(find_obj.objects, find_obj.objects + 13, sizeof(piv_obj_id_t) * (find_obj.num - 13));
find_obj.num = 1; find_obj.num = 1;
DOUT; DOUT;
@@ -1165,6 +1166,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(
) )
{ {
DIN; DIN;
CK_KEY_TYPE type = 0; // TODO: replace these with sign_info's fields?
CK_ULONG key_len = 0;
CK_BYTE buf[1024];
CK_ATTRIBUTE template[] = {
{CKA_KEY_TYPE, &type, sizeof(type)},
{CKA_MODULUS_BITS, &key_len, sizeof(key_len)},
{CKA_EC_POINT, buf, sizeof(buf)}
};
if (piv_state == NULL) { if (piv_state == NULL) {
DBG(("libykpiv is not initialized or already finalized")); DBG(("libykpiv is not initialized or already finalized"));
@@ -1186,23 +1195,61 @@ 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 slot", pMechanism->mechanism));
return CKR_MECHANISM_INVALID; return CKR_MECHANISM_INVALID; // TODO: also the key has a list of allowed mechanisms, check that
} }
memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM)); memcpy(&sign_info.mechanism, pMechanism, sizeof(CK_MECHANISM));
// Get key algorithm // Get key algorithm
/*if (get_key_algo(hKey, &sign_info.algo) != CKR_OK) { if (get_attribute(&session, hKey, template) != CKR_OK) {
DBG(("Unable to retrieve type for key %lu", hKey)); DBG(("Unable to get key type"));
return CKR_FUNCTION_FAILED; return CKR_KEY_HANDLE_INVALID;
}*/ // TODO: use get attribute instead? }
sign_info.algo = YKPIV_ALGO_RSA2048; // TODO: fix
DBG(("Key algorithm is %lu\n", type));
// Get key length and algorithm type
if (type == CKK_RSA) {
// RSA key
if (get_attribute(&session, hKey, template + 1) != CKR_OK) {
DBG(("Unable to get key length"));
return CKR_KEY_HANDLE_INVALID;
}
sign_info.key_len = key_len;
if (key_len == 1024)
sign_info.algo = YKPIV_ALGO_RSA1024;
else
sign_info.algo = YKPIV_ALGO_RSA2048;
}
else {
// ECDSA key
if (get_attribute(&session, hKey, template + 2) != CKR_OK) {
DBG(("Unable to get key length"));
return CKR_KEY_HANDLE_INVALID;
}
// The buffer contains an uncompressed point of the form 04, x, y
// TODO: is this a fine representation for an EC public key?
sign_info.key_len = ((template[2].ulValueLen - 1) / 2) * 8;
if (sign_info.key_len == 256)
sign_info.algo = YKPIV_ALGO_ECCP256;
/*else
sign_info.algo = ;*/
}
DBG(("Key length is %lu bit", sign_info.key_len));
//sign_info.key_len /= 8;
sign_info.key = piv_2_ykpiv(hKey); sign_info.key = piv_2_ykpiv(hKey);
if (sign_info.key == 0) { if (sign_info.key == 0) {
DBG(("Incorrect key %lu", hKey)); DBG(("Incorrect key %lu", hKey));
return CKR_KEY_HANDLE_INVALID; return CKR_KEY_HANDLE_INVALID;
} }
DBG(("Algorithm is %d", sign_info.algo));
// Make sure that both mechanism and key have the same algorithm // Make sure that both mechanism and key have the same algorithm
if ((is_RSA_mechanism(pMechanism->mechanism) && sign_info.algo == YKPIV_ALGO_ECCP256) || if ((is_RSA_mechanism(pMechanism->mechanism) && sign_info.algo == YKPIV_ALGO_ECCP256) ||
(!is_RSA_mechanism(pMechanism->mechanism) && (sign_info.algo != YKPIV_ALGO_ECCP256))) { (!is_RSA_mechanism(pMechanism->mechanism) && (sign_info.algo != YKPIV_ALGO_ECCP256))) {
@@ -1248,7 +1295,7 @@ CK_DEFINE_FUNCTION(CK_RV, C_Sign)(
//dump_hex(buf, 256, stderr, CK_TRUE); //dump_hex(buf, 256, stderr, CK_TRUE);
//*pulSignatureLen = 256; //*pulSignatureLen = 256;
DBG(("Using key %lx", sign_info.key)); // TODO: test what happens if there is no key on the card DBG(("Using key %lx", sign_info.key)); // TODO: test what happens if there is no key on the card
if ((r = ykpiv_sign_data(piv_state, buf, ulDataLen, pSignature, pulSignatureLen, YKPIV_ALGO_RSA2048, sign_info.key)) != YKPIV_OK) { if ((r = ykpiv_sign_data(piv_state, buf, ulDataLen, pSignature, pulSignatureLen, sign_info.algo, sign_info.key)) != YKPIV_OK) {
DBG(("Sign error, %s", ykpiv_strerror(r))); DBG(("Sign error, %s", ykpiv_strerror(r)));
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
} }