]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add FIPS indicators to X25519 and X448.
authorslontis <shane.lontis@oracle.com>
Wed, 21 Aug 2024 07:43:19 +0000 (17:43 +1000)
committerPauli <ppzgs1@gmail.com>
Sun, 25 Aug 2024 00:50:05 +0000 (10:50 +1000)
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)

doc/man7/EVP_KEYEXCH-X25519.pod
doc/man7/EVP_PKEY-X25519.pod
providers/implementations/exchange/ecx_exch.c
providers/implementations/keymgmt/ecx_kmgmt.c
test/evp_test.c
test/recipes/30-test_evp_data/evppkey_ecx.txt

index 6140c56196e4364c43a2b96c76840a42a425f434..5b2745da7760fdd19a27a58ff4d86e0352c5b882 100644 (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
index a63e50baa8322164c1c51760ef3fb3bd7d2bd081..c6de83222f1be4390bf76be1cb066507b4356e98 100644 (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().
index ccf39462eddc35eec316fbf660843f9b335240d9..cae2feb5519ee93ca371dd319a41160f917523f3 100644 (file)
 #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
 };
index cd9aac2276341b989ae755fc57dfeed62b8488b6..1f1ab0630110f40422f3fd3962798bf01214e808 100644 (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[])
index d290955806d7fac2ce425731d0fd78555e3efe87..6a47765745d21edae856dae4ed87991b82ba160b 100644 (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;
 }
index 2d6c6854239bedd094a212fd78be07af02db3253..eec740469d9add783a56d52be16b9e8cad587751 100644 (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