Skip to content

Commit

Permalink
Detect compressed EC points and convert to uncompressed
Browse files Browse the repository at this point in the history
openssl/openssl#16595

Providers may export EC points in compressed format, e.g.,
OpenSSL < 3.0.8, and this format may not actually match
the OSSL_PARAM "point-format". Use heuristics to
detect compressed points and convert to uncompressed.

Addresses #348

Signed-off-by: S-P Chan <[email protected]>
  • Loading branch information
space88man authored and simo5 committed Feb 26, 2024
1 parent c578c41 commit 3bb9a96
Showing 1 changed file with 71 additions and 8 deletions.
79 changes: 71 additions & 8 deletions src/objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -2508,11 +2508,21 @@ static CK_RV prep_rsa_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
return CKR_OK;
}

/* P-521 ~ 133 bytes, this should suffice */
#define MAX_EC_PUB_KEY_SIZE 150
static CK_RV prep_ec_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
struct pool_find_ctx *findctx)
{
EC_GROUP *group = NULL;
EC_POINT *point = NULL;
BN_CTX *bn_ctx = NULL;
int ret, plen;

OSSL_PARAM tmp;
const OSSL_PARAM *p;
OSSL_PARAM pub_key[2] = { 0 };
uint8_t pub_data[MAX_EC_PUB_KEY_SIZE];

const char *curve_name = NULL;
int curve_nid;
unsigned char *ecparams = NULL;
Expand All @@ -2524,20 +2534,67 @@ static CK_RV prep_ec_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
}
findctx->numattrs = 0;

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

group = EC_GROUP_new_from_params(params, p11prov_ctx_get_libctx(ctx), NULL);
if (!group) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Unable to decode ec group");
rv = CKR_KEY_INDIGESTIBLE;
goto done;
}

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);
EC_GROUP_free(group);
return CKR_KEY_INDIGESTIBLE;
}

/* Providers may export in any format - OpenSSL < 3.0.8
* ignores the "point-format" OSSL_PARAM and unconditionally uses
* compressed format:
* - https://github.com/openssl/openssl/pull/16624
* - https://github.com/openssl/openssl/issues/16595
*
* Convert from compressed to uncompressed if necessary
*/
if (((char *)p->data)[0] == '\x02' || ((char *)p->data)[0] == '\x03') {
P11PROV_debug("OpenSSL 3.0.7 BUG - received compressed EC public key");
pub_key[0].key = OSSL_PKEY_PARAM_PUB_KEY;
pub_key[0].data_type = p->data_type;
pub_key[0].data = pub_data;

point = EC_POINT_new(group);
bn_ctx = BN_CTX_new();
ret = EC_POINT_oct2point(group, point, p->data, p->data_size, bn_ctx);
if (!ret) {
goto done0;
}

plen = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED,
pub_key[0].data, MAX_EC_PUB_KEY_SIZE, bn_ctx);
if (!plen) {
ret = CKR_KEY_INDIGESTIBLE;
goto done0;
}

pub_key[0].data_size = plen;
ret = param_to_attr(ctx, pub_key, OSSL_PKEY_PARAM_PUB_KEY,
&findctx->attrs[0], CKA_P11PROV_PUB_KEY, false);
if (ret != CKR_OK) {
goto done0;
}
EC_POINT_free(point);
BN_CTX_free(bn_ctx);
} else {
rv = param_to_attr(ctx, params, OSSL_PKEY_PARAM_PUB_KEY,
&findctx->attrs[0], CKA_P11PROV_PUB_KEY, false);
if (rv != CKR_OK) {
return rv;
}
}

findctx->numattrs++;

curve_nid = EC_GROUP_get_curve_name(group);
if (curve_nid != NID_undef) {
curve_name = OSSL_EC_curve_nid2name(curve_nid);
Expand Down Expand Up @@ -2589,11 +2646,17 @@ static CK_RV prep_ec_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
findctx->bit_size = EC_GROUP_order_bits(group);
findctx->key_size = (findctx->bit_size + 7) / 8;
rv = CKR_OK;

done:
OPENSSL_free(ecparams);
EC_GROUP_free(group);
return rv;

done0:

EC_GROUP_free(group);
EC_POINT_free(point);
BN_CTX_free(bn_ctx);
return ret;
}

static CK_RV return_dup_key(P11PROV_OBJ *dst, P11PROV_OBJ *src)
Expand Down

0 comments on commit 3bb9a96

Please sign in to comment.