]> 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:07:20 +0000 (16:07 -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)

(cherry picked from commit 3206bb708246a97b281133009a419fb7421971d9)

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

index b6aa433ca93c6bf0abac81c908e4e34ce4d968cc..6abab0a7a173575db13429213d6ea856c333c945 100644 (file)
@@ -1308,6 +1308,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] = {
@@ -3497,3 +3509,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 35ecb43598ee9796d9c33a540bc23ef99f5b0a82..acb0b85f73433150dd195b6b5fec9c6a50767734 100644 (file)
@@ -812,6 +812,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.
@@ -853,6 +940,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;
@@ -1092,6 +1190,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());