/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 *
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 *
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 *
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.] */

#include <openssl/rsa.h>

#include <stdlib.h>
#include <string.h>

#include <gtest/gtest.h>

#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/nid.h>

#include "../fipsmodule/bn/internal.h"
#include "../fipsmodule/rsa/internal.h"
#include "../internal.h"
#include "../test/test_util.h"

#if defined(OPENSSL_THREADS)
#include <thread>
#include <vector>
#endif


// kPlaintext is a sample plaintext.
static const uint8_t kPlaintext[] = {0x54, 0x85, 0x9b, 0x34,
                                     0x2c, 0x49, 0xea, 0x2a};


// kKey1 is a DER-encoded 1024-bit RSAPrivateKey with e = 65537.
static const uint8_t kKey1[] = {
    0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xa1,
    0x71, 0x90, 0x77, 0x86, 0x8a, 0xc7, 0xb8, 0xfc, 0x2a, 0x45, 0x82, 0x6d,
    0xee, 0xeb, 0x35, 0x3a, 0x18, 0x3f, 0xb6, 0xb0, 0x1e, 0xb1, 0xd3, 0x09,
    0x6b, 0x05, 0x4d, 0xec, 0x1c, 0x37, 0x6f, 0x09, 0x31, 0x32, 0xda, 0x21,
    0x8a, 0x49, 0x0e, 0x16, 0x28, 0xed, 0x9a, 0x30, 0xf3, 0x14, 0x53, 0xfd,
    0x5b, 0xb0, 0xf6, 0x4a, 0x5d, 0x52, 0xe1, 0xda, 0xe1, 0x40, 0x6e, 0x65,
    0xbf, 0xca, 0x45, 0xd9, 0x62, 0x96, 0x4a, 0x1e, 0x11, 0xc4, 0x61, 0x83,
    0x1f, 0x58, 0x8d, 0x5e, 0xd0, 0x12, 0xaf, 0xa5, 0xec, 0x9b, 0x97, 0x2f,
    0x6c, 0xb2, 0x82, 0x4a, 0x73, 0xd0, 0xd3, 0x9a, 0xc9, 0x69, 0x6b, 0x24,
    0x3c, 0x82, 0x6f, 0xee, 0x4d, 0x0c, 0x7e, 0xdf, 0xd7, 0xae, 0xea, 0x3a,
    0xeb, 0x04, 0x27, 0x8d, 0x43, 0x81, 0x59, 0xa7, 0x90, 0x56, 0xc1, 0x69,
    0x42, 0xb3, 0xaf, 0x1c, 0x8d, 0x4e, 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01,
    0x02, 0x81, 0x80, 0x60, 0x82, 0xcd, 0x44, 0x46, 0xcf, 0xeb, 0xf9, 0x6f,
    0xf5, 0xad, 0x3b, 0xfd, 0x90, 0x18, 0x57, 0xe7, 0x74, 0xdb, 0x91, 0xd0,
    0xd3, 0x68, 0xa6, 0xaa, 0x38, 0xaa, 0x21, 0x1d, 0x06, 0xf9, 0x34, 0x8d,
    0xa0, 0x35, 0xb0, 0x24, 0xe0, 0xd0, 0x2f, 0x75, 0x9b, 0xdd, 0xfe, 0x91,
    0x48, 0x9f, 0x5c, 0x5e, 0x57, 0x54, 0x00, 0xc8, 0x0f, 0xe6, 0x1e, 0x52,
    0x84, 0xd9, 0xc9, 0xa5, 0x55, 0xf4, 0x0a, 0xbe, 0x88, 0x46, 0x7a, 0xfb,
    0x18, 0x37, 0x8e, 0xe6, 0x6e, 0xa2, 0x5f, 0x80, 0x48, 0x34, 0x3f, 0x5c,
    0xbe, 0x0e, 0x1e, 0xe8, 0x2f, 0x50, 0xba, 0x14, 0x96, 0x3c, 0xea, 0xfb,
    0xd2, 0x49, 0x33, 0xdc, 0x12, 0xb8, 0xa7, 0x8a, 0xb5, 0x27, 0xf9, 0x00,
    0x4b, 0xf5, 0xd2, 0x2a, 0xd0, 0x2c, 0x1d, 0x9b, 0xd5, 0x6c, 0x3e, 0x4b,
    0xb9, 0x7e, 0x39, 0xf7, 0x3e, 0x39, 0xc9, 0x47, 0x5e, 0xbe, 0x91, 0x02,
    0x41, 0x00, 0xcd, 0x33, 0xcf, 0x37, 0x01, 0xd7, 0x59, 0xcc, 0xbe, 0xa0,
    0x1c, 0xb9, 0xf5, 0xe7, 0x44, 0x9f, 0x62, 0x91, 0xa7, 0xa7, 0x7b, 0x0c,
    0x52, 0xcd, 0x7e, 0xe6, 0x31, 0x11, 0x8b, 0xd8, 0x2c, 0x8a, 0x63, 0xe1,
    0x07, 0xc9, 0xcb, 0xce, 0x01, 0x45, 0x63, 0xf5, 0x5d, 0x44, 0xfb, 0xeb,
    0x8d, 0x74, 0x16, 0x20, 0x7d, 0x3b, 0xb4, 0xa1, 0x61, 0xb0, 0xa8, 0x29,
    0x51, 0xc9, 0xef, 0xb6, 0xa1, 0xd5, 0x02, 0x41, 0x00, 0xc9, 0x68, 0xa6,
    0xd3, 0x88, 0xd5, 0x49, 0x9d, 0x6b, 0x44, 0x96, 0xfd, 0xbf, 0x66, 0x27,
    0xb4, 0x1f, 0x90, 0x76, 0x86, 0x2f, 0xe2, 0xce, 0x20, 0x5d, 0xee, 0x9b,
    0xeb, 0xc4, 0xb4, 0x62, 0x47, 0x79, 0x99, 0xb1, 0x99, 0xbc, 0xa2, 0xa6,
    0xb6, 0x96, 0x64, 0xd5, 0x77, 0x9b, 0x45, 0xd4, 0xf0, 0x99, 0xb5, 0x9e,
    0x61, 0x4d, 0xf5, 0x12, 0xdd, 0x84, 0x14, 0xaf, 0x1e, 0xdd, 0x83, 0x24,
    0x43, 0x02, 0x40, 0x60, 0x29, 0x7f, 0x59, 0xcf, 0xcb, 0x13, 0x92, 0x17,
    0x63, 0x01, 0x13, 0x44, 0x61, 0x74, 0x8f, 0x1c, 0xaa, 0x15, 0x5f, 0x2f,
    0x12, 0xbf, 0x5a, 0xfd, 0xb4, 0xf2, 0x19, 0xbe, 0xe7, 0x37, 0x38, 0x43,
    0x46, 0x19, 0x58, 0x3f, 0xe1, 0xf2, 0x46, 0x8a, 0x69, 0x59, 0xa4, 0x12,
    0x4a, 0x78, 0xa7, 0x86, 0x17, 0x03, 0x99, 0x0f, 0x34, 0xf1, 0x8a, 0xcf,
    0xc3, 0x4d, 0x48, 0xcc, 0xc5, 0x51, 0x61, 0x02, 0x41, 0x00, 0xc2, 0x12,
    0xb3, 0x5d, 0xf5, 0xe5, 0xff, 0xcf, 0x4e, 0x43, 0x83, 0x72, 0xf2, 0xf1,
    0x4e, 0xa4, 0xc4, 0x1d, 0x81, 0xf7, 0xff, 0x40, 0x7e, 0xfa, 0xb5, 0x48,
    0x6c, 0xba, 0x1c, 0x8a, 0xec, 0x80, 0x8e, 0xed, 0xc8, 0x32, 0xa9, 0x8f,
    0xd9, 0x30, 0xeb, 0x6e, 0x32, 0x3b, 0xd4, 0x44, 0xcf, 0xd1, 0x1f, 0x6b,
    0xe0, 0x37, 0x46, 0xd5, 0x35, 0xde, 0x79, 0x9d, 0x2c, 0xb9, 0x83, 0x1d,
    0x10, 0xdd, 0x02, 0x40, 0x0f, 0x14, 0x95, 0x96, 0xa0, 0xe2, 0x6c, 0xd4,
    0x88, 0xa7, 0x0b, 0x82, 0x14, 0x10, 0xad, 0x26, 0x0d, 0xe4, 0xa1, 0x5e,
    0x01, 0x3d, 0x21, 0xd2, 0xfb, 0x0e, 0xf9, 0x58, 0xa5, 0xca, 0x1e, 0x21,
    0xb3, 0xf5, 0x9a, 0x6c, 0x3d, 0x5a, 0x72, 0xb1, 0x2d, 0xfe, 0xac, 0x09,
    0x4f, 0xdd, 0xe5, 0x44, 0xd1, 0x4e, 0xf8, 0x59, 0x85, 0x3a, 0x65, 0xe2,
    0xcd, 0xbc, 0x27, 0x1d, 0x9b, 0x48, 0x9f, 0xb9};

static const uint8_t kKey1Public[] = {
    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa1, 0x71, 0x90, 0x77, 0x86,
    0x8a, 0xc7, 0xb8, 0xfc, 0x2a, 0x45, 0x82, 0x6d, 0xee, 0xeb, 0x35, 0x3a,
    0x18, 0x3f, 0xb6, 0xb0, 0x1e, 0xb1, 0xd3, 0x09, 0x6b, 0x05, 0x4d, 0xec,
    0x1c, 0x37, 0x6f, 0x09, 0x31, 0x32, 0xda, 0x21, 0x8a, 0x49, 0x0e, 0x16,
    0x28, 0xed, 0x9a, 0x30, 0xf3, 0x14, 0x53, 0xfd, 0x5b, 0xb0, 0xf6, 0x4a,
    0x5d, 0x52, 0xe1, 0xda, 0xe1, 0x40, 0x6e, 0x65, 0xbf, 0xca, 0x45, 0xd9,
    0x62, 0x96, 0x4a, 0x1e, 0x11, 0xc4, 0x61, 0x83, 0x1f, 0x58, 0x8d, 0x5e,
    0xd0, 0x12, 0xaf, 0xa5, 0xec, 0x9b, 0x97, 0x2f, 0x6c, 0xb2, 0x82, 0x4a,
    0x73, 0xd0, 0xd3, 0x9a, 0xc9, 0x69, 0x6b, 0x24, 0x3c, 0x82, 0x6f, 0xee,
    0x4d, 0x0c, 0x7e, 0xdf, 0xd7, 0xae, 0xea, 0x3a, 0xeb, 0x04, 0x27, 0x8d,
    0x43, 0x81, 0x59, 0xa7, 0x90, 0x56, 0xc1, 0x69, 0x42, 0xb3, 0xaf, 0x1c,
    0x8d, 0x4e, 0xbf, 0x02, 0x03, 0x01, 0x00, 0x01};

// kOAEPCiphertext1 is a sample encryption of |kPlaintext| with |kKey1| using
// RSA OAEP, SHA-1, and no label. It was generated with:
//
// clang-format off
// openssl pkeyutl -encrypt -inkey key1.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -in plaintext | xxd -i
// clang-format on
static const uint8_t kOAEPCiphertext1[] = {
    0x53, 0xa3, 0x0e, 0xc7, 0x95, 0x52, 0x80, 0x6f, 0x9d, 0x4c, 0xd2, 0x87,
    0xa0, 0x5d, 0x4b, 0xee, 0x78, 0x7d, 0xaa, 0x2a, 0xf6, 0x48, 0x5e, 0x83,
    0xb4, 0xc7, 0xd5, 0x82, 0xa7, 0xe9, 0x3e, 0x4c, 0x54, 0xa0, 0x1e, 0x5f,
    0x49, 0x17, 0x26, 0x36, 0x37, 0x22, 0x09, 0xe8, 0xde, 0x8d, 0x51, 0x49,
    0x0b, 0x34, 0x27, 0x30, 0x1f, 0x12, 0xbd, 0xf4, 0x2f, 0xed, 0x9e, 0xcf,
    0x9e, 0xda, 0x41, 0x69, 0xf7, 0x86, 0x64, 0xfc, 0x7d, 0x0a, 0x4b, 0x28,
    0x28, 0x9e, 0x38, 0x97, 0xae, 0x01, 0x86, 0xbe, 0xb0, 0x92, 0xfd, 0xa0,
    0x5c, 0x75, 0xaf, 0x01, 0x88, 0xf7, 0x24, 0xa8, 0xcd, 0x44, 0x3c, 0x13,
    0x42, 0xf7, 0x03, 0x9b, 0x88, 0x1c, 0x65, 0xf4, 0x83, 0xba, 0xc8, 0x10,
    0xe2, 0x9a, 0x37, 0x79, 0x77, 0xef, 0x20, 0x3d, 0x2d, 0xa4, 0xe5, 0x3e,
    0xd4, 0x18, 0x3e, 0x12, 0xc1, 0xc3, 0x68, 0x65};

