Implement riscv_vlen_asm for riscv32
[openssl.git] / test / rsa_test.c
index 13dcde1890225ed8c25ec9acb1981add93c4f546..2d9f6aa3a3f877124782ba1a11ab0faa4fe79377 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
@@ -9,10 +9,16 @@
 
 /* test vectors from p1ovect1.txt */
 
+/*
+ * RSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
 #include <stdio.h>
 #include <string.h>
 
-#include <internal/nelem.h>
+#include "internal/nelem.h"
 
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 
 #include "testutil.h"
 
-#ifdef OPENSSL_NO_RSA
-int setup_tests(void)
-{
-    /* No tests */
-    return 1;
-}
-#else
-# include <openssl/rsa.h>
+#include <openssl/rsa.h>
 
-# define SetKey \
+#define SetKey \
     RSA_set0_key(key,                                           \
                  BN_bin2bn(n, sizeof(n)-1, NULL),               \
                  BN_bin2bn(e, sizeof(e)-1, NULL),               \
@@ -42,7 +41,8 @@ int setup_tests(void)
                         BN_bin2bn(dmp1, sizeof(dmp1)-1, NULL),  \
                         BN_bin2bn(dmq1, sizeof(dmq1)-1, NULL),  \
                         BN_bin2bn(iqmp, sizeof(iqmp)-1, NULL)); \
-    memcpy(c, ctext_ex, sizeof(ctext_ex) - 1);                  \
+    if (c != NULL)                                              \
+        memcpy(c, ctext_ex, sizeof(ctext_ex) - 1);              \
     return sizeof(ctext_ex) - 1;
 
 static int key1(RSA *key, unsigned char *c)
@@ -211,69 +211,78 @@ static int key3(RSA *key, unsigned char *c)
     SetKey;
 }
 
-static int pad_unknown(void)
-{
-    unsigned long l;
-    while ((l = ERR_get_error()) != 0)
-        if (ERR_GET_REASON(l) == RSA_R_UNKNOWN_PADDING_TYPE)
-            return 1;
-    return 0;
-}
-
-static int rsa_setkey(RSA** key, unsigned char* ctext, int idx)
+static int rsa_setkey(RSA** key, unsigned char *ctext, int idx)
 {
     int clen = 0;
+
     *key = RSA_new();
-    switch (idx) {
-    case 0:
-        clen = key1(*key, ctext);
-        break;
-    case 1:
-        clen = key2(*key, ctext);
-        break;
-    case 2:
-        clen = key3(*key, ctext);
-        break;
-    }
+    if (*key != NULL)
+        switch (idx) {
+        case 0:
+            clen = key1(*key, ctext);
+            break;
+        case 1:
+            clen = key2(*key, ctext);
+            break;
+        case 2:
+            clen = key3(*key, ctext);
+            break;
+        }
     return clen;
 }
 
-static int test_rsa_pkcs1(int idx)
+static int test_rsa_simple(int idx, int en_pad_type, int de_pad_type,
+                           int success, unsigned char *ctext_ex, int *clen,
+                           RSA **retkey)
 {
     int ret = 0;
     RSA *key;
     unsigned char ptext[256];
     unsigned char ctext[256];
     static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
-    unsigned char ctext_ex[256];
     int plen;
-    int clen = 0;
+    int clentmp = 0;
     int num;
 
     plen = sizeof(ptext_ex) - 1;
-    clen = rsa_setkey(&key, ctext_ex, idx);
+    clentmp = rsa_setkey(&key, ctext_ex, idx);
+    if (clen != NULL)
+        *clen = clentmp;
 
-    num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
-                             RSA_PKCS1_PADDING);
-    if (!TEST_int_eq(num, clen))
+    num = RSA_public_encrypt(plen, ptext_ex, ctext, key, en_pad_type);
+    if (!TEST_int_eq(num, clentmp))
         goto err;
 
-    num = RSA_private_decrypt(num, ctext, ptext, key, RSA_PKCS1_PADDING);
-    if (!TEST_mem_eq(ptext, num, ptext_ex, plen))
-        goto err;
+    num = RSA_private_decrypt(num, ctext, ptext, key, de_pad_type);
+    if (success) {
+        if (!TEST_int_gt(num, 0) || !TEST_mem_eq(ptext, num, ptext_ex, plen))
+            goto err;
+    } else {
+        if (!TEST_int_lt(num, 0))
+            goto err;
+    }
 
     ret = 1;
+    if (retkey != NULL) {
+        *retkey = key;
+        key = NULL;
+    }
 err:
     RSA_free(key);
     return ret;
 }
 
