]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Revert "fips: remove redundant RSA encrypt/decrypt KAT"
authorNeil Horman <nhorman@openssl.org>
Thu, 25 Sep 2025 20:08:37 +0000 (16:08 -0400)
committerNeil Horman <nhorman@openssl.org>
Sat, 27 Sep 2025 20:01:19 +0000 (16:01 -0400)
This reverts commit 635bf4946a7e948f26a348ddc3b5a8d282354f64.

During code review for FIPS-140-3 certification, our lab noticed that
the known answer test for RSA was removed.  This was done in the above
commit, as part of
https://github.com/openssl/openssl/pull/25988

Under the assertion that FIPS 140-3 Implementation Guidance section D.G
had relaxed the requirements for testing, obviating the need for this
test.

However, for the 3.5 FIPS-140-3 certification we are adding assertions
for support of KAS-IFC-SSC, which follows FIPS-140-3 I.G section D.F,
which does not contain the same relaxed constraints.  As such we need to
reintroduce the test.

While the specifics of the I.G requirements are slightly different in
D.F (allowing for other, potentially less time-consuming tests), the
most expedient path forward here is to simply re-introduce the test as
it existed previously, hence the reversion of the above commit.

Fixes openssl/private#832

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28676)

providers/fips/self_test_data.inc
providers/fips/self_test_kats.c
test/recipes/03-test_fipsinstall.t

index ee15947a3b2af9b636dc0f7e41ece62160f031a4..e8dbe61c1e25273bb01d57442ce5d9b90d49c7b2 100644 (file)
@@ -1450,6 +1450,18 @@ static const ST_KAT_PARAM rsa_priv_key[] = {
     ST_KAT_PARAM_END()
 };
 
+/*-
+ * Using OSSL_PKEY_RSA_PAD_MODE_NONE directly in the expansion of the
+ * ST_KAT_PARAM_UTF8STRING macro below causes a failure on ancient
+ * HP/UX PA-RISC compilers.
+ */
+static const char pad_mode_none[] = OSSL_PKEY_RSA_PAD_MODE_NONE;
+
+static const ST_KAT_PARAM rsa_enc_params[] = {
+    ST_KAT_PARAM_UTF8STRING(OSSL_ASYM_CIPHER_PARAM_PAD_MODE, pad_mode_none),
+    ST_KAT_PARAM_END()
+};
+
 static const unsigned char rsa_sig_msg[] = "Hello World!";
 
 static const unsigned char rsa_expected_sig[256] = {
@@ -3664,3 +3676,33 @@ static const ST_KAT_ASYM_KEYGEN st_kat_asym_keygen_tests[] = {
 # endif
 };
 #endif /* !OPENSSL_NO_ML_DSA || !OPENSSL_NO_SLH_DSA */
+
+static const ST_KAT_ASYM_CIPHER st_kat_asym_cipher_tests[] = {
+    {
+        OSSL_SELF_TEST_DESC_ASYM_RSA_ENC,
+        "RSA",
+        1,
+        rsa_pub_key,
+        rsa_enc_params,
+        ITM(rsa_asym_plaintext_encrypt),
+        ITM(rsa_asym_expected_encrypt),
+    },
+    {
+        OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
+        "RSA",
+        0,
+        rsa_priv_key,
+        rsa_enc_params,
+        ITM(rsa_asym_expected_encrypt),
+        ITM(rsa_asym_plaintext_encrypt),
+    },
+    {
+        OSSL_SELF_TEST_DESC_ASYM_RSA_DEC,
+        "RSA",
+        0,
+        rsa_crt_key,
+        rsa_enc_params,
+        ITM(rsa_asym_expected_encrypt),
+        ITM(rsa_asym_plaintext_encrypt),
+    },
+};
index 156e7920f8e46073f56a7951d6daeab55bc95d94..f1a54c66093312015e62238188f2d09d7cfc1129 100644 (file)
@@ -858,6 +858,93 @@ err:
 }
 #endif
 
