]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
dh: add FIPS 140-3 PCT on key import.
authorPauli <ppzgs1@gmail.com>
Thu, 30 Jan 2025 23:38:28 +0000 (10:38 +1100)
committerTomas Mraz <tomas@openssl.org>
Thu, 31 Jul 2025 18:39:40 +0000 (20:39 +0200)
This is mandated by FIPS 140-3 IG 10.3.A additional comment 1

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28122)

crypto/dh/dh_check.c
include/crypto/dh.h
providers/implementations/keymgmt/dh_kmgmt.c

index ae23f61839eab39ef2106fd11e8d13950195e306..1993f8674b285feecab3a977a938766d2257fc87 100644 (file)
@@ -16,6 +16,7 @@
 #include <stdio.h>
 #include "internal/cryptlib.h"
 #include <openssl/bn.h>
+#include <openssl/self_test.h>
 #include "dh_local.h"
 #include "crypto/dh.h"
 
@@ -329,17 +330,27 @@ end:
  * FFC pairwise check from SP800-56A R3.
  *    Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency
  */
-int ossl_dh_check_pairwise(const DH *dh)
+int ossl_dh_check_pairwise(const DH *dh, int return_on_null_numbers)
 {
     int ret = 0;
     BN_CTX *ctx = NULL;
     BIGNUM *pub_key = NULL;
+    OSSL_SELF_TEST *st = NULL;
+    OSSL_CALLBACK *stcb = NULL;
+    void *stcbarg = NULL;
 
     if (dh->params.p == NULL
         || dh->params.g == NULL
         || dh->priv_key == NULL
         || dh->pub_key == NULL)
-        return 0;
+        return return_on_null_numbers;
+
+    OSSL_SELF_TEST_get_callback(dh->libctx, &stcb, &stcbarg);
+    st = OSSL_SELF_TEST_new(stcb, stcbarg);
+    if (st == NULL)
+        goto err;
+    OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
+                           OSSL_SELF_TEST_DESC_PCT_DH);
 
     ctx = BN_CTX_new_ex(dh->libctx);
     if (ctx == NULL)
@@ -351,10 +362,27 @@ int ossl_dh_check_pairwise(const DH *dh)
     /* recalculate the public key = (g ^ priv) mod p */
     if (!ossl_dh_generate_public_key(ctx, dh, dh->priv_key, pub_key))
         goto err;
+
+#ifdef FIPS_MODULE
+    {
+        int len;
+        unsigned char bytes[1024] = {0};    /* Max key size of 8192 bits */
+
+        if (BN_num_bytes(pub_key) > (int)sizeof(bytes))
+            goto err;
+        len = BN_bn2bin(pub_key, bytes);
+        OSSL_SELF_TEST_oncorrupt_byte(st, bytes);
+        if (BN_bin2bn(bytes, len, pub_key) == NULL)
+            goto err;
+    }
+#endif
     /* check it matches the existing public_key */
     ret = BN_cmp(pub_key, dh->pub_key) == 0;
-err:
+ err:
     BN_free(pub_key);
     BN_CTX_free(ctx);
+
+    OSSL_SELF_TEST_onend(st, ret);
+    OSSL_SELF_TEST_free(st);
     return ret;
 }
index 51232d18c2446bd73f0e4f7b213751364dc23f90..624c0bf9cc804e75e096c3dcd386c249b7b942a7 100644 (file)
@@ -42,7 +42,7 @@ int ossl_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
 
 int ossl_dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret);
 int ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret);
-int ossl_dh_check_pairwise(const DH *dh);
+int ossl_dh_check_pairwise(const DH *dh, int return_on_null_numbers);
 
 const DH_METHOD *ossl_dh_get_method(const DH *dh);
 
index a8c552c8a5527c60b2c3e19ecd0e62d6c339eba1..5afda2eeaacd87abe2bae2ba5d0951f7ab52b904 100644 (file)
 #include <openssl/core_names.h>
 #include <openssl/bn.h>
 #include <openssl/err.h>
+#include <openssl/self_test.h>
 #include "prov/implementations.h"
 #include "prov/providercommon.h"
 #include "prov/provider_ctx.h"
 #include "crypto/dh.h"
+#include "internal/fips.h"
 #include "internal/sizes.h"
 
 static OSSL_FUNC_keymgmt_new_fn dh_newdata;
@@ -207,6 +209,18 @@ static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
 
         ok = ok && ossl_dh_key_fromdata(dh, params, include_private);
+#ifdef FIPS_MODULE
+        /*
+         * FIPS 140-3 IG 10.3.A additional comment 1 mandates that a pairwise
+         * consistency check be undertaken on key import.  The required test
+         * is described in SP 800-56Ar3 5.6.2.1.4.
+         */
+        if (ok > 0 && !ossl_fips_self_testing()) {
+            ok = ossl_dh_check_pairwise(dh, 1);
+            if (ok <= 0)
+                ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
+        }
+#endif  /* FIPS_MODULE */
     }
 
     return ok;
@@ -444,7 +458,7 @@ static int dh_validate(const void *keydata, int selection, int checktype)
 
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR)
             == OSSL_KEYMGMT_SELECT_KEYPAIR)
-        ok = ok && ossl_dh_check_pairwise(dh);
+        ok = ok && ossl_dh_check_pairwise(dh, 0);
     return ok;
 }