+static int test_rsa_pkcs1(int idx)
+{
+    return test_rsa_simple(idx, RSA_PKCS1_PADDING, RSA_PKCS1_PADDING, 1, NULL,
+                           NULL, NULL);
+}
+
 static int test_rsa_oaep(int idx)
 {
     int ret = 0;
-    RSA *key;
+    RSA *key = NULL;
     unsigned char ptext[256];
-    unsigned char ctext[256];
     static unsigned char ptext_ex[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
     unsigned char ctext_ex[256];
     int plen;
@@ -281,43 +290,31 @@ static int test_rsa_oaep(int idx)
     int num;
     int n;
 
-    plen = sizeof(ptext_ex) - 1;
-    clen = rsa_setkey(&key, ctext_ex, idx);
-
-    num = RSA_public_encrypt(plen, ptext_ex, ctext, key,
-                             RSA_PKCS1_OAEP_PADDING);
-    if (num == -1 && pad_unknown()) {
-        TEST_info("Skipping: No OAEP support");
-        ret = 1;
-        goto err;
-    }
-    if (!TEST_int_eq(num, clen))
+    if (!test_rsa_simple(idx, RSA_PKCS1_OAEP_PADDING, RSA_PKCS1_OAEP_PADDING, 1,
+                         ctext_ex, &clen, &key))
         goto err;
 
-    num = RSA_private_decrypt(num, ctext, ptext, key,
-                              RSA_PKCS1_OAEP_PADDING);
-    if (!TEST_mem_eq(ptext, num, ptext_ex, plen))
-        goto err;
+    plen = sizeof(ptext_ex) - 1;
 
     /* Different ciphertexts. Try decrypting ctext_ex */
     num = RSA_private_decrypt(clen, ctext_ex, ptext, key,
                               RSA_PKCS1_OAEP_PADDING);
-    if (!TEST_mem_eq(ptext, num, ptext_ex, plen))
+    if (num <= 0 || !TEST_mem_eq(ptext, num, ptext_ex, plen))
         goto err;
 
     /* Try decrypting corrupted ciphertexts. */
     for (n = 0; n < clen; ++n) {
-        ctext[n] ^= 1;
-        num = RSA_private_decrypt(clen, ctext, ptext, key,
+        ctext_ex[n] ^= 1;
+        num = RSA_private_decrypt(clen, ctext_ex, ptext, key,
                                       RSA_PKCS1_OAEP_PADDING);
         if (!TEST_int_le(num, 0))
             goto err;
-        ctext[n] ^= 1;
+        ctext_ex[n] ^= 1;
     }
 
     /* Test truncated ciphertexts, as well as negative length. */
     for (n = -1; n < clen; ++n) {
-        num = RSA_private_decrypt(n, ctext, ptext, key,
+        num = RSA_private_decrypt(n, ctext_ex, ptext, key,
                                   RSA_PKCS1_OAEP_PADDING);
         if (!TEST_int_le(num, 0))
             goto err;
@@ -329,10 +326,395 @@ err:
     return ret;
 }
 
+static const struct {
+    int bits;
+    unsigned int r;
+} rsa_security_bits_cases[] = {
+    /* NIST SP 800-56B rev 2 (draft) Appendix D Table 5 */
+    { 2048,     112 },
+    { 3072,     128 },
+    { 4096,     152 },
+    { 6144,     176 },
+    { 8192,     200 },
+    /* NIST FIPS 140-2 IG 7.5 */
+    { 7680,     192 },
+    { 15360,    256 },
+    /* Older values */
+    { 256,      40  },
+    { 512,      56  },
+    { 1024,     80  },
+    /* Some other values */
+    { 8888,     208 },
+    { 2468,     120 },
+    { 13456,    248 },
+    /* Edge points */
+    { 15359,    256 },
+    { 15361,    264 },
+    { 7679,     192 },
+    { 7681,     200 },
+};
+
+static int test_rsa_security_bit(int n)
+{
+    static const unsigned char vals[8] = {
+        0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40
+    };
+    RSA *key = RSA_new();
+    const int bits = rsa_security_bits_cases[n].bits;
+    const int result = rsa_security_bits_cases[n].r;
+    const int bytes = (bits + 7) / 8;
+    int r = 0;
+    unsigned char num[2000];
+
+    if (!TEST_ptr(key) || !TEST_int_le(bytes, (int)sizeof(num)))
+        goto err;
+
+    /*
+     * It is necessary to set the RSA key in order to ask for the strength.
+     * A BN of an appropriate size is created, in general it won't have the
+     * properties necessary for RSA to function.  This is okay here since
+     * the RSA key is never used.
+     */
+    memset(num, vals[bits % 8], bytes);
+
+    /*
+     * The 'e' parameter is set to the same value as 'n'.  This saves having
+     * an extra BN to hold a sensible value for 'e'.  This is safe since the
+     * RSA key is not used.  The 'd' parameter can be NULL safely.
+     */
+    if (TEST_true(RSA_set0_key(key, BN_bin2bn(num, bytes, NULL),
+                               BN_bin2bn(num, bytes, NULL), NULL))
+            && TEST_uint_eq(RSA_security_bits(key), result))
+        r = 1;
+err:
+    RSA_free(key);
+    return r;
+}
+
+static int test_EVP_rsa_legacy_key(void)
+{
+    int ret;
+    size_t buflen = 384;
+    size_t msglen = 64;
+    unsigned char sigbuf[384];
+    unsigned char msgbuf[64];
+    BIGNUM *p;
+    BIGNUM *q;
+    BIGNUM *n;
+    BIGNUM *d;
+    BIGNUM *e;
+    RSA *rsa;
+    const EVP_MD *md;
+    EVP_MD_CTX *ctx = NULL;
+    EVP_PKEY *pkey = NULL;
+
+    unsigned char n_data[] = {
+    0x00, 0xc7, 0x28, 0x7a, 0x28, 0x91, 0x51, 0xa5, 0xe8, 0x3c, 0x45, 0xcf,
+    0x1d, 0xa9, 0x69, 0x7a, 0x0d, 0xdb, 0xdd, 0x8f, 0xe2, 0xde, 0x85, 0xdd,
+    0x85, 0x6d, 0x8f, 0x78, 0x20, 0xd6, 0xe, 0xe5, 0x06, 0xcb, 0x9c, 0xd6,
+    0xd3, 0xca, 0xef, 0x1d, 0x80, 0xd3, 0x18, 0x23, 0x91, 0x5c, 0xe5, 0xc8,
+    0x44, 0x37, 0x56, 0x1b, 0x68, 0x7f, 0x08, 0xa3, 0x1c, 0xf6, 0xe8, 0x11,
+    0x38, 0x0f, 0x2e, 0xad, 0xb1, 0x89, 0x8b, 0x08, 0xe8, 0x35, 0xaf, 0x3b,
+    0xfe, 0x37, 0x8d, 0x21, 0xd5, 0x3f, 0x1f, 0x4b, 0x01, 0x30, 0xd8, 0xd0,
+    0x24, 0xf7, 0xab, 0x57, 0xad, 0xac, 0xbc, 0x53, 0x6d, 0x84, 0x8e, 0xa1,
+    0xb2, 0x5b, 0x8e, 0xe7, 0xb3, 0xac, 0xfc, 0x60, 0x22, 0x10, 0x1e, 0x99,
+    0xfa, 0xa0, 0x60, 0x00, 0x69, 0x5f, 0x8e, 0xca, 0x6d, 0x9c, 0xee, 0x5e,
+    0x84, 0x4e, 0x53, 0x83, 0x42, 0x76, 0x4d, 0xb8, 0xc1, 0xeb, 0x4e, 0x3d,
+    0xc3, 0xce, 0xac, 0x79, 0xbb, 0x29, 0x5d, 0x92, 0x33, 0x6e, 0xcf, 0x8f,
+    0x5a, 0xf0, 0xb3, 0xb5, 0xdc, 0xd5, 0xa3, 0xaf, 0x40, 0x4b, 0x0f, 0x05,
+    0xac, 0x46, 0x53, 0x2d, 0x5f, 0x20, 0x96, 0x42, 0xa8, 0x47, 0x61, 0x54,
+    0x05, 0x2c, 0x8a, 0x26, 0x5d, 0x92, 0x1d, 0x01, 0x2a, 0x27, 0x8a, 0xfc,
+    0x64, 0x24, 0x5c, 0x34, 0xde, 0x92, 0xc6, 0x82, 0xea, 0x4d, 0xe2, 0x52,
+    0xe5, 0xad, 0x62, 0x00, 0xc6, 0xc8, 0xe9, 0x0c, 0x22, 0xf0, 0x9e, 0xbe,
+    0xdc, 0x51, 0x58, 0xad, 0x3b, 0xba, 0x2e, 0x45, 0x65, 0xcc, 0x5b, 0x55,
+    0x46, 0x67, 0x18, 0x4a, 0x80, 0x67, 0x5b, 0x84, 0x7f, 0x13, 0x37, 0x45,
+    0xd8, 0x03, 0xc6, 0x22, 0xc3, 0x4a, 0x46, 0x6b, 0xde, 0x50, 0xbf, 0x16,
+    0x0a, 0x23, 0x0b, 0xaa, 0x50, 0x54, 0xf6, 0x20, 0x83, 0x74, 0x33, 0x97,
+    0x2e, 0xf2, 0x8e, 0x7e, 0x13 };
+
+    unsigned char e_data[]  = { 0x01, 0x00, 0x01 };
+
+    unsigned char d_data[] = {
+    0x09, 0x2d, 0xcb, 0xe7, 0x87, 0xbf, 0x10, 0x1a, 0xf2, 0x80, 0x33, 0x2a,
+    0x06, 0x4f, 0x56, 0xb1, 0x41, 0xd3, 0x65, 0xd8, 0xca, 0x71, 0xb8, 0x02,
+    0x78, 0xc8, 0xb6, 0x7c, 0x28, 0xf4, 0x6c, 0xe8, 0xd1, 0xc4, 0x92, 0x40,
+    0x23, 0xa7, 0xbe, 0x9f, 0xdb, 0xda, 0xce, 0x74, 0xda, 0x27, 0xbb, 0x01,
+    0xad, 0xdd, 0x39, 0x99, 0x28, 0xd5, 0xb0, 0x92, 0xda, 0xac, 0x5a, 0x72,
+    0xcf, 0x7c, 0x52, 0xc4, 0x0e, 0x77, 0x4a, 0x7b, 0x4d, 0x52, 0x1c, 0xbd,
+    0x3c, 0x39, 0x34, 0x78, 0x7c, 0x16, 0xc8, 0xa1, 0xae, 0xeb, 0x27, 0x38,
+    0xb4, 0xf3, 0x80, 0x30, 0x80, 0x78, 0x13, 0x8e, 0x46, 0x20, 0x3e, 0xc2,
+    0x96, 0x26, 0xb1, 0x76, 0x1e, 0x00, 0x69, 0xbb, 0xd8, 0x2b, 0x58, 0xe4,
+    0x6c, 0xb4, 0xd0, 0x00, 0x0b, 0x47, 0xec, 0xfb, 0x7d, 0x52, 0x9d, 0x27,
+    0x92, 0xe6, 0x95, 0x73, 0xa0, 0x39, 0x37, 0xcd, 0x1f, 0x60, 0x13, 0x1c,
+    0x87, 0x9d, 0xa7, 0x91, 0x90, 0xf9, 0x36, 0xc5, 0xfa, 0x3f, 0xf9, 0x7f,
+    0x50, 0xf8, 0xb3, 0x54, 0x65, 0xff, 0x6f, 0xa6, 0x22, 0xcc, 0x4a, 0x1e,
+    0x49, 0x3f, 0x07, 0xc6, 0xf2, 0x65, 0x73, 0x13, 0x1b, 0x2d, 0xb6, 0x15,
+    0xff, 0xcd, 0x9a, 0x1c, 0xea, 0xef, 0x58, 0x56, 0x91, 0x2d, 0x47, 0x81,
+    0x56, 0x0d, 0xc3, 0xb0, 0x47, 0x58, 0x8d, 0x05, 0x7d, 0x5b, 0xc0, 0x22,
+    0xa4, 0xf0, 0x2e, 0x70, 0x36, 0x01, 0x89, 0xa1, 0x71, 0xed, 0x76, 0xe9,
+    0x8d, 0xf5, 0x49, 0xaf, 0x11, 0xbe, 0xe4, 0xd4, 0x48, 0x92, 0xb6, 0x5b,
+    0xc2, 0x04, 0xd4, 0x0c, 0x5c, 0x8b, 0xe3, 0xfa, 0x29, 0x63, 0x86, 0xb4,
+    0x10, 0xad, 0x32, 0x07, 0x85, 0xe2, 0x43, 0x76, 0x16, 0x90, 0xab, 0xdf,
+    0xb3, 0x36, 0x0a, 0xc4, 0x49, 0x7b, 0x95, 0x48, 0x50, 0x72, 0x8f, 0x7d,
+    0xf4, 0xfa, 0x60, 0xc1 };
+
+    unsigned char p_data[] = {
+    0x00, 0xed, 0xf7, 0xa7, 0x00, 0x5a, 0xbb, 0xd1, 0x52, 0x65, 0x9b, 0xec,
+    0xfe, 0x27, 0x8b, 0xe2, 0xbe, 0x40, 0x8c, 0x2f, 0x6f, 0xb4, 0x26, 0xb2,
+    0xbe, 0x45, 0x4b, 0x3b, 0x5a, 0xaa, 0xc6, 0xaa, 0xfa, 0xc1, 0x3a, 0xa9,
+    0xa1, 0xba, 0xb7, 0x86, 0x1a, 0x98, 0x15, 0x5f, 0x5c, 0x1c, 0x57, 0x78,
+    0x78, 0x6a, 0x13, 0xc2, 0x40, 0x7d, 0x07, 0x87, 0x47, 0xc6, 0x96, 0xd5,
+    0x92, 0xc9, 0x65, 0x2c, 0xfe, 0xbb, 0xe0, 0xd6, 0x76, 0x25, 0x5a, 0xa3,
+    0xdf, 0x97, 0x4b, 0x64, 0xfd, 0x3b, 0x2b, 0xbc, 0xfb, 0x80, 0xad, 0x3b,
+    0x7d, 0x1f, 0x48, 0x56, 0x27, 0xf7, 0x2f, 0x8e, 0x92, 0x07, 0xa8, 0x9f,
+    0xbc, 0x5a, 0xce, 0xfa, 0xd5, 0x67, 0xad, 0xf4, 0xbf, 0xe0, 0xc9, 0x3e,
+    0x8e, 0xb5, 0x90, 0x58, 0x54, 0x92, 0x9f, 0xda, 0x36, 0xc0, 0x0d, 0x57,
+    0xfe, 0x6c, 0x23, 0x63, 0x8b, 0xd1, 0x1e, 0x4f, 0xd3 };
+
+    unsigned char q_data[] = {
+    0x00, 0xd6, 0x3f, 0xf5, 0xee, 0xff, 0x4d, 0x7d, 0x8c, 0x1a, 0x85, 0x5d,
+    0x3c, 0x4f, 0x9d, 0xdf, 0xc7, 0x68, 0x27, 0x7f, 0xe4, 0x4f, 0x4f, 0xd7,
+    0xa2, 0x3b, 0xcd, 0x4a, 0x34, 0xd8, 0x55, 0x4a, 0x3e, 0x8e, 0xb3, 0xa8,
+    0xe9, 0x8a, 0xc5, 0x94, 0xd1, 0x09, 0x32, 0x4b, 0x79, 0x8d, 0x7b, 0x03,
+    0x0b, 0x5d, 0xca, 0x91, 0x41, 0xbc, 0x82, 0xc3, 0x89, 0x67, 0x4d, 0x03,
+    0x68, 0x03, 0x2d, 0x0e, 0x4e, 0x97, 0x6c, 0xf6, 0x3e, 0x1f, 0xf4, 0x50,
+    0x06, 0x5d, 0x05, 0x22, 0xf2, 0xf8, 0xf2, 0xde, 0xad, 0x2e, 0x9d, 0xc3,
+    0x97, 0x1b, 0xc3, 0x75, 0xe7, 0x86, 0xde, 0xc5, 0x11, 0x89, 0xed, 0x6a,
+    0x13, 0x14, 0x23, 0x4b, 0x98, 0x81, 0xf7, 0xd4, 0x1c, 0xee, 0x30, 0x92,
+    0x85, 0x20, 0x4f, 0x35, 0x02, 0xfa, 0xda, 0x14, 0x77, 0xfa, 0x08, 0x34,
+    0x60, 0xc7, 0x93, 0x72, 0xdc, 0xc4, 0x18, 0x70, 0xc1 };
+
+    memset(msgbuf, 0xef, 64);
+
+    ret = (TEST_ptr((p = BN_bin2bn(p_data, sizeof(p_data), NULL)))
+           && TEST_ptr((q = BN_bin2bn(q_data, sizeof(q_data), NULL)))
+           && TEST_ptr((n = BN_bin2bn(n_data, sizeof(n_data), NULL)))
+           && TEST_ptr((d = BN_bin2bn(d_data, sizeof(d_data), NULL)))
+           && TEST_ptr((e = BN_bin2bn(e_data, sizeof(e_data), NULL)))
+           && TEST_ptr((rsa = RSA_new()))
+           && TEST_ptr((md = EVP_sha256()))
+           && TEST_ptr((ctx = EVP_MD_CTX_new()))
+           && TEST_ptr((pkey = EVP_PKEY_new()))
+           && TEST_true(RSA_set0_factors(rsa, p, q))
+           && TEST_true(RSA_set0_key(rsa, n, e, d))
+           && TEST_true(EVP_PKEY_assign_RSA(pkey, rsa))
+           && TEST_true(EVP_DigestSignInit(ctx, NULL, md, NULL, pkey))
+           && TEST_true(EVP_DigestSign(ctx, sigbuf, &buflen, msgbuf, msglen)));
+
+    EVP_MD_CTX_free(ctx);
+    EVP_PKEY_free(pkey);
+    return ret;
+}
+
+static RSA *load_key(int priv)
+{
+    RSA *rsa = NULL;
+    BIGNUM *pn = NULL, *pe = NULL, *pd= NULL;
+
+    /* RSA key extracted using > openssl genpkey -algorithm RSA -text */
+    static const unsigned char n[] = {
+        0x00, 0xbe, 0x24, 0x14, 0xf2, 0x39, 0xde, 0x19, 0xb3, 0xd7, 0x86, 0x1e, 0xf8, 0xd3, 0x97,
+        0x9f, 0x78, 0x28, 0x4c, 0xbf, 0xef, 0x03, 0x29, 0xc5, 0xeb, 0x97, 0x18, 0xdb, 0xa5, 0x17,
+        0x07, 0x57, 0x96, 0xe2, 0x45, 0x91, 0x2b, 0xd2, 0x9e, 0x28, 0x61, 0xa7, 0x8f, 0x39, 0xaa,
+        0xde, 0x94, 0x6d, 0x2b, 0x39, 0xde, 0xbe, 0xcf, 0xd7, 0x29, 0x16, 0x3a, 0x1a, 0x86, 0x2f,
+        0xff, 0x7a, 0x2f, 0x12, 0xc4, 0x8a, 0x32, 0x06, 0x6f, 0x40, 0x42, 0x37, 0xaa, 0x5f, 0xaf,
+        0x40, 0x77, 0xa5, 0x73, 0x09, 0xbf, 0xc5, 0x85, 0x79, 0xc0, 0x38, 0xd6, 0xb7, 0x2f, 0x77,
+        0xf0, 0x5a, 0xaf, 0xaf, 0xc3, 0x63, 0x4b, 0xea, 0xa2, 0x0c, 0x27, 0xcd, 0x7c, 0x77, 0xf4,
+        0x29, 0x5a, 0x69, 0xbd, 0xfe, 0x17, 0xb6, 0xc5, 0xd7, 0xc0, 0x40, 0xf9, 0x29, 0x46, 0x1f,
+        0xc0, 0x4b, 0xcf, 0x4e, 0x8f, 0x74, 0xd9, 0xc8, 0xd0, 0xde, 0x9c, 0x48, 0x57, 0xcc, 0x30,
+        0xbc, 0x06, 0x47, 0x4a, 0x8e, 0x40, 0x8a, 0xa1, 0x2a, 0x09, 0x8d, 0xe8, 0x41, 0x3d, 0x21,
+        0x52, 0xdc, 0x9c, 0xa9, 0x43, 0x63, 0x01, 0x44, 0xb3, 0xec, 0x22, 0x06, 0x29, 0xf6, 0xd8,
+        0xf6, 0x6b, 0xc3, 0x36, 0x25, 0xb0, 0x9b, 0xdb, 0x9a, 0x22, 0x51, 0x13, 0x42, 0xbd, 0x28,
+        0x0b, 0xd8, 0x5e, 0xac, 0xc7, 0x71, 0x6e, 0x78, 0xfc, 0xf4, 0x1d, 0x74, 0x9b, 0x1a, 0x19,
+        0x13, 0x56, 0x04, 0xb4, 0x33, 0x4e, 0xed, 0x54, 0x59, 0x7f, 0x71, 0x5d, 0x24, 0x18, 0x91,
+        0x51, 0x20, 0x39, 0x78, 0x4e, 0x33, 0x73, 0x96, 0xa8, 0x12, 0x2f, 0xff, 0x48, 0xc2, 0x11,
+        0x33, 0x95, 0xe5, 0xcc, 0x1a, 0xe2, 0x39, 0xd5, 0x57, 0x44, 0x51, 0x59, 0xd1, 0x35, 0x62,
+        0x16, 0x22, 0xf5, 0x52, 0x3d, 0xe0, 0x9b, 0x2d, 0x33, 0x34, 0x75, 0x13, 0x7d, 0x62, 0x70,
+        0x53, 0x31
+    };
+    static const unsigned char e[] = {
+        0x01, 0x00, 0x01
+    };
+    static const unsigned char d[] = {
+        0x0b, 0xd3, 0x07, 0x7a, 0xb0, 0x0c, 0xb2, 0xe3, 0x5d, 0x49, 0x7f, 0xe0, 0xf4, 0x5b, 0x21,
+        0x31, 0x96, 0x2b, 0x7e, 0x32, 0xdf, 0x5a, 0xec, 0x5e, 0x10, 0x14, 0x9d, 0x99, 0xaa, 0xd8,
+        0xc3, 0xfa, 0x9c, 0x0e, 0x0c, 0x96, 0xe9, 0xa3, 0x58, 0x62, 0x68, 0xca, 0xba, 0x50, 0xc9,
+        0x04, 0x58, 0xd4, 0xe3, 0xa5, 0x99, 0x8f, 0x08, 0x2b, 0xcb, 0xe0, 0x1f, 0x84, 0xc5, 0x64,
+        0xbd, 0x48, 0xe2, 0xc1, 0x56, 0x51, 0x01, 0xb7, 0x8e, 0xca, 0xe3, 0x66, 0x70, 0xea, 0x7f,
+        0x8f, 0x45, 0x3a, 0xa6, 0x02, 0x3f, 0x16, 0xc3, 0xad, 0x57, 0x97, 0x8a, 0x37, 0x2d, 0x6d,
+        0xb4, 0xfd, 0x08, 0x98, 0x95, 0x72, 0xeb, 0xd7, 0xa9, 0x9a, 0xfa, 0xcf, 0x55, 0x10, 0x19,
+        0xf7, 0x7f, 0x7c, 0x8f, 0x49, 0xf3, 0x1d, 0xc2, 0xf2, 0xd7, 0xb3, 0x8a, 0xfc, 0x9b, 0x76,
+        0x40, 0x5c, 0xa7, 0x2f, 0x7a, 0x8a, 0x3d, 0xdf, 0xbc, 0x52, 0x69, 0x99, 0xf8, 0x4b, 0x7a,
+        0xbf, 0x11, 0x5d, 0x31, 0x41, 0x5f, 0xa3, 0xb9, 0x74, 0xaf, 0xe4, 0x08, 0x19, 0x9f, 0x88,
+        0xca, 0xfb, 0x8e, 0xab, 0xa4, 0x00, 0x31, 0xc9, 0xf1, 0x77, 0xe9, 0xe3, 0xf1, 0x98, 0xd9,
+        0x04, 0x08, 0x0c, 0x38, 0x35, 0x4b, 0xcc, 0xab, 0x22, 0xdf, 0x84, 0xea, 0xe4, 0x2e, 0x57,
+        0xa5, 0xc1, 0x91, 0x0c, 0x34, 0x3b, 0x88, 0xbc, 0x14, 0xee, 0x6e, 0xe3, 0xf0, 0xe0, 0xdc,
+        0xae, 0xd6, 0x0c, 0x9b, 0xa0, 0x6d, 0xb6, 0x92, 0x6c, 0x7e, 0x05, 0x46, 0x02, 0xbc, 0x23,
+        0xbc, 0x65, 0xe6, 0x62, 0x04, 0x19, 0xe6, 0x98, 0x67, 0x2d, 0x15, 0x0a, 0xc4, 0xea, 0xb5,
+        0x62, 0xa0, 0x54, 0xed, 0x07, 0x45, 0x3e, 0x21, 0x93, 0x3e, 0x22, 0xd0, 0xc3, 0xca, 0x37,
+        0x3c, 0xea, 0x90, 0xdd, 0xa6, 0xb1, 0x6c, 0x76, 0xce, 0x5a, 0xe1, 0xc2, 0x80, 0x1f, 0x32,
+        0x21
+    };
+
+    if (!TEST_ptr(rsa = RSA_new()))
+        return NULL;
+    pn = BN_bin2bn(n, sizeof(n), NULL);
+    pe = BN_bin2bn(e, sizeof(e), NULL);
+    if (priv)
+        pd = BN_bin2bn(d, sizeof(d), NULL);
+    if (!TEST_false(pn == NULL
+                    || pe == NULL
+                    || (priv && pd == NULL)
+                    || !RSA_set0_key(rsa, pn, pe, pd))) {
+        BN_free(pn);
+        BN_free(pe);
+        BN_free(pd);
+        RSA_free(rsa);
+        rsa = NULL;
+    }
+    return rsa;
+}
+
+static int test_rsa_saos(void)
+{
+    int ret = 0;
+    unsigned int siglen = 0;
+    RSA *rsa_priv = NULL, *rsa_pub = NULL;
+    static const unsigned char in[256] = { 0 };
+    unsigned char sig[256];
+    /* Maximum length allowed: The 3 relates to the octet byte 0x04 followed by a 2 byte length */
+    unsigned int inlen = sizeof(in) - RSA_PKCS1_PADDING_SIZE - 3;
+
+    /* A generated signature when in[inlen]= { 1 }. */
+    static const unsigned char sig_mismatch[256] = {
+        0x5f, 0x64, 0xab, 0xd3, 0x86, 0xdf, 0x6e, 0x91,
+        0xa8, 0xdb, 0x9d, 0x36, 0x7a, 0x15, 0xe5, 0x75,
+        0xe4, 0x27, 0xdf, 0xeb, 0x8d, 0xaf, 0xb0, 0x60,
+        0xec, 0x36, 0x8b, 0x00, 0x36, 0xb4, 0x61, 0x38,
+        0xfe, 0xfa, 0x49, 0x55, 0xcf, 0xb7, 0xff, 0xeb,
+        0x25, 0xa5, 0x41, 0x1e, 0xaa, 0x74, 0x3d, 0x57,
+        0xed, 0x5c, 0x4a, 0x01, 0x9e, 0xb2, 0x50, 0xbc,
+        0x50, 0x15, 0xd5, 0x97, 0x93, 0x91, 0x97, 0xa3,
+        0xff, 0x67, 0x2a, 0xe9, 0x04, 0xdd, 0x31, 0x6f,
+        0x4b, 0x44, 0x4f, 0x04, 0xa0, 0x48, 0x6a, 0xc1,
+        0x8d, 0xc2, 0xf3, 0xf7, 0xc4, 0x8c, 0x29, 0xcb,
+        0x2c, 0x04, 0x8f, 0x30, 0x71, 0xbb, 0x5b, 0xf9,
+        0xf9, 0x1b, 0xe8, 0xf0, 0xe8, 0xd1, 0xcf, 0x73,
+        0xf6, 0x02, 0x45, 0x6f, 0x53, 0x25, 0x1e, 0x74,
+        0x94, 0x6e, 0xf4, 0x0d, 0x36, 0x6c, 0xa3, 0xae,
+        0x8f, 0x94, 0x05, 0xa9, 0xe9, 0x65, 0x26, 0x7f,
+        0x07, 0xc5, 0x7e, 0xab, 0xd9, 0xe9, 0x09, 0x2d,
+        0x19, 0x8c, 0x6a, 0xcc, 0xd5, 0x62, 0x04, 0xb4,
+        0x9b, 0xaf, 0x99, 0x6a, 0x7a, 0x7b, 0xef, 0x01,
+        0x9b, 0xc1, 0x46, 0x59, 0x88, 0xee, 0x8b, 0xd7,
+        0xe5, 0x35, 0xad, 0x4c, 0xb2, 0x0d, 0x93, 0xdd,
+        0x0e, 0x50, 0x36, 0x2b, 0x7b, 0x42, 0x9b, 0x59,
+        0x95, 0xe7, 0xe1, 0x36, 0x50, 0x87, 0x7c, 0xac,
+        0x47, 0x13, 0x9b, 0xa7, 0x36, 0xdf, 0x8a, 0xd7,
+        0xee, 0x7d, 0x2e, 0xa6, 0xbb, 0x31, 0x32, 0xed,
+        0x39, 0x77, 0xf2, 0x41, 0xf9, 0x2d, 0x29, 0xfc,
+        0x6d, 0x32, 0x8e, 0x35, 0x99, 0x38, 0x8b, 0xd9,
+        0xc6, 0x77, 0x09, 0xe3, 0xe3, 0x06, 0x98, 0xe1,
+        0x96, 0xe9, 0x23, 0x11, 0xeb, 0x09, 0xa2, 0x6b,
+        0x21, 0x52, 0x67, 0x94, 0x15, 0x72, 0x7e, 0xdd,
+        0x66, 0x1c, 0xe7, 0xdb, 0x0e, 0x71, 0x5d, 0x95,
+        0x9d, 0xf8, 0x8e, 0x65, 0x97, 0x2f, 0x1a, 0x86
+    };
+    /* The signature generated by RSA_private_encrypt of in[inlen] */
+    static const unsigned char no_octet_sig[256] = {
+        0x78, 0xaf, 0x3e, 0xd1, 0xbc, 0x99, 0xb3, 0x19,
+        0xa8, 0xaa, 0x64, 0x56, 0x60, 0x95, 0xa0, 0x81,
+        0xd8, 0xb4, 0xe1, 0x9c, 0xf8, 0x94, 0xfa, 0x31,
+        0xb5, 0xde, 0x90, 0x75, 0xa7, 0xdb, 0xd4, 0x7e,
+        0xda, 0x62, 0xde, 0x16, 0x78, 0x4f, 0x9b, 0xc2,
+        0xa4, 0xd4, 0x5c, 0x17, 0x4f, 0x2d, 0xf2, 0x84,
+        0x5b, 0x5d, 0x00, 0xa0, 0xcf, 0xda, 0x3f, 0xbc,
+        0x40, 0xb4, 0x4e, 0xcb, 0x18, 0xeb, 0x4b, 0x0f,
+        0xce, 0x95, 0x3a, 0x5a, 0x9c, 0x49, 0xb4, 0x63,
+        0xd4, 0xde, 0xfb, 0xe2, 0xa8, 0xf3, 0x97, 0x52,
+        0x36, 0x3e, 0xc0, 0xab, 0xc8, 0x1c, 0xef, 0xdd,
+        0xf4, 0x37, 0xbc, 0xf3, 0xc3, 0x67, 0xf6, 0xc0,
+        0x6e, 0x75, 0xa6, 0xf3, 0x7e, 0x37, 0x96, 0xf2,
+        0xbb, 0x25, 0x3a, 0xa0, 0xa8, 0x8e, 0xce, 0xa0,
+        0xce, 0x0f, 0x22, 0x2d, 0x9c, 0x30, 0x0d, 0x20,
+        0x36, 0xc6, 0x9d, 0x36, 0x5d, 0x5b, 0x3e, 0xbc,
+        0x7c, 0x55, 0x95, 0xb4, 0x69, 0x19, 0x27, 0xf6,
+        0x63, 0x78, 0x21, 0x2d, 0xcf, 0x51, 0xb0, 0x46,
+        0x44, 0x02, 0x29, 0x93, 0xa5, 0x1b, 0xda, 0x21,
+        0xb3, 0x74, 0xf6, 0x4e, 0xd0, 0xdb, 0x3d, 0x59,
+        0xfd, 0xd7, 0x88, 0xd0, 0x2f, 0x84, 0xf6, 0xb1,
+        0xaa, 0xce, 0x3e, 0xa0, 0xdc, 0x1a, 0xd0, 0xe3,
+        0x5f, 0x3c, 0xda, 0x96, 0xee, 0xce, 0xf9, 0x75,
+        0xcf, 0x8d, 0xf3, 0x03, 0x28, 0xa7, 0x39, 0xbd,
+        0x95, 0xaa, 0x73, 0xbe, 0xa5, 0x5f, 0x84, 0x33,
+        0x07, 0x49, 0xbf, 0x03, 0xf8, 0x4b, 0x46, 0xbf,
+        0x38, 0xd4, 0x9b, 0x14, 0xa7, 0x01, 0xb7, 0x1f,
+        0x12, 0x08, 0x01, 0xed, 0xcd, 0x34, 0xf5, 0xb4,
+        0x06, 0x47, 0xe0, 0x53, 0x1c, 0x7c, 0x3f, 0xb5,
+        0x30, 0x59, 0xbb, 0xe3, 0xd6, 0x7c, 0x41, 0xcc,
+        0xd2, 0x11, 0x73, 0x03, 0x77, 0x7f, 0x5f, 0xad,
+        0x4a, 0x54, 0xdf, 0x17, 0x94, 0x97, 0x5c, 0x16
+    };
+
+    if (!TEST_ptr(rsa_priv = load_key(1)))
+        goto err;
+    if (!TEST_ptr(rsa_pub = load_key(0)))
+        goto err;
+    if (!TEST_int_ge((int)sizeof(sig), RSA_size(rsa_priv)))
+        goto err;
+
+    /* Test that a generated signature can be verified */
+    if (!TEST_true(RSA_sign_ASN1_OCTET_STRING(0, in, inlen, sig, &siglen,
+                                              rsa_priv)))
+        goto err;
+    if (!TEST_true(RSA_verify_ASN1_OCTET_STRING(0, in, inlen, sig, siglen, rsa_pub)))
+        goto err;
+
+    /* Test sign fails if the input is too large */
+    if (!TEST_false(RSA_sign_ASN1_OCTET_STRING(0, in, inlen + 1, sig, &siglen,
+                                               rsa_priv)))
+        goto err;
+
+    /* Fail if there is no private signing key */
+    if (!TEST_false(RSA_sign_ASN1_OCTET_STRING(0, in, inlen, sig, &siglen,
+                                               rsa_pub)))
+        goto err;
+
+    /* Fail if the signature is the wrong size */
+    if (!TEST_false(RSA_verify_ASN1_OCTET_STRING(0, in, inlen, sig, siglen - 1, rsa_pub)))
+        goto err;
+
+    /* Fail if the encrypted input is not octet encoded */
+    if (!TEST_false(RSA_verify_ASN1_OCTET_STRING(0, in, inlen, (unsigned char *)no_octet_sig,
+                                                 (unsigned int)sizeof(no_octet_sig),
+                                                 rsa_pub)))
+        goto err;
+
+    /* Fail if the signature does not match the input */
+    if (!TEST_false(RSA_verify_ASN1_OCTET_STRING(0, in, inlen, (unsigned char *)sig_mismatch,
+                                                 (unsigned int)sizeof(sig_mismatch),
+                                                 rsa_pub)))
+        goto err;
+
+    /* Fail if the signature is corrupt */
+    sig[0]++;
+    if (!TEST_false(RSA_verify_ASN1_OCTET_STRING(0, in, inlen, sig, siglen, rsa_pub)))
+        goto err;
+    sig[0]--;
+
+    ret = 1;
+err:
+    RSA_free(rsa_priv);
+    RSA_free(rsa_pub);
+    return ret;
+}
+
 int setup_tests(void)
 {
     ADD_ALL_TESTS(test_rsa_pkcs1, 3);
     ADD_ALL_TESTS(test_rsa_oaep, 3);
+    ADD_ALL_TESTS(test_rsa_security_bit, OSSL_NELEM(rsa_security_bits_cases));
+    ADD_TEST(test_rsa_saos);
+    ADD_TEST(test_EVP_rsa_legacy_key);
     return 1;
 }
-#endif