// kKey2 is a 2048-bit RSA private key, with e = 3.
static const uint8_t kKey2[] = {
    0x30, 0x82, 0x04, 0xa1, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
    0x93, 0x3a, 0x4f, 0xc9, 0x6a, 0x0a, 0x6b, 0x28, 0x04, 0xfa, 0xb7, 0x05,
    0x56, 0xdf, 0xa0, 0xaa, 0x4f, 0xaa, 0xab, 0x94, 0xa0, 0xa9, 0x25, 0xef,
    0xc5, 0x96, 0xd2, 0xd4, 0x66, 0x16, 0x62, 0x2c, 0x13, 0x7b, 0x91, 0xd0,
    0x36, 0x0a, 0x10, 0x11, 0x6d, 0x7a, 0x91, 0xb6, 0xe4, 0x74, 0x57, 0xc1,
    0x3d, 0x7a, 0xbe, 0x24, 0x05, 0x3a, 0x04, 0x0b, 0x73, 0x91, 0x53, 0xb1,
    0x74, 0x10, 0xe1, 0x87, 0xdc, 0x91, 0x28, 0x9c, 0x1e, 0xe5, 0xf2, 0xb9,
    0xfc, 0xa2, 0x48, 0x34, 0xb6, 0x78, 0xed, 0x6d, 0x95, 0xfb, 0xf2, 0xc0,
    0x4e, 0x1c, 0xa4, 0x15, 0x00, 0x3c, 0x8a, 0x68, 0x2b, 0xd6, 0xce, 0xd5,
    0xb3, 0x9f, 0x66, 0x02, 0xa7, 0x0d, 0x08, 0xa3, 0x23, 0x9b, 0xe5, 0x36,
    0x96, 0x13, 0x22, 0xf9, 0x69, 0xa6, 0x87, 0x88, 0x9b, 0x85, 0x3f, 0x83,
    0x9c, 0xab, 0x1a, 0x1b, 0x6d, 0x8d, 0x16, 0xf4, 0x5e, 0xbd, 0xee, 0x4b,
    0x59, 0x56, 0xf8, 0x9d, 0x58, 0xcd, 0xd2, 0x83, 0x85, 0x59, 0x43, 0x84,
    0x63, 0x4f, 0xe6, 0x1a, 0x86, 0x66, 0x0d, 0xb5, 0xa0, 0x87, 0x89, 0xb6,
    0x13, 0x82, 0x43, 0xda, 0x34, 0x92, 0x3b, 0x68, 0xc4, 0x95, 0x71, 0x2f,
    0x15, 0xc2, 0xe0, 0x43, 0x67, 0x3c, 0x08, 0x00, 0x36, 0x10, 0xc3, 0xb4,
    0x46, 0x4c, 0x4e, 0x6e, 0xf5, 0x44, 0xa9, 0x04, 0x44, 0x9d, 0xce, 0xc7,
    0x05, 0x79, 0xee, 0x11, 0xcf, 0xaf, 0x2c, 0xd7, 0x9a, 0x32, 0xd3, 0xa5,
    0x30, 0xd4, 0x3a, 0x78, 0x43, 0x37, 0x74, 0x22, 0x90, 0x24, 0x04, 0x11,
    0xd7, 0x95, 0x08, 0x52, 0xa4, 0x71, 0x41, 0x68, 0x94, 0xb0, 0xa0, 0xc3,
    0xec, 0x4e, 0xd2, 0xc4, 0x30, 0x71, 0x98, 0x64, 0x9c, 0xe3, 0x7c, 0x76,
    0xef, 0x33, 0xa3, 0x2b, 0xb1, 0x87, 0x63, 0xd2, 0x5c, 0x09, 0xfc, 0x90,
    0x2d, 0x92, 0xf4, 0x57, 0x02, 0x01, 0x03, 0x02, 0x82, 0x01, 0x00, 0x62,
    0x26, 0xdf, 0xdb, 0x9c, 0x06, 0xf2, 0x1a, 0xad, 0xfc, 0x7a, 0x03, 0x8f,
    0x3f, 0xc0, 0x71, 0x8a, 0x71, 0xc7, 0xb8, 0x6b, 0x1b, 0x6e, 0x9f, 0xd9,
    0x0f, 0x37, 0x38, 0x44, 0x0e, 0xec, 0x1d, 0x62, 0x52, 0x61, 0x35, 0x79,
    0x5c, 0x0a, 0xb6, 0x48, 0xfc, 0x61, 0x24, 0x98, 0x4d, 0x8f, 0xd6, 0x28,
    0xfc, 0x7e, 0xc2, 0xae, 0x26, 0xad, 0x5c, 0xf7, 0xb6, 0x37, 0xcb, 0xa2,
    0xb5, 0xeb, 0xaf, 0xe8, 0x60, 0xc5, 0xbd, 0x69, 0xee, 0xa1, 0xd1, 0x53,
    0x16, 0xda, 0xcd, 0xce, 0xfb, 0x48, 0xf3, 0xb9, 0x52, 0xa1, 0xd5, 0x89,
    0x68, 0x6d, 0x63, 0x55, 0x7d, 0xb1, 0x9a, 0xc7, 0xe4, 0x89, 0xe3, 0xcd,
    0x14, 0xee, 0xac, 0x6f, 0x5e, 0x05, 0xc2, 0x17, 0xbd, 0x43, 0x79, 0xb9,
    0x62, 0x17, 0x50, 0xf1, 0x19, 0xaf, 0xb0, 0x67, 0xae, 0x2a, 0x57, 0xbd,
    0xc7, 0x66, 0xbc, 0xf3, 0xb3, 0x64, 0xa1, 0xe3, 0x16, 0x74, 0x9e, 0xea,
    0x02, 0x5c, 0xab, 0x94, 0xd8, 0x97, 0x02, 0x42, 0x0c, 0x2c, 0xba, 0x54,
    0xb9, 0xaf, 0xe0, 0x45, 0x93, 0xad, 0x7f, 0xb3, 0x10, 0x6a, 0x96, 0x50,
    0x4b, 0xaf, 0xcf, 0xc8, 0x27, 0x62, 0x2d, 0x83, 0xe9, 0x26, 0xc6, 0x94,
    0xc1, 0xef, 0x5c, 0x8e, 0x06, 0x42, 0x53, 0xe5, 0x56, 0xaf, 0xc2, 0x99,
    0x01, 0xaa, 0x9a, 0x71, 0xbc, 0xe8, 0x21, 0x33, 0x2a, 0x2d, 0xa3, 0x36,
    0xac, 0x1b, 0x86, 0x19, 0xf8, 0xcd, 0x1f, 0x80, 0xa4, 0x26, 0x98, 0xb8,
    0x9f, 0x62, 0x62, 0xd5, 0x1a, 0x7f, 0xee, 0xdb, 0xdf, 0x81, 0xd3, 0x21,
    0xdb, 0x33, 0x92, 0xee, 0xff, 0xe2, 0x2f, 0x32, 0x77, 0x73, 0x6a, 0x58,
    0xab, 0x21, 0xf3, 0xe3, 0xe1, 0xbc, 0x4f, 0x12, 0x72, 0xa6, 0xb5, 0xc2,
    0xfb, 0x27, 0x9e, 0xc8, 0xca, 0xab, 0x64, 0xa0, 0x87, 0x07, 0x9d, 0xef,
    0xca, 0x0f, 0xdb, 0x02, 0x81, 0x81, 0x00, 0xe6, 0xd3, 0x4d, 0xc0, 0xa1,
    0x91, 0x0e, 0x62, 0xfd, 0xb0, 0xdd, 0xc6, 0x30, 0xb8, 0x8c, 0xcb, 0x14,
    0xc1, 0x4b, 0x69, 0x30, 0xdd, 0xcd, 0x86, 0x67, 0xcb, 0x37, 0x14, 0xc5,
    0x03, 0xd2, 0xb4, 0x69, 0xab, 0x3d, 0xe5, 0x16, 0x81, 0x0f, 0xe5, 0x50,
    0xf4, 0x18, 0xb1, 0xec, 0xbc, 0x71, 0xe9, 0x80, 0x99, 0x06, 0xe4, 0xa3,
    0xfe, 0x44, 0x84, 0x4a, 0x2d, 0x1e, 0x07, 0x7f, 0x22, 0x70, 0x6d, 0x4f,
    0xd4, 0x93, 0x0b, 0x8b, 0x99, 0xce, 0x1e, 0xab, 0xcd, 0x4c, 0xd2, 0xd3,
    0x10, 0x47, 0x5c, 0x09, 0x9f, 0x6d, 0x82, 0xc0, 0x08, 0x75, 0xe3, 0x3d,
    0x83, 0xc2, 0x19, 0x50, 0x29, 0xec, 0x1f, 0x84, 0x29, 0xcc, 0xf1, 0x56,
    0xee, 0xbd, 0x54, 0x5d, 0xe6, 0x19, 0xdf, 0x0d, 0x1c, 0xa4, 0xbb, 0x0a,
    0xfe, 0x84, 0x44, 0x29, 0x1d, 0xf9, 0x5c, 0x80, 0x96, 0x5b, 0x24, 0xb4,
    0xf7, 0x02, 0x1b, 0x02, 0x81, 0x81, 0x00, 0xa3, 0x48, 0xf1, 0x9c, 0x58,
    0xc2, 0x5f, 0x38, 0xfb, 0xd8, 0x12, 0x39, 0xf1, 0x8e, 0x73, 0xa1, 0xcf,
    0x78, 0x12, 0xe0, 0xed, 0x2a, 0xbb, 0xef, 0xac, 0x23, 0xb2, 0xbf, 0xd6,
    0x0c, 0xe9, 0x6e, 0x1e, 0xab, 0xea, 0x3f, 0x68, 0x36, 0xa7, 0x1f, 0xe5,
    0xab, 0xe0, 0x86, 0xa5, 0x76, 0x32, 0x98, 0xdd, 0x75, 0xb5, 0x2b, 0xbc,
    0xcb, 0x8a, 0x03, 0x00, 0x7c, 0x2e, 0xca, 0xf8, 0xbc, 0x19, 0xe4, 0xe3,
    0xa3, 0x31, 0xbd, 0x1d, 0x20, 0x2b, 0x09, 0xad, 0x6f, 0x4c, 0xed, 0x48,
    0xd4, 0xdf, 0x87, 0xf9, 0xf0, 0x46, 0xb9, 0x86, 0x4c, 0x4b, 0x71, 0xe7,
    0x48, 0x78, 0xdc, 0xed, 0xc7, 0x82, 0x02, 0x44, 0xd3, 0xa6, 0xb3, 0x10,
    0x5f, 0x62, 0x81, 0xfc, 0xb8, 0xe4, 0x0e, 0xf4, 0x1a, 0xdd, 0xab, 0x3f,
    0xbc, 0x63, 0x79, 0x5b, 0x39, 0x69, 0x5e, 0xea, 0xa9, 0x15, 0xfe, 0x90,
    0xec, 0xda, 0x75, 0x02, 0x81, 0x81, 0x00, 0x99, 0xe2, 0x33, 0xd5, 0xc1,
    0x0b, 0x5e, 0xec, 0xa9, 0x20, 0x93, 0xd9, 0x75, 0xd0, 0x5d, 0xdc, 0xb8,
    0x80, 0xdc, 0xf0, 0xcb, 0x3e, 0x89, 0x04, 0x45, 0x32, 0x24, 0xb8, 0x83,
    0x57, 0xe1, 0xcd, 0x9b, 0xc7, 0x7e, 0x98, 0xb9, 0xab, 0x5f, 0xee, 0x35,
    0xf8, 0x10, 0x76, 0x9d, 0xd2, 0xf6, 0x9b, 0xab, 0x10, 0xaf, 0x43, 0x17,
    0xfe, 0xd8, 0x58, 0x31, 0x73, 0x69, 0x5a, 0x54, 0xc1, 0xa0, 0x48, 0xdf,
    0xe3, 0x0c, 0xb2, 0x5d, 0x11, 0x34, 0x14, 0x72, 0x88, 0xdd, 0xe1, 0xe2,
    0x0a, 0xda, 0x3d, 0x5b, 0xbf, 0x9e, 0x57, 0x2a, 0xb0, 0x4e, 0x97, 0x7e,
    0x57, 0xd6, 0xbb, 0x8a, 0xc6, 0x9d, 0x6a, 0x58, 0x1b, 0xdd, 0xf6, 0x39,
    0xf4, 0x7e, 0x38, 0x3e, 0x99, 0x66, 0x94, 0xb3, 0x68, 0x6d, 0xd2, 0x07,
    0x54, 0x58, 0x2d, 0x70, 0xbe, 0xa6, 0x3d, 0xab, 0x0e, 0xe7, 0x6d, 0xcd,
    0xfa, 0x01, 0x67, 0x02, 0x81, 0x80, 0x6c, 0xdb, 0x4b, 0xbd, 0x90, 0x81,
    0x94, 0xd0, 0xa7, 0xe5, 0x61, 0x7b, 0xf6, 0x5e, 0xf7, 0xc1, 0x34, 0xfa,
    0xb7, 0x40, 0x9e, 0x1c, 0x7d, 0x4a, 0x72, 0xc2, 0x77, 0x2a, 0x8e, 0xb3,
    0x46, 0x49, 0x69, 0xc7, 0xf1, 0x7f, 0x9a, 0xcf, 0x1a, 0x15, 0x43, 0xc7,
    0xeb, 0x04, 0x6e, 0x4e, 0xcc, 0x65, 0xe8, 0xf9, 0x23, 0x72, 0x7d, 0xdd,
    0x06, 0xac, 0xaa, 0xfd, 0x74, 0x87, 0x50, 0x7d, 0x66, 0x98, 0x97, 0xc2,
    0x21, 0x28, 0xbe, 0x15, 0x72, 0x06, 0x73, 0x9f, 0x88, 0x9e, 0x30, 0x8d,
    0xea, 0x5a, 0xa6, 0xa0, 0x2f, 0x26, 0x59, 0x88, 0x32, 0x4b, 0xef, 0x85,
    0xa5, 0xe8, 0x9e, 0x85, 0x01, 0x56, 0xd8, 0x8d, 0x19, 0xcc, 0xb5, 0x94,
    0xec, 0x56, 0xa8, 0x7b, 0x42, 0xb4, 0xa2, 0xbc, 0x93, 0xc7, 0x7f, 0xd2,
    0xec, 0xfb, 0x92, 0x26, 0x46, 0x3f, 0x47, 0x1b, 0x63, 0xff, 0x0b, 0x48,
    0x91, 0xa3, 0x02, 0x81, 0x80, 0x2c, 0x4a, 0xb9, 0xa4, 0x46, 0x7b, 0xff,
    0x50, 0x7e, 0xbf, 0x60, 0x47, 0x3b, 0x2b, 0x66, 0x82, 0xdc, 0x0e, 0x53,
    0x65, 0x71, 0xe9, 0xda, 0x2a, 0xb8, 0x32, 0x93, 0x42, 0xb7, 0xff, 0xea,
    0x67, 0x66, 0xf1, 0xbc, 0x87, 0x28, 0x65, 0x29, 0x79, 0xca, 0xab, 0x93,
    0x56, 0xda, 0x95, 0xc1, 0x26, 0x44, 0x3d, 0x27, 0xc1, 0x91, 0xc6, 0x9b,
    0xd9, 0xec, 0x9d, 0xb7, 0x49, 0xe7, 0x16, 0xee, 0x99, 0x87, 0x50, 0x95,
    0x81, 0xd4, 0x5c, 0x5b, 0x5a, 0x5d, 0x0a, 0x43, 0xa5, 0xa7, 0x8f, 0x5a,
    0x80, 0x49, 0xa0, 0xb7, 0x10, 0x85, 0xc7, 0xf4, 0x42, 0x34, 0x86, 0xb6,
    0x5f, 0x3f, 0x88, 0x9e, 0xc7, 0xf5, 0x59, 0x29, 0x39, 0x68, 0x48, 0xf2,
    0xd7, 0x08, 0x5b, 0x92, 0x8e, 0x6b, 0xea, 0xa5, 0x63, 0x5f, 0xc0, 0xfb,
    0xe4, 0xe1, 0xb2, 0x7d, 0xb7, 0x40, 0xe9, 0x55, 0x06, 0xbf, 0x58, 0x25,
    0x6f};

