Skip to content

Commit

Permalink
Fix importing EdDSA keys from OpenSSL
Browse files Browse the repository at this point in the history
Signed-off-by: Jakub Jelen <[email protected]>
  • Loading branch information
Jakuje committed Nov 13, 2024
1 parent e064032 commit 4b510c7
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 7 deletions.
22 changes: 17 additions & 5 deletions src/keymgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1396,8 +1396,8 @@ static int p11prov_ec_match(const void *keydata1, const void *keydata2,
return p11prov_common_match(keydata1, keydata2, CKK_EC, selection);
}

static int p11prov_ec_import(void *keydata, int selection,
const OSSL_PARAM params[])
static int p11prov_ec_import_genr(CK_KEY_TYPE key_type, void *keydata,
int selection, const OSSL_PARAM params[])
{
P11PROV_OBJ *key = (P11PROV_OBJ *)keydata;
CK_OBJECT_CLASS class = CKO_PUBLIC_KEY;
Expand Down Expand Up @@ -1426,13 +1426,19 @@ static int p11prov_ec_import(void *keydata, int selection,
}
}

rv = p11prov_obj_import_key(key, CKK_EC, class, params);
rv = p11prov_obj_import_key(key, key_type, class, params);
if (rv != CKR_OK) {
return RET_OSSL_ERR;
}
return RET_OSSL_OK;
}

static int p11prov_ec_import(void *keydata, int selection,
const OSSL_PARAM params[])
{
return p11prov_ec_import_genr(CKK_EC, keydata, selection, params);
}

static int p11prov_ec_export(void *keydata, int selection, OSSL_CALLBACK *cb_fn,
void *cb_arg)
{
Expand Down Expand Up @@ -1915,6 +1921,12 @@ static int p11prov_ed_export(void *keydata, int selection, OSSL_CALLBACK *cb_fn,
return RET_OSSL_ERR;
}

static int p11prov_ed_import(void *keydata, int selection,
const OSSL_PARAM params[])
{
return p11prov_ec_import_genr(CKK_EC_EDWARDS, keydata, selection, params);
}

static const OSSL_PARAM *p11prov_ed_import_types(int selection)
{
static const OSSL_PARAM p11prov_ed_imp_key_types[] = {
Expand Down Expand Up @@ -2082,7 +2094,7 @@ const OSSL_DISPATCH p11prov_ed25519_keymgmt_functions[] = {
DISPATCH_KEYMGMT_ELEM(ec, FREE, free),
DISPATCH_KEYMGMT_ELEM(ec, HAS, has),
DISPATCH_KEYMGMT_ELEM(ed, MATCH, match),
DISPATCH_KEYMGMT_ELEM(ec, IMPORT, import),
DISPATCH_KEYMGMT_ELEM(ed, IMPORT, import),
DISPATCH_KEYMGMT_ELEM(ed, IMPORT_TYPES, import_types),
DISPATCH_KEYMGMT_ELEM(ed, EXPORT, export),
DISPATCH_KEYMGMT_ELEM(ed, EXPORT_TYPES, export_types),
Expand All @@ -2106,7 +2118,7 @@ const OSSL_DISPATCH p11prov_ed448_keymgmt_functions[] = {
DISPATCH_KEYMGMT_ELEM(ec, FREE, free),
DISPATCH_KEYMGMT_ELEM(ec, HAS, has),
DISPATCH_KEYMGMT_ELEM(ed, MATCH, match),
DISPATCH_KEYMGMT_ELEM(ec, IMPORT, import),
DISPATCH_KEYMGMT_ELEM(ed, IMPORT, import),
DISPATCH_KEYMGMT_ELEM(ed, IMPORT_TYPES, import_types),
DISPATCH_KEYMGMT_ELEM(ed, EXPORT, export),
DISPATCH_KEYMGMT_ELEM(ed, EXPORT_TYPES, export_types),
Expand Down
145 changes: 143 additions & 2 deletions src/objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -2974,6 +2974,134 @@ static CK_RV prep_ec_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
return rv;
}

static CK_RV prep_ed_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
struct pool_find_ctx *findctx)
{
OSSL_PARAM tmp;
const OSSL_PARAM *p;

data_buffer digest_data[4];
data_buffer digest = { 0 };

const unsigned char *ecparams = NULL;
int len, i;
CK_RV rv;

if (findctx->numattrs != MAX_ATTRS_SIZE) {
return CKR_ARGUMENTS_BAD;
}
findctx->numattrs = 0;

switch (findctx->class) {
case CKO_PUBLIC_KEY:
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
if (!p) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Missing %s",
OSSL_PKEY_PARAM_PUB_KEY);
rv = CKR_KEY_INDIGESTIBLE;
goto done;
}

if (p->data_size == ED25519_BYTE_SIZE) {
ecparams = ed25519_ec_params;
len = ED25519_EC_PARAMS_LEN;
findctx->bit_size = ED25519_BIT_SIZE;
findctx->key_size = ED25519_BYTE_SIZE;
} else if (p->data_size == ED448_BYTE_SIZE) {
ecparams = ed448_ec_params;
len = ED448_EC_PARAMS_LEN;
findctx->bit_size = ED448_BIT_SIZE;
findctx->key_size = ED448_BYTE_SIZE;
} else {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Public key of unknown length %d",
p->data_size);
rv = CKR_KEY_INDIGESTIBLE;
goto done;
}

rv = param_to_attr(ctx, params, OSSL_PKEY_PARAM_PUB_KEY,
&findctx->attrs[0], CKA_P11PROV_PUB_KEY, false);
if (rv != CKR_OK) {
goto done;
}

findctx->numattrs++;

break;
case CKO_PRIVATE_KEY:
/* A Token would never allow us to search by private exponent,
* so we store a hash of the private key in CKA_ID */
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
if (!p) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Missing %s",
OSSL_PKEY_PARAM_PRIV_KEY);
return CKR_KEY_INDIGESTIBLE;
}

