Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TLS13-KDF #446

Merged
merged 4 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
623 changes: 513 additions & 110 deletions src/kdf.c

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/kdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
}
extern const void *p11prov_hkdf_static_ctx;
extern const OSSL_DISPATCH p11prov_hkdf_kdf_functions[];
extern const OSSL_DISPATCH p11prov_tls13_kdf_functions[];

#endif /* _KDF_H */
15 changes: 14 additions & 1 deletion src/keymgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,18 @@ static int p11prov_ec_get_params(void *keydata, OSSL_PARAM params[])
memcpy(p->data, pub_key->pValue, pub_key->ulValueLen);
}
}
p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
if (p) {
bool compressed = p11prov_obj_get_ec_compressed(key);
if (compressed) {
ret = OSSL_PARAM_set_utf8_string(p, "compressed");
} else {
ret = OSSL_PARAM_set_utf8_string(p, "uncompressed");
}
if (ret != RET_OSSL_OK) {
return ret;
}
}

return RET_OSSL_OK;
}
Expand All @@ -1655,10 +1667,11 @@ static const OSSL_PARAM *p11prov_ec_gettable_params(void *provctx)
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_X, NULL, 0),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_EC_PUB_Y, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, NULL,
0),
/*
* OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAM
* OSSL_PKEY_PARAM_EC_ENCODING
* OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT
* OSSL_PKEY_PARAM_EC_FIELD_TYPE
* OSSL_PKEY_PARAM_EC_P
* OSSL_PKEY_PARAM_EC_A
Expand Down
182 changes: 69 additions & 113 deletions src/objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -1728,6 +1728,20 @@ const char *p11prov_obj_get_ec_group_name(P11PROV_OBJ *obj)
return (const char *)attr->pValue;
}

bool p11prov_obj_get_ec_compressed(P11PROV_OBJ *obj)
{
CK_ATTRIBUTE *pub_key;
uint8_t *buf;

pub_key = p11prov_obj_get_attr(obj, CKA_P11PROV_PUB_KEY);
if (!pub_key) {
return false;
}
buf = pub_key->pValue;

return (buf[0] & 0x01) == 0x01;
}

static int ossl_param_construct_bn(P11PROV_CTX *provctx, OSSL_PARAM *param,
const char *key, const BIGNUM *val)
{
Expand Down Expand Up @@ -2663,100 +2677,12 @@ static CK_RV param_to_attr(P11PROV_CTX *ctx, const OSSL_PARAM params[],
return CKR_OK;
}

static CK_RV digest(P11PROV_CTX *ctx, const uint8_t *prefx, size_t plen,
const uint8_t *data1, size_t len1, const uint8_t *data2,
size_t len2, const uint8_t *data3, size_t len3,
uint8_t **out, size_t *outlen)
{
EVP_MD_CTX *mdctx = NULL;
EVP_MD *md = NULL;
unsigned char *dgst = NULL;
unsigned int dlen = 0;
CK_RV rv;
int err;

md = EVP_MD_fetch(p11prov_ctx_get_libctx(ctx), "sha256", NULL);
if (!md) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "Failed to fetch sha256 digest");
goto done;
}
dlen = EVP_MD_get_size(md);
if (dlen == -1) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "Failed to get sha256 digest length");
goto done;
}
dgst = OPENSSL_malloc(dlen);
if (!dgst) {
rv = CKR_HOST_MEMORY;
goto done;
}
mdctx = EVP_MD_CTX_new();
if (!mdctx) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_MD_CTX_new failed");
goto done;
}
err = EVP_DigestInit(mdctx, md);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestInit failed");
goto done;
}
if (len1 > 0) {
err = EVP_DigestUpdate(mdctx, data1, len1);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestUpdate(1) failed");
goto done;
}
}
if (len2 > 0) {
err = EVP_DigestUpdate(mdctx, data2, len2);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestUpdate(2) failed");
goto done;
}
}
if (len3 > 0) {
err = EVP_DigestUpdate(mdctx, data3, len3);
if (err != RET_OSSL_OK) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestUpdate(3) failed");
goto done;
}
}
err = EVP_DigestFinal(mdctx, dgst, &dlen);
if (err != RET_OSSL_OK || dlen == 0) {
rv = CKR_GENERAL_ERROR;
P11PROV_raise(ctx, rv, "EVP_DigestFinal(2) failed");
goto done;
}

*out = dgst;
*outlen = dlen;
dgst = NULL;
rv = CKR_OK;

done:
OPENSSL_free(dgst);
EVP_MD_CTX_free(mdctx);
EVP_MD_free(md);
return rv;
}

static CK_RV prep_rsa_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
struct pool_find_ctx *findctx)
{
const OSSL_PARAM *pn;
const OSSL_PARAM *pe;
const OSSL_PARAM *pd;
const char *prefix = "PrivKey";
size_t prefix_len = 7;
uint8_t *attr_data = NULL;
size_t attr_size = 0;
data_buffer digest_data[5];
data_buffer digest = { 0 };
const OSSL_PARAM *p;
size_t key_size;
CK_RV rv;

Expand Down Expand Up @@ -2786,39 +2712,50 @@ static CK_RV prep_rsa_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
/* A Token would never allow us to search by private exponent,
* so we store a hash of the private key in CKA_ID */