// kPKCS1Ciphertext2 is "hello world" encrypted with kKey2 and RSAES-PKCS1-v1_5.
static const uint8_t kPKCS1Ciphertext2[] = {
    0x63, 0x0a, 0x30, 0x45, 0x43, 0x11, 0x45, 0xb7, 0x99, 0x67, 0x90, 0x35,
    0x37, 0x27, 0xff, 0xbc, 0xe0, 0xbf, 0xa6, 0xd1, 0x47, 0x50, 0xbb, 0x6c,
    0x1c, 0xaa, 0x66, 0xf2, 0xff, 0x9d, 0x9a, 0xa6, 0xb4, 0x16, 0x63, 0xb0,
    0xa1, 0x7c, 0x7c, 0x0c, 0xef, 0xb3, 0x66, 0x52, 0x42, 0xd7, 0x5e, 0xf3,
    0xa4, 0x15, 0x33, 0x40, 0x43, 0xe8, 0xb1, 0xfc, 0xe0, 0x42, 0x83, 0x46,
    0x28, 0xce, 0xde, 0x7b, 0x01, 0xeb, 0x28, 0x92, 0x70, 0xdf, 0x8d, 0x54,
    0x9e, 0xed, 0x23, 0xb4, 0x78, 0xc3, 0xca, 0x85, 0x53, 0x48, 0xd6, 0x8a,
    0x87, 0xf7, 0x69, 0xcd, 0x82, 0x8c, 0x4f, 0x5c, 0x05, 0x55, 0xa6, 0x78,
    0x89, 0xab, 0x4c, 0xd8, 0xa9, 0xd6, 0xa5, 0xf4, 0x29, 0x4c, 0x23, 0xc8,
    0xcf, 0xf0, 0x4c, 0x64, 0x6b, 0x4e, 0x02, 0x17, 0x69, 0xd6, 0x47, 0x83,
    0x30, 0x43, 0x02, 0x29, 0xda, 0xda, 0x75, 0x3b, 0xd7, 0xa7, 0x2b, 0x31,
    0xb3, 0xe9, 0x71, 0xa4, 0x41, 0xf7, 0x26, 0x9b, 0xcd, 0x23, 0xfa, 0x45,
    0x3c, 0x9b, 0x7d, 0x28, 0xf7, 0xf9, 0x67, 0x04, 0xba, 0xfc, 0x46, 0x75,
    0x11, 0x3c, 0xd5, 0x27, 0x43, 0x53, 0xb1, 0xb6, 0x9e, 0x18, 0xeb, 0x11,
    0xb4, 0x25, 0x20, 0x30, 0x0b, 0xe0, 0x1c, 0x17, 0x36, 0x22, 0x10, 0x0f,
    0x99, 0xb5, 0x50, 0x14, 0x73, 0x07, 0xf0, 0x2f, 0x5d, 0x4c, 0xe3, 0xf2,
    0x86, 0xc2, 0x05, 0xc8, 0x38, 0xed, 0xeb, 0x2a, 0x4a, 0xab, 0x76, 0xe3,
    0x1a, 0x75, 0x44, 0xf7, 0x6e, 0x94, 0xdc, 0x25, 0x62, 0x7e, 0x31, 0xca,
    0xc2, 0x73, 0x51, 0xb5, 0x03, 0xfb, 0xf9, 0xf6, 0xb5, 0x8d, 0x4e, 0x6c,
    0x21, 0x0e, 0xf9, 0x97, 0x26, 0x57, 0xf3, 0x52, 0x72, 0x07, 0xf8, 0xb4,
    0xcd, 0xb4, 0x39, 0xcf, 0xbf, 0x78, 0xcc, 0xb6, 0x87, 0xf9, 0xb7, 0x8b,
    0x6a, 0xce, 0x9f, 0xc8};

// kOAEPCiphertext2 is a sample encryption of |kPlaintext| with |kKey2| using
// RSA OAEP, SHA-1, and no label. It was generated with:
//
// clang-format off
// openssl pkeyutl -encrypt -inkey key2.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -in plaintext | xxd -i
// clang-format on
static const uint8_t kOAEPCiphertext2[] = {
    0x56, 0x10, 0x50, 0x5b, 0x9a, 0xa8, 0x2e, 0x3f, 0x24, 0x06, 0x5b, 0xd3,
    0x06, 0x03, 0xde, 0x18, 0x69, 0xb2, 0x1b, 0xec, 0x12, 0x14, 0x76, 0xb9,
    0x8c, 0x7b, 0xf8, 0x4a, 0xaf, 0x87, 0xa8, 0x83, 0x49, 0x1c, 0x5e, 0xb4,
    0xe5, 0x9f, 0xff, 0x00, 0xf2, 0xdd, 0x34, 0xf0, 0x10, 0x9f, 0xca, 0xc6,
    0x02, 0x54, 0x23, 0xb2, 0xc3, 0xdc, 0x74, 0xa8, 0x9f, 0xd2, 0xdc, 0x87,
    0x48, 0x2f, 0x02, 0x8b, 0xf1, 0x7a, 0x91, 0x8d, 0x2d, 0x77, 0x7f, 0x6f,
    0x8f, 0x19, 0xde, 0x90, 0x54, 0x0d, 0x1b, 0x7b, 0x96, 0x81, 0x84, 0xf9,
    0x03, 0x48, 0xef, 0xab, 0xe5, 0x07, 0xcd, 0x7f, 0x01, 0xeb, 0x86, 0x8d,
    0x7e, 0x7e, 0xf8, 0x2a, 0x50, 0x02, 0xcd, 0xcb, 0xa5, 0xfe, 0xc2, 0x35,
    0x1f, 0x82, 0xef, 0xb9, 0x1d, 0x98, 0xd5, 0x07, 0x94, 0x37, 0x08, 0x13,
    0x1c, 0xc8, 0x19, 0x06, 0x13, 0x2d, 0x1c, 0xb2, 0x50, 0x34, 0xad, 0x99,
    0x3c, 0xe6, 0xce, 0x4c, 0x88, 0x6d, 0x96, 0xc8, 0x85, 0xd1, 0x5e, 0xd5,
    0x77, 0x02, 0x0a, 0xa9, 0x2a, 0xf1, 0xa3, 0x4a, 0x04, 0x65, 0x87, 0x05,
    0x6b, 0x34, 0x65, 0x1c, 0xef, 0x64, 0x11, 0xee, 0x23, 0x7e, 0x36, 0x4f,
    0x4c, 0x5d, 0xb7, 0xd6, 0x79, 0x30, 0xec, 0xdf, 0xde, 0x35, 0x32, 0xd0,
    0xb0, 0x7e, 0x26, 0x1f, 0xea, 0xa2, 0x78, 0x98, 0x4b, 0x77, 0x9b, 0x03,
    0x75, 0x33, 0x08, 0x72, 0x91, 0x0b, 0x77, 0xc0, 0x6e, 0xe1, 0x0f, 0x14,
    0xf1, 0xf0, 0xb9, 0xe5, 0x5f, 0x08, 0xc2, 0x92, 0x79, 0x2e, 0x6f, 0xef,
    0x2a, 0x1b, 0x31, 0x64, 0x36, 0x67, 0xf8, 0x1d, 0xc8, 0xb7, 0xc3, 0x15,
    0x6c, 0xd8, 0x35, 0x34, 0x44, 0xb2, 0x91, 0xf2, 0x07, 0x86, 0xd6, 0xfa,
    0x42, 0x04, 0xae, 0xc5, 0x17, 0x14, 0x61, 0x6f, 0x12, 0x84, 0xb9, 0x99,
    0x47, 0xd1, 0xdc, 0x3c};

// kKey3 is a DER-encoded RSAPrivateKey. It is a 1024-bit RSA private key with
// exponent 17.
static const uint8_t kKey3[] = {
    0x30, 0x82, 0x02, 0x5b, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xbb,
    0xf8, 0x2f, 0x09, 0x06, 0x82, 0xce, 0x9c, 0x23, 0x38, 0xac, 0x2b, 0x9d,
    0xa8, 0x71, 0xf7, 0x36, 0x8d, 0x07, 0xee, 0xd4, 0x10, 0x43, 0xa4, 0x40,
    0xd6, 0xb6, 0xf0, 0x74, 0x54, 0xf5, 0x1f, 0xb8, 0xdf, 0xba, 0xaf, 0x03,
    0x5c, 0x02, 0xab, 0x61, 0xea, 0x48, 0xce, 0xeb, 0x6f, 0xcd, 0x48, 0x76,
    0xed, 0x52, 0x0d, 0x60, 0xe1, 0xec, 0x46, 0x19, 0x71, 0x9d, 0x8a, 0x5b,
    0x8b, 0x80, 0x7f, 0xaf, 0xb8, 0xe0, 0xa3, 0xdf, 0xc7, 0x37, 0x72, 0x3e,
    0xe6, 0xb4, 0xb7, 0xd9, 0x3a, 0x25, 0x84, 0xee, 0x6a, 0x64, 0x9d, 0x06,
    0x09, 0x53, 0x74, 0x88, 0x34, 0xb2, 0x45, 0x45, 0x98, 0x39, 0x4e, 0xe0,
    0xaa, 0xb1, 0x2d, 0x7b, 0x61, 0xa5, 0x1f, 0x52, 0x7a, 0x9a, 0x41, 0xf6,
    0xc1, 0x68, 0x7f, 0xe2, 0x53, 0x72, 0x98, 0xca, 0x2a, 0x8f, 0x59, 0x46,
    0xf8, 0xe5, 0xfd, 0x09, 0x1d, 0xbd, 0xcb, 0x02, 0x01, 0x11, 0x02, 0x81,
    0x81, 0x00, 0xa5, 0xda, 0xfc, 0x53, 0x41, 0xfa, 0xf2, 0x89, 0xc4, 0xb9,
    0x88, 0xdb, 0x30, 0xc1, 0xcd, 0xf8, 0x3f, 0x31, 0x25, 0x1e, 0x06, 0x68,
    0xb4, 0x27, 0x84, 0x81, 0x38, 0x01, 0x57, 0x96, 0x41, 0xb2, 0x94, 0x10,
    0xb3, 0xc7, 0x99, 0x8d, 0x6b, 0xc4, 0x65, 0x74, 0x5e, 0x5c, 0x39, 0x26,
    0x69, 0xd6, 0x87, 0x0d, 0xa2, 0xc0, 0x82, 0xa9, 0x39, 0xe3, 0x7f, 0xdc,
    0xb8, 0x2e, 0xc9, 0x3e, 0xda, 0xc9, 0x7f, 0xf3, 0xad, 0x59, 0x50, 0xac,
    0xcf, 0xbc, 0x11, 0x1c, 0x76, 0xf1, 0xa9, 0x52, 0x94, 0x44, 0xe5, 0x6a,
    0xaf, 0x68, 0xc5, 0x6c, 0x09, 0x2c, 0xd3, 0x8d, 0xc3, 0xbe, 0xf5, 0xd2,
    0x0a, 0x93, 0x99, 0x26, 0xed, 0x4f, 0x74, 0xa1, 0x3e, 0xdd, 0xfb, 0xe1,
    0xa1, 0xce, 0xcc, 0x48, 0x94, 0xaf, 0x94, 0x28, 0xc2, 0xb7, 0xb8, 0x88,
    0x3f, 0xe4, 0x46, 0x3a, 0x4b, 0xc8, 0x5b, 0x1c, 0xb3, 0xc1, 0x02, 0x41,
    0x00, 0xee, 0xcf, 0xae, 0x81, 0xb1, 0xb9, 0xb3, 0xc9, 0x08, 0x81, 0x0b,
    0x10, 0xa1, 0xb5, 0x60, 0x01, 0x99, 0xeb, 0x9f, 0x44, 0xae, 0xf4, 0xfd,
    0xa4, 0x93, 0xb8, 0x1a, 0x9e, 0x3d, 0x84, 0xf6, 0x32, 0x12, 0x4e, 0xf0,
    0x23, 0x6e, 0x5d, 0x1e, 0x3b, 0x7e, 0x28, 0xfa, 0xe7, 0xaa, 0x04, 0x0a,
    0x2d, 0x5b, 0x25, 0x21, 0x76, 0x45, 0x9d, 0x1f, 0x39, 0x75, 0x41, 0xba,
    0x2a, 0x58, 0xfb, 0x65, 0x99, 0x02, 0x41, 0x00, 0xc9, 0x7f, 0xb1, 0xf0,
    0x27, 0xf4, 0x53, 0xf6, 0x34, 0x12, 0x33, 0xea, 0xaa, 0xd1, 0xd9, 0x35,
    0x3f, 0x6c, 0x42, 0xd0, 0x88, 0x66, 0xb1, 0xd0, 0x5a, 0x0f, 0x20, 0x35,
    0x02, 0x8b, 0x9d, 0x86, 0x98, 0x40, 0xb4, 0x16, 0x66, 0xb4, 0x2e, 0x92,
    0xea, 0x0d, 0xa3, 0xb4, 0x32, 0x04, 0xb5, 0xcf, 0xce, 0x33, 0x52, 0x52,
    0x4d, 0x04, 0x16, 0xa5, 0xa4, 0x41, 0xe7, 0x00, 0xaf, 0x46, 0x15, 0x03,
    0x02, 0x40, 0x54, 0x49, 0x4c, 0xa6, 0x3e, 0xba, 0x03, 0x37, 0xe4, 0xe2,
    0x40, 0x23, 0xfc, 0xd6, 0x9a, 0x5a, 0xeb, 0x07, 0xdd, 0xdc, 0x01, 0x83,
    0xa4, 0xd0, 0xac, 0x9b, 0x54, 0xb0, 0x51, 0xf2, 0xb1, 0x3e, 0xd9, 0x49,
    0x09, 0x75, 0xea, 0xb7, 0x74, 0x14, 0xff, 0x59, 0xc1, 0xf7, 0x69, 0x2e,
    0x9a, 0x2e, 0x20, 0x2b, 0x38, 0xfc, 0x91, 0x0a, 0x47, 0x41, 0x74, 0xad,
    0xc9, 0x3c, 0x1f, 0x67, 0xc9, 0x81, 0x02, 0x40, 0x47, 0x1e, 0x02, 0x90,
    0xff, 0x0a, 0xf0, 0x75, 0x03, 0x51, 0xb7, 0xf8, 0x78, 0x86, 0x4c, 0xa9,
    0x61, 0xad, 0xbd, 0x3a, 0x8a, 0x7e, 0x99, 0x1c, 0x5c, 0x05, 0x56, 0xa9,
    0x4c, 0x31, 0x46, 0xa7, 0xf9, 0x80, 0x3f, 0x8f, 0x6f, 0x8a, 0xe3, 0x42,
    0xe9, 0x31, 0xfd, 0x8a, 0xe4, 0x7a, 0x22, 0x0d, 0x1b, 0x99, 0xa4, 0x95,
    0x84, 0x98, 0x07, 0xfe, 0x39, 0xf9, 0x24, 0x5a, 0x98, 0x36, 0xda, 0x3d,
    0x02, 0x41, 0x00, 0xb0, 0x6c, 0x4f, 0xda, 0xbb, 0x63, 0x01, 0x19, 0x8d,
    0x26, 0x5b, 0xdb, 0xae, 0x94, 0x23, 0xb3, 0x80, 0xf2, 0x71, 0xf7, 0x34,
    0x53, 0x88, 0x50, 0x93, 0x07, 0x7f, 0xcd, 0x39, 0xe2, 0x11, 0x9f, 0xc9,
    0x86, 0x32, 0x15, 0x4f, 0x58, 0x83, 0xb1, 0x67, 0xa9, 0x67, 0xbf, 0x40,
    0x2b, 0x4e, 0x9e, 0x2e, 0x0f, 0x96, 0x56, 0xe6, 0x98, 0xea, 0x36, 0x66,
    0xed, 0xfb, 0x25, 0x79, 0x80, 0x39, 0xf7};