i = 0;

if (p->data_size == ED25519_BYTE_SIZE) {
ecparams = ed25519_ec_params;
len = ED25519_EC_PARAMS_LEN;
findctx->bit_size = ED25519_BIT_SIZE;
findctx->key_size = ED25519_BYTE_SIZE;
} else if (p->data_size == ED448_BYTE_SIZE) {
ecparams = ed448_ec_params;
len = ED448_EC_PARAMS_LEN;
findctx->bit_size = ED448_BIT_SIZE;
findctx->key_size = ED448_BYTE_SIZE;
} else {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Private key of unknown length %d",
p->data_size);
rv = CKR_KEY_INDIGESTIBLE;
goto done;
}

/* prefix */
digest_data[i].data = (uint8_t *)"PrivKey";
digest_data[i].length = 7;
i++;

digest_data[i].data = (CK_BYTE *)ecparams;
digest_data[i].length = len;
i++;

digest_data[i].data = p->data;
digest_data[i].length = p->data_size;
i++;

digest_data[i].data = NULL;

rv = p11prov_digest_util(ctx, "sha256", NULL, digest_data, &digest);
if (rv != CKR_OK) {
return rv;
}
findctx->attrs[0].type = CKA_ID;
findctx->attrs[0].pValue = digest.data;
findctx->attrs[0].ulValueLen = digest.length;
findctx->numattrs++;

break;
default:
return CKR_GENERAL_ERROR;
}

/* common params */
tmp.key = "EC Params";
tmp.data = (CK_BYTE *)ecparams;
tmp.data_size = len;
rv = param_to_attr(ctx, &tmp, tmp.key, &findctx->attrs[findctx->numattrs],
CKA_EC_PARAMS, false);
if (rv != CKR_OK) {
goto done;
}
findctx->numattrs++;
rv = CKR_OK;

done:
return rv;
}

static CK_RV return_dup_key(P11PROV_OBJ *dst, P11PROV_OBJ *src)
{
CK_RV rv;
Expand Down Expand Up @@ -3073,14 +3201,21 @@ static CK_RV p11prov_obj_import_public_key(P11PROV_OBJ *key, CK_KEY_TYPE type,
break;

case CKK_EC:
case CKK_EC_EDWARDS:
rv = prep_ec_find(ctx, params, &findctx);
if (rv != CKR_OK) {
goto done;
}
allocattrs = EC_ATTRS_NUM;
break;

case CKK_EC_EDWARDS:
rv = prep_ed_find(ctx, params, &findctx);
if (rv != CKR_OK) {
goto done;
}
allocattrs = EC_ATTRS_NUM;
break;

default:
P11PROV_raise(key->ctx, CKR_KEY_INDIGESTIBLE,
"Unsupported key type: %08lx", type);
Expand Down Expand Up @@ -3620,13 +3755,19 @@ static CK_RV p11prov_obj_import_private_key(P11PROV_OBJ *key, CK_KEY_TYPE type,
break;

case CKK_EC:
case CKK_EC_EDWARDS:
rv = prep_ec_find(ctx, params, &findctx);
if (rv != CKR_OK) {
goto done;
}
break;

case CKK_EC_EDWARDS:
rv = prep_ed_find(ctx, params, &findctx);
if (rv != CKR_OK) {
goto done;
}
break;

default:
P11PROV_raise(key->ctx, CKR_KEY_INDIGESTIBLE,
"Unsupported key type: %08lx", type);
Expand Down

0 comments on commit 4b510c7

Please sign in to comment.