pn = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N);
if (!pn) {
/* prefix */
digest_data[0].data = (uint8_t *)"PrivKey";
digest_data[0].length = 7;

p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_N);
if (!p) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Missing %s",
OSSL_PKEY_PARAM_RSA_N);
return CKR_KEY_INDIGESTIBLE;
}
digest_data[1].data = p->data;
digest_data[1].length = p->data_size;
key_size = p->data_size;

pe = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E);
if (!pe) {
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_E);
if (!p) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Missing %s",
OSSL_PKEY_PARAM_RSA_E);
return CKR_KEY_INDIGESTIBLE;
}
digest_data[2].data = p->data;
digest_data[2].length = p->data_size;

pd = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
if (!pd) {
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_D);
if (!p) {
P11PROV_raise(ctx, CKR_KEY_INDIGESTIBLE, "Missing %s",
OSSL_PKEY_PARAM_RSA_D);
return CKR_KEY_INDIGESTIBLE;
}
digest_data[3].data = p->data;
digest_data[3].length = p->data_size;

digest_data[4].data = NULL;

rv = p11prov_digest_util(ctx, "sha256", NULL, digest_data, &digest);

rv = digest(ctx, (uint8_t *)prefix, prefix_len, pn->data, pn->data_size,
pe->data, pe->data_size, pd->data, pd->data_size,
&attr_data, &attr_size);
if (rv != CKR_OK) {
return rv;
}
findctx->attrs[0].type = CKA_ID;
findctx->attrs[0].pValue = attr_data;
findctx->attrs[0].ulValueLen = attr_size;
findctx->attrs[0].pValue = digest.data;
findctx->attrs[0].ulValueLen = digest.length;
findctx->numattrs++;

key_size = pn->data_size;
break;
default:
return CKR_GENERAL_ERROR;
Expand All @@ -2844,15 +2781,13 @@ static CK_RV prep_ec_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
OSSL_PARAM pub_key[2] = { 0 };
uint8_t pub_data[MAX_EC_PUB_KEY_SIZE];

const char *prefix = "PrivKey";
size_t prefix_len = 7;
uint8_t *attr_data = NULL;
size_t attr_size = 0;
data_buffer digest_data[5];
data_buffer digest = { 0 };

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

if (findctx->numattrs != MAX_ATTRS_SIZE) {
Expand Down Expand Up @@ -2956,15 +2891,36 @@ static CK_RV prep_ec_find(P11PROV_CTX *ctx, const OSSL_PARAM params[],
return CKR_KEY_INDIGESTIBLE;
}

rv = digest(ctx, (uint8_t *)prefix, prefix_len, (uint8_t *)curve_name,
curve_name ? strlen(curve_name) : 0, ecparams, len, p->data,
p->data_size, &attr_data, &attr_size);
i = 0;

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

if (curve_name) {
digest_data[i].data = (uint8_t *)curve_name;
digest_data[i].length = strlen(curve_name);
i++;
}

digest_data[i].data = 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 = attr_data;
findctx->attrs[0].ulValueLen = attr_size;
findctx->attrs[0].pValue = digest.data;
findctx->attrs[0].ulValueLen = digest.length;
findctx->numattrs++;

break;
Expand Down
1 change: 1 addition & 0 deletions src/objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ CK_RV p11prov_obj_set_attributes(P11PROV_CTX *ctx, P11PROV_SESSION *session,
P11PROV_OBJ *obj, CK_ATTRIBUTE *template,
CK_ULONG tsize);
const char *p11prov_obj_get_ec_group_name(P11PROV_OBJ *obj);
bool p11prov_obj_get_ec_compressed(P11PROV_OBJ *obj);
int p11prov_obj_export_public_key(P11PROV_OBJ *obj, CK_KEY_TYPE key_type,
bool search_related, OSSL_CALLBACK *cb_fn,
void *cb_arg);
Expand Down
1 change: 1 addition & 0 deletions src/provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,7 @@ static CK_RV operations_init(P11PROV_CTX *ctx)
break;
case CKM_HKDF_DERIVE:
ADD_ALGO(HKDF, hkdf, kdf);
ADD_ALGO(TLS13_KDF, tls13, kdf);
ADD_ALGO(HKDF, hkdf, exchange);
UNCHECK_MECHS(CKM_HKDF_DERIVE);
break;
Expand Down
3 changes: 3 additions & 0 deletions src/provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
#define P11PROV_NAMES_RAND "PKCS11-RAND"
#define P11PROV_DESCS_RAND "PKCS11 Random Generator"
#define P11PROV_NAME_CERTIFICATE "CERTIFICATE"
#define P11PROV_NAME_TLS13_KDF "TLS13-KDF"
#define P11PROV_NAMES_TLS13_KDF P11PROV_NAME_TLS13_KDF
#define P11PROV_DESCS_TLS13_KDF "PKCS11 TLS 1.3 HKDF Implementation"

#define P11PROV_PARAM_URI "pkcs11_uri"
#define P11PROV_PARAM_KEY_USAGE "pkcs11_key_usage"
Expand Down
Loading
Loading