// kOAEPCiphertext3 is a sample encryption of |kPlaintext| with |kKey3| using
// RSA OAEP, SHA-1, and no label.
static const uint8_t kOAEPCiphertext3[] = {
    0xb8, 0x24, 0x6b, 0x56, 0xa6, 0xed, 0x58, 0x81, 0xae, 0xb5, 0x85, 0xd9,
    0xa2, 0x5b, 0x2a, 0xd7, 0x90, 0xc4, 0x17, 0xe0, 0x80, 0x68, 0x1b, 0xf1,
    0xac, 0x2b, 0xc3, 0xde, 0xb6, 0x9d, 0x8b, 0xce, 0xf0, 0xc4, 0x36, 0x6f,
    0xec, 0x40, 0x0a, 0xf0, 0x52, 0xa7, 0x2e, 0x9b, 0x0e, 0xff, 0xb5, 0xb3,
    0xf2, 0xf1, 0x92, 0xdb, 0xea, 0xca, 0x03, 0xc1, 0x27, 0x40, 0x05, 0x71,
    0x13, 0xbf, 0x1f, 0x06, 0x69, 0xac, 0x22, 0xe9, 0xf3, 0xa7, 0x85, 0x2e,
    0x3c, 0x15, 0xd9, 0x13, 0xca, 0xb0, 0xb8, 0x86, 0x3a, 0x95, 0xc9, 0x92,
    0x94, 0xce, 0x86, 0x74, 0x21, 0x49, 0x54, 0x61, 0x03, 0x46, 0xf4, 0xd4,
    0x74, 0xb2, 0x6f, 0x7c, 0x48, 0xb4, 0x2e, 0xe6, 0x8e, 0x1f, 0x57, 0x2a,
    0x1f, 0xc4, 0x02, 0x6a, 0xc4, 0x56, 0xb4, 0xf5, 0x9f, 0x7b, 0x62, 0x1e,
    0xa1, 0xb9, 0xd8, 0x8f, 0x64, 0x20, 0x2f, 0xb1};

// kEstonianRSAKey is an RSAPublicKey encoded with a negative modulus. See
// https://crbug.com/532048.
static const uint8_t kEstonianRSAKey[] = {
    0x30, 0x82, 0x01, 0x09, 0x02, 0x82, 0x01, 0x00, 0x96, 0xa6, 0x2e, 0x9c,
    0x4e, 0x6a, 0xc3, 0xcc, 0xcd, 0x8f, 0x70, 0xc3, 0x55, 0xbf, 0x5e, 0x9c,
    0xd4, 0xf3, 0x17, 0xc3, 0x97, 0x70, 0xae, 0xdf, 0x12, 0x5c, 0x15, 0x80,
    0x03, 0xef, 0x2b, 0x18, 0x9d, 0x6a, 0xcb, 0x52, 0x22, 0xc1, 0x81, 0xb8,
    0x7e, 0x61, 0xe8, 0x0f, 0x79, 0x24, 0x0f, 0x82, 0x70, 0x24, 0x4e, 0x29,
    0x20, 0x05, 0x54, 0xeb, 0xd4, 0xa9, 0x65, 0x59, 0xb6, 0x3c, 0x75, 0x95,
    0x2f, 0x4c, 0xf6, 0x9d, 0xd1, 0xaf, 0x5f, 0x14, 0x14, 0xe7, 0x25, 0xea,
    0xa5, 0x47, 0x5d, 0xc6, 0x3e, 0x28, 0x8d, 0xdc, 0x54, 0x87, 0x2a, 0x7c,
    0x10, 0xe9, 0xc6, 0x76, 0x2d, 0xe7, 0x79, 0xd8, 0x0e, 0xbb, 0xa9, 0xac,
    0xb5, 0x18, 0x98, 0xd6, 0x47, 0x6e, 0x06, 0x70, 0xbf, 0x9e, 0x82, 0x25,
    0x95, 0x4e, 0xfd, 0x70, 0xd7, 0x73, 0x45, 0x2e, 0xc1, 0x1f, 0x7a, 0x9a,
    0x9d, 0x60, 0xc0, 0x1f, 0x67, 0x06, 0x2a, 0x4e, 0x87, 0x3f, 0x19, 0x88,
    0x69, 0x64, 0x4d, 0x9f, 0x75, 0xf5, 0xd3, 0x1a, 0x41, 0x3d, 0x35, 0x17,
    0xb6, 0xd1, 0x44, 0x0d, 0x25, 0x8b, 0xe7, 0x94, 0x39, 0xb0, 0x7c, 0xaf,
    0x3e, 0x6a, 0xfa, 0x8d, 0x90, 0x21, 0x0f, 0x8a, 0x43, 0x94, 0x37, 0x7c,
    0x2a, 0x15, 0x4c, 0xa0, 0xfa, 0xa9, 0x2f, 0x21, 0xa6, 0x6f, 0x8e, 0x2f,
    0x89, 0xbc, 0xbb, 0x33, 0xf8, 0x31, 0xfc, 0xdf, 0xcd, 0x68, 0x9a, 0xbc,
    0x75, 0x06, 0x95, 0xf1, 0x3d, 0xef, 0xca, 0x76, 0x27, 0xd2, 0xba, 0x8e,
    0x0e, 0x1c, 0x43, 0xd7, 0x70, 0xb9, 0xc6, 0x15, 0xca, 0xd5, 0x4d, 0x87,
    0xb9, 0xd1, 0xae, 0xde, 0x69, 0x73, 0x00, 0x2a, 0x97, 0x51, 0x4b, 0x30,
    0x01, 0xc2, 0x85, 0xd0, 0x05, 0xcc, 0x2e, 0xe8, 0xc7, 0x42, 0xe7, 0x94,
    0x51, 0xe3, 0xf5, 0x19, 0x35, 0xdc, 0x57, 0x96, 0xe7, 0xd9, 0xb4, 0x49,
    0x02, 0x03, 0x01, 0x00, 0x01,
};

// kExponent1RSAKey is an RSAPublicKey encoded with an exponent of 1. See
// https://crbug.com/541257
static const uint8_t kExponent1RSAKey[] = {
    0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xcf, 0x86, 0x9a,
    0x7d, 0x5c, 0x9f, 0xbd, 0x33, 0xbb, 0xc2, 0xb1, 0x06, 0xa8, 0x3e, 0xc5,
    0x18, 0xf3, 0x01, 0x04, 0xdd, 0x7a, 0x38, 0x0e, 0x8e, 0x8d, 0x10, 0xaa,
    0xf8, 0x64, 0x49, 0x82, 0xa6, 0x16, 0x9d, 0xd9, 0xae, 0x5e, 0x7f, 0x9b,
    0x53, 0xcb, 0xbb, 0x29, 0xda, 0x98, 0x47, 0x26, 0x88, 0x2e, 0x1d, 0x64,
    0xb3, 0xbc, 0x7e, 0x96, 0x3a, 0xa7, 0xd6, 0x87, 0xf6, 0xf5, 0x3f, 0xa7,
    0x3b, 0xd3, 0xc5, 0xd5, 0x61, 0x3c, 0x63, 0x05, 0xf9, 0xbc, 0x64, 0x1d,
    0x71, 0x65, 0xf5, 0xc8, 0xe8, 0x64, 0x41, 0x35, 0x88, 0x81, 0x6b, 0x2a,
    0x24, 0xbb, 0xdd, 0x9f, 0x75, 0x4f, 0xea, 0x35, 0xe5, 0x32, 0x76, 0x5a,
    0x8b, 0x7a, 0xb5, 0x92, 0x65, 0x34, 0xb7, 0x88, 0x42, 0x5d, 0x41, 0x0b,
    0xd1, 0x00, 0x2d, 0x43, 0x47, 0x55, 0x60, 0x3c, 0x0e, 0x60, 0x04, 0x5c,
    0x88, 0x13, 0xc7, 0x42, 0x55, 0x16, 0x31, 0x32, 0x81, 0xba, 0xde, 0xa9,
    0x56, 0xeb, 0xdb, 0x66, 0x7f, 0x31, 0xba, 0xe8, 0x87, 0x1a, 0xcc, 0xad,
    0x90, 0x86, 0x4b, 0xa7, 0x6d, 0xd5, 0xc1, 0xb7, 0xe7, 0x67, 0x56, 0x41,
    0xf7, 0x03, 0xb3, 0x09, 0x61, 0x63, 0xb5, 0xb0, 0x19, 0x7b, 0xc5, 0x91,
    0xc8, 0x96, 0x5b, 0x6a, 0x80, 0xa1, 0x53, 0x0f, 0x9a, 0x47, 0xb5, 0x9a,
    0x44, 0x53, 0xbd, 0x93, 0xe3, 0xe4, 0xce, 0x0c, 0x17, 0x11, 0x51, 0x1d,
    0xfd, 0x6c, 0x74, 0xe4, 0xec, 0x2a, 0xce, 0x57, 0x27, 0xcc, 0x83, 0x98,
    0x08, 0x32, 0x2c, 0xd5, 0x75, 0xa9, 0x27, 0xfe, 0xaa, 0x5e, 0x48, 0xc9,
    0x46, 0x9a, 0x29, 0x3f, 0xe6, 0x01, 0x4d, 0x97, 0x4a, 0x70, 0xd1, 0x5d,
    0xf8, 0xc0, 0x0b, 0x23, 0xcb, 0xbe, 0xf5, 0x70, 0x0b, 0xc2, 0xf2, 0xc0,
    0x33, 0x9c, 0xc4, 0x8b, 0x39, 0x7e, 0x3d, 0xc6, 0x23, 0x39, 0x9a, 0x98,
    0xdd, 0x02, 0x01, 0x01,
};

struct RSAEncryptParam {
  bssl::Span<const uint8_t> der;
  bssl::Span<const uint8_t> oaep_ciphertext;
} kRSAEncryptParams[] = {
    {kKey1, kOAEPCiphertext1},
    {kKey2, kOAEPCiphertext2},
    {kKey3, kOAEPCiphertext3},
};

class RSAEncryptTest : public testing::TestWithParam<RSAEncryptParam> {};

TEST_P(RSAEncryptTest, TestKey) {
  // Construct an RSA key in different ways.
  const auto &param = GetParam();
  bssl::UniquePtr<RSA> parsed(
      RSA_private_key_from_bytes(param.der.data(), param.der.size()));
  ASSERT_TRUE(parsed);
  EXPECT_TRUE(RSA_get0_e(parsed.get()));
  EXPECT_TRUE(RSA_get0_d(parsed.get()));

  bssl::UniquePtr<RSA> constructed(RSA_new_private_key(
      RSA_get0_n(parsed.get()), RSA_get0_e(parsed.get()),
      RSA_get0_d(parsed.get()), RSA_get0_p(parsed.get()),
      RSA_get0_q(parsed.get()), RSA_get0_dmp1(parsed.get()),
      RSA_get0_dmq1(parsed.get()), RSA_get0_iqmp(parsed.get())));
  ASSERT_TRUE(constructed);
  EXPECT_TRUE(RSA_get0_e(constructed.get()));
  EXPECT_TRUE(RSA_get0_d(constructed.get()));

  bssl::UniquePtr<RSA> no_crt(RSA_new_private_key_no_crt(
      RSA_get0_n(parsed.get()), RSA_get0_e(parsed.get()),
      RSA_get0_d(parsed.get())));
  ASSERT_TRUE(no_crt);
  EXPECT_TRUE(RSA_get0_e(no_crt.get()));
  EXPECT_TRUE(RSA_get0_d(no_crt.get()));

  bssl::UniquePtr<RSA> no_e(RSA_new_private_key_no_e(RSA_get0_n(parsed.get()),
                                                     RSA_get0_d(parsed.get())));
  ASSERT_TRUE(no_e);
  EXPECT_FALSE(RSA_get0_e(no_e.get()));
  EXPECT_TRUE(RSA_get0_d(no_e.get()));

  bssl::UniquePtr<RSA> pub(
      RSA_new_public_key(RSA_get0_n(parsed.get()), RSA_get0_e(parsed.get())));
  ASSERT_TRUE(pub);
  EXPECT_TRUE(RSA_get0_e(pub.get()));
  EXPECT_FALSE(RSA_get0_d(pub.get()));

  for (RSA *key :
       {parsed.get(), constructed.get(), no_crt.get(), no_e.get(), pub.get()}) {
    EXPECT_TRUE(RSA_check_key(key));

    std::vector<uint8_t> ciphertext(RSA_size(key)), plaintext(RSA_size(key));
    size_t ciphertext_len = 0, plaintext_len = 0;

    if (RSA_get0_e(key) != nullptr) {
      // Test that PKCS#1 v1.5 encryption round-trips.
      ASSERT_TRUE(RSA_encrypt(key, &ciphertext_len, ciphertext.data(),
                              ciphertext.size(), kPlaintext, sizeof(kPlaintext),
                              RSA_PKCS1_PADDING));
      EXPECT_EQ(RSA_size(key), ciphertext_len);

      ASSERT_TRUE(RSA_decrypt(parsed.get(), &plaintext_len, plaintext.data(),
                              plaintext.size(), ciphertext.data(),
                              ciphertext_len, RSA_PKCS1_PADDING));
      EXPECT_EQ(Bytes(kPlaintext), Bytes(plaintext.data(), plaintext_len));

      // Test that OAEP encryption round-trips.
      ciphertext_len = 0;
      ASSERT_TRUE(RSA_encrypt(key, &ciphertext_len, ciphertext.data(),
                              ciphertext.size(), kPlaintext, sizeof(kPlaintext),
                              RSA_PKCS1_OAEP_PADDING));
      EXPECT_EQ(RSA_size(key), ciphertext_len);

      plaintext_len = 0;
      ASSERT_TRUE(RSA_decrypt(parsed.get(), &plaintext_len, plaintext.data(),
                              plaintext.size(), ciphertext.data(),
                              ciphertext_len, RSA_PKCS1_OAEP_PADDING));
      EXPECT_EQ(Bytes(kPlaintext), Bytes(plaintext.data(), plaintext_len));
    }

    if (RSA_get0_d(key) != nullptr) {
      // |oaep_ciphertext| should decrypt to |kPlaintext|.
      plaintext_len = 0;
      ASSERT_TRUE(RSA_decrypt(key, &plaintext_len, plaintext.data(),
                              plaintext.size(), param.oaep_ciphertext.data(),
                              param.oaep_ciphertext.size(),
                              RSA_PKCS1_OAEP_PADDING));
      EXPECT_EQ(Bytes(kPlaintext), Bytes(plaintext.data(), plaintext_len));

      // Try decrypting corrupted ciphertexts.
      ciphertext.assign(
          param.oaep_ciphertext.data(),
          param.oaep_ciphertext.data() + param.oaep_ciphertext.size());
      for (size_t i = 0; i < ciphertext.size(); i++) {
        SCOPED_TRACE(i);
        ciphertext[i] ^= 1;
        EXPECT_FALSE(RSA_decrypt(key, &plaintext_len, plaintext.data(),
                                 plaintext.size(), ciphertext.data(),
                                 ciphertext.size(), RSA_PKCS1_OAEP_PADDING));
        ERR_clear_error();
        ciphertext[i] ^= 1;
      }

      // Test truncated ciphertexts.
      for (size_t len = 0; len < ciphertext.size(); len++) {
        SCOPED_TRACE(len);
        EXPECT_FALSE(RSA_decrypt(key, &plaintext_len, plaintext.data(),
                                 plaintext.size(), ciphertext.data(), len,
                                 RSA_PKCS1_OAEP_PADDING));
        ERR_clear_error();
      }
    }
  }
}

