+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#ifdef OPENSSL_FIPS
+
+
+#include <openssl/fips.h>
+#include <openssl/evp.h>
+
+static int fips_rsa_pairwise_fail = 0;
+
+void FIPS_corrupt_rsa_keygen(void)
+ {
+ fips_rsa_pairwise_fail = 1;
+ }
+
+int fips_check_rsa(RSA *rsa)
+ {
+ const unsigned char tbs[] = "RSA Pairwise Check Data";
+ unsigned char *ctbuf = NULL, *ptbuf = NULL;
+ int len, ret = 0;
+ EVP_PKEY pk;
+ pk.type = EVP_PKEY_RSA;
+ pk.pkey.rsa = rsa;
+
+ /* Perform pairwise consistency signature test */
+ if (!fips_pkey_signature_test(&pk, tbs, -1,
+ NULL, 0, NULL, RSA_PKCS1_PADDING, NULL)
+ || !fips_pkey_signature_test(&pk, tbs, -1,
+ NULL, 0, NULL, RSA_X931_PADDING, NULL)
+ || !fips_pkey_signature_test(&pk, tbs, -1,
+ NULL, 0, NULL, RSA_PKCS1_PSS_PADDING, NULL))
+ goto err;
+ /* Now perform pairwise consistency encrypt/decrypt test */
+ ctbuf = OPENSSL_malloc(RSA_size(rsa));
+ if (!ctbuf)
+ goto err;
+
+ len = RSA_public_encrypt(sizeof(tbs) - 1, tbs, ctbuf, rsa, RSA_PKCS1_PADDING);
+ if (len <= 0)
+ goto err;
+ /* Check ciphertext doesn't match plaintext */
+ if ((len == (sizeof(tbs) - 1)) && !memcmp(tbs, ctbuf, len))
+ goto err;
+ ptbuf = OPENSSL_malloc(RSA_size(rsa));
+
+ if (!ptbuf)
+ goto err;
+ len = RSA_private_decrypt(len, ctbuf, ptbuf, rsa, RSA_PKCS1_PADDING);
+ if (len != (sizeof(tbs) - 1))
+ goto err;
+ if (memcmp(ptbuf, tbs, len))
+ goto err;
+
+ ret = 1;
+
+ if (!ptbuf)
+ goto err;
+
+ err:
+ if (ret == 0)
+ {
+ fips_set_selftest_fail();
+ FIPSerr(FIPS_F_FIPS_CHECK_RSA,FIPS_R_PAIRWISE_TEST_FAILED);
+ }
+
+ if (ctbuf)
+ OPENSSL_free(ctbuf);
+ if (ptbuf)
+ OPENSSL_free(ptbuf);