diff --git a/src/kdf.c b/src/kdf.c index 609d924d..a9b890c5 100644 --- a/src/kdf.c +++ b/src/kdf.c @@ -2,6 +2,7 @@ SPDX-License-Identifier: Apache-2.0 */ #include "provider.h" +#include "platform/endian.h" #include #include @@ -12,9 +13,23 @@ struct p11prov_kdf_ctx { CK_MECHANISM_TYPE mechtype; - CK_HKDF_PARAMS params; + int mode; + CK_MECHANISM_TYPE hash_mech; + CK_ULONG salt_type; + uint8_t *salt; + size_t saltlen; + uint8_t *info; + size_t infolen; + uint8_t *prefix; + uint8_t *label; + uint8_t *data; + size_t prefixlen; + size_t labellen; + size_t datalen; P11PROV_SESSION *session; + + bool is_tls13_kdf; }; typedef struct p11prov_kdf_ctx P11PROV_KDF_CTX; @@ -48,7 +63,7 @@ static void *p11prov_hkdf_newctx(void *provctx) hkdfctx->provctx = ctx; /* default mechanism */ - hkdfctx->mechtype = CKM_HKDF_DERIVE; + hkdfctx->mechtype = CKM_HKDF_DATA; return hkdfctx; } @@ -76,44 +91,146 @@ static void p11prov_hkdf_reset(void *ctx) hkdfctx->session = NULL; } - OPENSSL_clear_free(hkdfctx->params.pSalt, hkdfctx->params.ulSaltLen); - OPENSSL_clear_free(hkdfctx->params.pInfo, hkdfctx->params.ulInfoLen); + OPENSSL_clear_free(hkdfctx->salt, hkdfctx->saltlen); + OPENSSL_clear_free(hkdfctx->info, hkdfctx->infolen); + OPENSSL_clear_free(hkdfctx->prefix, hkdfctx->prefixlen); + OPENSSL_clear_free(hkdfctx->label, hkdfctx->labellen); + OPENSSL_clear_free(hkdfctx->data, hkdfctx->datalen); /* zero all */ memset(hkdfctx, 0, sizeof(*hkdfctx)); /* restore defaults */ hkdfctx->provctx = provctx; - hkdfctx->mechtype = CKM_HKDF_DERIVE; + hkdfctx->mechtype = CKM_HKDF_DATA; } -static int p11prov_hkdf_derive(void *ctx, unsigned char *key, size_t keylen, - const OSSL_PARAM params[]) +static CK_RV inner_pkcs11_key(P11PROV_KDF_CTX *hkdfctx, const uint8_t *key, + size_t keylen, P11PROV_OBJ **keyobj) { - P11PROV_KDF_CTX *hkdfctx = (P11PROV_KDF_CTX *)ctx; - CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; - CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; - CK_BBOOL val_true = CK_TRUE; + CK_SLOT_ID slotid = CK_UNAVAILABLE_INFORMATION; + CK_RV ret; + + if (hkdfctx->session == NULL) { + ret = p11prov_get_session(hkdfctx->provctx, &slotid, NULL, NULL, + hkdfctx->mechtype, NULL, NULL, false, false, + &hkdfctx->session); + if (ret != CKR_OK) { + return ret; + } + } + if (hkdfctx->session == NULL) { + return CKR_SESSION_HANDLE_INVALID; + } + + *keyobj = p11prov_create_secret_key(hkdfctx->provctx, hkdfctx->session, + true, (void *)key, keylen); + if (*keyobj == NULL) { + return CKR_KEY_HANDLE_INVALID; + } + return CKR_OK; +} + +static int inner_extract_key_value(P11PROV_CTX *ctx, P11PROV_SESSION *session, + CK_OBJECT_HANDLE dkey_handle, + unsigned char *key, size_t keylen) +{ + CK_ULONG key_size; + struct fetch_attrs attrs[1]; + int num = 0; + CK_RV ret; + + P11PROV_debug("HKDF derived key handle: %lu", dkey_handle); + FA_SET_BUF_VAL(attrs, num, CKA_VALUE, key, keylen, true); + ret = p11prov_fetch_attributes(ctx, session, dkey_handle, attrs, num); + if (ret != CKR_OK) { + P11PROV_raise(ctx, ret, "Failed to retrieve derived key"); + return ret; + } + FA_GET_LEN(attrs, 0, key_size); + if (key_size != keylen) { + ret = CKR_GENERAL_ERROR; + P11PROV_raise(ctx, ret, "Expected derived key of len %zu, but got %lu", + keylen, key_size); + return ret; + } + + return CKR_OK; +} + +static int inner_derive_key(P11PROV_CTX *ctx, P11PROV_OBJ *key, + P11PROV_SESSION **session, CK_MECHANISM *mechanism, + size_t keylen, CK_OBJECT_HANDLE *dkey_handle) +{ + CK_OBJECT_CLASS class = CKO_DATA; CK_BBOOL val_false = CK_FALSE; CK_ULONG key_size = keylen; - CK_ATTRIBUTE key_template[5] = { - { CKA_CLASS, &key_class, sizeof(key_class) }, - { CKA_KEY_TYPE, &key_type, sizeof(key_type) }, - { CKA_SENSITIVE, &val_false, sizeof(val_false) }, - { CKA_EXTRACTABLE, &val_true, sizeof(val_true) }, + CK_ATTRIBUTE key_template[3] = { + { CKA_CLASS, &class, sizeof(class) }, + { CKA_TOKEN, &val_false, sizeof(val_false) }, { CKA_VALUE_LEN, &key_size, sizeof(key_size) }, }; - CK_MECHANISM mechanism; CK_OBJECT_HANDLE pkey_handle; - CK_OBJECT_HANDLE dkey_handle; CK_SLOT_ID slotid; - struct fetch_attrs attrs[1]; - int num = 0; + CK_RV ret; + + pkey_handle = p11prov_obj_get_handle(key); + if (pkey_handle == CK_INVALID_HANDLE) { + ret = CKR_KEY_HANDLE_INVALID; + P11PROV_raise(ctx, ret, "Invalid key handle"); + return ret; + } + + slotid = p11prov_obj_get_slotid(key); + if (slotid == CK_UNAVAILABLE_INFORMATION) { + ret = CKR_SLOT_ID_INVALID; + P11PROV_raise(ctx, ret, "Invalid key slotid"); + return ret; + } + + return p11prov_derive_key(ctx, slotid, mechanism, pkey_handle, key_template, + 3, session, dkey_handle); +} + +static int p11prov_hkdf_derive(void *ctx, unsigned char *key, size_t keylen, + const OSSL_PARAM params[]) +{ + P11PROV_KDF_CTX *hkdfctx = (P11PROV_KDF_CTX *)ctx; + CK_HKDF_PARAMS ck_params = { + .bExtract = (hkdfctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND + || hkdfctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_ONLY) + ? CK_TRUE + : CK_FALSE, + .bExpand = (hkdfctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND + || hkdfctx->mode == EVP_KDF_HKDF_MODE_EXPAND_ONLY) + ? CK_TRUE + : CK_FALSE, + .prfHashMechanism = hkdfctx->hash_mech, + .ulSaltType = hkdfctx->salt_type, + .pSalt = hkdfctx->salt, + .ulSaltLen = hkdfctx->saltlen, + .hSaltKey = CK_INVALID_HANDLE, + .pInfo = hkdfctx->info, + .ulInfoLen = hkdfctx->infolen, + }; + CK_MECHANISM mechanism = { + .mechanism = hkdfctx->mechtype, + .pParameter = &ck_params, + .ulParameterLen = sizeof(ck_params), + }; + + CK_OBJECT_HANDLE dkey_handle; CK_RV ret; P11PROV_debug("hkdf derive (ctx:%p, key:%p[%zu], params:%p)", ctx, key, keylen, params); + ret = p11prov_hkdf_set_ctx_params(ctx, params); + if (ret != RET_OSSL_OK) { + P11PROV_raise(hkdfctx->provctx, ret, "Invalid params"); + return RET_OSSL_ERR; + } + if (hkdfctx->key == NULL || key == NULL) { ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); return RET_OSSL_ERR; @@ -124,49 +241,266 @@ static int p11prov_hkdf_derive(void *ctx, unsigned char *key, size_t keylen, return RET_OSSL_ERR; } - mechanism.mechanism = hkdfctx->mechtype; - mechanism.pParameter = &hkdfctx->params; - mechanism.ulParameterLen = sizeof(hkdfctx->params); + /* no salt ? */ + if (hkdfctx->salt_type == 0) { + ck_params.ulSaltType = CKF_HKDF_SALT_NULL; + } - pkey_handle = p11prov_obj_get_handle(hkdfctx->key); - if (pkey_handle == CK_INVALID_HANDLE) { - P11PROV_raise(hkdfctx->provctx, CKR_KEY_HANDLE_INVALID, - "Provided key has invalid handle"); + ret = inner_derive_key(hkdfctx->provctx, hkdfctx->key, &hkdfctx->session, + &mechanism, keylen, &dkey_handle); + if (ret != CKR_OK) { return RET_OSSL_ERR; } - /* no salt ? */ - if (hkdfctx->params.ulSaltType == 0) { - hkdfctx->params.ulSaltType = CKF_HKDF_SALT_NULL; + ret = inner_extract_key_value(hkdfctx->provctx, hkdfctx->session, + dkey_handle, key, keylen); + if (ret != CKR_OK) { + return RET_OSSL_ERR; } - slotid = p11prov_obj_get_slotid(hkdfctx->key); - if (slotid == CK_UNAVAILABLE_INFORMATION) { - P11PROV_raise(hkdfctx->provctx, CKR_SLOT_ID_INVALID, - "Provided key has invalid slot"); - return RET_OSSL_ERR; + return RET_OSSL_OK; +} + +/* ref: RFC 8446 - 7.1 Key Schedule + * Citation: + * HKDF-Expand-Label(Secret, Label, Context, Length) = + HKDF-Expand(Secret, HkdfLabel, Length) + * + * Where HkdfLabel is specified as: + * + * struct { + * uint16 length = Length; + * opaque label<7..255> = "tls13 " + Label; + * opaque context<0..255> = Context; + * } HkdfLabel; + */ +#define TLS13_HL_KEY_SIZE 2 +#define TLS13_HL_KEY_MAX_LENGTH 65535 +#define TLS13_HL_LABEL_SIZE 1 +#define TLS13_HL_LABEL_MAX_LENGTH 255 +#define TLS13_HL_CONTEXT_SIZE 1 +#define TLS13_HL_CONTEXT_MAX_LENGTH 255 +#define TLS13_HKDF_LABEL_MAX_SIZE \ + (TLS13_HL_KEY_SIZE + TLS13_HL_LABEL_SIZE + TLS13_HL_LABEL_MAX_LENGTH \ + + TLS13_HL_CONTEXT_SIZE + TLS13_HL_CONTEXT_MAX_LENGTH) + +static CK_RV p11prov_tls13_expand_label(P11PROV_KDF_CTX *hkdfctx, + P11PROV_OBJ *keyobj, uint8_t *prefix, + size_t prefixlen, uint8_t *label, + size_t labellen, uint8_t *data, + size_t datalen, size_t keylen, + CK_OBJECT_HANDLE *dkey_handle) +{ + CK_HKDF_PARAMS params = { + .bExtract = CK_FALSE, + .bExpand = CK_TRUE, + .prfHashMechanism = hkdfctx->hash_mech, + .ulSaltType = 0, + .pSalt = NULL, + .ulSaltLen = 0, + .hSaltKey = CK_INVALID_HANDLE, + }; + CK_MECHANISM mechanism = { + .mechanism = hkdfctx->mechtype, + .pParameter = ¶ms, + .ulParameterLen = sizeof(params), + }; + uint8_t info[TLS13_HKDF_LABEL_MAX_SIZE]; + size_t i; + uint16_t keysize; + CK_RV ret; + + P11PROV_debug( + "tls13 expand label (prefix:%p[%zu], label:%p[%zu], data:%p[%zu])", + prefix, prefixlen, label, labellen, data, datalen); + + if (prefix == NULL || prefixlen == 0 || label == NULL || labellen == 0 + || (prefixlen + labellen > TLS13_HL_LABEL_MAX_LENGTH) + || (datalen > 0 && data == NULL) || (datalen == 0 && data != NULL) + || (datalen > TLS13_HL_CONTEXT_MAX_LENGTH) + || (keylen > TLS13_HL_KEY_MAX_LENGTH)) { + return CKR_ARGUMENTS_BAD; } - ret = p11prov_derive_key(hkdfctx->provctx, slotid, &mechanism, pkey_handle, - key_template, 5, &hkdfctx->session, &dkey_handle); + params.pInfo = info; + params.ulInfoLen = 2 + 1 + prefixlen + labellen + 1 + datalen; + if (params.ulInfoLen > TLS13_HKDF_LABEL_MAX_SIZE) { + return CKR_ARGUMENTS_BAD; + } + i = 0; + keysize = htobe16(keylen); + memcpy(&info[i], &keysize, sizeof(keysize)); + i += sizeof(keysize); + info[i] = prefixlen + labellen; + i += 1; + memcpy(&info[i], prefix, prefixlen); + i += prefixlen; + memcpy(&info[i], label, labellen); + i += labellen; + info[i] = datalen; + i += 1; + if (datalen > 0) { + memcpy(&info[i], data, datalen); + i += datalen; + } + if (params.ulInfoLen != i) { + OPENSSL_cleanse(params.pInfo, TLS13_HKDF_LABEL_MAX_SIZE); + return CKR_HOST_MEMORY; + } + + ret = inner_derive_key(hkdfctx->provctx, keyobj, &hkdfctx->session, + &mechanism, keylen, dkey_handle); + + OPENSSL_cleanse(params.pInfo, params.ulInfoLen); + return ret; +} + +static CK_RV p11prov_tls13_derive_secret(P11PROV_KDF_CTX *hkdfctx, + P11PROV_OBJ *keyobj, size_t keylen, + CK_OBJECT_HANDLE *dkey_handle) +{ + P11PROV_OBJ *zerokey = NULL; + CK_HKDF_PARAMS params = { + .bExtract = CK_TRUE, + .bExpand = CK_FALSE, + .prfHashMechanism = hkdfctx->hash_mech, + .ulSaltType = CKF_HKDF_SALT_DATA, + .hSaltKey = CK_INVALID_HANDLE, + .pInfo = NULL, + .ulInfoLen = 0, + }; + CK_MECHANISM mechanism = { + .mechanism = CKM_HKDF_DATA, + .pParameter = ¶ms, + .ulParameterLen = sizeof(params), + }; + uint8_t saltbuf[EVP_MAX_MD_SIZE] = { 0 }; + uint8_t zerobuf[EVP_MAX_MD_SIZE] = { 0 }; + size_t saltlen; + size_t hashlen; + CK_RV ret; + + ret = p11prov_digest_get_digest_size(hkdfctx->hash_mech, &hashlen); if (ret != CKR_OK) { + return ret; + } + saltlen = hashlen; + + if (hkdfctx->salt) { + P11PROV_OBJ *ek = NULL; + unsigned char info[hashlen]; + const char *mdname; + data_buffer digest_data[1] = { 0 }; /* intentionally empty */ + data_buffer digest = { .data = info, .length = hashlen }; + CK_OBJECT_HANDLE skey_handle; + + /* OpenSSL special cases this in an odd way and regenerates a hash as + * if an empty message was received. */ + ret = p11prov_digest_get_name(hkdfctx->hash_mech, &mdname); + if (ret != CKR_OK) { + return ret; + } + + ret = p11prov_digest_util(hkdfctx->provctx, mdname, NULL, digest_data, + &digest); + if (ret != CKR_OK) { + return ret; + } + + /* In OpenSSL the salt is used as the derivation key */ + ret = inner_pkcs11_key(hkdfctx, hkdfctx->salt, hkdfctx->saltlen, &ek); + if (ret != CKR_OK) { + return ret; + } + + ret = p11prov_tls13_expand_label( + hkdfctx, ek, hkdfctx->prefix, hkdfctx->prefixlen, hkdfctx->label, + hkdfctx->labellen, info, hashlen, hashlen, &skey_handle); + p11prov_obj_free(ek); + if (ret != CKR_OK) { + return ret; + } + + ret = inner_extract_key_value(hkdfctx->provctx, hkdfctx->session, + skey_handle, saltbuf, saltlen); + if (ret != CKR_OK) { + return ret; + } + } + + params.pSalt = saltbuf; + params.ulSaltLen = saltlen; + + if (!keyobj) { + ret = inner_pkcs11_key(hkdfctx, zerobuf, hashlen, &zerokey); + if (ret != CKR_OK) { + return ret; + } + keyobj = zerokey; + } + + ret = inner_derive_key(hkdfctx->provctx, keyobj, &hkdfctx->session, + &mechanism, keylen, dkey_handle); + + p11prov_obj_free(zerokey); + return ret; +} + +static int p11prov_tls13_kdf_derive(void *ctx, unsigned char *key, + size_t keylen, const OSSL_PARAM params[]) +{ + P11PROV_KDF_CTX *hkdfctx = (P11PROV_KDF_CTX *)ctx; + CK_OBJECT_HANDLE dkey_handle; + CK_RV ret; + + P11PROV_debug("tls13 hkdf derive (ctx:%p, key:%p[%zu], params:%p)", ctx, + key, keylen, params); + + ret = p11prov_hkdf_set_ctx_params(ctx, params); + if (ret != RET_OSSL_OK) { + P11PROV_raise(hkdfctx->provctx, ret, "Invalid params"); return RET_OSSL_ERR; } - P11PROV_debug("HKDF derived hey handle: %lu", dkey_handle); - FA_SET_BUF_VAL(attrs, num, CKA_VALUE, key, keylen, true); - ret = p11prov_fetch_attributes(hkdfctx->provctx, hkdfctx->session, - dkey_handle, attrs, num); - if (ret != CKR_OK) { - P11PROV_raise(hkdfctx->provctx, ret, "Failed to retrieve derived key"); + if (key == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); return RET_OSSL_ERR; } - FA_GET_LEN(attrs, 0, key_size); - if (key_size != keylen) { - ret = CKR_GENERAL_ERROR; - P11PROV_raise(hkdfctx->provctx, ret, - "Expected derived key of len %zu, but got %lu", keylen, - key_size); + + if (keylen == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return RET_OSSL_ERR; + } + + switch (hkdfctx->mode) { + case EVP_KDF_HKDF_MODE_EXPAND_ONLY: + if (hkdfctx->key == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + return RET_OSSL_ERR; + } + ret = p11prov_tls13_expand_label( + hkdfctx, hkdfctx->key, hkdfctx->prefix, hkdfctx->prefixlen, + hkdfctx->label, hkdfctx->labellen, hkdfctx->data, hkdfctx->datalen, + keylen, &dkey_handle); + if (ret != CKR_OK) { + return RET_OSSL_ERR; + } + break; + case EVP_KDF_HKDF_MODE_EXTRACT_ONLY: + /* key can be null here */ + ret = p11prov_tls13_derive_secret(hkdfctx, hkdfctx->key, keylen, + &dkey_handle); + if (ret != CKR_OK) { + return RET_OSSL_ERR; + } + break; + default: + return RET_OSSL_ERR; + } + + ret = inner_extract_key_value(hkdfctx->provctx, hkdfctx->session, + dkey_handle, key, keylen); + if (ret != CKR_OK) { return RET_OSSL_ERR; } @@ -185,6 +519,8 @@ static int p11prov_hkdf_set_ctx_params(void *ctx, const OSSL_PARAM params[]) return RET_OSSL_OK; } + /* params common to HKDF and TLS13_KDF first */ + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST); if (p) { const char *digest = NULL; @@ -195,108 +531,137 @@ static int p11prov_hkdf_set_ctx_params(void *ctx, const OSSL_PARAM params[]) return ret; } - rv = p11prov_digest_get_by_name(digest, - &hkdfctx->params.prfHashMechanism); + rv = p11prov_digest_get_by_name(digest, &hkdfctx->hash_mech); if (rv != CKR_OK) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); return RET_OSSL_ERR; } - P11PROV_debug("set digest to %lu", hkdfctx->params.prfHashMechanism); + P11PROV_debug("set digest to %lu", hkdfctx->hash_mech); } p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE); if (p) { - int mode; if (p->data_type == OSSL_PARAM_UTF8_STRING) { if (OPENSSL_strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) { - mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; + hkdfctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; } else if (OPENSSL_strcasecmp(p->data, "EXTRACT_ONLY") == 0) { - mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; + hkdfctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; } else if (OPENSSL_strcasecmp(p->data, "EXPAND_ONLY") == 0) { - mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; + hkdfctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; } else { - mode = 1; + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return RET_OSSL_ERR; } } else { - ret = OSSL_PARAM_get_int(p, &mode); + ret = OSSL_PARAM_get_int(p, &hkdfctx->mode); if (ret != RET_OSSL_OK) { return ret; } } - switch (mode) { + switch (hkdfctx->mode) { case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND: - hkdfctx->params.bExtract = CK_TRUE; - hkdfctx->params.bExpand = CK_TRUE; break; case EVP_KDF_HKDF_MODE_EXTRACT_ONLY: - hkdfctx->params.bExtract = CK_TRUE; - hkdfctx->params.bExpand = CK_FALSE; break; case EVP_KDF_HKDF_MODE_EXPAND_ONLY: - hkdfctx->params.bExtract = CK_FALSE; - hkdfctx->params.bExpand = CK_TRUE; break; default: ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); return RET_OSSL_ERR; } - P11PROV_debug("set mode to extract:%d expand:%d", - (int)hkdfctx->params.bExtract, - (int)hkdfctx->params.bExpand); + P11PROV_debug("set mode to mode:%d", hkdfctx->mode); } p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY); if (p) { - CK_SLOT_ID slotid = CK_UNAVAILABLE_INFORMATION; - void *secret = NULL; + const void *secret = NULL; size_t secret_len; - /* TODO: import into a pkcs11 key? */ - ret = OSSL_PARAM_get_octet_string(p, &secret, 0, &secret_len); + + ret = OSSL_PARAM_get_octet_string_ptr(p, &secret, &secret_len); if (ret != RET_OSSL_OK) { return ret; } - /* Create Session and key from key material */ - if (hkdfctx->session == NULL) { - ret = p11prov_get_session(hkdfctx->provctx, &slotid, NULL, NULL, - hkdfctx->mechtype, NULL, NULL, false, - false, &hkdfctx->session); - if (ret != CKR_OK) { - return RET_OSSL_ERR; - } - } - if (hkdfctx->session == NULL) { - return RET_OSSL_ERR; - } - - hkdfctx->key = p11prov_create_secret_key( - hkdfctx->provctx, hkdfctx->session, true, secret, secret_len); - OPENSSL_clear_free(secret, secret_len); - if (hkdfctx->key == NULL) { + /* Create Session and key from key material */ + p11prov_obj_free(hkdfctx->key); + ret = inner_pkcs11_key(hkdfctx, secret, secret_len, &hkdfctx->key); + if (ret != CKR_OK) { return RET_OSSL_ERR; } } p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT); if (p) { - void *ptr = NULL; - size_t len; - OPENSSL_cleanse(hkdfctx->params.pSalt, hkdfctx->params.ulSaltLen); - hkdfctx->params.pSalt = NULL; - ret = OSSL_PARAM_get_octet_string(p, &ptr, 0, &len); + OPENSSL_clear_free(hkdfctx->salt, hkdfctx->saltlen); + hkdfctx->salt = NULL; + ret = OSSL_PARAM_get_octet_string(p, (void **)&hkdfctx->salt, 0, + &hkdfctx->saltlen); if (ret != RET_OSSL_OK) { return ret; } - hkdfctx->params.ulSaltType = CKF_HKDF_SALT_DATA; - hkdfctx->params.pSalt = ptr; - hkdfctx->params.ulSaltLen = len; - P11PROV_debug("set salt (len:%lu)", hkdfctx->params.ulSaltLen); + hkdfctx->salt_type = CKF_HKDF_SALT_DATA; + P11PROV_debug("set salt (len:%lu)", hkdfctx->saltlen); } + if (hkdfctx->is_tls13_kdf) { + + if (hkdfctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return RET_OSSL_ERR; + } + + OPENSSL_clear_free(hkdfctx->info, hkdfctx->infolen); + hkdfctx->info = NULL; + hkdfctx->infolen = 0; + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PREFIX); + if (p) { + OPENSSL_clear_free(hkdfctx->prefix, hkdfctx->prefixlen); + hkdfctx->prefix = NULL; + hkdfctx->prefixlen = 0; + ret = OSSL_PARAM_get_octet_string(p, (void **)&hkdfctx->prefix, 0, + &hkdfctx->prefixlen); + if (ret != RET_OSSL_OK) { + return ret; + } + } + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_LABEL); + if (p) { + OPENSSL_clear_free(hkdfctx->label, hkdfctx->labellen); + hkdfctx->label = NULL; + hkdfctx->labellen = 0; + ret = OSSL_PARAM_get_octet_string(p, (void **)&hkdfctx->label, 0, + &hkdfctx->labellen); + if (ret != RET_OSSL_OK) { + return ret; + } + } + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DATA); + if (p) { + OPENSSL_clear_free(hkdfctx->data, hkdfctx->datalen); + hkdfctx->data = NULL; + hkdfctx->datalen = 0; + ret = OSSL_PARAM_get_octet_string(p, (void **)&hkdfctx->data, 0, + &hkdfctx->datalen); + if (ret != RET_OSSL_OK) { + return ret; + } + } + + return RET_OSSL_OK; + } + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO); + if (p) { + OPENSSL_clear_free(hkdfctx->info, hkdfctx->infolen); + hkdfctx->info = NULL; + hkdfctx->infolen = 0; + } /* can be multiple parameters, which will be all concatenated */ - for (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO); p != NULL; - p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_INFO)) { + for (; p; p = OSSL_PARAM_locate_const(p + 1, OSSL_KDF_PARAM_INFO)) { uint8_t *ptr; size_t len; @@ -304,16 +669,18 @@ static int p11prov_hkdf_set_ctx_params(void *ctx, const OSSL_PARAM params[]) return RET_OSSL_ERR; } - len = hkdfctx->params.ulInfoLen + p->data_size; - ptr = OPENSSL_realloc(hkdfctx->params.pInfo, len); + len = hkdfctx->infolen + p->data_size; + ptr = OPENSSL_realloc(hkdfctx->info, len); if (ptr == NULL) { - OPENSSL_cleanse(hkdfctx->params.pInfo, hkdfctx->params.ulInfoLen); + OPENSSL_clear_free(hkdfctx->info, hkdfctx->infolen); + hkdfctx->info = NULL; + hkdfctx->infolen = 0; return RET_OSSL_ERR; } - memcpy(ptr + hkdfctx->params.ulInfoLen, p->data, p->data_size); - hkdfctx->params.pInfo = ptr; - hkdfctx->params.ulInfoLen = len; - P11PROV_debug("set info (len:%lu)", hkdfctx->params.ulInfoLen); + memcpy(ptr + hkdfctx->infolen, p->data, p->data_size); + hkdfctx->info = ptr; + hkdfctx->infolen = len; + P11PROV_debug("set info (len:%lu)", hkdfctx->infolen); } return RET_OSSL_OK; @@ -348,13 +715,12 @@ static int p11prov_hkdf_get_ctx_params(void *ctx, OSSL_PARAM *params) p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE); if (p) { size_t ret_size = 0; - if (hkdfctx->params.bExpand != CK_FALSE) { + if (hkdfctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY) { ret_size = SIZE_MAX; } else { CK_RV rv; - rv = p11prov_digest_get_digest_size( - hkdfctx->params.prfHashMechanism, &ret_size); + rv = p11prov_digest_get_digest_size(hkdfctx->hash_mech, &ret_size); if (rv != CKR_OK) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); return RET_OSSL_ERR; @@ -390,3 +756,40 @@ const OSSL_DISPATCH p11prov_hkdf_kdf_functions[] = { DISPATCH_HKDF_ELEM(hkdf, GETTABLE_CTX_PARAMS, gettable_ctx_params), { 0, NULL }, }; + +static void *p11prov_tls13_kdf_newctx(void *provctx) +{ + P11PROV_KDF_CTX *ctx = (P11PROV_KDF_CTX *)p11prov_hkdf_newctx(provctx); + ctx->is_tls13_kdf = true; + return ctx; +} + +static const OSSL_PARAM *p11prov_tls13_kdf_settable_ctx_params(void *ctx, + void *prov) +{ + static const OSSL_PARAM params[] = { + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), + OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PREFIX, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_LABEL, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_DATA, NULL, 0), + OSSL_PARAM_END, + }; + return params; +} + +const OSSL_DISPATCH p11prov_tls13_kdf_functions[] = { + DISPATCH_HKDF_ELEM(tls13_kdf, NEWCTX, newctx), + DISPATCH_HKDF_ELEM(hkdf, FREECTX, freectx), + DISPATCH_HKDF_ELEM(hkdf, RESET, reset), + DISPATCH_HKDF_ELEM(tls13_kdf, DERIVE, derive), + DISPATCH_HKDF_ELEM(hkdf, SET_CTX_PARAMS, set_ctx_params), + DISPATCH_HKDF_ELEM(tls13_kdf, SETTABLE_CTX_PARAMS, settable_ctx_params), + DISPATCH_HKDF_ELEM(hkdf, GET_CTX_PARAMS, get_ctx_params), + DISPATCH_HKDF_ELEM(hkdf, GETTABLE_CTX_PARAMS, gettable_ctx_params), + { 0, NULL }, +}; diff --git a/src/kdf.h b/src/kdf.h index cc938780..dfd3cb20 100644 --- a/src/kdf.h +++ b/src/kdf.h @@ -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 */ diff --git a/src/keymgmt.c b/src/keymgmt.c index f6fd9cc6..54652686 100644 --- a/src/keymgmt.c +++ b/src/keymgmt.c @@ -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; } @@ -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 diff --git a/src/objects.c b/src/objects.c index ab7d61ff..7800c292 100644 --- a/src/objects.c +++ b/src/objects.c @@ -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) { @@ -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; @@ -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; @@ -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) { @@ -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; diff --git a/src/objects.h b/src/objects.h index 4a06cc30..c6ee04ff 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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); diff --git a/src/provider.c b/src/provider.c index a41d0ea7..199659c9 100644 --- a/src/provider.c +++ b/src/provider.c @@ -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; diff --git a/src/provider.h b/src/provider.h index b1f1643e..418f9d00 100644 --- a/src/provider.h +++ b/src/provider.h @@ -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" diff --git a/src/util.c b/src/util.c index 273c2bbd..66a3bd0f 100644 --- a/src/util.c +++ b/src/util.c @@ -1170,3 +1170,92 @@ void p11prov_force_rwlock_reinit(pthread_rwlock_t *lock) pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; memcpy(lock, &rwlock, sizeof(rwlock)); } + +CK_RV p11prov_digest_util(P11PROV_CTX *ctx, const char *digest, + const char *properties, data_buffer data[], + data_buffer *output) +{ + EVP_MD_CTX *mdctx = NULL; + EVP_MD *md = NULL; + unsigned char *dgst = NULL; + unsigned int dlen = 0; + CK_RV rv; + int err; + + if (!data || !output) { + rv = CKR_GENERAL_ERROR; + P11PROV_raise(ctx, rv, "Invalid function arguments"); + return rv; + } + + md = EVP_MD_fetch(p11prov_ctx_get_libctx(ctx), digest, properties); + if (!md) { + rv = CKR_GENERAL_ERROR; + P11PROV_raise(ctx, rv, "Failed to fetch %s digest", digest); + goto done; + } + + dlen = EVP_MD_get_size(md); + if (dlen == -1) { + rv = CKR_GENERAL_ERROR; + P11PROV_raise(ctx, rv, "Failed to get %s digest length", digest); + goto done; + } + + if (output->data) { + if (output->length < dlen) { + rv = CKR_GENERAL_ERROR; + P11PROV_raise(ctx, rv, "Invalid function arguments"); + goto done; + } + dgst = output->data; + } else { + 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; + } + + for (int i = 0; data[i].data; i++) { + err = EVP_DigestUpdate(mdctx, data[i].data, data[i].length); + if (err != RET_OSSL_OK) { + rv = CKR_GENERAL_ERROR; + P11PROV_raise(ctx, rv, "EVP_DigestUpdate(%d) failed", i); + 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 failed"); + goto done; + } + + output->data = dgst; + output->length = dlen; + rv = CKR_OK; + +done: + if (output->data != dgst) { + OPENSSL_free(dgst); + } + EVP_MD_CTX_free(mdctx); + EVP_MD_free(md); + return rv; +} diff --git a/src/util.h b/src/util.h index aef8f4a4..a96eec72 100644 --- a/src/util.h +++ b/src/util.h @@ -132,4 +132,14 @@ static inline void constant_select_buf(CK_ULONG cond, CK_ULONG size, } } +struct data_buffer { + uint8_t *data; + size_t length; +}; +typedef struct data_buffer data_buffer; + +CK_RV p11prov_digest_util(P11PROV_CTX *provctx, const char *digest, + const char *properties, data_buffer data[], + data_buffer *output); + #endif /* _UTIL_H */ diff --git a/tests/ttls b/tests/ttls index a3ea93f4..6ec20721 100755 --- a/tests/ttls +++ b/tests/ttls @@ -93,4 +93,18 @@ run_test "$ECPRIURI" "$ECCRTURI" "" "-tls1_2" title PARA "Run test with TLS 1.2 and ECDH" run_test "$ECPRIURI" "$ECCRTURI" "" "-tls1_2 -cipher ECDHE-ECDSA-AES128-GCM-SHA256 -groups secp256r1" +#Try again forcing all operations on the token +#We need to disable digest operations as OpenSSL depends on context duplication working +ORIG_OPENSSL_CONF=${OPENSSL_CONF} +sed -e "s/#MORECONF/alg_section = algorithm_sec\n\n[algorithm_sec]\ndefault_properties = ?provider=pkcs11/" \ + -e "s/#pkcs11-module-block-operations/pkcs11-module-block-operations = digest/" \ + "${OPENSSL_CONF}" > "${OPENSSL_CONF}.forcetoken" +OPENSSL_CONF=${OPENSSL_CONF}.forcetoken + +title PARA "Run test with TLS 1.3 preferring token functions" +run_test "$ECPRIURI" "$ECCRTURI" "" "-tls1_3" + +OPENSSL_CONF=${ORIG_OPENSSL_CONF} + + exit 0;