INSTANTIATE_TEST_SUITE_P(All, RSAEncryptTest,
                         testing::ValuesIn(kRSAEncryptParams));

TEST(RSATest, TestDecrypt) {
  bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(kKey2, sizeof(kKey2)));
  ASSERT_TRUE(rsa);

  EXPECT_TRUE(RSA_check_key(rsa.get()));

  std::vector<uint8_t> out(RSA_size(rsa.get()));
  size_t out_len;
  ASSERT_TRUE(RSA_decrypt(rsa.get(), &out_len, out.data(), out.size(),
                          kPKCS1Ciphertext2, sizeof(kPKCS1Ciphertext2),
                          RSA_PKCS1_PADDING));
  out.resize(out_len);
  EXPECT_EQ(Bytes("hello world"), Bytes(out));
}

TEST(RSATest, CheckFIPS) {
  bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(kKey1, sizeof(kKey1)));
  ASSERT_TRUE(rsa);
  EXPECT_TRUE(RSA_check_fips(rsa.get()));

  // Check that RSA_check_fips works on a public key.
  bssl::UniquePtr<RSA> pub(
      RSA_public_key_from_bytes(kKey1Public, sizeof(kKey1Public)));
  ASSERT_TRUE(pub);
  EXPECT_TRUE(RSA_check_fips(pub.get()));
}

TEST(RSATest, GenerateFIPS) {
  bssl::UniquePtr<RSA> rsa(RSA_new());
  ASSERT_TRUE(rsa);

  // RSA_generate_key_fips may only be used for 2048-, 3072-, and 4096-bit
  // keys.
  EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 512, nullptr));
  EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 1024, nullptr));
  EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 2047, nullptr));
  EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 2049, nullptr));
  EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 3071, nullptr));
  EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 3073, nullptr));
  EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 4095, nullptr));
  EXPECT_FALSE(RSA_generate_key_fips(rsa.get(), 4097, nullptr));
  ERR_clear_error();

  // Test that we can generate keys of the supported lengths:
  for (const size_t bits : {2048, 3072, 4096}) {
    SCOPED_TRACE(bits);

    rsa.reset(RSA_new());
    ASSERT_TRUE(rsa);
    ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), bits, nullptr));
    EXPECT_EQ(bits, BN_num_bits(rsa->n));
  }
}

TEST(RSATest, BadKey) {
  bssl::UniquePtr<RSA> key(RSA_new());
  bssl::UniquePtr<BIGNUM> e(BN_new());
  ASSERT_TRUE(key);
  ASSERT_TRUE(e);
  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));

  // Generate a bad key.
  ASSERT_TRUE(RSA_generate_key_ex(key.get(), 2048, e.get(), nullptr));
  ASSERT_TRUE(BN_add(key->p, key->p, BN_value_one()));

  // Bad keys are detected.
  EXPECT_FALSE(RSA_check_key(key.get()));
  EXPECT_FALSE(RSA_check_fips(key.get()));

  // Bad keys may not be parsed.
  uint8_t *der;
  size_t der_len;
  ASSERT_TRUE(RSA_private_key_to_bytes(&der, &der_len, key.get()));
  bssl::UniquePtr<uint8_t> delete_der(der);
  key.reset(RSA_private_key_from_bytes(der, der_len));
  EXPECT_FALSE(key);
}

TEST(RSATest, ASN1) {
  // Test that private keys may be decoded.
  bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(kKey1, sizeof(kKey1)));
  ASSERT_TRUE(rsa);

  // Test that the serialization round-trips.
  uint8_t *der;
  size_t der_len;
  ASSERT_TRUE(RSA_private_key_to_bytes(&der, &der_len, rsa.get()));
  bssl::UniquePtr<uint8_t> delete_der(der);
  EXPECT_EQ(Bytes(kKey1), Bytes(der, der_len));

  // Test that serializing public keys works.
  ASSERT_TRUE(RSA_public_key_to_bytes(&der, &der_len, rsa.get()));
  delete_der.reset(der);

  // Public keys may be parsed back out.
  rsa.reset(RSA_public_key_from_bytes(der, der_len));
  ASSERT_TRUE(rsa);
  EXPECT_FALSE(rsa->p);
  EXPECT_FALSE(rsa->q);

  // Serializing the result round-trips.
  uint8_t *der2;
  size_t der2_len;
  ASSERT_TRUE(RSA_public_key_to_bytes(&der2, &der2_len, rsa.get()));
  bssl::UniquePtr<uint8_t> delete_der2(der2);
  EXPECT_EQ(Bytes(der, der_len), Bytes(der2, der2_len));

  // Public keys cannot be serialized as private keys.
  int ok = RSA_private_key_to_bytes(&der, &der_len, rsa.get());
  if (ok) {
    OPENSSL_free(der);
  }
  EXPECT_FALSE(ok);
  ERR_clear_error();

  // Public keys with negative moduli are invalid.
  rsa.reset(RSA_public_key_from_bytes(kEstonianRSAKey,
                                      sizeof(kEstonianRSAKey)));
  EXPECT_FALSE(rsa);
  ERR_clear_error();
}

TEST(RSATest, BadExponent) {
  bssl::UniquePtr<RSA> rsa(
      RSA_public_key_from_bytes(kExponent1RSAKey, sizeof(kExponent1RSAKey)));
  EXPECT_FALSE(rsa);
  ERR_clear_error();
}

// Attempting to generate an excessively small key should fail.
TEST(RSATest, GenerateSmallKey) {
  bssl::UniquePtr<RSA> rsa(RSA_new());
  ASSERT_TRUE(rsa);
  bssl::UniquePtr<BIGNUM> e(BN_new());
  ASSERT_TRUE(e);
  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));

  EXPECT_FALSE(RSA_generate_key_ex(rsa.get(), 255, e.get(), nullptr));
  uint32_t err = ERR_get_error();
  EXPECT_EQ(ERR_LIB_RSA, ERR_GET_LIB(err));
  EXPECT_EQ(RSA_R_KEY_SIZE_TOO_SMALL, ERR_GET_REASON(err));
}

// Attempting to generate an funny RSA key length should round down.
TEST(RSATest, RoundKeyLengths) {
  bssl::UniquePtr<BIGNUM> e(BN_new());
  ASSERT_TRUE(e);
  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));

  bssl::UniquePtr<RSA> rsa(RSA_new());
  ASSERT_TRUE(rsa);
  ASSERT_TRUE(RSA_generate_key_ex(rsa.get(), 1025, e.get(), nullptr));
  EXPECT_EQ(1024u, BN_num_bits(rsa->n));

  rsa.reset(RSA_new());
  ASSERT_TRUE(rsa);
  ASSERT_TRUE(RSA_generate_key_ex(rsa.get(), 1027, e.get(), nullptr));
  EXPECT_EQ(1024u, BN_num_bits(rsa->n));

  rsa.reset(RSA_new());
  ASSERT_TRUE(rsa);
  ASSERT_TRUE(RSA_generate_key_ex(rsa.get(), 1151, e.get(), nullptr));
  EXPECT_EQ(1024u, BN_num_bits(rsa->n));

  rsa.reset(RSA_new());
  ASSERT_TRUE(rsa);
  ASSERT_TRUE(RSA_generate_key_ex(rsa.get(), 1152, e.get(), nullptr));
  EXPECT_EQ(1152u, BN_num_bits(rsa->n));
}

TEST(RSATest, BlindingDisabled) {
  bssl::UniquePtr<RSA> rsa(
      RSA_private_key_from_bytes(kKey2, sizeof(kKey2)));
  ASSERT_TRUE(rsa);

  rsa->flags |= RSA_FLAG_NO_BLINDING;

  std::vector<uint8_t> sig(RSA_size(rsa.get()));
  static const uint8_t kZeros[32] = {0};
  unsigned sig_len;
  ASSERT_TRUE(RSA_sign(NID_sha256, kZeros, sizeof(kZeros), sig.data(), &sig_len,
                       rsa.get()));
  EXPECT_TRUE(RSA_verify(NID_sha256, kZeros, sizeof(kZeros), sig.data(),
                         sig_len, rsa.get()));
}

