From d1a8d5a8330a8c9d939e18a22f7382af090cf108 Mon Sep 17 00:00:00 2001 From: Daniel Van Geest Date: Thu, 3 Apr 2025 10:45:20 +0100 Subject: [PATCH] Add HKDF algorithms with fixed digests. Add HKDF-SHA256, HKDF-SHA384 and HKDF-SHA512 which are versions of HKDF that have the digest pre-set. The digest cannot be changed for contexts of these types. RFC 8619 defines algorithm identifiers for these combinations. These algorithm identifiers will be used in future features, e.g. KEMRecipientInfo. Reviewed-by: Shane Lontis Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/27247) --- CHANGES.md | 5 + crypto/objects/obj_dat.h | 25 ++++- crypto/objects/obj_mac.num | 3 + crypto/objects/objects.txt | 3 + fuzz/oids.txt | 3 + include/openssl/core_names.h.in | 3 + include/openssl/obj_mac.h | 15 +++ providers/defltprov.c | 12 +++ providers/fips/fipsprov.c | 12 +++ providers/implementations/exchange/kdf_exch.c | 12 +++ .../include/prov/implementations.h | 6 ++ .../implementations/include/prov/names.h | 6 ++ providers/implementations/kdfs/hkdf.c | 92 ++++++++++++++++++- test/evp_kdf_test.c | 64 ++++++++++++- test/recipes/20-test_kdf.t | 3 + test/recipes/30-test_evp_data/evpkdf_hkdf.txt | 6 ++ .../30-test_evp_data/evppkey_kdf_hkdf.txt | 6 ++ 17 files changed, 267 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index e21a6e52edd..1b1b6bac2fb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -112,6 +112,11 @@ OpenSSL 3.6 *Dimitri John Ledkov* + * HKDF with (SHA-256,SHA-384,SHA-512) has assigned OIDs. Added ability to load + HKDF configured with these explicit digests by name or OID. + + *Daniel Van Geest (CryptoNext Security)* + OpenSSL 3.5 ----------- diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h index dcd0f3f41c4..5b6a97c6fbb 100644 --- a/crypto/objects/obj_dat.h +++ b/crypto/objects/obj_dat.h @@ -10,7 +10,7 @@ */ /* Serialized OID's */ -static const unsigned char so[9517] = { +static const unsigned char so[9550] = { 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ @@ -1348,9 +1348,12 @@ static const unsigned char so[9517] = { 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x2C, /* [ 9489] OBJ_SLH_DSA_SHAKE_192f_WITH_SHAKE256 */ 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x2D, /* [ 9498] OBJ_SLH_DSA_SHAKE_256s_WITH_SHAKE256 */ 0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x2E, /* [ 9507] OBJ_SLH_DSA_SHAKE_256f_WITH_SHAKE256 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x1C, /* [ 9516] OBJ_HKDF_SHA256 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x1D, /* [ 9527] OBJ_HKDF_SHA384 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x1E, /* [ 9538] OBJ_HKDF_SHA512 */ }; -#define NUM_NID 1496 +#define NUM_NID 1499 static const ASN1_OBJECT nid_objs[NUM_NID] = { {"UNDEF", "undefined", NID_undef}, {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, @@ -2848,9 +2851,12 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { {"AES-128-CBC-HMAC-SHA512-ETM", "aes-128-cbc-hmac-sha512-etm", NID_aes_128_cbc_hmac_sha512_etm}, {"AES-192-CBC-HMAC-SHA512-ETM", "aes-192-cbc-hmac-sha512-etm", NID_aes_192_cbc_hmac_sha512_etm}, {"AES-256-CBC-HMAC-SHA512-ETM", "aes-256-cbc-hmac-sha512-etm", NID_aes_256_cbc_hmac_sha512_etm}, + {"id-alg-hkdf-with-sha256", "HKDF-SHA256", NID_HKDF_SHA256, 11, &so[9516]}, + {"id-alg-hkdf-with-sha384", "HKDF-SHA384", NID_HKDF_SHA384, 11, &so[9527]}, + {"id-alg-hkdf-with-sha512", "HKDF-SHA512", NID_HKDF_SHA512, 11, &so[9538]}, }; -#define NUM_SN 1487 +#define NUM_SN 1490 static const unsigned int sn_objs[NUM_SN] = { 364, /* "AD_DVCS" */ 419, /* "AES-128-CBC" */ @@ -3480,6 +3486,9 @@ static const unsigned int sn_objs[NUM_SN] = { 323, /* "id-alg-des40" */ 326, /* "id-alg-dh-pop" */ 325, /* "id-alg-dh-sig-hmac-sha1" */ + 1496, /* "id-alg-hkdf-with-sha256" */ + 1497, /* "id-alg-hkdf-with-sha384" */ + 1498, /* "id-alg-hkdf-with-sha512" */ 1456, /* "id-alg-ml-kem-1024" */ 1454, /* "id-alg-ml-kem-512" */ 1455, /* "id-alg-ml-kem-768" */ @@ -4341,7 +4350,7 @@ static const unsigned int sn_objs[NUM_SN] = { 1289, /* "zstd" */ }; -#define NUM_LN 1487 +#define NUM_LN 1490 static const unsigned int ln_objs[NUM_LN] = { 363, /* "AD Time Stamping" */ 405, /* "ANSI X9.62" */ @@ -4468,6 +4477,9 @@ static const unsigned int ln_objs[NUM_LN] = { 1472, /* "HASH-ML-DSA-44-WITH-SHA512" */ 1473, /* "HASH-ML-DSA-65-WITH-SHA512" */ 1474, /* "HASH-ML-DSA-87-WITH-SHA512" */ + 1496, /* "HKDF-SHA256" */ + 1497, /* "HKDF-SHA384" */ + 1498, /* "HKDF-SHA512" */ 1156, /* "HMAC DSTU Gost 34311-95" */ 988, /* "HMAC GOST 34.11-2012 256 bit" */ 989, /* "HMAC GOST 34.11-2012 512 bit" */ @@ -5832,7 +5844,7 @@ static const unsigned int ln_objs[NUM_LN] = { 125, /* "zlib compression" */ }; -#define NUM_OBJ 1344 +#define NUM_OBJ 1347 static const unsigned int obj_objs[NUM_OBJ] = { 0, /* OBJ_undef 0 */ 181, /* OBJ_iso 1 */ @@ -7145,6 +7157,9 @@ static const unsigned int obj_objs[NUM_OBJ] = { 247, /* OBJ_id_smime_alg_CMSRC2wrap 1 2 840 113549 1 9 16 3 7 */ 125, /* OBJ_zlib_compression 1 2 840 113549 1 9 16 3 8 */ 893, /* OBJ_id_alg_PWRI_KEK 1 2 840 113549 1 9 16 3 9 */ + 1496, /* OBJ_HKDF_SHA256 1 2 840 113549 1 9 16 3 28 */ + 1497, /* OBJ_HKDF_SHA384 1 2 840 113549 1 9 16 3 29 */ + 1498, /* OBJ_HKDF_SHA512 1 2 840 113549 1 9 16 3 30 */ 248, /* OBJ_id_smime_cd_ldap 1 2 840 113549 1 9 16 4 1 */ 249, /* OBJ_id_smime_spq_ets_sqt_uri 1 2 840 113549 1 9 16 5 1 */ 250, /* OBJ_id_smime_spq_ets_sqt_unotice 1 2 840 113549 1 9 16 5 2 */ diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num index 15bd8909e8e..842b024dcc0 100644 --- a/crypto/objects/obj_mac.num +++ b/crypto/objects/obj_mac.num @@ -1493,3 +1493,6 @@ aes_256_cbc_hmac_sha256_etm 1492 aes_128_cbc_hmac_sha512_etm 1493 aes_192_cbc_hmac_sha512_etm 1494 aes_256_cbc_hmac_sha512_etm 1495 +HKDF_SHA256 1496 +HKDF_SHA384 1497 +HKDF_SHA512 1498 diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt index 6afeefff608..bbd757b8cf1 100644 --- a/crypto/objects/objects.txt +++ b/crypto/objects/objects.txt @@ -336,6 +336,9 @@ id-smime-alg 5 : id-smime-alg-ESDH id-smime-alg 6 : id-smime-alg-CMS3DESwrap id-smime-alg 7 : id-smime-alg-CMSRC2wrap id-smime-alg 9 : id-alg-PWRI-KEK +id-smime-alg 28 : id-alg-hkdf-with-sha256 : HKDF-SHA256 +id-smime-alg 29 : id-alg-hkdf-with-sha384 : HKDF-SHA384 +id-smime-alg 30 : id-alg-hkdf-with-sha512 : HKDF-SHA512 # S/MIME Certificate Distribution id-smime-cd 1 : id-smime-cd-ldap diff --git a/fuzz/oids.txt b/fuzz/oids.txt index 307e92ea513..29a801ae37b 100644 --- a/fuzz/oids.txt +++ b/fuzz/oids.txt @@ -1344,3 +1344,6 @@ OBJ_SLH_DSA_SHAKE_192s_WITH_SHAKE256="\x60\x86\x48\x01\x65\x03\x04\x03\x2B" OBJ_SLH_DSA_SHAKE_192f_WITH_SHAKE256="\x60\x86\x48\x01\x65\x03\x04\x03\x2C" OBJ_SLH_DSA_SHAKE_256s_WITH_SHAKE256="\x60\x86\x48\x01\x65\x03\x04\x03\x2D" OBJ_SLH_DSA_SHAKE_256f_WITH_SHAKE256="\x60\x86\x48\x01\x65\x03\x04\x03\x2E" +OBJ_HKDF_SHA256="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1C" +OBJ_HKDF_SHA384="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1D" +OBJ_HKDF_SHA512="\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x03\x1E" diff --git a/include/openssl/core_names.h.in b/include/openssl/core_names.h.in index d53cac43327..66f796c03a2 100644 --- a/include/openssl/core_names.h.in +++ b/include/openssl/core_names.h.in @@ -66,6 +66,9 @@ extern "C" { /* Known KDF names */ # define OSSL_KDF_NAME_HKDF "HKDF" +# define OSSL_KDF_NAME_HKDF_SHA256 "HKDF-SHA256" +# define OSSL_KDF_NAME_HKDF_SHA384 "HKDF-SHA384" +# define OSSL_KDF_NAME_HKDF_SHA512 "HKDF-SHA512" # define OSSL_KDF_NAME_TLS1_3_KDF "TLS13-KDF" # define OSSL_KDF_NAME_PBKDF1 "PBKDF1" # define OSSL_KDF_NAME_PBKDF2 "PBKDF2" diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h index 8326216f67f..a2f4bc01605 100644 --- a/include/openssl/obj_mac.h +++ b/include/openssl/obj_mac.h @@ -1062,6 +1062,21 @@ #define NID_id_alg_PWRI_KEK 893 #define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L +#define SN_HKDF_SHA256 "id-alg-hkdf-with-sha256" +#define LN_HKDF_SHA256 "HKDF-SHA256" +#define NID_HKDF_SHA256 1496 +#define OBJ_HKDF_SHA256 OBJ_id_smime_alg,28L + +#define SN_HKDF_SHA384 "id-alg-hkdf-with-sha384" +#define LN_HKDF_SHA384 "HKDF-SHA384" +#define NID_HKDF_SHA384 1497 +#define OBJ_HKDF_SHA384 OBJ_id_smime_alg,29L + +#define SN_HKDF_SHA512 "id-alg-hkdf-with-sha512" +#define LN_HKDF_SHA512 "HKDF-SHA512" +#define NID_HKDF_SHA512 1498 +#define OBJ_HKDF_SHA512 OBJ_id_smime_alg,30L + #define SN_id_smime_cd_ldap "id-smime-cd-ldap" #define NID_id_smime_cd_ldap 248 #define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L diff --git a/providers/defltprov.c b/providers/defltprov.c index 7e3c354de0f..412737296c6 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -358,6 +358,9 @@ static const OSSL_ALGORITHM deflt_macs[] = { static const OSSL_ALGORITHM deflt_kdfs[] = { { PROV_NAMES_HKDF, "provider=default", ossl_kdf_hkdf_functions }, + { PROV_NAMES_HKDF_SHA256, "provider=default", ossl_kdf_hkdf_sha256_functions }, + { PROV_NAMES_HKDF_SHA384, "provider=default", ossl_kdf_hkdf_sha384_functions }, + { PROV_NAMES_HKDF_SHA512, "provider=default", ossl_kdf_hkdf_sha512_functions }, { PROV_NAMES_TLS1_3_KDF, "provider=default", ossl_kdf_tls1_3_kdf_functions }, { PROV_NAMES_SSKDF, "provider=default", ossl_kdf_sskdf_functions }, @@ -395,6 +398,9 @@ static const OSSL_ALGORITHM deflt_keyexch[] = { #endif { PROV_NAMES_TLS1_PRF, "provider=default", ossl_kdf_tls1_prf_keyexch_functions }, { PROV_NAMES_HKDF, "provider=default", ossl_kdf_hkdf_keyexch_functions }, + { PROV_NAMES_HKDF_SHA256, "provider=default", ossl_kdf_hkdf_sha256_keyexch_functions }, + { PROV_NAMES_HKDF_SHA384, "provider=default", ossl_kdf_hkdf_sha384_keyexch_functions }, + { PROV_NAMES_HKDF_SHA512, "provider=default", ossl_kdf_hkdf_sha512_keyexch_functions }, { PROV_NAMES_SCRYPT, "provider=default", ossl_kdf_scrypt_keyexch_functions }, { NULL, NULL, NULL } @@ -583,6 +589,12 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = { PROV_DESCS_TLS1_PRF_SIGN }, { PROV_NAMES_HKDF, "provider=default", ossl_kdf_keymgmt_functions, PROV_DESCS_HKDF_SIGN }, + { PROV_NAMES_HKDF_SHA256, "provider=default", ossl_kdf_keymgmt_functions, + PROV_DESCS_HKDF_SHA256_SIGN }, + { PROV_NAMES_HKDF_SHA384, "provider=default", ossl_kdf_keymgmt_functions, + PROV_DESCS_HKDF_SHA384_SIGN }, + { PROV_NAMES_HKDF_SHA512, "provider=default", ossl_kdf_keymgmt_functions, + PROV_DESCS_HKDF_SHA512_SIGN }, { PROV_NAMES_SCRYPT, "provider=default", ossl_kdf_keymgmt_functions, PROV_DESCS_SCRYPT_SIGN }, { PROV_NAMES_HMAC, "provider=default", ossl_mac_legacy_keymgmt_functions, diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 5f9745ce5ad..5a1e11c03f3 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -404,6 +404,9 @@ static const OSSL_ALGORITHM fips_macs_internal[] = { static const OSSL_ALGORITHM fips_kdfs[] = { { PROV_NAMES_HKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_functions }, + { PROV_NAMES_HKDF_SHA256, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_sha256_functions }, + { PROV_NAMES_HKDF_SHA384, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_sha384_functions }, + { PROV_NAMES_HKDF_SHA512, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_sha512_functions }, { PROV_NAMES_TLS1_3_KDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_tls1_3_kdf_functions }, { PROV_NAMES_SSKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_sskdf_functions }, @@ -445,6 +448,9 @@ static const OSSL_ALGORITHM fips_keyexch[] = { { PROV_NAMES_TLS1_PRF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_tls1_prf_keyexch_functions }, { PROV_NAMES_HKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_keyexch_functions }, + { PROV_NAMES_HKDF_SHA256, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_sha256_keyexch_functions }, + { PROV_NAMES_HKDF_SHA384, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_sha384_keyexch_functions }, + { PROV_NAMES_HKDF_SHA512, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_sha512_keyexch_functions }, { NULL, NULL, NULL } }; @@ -612,6 +618,12 @@ static const OSSL_ALGORITHM fips_keymgmt[] = { PROV_DESCS_TLS1_PRF_SIGN }, { PROV_NAMES_HKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_keymgmt_functions, PROV_DESCS_HKDF_SIGN }, + { PROV_NAMES_HKDF_SHA256, FIPS_DEFAULT_PROPERTIES, ossl_kdf_keymgmt_functions, + PROV_DESCS_HKDF_SHA256_SIGN }, + { PROV_NAMES_HKDF_SHA384, FIPS_DEFAULT_PROPERTIES, ossl_kdf_keymgmt_functions, + PROV_DESCS_HKDF_SHA384_SIGN }, + { PROV_NAMES_HKDF_SHA512, FIPS_DEFAULT_PROPERTIES, ossl_kdf_keymgmt_functions, + PROV_DESCS_HKDF_SHA512_SIGN }, { PROV_NAMES_HMAC, FIPS_DEFAULT_PROPERTIES, ossl_mac_legacy_keymgmt_functions, PROV_DESCS_HMAC_SIGN }, #ifndef OPENSSL_NO_CMAC diff --git a/providers/implementations/exchange/kdf_exch.c b/providers/implementations/exchange/kdf_exch.c index 340a2663c58..5e363737b0e 100644 --- a/providers/implementations/exchange/kdf_exch.c +++ b/providers/implementations/exchange/kdf_exch.c @@ -79,6 +79,9 @@ err: KDF_NEWCTX(tls1_prf, "TLS1-PRF") KDF_NEWCTX(hkdf, "HKDF") +KDF_NEWCTX(hkdf_sha256, "HKDF-SHA256") +KDF_NEWCTX(hkdf_sha384, "HKDF-SHA384") +KDF_NEWCTX(hkdf_sha512, "HKDF-SHA512") KDF_NEWCTX(scrypt, "SCRYPT") static int kdf_init(void *vpkdfctx, void *vkdf, const OSSL_PARAM params[]) @@ -206,6 +209,9 @@ static const OSSL_PARAM *kdf_settable_ctx_params(ossl_unused void *vpkdfctx, KDF_SETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF") KDF_SETTABLE_CTX_PARAMS(hkdf, "HKDF") +KDF_SETTABLE_CTX_PARAMS(hkdf_sha256, "HKDF-SHA256") +KDF_SETTABLE_CTX_PARAMS(hkdf_sha384, "HKDF-SHA384") +KDF_SETTABLE_CTX_PARAMS(hkdf_sha512, "HKDF-SHA512") KDF_SETTABLE_CTX_PARAMS(scrypt, "SCRYPT") static const OSSL_PARAM *kdf_gettable_ctx_params(ossl_unused void *vpkdfctx, @@ -234,6 +240,9 @@ static const OSSL_PARAM *kdf_gettable_ctx_params(ossl_unused void *vpkdfctx, KDF_GETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF") KDF_GETTABLE_CTX_PARAMS(hkdf, "HKDF") +KDF_GETTABLE_CTX_PARAMS(hkdf_sha256, "HKDF-SHA256") +KDF_GETTABLE_CTX_PARAMS(hkdf_sha384, "HKDF-SHA384") +KDF_GETTABLE_CTX_PARAMS(hkdf_sha512, "HKDF-SHA512") KDF_GETTABLE_CTX_PARAMS(scrypt, "SCRYPT") #define KDF_KEYEXCH_FUNCTIONS(funcname) \ @@ -254,4 +263,7 @@ KDF_GETTABLE_CTX_PARAMS(scrypt, "SCRYPT") KDF_KEYEXCH_FUNCTIONS(tls1_prf) KDF_KEYEXCH_FUNCTIONS(hkdf) +KDF_KEYEXCH_FUNCTIONS(hkdf_sha256) +KDF_KEYEXCH_FUNCTIONS(hkdf_sha384) +KDF_KEYEXCH_FUNCTIONS(hkdf_sha512) KDF_KEYEXCH_FUNCTIONS(scrypt) diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 311e5f38693..e2a3cd543c5 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -287,6 +287,9 @@ extern const OSSL_DISPATCH ossl_kdf_scrypt_functions[]; #endif extern const OSSL_DISPATCH ossl_kdf_tls1_prf_functions[]; extern const OSSL_DISPATCH ossl_kdf_hkdf_functions[]; +extern const OSSL_DISPATCH ossl_kdf_hkdf_sha256_functions[]; +extern const OSSL_DISPATCH ossl_kdf_hkdf_sha384_functions[]; +extern const OSSL_DISPATCH ossl_kdf_hkdf_sha512_functions[]; extern const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[]; extern const OSSL_DISPATCH ossl_kdf_sshkdf_functions[]; extern const OSSL_DISPATCH ossl_kdf_sskdf_functions[]; @@ -374,6 +377,9 @@ extern const OSSL_DISPATCH ossl_x448_keyexch_functions[]; #endif extern const OSSL_DISPATCH ossl_kdf_tls1_prf_keyexch_functions[]; extern const OSSL_DISPATCH ossl_kdf_hkdf_keyexch_functions[]; +extern const OSSL_DISPATCH ossl_kdf_hkdf_sha256_keyexch_functions[]; +extern const OSSL_DISPATCH ossl_kdf_hkdf_sha384_keyexch_functions[]; +extern const OSSL_DISPATCH ossl_kdf_hkdf_sha512_keyexch_functions[]; extern const OSSL_DISPATCH ossl_kdf_scrypt_keyexch_functions[]; /* Signature */ diff --git a/providers/implementations/include/prov/names.h b/providers/implementations/include/prov/names.h index 34e1147b2b7..aaf9808a3ba 100644 --- a/providers/implementations/include/prov/names.h +++ b/providers/implementations/include/prov/names.h @@ -278,6 +278,12 @@ */ #define PROV_NAMES_HKDF "HKDF" #define PROV_DESCS_HKDF_SIGN "OpenSSL HKDF via EVP_PKEY implementation" +#define PROV_NAMES_HKDF_SHA256 "HKDF-SHA256:id-alg-hkdf-with-sha256:1.2.840.113549.1.9.16.3.28" +#define PROV_DESCS_HKDF_SHA256_SIGN "OpenSSL HKDF-SHA256 via EVP_PKEY implementation" +#define PROV_NAMES_HKDF_SHA384 "HKDF-SHA384:id-alg-hkdf-with-sha384:1.2.840.113549.1.9.16.3.29" +#define PROV_DESCS_HKDF_SHA384_SIGN "OpenSSL HKDF-SHA384 via EVP_PKEY implementation" +#define PROV_NAMES_HKDF_SHA512 "HKDF-SHA512:id-alg-hkdf-with-sha512:1.2.840.113549.1.9.16.3.30" +#define PROV_DESCS_HKDF_SHA512_SIGN "OpenSSL HKDF-SHA512 via EVP_PKEY implementation" #define PROV_NAMES_TLS1_3_KDF "TLS13-KDF" #define PROV_NAMES_SSKDF "SSKDF" #define PROV_NAMES_PBKDF1 "PBKDF1" diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c index f5306d60682..bfe8d8d533f 100644 --- a/providers/implementations/kdfs/hkdf.c +++ b/providers/implementations/kdfs/hkdf.c @@ -51,6 +51,13 @@ static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params; static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params; static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_tls1_3_gettable_ctx_params; static OSSL_FUNC_kdf_get_ctx_params_fn kdf_tls1_3_get_ctx_params; +static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_sha256_new; +static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_sha384_new; +static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_sha512_new; +static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_fixed_digest_settable_ctx_params; +static OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_fixed_digest_set_ctx_params; + +static void *kdf_hkdf_fixed_digest_new(void *provctx, const char *digest); static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md, const unsigned char *salt, size_t salt_len, @@ -66,12 +73,14 @@ static int HKDF_Expand(const EVP_MD *evp_md, const unsigned char *info, size_t info_len, unsigned char *okm, size_t okm_len); -/* Settable context parameters that are common across HKDF and the TLS KDF */ -#define HKDF_COMMON_SETTABLES \ +/* + * Settable context parameters that are common across HKDF (including + * implementations with a default digest) and the TLS KDF + */ +#define HKDF_COMMON_SETTABLES_NO_DIGEST \ 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) @@ -476,6 +485,83 @@ const OSSL_DISPATCH ossl_kdf_hkdf_functions[] = { OSSL_DISPATCH_END }; +static void *kdf_hkdf_fixed_digest_new(void *provctx, const char *digest) +{ + OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx); + KDF_HKDF *ctx; + OSSL_PARAM params[2]; + + ctx = kdf_hkdf_new(provctx); + if (ctx == NULL) + return NULL; + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST, + (char *)digest, 0); + params[1] = OSSL_PARAM_construct_end(); + if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) { + kdf_hkdf_free(ctx); + return NULL; + } + + return ctx; +} + +#define KDF_HKDF_FIXED_DIGEST_NEW(hashname, hashstring) \ + static void *kdf_hkdf_##hashname##_new(void *provctx) \ + { \ + return kdf_hkdf_fixed_digest_new(provctx, hashstring); \ + } + +KDF_HKDF_FIXED_DIGEST_NEW(sha256, "SHA256") +KDF_HKDF_FIXED_DIGEST_NEW(sha384, "SHA384") +KDF_HKDF_FIXED_DIGEST_NEW(sha512, "SHA512") + +static const OSSL_PARAM *kdf_hkdf_fixed_digest_settable_ctx_params(ossl_unused void *ctx, + ossl_unused void *provctx) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + HKDF_COMMON_SETTABLES_NO_DIGEST, + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_KDF_PARAM_FIPS_KEY_CHECK) + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int kdf_hkdf_fixed_digest_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + if (OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST) != NULL) { + /* + * TODO: OPENSSL MAINTAINERS: should it fail an any attempt to set the digest or + * should it be allowed to set the digest to the current digest? + */ + ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, + "Setting the digest is not supported for fixed-digest HKDFs"); + return 0; + } + + return kdf_hkdf_set_ctx_params(vctx, params); +} + +#define MAKE_KDF_HKDF_FIXED_DIGEST_FUNCTIONS(hashname) \ + const OSSL_DISPATCH ossl_kdf_hkdf_##hashname##_functions[] = { \ + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_##hashname##_new }, \ + { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_hkdf_dup }, \ + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free }, \ + { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset }, \ + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive }, \ + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, \ + (void(*)(void))kdf_hkdf_fixed_digest_settable_ctx_params }, \ + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_fixed_digest_set_ctx_params }, \ + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, (void(*)(void))kdf_hkdf_gettable_ctx_params }, \ + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params }, \ + OSSL_DISPATCH_END \ + }; + +MAKE_KDF_HKDF_FIXED_DIGEST_FUNCTIONS(sha256) +MAKE_KDF_HKDF_FIXED_DIGEST_FUNCTIONS(sha384) +MAKE_KDF_HKDF_FIXED_DIGEST_FUNCTIONS(sha512) + /* * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" * Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and diff --git a/test/evp_kdf_test.c b/test/evp_kdf_test.c index 1de2cff02a3..ddbb4fc1474 100644 --- a/test/evp_kdf_test.c +++ b/test/evp_kdf_test.c @@ -240,7 +240,42 @@ static int test_kdf_hkdf(void) return ret; } -static int do_kdf_hkdf_gettables(int extract_only, int has_digest) +static int kdf_hkdf_fixed_digest(const char *kdf_name, char *digest) +{ + int ret; + EVP_KDF_CTX *kctx1 = NULL; + EVP_KDF_CTX *kctx2 = NULL; + unsigned char out1[10]; + unsigned char out2[10]; + OSSL_PARAM *params1; + OSSL_PARAM *params2; + + params1 = construct_hkdf_params(digest, "secret", 6, "salt", "label"); + params2 = construct_hkdf_params(NULL, "secret", 6, "salt", "label"); + + ret = TEST_ptr(params1) + && TEST_ptr(params2) + && TEST_ptr(kctx1 = get_kdfbyname(OSSL_KDF_NAME_HKDF)) + && TEST_ptr(kctx2 = get_kdfbyname(kdf_name)) + && TEST_int_gt(EVP_KDF_derive(kctx1, out1, sizeof(out1), params1), 0) + && TEST_int_gt(EVP_KDF_derive(kctx2, out2, sizeof(out2), params2), 0) + && TEST_mem_eq(out1, sizeof(out1), out2, sizeof(out2)); + + EVP_KDF_CTX_free(kctx1); + EVP_KDF_CTX_free(kctx2); + OPENSSL_free(params1); + OPENSSL_free(params2); + return ret; +} + +static int test_kdf_hkdf_fixed_digest(void) +{ + return kdf_hkdf_fixed_digest(OSSL_KDF_NAME_HKDF_SHA256, "sha256") + && kdf_hkdf_fixed_digest(OSSL_KDF_NAME_HKDF_SHA384, "sha384") + && kdf_hkdf_fixed_digest(OSSL_KDF_NAME_HKDF_SHA512, "sha512"); +} + +static int do_kdf_hkdf_gettables(int expand_only, int has_digest) { int ret = 0; size_t sz = 0; @@ -352,6 +387,31 @@ static int test_kdf_hkdf_invalid_digest(void) return ret; } +static int kdf_hkdf_fixed_digest_change_digest(const char *kdf_name, char *digest) +{ + int ret; + EVP_KDF_CTX *kctx = NULL; + OSSL_PARAM *params; + + /* It is not allowed to change the digest in a fixed-digest KDF */ + params = construct_hkdf_params(digest, "secret", 6, "salt", "label"); + + ret = TEST_ptr(params) + && TEST_ptr(kctx = get_kdfbyname(kdf_name)) + && TEST_false(EVP_KDF_CTX_set_params(kctx, params)); + + EVP_KDF_CTX_free(kctx); + OPENSSL_free(params); + return ret; +} + +static int test_kdf_hkdf_fixed_digest_change_digest(void) +{ + return kdf_hkdf_fixed_digest_change_digest(OSSL_KDF_NAME_HKDF_SHA256, "sha256") + && kdf_hkdf_fixed_digest_change_digest(OSSL_KDF_NAME_HKDF_SHA384, "sha384") + && kdf_hkdf_fixed_digest_change_digest(OSSL_KDF_NAME_HKDF_SHA512, "sha512"); +} + static int test_kdf_hkdf_derive_set_params_fail(void) { int ret = 0, i = 0; @@ -2096,7 +2156,9 @@ int setup_tests(void) ADD_TEST(test_kdf_tls1_prf_empty_seed); ADD_TEST(test_kdf_tls1_prf_1byte_seed); ADD_TEST(test_kdf_hkdf); + ADD_TEST(test_kdf_hkdf_fixed_digest); ADD_TEST(test_kdf_hkdf_invalid_digest); + ADD_TEST(test_kdf_hkdf_fixed_digest_change_digest); ADD_TEST(test_kdf_hkdf_zero_output_size); ADD_TEST(test_kdf_hkdf_empty_key); ADD_TEST(test_kdf_hkdf_1byte_key); diff --git a/test/recipes/20-test_kdf.t b/test/recipes/20-test_kdf.t index 44b066497c6..de5c6e379e8 100755 --- a/test/recipes/20-test_kdf.t +++ b/test/recipes/20-test_kdf.t @@ -25,6 +25,9 @@ my @kdf_tests = ( { cmd => [qw{openssl kdf -keylen 10 -digest SHA256 -kdfopt key:secret -kdfopt salt:salt -kdfopt info:label HKDF}], expected => '2a:c4:36:9f:52:59:96:f8:de:13', desc => 'HKDF SHA256' }, + { cmd => [qw{openssl kdf -keylen 10 -kdfopt key:secret -kdfopt salt:salt -kdfopt info:label HKDF-SHA256}], + expected => '2a:c4:36:9f:52:59:96:f8:de:13', + desc => 'HKDF-SHA256' }, { cmd => [qw{openssl kdf -keylen 25 -digest SHA256 -kdfopt pass:passwordPASSWORDpassword -kdfopt salt:saltSALTsaltSALTsaltSALTsaltSALTsalt -kdfopt iter:4096 PBKDF2}], expected => '34:8C:89:DB:CB:D3:2B:2F:32:D8:14:B8:11:6E:84:CF:2B:17:34:7E:BC:18:00:18:1C', desc => 'PBKDF2 SHA256'}, diff --git a/test/recipes/30-test_evp_data/evpkdf_hkdf.txt b/test/recipes/30-test_evp_data/evpkdf_hkdf.txt index c617f2cc440..71ae8c6f71a 100644 --- a/test/recipes/30-test_evp_data/evpkdf_hkdf.txt +++ b/test/recipes/30-test_evp_data/evpkdf_hkdf.txt @@ -20,6 +20,12 @@ Ctrl.salt = hexsalt:000102030405060708090a0b0c Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9 Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865 +KDF = HKDF-SHA256 +Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +Ctrl.salt = hexsalt:000102030405060708090a0b0c +Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9 +Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865 + KDF = HKDF Ctrl.mode = mode:EXTRACT_ONLY Ctrl.digest = digest:SHA256 diff --git a/test/recipes/30-test_evp_data/evppkey_kdf_hkdf.txt b/test/recipes/30-test_evp_data/evppkey_kdf_hkdf.txt index 1fb24720012..932ada897e7 100644 --- a/test/recipes/30-test_evp_data/evppkey_kdf_hkdf.txt +++ b/test/recipes/30-test_evp_data/evppkey_kdf_hkdf.txt @@ -20,6 +20,12 @@ Ctrl.salt = hexsalt:000102030405060708090a0b0c Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9 Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865 +PKEYKDF = HKDF-SHA256 +Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b +Ctrl.salt = hexsalt:000102030405060708090a0b0c +Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9 +Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865 + PKEYKDF = HKDF Ctrl.mode = mode:EXTRACT_ONLY Ctrl.md = md:SHA256 -- 2.47.3