Skip to content

Commit

Permalink
Add support compat decoding of CKA_EC_POINT
Browse files Browse the repository at this point in the history
For CCK_EC_EDWARDS and CKK_EC_MONTGOMERY curves the spec assumes a plain
byte array for CKA_EC_POINT, but many implementations incorrectly use
DER OCTET STRING encoding for this point.

DEtecting this is easy when reading from the token, and hpefully all
tokens will support handling DER encoded input (as backwards
compatibility) when importing objects.

Signed-off-by: Simo Sorce <[email protected]>
  • Loading branch information
simo5 committed Nov 26, 2024
1 parent b0cc1ff commit f6c1a9a
Showing 1 changed file with 64 additions and 22 deletions.
86 changes: 64 additions & 22 deletions src/objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,53 @@ static int fetch_rsa_key(P11PROV_CTX *ctx, P11PROV_SESSION *session,
return CKR_OK;
}

static CK_RV decode_ec_point(CK_KEY_TYPE key_type, CK_ATTRIBUTE *attr,
struct data_buffer *ec_point)
{
ASN1_OCTET_STRING *octet;
const unsigned char *val;
CK_RV ret = CKR_GENERAL_ERROR;
int err;

/* in d2i functions 'in' is overwritten to return the remainder of
* the buffer after parsing, so we always need to avoid passing in
* our pointer holders, to avoid having them clobbered */
val = attr->pValue;
octet = d2i_ASN1_OCTET_STRING(NULL, (const unsigned char **)&val,
attr->ulValueLen);
if (!octet) {
/* 3.1 spec says CKA_EC_POINT is not DER encoded for Edwards and
* Montgomery curves so do not fail in that case and just take
* the value as is */
if (key_type == CKK_EC) {
return CKR_KEY_INDIGESTIBLE;
} else {
octet = ASN1_OCTET_STRING_new();
if (!octet) {
return CKR_HOST_MEMORY;
}
/* makes a copy of the value */
err = ASN1_OCTET_STRING_set(octet, attr->pValue, attr->ulValueLen);
if (err != RET_OSSL_OK) {
ret = CKR_HOST_MEMORY;
goto done;
}
}
}

ec_point->data = octet->data;
ec_point->length = octet->length;

/* moved octet data, do not free it */
octet->data = NULL;
octet->length = 0;

ret = CKR_OK;
done:
ASN1_OCTET_STRING_free(octet);
return ret;
}

const CK_BYTE ed25519_ec_params[] = { ED25519_EC_PARAMS };
const CK_BYTE ed448_ec_params[] = { ED448_EC_PARAMS };

Expand All @@ -679,7 +726,8 @@ static CK_RV pre_process_ec_key_data(P11PROV_OBJ *key)
int buffer_size;
const char *curve_name = NULL;
int curve_nid;
ASN1_OCTET_STRING *octet;
struct data_buffer ec_point = { 0 };
CK_RV ret;

attr = p11prov_obj_get_attr(key, CKA_EC_PARAMS);
if (!attr) {
Expand Down Expand Up @@ -778,21 +826,15 @@ static CK_RV pre_process_ec_key_data(P11PROV_OBJ *key)
return CKR_OK;
}

val = attr->pValue;
octet = d2i_ASN1_OCTET_STRING(NULL, (const unsigned char **)&val,
attr->ulValueLen);
if (!octet) {
return CKR_KEY_INDIGESTIBLE;
ret = decode_ec_point(type, attr, &ec_point);
if (ret != CKR_OK) {
return ret;
}

CKATTR_ASSIGN(key->attrs[key->numattrs], CKA_P11PROV_PUB_KEY, octet->data,
octet->length);
/* takes the data allocated in ec_point */
CKATTR_ASSIGN(key->attrs[key->numattrs], CKA_P11PROV_PUB_KEY,
ec_point.data, ec_point.length);
key->numattrs++;

/* moved octet data to attrs, do not free it */
octet->data = NULL;
octet->length = 0;
ASN1_OCTET_STRING_free(octet);
return CKR_OK;
}

Expand Down Expand Up @@ -2228,29 +2270,29 @@ CK_ATTRIBUTE *p11prov_obj_get_ec_public_raw(P11PROV_OBJ *key)

ec_point = p11prov_obj_get_attr(key, CKA_EC_POINT);
if (ec_point) {
const unsigned char *val;
ASN1_OCTET_STRING *octet;
struct data_buffer data = { 0 };
void *tmp_ptr;
CK_RV ret;

val = ec_point->pValue;
octet = d2i_ASN1_OCTET_STRING(NULL, (const unsigned char **)&val,
ec_point->ulValueLen);
if (!octet) {
P11PROV_raise(key->ctx, CKR_KEY_INDIGESTIBLE,
"Failed to decode CKA_EC_POINT");
ret = decode_ec_point(key->data.key.type, ec_point, &data);
if (ret != CKR_OK) {
P11PROV_raise(key->ctx, ret, "Failed to decode EC_POINT");
return NULL;
}

tmp_ptr = OPENSSL_realloc(key->attrs, sizeof(CK_ATTRIBUTE)
* (key->numattrs + 1));
if (!tmp_ptr) {
P11PROV_raise(key->ctx, CKR_HOST_MEMORY,
"Failed to allocate memory key attributes");
OPENSSL_free(data.data);
return NULL;
}
key->attrs = tmp_ptr;

/* takes the data allocated in data */
CKATTR_ASSIGN(key->attrs[key->numattrs], CKA_P11PROV_PUB_KEY,
octet->data, octet->length);
data.data, data.length);
key->numattrs++;

pub_key = &key->attrs[key->numattrs - 1];
Expand Down

0 comments on commit f6c1a9a

Please sign in to comment.