p11test: Add support for EdDSA keys
This commit is contained in:
parent
32ec1f92b9
commit
485b6cff44
@ -144,6 +144,38 @@ add_supported_mechs(test_cert_t *o)
|
|||||||
o->mechs[0].result_flags = 0;
|
o->mechs[0].result_flags = 0;
|
||||||
o->mechs[0].usage_flags = CKF_SIGN | CKF_VERIFY;
|
o->mechs[0].usage_flags = CKF_SIGN | CKF_VERIFY;
|
||||||
}
|
}
|
||||||
|
} else if (o->type == EVP_PKEY_ED25519) {
|
||||||
|
if (token.num_ed_mechs > 0 ) {
|
||||||
|
o->num_mechs = token.num_ed_mechs;
|
||||||
|
for (i = 0; i <= token.num_ed_mechs; i++) {
|
||||||
|
o->mechs[i].mech = token.ed_mechs[i].mech;
|
||||||
|
o->mechs[i].result_flags = 0;
|
||||||
|
o->mechs[i].usage_flags =
|
||||||
|
token.ed_mechs[i].usage_flags;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Use the default list */
|
||||||
|
o->num_mechs = 1;
|
||||||
|
o->mechs[0].mech = CKM_EDDSA;
|
||||||
|
o->mechs[0].result_flags = 0;
|
||||||
|
o->mechs[0].usage_flags = CKF_SIGN | CKF_VERIFY;
|
||||||
|
}
|
||||||
|
} else if (o->type == EVP_PKEY_X25519) {
|
||||||
|
if (token.num_montgomery_mechs > 0 ) {
|
||||||
|
o->num_mechs = token.num_montgomery_mechs;
|
||||||
|
for (i = 0; i <= token.num_ed_mechs; i++) {
|
||||||
|
o->mechs[i].mech = token.montgomery_mechs[i].mech;
|
||||||
|
o->mechs[i].result_flags = 0;
|
||||||
|
o->mechs[i].usage_flags =
|
||||||
|
token.montgomery_mechs[i].usage_flags;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Use the default list */
|
||||||
|
o->num_mechs = 1;
|
||||||
|
o->mechs[0].mech = CKM_ECDH1_DERIVE;
|
||||||
|
o->mechs[0].result_flags = 0;
|
||||||
|
o->mechs[0].usage_flags = CKF_DERIVE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,8 +431,102 @@ int callback_public_keys(test_certs_t *objects,
|
|||||||
EC_KEY_set_group(o->key.ec, ecgroup);
|
EC_KEY_set_group(o->key.ec, ecgroup);
|
||||||
o->bits = EC_GROUP_get_degree(ecgroup);
|
o->bits = EC_GROUP_get_degree(ecgroup);
|
||||||
}
|
}
|
||||||
|
} else if (o->key_type == CKK_EC_EDWARDS
|
||||||
|
|| o->key_type == CKK_EC_MONTGOMERY) {
|
||||||
|
EVP_PKEY *key = NULL;
|
||||||
|
ASN1_PRINTABLESTRING *curve = NULL;
|
||||||
|
const unsigned char *a;
|
||||||
|
ASN1_OCTET_STRING *os;
|
||||||
|
int evp_type;
|
||||||
|
|
||||||
|
a = template[6].pValue;
|
||||||
|
if (!d2i_ASN1_PRINTABLESTRING(&curve, &a, (long)template[6].ulValueLen)) {
|
||||||
|
debug_print(" [WARN %s ] Failed to convert EC_PARAMS"
|
||||||
|
" to curve name", o->id_str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (o->key_type) {
|
||||||
|
case CKK_EC_EDWARDS:
|
||||||
|
if (strcmp((char *)curve->data, "edwards25519")) {
|
||||||
|
debug_print(" [WARN %s ] Unknown curve name. "
|
||||||
|
" expected edwards25519, got %s", o->id_str, curve->data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
evp_type = EVP_PKEY_ED25519;
|
||||||
|
break;
|
||||||
|
case CKK_EC_MONTGOMERY:
|
||||||
|
if (strcmp((char *)curve->data, "curve25519")) {
|
||||||
|
debug_print(" [WARN %s ] Unknown curve name. "
|
||||||
|
" expected curve25519, got %s", o->id_str, curve->data);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
evp_type = EVP_PKEY_X25519;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug_print(" [WARN %s ] Unknown key type %lu", o->id_str, o->key_type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ASN1_PRINTABLESTRING_free(curve);
|
||||||
|
|
||||||
|
/* PKCS#11-compliant modules should return ASN1_OCTET_STRING */
|
||||||
|
a = template[7].pValue;
|
||||||
|
os = d2i_ASN1_OCTET_STRING(NULL, &a, (long)template[7].ulValueLen);
|
||||||
|
if (!os) {
|
||||||
|
debug_print(" [WARN %s ] Can not decode EC_POINT", o->id_str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (os->length != 32) {
|
||||||
|
debug_print(" [WARN %s ] Invalid length of EC_POINT value", o->id_str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
key = EVP_PKEY_new_raw_public_key(evp_type, NULL,
|
||||||
|
(const uint8_t *)os->data,
|
||||||
|
os->length);
|
||||||
|
if (key == NULL) {
|
||||||
|
debug_print(" [WARN %s ] Out of memory", o->id_str);
|
||||||
|
ASN1_STRING_free(os);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (o->key.pkey != NULL) {
|
||||||
|
unsigned char *pub = NULL;
|
||||||
|
size_t publen = 0;
|
||||||
|
|
||||||
|
/* TODO check EVP_PKEY type */
|
||||||
|
|
||||||
|
if (EVP_PKEY_get_raw_public_key(o->key.pkey, NULL, &publen) != 1) {
|
||||||
|
debug_print(" [WARN %s ] Can not get size of the key", o->id_str);
|
||||||
|
ASN1_STRING_free(os);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pub = malloc(publen);
|
||||||
|
if (pub == NULL) {
|
||||||
|
debug_print(" [WARN %s ] Out of memory", o->id_str);
|
||||||
|
ASN1_STRING_free(os);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EVP_PKEY_get_raw_public_key(o->key.pkey, pub, &publen) != 1 ||
|
||||||
|
publen != (size_t)os->length ||
|
||||||
|
memcmp(pub, os->data, publen) != 0) {
|
||||||
|
debug_print(" [WARN %s ] Got different public"
|
||||||
|
"key then from the certificate",
|
||||||
|
o->id_str);
|
||||||
|
free(pub);
|
||||||
|
ASN1_STRING_free(os);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(pub);
|
||||||
|
EVP_PKEY_free(key);
|
||||||
|
o->verify_public = 1;
|
||||||
|
} else { /* store the public key for future use */
|
||||||
|
o->type = evp_type;
|
||||||
|
o->key.pkey = key;
|
||||||
|
o->bits = 255;
|
||||||
|
}
|
||||||
|
ASN1_STRING_free(os);
|
||||||
} else {
|
} else {
|
||||||
debug_print(" [WARN %s ] non-RSA, non-EC key. Key type: %02lX",
|
debug_print(" [WARN %s ] unknown key. Key type: %02lX",
|
||||||
o->id_str, o->key_type);
|
o->id_str, o->key_type);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -577,10 +703,15 @@ void clean_all_objects(test_certs_t *objects) {
|
|||||||
free(objects->data[i].label);
|
free(objects->data[i].label);
|
||||||
X509_free(objects->data[i].x509);
|
X509_free(objects->data[i].x509);
|
||||||
if (objects->data[i].key_type == CKK_RSA &&
|
if (objects->data[i].key_type == CKK_RSA &&
|
||||||
objects->data[i].key.rsa != NULL)
|
objects->data[i].key.rsa != NULL) {
|
||||||
RSA_free(objects->data[i].key.rsa);
|
RSA_free(objects->data[i].key.rsa);
|
||||||
else if (objects->data[i].key.ec != NULL)
|
} else if (objects->data[i].key_type == CKK_EC &&
|
||||||
|
objects->data[i].key.ec != NULL) {
|
||||||
EC_KEY_free(objects->data[i].key.ec);
|
EC_KEY_free(objects->data[i].key.ec);
|
||||||
|
} else if (objects->data[i].key_type == CKK_EC_EDWARDS &&
|
||||||
|
objects->data[i].key.pkey != NULL) {
|
||||||
|
EVP_PKEY_free(objects->data[i].key.pkey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(objects->data);
|
free(objects->data);
|
||||||
}
|
}
|
||||||
@ -614,6 +745,10 @@ const char *get_mechanism_name(int mech_id)
|
|||||||
return "ECDSA_SHA384";
|
return "ECDSA_SHA384";
|
||||||
case CKM_ECDSA_SHA512:
|
case CKM_ECDSA_SHA512:
|
||||||
return "ECDSA_SHA512";
|
return "ECDSA_SHA512";
|
||||||
|
case CKM_EDDSA:
|
||||||
|
return "EDDSA";
|
||||||
|
case CKM_XEDDSA:
|
||||||
|
return "XEDDSA";
|
||||||
case CKM_ECDH1_DERIVE:
|
case CKM_ECDH1_DERIVE:
|
||||||
return "ECDH1_DERIVE";
|
return "ECDH1_DERIVE";
|
||||||
case CKM_ECDH1_COFACTOR_DERIVE:
|
case CKM_ECDH1_COFACTOR_DERIVE:
|
||||||
@ -650,6 +785,10 @@ const char *get_mechanism_name(int mech_id)
|
|||||||
return "SHA512_HMAC";
|
return "SHA512_HMAC";
|
||||||
case CKM_RSA_PKCS_OAEP:
|
case CKM_RSA_PKCS_OAEP:
|
||||||
return "RSA_PKCS_OAEP";
|
return "RSA_PKCS_OAEP";
|
||||||
|
case CKM_RIPEMD160:
|
||||||
|
return "RIPEMD160";
|
||||||
|
case CKM_GOSTR3411:
|
||||||
|
return "GOSTR3411";
|
||||||
case CKM_MD5:
|
case CKM_MD5:
|
||||||
return "MD5";
|
return "MD5";
|
||||||
case CKM_SHA_1:
|
case CKM_SHA_1:
|
||||||
@ -662,6 +801,14 @@ const char *get_mechanism_name(int mech_id)
|
|||||||
return "SHA384";
|
return "SHA384";
|
||||||
case CKM_SHA512:
|
case CKM_SHA512:
|
||||||
return "SHA512";
|
return "SHA512";
|
||||||
|
case CKM_SHA3_256:
|
||||||
|
return "SHA3_256";
|
||||||
|
case CKM_SHA3_224:
|
||||||
|
return "SHA3_224";
|
||||||
|
case CKM_SHA3_384:
|
||||||
|
return "SHA3_384";
|
||||||
|
case CKM_SHA3_512:
|
||||||
|
return "SHA3_512";
|
||||||
default:
|
default:
|
||||||
sprintf(name_buffer, "0x%.8X", mech_id);
|
sprintf(name_buffer, "0x%.8X", mech_id);
|
||||||
return name_buffer;
|
return name_buffer;
|
||||||
|
@ -36,6 +36,7 @@ typedef struct {
|
|||||||
union {
|
union {
|
||||||
RSA *rsa;
|
RSA *rsa;
|
||||||
EC_KEY *ec;
|
EC_KEY *ec;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
} key;
|
} key;
|
||||||
CK_OBJECT_HANDLE private_handle;
|
CK_OBJECT_HANDLE private_handle;
|
||||||
CK_OBJECT_HANDLE public_handle;
|
CK_OBJECT_HANDLE public_handle;
|
||||||
|
@ -20,15 +20,14 @@
|
|||||||
*/
|
*/
|
||||||
#include "p11test_case_ec_derive.h"
|
#include "p11test_case_ec_derive.h"
|
||||||
|
|
||||||
unsigned long pkcs11_derive(test_cert_t *o, token_info_t * info,
|
size_t
|
||||||
EC_KEY *key, test_mech_t *mech, unsigned char **secret)
|
pkcs11_derive(test_cert_t *o, token_info_t * info,
|
||||||
|
unsigned char *pub, size_t pub_len, test_mech_t *mech, unsigned char **secret)
|
||||||
{
|
{
|
||||||
CK_RV rv;
|
CK_RV rv;
|
||||||
CK_FUNCTION_LIST_PTR fp = info->function_pointer;
|
CK_FUNCTION_LIST_PTR fp = info->function_pointer;
|
||||||
CK_ECDH1_DERIVE_PARAMS params = {CKD_NULL, 0, NULL_PTR, 0, NULL_PTR};
|
CK_ECDH1_DERIVE_PARAMS params = {CKD_NULL, 0, NULL_PTR, 0, NULL_PTR};
|
||||||
CK_MECHANISM mechanism = { mech->mech, NULL_PTR, 0 };
|
CK_MECHANISM mechanism = { mech->mech, NULL_PTR, 0 };
|
||||||
const EC_POINT *publickey = NULL;
|
|
||||||
const EC_GROUP *group = NULL;
|
|
||||||
CK_OBJECT_HANDLE newkey;
|
CK_OBJECT_HANDLE newkey;
|
||||||
CK_OBJECT_CLASS newkey_class = CKO_SECRET_KEY;
|
CK_OBJECT_CLASS newkey_class = CKO_SECRET_KEY;
|
||||||
CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET;
|
CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET;
|
||||||
@ -47,23 +46,6 @@ unsigned long pkcs11_derive(test_cert_t *o, token_info_t * info,
|
|||||||
};
|
};
|
||||||
CK_ATTRIBUTE get_value = {CKA_VALUE, NULL_PTR, 0};
|
CK_ATTRIBUTE get_value = {CKA_VALUE, NULL_PTR, 0};
|
||||||
CK_ULONG template_len = 9;
|
CK_ULONG template_len = 9;
|
||||||
unsigned char *pub = NULL;
|
|
||||||
size_t pub_len;
|
|
||||||
|
|
||||||
/* Convert the public key to the octet string */
|
|
||||||
group = EC_KEY_get0_group(key);
|
|
||||||
publickey = EC_KEY_get0_public_key(key);
|
|
||||||
pub_len = EC_POINT_point2oct(group, publickey,
|
|
||||||
POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
|
|
||||||
if (pub_len == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pub = malloc(pub_len);
|
|
||||||
if (pub == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pub_len = EC_POINT_point2oct(group, publickey,
|
|
||||||
POINT_CONVERSION_UNCOMPRESSED, pub, pub_len, NULL);
|
|
||||||
|
|
||||||
params.pSharedData = NULL;
|
params.pSharedData = NULL;
|
||||||
params.ulSharedDataLen = 0;
|
params.ulSharedDataLen = 0;
|
||||||
@ -75,7 +57,6 @@ unsigned long pkcs11_derive(test_cert_t *o, token_info_t * info,
|
|||||||
|
|
||||||
rv = fp->C_DeriveKey(info->session_handle, &mechanism, o->private_handle,
|
rv = fp->C_DeriveKey(info->session_handle, &mechanism, o->private_handle,
|
||||||
template, template_len, &newkey);
|
template, template_len, &newkey);
|
||||||
free(pub);
|
|
||||||
if (rv != CKR_OK) {
|
if (rv != CKR_OK) {
|
||||||
debug_print(" C_DeriveKey: rv = 0x%.8lX\n", rv);
|
debug_print(" C_DeriveKey: rv = 0x%.8lX\n", rv);
|
||||||
return 0;
|
return 0;
|
||||||
@ -106,12 +87,138 @@ unsigned long pkcs11_derive(test_cert_t *o, token_info_t * info,
|
|||||||
return get_value.ulValueLen;
|
return get_value.ulValueLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test_derive_x25519(test_cert_t *o, token_info_t *info, test_mech_t *mech)
|
||||||
|
{
|
||||||
|
unsigned char *secret = NULL, *pkcs11_secret = NULL;
|
||||||
|
EVP_PKEY_CTX *pctx = NULL;
|
||||||
|
EVP_PKEY *pkey = NULL; /* This is peer key */
|
||||||
|
unsigned char *pub = NULL;
|
||||||
|
size_t pub_len = 0, secret_len = 32, pkcs11_secret_len = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (o->private_handle == CK_INVALID_HANDLE) {
|
||||||
|
debug_print(" [SKIP %s ] Missing private key", o->id_str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o->type != EVP_PKEY_X25519) {
|
||||||
|
debug_print(" [ KEY %s ] Skip non-EC key for derive", o->id_str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First, we need to generate our key */
|
||||||
|
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
|
||||||
|
if (pctx == NULL) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_CTX_new_id failed", o->id_str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = EVP_PKEY_keygen_init(pctx);
|
||||||
|
if (rc != 1) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_keygen_init failed", o->id_str);
|
||||||
|
EVP_PKEY_CTX_free(pctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = EVP_PKEY_keygen(pctx, &pkey);
|
||||||
|
EVP_PKEY_CTX_free(pctx);
|
||||||
|
if (rc != 1) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_keygen failed", o->id_str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Just here we start with key derivation in OpenSSL */
|
||||||
|
pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||||
|
if (pctx == NULL) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_CTX_new failed", o->id_str);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = EVP_PKEY_derive_init(pctx);
|
||||||
|
if (rc != 1) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_derive_init failed", o->id_str);
|
||||||
|
EVP_PKEY_CTX_free(pctx);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = EVP_PKEY_derive_set_peer(pctx, o->key.pkey);
|
||||||
|
if (rc != 1) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_derive_set_peer failed", o->id_str);
|
||||||
|
EVP_PKEY_CTX_free(pctx);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate the memory for the shared secret */
|
||||||
|
if ((secret = malloc(secret_len)) == NULL) {
|
||||||
|
debug_print(" [ KEY %s ] Failed to allocate memory for secret", o->id_str);
|
||||||
|
EVP_PKEY_CTX_free(pctx);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = EVP_PKEY_derive(pctx, secret, &secret_len);
|
||||||
|
EVP_PKEY_CTX_free(pctx);
|
||||||
|
if (rc != 1) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_derive failed", o->id_str);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
free(secret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to do the same with the card key */
|
||||||
|
rc = EVP_PKEY_get_raw_public_key(pkey, pub, &pub_len);
|
||||||
|
if (rc != 1) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_get_raw_public_key failed", o->id_str);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
free(secret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pub = malloc(pub_len);
|
||||||
|
if (pub == NULL) {
|
||||||
|
debug_print(" [ KEY %s ] failed to allocate memory", o->id_str);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
free(secret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
rc = EVP_PKEY_get_raw_public_key(pkey, pub, &pub_len);
|
||||||
|
if (rc != 1) {
|
||||||
|
debug_print(" [ KEY %s ] EVP_PKEY_get_raw_public_key failed", o->id_str);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
free(secret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkcs11_secret_len = pkcs11_derive(o, info, pub, pub_len, mech, &pkcs11_secret);
|
||||||
|
|
||||||
|
if (secret_len == pkcs11_secret_len && memcmp(secret, pkcs11_secret, secret_len) == 0) {
|
||||||
|
mech->result_flags |= FLAGS_DERIVE;
|
||||||
|
debug_print(" [ OK %s ] Derived secrets match", o->id_str);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
free(secret);
|
||||||
|
free(pkcs11_secret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_print(" [ KEY %s ] Derived secret does not match", o->id_str);
|
||||||
|
free(pub);
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
free(secret);
|
||||||
|
free(pkcs11_secret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int test_derive(test_cert_t *o, token_info_t *info, test_mech_t *mech)
|
int test_derive(test_cert_t *o, token_info_t *info, test_mech_t *mech)
|
||||||
{
|
{
|
||||||
int nid, field_size, secret_len, pkcs11_secret_len;
|
int nid, field_size;
|
||||||
EC_KEY *key = NULL;
|
EC_KEY *key = NULL;
|
||||||
|
const EC_POINT *publickey = NULL;
|
||||||
|
const EC_GROUP *group = NULL;
|
||||||
unsigned char *secret = NULL, *pkcs11_secret = NULL;
|
unsigned char *secret = NULL, *pkcs11_secret = NULL;
|
||||||
|
unsigned char *pub = NULL;
|
||||||
|
size_t pub_len = 0, secret_len = 0, pkcs11_secret_len = 0;
|
||||||
|
|
||||||
if (o->private_handle == CK_INVALID_HANDLE) {
|
if (o->private_handle == CK_INVALID_HANDLE) {
|
||||||
debug_print(" [SKIP %s ] Missing private key", o->id_str);
|
debug_print(" [SKIP %s ] Missing private key", o->id_str);
|
||||||
@ -124,7 +231,7 @@ int test_derive(test_cert_t *o, token_info_t *info, test_mech_t *mech)
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug_print(" [ KEY %s ] Trying EC derive using CKM_%s and %lu-bit key",
|
debug_print(" [ KEY %s ] Trying EC derive using CKM_%s and %lu-bit key",
|
||||||
o->id_str, get_mechanism_name(mech->mech), o->bits);
|
o->id_str, get_mechanism_name(mech->mech), o->bits);
|
||||||
if (o->bits == 256)
|
if (o->bits == 256)
|
||||||
nid = NID_X9_62_prime256v1;
|
nid = NID_X9_62_prime256v1;
|
||||||
else if (o->bits == 384)
|
else if (o->bits == 384)
|
||||||
@ -150,7 +257,7 @@ int test_derive(test_cert_t *o, token_info_t *info, test_mech_t *mech)
|
|||||||
|
|
||||||
/* Allocate the memory for the shared secret */
|
/* Allocate the memory for the shared secret */
|
||||||
if ((secret = OPENSSL_malloc(secret_len)) == NULL) {
|
if ((secret = OPENSSL_malloc(secret_len)) == NULL) {
|
||||||
debug_print(" [ KEY %s ] Failed to generate peer private key", o->id_str);
|
debug_print(" [ KEY %s ] Failed to allocate memory for secret", o->id_str);
|
||||||
EC_KEY_free(key);
|
EC_KEY_free(key);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -160,7 +267,37 @@ int test_derive(test_cert_t *o, token_info_t *info, test_mech_t *mech)
|
|||||||
EC_KEY_get0_public_key(o->key.ec), key, NULL);
|
EC_KEY_get0_public_key(o->key.ec), key, NULL);
|
||||||
|
|
||||||
/* Try to do the same with the card key */
|
/* Try to do the same with the card key */
|
||||||
pkcs11_secret_len = pkcs11_derive(o, info, key, mech, &pkcs11_secret);
|
|
||||||
|
/* Convert the public key to the octet string */
|
||||||
|
group = EC_KEY_get0_group(key);
|
||||||
|
publickey = EC_KEY_get0_public_key(key);
|
||||||
|
pub_len = EC_POINT_point2oct(group, publickey,
|
||||||
|
POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
|
||||||
|
if (pub_len == 0) {
|
||||||
|
debug_print(" [ KEY %s ] Failed to allocate memory for secret", o->id_str);
|
||||||
|
EC_KEY_free(key);
|
||||||
|
OPENSSL_free(secret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pub = malloc(pub_len);
|
||||||
|
if (pub == NULL) {
|
||||||
|
debug_print(" [ OK %s ] Failed to allocate memory", o->id_str);
|
||||||
|
EC_KEY_free(key);
|
||||||
|
OPENSSL_free(secret);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pub_len = EC_POINT_point2oct(group, publickey,
|
||||||
|
POINT_CONVERSION_UNCOMPRESSED, pub, pub_len, NULL);
|
||||||
|
if (pub_len == 0) {
|
||||||
|
debug_print(" [ KEY %s ] Failed to allocate memory for secret", o->id_str);
|
||||||
|
EC_KEY_free(key);
|
||||||
|
OPENSSL_free(secret);
|
||||||
|
free(pub);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pkcs11_secret_len = pkcs11_derive(o, info, pub, pub_len, mech, &pkcs11_secret);
|
||||||
|
free(pub);
|
||||||
|
|
||||||
if (secret_len == pkcs11_secret_len && memcmp(secret, pkcs11_secret, secret_len) == 0) {
|
if (secret_len == pkcs11_secret_len && memcmp(secret, pkcs11_secret, secret_len) == 0) {
|
||||||
mech->result_flags |= FLAGS_DERIVE;
|
mech->result_flags |= FLAGS_DERIVE;
|
||||||
@ -197,16 +334,24 @@ void derive_tests(void **state) {
|
|||||||
if (objects.data[i].private_handle == CK_INVALID_HANDLE)
|
if (objects.data[i].private_handle == CK_INVALID_HANDLE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Skip the non EC keys */
|
|
||||||
if (objects.data[i].key_type != CKK_EC)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (j = 0; j < o->num_mechs; j++) {
|
for (j = 0; j < o->num_mechs; j++) {
|
||||||
if ((o->mechs[j].usage_flags & CKF_DERIVE) == 0
|
if ((o->mechs[j].usage_flags & CKF_DERIVE) == 0
|
||||||
|| ! o->derive_priv)
|
|| ! o->derive_priv)
|
||||||
continue;
|
continue;
|
||||||
errors += test_derive(&(objects.data[i]), info,
|
|
||||||
&(o->mechs[j]));
|
switch (o->key_type) {
|
||||||
|
case CKK_EC:
|
||||||
|
errors += test_derive(&(objects.data[i]), info,
|
||||||
|
&(o->mechs[j]));
|
||||||
|
break;
|
||||||
|
case CKK_EC_MONTGOMERY:
|
||||||
|
errors += test_derive_x25519(&(objects.data[i]), info,
|
||||||
|
&(o->mechs[j]));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Other keys do not support derivation */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,14 +363,17 @@ void derive_tests(void **state) {
|
|||||||
's', "MECHANISM",
|
's', "MECHANISM",
|
||||||
's', "DERIVE WORKS");
|
's', "DERIVE WORKS");
|
||||||
for (i = 0; i < objects.count; i++) {
|
for (i = 0; i < objects.count; i++) {
|
||||||
if (objects.data[i].key_type != CKK_EC)
|
if (objects.data[i].key_type != CKK_EC &&
|
||||||
|
objects.data[i].key_type != CKK_EC_MONTGOMERY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
test_cert_t *o = &objects.data[i];
|
test_cert_t *o = &objects.data[i];
|
||||||
printf("\n[%-6s] [%s]\n",
|
printf("\n[%-6s] [%s]\n",
|
||||||
o->id_str,
|
o->id_str,
|
||||||
o->label);
|
o->label);
|
||||||
printf("[ EC ] [%6lu] [ %s ] [ %s%s ]\n",
|
printf("[ %s ] [%6lu] [ %s ] [ %s%s ]\n",
|
||||||
|
(o->key_type == CKK_EC ? " EC " :
|
||||||
|
o->key_type == CKK_EC_MONTGOMERY ? "EC_M" : " ?? "),
|
||||||
o->bits,
|
o->bits,
|
||||||
o->verify_public == 1 ? " ./ " : " ",
|
o->verify_public == 1 ? " ./ " : " ",
|
||||||
o->derive_pub ? "[./]" : "[ ]",
|
o->derive_pub ? "[./]" : "[ ]",
|
||||||
|
@ -102,6 +102,27 @@ void supported_mechanisms_test(void **state) {
|
|||||||
P11TEST_FAIL(info, "Too many EC mechanisms (%d)", MAX_MECHS);
|
P11TEST_FAIL(info, "Too many EC mechanisms (%d)", MAX_MECHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We list all known edwards EC curve mechanisms */
|
||||||
|
if (mechanism_list[i] == CKM_EDDSA) {
|
||||||
|
if (token.num_ed_mechs < MAX_MECHS) {
|
||||||
|
mech = &token.ed_mechs[token.num_ed_mechs++];
|
||||||
|
mech->mech = mechanism_list[i];
|
||||||
|
mech->usage_flags = mechanism_info[i].flags;
|
||||||
|
} else
|
||||||
|
P11TEST_FAIL(info, "Too many edwards EC mechanisms (%d)", MAX_MECHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We list all known montgomery EC curve mechanisms */
|
||||||
|
if (mechanism_list[i] == CKM_XEDDSA
|
||||||
|
|| mechanism_list[i] == CKM_ECDH1_DERIVE) {
|
||||||
|
if (token.num_montgomery_mechs < MAX_MECHS) {
|
||||||
|
mech = &token.montgomery_mechs[token.num_montgomery_mechs++];
|
||||||
|
mech->mech = mechanism_list[i];
|
||||||
|
mech->usage_flags = mechanism_info[i].flags;
|
||||||
|
} else
|
||||||
|
P11TEST_FAIL(info, "Too many montgomery EC mechanisms (%d)", MAX_MECHS);
|
||||||
|
}
|
||||||
|
|
||||||
if ((mechanism_info[i].flags & CKF_GENERATE_KEY_PAIR) != 0) {
|
if ((mechanism_info[i].flags & CKF_GENERATE_KEY_PAIR) != 0) {
|
||||||
if (token.num_keygen_mechs < MAX_MECHS) {
|
if (token.num_keygen_mechs < MAX_MECHS) {
|
||||||
mech = &token.keygen_mechs[token.num_keygen_mechs++];
|
mech = &token.keygen_mechs[token.num_keygen_mechs++];
|
||||||
|
@ -77,8 +77,10 @@ void multipart_tests(void **state) {
|
|||||||
continue;
|
continue;
|
||||||
printf("[%-6s] [%s] [%6lu] [ %s ] [%s%s] [%s]\n",
|
printf("[%-6s] [%s] [%6lu] [ %s ] [%s%s] [%s]\n",
|
||||||
objects.data[i].id_str,
|
objects.data[i].id_str,
|
||||||
objects.data[i].key_type == CKK_RSA ? "RSA " :
|
(objects.data[i].key_type == CKK_RSA ? "RSA " :
|
||||||
objects.data[i].key_type == CKK_EC ? " EC " : " ?? ",
|
objects.data[i].key_type == CKK_EC ? " EC " :
|
||||||
|
objects.data[i].key_type == CKK_EC_EDWARDS ? "EC_E" :
|
||||||
|
objects.data[i].key_type == CKK_EC_MONTGOMERY ? "EC_M" : " ?? "),
|
||||||
objects.data[i].bits,
|
objects.data[i].bits,
|
||||||
objects.data[i].verify_public == 1 ? " ./ " : " ",
|
objects.data[i].verify_public == 1 ? " ./ " : " ",
|
||||||
objects.data[i].sign ? "[./] " : "[ ] ",
|
objects.data[i].sign ? "[./] " : "[ ] ",
|
||||||
|
@ -458,8 +458,34 @@ int verify_message_openssl(test_cert_t *o, token_info_t *info, CK_BYTE *message,
|
|||||||
rv, ERR_error_string(ERR_peek_last_error(), NULL));
|
rv, ERR_error_string(ERR_peek_last_error(), NULL));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
} else if (o->type == EVP_PKEY_ED25519) {
|
||||||
|
/* need to be created even though we do not do any MD */
|
||||||
|
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
|
||||||
|
|
||||||
|
rv = EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, o->key.pkey);
|
||||||
|
if (rv != 1) {
|
||||||
|
fprintf(stderr, " [FAIL %s ] EVP_DigestVerifyInit: rv = %lu: %s\n", o->id_str,
|
||||||
|
rv, ERR_error_string(ERR_peek_last_error(), NULL));
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = EVP_DigestVerify(ctx, sign, sign_length, message, message_length);
|
||||||
|
if (rv == 1) {
|
||||||
|
debug_print(" [ OK %s ] EdDSA Signature of length %lu is valid.",
|
||||||
|
o->id_str, message_length);
|
||||||
|
mech->result_flags |= FLAGS_SIGN_OPENSSL;
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, " [FAIL %s ] EVP_DigestVerifyInit: rv = %lu: %s\n", o->id_str,
|
||||||
|
rv, ERR_error_string(ERR_peek_last_error(), NULL));
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, " [ KEY %s ] Unknown type. Not verifying", o->id_str);
|
fprintf(stderr, " [ KEY %s ] Unknown type. Not verifying\n", o->id_str);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -557,7 +583,7 @@ int sign_verify_test(test_cert_t *o, token_info_t *info, test_mech_t *mech,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o->type != EVP_PK_EC && o->type != EVP_PK_RSA) {
|
if (o->type != EVP_PK_EC && o->type != EVP_PK_RSA && o->type != EVP_PKEY_ED25519) {
|
||||||
debug_print(" [SKIP %s ] Skip non-RSA and non-EC key", o->id_str);
|
debug_print(" [SKIP %s ] Skip non-RSA and non-EC key", o->id_str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -656,8 +682,10 @@ void readonly_tests(void **state) {
|
|||||||
o->id_str,
|
o->id_str,
|
||||||
o->label);
|
o->label);
|
||||||
printf("[ %s ] [%6lu] [ %s ] [%s%s] [%s%s] [%s %s] [%s%s]\n",
|
printf("[ %s ] [%6lu] [ %s ] [%s%s] [%s%s] [%s %s] [%s%s]\n",
|
||||||
o->key_type == CKK_RSA ? "RSA " :
|
(o->key_type == CKK_RSA ? "RSA " :
|
||||||
o->key_type == CKK_EC ? " EC " : " ?? ",
|
o->key_type == CKK_EC ? " EC " :
|
||||||
|
o->key_type == CKK_EC_EDWARDS ? "EC_E" :
|
||||||
|
o->key_type == CKK_EC_MONTGOMERY ? "EC_M" : " ?? "),
|
||||||
o->bits,
|
o->bits,
|
||||||
o->verify_public == 1 ? " ./ " : " ",
|
o->verify_public == 1 ? " ./ " : " ",
|
||||||
o->sign ? "[./] " : "[ ] ",
|
o->sign ? "[./] " : "[ ] ",
|
||||||
|
@ -54,9 +54,9 @@ void usage_test(void **state) {
|
|||||||
fprintf(stderr, " [ ERROR %s ] If Unwrap is set, Wrap should be set too.\n",
|
fprintf(stderr, " [ ERROR %s ] If Unwrap is set, Wrap should be set too.\n",
|
||||||
objects.data[i].id_str);
|
objects.data[i].id_str);
|
||||||
}
|
}
|
||||||
if (objects.data[i].derive_pub != objects.data[i].derive_priv) {
|
if (objects.data[i].derive_pub) {
|
||||||
errors++;
|
errors++;
|
||||||
fprintf(stderr, " [ ERROR %s ] Derive should be set on both private and public part.\n",
|
fprintf(stderr, " [ ERROR %s ] Derive should not be set on public key\n",
|
||||||
objects.data[i].id_str);
|
objects.data[i].id_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,8 +99,10 @@ void usage_test(void **state) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
printf("[ %s ] [%6lu] [ %s ] [%s%s] [%s%s] [%s %s] [%s%s] [ %s ]\n",
|
printf("[ %s ] [%6lu] [ %s ] [%s%s] [%s%s] [%s %s] [%s%s] [ %s ]\n",
|
||||||
objects.data[i].key_type == CKK_RSA ? "RSA " :
|
(objects.data[i].key_type == CKK_RSA ? "RSA " :
|
||||||
objects.data[i].key_type == CKK_EC ? " EC " : " ?? ",
|
objects.data[i].key_type == CKK_EC ? " EC " :
|
||||||
|
objects.data[i].key_type == CKK_EC_EDWARDS ? "EC_E" :
|
||||||
|
objects.data[i].key_type == CKK_EC_MONTGOMERY ? "EC_M" : " ?? "),
|
||||||
objects.data[i].bits,
|
objects.data[i].bits,
|
||||||
objects.data[i].verify_public == 1 ? " ./ " : " ",
|
objects.data[i].verify_public == 1 ? " ./ " : " ",
|
||||||
objects.data[i].sign ? "[./] " : "[ ] ",
|
objects.data[i].sign ? "[./] " : "[ ] ",
|
||||||
@ -115,8 +117,10 @@ void usage_test(void **state) {
|
|||||||
P11TEST_DATA_ROW(info, 14,
|
P11TEST_DATA_ROW(info, 14,
|
||||||
's', objects.data[i].id_str,
|
's', objects.data[i].id_str,
|
||||||
's', objects.data[i].label,
|
's', objects.data[i].label,
|
||||||
's', objects.data[i].key_type == CKK_RSA ? "RSA" :
|
's', (objects.data[i].key_type == CKK_RSA ? "RSA " :
|
||||||
objects.data[i].key_type == CKK_EC ? "EC" : "??",
|
objects.data[i].key_type == CKK_EC ? " EC " :
|
||||||
|
objects.data[i].key_type == CKK_EC_EDWARDS ? "EC_E" :
|
||||||
|
objects.data[i].key_type == CKK_EC_MONTGOMERY ? "EC_M" : " ?? "),
|
||||||
'd', objects.data[i].bits,
|
'd', objects.data[i].bits,
|
||||||
's', objects.data[i].verify_public == 1 ? "YES" : "",
|
's', objects.data[i].verify_public == 1 ? "YES" : "",
|
||||||
's', objects.data[i].sign ? "YES" : "",
|
's', objects.data[i].sign ? "YES" : "",
|
||||||
|
@ -80,6 +80,10 @@ typedef struct {
|
|||||||
size_t num_rsa_mechs;
|
size_t num_rsa_mechs;
|
||||||
test_mech_t ec_mechs[MAX_MECHS];
|
test_mech_t ec_mechs[MAX_MECHS];
|
||||||
size_t num_ec_mechs;
|
size_t num_ec_mechs;
|
||||||
|
test_mech_t ed_mechs[MAX_MECHS];
|
||||||
|
size_t num_ed_mechs;
|
||||||
|
test_mech_t montgomery_mechs[MAX_MECHS];
|
||||||
|
size_t num_montgomery_mechs;
|
||||||
test_mech_t keygen_mechs[MAX_MECHS];
|
test_mech_t keygen_mechs[MAX_MECHS];
|
||||||
size_t num_keygen_mechs;
|
size_t num_keygen_mechs;
|
||||||
} token_info_t;
|
} token_info_t;
|
||||||
|
Loading…
Reference in New Issue
Block a user