TEST(RSATest, CheckKey) {
  static const char kN[] =
      "b5a5651bc2e15ce31d789f0984053a2ea0cf8f964a78068c45acfdf078c57fd62d5a287c"
      "32f3baa879f5dfea27d7a3077c9d3a2a728368c3d90164690c3d82f660ffebc7f13fed45"
      "4eb5103df943c10dc32ec60b0d9b6e307bfd7f9b943e0dc3901e42501765365f7286eff2"
      "f1f728774aa6a371e108a3a7dd00d7bcd4c1a186c2865d4b370ea38cc89c0b23b318dbca"
      "fbd872b4f9b833dfb2a4ca7fcc23298020044e8130bfe930adfb3e5cab8d324547adf4b2"
      "ce34d7cea4298f0b613d85f2bf1df03da44aee0784a1a20a15ee0c38a0f8e84962f1f61b"
      "18bd43781c7385f3c2b8e2aebd3c560b4faad208ad3938bad27ddda9ed9e933dba088021"
      "2dd9e28d";
  static const char kE[] = "10001";
  static const char kD[] =
      "fb9c6afd9568ce5ddac8e6a32bb881eb6cdd962bbc639dce5805548bf0fec2214f18ffd3"
      "6a50aa520cfe4477f9507d87355a24e3ff537f9f29ccffe5730b11896ebb9142982ed0df"
      "9c32ba98dddab863f3e5aa764d16ebff4500d3ee11de12fabd7aeca83c7ffa5d242b3ddc"
      "ecc64bcb5220996e79249a6d3f78975dfde769710569812dee59c0f56e4650d02a939d9c"
      "853e2cba9b0c2447a8757951ae9a0336dfa64c3d5476df9b20f200cfb52e3fbd2d4e3f34"
      "200b1171cbac367096f23366e74592025875efb6a7e3b1dd365abb0d86f34ee65ddbfa93"
      "90460da0d346833d6aa6277c0216b20073ba2f18471549c309e82d12e10714d0e0dbf146"
      "6fcd1f1";
  static const char kP[] =
      "edbe476fe8989f3966e72a20348ec6d8e924f44e1d9fa2c3485ea8a2ffd39f68574a5cef"
      "ffbb92d6764789ac0f67149127239c2027fbc55b5268a1dac6588de44e614f3bdce00f0a"
      "56d138800ad772d159a583c6548e37cadbfcf1b4ebfd50d01508986a516f36ed827b94ef"
      "1f9b4e233bf5762b3a903d2dfbbbce1fba30e9f1";
  static const char kQ[] =
      "c398518790a166dbe50498f04940d14c87ded09313fb0f69f69255c688142802ba3d4f9e"
      "f9425dadc462170635593c06a332cfc5fc9e6e1c05281950a5ce3bad4fd7cc83a38bd4ad"
      "6865594275af424f47c64c04af1caab2e261e95b975097c887d587dc8150df34cbeccd7d"
      "0688c392d9f1c617810043c9b93b884bf6ed465d";
  static const char kDMP1[] =
      "b44db5d1fa7e1d6ba44e36d59be6988a132f7294f7c484e543b27e84b82e9fdbbb2feb92"
      "1cc9fe0fe63e54fc07e66e63b3623f5ae7d7fb124a4a8e4de4556eaf327e7c5ff3207e67"
      "a1f624ba7efe6cd6b6fd5f160034a7bd92df9fd44d919d436260556f74793b181ff867b8"
      "7ea9033697978e5a349d05b9250c86c3eb2a8391";
  static const char kDMQ1[] =
      "7c06d9240265264927a6cba80a7b4c7c9fe77d10d669abb38083f85a24adcb55376d6b50"
      "9e34241cecdb5a483889f6132b672bf31aa607a242eed3669d4cf1f08b2186f0ae431bc0"
      "3de38e3f234ad7dc57e1f9103b4e0d3bd36b4cc324671968322207bd9e4e7ecb06c888e0"
      "cfc4e766f646665b3f14c0e7684ac4b98ec1948d";
  static const char kIQMP[] =
      "2887a5cb0c1bf6710e91c25da141dad92134a927431471c2d4a8b78036026d21182990e1"
      "2c1d70635f07ee551383899365a69b33d4db23e5ff7371ff4244d2c3290ce2b91ac11adc"
      "a54bb61ea5e64b9423102933ea100c12dad809fbf9589515e9d28e867f6b95c2d307f792"
      "cac28c6d7d23f441cb5b62798233db29b5cc0348";

  bssl::UniquePtr<RSA> rsa(RSA_new());
  ASSERT_TRUE(rsa);

  // Missing n or e does not pass.
  ASSERT_TRUE(BN_hex2bn(&rsa->n, kN));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();

  BN_free(rsa->n);
  rsa->n = nullptr;
  ASSERT_TRUE(BN_hex2bn(&rsa->e, kE));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();

  // Public keys pass.
  ASSERT_TRUE(BN_hex2bn(&rsa->n, kN));
  EXPECT_TRUE(RSA_check_key(rsa.get()));

  // Configuring d also passes.
  ASSERT_TRUE(BN_hex2bn(&rsa->d, kD));
  EXPECT_TRUE(RSA_check_key(rsa.get()));

  // p and q must be provided together.
  ASSERT_TRUE(BN_hex2bn(&rsa->p, kP));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();

  BN_free(rsa->p);
  rsa->p = nullptr;
  ASSERT_TRUE(BN_hex2bn(&rsa->q, kQ));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();

  // Supplying p and q without CRT parameters passes.
  ASSERT_TRUE(BN_hex2bn(&rsa->p, kP));
  EXPECT_TRUE(RSA_check_key(rsa.get()));

  // With p and q together, it is sufficient to check d against e.
  ASSERT_TRUE(BN_add_word(rsa->d, 1));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();

  // Test another invalid d. p-1 is divisible by 3, so there is no valid value
  // of d here if e = 111. Set d to what extended GCD would have given if it
  // forgot to check the inverse existed.
  static const char kDBogus[] =
      "140be923edb928cf4340a08ada19f23da680ff20275a81e033825ee8605afc3bf6039b87"
      "f0ddc7ea3b95f214a6fdda1064d0c66b50ac7bfe8cfe6c85d3cd217ae6f5094cd72a39e5"
      "a17a9ce43eae1ba5d7d8c3fb743d8cbcb3bcd74edd0b75fcca23a0b00bcea119864c0243"
      "bf9ab32b25a4d73a1e062482f538055bc2258369353647d4325aec7a28dc1a6798e85fae"
      "85850558868468d60015927cb10b2a893e23aa16b1f9278d4413f64d0a3122218f9000ae"
      "cd8743b8e9e50bd9de81eebc4e0230d1f4f7bffc1e6f903606afba9ee694c2b40022f171"
      "a760e7c63e736e31d7c7ff8b77dc206c2a3aa5afd540073060ebb9050bddce1ff1917630"
      "47fff51d";
  ASSERT_TRUE(BN_set_word(rsa->e, 111));
  ASSERT_TRUE(BN_hex2bn(&rsa->d, kDBogus));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  ASSERT_TRUE(BN_hex2bn(&rsa->e, kE));

  // d computed via the Euler totient rather than the Carmichael totient is also
  // acceptable.
  static const char kDEuler[] =
      "3d231ff6ca0ee41ea50ab62c93bcd6aa5f01bd484e643b7ff6eb94c4dd414c17a0481a1c"
      "4361f94f3f4d5c42098af09a527cf0d8dc96122ae8dd29189a4011d62f2bb40625d2e85f"
      "4d706fb90c2e9bc9b00a0c2a28384a4c134f6d25c62d64a08fdf3f5e89a14d3daee46fda"
      "8b4a2eda87cbb2735fd47290cb37bf65150edef854a28927ce5ac36d36107711cffb8ac3"
      "2b090e409bb822b117744a9aabf878b8b1998d406337ec24cee3877795061c67322ac626"
      "6c675a2cefe0f85f06b4d24eb6ad8e3fae7f218f5bd8ff2fb8bf8176d8527b0dfdaf8490"
      "8f9bfaf3f37dcf8aa0211311bac07b1a478c3ed8a6369e5d5fc42b2afa93f5de8f520981"
      "c62bbe81";
  ASSERT_TRUE(BN_hex2bn(&rsa->d, kDEuler));
  EXPECT_TRUE(RSA_check_key(rsa.get()));

  // If d is completely out of range but otherwise valid, it is rejected.
  static const char kDTooLarge[] =
      "f2c885128cf04101c283553617c210d8ffd14cde98dc420c3c9892b55606cbedcda24298"
      "7655b3f7b9433c2c316293a1cf1a2b034f197aeec1de8d81a67d94cc902b9fce1712d5a4"
      "9c257ff705725cd77338d23535d3b87c8f4cecc15a6b72641ffd81aea106839d216b5fcd"
      "7d415751d27255e540dd1638a8389721e9d0807d65d24d7b8c2f60e4b2c0bf250544ce68"
      "b5ddbc1463d5a4638b2816b0f033dacdc0162f329af9e4d142352521fbd2fe14af824ef3"
      "1601fe843c79cc3efbcb8eafd79262bdd25e2bdf21440f774e26d88ed7df938c5cf6982d"
      "e9fa635b8ca36ce5c5fbd579a53cbb0348ceae752d4bc5621c5acc922ca2082494633337"
      "42e770c1";
  ASSERT_TRUE(BN_hex2bn(&rsa->d, kDTooLarge));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  ASSERT_TRUE(BN_hex2bn(&rsa->d, kD));

  // CRT value must either all be provided or all missing.
  ASSERT_TRUE(BN_hex2bn(&rsa->dmp1, kDMP1));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  BN_free(rsa->dmp1);
  rsa->dmp1 = nullptr;

  ASSERT_TRUE(BN_hex2bn(&rsa->dmq1, kDMQ1));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  BN_free(rsa->dmq1);
  rsa->dmq1 = nullptr;

  ASSERT_TRUE(BN_hex2bn(&rsa->iqmp, kIQMP));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();

  // The full key is accepted.
  ASSERT_TRUE(BN_hex2bn(&rsa->dmp1, kDMP1));
  ASSERT_TRUE(BN_hex2bn(&rsa->dmq1, kDMQ1));
  EXPECT_TRUE(RSA_check_key(rsa.get()));

  // Incorrect CRT values are rejected.
  ASSERT_TRUE(BN_add_word(rsa->dmp1, 1));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  ASSERT_TRUE(BN_sub_word(rsa->dmp1, 1));

  ASSERT_TRUE(BN_add_word(rsa->dmq1, 1));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  ASSERT_TRUE(BN_sub_word(rsa->dmq1, 1));

  ASSERT_TRUE(BN_add_word(rsa->iqmp, 1));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  ASSERT_TRUE(BN_sub_word(rsa->iqmp, 1));

  // Non-reduced CRT values are rejected.
  ASSERT_TRUE(BN_add(rsa->dmp1, rsa->dmp1, rsa->p));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  ASSERT_TRUE(BN_sub(rsa->dmp1, rsa->dmp1, rsa->p));

  ASSERT_TRUE(BN_add(rsa->dmq1, rsa->dmq1, rsa->q));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  ASSERT_TRUE(BN_sub(rsa->dmq1, rsa->dmq1, rsa->q));

  ASSERT_TRUE(BN_add(rsa->iqmp, rsa->iqmp, rsa->p));
  EXPECT_FALSE(RSA_check_key(rsa.get()));
  ERR_clear_error();
  ASSERT_TRUE(BN_sub(rsa->iqmp, rsa->iqmp, rsa->p));
}

TEST(RSATest, KeygenFail) {
  bssl::UniquePtr<RSA> rsa(RSA_new());
  ASSERT_TRUE(rsa);

  // Cause RSA key generation after a prime has been generated, to test that
  // |rsa| is left alone.
  BN_GENCB cb;
  BN_GENCB_set(&cb,
               [](int event, int, BN_GENCB *) -> int { return event != 3; },
               nullptr);

  bssl::UniquePtr<BIGNUM> e(BN_new());
  ASSERT_TRUE(e);
  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));

  // Key generation should fail.
  EXPECT_FALSE(RSA_generate_key_ex(rsa.get(), 2048, e.get(), &cb));

  // Failed key generations do not leave garbage in |rsa|.
  EXPECT_FALSE(rsa->n);
  EXPECT_FALSE(rsa->e);
  EXPECT_FALSE(rsa->d);
  EXPECT_FALSE(rsa->p);
  EXPECT_FALSE(rsa->q);
  EXPECT_FALSE(rsa->dmp1);
  EXPECT_FALSE(rsa->dmq1);
  EXPECT_FALSE(rsa->iqmp);
  EXPECT_FALSE(rsa->mont_n);
  EXPECT_FALSE(rsa->mont_p);
  EXPECT_FALSE(rsa->mont_q);
  EXPECT_FALSE(rsa->d_fixed);
  EXPECT_FALSE(rsa->dmp1_fixed);
  EXPECT_FALSE(rsa->dmq1_fixed);
  EXPECT_FALSE(rsa->iqmp_mont);
  EXPECT_FALSE(rsa->private_key_frozen);

  // Failed key generations leave the previous contents alone.
  EXPECT_TRUE(RSA_generate_key_ex(rsa.get(), 2048, e.get(), nullptr));
  uint8_t *der;
  size_t der_len;
  ASSERT_TRUE(RSA_private_key_to_bytes(&der, &der_len, rsa.get()));
  bssl::UniquePtr<uint8_t> delete_der(der);

  EXPECT_FALSE(RSA_generate_key_ex(rsa.get(), 2048, e.get(), &cb));

  uint8_t *der2;
  size_t der2_len;
  ASSERT_TRUE(RSA_private_key_to_bytes(&der2, &der2_len, rsa.get()));
  bssl::UniquePtr<uint8_t> delete_der2(der2);
  EXPECT_EQ(Bytes(der, der_len), Bytes(der2, der2_len));

  // Generating a key over an existing key works, despite any cached state.
  EXPECT_TRUE(RSA_generate_key_ex(rsa.get(), 2048, e.get(), nullptr));
  EXPECT_TRUE(RSA_check_key(rsa.get()));
  uint8_t *der3;
  size_t der3_len;
  ASSERT_TRUE(RSA_private_key_to_bytes(&der3, &der3_len, rsa.get()));
  bssl::UniquePtr<uint8_t> delete_der3(der3);
  EXPECT_NE(Bytes(der, der_len), Bytes(der3, der3_len));
}

TEST(RSATest, KeygenFailOnce) {
  bssl::UniquePtr<RSA> rsa(RSA_new());
  ASSERT_TRUE(rsa);

  // Cause only the first iteration of RSA key generation to fail.
  bool failed = false;
  BN_GENCB cb;
  BN_GENCB_set(&cb,
               [](int event, int n, BN_GENCB *cb_ptr) -> int {
                 bool *failed_ptr = static_cast<bool *>(cb_ptr->arg);
                 if (*failed_ptr) {
                   ADD_FAILURE() << "Callback called multiple times.";
                   return 1;
                 }
                 *failed_ptr = true;
                 return 0;
               },
               &failed);

  // Although key generation internally retries, the external behavior of
  // |BN_GENCB| is preserved.
  bssl::UniquePtr<BIGNUM> e(BN_new());
  ASSERT_TRUE(e);
  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));
  EXPECT_FALSE(RSA_generate_key_ex(rsa.get(), 2048, e.get(), &cb));
}

TEST(RSATest, KeygenInternalRetry) {
  bssl::UniquePtr<RSA> rsa(RSA_new());
  ASSERT_TRUE(rsa);

  // Simulate one internal attempt at key generation failing.
  bool failed = false;
  BN_GENCB cb;
  BN_GENCB_set(&cb,
               [](int event, int n, BN_GENCB *cb_ptr) -> int {
                 bool *failed_ptr = static_cast<bool *>(cb_ptr->arg);
                 if (*failed_ptr) {
                   return 1;
                 }
                 *failed_ptr = true;
                 // This test does not test any public API behavior. It is just
                 // a hack to exercise the retry codepath and make sure it
                 // works.
                 OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS);
                 return 0;
               },
               &failed);

  // Key generation internally retries on RSA_R_TOO_MANY_ITERATIONS.
  bssl::UniquePtr<BIGNUM> e(BN_new());
  ASSERT_TRUE(e);
  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));
  EXPECT_TRUE(RSA_generate_key_ex(rsa.get(), 2048, e.get(), &cb));
}

// Test that, after a key has been used, it can still be modified into another
// key.
TEST(RSATest, OverwriteKey) {
  // Make a key and perform public and private key operations with it, so that
  // all derived values are filled in.
  bssl::UniquePtr<RSA> key1(RSA_private_key_from_bytes(kKey1, sizeof(kKey1)));
  ASSERT_TRUE(key1);

  ASSERT_TRUE(RSA_check_key(key1.get()));
  size_t len;
  std::vector<uint8_t> ciphertext(RSA_size(key1.get()));
  ASSERT_TRUE(RSA_encrypt(key1.get(), &len, ciphertext.data(),
                          ciphertext.size(), kPlaintext, sizeof(kPlaintext),
                          RSA_PKCS1_OAEP_PADDING));
  ciphertext.resize(len);

  std::vector<uint8_t> plaintext(RSA_size(key1.get()));
  ASSERT_TRUE(RSA_decrypt(key1.get(), &len, plaintext.data(),
                          plaintext.size(), ciphertext.data(), ciphertext.size(),
                          RSA_PKCS1_OAEP_PADDING));
  plaintext.resize(len);
  EXPECT_EQ(Bytes(plaintext), Bytes(kPlaintext));

  // Overwrite |key1| with the contents of |key2|.
  bssl::UniquePtr<RSA> key2(RSA_private_key_from_bytes(kKey2, sizeof(kKey2)));
  ASSERT_TRUE(key2);

  auto copy_rsa_fields = [](RSA *dst, const RSA *src) {
    bssl::UniquePtr<BIGNUM> n(BN_dup(RSA_get0_n(src)));
    ASSERT_TRUE(n);
    bssl::UniquePtr<BIGNUM> e(BN_dup(RSA_get0_e(src)));
    ASSERT_TRUE(e);
    bssl::UniquePtr<BIGNUM> d(BN_dup(RSA_get0_d(src)));
    ASSERT_TRUE(d);
    bssl::UniquePtr<BIGNUM> p(BN_dup(RSA_get0_p(src)));
    ASSERT_TRUE(p);
    bssl::UniquePtr<BIGNUM> q(BN_dup(RSA_get0_q(src)));
    ASSERT_TRUE(q);
    bssl::UniquePtr<BIGNUM> dmp1(BN_dup(RSA_get0_dmp1(src)));
    ASSERT_TRUE(dmp1);
    bssl::UniquePtr<BIGNUM> dmq1(BN_dup(RSA_get0_dmq1(src)));
    ASSERT_TRUE(dmq1);
    bssl::UniquePtr<BIGNUM> iqmp(BN_dup(RSA_get0_iqmp(src)));
    ASSERT_TRUE(iqmp);
    ASSERT_TRUE(RSA_set0_key(dst, n.release(), e.release(), d.release()));
    ASSERT_TRUE(RSA_set0_factors(dst, p.release(), q.release()));
    ASSERT_TRUE(RSA_set0_crt_params(dst, dmp1.release(), dmq1.release(),
                                    iqmp.release()));
  };
  ASSERT_NO_FATAL_FAILURE(copy_rsa_fields(key1.get(), key2.get()));

  auto check_rsa_compatible = [&](RSA *enc, RSA *dec) {
    ciphertext.resize(RSA_size(enc));
    ASSERT_TRUE(RSA_encrypt(enc, &len, ciphertext.data(), ciphertext.size(),
                            kPlaintext, sizeof(kPlaintext),
                            RSA_PKCS1_OAEP_PADDING));
    ciphertext.resize(len);

    plaintext.resize(RSA_size(dec));
    ASSERT_TRUE(RSA_decrypt(dec, &len, plaintext.data(),
                            plaintext.size(), ciphertext.data(),
                            ciphertext.size(), RSA_PKCS1_OAEP_PADDING));
    plaintext.resize(len);
    EXPECT_EQ(Bytes(plaintext), Bytes(kPlaintext));
  };

  ASSERT_NO_FATAL_FAILURE(
      check_rsa_compatible(/*enc=*/key1.get(), /*dec=*/key2.get()));
  ASSERT_NO_FATAL_FAILURE(
      check_rsa_compatible(/*enc=*/key2.get(), /*dec=*/key1.get()));

  // If we generate a new key on top of |key1|, it should be usable and
  // self-consistent. We test this by making a new key with the same parameters
  // and checking they behave the same.
  ASSERT_TRUE(
      RSA_generate_key_ex(key1.get(), 1024, RSA_get0_e(key2.get()), nullptr));
  EXPECT_NE(0, BN_cmp(RSA_get0_n(key1.get()), RSA_get0_n(key2.get())));

  key2.reset(RSA_new());
  ASSERT_TRUE(key2);
  ASSERT_NO_FATAL_FAILURE(copy_rsa_fields(key2.get(), key1.get()));
  ASSERT_NO_FATAL_FAILURE(
      check_rsa_compatible(/*enc=*/key1.get(), /*dec=*/key2.get()));
  ASSERT_NO_FATAL_FAILURE(
      check_rsa_compatible(/*enc=*/key2.get(), /*dec=*/key1.get()));
}

