+}
+#endif /* FIPS_MODULE */
+
+static int rsa_keygen(OPENSSL_CTX *libctx, RSA *rsa, int bits, int primes,
+ BIGNUM *e_value, BN_GENCB *cb, int pairwise_test)
+{
+ int ok = 0;
+
+ /*
+ * Only multi-prime keys or insecure keys with a small key length will use
+ * the older rsa_multiprime_keygen().
+ */
+ if (primes == 2 && bits >= 2048)
+ ok = rsa_sp800_56b_generate_key(rsa, bits, e_value, cb);
+#ifndef FIPS_MODULE
+ else
+ ok = rsa_multiprime_keygen(rsa, bits, primes, e_value, cb);
+#endif /* FIPS_MODULE */
+
+#ifdef FIPS_MODULE
+ pairwise_test = 1; /* FIPS MODE needs to always run the pairwise test */
+#endif
+ if (pairwise_test && ok > 0) {
+ OSSL_CALLBACK *stcb = NULL;
+ void *stcbarg = NULL;
+
+ OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg);
+ ok = rsa_keygen_pairwise_test(rsa, stcb, stcbarg);
+ if (!ok) {
+ /* Clear intermediate results */
+ BN_clear_free(rsa->d);
+ BN_clear_free(rsa->p);
+ BN_clear_free(rsa->q);
+ BN_clear_free(rsa->dmp1);
+ BN_clear_free(rsa->dmq1);
+ BN_clear_free(rsa->iqmp);
+ rsa->d = NULL;
+ rsa->p = NULL;
+ rsa->q = NULL;
+ rsa->dmp1 = NULL;
+ rsa->dmq1 = NULL;
+ rsa->iqmp = NULL;
+ }
+ }
+ return ok;
+}
+
+/*
+ * For RSA key generation it is not known whether the key pair will be used
+ * for key transport or signatures. FIPS 140-2 IG 9.9 states that in this case
+ * either a signature verification OR an encryption operation may be used to
+ * perform the pairwise consistency check. The simpler encrypt/decrypt operation
+ * has been chosen for this case.
+ */
+static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg)
+{
+ int ret = 0;
+ unsigned int ciphertxt_len;
+ unsigned char *ciphertxt = NULL;
+ const unsigned char plaintxt[16] = {0};
+ unsigned char decoded[256];
+ unsigned int decoded_len;
+ unsigned int plaintxt_len = (unsigned int)sizeof(plaintxt_len);
+ int padding = RSA_PKCS1_PADDING;
+ OSSL_SELF_TEST *st = NULL;
+
+ st = OSSL_SELF_TEST_new(cb, cbarg);
+ if (st == NULL)
+ goto err;
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
+ OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1);
+
+ ciphertxt_len = RSA_size(rsa);
+ ciphertxt = OPENSSL_zalloc(ciphertxt_len);
+ if (ciphertxt == NULL)
+ goto err;
+
+ ciphertxt_len = RSA_public_encrypt(plaintxt_len, plaintxt, ciphertxt, rsa,
+ padding);
+ if (ciphertxt_len <= 0)
+ goto err;
+ if (ciphertxt_len == plaintxt_len
+ && memcmp(ciphertxt, plaintxt, plaintxt_len) == 0)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, ciphertxt);
+
+ decoded_len = RSA_private_decrypt(ciphertxt_len, ciphertxt, decoded, rsa,
+ padding);
+ if (decoded_len != plaintxt_len
+ || memcmp(decoded, plaintxt, decoded_len) != 0)
+ goto err;
+
+ ret = 1;
+err:
+ OSSL_SELF_TEST_onend(st, ret);
+ OSSL_SELF_TEST_free(st);
+ OPENSSL_free(ciphertxt);
+
+ return ret;