+/*
+ * Test an encrypt or decrypt KAT..
+ *
+ * FIPS 140-2 IG D.9 states that separate KAT tests are needed for encrypt
+ * and decrypt..
+ */
+static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st,
+                                 OSSL_LIB_CTX *libctx)
+{
+    int ret = 0;
+    OSSL_PARAM *keyparams = NULL, *initparams = NULL;
+    OSSL_PARAM_BLD *keybld = NULL, *initbld = NULL;
+    EVP_PKEY_CTX *encctx = NULL, *keyctx = NULL;
+    EVP_PKEY *key = NULL;
+    BN_CTX *bnctx = NULL;
+    unsigned char out[256];
+    size_t outlen = sizeof(out);
+
+    OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER, t->desc);
+
+    bnctx = BN_CTX_new_ex(libctx);
+    if (bnctx == NULL)
+        goto err;
+
+    /* Load a public or private key from data */
+    keybld = OSSL_PARAM_BLD_new();
+    if (keybld == NULL
+        || !add_params(keybld, t->key, bnctx))
+        goto err;
+    keyparams = OSSL_PARAM_BLD_to_param(keybld);
+    keyctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL);
+    if (keyctx == NULL || keyparams == NULL)
+        goto err;
+    if (EVP_PKEY_fromdata_init(keyctx) <= 0
+        || EVP_PKEY_fromdata(keyctx, &key, EVP_PKEY_KEYPAIR, keyparams) <= 0)
+        goto err;
+
+    /* Create a EVP_PKEY_CTX to use for the encrypt or decrypt operation */
+    encctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL);
+    if (encctx == NULL
+        || (t->encrypt && EVP_PKEY_encrypt_init(encctx) <= 0)
+        || (!t->encrypt && EVP_PKEY_decrypt_init(encctx) <= 0))
+        goto err;
+
+    /* Add any additional parameters such as padding */
+    if (t->postinit != NULL) {
+        initbld = OSSL_PARAM_BLD_new();
+        if (initbld == NULL)
+            goto err;
+        if (!add_params(initbld, t->postinit, bnctx))
+            goto err;
+        initparams = OSSL_PARAM_BLD_to_param(initbld);
+        if (initparams == NULL)
+            goto err;
+        if (EVP_PKEY_CTX_set_params(encctx, initparams) <= 0)
+            goto err;
+    }
+
+    if (t->encrypt) {
+        if (EVP_PKEY_encrypt(encctx, out, &outlen,
+                             t->in, t->in_len) <= 0)
+            goto err;
+    } else {
+        if (EVP_PKEY_decrypt(encctx, out, &outlen,
+                             t->in, t->in_len) <= 0)
+            goto err;
+    }
+    /* Check the KAT */
+    OSSL_SELF_TEST_oncorrupt_byte(st, out);
+    if (outlen != t->expected_len
+        || memcmp(out, t->expected, t->expected_len) != 0)
+        goto err;
+
+    ret = 1;
+err:
+    BN_CTX_free(bnctx);
+    EVP_PKEY_free(key);
+    EVP_PKEY_CTX_free(encctx);
+    EVP_PKEY_CTX_free(keyctx);
+    OSSL_PARAM_free(keyparams);
+    OSSL_PARAM_BLD_free(keybld);
+    OSSL_PARAM_free(initparams);
+    OSSL_PARAM_BLD_free(initbld);
+    OSSL_SELF_TEST_onend(st, ret);
+    return ret;
+}
+
 /*
  * Test a data driven list of KAT's for digest algorithms.
  * All tests are run regardless of if they fail or not.
@@ -899,6 +986,17 @@ static int self_test_kems(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
     return ret;
 }
 
+static int self_test_asym_ciphers(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
+{
+    int i, ret = 1;
+
+    for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_cipher_tests); ++i) {
+        if (!self_test_asym_cipher(&st_kat_asym_cipher_tests[i], st, libctx))
+            ret = 0;
+    }
+    return ret;
+}
+
 static int self_test_kdfs(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
 {
     int i, ret = 1;
@@ -1151,6 +1249,8 @@ int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
         ret = 0;
     if (!self_test_kems(st, libctx))
         ret = 0;
+    if (!self_test_asym_ciphers(st, libctx))
+        ret = 0;
 
     RAND_set0_private(libctx, saved_rand);
     return ret;
index 1f9110ef600a03ada86cba2213da40595ecf175c..3dcbe67c6d558c8362d211e9f4f9426e6f20baa9 100644 (file)
@@ -63,7 +63,7 @@ my @commandline =
         ( 'x942kdf_key_check',              'x942kdf-key-check' )
     );
 
-plan tests => 40 + (scalar @pedantic_okay) + (scalar @pedantic_fail)
+plan tests => 41 + (scalar @pedantic_okay) + (scalar @pedantic_fail)
               + 4 * (scalar @commandline);
 
 my $infile = bldtop_file('providers', platform->dso('fips'));
@@ -392,6 +392,16 @@ SKIP: {
        "fipsinstall fails when the ML-KEM decapsulate implicit failure result is corrupted");
 }
 
+# corrupt an Asymmetric cipher test
+SKIP: {
+    skip "Skipping Asymmetric RSA corruption test because of no rsa in this build", 1
+        if disabled("rsa") || disabled("fips-post");
+    ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
+                '-corrupt_desc', 'RSA_Encrypt',
+                '-corrupt_type', 'KAT_AsymmetricCipher'])),
+       "fipsinstall fails when the asymmetric cipher result is corrupted");
+}
+
 # 'local' ensures that this change is only done in this file.
 local $ENV{OPENSSL_CONF_INCLUDE} = abs2rel(curdir());