// Test that RSA keys do not support operations will cleanly fail them.
TEST(RSATest, MissingParameters) {
  bssl::UniquePtr<RSA> sample(RSA_private_key_from_bytes(kKey1, sizeof(kKey1)));
  ASSERT_TRUE(sample);

  // Make a sample signature.
  const uint8_t kZeros[32] = {0};
  std::vector<uint8_t> sig(RSA_size(sample.get()));
  unsigned len_u;
  ASSERT_TRUE(RSA_sign(NID_sha256, kZeros, sizeof(kZeros), sig.data(), &len_u,
                       sample.get()));
  sig.resize(len_u);

  // A public key cannot perform private key operations.
  bssl::UniquePtr<RSA> rsa(
      RSA_new_public_key(RSA_get0_n(sample.get()), RSA_get0_e(sample.get())));
  ASSERT_TRUE(rsa);

  std::vector<uint8_t> out(RSA_size(sample.get()));
  EXPECT_FALSE(RSA_sign(NID_sha256, kZeros, sizeof(kZeros), out.data(), &len_u,
                        rsa.get()));
  uint32_t err = ERR_get_error();
  EXPECT_EQ(ERR_LIB_RSA, ERR_GET_LIB(err));
  EXPECT_EQ(RSA_R_VALUE_MISSING, ERR_GET_REASON(err));

  size_t len;
  EXPECT_FALSE(RSA_decrypt(rsa.get(), &len, out.data(), out.size(),
                           kOAEPCiphertext1, sizeof(kOAEPCiphertext1),
                           RSA_PKCS1_OAEP_PADDING));
  err = ERR_get_error();
  EXPECT_EQ(ERR_LIB_RSA, ERR_GET_LIB(err));
  EXPECT_EQ(RSA_R_VALUE_MISSING, ERR_GET_REASON(err));

  // A private key without e cannot perform public key operations.
  rsa.reset(RSA_new_private_key_no_e(RSA_get0_n(sample.get()),
                                     RSA_get0_d(sample.get())));
  ASSERT_TRUE(rsa);

  EXPECT_FALSE(RSA_verify(NID_sha256, kZeros, sizeof(kZeros), sig.data(),
                          sig.size(), rsa.get()));
  err = ERR_get_error();
  EXPECT_EQ(ERR_LIB_RSA, ERR_GET_LIB(err));
  EXPECT_EQ(RSA_R_VALUE_MISSING, ERR_GET_REASON(err));

  EXPECT_FALSE(RSA_encrypt(rsa.get(), &len, out.data(), out.size(), kPlaintext,
                           sizeof(kPlaintext), RSA_PKCS1_OAEP_PADDING));
  err = ERR_get_error();
  EXPECT_EQ(ERR_LIB_RSA, ERR_GET_LIB(err));
  EXPECT_EQ(RSA_R_VALUE_MISSING, ERR_GET_REASON(err));
}

TEST(RSATest, Negative) {
  auto dup_neg = [](const BIGNUM *bn) -> bssl::UniquePtr<BIGNUM> {
    bssl::UniquePtr<BIGNUM> ret(BN_dup(bn));
    if (!ret) {
      return nullptr;
    }
    BN_set_negative(ret.get(), 1);
    return ret;
  };

  bssl::UniquePtr<RSA> key(
      RSA_private_key_from_bytes(kKey1, sizeof(kKey1)));
  ASSERT_TRUE(key);
  const BIGNUM *n = RSA_get0_n(key.get());
  bssl::UniquePtr<BIGNUM> neg_n = dup_neg(n);
  ASSERT_TRUE(neg_n);
  const BIGNUM *e = RSA_get0_e(key.get());
  bssl::UniquePtr<BIGNUM> neg_e = dup_neg(e);
  ASSERT_TRUE(neg_e);
  const BIGNUM *d = RSA_get0_d(key.get());
  bssl::UniquePtr<BIGNUM> neg_d = dup_neg(d);
  ASSERT_TRUE(neg_d);
  const BIGNUM *p = RSA_get0_p(key.get());
  bssl::UniquePtr<BIGNUM> neg_p = dup_neg(p);
  ASSERT_TRUE(neg_p);
  const BIGNUM *q = RSA_get0_q(key.get());
  bssl::UniquePtr<BIGNUM> neg_q = dup_neg(q);
  ASSERT_TRUE(neg_q);
  const BIGNUM *dmp1 = RSA_get0_dmp1(key.get());
  bssl::UniquePtr<BIGNUM> neg_dmp1 = dup_neg(dmp1);
  ASSERT_TRUE(neg_dmp1);
  const BIGNUM *dmq1 = RSA_get0_dmq1(key.get());
  bssl::UniquePtr<BIGNUM> neg_dmq1 = dup_neg(dmq1);
  ASSERT_TRUE(neg_dmq1);
  const BIGNUM *iqmp = RSA_get0_iqmp(key.get());
  bssl::UniquePtr<BIGNUM> neg_iqmp = dup_neg(iqmp);
  ASSERT_TRUE(neg_iqmp);

  EXPECT_FALSE(RSA_new_public_key(neg_n.get(), e));
  EXPECT_FALSE(RSA_new_public_key(n, neg_e.get()));
  EXPECT_FALSE(RSA_new_private_key(neg_n.get(), e, d, p, q, dmp1, dmq1, iqmp));
  EXPECT_FALSE(RSA_new_private_key(n, neg_e.get(), d, p, q, dmp1, dmq1, iqmp));
  EXPECT_FALSE(RSA_new_private_key(n, e, neg_d.get(), p, q, dmp1, dmq1, iqmp));
  EXPECT_FALSE(RSA_new_private_key(n, e, d, neg_p.get(), q, dmp1, dmq1, iqmp));
  EXPECT_FALSE(RSA_new_private_key(n, e, d, p, neg_q.get(), dmp1, dmq1, iqmp));
  EXPECT_FALSE(RSA_new_private_key(n, e, d, p, q, neg_dmp1.get(), dmq1, iqmp));
  EXPECT_FALSE(RSA_new_private_key(n, e, d, p, q, dmp1, neg_dmq1.get(), iqmp));
  EXPECT_FALSE(RSA_new_private_key(n, e, d, p, q, dmp1, dmq1, neg_iqmp.get()));
}

TEST(RSATest, LargeE) {
  // Test an RSA key with large e by swapping d and e in kKey1.
  // Since e is small, e mod (p-1) and e mod (q-1) will simply be e.
  bssl::UniquePtr<RSA> key(RSA_private_key_from_bytes(kKey1, sizeof(kKey1)));
  ASSERT_TRUE(key);
  const BIGNUM *n = RSA_get0_n(key.get());
  const BIGNUM *e = RSA_get0_e(key.get());
  const BIGNUM *d = RSA_get0_d(key.get());
  const BIGNUM *p = RSA_get0_p(key.get());
  const BIGNUM *q = RSA_get0_q(key.get());
  const BIGNUM *iqmp = RSA_get0_iqmp(key.get());

  // By default, the large exponent is not allowed as e.
  bssl::UniquePtr<RSA> pub(RSA_new_public_key(n, /*e=*/d));
  EXPECT_FALSE(pub);
  bssl::UniquePtr<RSA> priv(RSA_new_private_key(n, /*e=*/d, /*d=*/e, p, q,
                                                /*dmp1=*/e, /*dmq1=*/e, iqmp));
  EXPECT_FALSE(priv);

  // Constructing such a key piecemeal also would not work. This was only
  // possible with private APIs, so when |RSA| is opaque, this case will be
  // impossible.
  priv.reset(RSA_new());
  ASSERT_TRUE(priv);
  priv->n = BN_dup(n);
  ASSERT_TRUE(priv->n);
  priv->e = BN_dup(d);  // Swapped
  ASSERT_TRUE(priv->e);
  priv->d = BN_dup(e);
  ASSERT_TRUE(priv->d);

  static const uint8_t kDigest[32] = {0};
  std::vector<uint8_t> sig(RSA_size(priv.get()));
  size_t len;
  EXPECT_FALSE(RSA_sign_pss_mgf1(priv.get(), &len, sig.data(), sig.size(),
                                 kDigest, sizeof(kDigest), EVP_sha256(),
                                 EVP_sha256(), /*salt_len=*/32));

  // But the "large e" APIs tolerate it.
  pub.reset(RSA_new_public_key_large_e(n, /*e=*/d));
  ASSERT_TRUE(pub);
  priv.reset(RSA_new_private_key_large_e(n, /*e=*/d, /*d=*/e, p, q, /*dmp1=*/e,
                                         /*dmq1=*/e, iqmp));
  ASSERT_TRUE(priv);

  // Test that operations work correctly.
  sig.resize(RSA_size(priv.get()));
  ASSERT_TRUE(RSA_sign_pss_mgf1(priv.get(), &len, sig.data(), sig.size(),
                                kDigest, sizeof(kDigest), EVP_sha256(),
                                EVP_sha256(), /*salt_len=*/32));
  sig.resize(len);

  EXPECT_TRUE(RSA_verify_pss_mgf1(pub.get(), kDigest, sizeof(kDigest),
                                  EVP_sha256(), EVP_sha256(), /*salt_len=*/32,
                                  sig.data(), sig.size()));

  // e = 1 is still invalid.
  EXPECT_FALSE(RSA_new_public_key_large_e(n, BN_value_one()));

  // e must still be odd.
  bssl::UniquePtr<BIGNUM> bad_e(BN_dup(d));
  ASSERT_TRUE(bad_e);
  ASSERT_TRUE(BN_add_word(bad_e.get(), 1));
  EXPECT_FALSE(RSA_new_public_key_large_e(n, bad_e.get()));

  // e must still be bounded by n.
  bad_e.reset(BN_dup(n));
  ASSERT_TRUE(bad_e);
  ASSERT_TRUE(BN_add_word(bad_e.get(), 2));  // Preserve parity.
  EXPECT_FALSE(RSA_new_public_key_large_e(n, bad_e.get()));
}

