Add FIPS indicators to X25519 and X448.

X25519 and X448 are unapproved in FIPS 140-3
So always trigger the indicator callback if these Keys are used,
and add "fips-indicator" getters that return 0.

This has been added to keygen and key exchange.
(KEM will also require it if ever becomes a FIPS algorithm).

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/25246)
This commit is contained in:
slontis 2024-08-21 17:43:19 +10:00 committed by Pauli
parent 32b43b9160
commit c37e21763b
6 changed files with 144 additions and 14 deletions

View File

@ -16,6 +16,11 @@ Key exchange support for the B<X25519> and B<X448> key types.
=item "pad" (B<OSSL_EXCHANGE_PARAM_PAD>) <unsigned integer>
=item "fips-indicator" (B<OSSL_EXCHANGE_PARAM_FIPS_APPROVED_INDICATOR>) <integer>
B<X25519> and B<X448> are not FIPS approved in FIPS 140-3.
So this getter will return 0.
See L<provider-keyexch(7)/Common Key Exchange parameters>.
=back
@ -40,7 +45,7 @@ L<OSSL_PROVIDER-FIPS(7)>,
=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

View File

@ -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<OSSL_PKEY_PARAM_FIPS_APPROVED_INDICATOR>) <integer>
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<provider-keymgmt(7)/Common Information Parameters> for further information.
=back
Use EVP_PKEY_CTX_set_params() after calling EVP_PKEY_keygen_init().

View File

@ -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
};

View File

@ -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 <openssl/sha.h> /* 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[])

View File

@ -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;
}

View File

@ -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