diff --git a/doc/man7/EVP_KEYEXCH-X25519.pod b/doc/man7/EVP_KEYEXCH-X25519.pod index 6140c56196..5b2745da77 100644 --- a/doc/man7/EVP_KEYEXCH-X25519.pod +++ b/doc/man7/EVP_KEYEXCH-X25519.pod @@ -16,6 +16,11 @@ Key exchange support for the B and B key types. =item "pad" (B) +=item "fips-indicator" (B) + +B and B are not FIPS approved in FIPS 140-3. +So this getter will return 0. + See L. =back @@ -40,7 +45,7 @@ L, =head1 COPYRIGHT -Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_PKEY-X25519.pod b/doc/man7/EVP_PKEY-X25519.pod index a63e50baa8..c6de83222f 100644 --- a/doc/man7/EVP_PKEY-X25519.pod +++ b/doc/man7/EVP_PKEY-X25519.pod @@ -23,9 +23,15 @@ DHKEM requires the generation of a keypair using an input key material (seed). Use this to specify the key material used for generation of the private key. This value should not be reused for other purposes. It should have a length of at least 32 for X25519, and 56 for X448. - This is only supported by X25519 and X448. +=item "fips-indicator" (B) + +This getter is only supported by X25519 and X448 for the FIPS provider. +Since X25519 and X448 are unapproved in FIPS 140-3 this getter return 0. + +See L for further information. + =back Use EVP_PKEY_CTX_set_params() after calling EVP_PKEY_keygen_init(). diff --git a/providers/implementations/exchange/ecx_exch.c b/providers/implementations/exchange/ecx_exch.c index ccf39462ed..cae2feb551 100644 --- a/providers/implementations/exchange/ecx_exch.c +++ b/providers/implementations/exchange/ecx_exch.c @@ -17,14 +17,19 @@ #include "crypto/ecx.h" #include "prov/implementations.h" #include "prov/providercommon.h" +#include "prov/fipsindicator.h" +#include "prov/fipscommon.h" static OSSL_FUNC_keyexch_newctx_fn x25519_newctx; static OSSL_FUNC_keyexch_newctx_fn x448_newctx; -static OSSL_FUNC_keyexch_init_fn ecx_init; +static OSSL_FUNC_keyexch_init_fn x25519_init; +static OSSL_FUNC_keyexch_init_fn x448_init; static OSSL_FUNC_keyexch_set_peer_fn ecx_set_peer; static OSSL_FUNC_keyexch_derive_fn ecx_derive; static OSSL_FUNC_keyexch_freectx_fn ecx_freectx; static OSSL_FUNC_keyexch_dupctx_fn ecx_dupctx; +static OSSL_FUNC_keyexch_gettable_ctx_params_fn ecx_gettable_ctx_params; +static OSSL_FUNC_keyexch_get_ctx_params_fn ecx_get_ctx_params; /* * What's passed as an actual key is defined by the KEYMGMT interface. @@ -64,8 +69,7 @@ static void *x448_newctx(void *provctx) return ecx_newctx(provctx, X448_KEYLEN); } -static int ecx_init(void *vecxctx, void *vkey, - ossl_unused const OSSL_PARAM params[]) +static int ecx_init(void *vecxctx, void *vkey, const char *algname) { PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx; ECX_KEY *key = vkey; @@ -84,9 +88,25 @@ static int ecx_init(void *vecxctx, void *vkey, ossl_ecx_key_free(ecxctx->key); ecxctx->key = key; +#ifdef FIPS_MODULE + if (!ossl_FIPS_IND_callback(key->libctx, algname, "Init")) + return 0; +#endif return 1; } +static int x25519_init(void *vecxctx, void *vkey, + ossl_unused const OSSL_PARAM params[]) +{ + return ecx_init(vecxctx, vkey, "X25519"); +} + +static int x448_init(void *vecxctx, void *vkey, + ossl_unused const OSSL_PARAM params[]) +{ + return ecx_init(vecxctx, vkey, "X448"); +} + static int ecx_set_peer(void *vecxctx, void *vkey) { PROV_ECX_CTX *ecxctx = (PROV_ECX_CTX *)vecxctx; @@ -158,22 +178,51 @@ static void *ecx_dupctx(void *vecxctx) return dstctx; } +static const OSSL_PARAM *ecx_gettable_ctx_params(ossl_unused void *vctx, + ossl_unused void *provctx) +{ + static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() + OSSL_PARAM_END + }; + return known_gettable_ctx_params; +} + +static int ecx_get_ctx_params(ossl_unused void *vctx, OSSL_PARAM params[]) +{ +#ifdef FIPS_MODULE + int approved = 0; + OSSL_PARAM *p = OSSL_PARAM_locate(params, + OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR); + + if (p != NULL && !OSSL_PARAM_set_int(p, approved)) + return 0; +#endif + return 1; +} + const OSSL_DISPATCH ossl_x25519_keyexch_functions[] = { { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))x25519_newctx }, - { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecx_init }, + { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))x25519_init }, { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecx_derive }, { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecx_set_peer }, { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecx_freectx }, { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecx_dupctx }, + { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ecx_get_ctx_params }, + { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS, + (void (*)(void))ecx_gettable_ctx_params }, OSSL_DISPATCH_END }; const OSSL_DISPATCH ossl_x448_keyexch_functions[] = { { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))x448_newctx }, - { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecx_init }, + { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))x448_init }, { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecx_derive }, { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecx_set_peer }, { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecx_freectx }, { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecx_dupctx }, + { OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ecx_get_ctx_params }, + { OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS, + (void (*)(void))ecx_gettable_ctx_params }, OSSL_DISPATCH_END }; diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c b/providers/implementations/keymgmt/ecx_kmgmt.c index cd9aac2276..1f1ab06301 100644 --- a/providers/implementations/keymgmt/ecx_kmgmt.c +++ b/providers/implementations/keymgmt/ecx_kmgmt.c @@ -24,6 +24,8 @@ #include "prov/providercommon.h" #include "prov/provider_ctx.h" #include "prov/ecx.h" +#include "prov/fipsindicator.h" +#include "prov/fipscommon.h" #ifdef S390X_EC_ASM # include "s390x_arch.h" # include /* For SHA512_DIGEST_LENGTH */ @@ -303,6 +305,16 @@ static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits, if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen)) return 0; } +#ifdef FIPS_MODULE + { + /* X25519 and X448 are not approved */ + int approved = 0; + + p = OSSL_PARAM_locate(params, OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR); + if (p != NULL && !OSSL_PARAM_set_int(p, approved)) + return 0; + } +#endif return key_to_params(ecx, NULL, params, 1); } @@ -351,6 +363,7 @@ static const OSSL_PARAM ecx_gettable_params[] = { OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0), OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), ECX_KEY_TYPES(), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; @@ -475,7 +488,8 @@ static const OSSL_PARAM *ed448_settable_params(void *provctx) } static void *ecx_gen_init(void *provctx, int selection, - const OSSL_PARAM params[], ECX_KEY_TYPE type) + const OSSL_PARAM params[], ECX_KEY_TYPE type, + const char *algdesc) { OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx); struct ecx_gen_ctx *gctx = NULL; @@ -487,6 +501,14 @@ static void *ecx_gen_init(void *provctx, int selection, gctx->libctx = libctx; gctx->type = type; gctx->selection = selection; +#ifdef FIPS_MODULE + /* X25519/X448 are not FIPS approved, (ED25519/ED448 are approved) */ + if (algdesc != NULL + && !ossl_FIPS_IND_callback(libctx, algdesc, "KeyGen Init")) { + OPENSSL_free(gctx); + return 0; + } +#endif } if (!ecx_gen_set_params(gctx, params)) { OPENSSL_free(gctx); @@ -498,25 +520,25 @@ static void *ecx_gen_init(void *provctx, int selection, static void *x25519_gen_init(void *provctx, int selection, const OSSL_PARAM params[]) { - return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519); + return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519"); } static void *x448_gen_init(void *provctx, int selection, const OSSL_PARAM params[]) { - return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448); + return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448"); } static void *ed25519_gen_init(void *provctx, int selection, const OSSL_PARAM params[]) { - return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519); + return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519, NULL); } static void *ed448_gen_init(void *provctx, int selection, const OSSL_PARAM params[]) { - return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448); + return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448, NULL); } static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[]) diff --git a/test/evp_test.c b/test/evp_test.c index d290955806..6a47765745 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -118,11 +118,15 @@ static int check_fips_approved(EVP_TEST *t, int approved) * approved should be 0 and the fips indicator callback should be triggered. */ if (t->expect_unapproved) { - if (approved == 1 || fips_indicator_callback_unapproved_count == 0) + if (approved == 1 || fips_indicator_callback_unapproved_count == 0) { + TEST_error("Test is not expected to be FIPS approved"); return 0; + } } else { - if (approved == 0 || fips_indicator_callback_unapproved_count > 0) + if (approved == 0 || fips_indicator_callback_unapproved_count > 0) { + TEST_error("Test is expected to be FIPS approved"); return 0; + } } return 1; } diff --git a/test/recipes/30-test_evp_data/evppkey_ecx.txt b/test/recipes/30-test_evp_data/evppkey_ecx.txt index 2d6c685423..eec740469d 100644 --- a/test/recipes/30-test_evp_data/evppkey_ecx.txt +++ b/test/recipes/30-test_evp_data/evppkey_ecx.txt @@ -57,18 +57,30 @@ PrivPubKeyPair = Bob-25519:Bob-25519-PUBLIC PrivPubKeyPair = Bob-25519-Raw:Bob-25519-PUBLIC-Raw +Availablein = default Derive=Alice-25519 PeerKey=Bob-25519-PUBLIC SharedSecret=4A5D9D5BA4CE2DE1728E3BF480350F25E07E21C947D19E3376F09B3C1E161742 +# Test that X25519 Key exchange is not FIPS approved +Availablein = fips +FIPSversion = >=3.4.0 +Derive=Alice-25519 +PeerKey=Bob-25519-PUBLIC +SharedSecret=4A5D9D5BA4CE2DE1728E3BF480350F25E07E21C947D19E3376F09B3C1E161742 +Unapproved=1 + +Availablein = default Derive=Bob-25519 PeerKey=Alice-25519-PUBLIC SharedSecret=4A5D9D5BA4CE2DE1728E3BF480350F25E07E21C947D19E3376F09B3C1E161742 +Availablein = default Derive=Alice-25519-Raw PeerKey=Bob-25519-PUBLIC-Raw SharedSecret=4A5D9D5BA4CE2DE1728E3BF480350F25E07E21C947D19E3376F09B3C1E161742 +Availablein = default Derive=Bob-25519-Raw PeerKey=Alice-25519-PUBLIC-Raw SharedSecret=4A5D9D5BA4CE2DE1728E3BF480350F25E07E21C947D19E3376F09B3C1E161742 @@ -129,23 +141,36 @@ PrivPubKeyPair = Bob-448-Raw:Bob-448-PUBLIC-Raw PublicKeyRaw=Bob-448-PUBLIC-Raw-NonCanonical:X448:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +Availablein = default Derive=Alice-448 PeerKey=Bob-448-PUBLIC SharedSecret=07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d +# Test that X448 Key exchange is not FIPS approved +Availablein = fips +FIPSversion = >=3.4.0 +Derive=Alice-448 +PeerKey=Bob-448-PUBLIC +SharedSecret=07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d +Unapproved=1 + +Availablein = default Derive=Bob-448 PeerKey=Alice-448-PUBLIC SharedSecret=07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d +Availablein = default Derive=Alice-448-Raw PeerKey=Bob-448-PUBLIC-Raw SharedSecret=07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d +Availablein = default Derive=Bob-448-Raw PeerKey=Alice-448-PUBLIC-Raw SharedSecret=07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d # Self-generated non-canonical +Availablein = default Derive=Alice-448-Raw PeerKey=Bob-448-PUBLIC-Raw-NonCanonical SharedSecret=66e2e682b1f8e68c809f1bb3e406bd826921d9c1a5bfbfcbab7ae72feecee63660eabd54934f3382061d17607f581a90bdac917a064959fb @@ -536,6 +561,7 @@ PrivateKeyRaw = WychePRIVATE0:X25519:288796bc5aff4b81a37501757bc0753a3c21964790d PublicKeyRaw = WychePUBLIC0:X25519:f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f +Availablein = default Derive=WychePRIVATE0 PeerKey=WychePUBLIC0 SharedSecret=b4e0dd76da7b071728b61f856771aa356e57eda78a5b1655cc3820fb5f854c5c @@ -544,6 +570,7 @@ PrivateKeyRaw = WychePRIVATE1:X25519:60887b3dc72443026ebedbbbb70665f42b87add1440 PublicKeyRaw = WychePUBLIC1:X25519:f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +Availablein = default Derive=WychePRIVATE1 PeerKey=WychePUBLIC1 SharedSecret=38d6304c4a7e6d9f7959334fb5245bd2c754525d4c91db950206926234c1f633 @@ -552,18 +579,21 @@ PrivateKeyRaw = WychePRIVATE2:X25519:a0a4f130b98a5be4b1cedb7cb85584a3520e142d474 PublicKeyRaw = WychePUBLIC2:X25519:0ab4e76380d84dde4f6833c58f2a9fb8f83bb0169b172be4b6e0592887741a36 +Availablein = default Derive=WychePRIVATE2 PeerKey=WychePUBLIC2 SharedSecret=0200000000000000000000000000000000000000000000000000000000000000 PublicKeyRaw = WychePUBLIC3:X25519:89e10d5701b4337d2d032181538b1064bd4084401ceca1fd12663a1959388000 +Availablein = default Derive=WychePRIVATE2 PeerKey=WychePUBLIC3 SharedSecret=0900000000000000000000000000000000000000000000000000000000000000 PublicKeyRaw = WychePUBLIC4:X25519:2b55d3aa4a8f80c8c0b2ae5f933e85af49beac36c2fa7394bab76c8933f8f81d +Availablein = default Derive=WychePRIVATE2 PeerKey=WychePUBLIC4 SharedSecret=1000000000000000000000000000000000000000000000000000000000000000 @@ -919,3 +949,17 @@ Input = 616263 Ctrl = instance:Ed448ph Ctrl = hexcontext-string:666f6f Output = c32299d46ec8ff02b54540982814dce9a05812f81962b649d528095916a2aa481065b1580423ef927ecf0af5888f90da0f6a9a85ad5dc3f280d91224ba9911a3653d00e484e2ce232521481c8658df304bb7745a73514cdb9bf3e15784ab71284f8d0704a608c54a6b62d97beb511d132100 + +# Test that X25519 KeyGen is not FIPS approved +Availablein = fips +FIPSversion = >=3.4.0 +KeyGen = X25519 +KeyName = x25519_gen_key +Unapproved = 1 + +# Test that X448 KeyGen is not FIPS approved +Availablein = fips +FIPSversion = >=3.4.0 +KeyGen = X448 +KeyName = x448_gen_key +Unapproved = 1