// Test minimum key limits on RSA keys. Currently, we require a minimum of
// 512-bit RSA.
//
// TODO(crbug.com/boringssl/607): Raise this limit. 512-bit RSA was factored in
// 1999.
TEST(RSATest, SmallKey) {
  static const uint8_t kRSA511Private[] = {
      0x30, 0x82, 0x01, 0x39, 0x02, 0x01, 0x00, 0x02, 0x40, 0x56, 0xc1, 0x3d,
      0xb3, 0x4f, 0xe4, 0xe9, 0x2f, 0x29, 0x8a, 0xd3, 0xe2, 0xfe, 0xb3, 0x3b,
      0x88, 0x02, 0x8b, 0xdd, 0x44, 0xb5, 0x41, 0x4b, 0x43, 0x97, 0x93, 0x75,
      0x78, 0x4b, 0x10, 0x30, 0x88, 0xce, 0xd2, 0x32, 0xe3, 0x9e, 0xda, 0x68,
      0xc9, 0xc3, 0xcd, 0xa1, 0xde, 0xbc, 0x4a, 0xeb, 0x37, 0x60, 0xd2, 0x82,
      0x2f, 0x5d, 0x21, 0x3b, 0x88, 0x0e, 0x12, 0x44, 0x4d, 0x5d, 0x44, 0xc1,
      0x9d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x40, 0x08, 0xe5, 0xf5, 0x30,
      0x29, 0x27, 0xaf, 0x8b, 0x38, 0xd5, 0x96, 0x7a, 0x17, 0xe9, 0xc6, 0x57,
      0x62, 0xfb, 0x79, 0x8c, 0x8c, 0x92, 0xcf, 0xe7, 0x74, 0xea, 0x99, 0x07,
      0xe7, 0x9b, 0x17, 0x7f, 0x30, 0x9f, 0x86, 0x55, 0x15, 0x8d, 0xe6, 0xa8,
      0x0d, 0x7b, 0x42, 0x41, 0x27, 0x18, 0x29, 0x55, 0xb1, 0x08, 0x07, 0x2a,
      0x4e, 0x67, 0x19, 0x9c, 0xe3, 0xe4, 0x84, 0xd6, 0x82, 0x62, 0xd4, 0x81,
      0x02, 0x21, 0x00, 0xcd, 0x5a, 0x9b, 0x23, 0x3d, 0xb5, 0x9c, 0x56, 0xbc,
      0xc5, 0x56, 0xcf, 0x77, 0x58, 0xc0, 0x62, 0x72, 0xa0, 0x85, 0x77, 0xf4,
      0xc3, 0xf8, 0x47, 0x6d, 0xc0, 0x8f, 0x18, 0x77, 0xee, 0xf1, 0xad, 0x02,
      0x20, 0x6c, 0x26, 0xaa, 0x8a, 0xaf, 0x7b, 0x9f, 0x35, 0x19, 0x08, 0xc2,
      0xa0, 0x9f, 0x4e, 0x9e, 0x62, 0x48, 0xb1, 0x7c, 0x0e, 0x68, 0x63, 0x0d,
      0x05, 0x76, 0x73, 0x0a, 0xa0, 0xb3, 0xed, 0x6d, 0xb1, 0x02, 0x21, 0x00,
      0xc2, 0x26, 0x1c, 0xb0, 0xa7, 0xe2, 0x31, 0x4a, 0x4c, 0x34, 0xe2, 0xcb,
      0x49, 0x51, 0xce, 0xaa, 0x05, 0x27, 0xc0, 0xa8, 0x55, 0xf0, 0x85, 0xa6,
      0xba, 0x9c, 0x28, 0x6e, 0x00, 0xce, 0x17, 0x0d, 0x02, 0x20, 0x65, 0x51,
      0xb0, 0x11, 0xaf, 0x26, 0xbc, 0x57, 0x4d, 0x35, 0xb4, 0xc8, 0x2f, 0x96,
      0xc2, 0xb0, 0xc6, 0xf3, 0x67, 0x8a, 0x43, 0xe7, 0x0f, 0xaa, 0xdf, 0x76,
      0x15, 0x2d, 0xca, 0x82, 0x93, 0x71, 0x02, 0x21, 0x00, 0x9e, 0x89, 0x74,
      0x15, 0x7e, 0x73, 0x43, 0xa0, 0x1e, 0xa9, 0xa5, 0x9f, 0xad, 0xf1, 0xa0,
      0xfa, 0x13, 0x86, 0x10, 0x3f, 0xb0, 0xba, 0x3f, 0x45, 0x87, 0x13, 0x02,
      0x86, 0xa4, 0xa4, 0x31, 0x92};
  static const uint8_t kRSA511Public[] = {
      0x30, 0x47, 0x02, 0x40, 0x56, 0xc1, 0x3d, 0xb3, 0x4f, 0xe4, 0xe9,
      0x2f, 0x29, 0x8a, 0xd3, 0xe2, 0xfe, 0xb3, 0x3b, 0x88, 0x02, 0x8b,
      0xdd, 0x44, 0xb5, 0x41, 0x4b, 0x43, 0x97, 0x93, 0x75, 0x78, 0x4b,
      0x10, 0x30, 0x88, 0xce, 0xd2, 0x32, 0xe3, 0x9e, 0xda, 0x68, 0xc9,
      0xc3, 0xcd, 0xa1, 0xde, 0xbc, 0x4a, 0xeb, 0x37, 0x60, 0xd2, 0x82,
      0x2f, 0x5d, 0x21, 0x3b, 0x88, 0x0e, 0x12, 0x44, 0x4d, 0x5d, 0x44,
      0xc1, 0x9d, 0x02, 0x03, 0x01, 0x00, 0x01};
  static const uint8_t kRSA512Private[] = {
      0x30, 0x82, 0x01, 0x3a, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xa5, 0x44,
      0x8f, 0x3d, 0xa2, 0x0b, 0x20, 0xc6, 0xac, 0x10, 0xc1, 0x27, 0x11, 0xf0,
      0x43, 0x5d, 0x05, 0xb7, 0x0f, 0x80, 0x3b, 0x9b, 0x85, 0xf1, 0x7a, 0x0e,
      0xbd, 0x72, 0xed, 0x8a, 0xdc, 0xa1, 0xaa, 0xd4, 0x53, 0xcb, 0x65, 0x78,
      0x4b, 0x30, 0x6b, 0x52, 0x51, 0xee, 0xcd, 0x2f, 0x90, 0x7b, 0xd1, 0x9c,
      0xe9, 0x79, 0x98, 0x58, 0xe3, 0x47, 0x35, 0xa7, 0xcd, 0x6a, 0x71, 0x38,
      0xb5, 0x0d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x41, 0x00, 0x94, 0x24,
      0x82, 0xa9, 0xe2, 0xa9, 0x4a, 0xf6, 0x0b, 0xa2, 0xf1, 0x21, 0x0e, 0x89,
      0x6a, 0x38, 0xe6, 0x38, 0x93, 0xe2, 0x84, 0x8c, 0x02, 0x62, 0xd4, 0xe0,
      0x85, 0x9d, 0x91, 0xa4, 0xd9, 0xe3, 0x77, 0x6c, 0x26, 0x85, 0xf6, 0x2e,
      0x0a, 0xe4, 0x18, 0x73, 0x06, 0x9a, 0xea, 0xde, 0x78, 0x65, 0xba, 0x7a,
      0xdb, 0xc0, 0x3b, 0xf7, 0x29, 0x1e, 0x43, 0xed, 0xaf, 0xf5, 0xaf, 0xa8,
      0xdf, 0x01, 0x02, 0x21, 0x00, 0xdb, 0x93, 0x05, 0x2d, 0xf3, 0xdf, 0xe4,
      0x31, 0xef, 0x50, 0xc7, 0x54, 0x0f, 0x08, 0x5d, 0x50, 0x42, 0xfa, 0xb9,
      0x20, 0x37, 0x98, 0xd3, 0xc0, 0x64, 0x2f, 0xb6, 0xe4, 0xb2, 0xfe, 0xe5,
      0x6d, 0x02, 0x21, 0x00, 0xc0, 0xaf, 0x3a, 0x1f, 0xd9, 0xba, 0x5a, 0x6a,
      0xc2, 0x80, 0x2e, 0x7b, 0x65, 0x3d, 0x8a, 0x76, 0xae, 0x4b, 0x5a, 0xff,
      0x7a, 0x9a, 0x5e, 0xc2, 0xfa, 0x07, 0xfb, 0x2d, 0x0c, 0x16, 0x6a, 0x21,
      0x02, 0x20, 0x06, 0xf3, 0xb9, 0xb7, 0x41, 0xc0, 0x75, 0xfe, 0x2a, 0xc0,
      0x98, 0xff, 0x0d, 0x56, 0xcb, 0x75, 0x8e, 0x19, 0x58, 0x21, 0x30, 0x01,
      0x73, 0xba, 0xe4, 0xb1, 0x2a, 0x0e, 0x45, 0xa8, 0x92, 0x65, 0x02, 0x20,
      0x25, 0xcd, 0xbb, 0x3f, 0xa8, 0x7e, 0x11, 0x63, 0x44, 0xc9, 0xd5, 0x54,
      0xcc, 0x66, 0x28, 0x96, 0x64, 0x57, 0xd0, 0x80, 0xb3, 0x53, 0x3a, 0x28,
      0x52, 0xd9, 0xe2, 0x03, 0xd2, 0x8d, 0x4b, 0x41, 0x02, 0x20, 0x09, 0x30,
      0xd9, 0xfd, 0xad, 0x31, 0x1a, 0x38, 0xb7, 0x71, 0x06, 0xed, 0x49, 0xa6,
      0xe2, 0xec, 0x42, 0xc2, 0x8e, 0xe9, 0xec, 0xf7, 0x3e, 0xb7, 0x4a, 0x5e,
      0x2e, 0xa2, 0x7a, 0x8d, 0xa4, 0x95};
  static const uint8_t kRSA512Public[] = {
      0x30, 0x48, 0x02, 0x41, 0x00, 0xa5, 0x44, 0x8f, 0x3d, 0xa2, 0x0b,
      0x20, 0xc6, 0xac, 0x10, 0xc1, 0x27, 0x11, 0xf0, 0x43, 0x5d, 0x05,
      0xb7, 0x0f, 0x80, 0x3b, 0x9b, 0x85, 0xf1, 0x7a, 0x0e, 0xbd, 0x72,
      0xed, 0x8a, 0xdc, 0xa1, 0xaa, 0xd4, 0x53, 0xcb, 0x65, 0x78, 0x4b,
      0x30, 0x6b, 0x52, 0x51, 0xee, 0xcd, 0x2f, 0x90, 0x7b, 0xd1, 0x9c,
      0xe9, 0x79, 0x98, 0x58, 0xe3, 0x47, 0x35, 0xa7, 0xcd, 0x6a, 0x71,
      0x38, 0xb5, 0x0d, 0x02, 0x03, 0x01, 0x00, 0x01};

  bssl::UniquePtr<RSA> rsa(
      RSA_public_key_from_bytes(kRSA511Public, sizeof(kRSA511Public)));
  EXPECT_FALSE(rsa);
  rsa.reset(RSA_private_key_from_bytes(kRSA511Private, sizeof(kRSA511Private)));
  EXPECT_FALSE(rsa);

  rsa.reset(RSA_public_key_from_bytes(kRSA512Public, sizeof(kRSA512Public)));
  EXPECT_TRUE(rsa);
  rsa.reset(RSA_private_key_from_bytes(kRSA512Private, sizeof(kRSA512Private)));
  EXPECT_TRUE(rsa);
}

#if !defined(BORINGSSL_SHARED_LIBRARY)
TEST(RSATest, SqrtTwo) {
  bssl::UniquePtr<BIGNUM> sqrt(BN_new()), pow2(BN_new());
  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
  ASSERT_TRUE(sqrt);
  ASSERT_TRUE(pow2);
  ASSERT_TRUE(ctx);

  size_t bits = kBoringSSLRSASqrtTwoLen * BN_BITS2;
  ASSERT_TRUE(BN_one(pow2.get()));
  ASSERT_TRUE(BN_lshift(pow2.get(), pow2.get(), 2 * bits - 1));

  // Check that sqrt² < pow2.
  ASSERT_TRUE(
      bn_set_words(sqrt.get(), kBoringSSLRSASqrtTwo, kBoringSSLRSASqrtTwoLen));
  ASSERT_TRUE(BN_sqr(sqrt.get(), sqrt.get(), ctx.get()));
  EXPECT_LT(BN_cmp(sqrt.get(), pow2.get()), 0);

  // Check that pow2 < (sqrt + 1)².
  ASSERT_TRUE(
      bn_set_words(sqrt.get(), kBoringSSLRSASqrtTwo, kBoringSSLRSASqrtTwoLen));
  ASSERT_TRUE(BN_add_word(sqrt.get(), 1));
  ASSERT_TRUE(BN_sqr(sqrt.get(), sqrt.get(), ctx.get()));
  EXPECT_LT(BN_cmp(pow2.get(), sqrt.get()), 0);

  // Check the kBoringSSLRSASqrtTwo is sized for a 4096-bit RSA key.
  EXPECT_EQ(4096u / 2u, bits);
}
#endif  // !BORINGSSL_SHARED_LIBRARY

#if defined(OPENSSL_THREADS)
TEST(RSATest, Threads) {
  bssl::UniquePtr<RSA> rsa_template(
      RSA_private_key_from_bytes(kKey1, sizeof(kKey1)));
  ASSERT_TRUE(rsa_template);

  const uint8_t kDummyHash[32] = {0};
  std::vector<uint8_t> sig(RSA_size(rsa_template.get()));
  unsigned sig_len;
  EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig.data(),
                       &sig_len, rsa_template.get()));
  sig.resize(sig_len);

  // RSA keys may be assembled piece-meal and then used in parallel between
  // threads, which requires internal locking to create some derived properties.
  bssl::UniquePtr<RSA> rsa(RSA_new());
  rsa->n = BN_dup(rsa_template->n);
  ASSERT_TRUE(rsa->n);
  rsa->e = BN_dup(rsa_template->e);
  ASSERT_TRUE(rsa->e);
  rsa->d = BN_dup(rsa_template->d);
  ASSERT_TRUE(rsa->d);
  rsa->p = BN_dup(rsa_template->p);
  ASSERT_TRUE(rsa->p);
  rsa->q = BN_dup(rsa_template->q);
  ASSERT_TRUE(rsa->q);
  rsa->dmp1 = BN_dup(rsa_template->dmp1);
  ASSERT_TRUE(rsa->dmp1);
  rsa->dmq1 = BN_dup(rsa_template->dmq1);
  ASSERT_TRUE(rsa->dmq1);
  rsa->iqmp = BN_dup(rsa_template->iqmp);
  ASSERT_TRUE(rsa->iqmp);

  // Each of these operations must be safe to do concurrently on different
  // threads.
  auto raw_access = [&] { EXPECT_EQ(0, BN_cmp(rsa->d, rsa_template->d)); };
  auto getter = [&] {
    const BIGNUM *d;
    RSA_get0_key(rsa.get(), nullptr, nullptr, &d);
    EXPECT_EQ(0, BN_cmp(d, rsa_template->d));
  };
  auto sign = [&] {
    std::vector<uint8_t> sig2(RSA_size(rsa.get()));
    unsigned sig2_len;
    EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash),
                         sig2.data(), &sig2_len, rsa.get()));
    sig2.resize(sig2_len);
    // RSASSA-PKCS1-v1_5 is deterministic.
    EXPECT_EQ(Bytes(sig), Bytes(sig2));
  };
  auto verify = [&] {
    EXPECT_TRUE(RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash),
                           sig.data(), sig.size(), rsa.get()));
  };

  std::vector<std::thread> threads;
  threads.emplace_back(raw_access);
  threads.emplace_back(raw_access);
  threads.emplace_back(getter);
  threads.emplace_back(getter);
  threads.emplace_back(sign);
  threads.emplace_back(sign);
  threads.emplace_back(verify);
  threads.emplace_back(verify);
  for (auto &thread : threads) {
    thread.join();
  }
}

// This test might be excessively slow on slower CPUs or platforms that do not
// expect server workloads. It is disabled by default and reenabled on some
// platforms when running tests standalone via all_tests.go.
//
// Additionally, even when running disabled tests standalone, limit this to
// x86_64. On other platforms, this test hits resource limits or is too slow. We
// also disable on FreeBSD. See https://crbug.com/boringssl/603.
#if defined(OPENSSL_TSAN) || \
    (defined(OPENSSL_X86_64) && !defined(OPENSSL_FREEBSD))
TEST(RSATest, DISABLED_BlindingCacheConcurrency) {
  bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(kKey1, sizeof(kKey1)));
  ASSERT_TRUE(rsa);

#if defined(OPENSSL_TSAN)
  constexpr size_t kSignaturesPerThread = 10;
  constexpr size_t kNumThreads = 10;
#else
  constexpr size_t kSignaturesPerThread = 100;
  constexpr size_t kNumThreads = 2048;
#endif

  const uint8_t kDummyHash[32] = {0};
  auto worker = [&] {
    std::vector<uint8_t> sig(RSA_size(rsa.get()));
    for (size_t i = 0; i < kSignaturesPerThread; i++) {
      unsigned sig_len = sig.size();
      EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash),
                           sig.data(), &sig_len, rsa.get()));
    }
  };

  std::vector<std::thread> threads;
  threads.reserve(kNumThreads);
  for (size_t i = 0; i < kNumThreads; i++) {
    threads.emplace_back(worker);
  }
  for (auto &thread : threads) {
    thread.join();
  }
}
#endif  // TSAN || (X86_64 && !FREEBSD)

#endif  // THREADS
