boringssl/crypto/rsa/rsa_test.cc
Steven Valdez 400d0b7b5e Add PWCT for RSA and ECDSA for FIPS 140-2.
Since only the consumers knows whether an EC key will be used for
ECDSA or ECDHE, it is part of the FIPS policy for the consumer to
check the validity of the generated key before signing with it.

Change-Id: Ie250f655c8fcb6a59cc7210def1e87eb958e9349
Reviewed-on: https://boringssl-review.googlesource.com/14745
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
2017-04-13 17:00:43 +00:00

812 lines
40 KiB
C++

/* 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/err.h>
#include <openssl/nid.h>
#include "../bn/internal.h"
#include "../internal.h"
#include "../test/test_util.h"
#include "internal.h"
// kPlaintext is a sample plaintext.
static const uint8_t kPlaintext[] = "\x54\x85\x9b\x34\x2c\x49\xea\x2a";
static const size_t kPlaintextLen = sizeof(kPlaintext) - 1;
// kKey1 is a DER-encoded RSAPrivateKey.
static const uint8_t kKey1[] =
"\x30\x82\x01\x38\x02\x01\x00\x02\x41\x00\xaa\x36\xab\xce\x88\xac\xfd\xff"
"\x55\x52\x3c\x7f\xc4\x52\x3f\x90\xef\xa0\x0d\xf3\x77\x4a\x25\x9f\x2e\x62"
"\xb4\xc5\xd9\x9c\xb5\xad\xb3\x00\xa0\x28\x5e\x53\x01\x93\x0e\x0c\x70\xfb"
"\x68\x76\x93\x9c\xe6\x16\xce\x62\x4a\x11\xe0\x08\x6d\x34\x1e\xbc\xac\xa0"
"\xa1\xf5\x02\x01\x11\x02\x40\x0a\x03\x37\x48\x62\x64\x87\x69\x5f\x5f\x30"
"\xbc\x38\xb9\x8b\x44\xc2\xcd\x2d\xff\x43\x40\x98\xcd\x20\xd8\xa1\x38\xd0"
"\x90\xbf\x64\x79\x7c\x3f\xa7\xa2\xcd\xcb\x3c\xd1\xe0\xbd\xba\x26\x54\xb4"
"\xf9\xdf\x8e\x8a\xe5\x9d\x73\x3d\x9f\x33\xb3\x01\x62\x4a\xfd\x1d\x51\x02"
"\x21\x00\xd8\x40\xb4\x16\x66\xb4\x2e\x92\xea\x0d\xa3\xb4\x32\x04\xb5\xcf"
"\xce\x33\x52\x52\x4d\x04\x16\xa5\xa4\x41\xe7\x00\xaf\x46\x12\x0d\x02\x21"
"\x00\xc9\x7f\xb1\xf0\x27\xf4\x53\xf6\x34\x12\x33\xea\xaa\xd1\xd9\x35\x3f"
"\x6c\x42\xd0\x88\x66\xb1\xd0\x5a\x0f\x20\x35\x02\x8b\x9d\x89\x02\x20\x59"
"\x0b\x95\x72\xa2\xc2\xa9\xc4\x06\x05\x9d\xc2\xab\x2f\x1d\xaf\xeb\x7e\x8b"
"\x4f\x10\xa7\x54\x9e\x8e\xed\xf5\xb4\xfc\xe0\x9e\x05\x02\x21\x00\x8e\x3c"
"\x05\x21\xfe\x15\xe0\xea\x06\xa3\x6f\xf0\xf1\x0c\x99\x52\xc3\x5b\x7a\x75"
"\x14\xfd\x32\x38\xb8\x0a\xad\x52\x98\x62\x8d\x51\x02\x20\x36\x3f\xf7\x18"
"\x9d\xa8\xe9\x0b\x1d\x34\x1f\x71\xd0\x9b\x76\xa8\xa9\x43\xe1\x1d\x10\xb2"
"\x4d\x24\x9f\x2d\xea\xfe\xf8\x0c\x18\x26";
// kFIPSKey is a DER-encoded RSAPrivateKey that is FIPS-compliant.
static const uint8_t kFIPSKey[] =
"\x30\x82\x02\x5c\x02\x01\x00\x02\x81\x81\x00\xa1\x71\x90\x77\x86\x8a\xc7"
"\xb8\xfc\x2a\x45\x82\x6d\xee\xeb\x35\x3a\x18\x3f\xb6\xb0\x1e\xb1\xd3\x09"
"\x6b\x05\x4d\xec\x1c\x37\x6f\x09\x31\x32\xda\x21\x8a\x49\x0e\x16\x28\xed"
"\x9a\x30\xf3\x14\x53\xfd\x5b\xb0\xf6\x4a\x5d\x52\xe1\xda\xe1\x40\x6e\x65"
"\xbf\xca\x45\xd9\x62\x96\x4a\x1e\x11\xc4\x61\x83\x1f\x58\x8d\x5e\xd0\x12"
"\xaf\xa5\xec\x9b\x97\x2f\x6c\xb2\x82\x4a\x73\xd0\xd3\x9a\xc9\x69\x6b\x24"
"\x3c\x82\x6f\xee\x4d\x0c\x7e\xdf\xd7\xae\xea\x3a\xeb\x04\x27\x8d\x43\x81"
"\x59\xa7\x90\x56\xc1\x69\x42\xb3\xaf\x1c\x8d\x4e\xbf\x02\x03\x01\x00\x01"
"\x02\x81\x80\x60\x82\xcd\x44\x46\xcf\xeb\xf9\x6f\xf5\xad\x3b\xfd\x90\x18"
"\x57\xe7\x74\xdb\x91\xd0\xd3\x68\xa6\xaa\x38\xaa\x21\x1d\x06\xf9\x34\x8d"
"\xa0\x35\xb0\x24\xe0\xd0\x2f\x75\x9b\xdd\xfe\x91\x48\x9f\x5c\x5e\x57\x54"
"\x00\xc8\x0f\xe6\x1e\x52\x84\xd9\xc9\xa5\x55\xf4\x0a\xbe\x88\x46\x7a\xfb"
"\x18\x37\x8e\xe6\x6e\xa2\x5f\x80\x48\x34\x3f\x5c\xbe\x0e\x1e\xe8\x2f\x50"
"\xba\x14\x96\x3c\xea\xfb\xd2\x49\x33\xdc\x12\xb8\xa7\x8a\xb5\x27\xf9\x00"
"\x4b\xf5\xd2\x2a\xd0\x2c\x1d\x9b\xd5\x6c\x3e\x4b\xb9\x7e\x39\xf7\x3e\x39"
"\xc9\x47\x5e\xbe\x91\x02\x41\x00\xcd\x33\xcf\x37\x01\xd7\x59\xcc\xbe\xa0"
"\x1c\xb9\xf5\xe7\x44\x9f\x62\x91\xa7\xa7\x7b\x0c\x52\xcd\x7e\xe6\x31\x11"
"\x8b\xd8\x2c\x8a\x63\xe1\x07\xc9\xcb\xce\x01\x45\x63\xf5\x5d\x44\xfb\xeb"
"\x8d\x74\x16\x20\x7d\x3b\xb4\xa1\x61\xb0\xa8\x29\x51\xc9\xef\xb6\xa1\xd5"
"\x02\x41\x00\xc9\x68\xa6\xd3\x88\xd5\x49\x9d\x6b\x44\x96\xfd\xbf\x66\x27"
"\xb4\x1f\x90\x76\x86\x2f\xe2\xce\x20\x5d\xee\x9b\xeb\xc4\xb4\x62\x47\x79"
"\x99\xb1\x99\xbc\xa2\xa6\xb6\x96\x64\xd5\x77\x9b\x45\xd4\xf0\x99\xb5\x9e"
"\x61\x4d\xf5\x12\xdd\x84\x14\xaf\x1e\xdd\x83\x24\x43\x02\x40\x60\x29\x7f"
"\x59\xcf\xcb\x13\x92\x17\x63\x01\x13\x44\x61\x74\x8f\x1c\xaa\x15\x5f\x2f"
"\x12\xbf\x5a\xfd\xb4\xf2\x19\xbe\xe7\x37\x38\x43\x46\x19\x58\x3f\xe1\xf2"
"\x46\x8a\x69\x59\xa4\x12\x4a\x78\xa7\x86\x17\x03\x99\x0f\x34\xf1\x8a\xcf"
"\xc3\x4d\x48\xcc\xc5\x51\x61\x02\x41\x00\xc2\x12\xb3\x5d\xf5\xe5\xff\xcf"
"\x4e\x43\x83\x72\xf2\xf1\x4e\xa4\xc4\x1d\x81\xf7\xff\x40\x7e\xfa\xb5\x48"
"\x6c\xba\x1c\x8a\xec\x80\x8e\xed\xc8\x32\xa9\x8f\xd9\x30\xeb\x6e\x32\x3b"
"\xd4\x44\xcf\xd1\x1f\x6b\xe0\x37\x46\xd5\x35\xde\x79\x9d\x2c\xb9\x83\x1d"
"\x10\xdd\x02\x40\x0f\x14\x95\x96\xa0\xe2\x6c\xd4\x88\xa7\x0b\x82\x14\x10"
"\xad\x26\x0d\xe4\xa1\x5e\x01\x3d\x21\xd2\xfb\x0e\xf9\x58\xa5\xca\x1e\x21"
"\xb3\xf5\x9a\x6c\x3d\x5a\x72\xb1\x2d\xfe\xac\x09\x4f\xdd\xe5\x44\xd1\x4e"
"\xf8\x59\x85\x3a\x65\xe2\xcd\xbc\x27\x1d\x9b\x48\x9f\xb9";
// kOAEPCiphertext1 is a sample encryption of |kPlaintext| with |kKey1| using
// RSA OAEP.
static const uint8_t kOAEPCiphertext1[] =
"\x1b\x8f\x05\xf9\xca\x1a\x79\x52\x6e\x53\xf3\xcc\x51\x4f\xdb\x89\x2b\xfb"
"\x91\x93\x23\x1e\x78\xb9\x92\xe6\x8d\x50\xa4\x80\xcb\x52\x33\x89\x5c\x74"
"\x95\x8d\x5d\x02\xab\x8c\x0f\xd0\x40\xeb\x58\x44\xb0\x05\xc3\x9e\xd8\x27"
"\x4a\x9d\xbf\xa8\x06\x71\x40\x94\x39\xd2";
// kKey2 is a DER-encoded RSAPrivateKey.
static const uint8_t kKey2[] =
"\x30\x81\xfb\x02\x01\x00\x02\x33\x00\xa3\x07\x9a\x90\xdf\x0d\xfd\x72\xac"
"\x09\x0c\xcc\x2a\x78\xb8\x74\x13\x13\x3e\x40\x75\x9c\x98\xfa\xf8\x20\x4f"
"\x35\x8a\x0b\x26\x3c\x67\x70\xe7\x83\xa9\x3b\x69\x71\xb7\x37\x79\xd2\x71"
"\x7b\xe8\x34\x77\xcf\x02\x01\x03\x02\x32\x6c\xaf\xbc\x60\x94\xb3\xfe\x4c"
"\x72\xb0\xb3\x32\xc6\xfb\x25\xa2\xb7\x62\x29\x80\x4e\x68\x65\xfc\xa4\x5a"
"\x74\xdf\x0f\x8f\xb8\x41\x3b\x52\xc0\xd0\xe5\x3d\x9b\x59\x0f\xf1\x9b\xe7"
"\x9f\x49\xdd\x21\xe5\xeb\x02\x1a\x00\xcf\x20\x35\x02\x8b\x9d\x86\x98\x40"
"\xb4\x16\x66\xb4\x2e\x92\xea\x0d\xa3\xb4\x32\x04\xb5\xcf\xce\x91\x02\x1a"
"\x00\xc9\x7f\xb1\xf0\x27\xf4\x53\xf6\x34\x12\x33\xea\xaa\xd1\xd9\x35\x3f"
"\x6c\x42\xd0\x88\x66\xb1\xd0\x5f\x02\x1a\x00\x8a\x15\x78\xac\x5d\x13\xaf"
"\x10\x2b\x22\xb9\x99\xcd\x74\x61\xf1\x5e\x6d\x22\xcc\x03\x23\xdf\xdf\x0b"
"\x02\x1a\x00\x86\x55\x21\x4a\xc5\x4d\x8d\x4e\xcd\x61\x77\xf1\xc7\x36\x90"
"\xce\x2a\x48\x2c\x8b\x05\x99\xcb\xe0\x3f\x02\x1a\x00\x83\xef\xef\xb8\xa9"
"\xa4\x0d\x1d\xb6\xed\x98\xad\x84\xed\x13\x35\xdc\xc1\x08\xf3\x22\xd0\x57"
"\xcf\x8d";
// kOAEPCiphertext2 is a sample encryption of |kPlaintext| with |kKey2| using
// RSA OAEP.
static const uint8_t kOAEPCiphertext2[] =
"\x14\xbd\xdd\x28\xc9\x83\x35\x19\x23\x80\xe8\xe5\x49\xb1\x58\x2a\x8b\x40"
"\xb4\x48\x6d\x03\xa6\xa5\x31\x1f\x1f\xd5\xf0\xa1\x80\xe4\x17\x53\x03\x29"
"\xa9\x34\x90\x74\xb1\x52\x13\x54\x29\x08\x24\x52\x62\x51";
// kKey3 is a DER-encoded RSAPrivateKey.
static const uint8_t kKey3[] =
"\x30\x82\x02\x5b\x02\x01\x00\x02\x81\x81\x00\xbb\xf8\x2f\x09\x06\x82\xce"
"\x9c\x23\x38\xac\x2b\x9d\xa8\x71\xf7\x36\x8d\x07\xee\xd4\x10\x43\xa4\x40"
"\xd6\xb6\xf0\x74\x54\xf5\x1f\xb8\xdf\xba\xaf\x03\x5c\x02\xab\x61\xea\x48"
"\xce\xeb\x6f\xcd\x48\x76\xed\x52\x0d\x60\xe1\xec\x46\x19\x71\x9d\x8a\x5b"
"\x8b\x80\x7f\xaf\xb8\xe0\xa3\xdf\xc7\x37\x72\x3e\xe6\xb4\xb7\xd9\x3a\x25"
"\x84\xee\x6a\x64\x9d\x06\x09\x53\x74\x88\x34\xb2\x45\x45\x98\x39\x4e\xe0"
"\xaa\xb1\x2d\x7b\x61\xa5\x1f\x52\x7a\x9a\x41\xf6\xc1\x68\x7f\xe2\x53\x72"
"\x98\xca\x2a\x8f\x59\x46\xf8\xe5\xfd\x09\x1d\xbd\xcb\x02\x01\x11\x02\x81"
"\x81\x00\xa5\xda\xfc\x53\x41\xfa\xf2\x89\xc4\xb9\x88\xdb\x30\xc1\xcd\xf8"
"\x3f\x31\x25\x1e\x06\x68\xb4\x27\x84\x81\x38\x01\x57\x96\x41\xb2\x94\x10"
"\xb3\xc7\x99\x8d\x6b\xc4\x65\x74\x5e\x5c\x39\x26\x69\xd6\x87\x0d\xa2\xc0"
"\x82\xa9\x39\xe3\x7f\xdc\xb8\x2e\xc9\x3e\xda\xc9\x7f\xf3\xad\x59\x50\xac"
"\xcf\xbc\x11\x1c\x76\xf1\xa9\x52\x94\x44\xe5\x6a\xaf\x68\xc5\x6c\x09\x2c"
"\xd3\x8d\xc3\xbe\xf5\xd2\x0a\x93\x99\x26\xed\x4f\x74\xa1\x3e\xdd\xfb\xe1"
"\xa1\xce\xcc\x48\x94\xaf\x94\x28\xc2\xb7\xb8\x88\x3f\xe4\x46\x3a\x4b\xc8"
"\x5b\x1c\xb3\xc1\x02\x41\x00\xee\xcf\xae\x81\xb1\xb9\xb3\xc9\x08\x81\x0b"
"\x10\xa1\xb5\x60\x01\x99\xeb\x9f\x44\xae\xf4\xfd\xa4\x93\xb8\x1a\x9e\x3d"
"\x84\xf6\x32\x12\x4e\xf0\x23\x6e\x5d\x1e\x3b\x7e\x28\xfa\xe7\xaa\x04\x0a"
"\x2d\x5b\x25\x21\x76\x45\x9d\x1f\x39\x75\x41\xba\x2a\x58\xfb\x65\x99\x02"
"\x41\x00\xc9\x7f\xb1\xf0\x27\xf4\x53\xf6\x34\x12\x33\xea\xaa\xd1\xd9\x35"
"\x3f\x6c\x42\xd0\x88\x66\xb1\xd0\x5a\x0f\x20\x35\x02\x8b\x9d\x86\x98\x40"
"\xb4\x16\x66\xb4\x2e\x92\xea\x0d\xa3\xb4\x32\x04\xb5\xcf\xce\x33\x52\x52"
"\x4d\x04\x16\xa5\xa4\x41\xe7\x00\xaf\x46\x15\x03\x02\x40\x54\x49\x4c\xa6"
"\x3e\xba\x03\x37\xe4\xe2\x40\x23\xfc\xd6\x9a\x5a\xeb\x07\xdd\xdc\x01\x83"
"\xa4\xd0\xac\x9b\x54\xb0\x51\xf2\xb1\x3e\xd9\x49\x09\x75\xea\xb7\x74\x14"
"\xff\x59\xc1\xf7\x69\x2e\x9a\x2e\x20\x2b\x38\xfc\x91\x0a\x47\x41\x74\xad"
"\xc9\x3c\x1f\x67\xc9\x81\x02\x40\x47\x1e\x02\x90\xff\x0a\xf0\x75\x03\x51"
"\xb7\xf8\x78\x86\x4c\xa9\x61\xad\xbd\x3a\x8a\x7e\x99\x1c\x5c\x05\x56\xa9"
"\x4c\x31\x46\xa7\xf9\x80\x3f\x8f\x6f\x8a\xe3\x42\xe9\x31\xfd\x8a\xe4\x7a"
"\x22\x0d\x1b\x99\xa4\x95\x84\x98\x07\xfe\x39\xf9\x24\x5a\x98\x36\xda\x3d"
"\x02\x41\x00\xb0\x6c\x4f\xda\xbb\x63\x01\x19\x8d\x26\x5b\xdb\xae\x94\x23"
"\xb3\x80\xf2\x71\xf7\x34\x53\x88\x50\x93\x07\x7f\xcd\x39\xe2\x11\x9f\xc9"
"\x86\x32\x15\x4f\x58\x83\xb1\x67\xa9\x67\xbf\x40\x2b\x4e\x9e\x2e\x0f\x96"
"\x56\xe6\x98\xea\x36\x66\xed\xfb\x25\x79\x80\x39\xf7";
// kOAEPCiphertext3 is a sample encryption of |kPlaintext| with |kKey3| using
// RSA OAEP.
static const uint8_t kOAEPCiphertext3[] =
"\xb8\x24\x6b\x56\xa6\xed\x58\x81\xae\xb5\x85\xd9\xa2\x5b\x2a\xd7\x90\xc4"
"\x17\xe0\x80\x68\x1b\xf1\xac\x2b\xc3\xde\xb6\x9d\x8b\xce\xf0\xc4\x36\x6f"
"\xec\x40\x0a\xf0\x52\xa7\x2e\x9b\x0e\xff\xb5\xb3\xf2\xf1\x92\xdb\xea\xca"
"\x03\xc1\x27\x40\x05\x71\x13\xbf\x1f\x06\x69\xac\x22\xe9\xf3\xa7\x85\x2e"
"\x3c\x15\xd9\x13\xca\xb0\xb8\x86\x3a\x95\xc9\x92\x94\xce\x86\x74\x21\x49"
"\x54\x61\x03\x46\xf4\xd4\x74\xb2\x6f\x7c\x48\xb4\x2e\xe6\x8e\x1f\x57\x2a"
"\x1f\xc4\x02\x6a\xc4\x56\xb4\xf5\x9f\x7b\x62\x1e\xa1\xb9\xd8\x8f\x64\x20"
"\x2f\xb1";
static const uint8_t kTwoPrimeKey[] =
"\x30\x82\x04\xa1\x02\x01\x00\x02\x82\x01\x01\x00\x93\x3a\x4f\xc9\x6a\x0a"
"\x6b\x28\x04\xfa\xb7\x05\x56\xdf\xa0\xaa\x4f\xaa\xab\x94\xa0\xa9\x25\xef"
"\xc5\x96\xd2\xd4\x66\x16\x62\x2c\x13\x7b\x91\xd0\x36\x0a\x10\x11\x6d\x7a"
"\x91\xb6\xe4\x74\x57\xc1\x3d\x7a\xbe\x24\x05\x3a\x04\x0b\x73\x91\x53\xb1"
"\x74\x10\xe1\x87\xdc\x91\x28\x9c\x1e\xe5\xf2\xb9\xfc\xa2\x48\x34\xb6\x78"
"\xed\x6d\x95\xfb\xf2\xc0\x4e\x1c\xa4\x15\x00\x3c\x8a\x68\x2b\xd6\xce\xd5"
"\xb3\x9f\x66\x02\xa7\x0d\x08\xa3\x23\x9b\xe5\x36\x96\x13\x22\xf9\x69\xa6"
"\x87\x88\x9b\x85\x3f\x83\x9c\xab\x1a\x1b\x6d\x8d\x16\xf4\x5e\xbd\xee\x4b"
"\x59\x56\xf8\x9d\x58\xcd\xd2\x83\x85\x59\x43\x84\x63\x4f\xe6\x1a\x86\x66"
"\x0d\xb5\xa0\x87\x89\xb6\x13\x82\x43\xda\x34\x92\x3b\x68\xc4\x95\x71\x2f"
"\x15\xc2\xe0\x43\x67\x3c\x08\x00\x36\x10\xc3\xb4\x46\x4c\x4e\x6e\xf5\x44"
"\xa9\x04\x44\x9d\xce\xc7\x05\x79\xee\x11\xcf\xaf\x2c\xd7\x9a\x32\xd3\xa5"
"\x30\xd4\x3a\x78\x43\x37\x74\x22\x90\x24\x04\x11\xd7\x95\x08\x52\xa4\x71"
"\x41\x68\x94\xb0\xa0\xc3\xec\x4e\xd2\xc4\x30\x71\x98\x64\x9c\xe3\x7c\x76"
"\xef\x33\xa3\x2b\xb1\x87\x63\xd2\x5c\x09\xfc\x90\x2d\x92\xf4\x57\x02\x01"
"\x03\x02\x82\x01\x00\x62\x26\xdf\xdb\x9c\x06\xf2\x1a\xad\xfc\x7a\x03\x8f"
"\x3f\xc0\x71\x8a\x71\xc7\xb8\x6b\x1b\x6e\x9f\xd9\x0f\x37\x38\x44\x0e\xec"
"\x1d\x62\x52\x61\x35\x79\x5c\x0a\xb6\x48\xfc\x61\x24\x98\x4d\x8f\xd6\x28"
"\xfc\x7e\xc2\xae\x26\xad\x5c\xf7\xb6\x37\xcb\xa2\xb5\xeb\xaf\xe8\x60\xc5"
"\xbd\x69\xee\xa1\xd1\x53\x16\xda\xcd\xce\xfb\x48\xf3\xb9\x52\xa1\xd5\x89"
"\x68\x6d\x63\x55\x7d\xb1\x9a\xc7\xe4\x89\xe3\xcd\x14\xee\xac\x6f\x5e\x05"
"\xc2\x17\xbd\x43\x79\xb9\x62\x17\x50\xf1\x19\xaf\xb0\x67\xae\x2a\x57\xbd"
"\xc7\x66\xbc\xf3\xb3\x64\xa1\xe3\x16\x74\x9e\xea\x02\x5c\xab\x94\xd8\x97"
"\x02\x42\x0c\x2c\xba\x54\xb9\xaf\xe0\x45\x93\xad\x7f\xb3\x10\x6a\x96\x50"
"\x4b\xaf\xcf\xc8\x27\x62\x2d\x83\xe9\x26\xc6\x94\xc1\xef\x5c\x8e\x06\x42"
"\x53\xe5\x56\xaf\xc2\x99\x01\xaa\x9a\x71\xbc\xe8\x21\x33\x2a\x2d\xa3\x36"
"\xac\x1b\x86\x19\xf8\xcd\x1f\x80\xa4\x26\x98\xb8\x9f\x62\x62\xd5\x1a\x7f"
"\xee\xdb\xdf\x81\xd3\x21\xdb\x33\x92\xee\xff\xe2\x2f\x32\x77\x73\x6a\x58"
"\xab\x21\xf3\xe3\xe1\xbc\x4f\x12\x72\xa6\xb5\xc2\xfb\x27\x9e\xc8\xca\xab"
"\x64\xa0\x87\x07\x9d\xef\xca\x0f\xdb\x02\x81\x81\x00\xe6\xd3\x4d\xc0\xa1"
"\x91\x0e\x62\xfd\xb0\xdd\xc6\x30\xb8\x8c\xcb\x14\xc1\x4b\x69\x30\xdd\xcd"
"\x86\x67\xcb\x37\x14\xc5\x03\xd2\xb4\x69\xab\x3d\xe5\x16\x81\x0f\xe5\x50"
"\xf4\x18\xb1\xec\xbc\x71\xe9\x80\x99\x06\xe4\xa3\xfe\x44\x84\x4a\x2d\x1e"
"\x07\x7f\x22\x70\x6d\x4f\xd4\x93\x0b\x8b\x99\xce\x1e\xab\xcd\x4c\xd2\xd3"
"\x10\x47\x5c\x09\x9f\x6d\x82\xc0\x08\x75\xe3\x3d\x83\xc2\x19\x50\x29\xec"
"\x1f\x84\x29\xcc\xf1\x56\xee\xbd\x54\x5d\xe6\x19\xdf\x0d\x1c\xa4\xbb\x0a"
"\xfe\x84\x44\x29\x1d\xf9\x5c\x80\x96\x5b\x24\xb4\xf7\x02\x1b\x02\x81\x81"
"\x00\xa3\x48\xf1\x9c\x58\xc2\x5f\x38\xfb\xd8\x12\x39\xf1\x8e\x73\xa1\xcf"
"\x78\x12\xe0\xed\x2a\xbb\xef\xac\x23\xb2\xbf\xd6\x0c\xe9\x6e\x1e\xab\xea"
"\x3f\x68\x36\xa7\x1f\xe5\xab\xe0\x86\xa5\x76\x32\x98\xdd\x75\xb5\x2b\xbc"
"\xcb\x8a\x03\x00\x7c\x2e\xca\xf8\xbc\x19\xe4\xe3\xa3\x31\xbd\x1d\x20\x2b"
"\x09\xad\x6f\x4c\xed\x48\xd4\xdf\x87\xf9\xf0\x46\xb9\x86\x4c\x4b\x71\xe7"
"\x48\x78\xdc\xed\xc7\x82\x02\x44\xd3\xa6\xb3\x10\x5f\x62\x81\xfc\xb8\xe4"
"\x0e\xf4\x1a\xdd\xab\x3f\xbc\x63\x79\x5b\x39\x69\x5e\xea\xa9\x15\xfe\x90"
"\xec\xda\x75\x02\x81\x81\x00\x99\xe2\x33\xd5\xc1\x0b\x5e\xec\xa9\x20\x93"
"\xd9\x75\xd0\x5d\xdc\xb8\x80\xdc\xf0\xcb\x3e\x89\x04\x45\x32\x24\xb8\x83"
"\x57\xe1\xcd\x9b\xc7\x7e\x98\xb9\xab\x5f\xee\x35\xf8\x10\x76\x9d\xd2\xf6"
"\x9b\xab\x10\xaf\x43\x17\xfe\xd8\x58\x31\x73\x69\x5a\x54\xc1\xa0\x48\xdf"
"\xe3\x0c\xb2\x5d\x11\x34\x14\x72\x88\xdd\xe1\xe2\x0a\xda\x3d\x5b\xbf\x9e"
"\x57\x2a\xb0\x4e\x97\x7e\x57\xd6\xbb\x8a\xc6\x9d\x6a\x58\x1b\xdd\xf6\x39"
"\xf4\x7e\x38\x3e\x99\x66\x94\xb3\x68\x6d\xd2\x07\x54\x58\x2d\x70\xbe\xa6"
"\x3d\xab\x0e\xe7\x6d\xcd\xfa\x01\x67\x02\x81\x80\x6c\xdb\x4b\xbd\x90\x81"
"\x94\xd0\xa7\xe5\x61\x7b\xf6\x5e\xf7\xc1\x34\xfa\xb7\x40\x9e\x1c\x7d\x4a"
"\x72\xc2\x77\x2a\x8e\xb3\x46\x49\x69\xc7\xf1\x7f\x9a\xcf\x1a\x15\x43\xc7"
"\xeb\x04\x6e\x4e\xcc\x65\xe8\xf9\x23\x72\x7d\xdd\x06\xac\xaa\xfd\x74\x87"
"\x50\x7d\x66\x98\x97\xc2\x21\x28\xbe\x15\x72\x06\x73\x9f\x88\x9e\x30\x8d"
"\xea\x5a\xa6\xa0\x2f\x26\x59\x88\x32\x4b\xef\x85\xa5\xe8\x9e\x85\x01\x56"
"\xd8\x8d\x19\xcc\xb5\x94\xec\x56\xa8\x7b\x42\xb4\xa2\xbc\x93\xc7\x7f\xd2"
"\xec\xfb\x92\x26\x46\x3f\x47\x1b\x63\xff\x0b\x48\x91\xa3\x02\x81\x80\x2c"
"\x4a\xb9\xa4\x46\x7b\xff\x50\x7e\xbf\x60\x47\x3b\x2b\x66\x82\xdc\x0e\x53"
"\x65\x71\xe9\xda\x2a\xb8\x32\x93\x42\xb7\xff\xea\x67\x66\xf1\xbc\x87\x28"
"\x65\x29\x79\xca\xab\x93\x56\xda\x95\xc1\x26\x44\x3d\x27\xc1\x91\xc6\x9b"
"\xd9\xec\x9d\xb7\x49\xe7\x16\xee\x99\x87\x50\x95\x81\xd4\x5c\x5b\x5a\x5d"
"\x0a\x43\xa5\xa7\x8f\x5a\x80\x49\xa0\xb7\x10\x85\xc7\xf4\x42\x34\x86\xb6"
"\x5f\x3f\x88\x9e\xc7\xf5\x59\x29\x39\x68\x48\xf2\xd7\x08\x5b\x92\x8e\x6b"
"\xea\xa5\x63\x5f\xc0\xfb\xe4\xe1\xb2\x7d\xb7\x40\xe9\x55\x06\xbf\x58\x25"
"\x6f";
static const uint8_t kTwoPrimeEncryptedMessage[] = {
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,
};
// 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 {
const uint8_t *der;
size_t der_len;
const uint8_t *oaep_ciphertext;
size_t oaep_ciphertext_len;
} kRSAEncryptParams[] = {
{kKey1, sizeof(kKey1) - 1, kOAEPCiphertext1, sizeof(kOAEPCiphertext1) - 1},
{kKey2, sizeof(kKey2) - 1, kOAEPCiphertext2, sizeof(kOAEPCiphertext2) - 1},
{kKey3, sizeof(kKey3) - 1, kOAEPCiphertext3, sizeof(kOAEPCiphertext3) - 1},
};
class RSAEncryptTest : public testing::TestWithParam<RSAEncryptParam> {};
TEST_P(RSAEncryptTest, TestKey) {
const auto &param = GetParam();
bssl::UniquePtr<RSA> key(
RSA_private_key_from_bytes(param.der, param.der_len));
ASSERT_TRUE(key);
EXPECT_TRUE(RSA_check_key(key.get()));
uint8_t ciphertext[256];
// Test that PKCS#1 v1.5 encryption round-trips.
size_t ciphertext_len = 0;
ASSERT_TRUE(RSA_encrypt(key.get(), &ciphertext_len, ciphertext,
sizeof(ciphertext), kPlaintext, kPlaintextLen,
RSA_PKCS1_PADDING));
EXPECT_EQ(RSA_size(key.get()), ciphertext_len);
uint8_t plaintext[256];
size_t plaintext_len = 0;
ASSERT_TRUE(RSA_decrypt(key.get(), &plaintext_len, plaintext,
sizeof(plaintext), ciphertext, ciphertext_len,
RSA_PKCS1_PADDING));
EXPECT_EQ(Bytes(kPlaintext, kPlaintextLen), Bytes(plaintext, plaintext_len));
// Test that OAEP encryption round-trips.
ciphertext_len = 0;
ASSERT_TRUE(RSA_encrypt(key.get(), &ciphertext_len, ciphertext,
sizeof(ciphertext), kPlaintext, kPlaintextLen,
RSA_PKCS1_OAEP_PADDING));
EXPECT_EQ(RSA_size(key.get()), ciphertext_len);
plaintext_len = 0;
ASSERT_TRUE(RSA_decrypt(key.get(), &plaintext_len, plaintext,
sizeof(plaintext), ciphertext, ciphertext_len,
RSA_PKCS1_OAEP_PADDING));
EXPECT_EQ(Bytes(kPlaintext, kPlaintextLen), Bytes(plaintext, plaintext_len));
// |oaep_ciphertext| should decrypt to |kPlaintext|.
plaintext_len = 0;
ASSERT_TRUE(RSA_decrypt(key.get(), &plaintext_len, plaintext,
sizeof(plaintext), param.oaep_ciphertext,
param.oaep_ciphertext_len, RSA_PKCS1_OAEP_PADDING));
EXPECT_EQ(Bytes(kPlaintext, kPlaintextLen), Bytes(plaintext, plaintext_len));
// Try decrypting corrupted ciphertexts.
OPENSSL_memcpy(ciphertext, param.oaep_ciphertext, param.oaep_ciphertext_len);
for (size_t i = 0; i < param.oaep_ciphertext_len; i++) {
SCOPED_TRACE(i);
ciphertext[i] ^= 1;
EXPECT_FALSE(RSA_decrypt(
key.get(), &plaintext_len, plaintext, sizeof(plaintext), ciphertext,
param.oaep_ciphertext_len, RSA_PKCS1_OAEP_PADDING));
ERR_clear_error();
ciphertext[i] ^= 1;
}
// Test truncated ciphertexts.
for (size_t len = 0; len < param.oaep_ciphertext_len; len++) {
SCOPED_TRACE(len);
EXPECT_FALSE(RSA_decrypt(key.get(), &plaintext_len, plaintext,
sizeof(plaintext), ciphertext, len,
RSA_PKCS1_OAEP_PADDING));
ERR_clear_error();
}
}
INSTANTIATE_TEST_CASE_P(, RSAEncryptTest, testing::ValuesIn(kRSAEncryptParams));
TEST(RSATest, TestDecrypt) {
bssl::UniquePtr<RSA> rsa(
RSA_private_key_from_bytes(kTwoPrimeKey, sizeof(kTwoPrimeKey) - 1));
ASSERT_TRUE(rsa);
EXPECT_TRUE(RSA_check_key(rsa.get()));
uint8_t out[256];
size_t out_len;
ASSERT_TRUE(RSA_decrypt(
rsa.get(), &out_len, out, sizeof(out), kTwoPrimeEncryptedMessage,
sizeof(kTwoPrimeEncryptedMessage), RSA_PKCS1_PADDING));
EXPECT_EQ(Bytes("hello world"), Bytes(out, out_len));
}
TEST(RSATest, CheckFIPS) {
bssl::UniquePtr<RSA> rsa(
RSA_private_key_from_bytes(kFIPSKey, sizeof(kFIPSKey) - 1));
ASSERT_TRUE(rsa);
EXPECT_TRUE(RSA_check_key(rsa.get()));
EXPECT_TRUE(RSA_check_fips(rsa.get()));
}
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(), 512, 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, OnlyDGiven) {
static const char kN[] =
"00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd09ac42b2662"
"1cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e5808c659";
static const char kE[] = "010001";
static const char kD[] =
"0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea316eaeca21a"
"73ac365e58713195f2ae9849348525ca855386b6d028e437a9495a01";
bssl::UniquePtr<RSA> key(RSA_new());
ASSERT_TRUE(key);
ASSERT_TRUE(BN_hex2bn(&key->n, kN));
ASSERT_TRUE(BN_hex2bn(&key->e, kE));
ASSERT_TRUE(BN_hex2bn(&key->d, kD));
// Keys with only n, e, and d are functional.
EXPECT_TRUE(RSA_check_key(key.get()));
const uint8_t kDummyHash[16] = {0};
uint8_t buf[64];
unsigned buf_len = sizeof(buf);
ASSERT_LE(RSA_size(key.get()), sizeof(buf));
EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
&buf_len, key.get()));
EXPECT_TRUE(RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
buf_len, key.get()));
// Keys without the public exponent must continue to work when blinding is
// disabled to support Java's RSAPrivateKeySpec API. See
// https://bugs.chromium.org/p/boringssl/issues/detail?id=12.
bssl::UniquePtr<RSA> key2(RSA_new());
ASSERT_TRUE(key2);
ASSERT_TRUE(BN_hex2bn(&key2->n, kN));
ASSERT_TRUE(BN_hex2bn(&key2->d, kD));
key2->flags |= RSA_FLAG_NO_BLINDING;
ASSERT_LE(RSA_size(key2.get()), sizeof(buf));
EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
&buf_len, key2.get()));
// Verify the signature with |key|. |key2| has no public exponent.
EXPECT_TRUE(RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
buf_len, key.get()));
}
TEST(RSATest, RecoverCRTParams) {
bssl::UniquePtr<BIGNUM> e(BN_new());
ASSERT_TRUE(e);
ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));
bssl::UniquePtr<RSA> key1(RSA_new());
ASSERT_TRUE(key1);
ASSERT_TRUE(RSA_generate_key_ex(key1.get(), 512, e.get(), nullptr));
EXPECT_TRUE(RSA_check_key(key1.get()));
// Create a copy of the key without CRT parameters.
bssl::UniquePtr<RSA> key2(RSA_new());
ASSERT_TRUE(key2);
key2->n = BN_dup(key1->n);
key2->e = BN_dup(key1->e);
key2->d = BN_dup(key1->d);
ASSERT_TRUE(key2->n);
ASSERT_TRUE(key2->e);
ASSERT_TRUE(key2->d);
ASSERT_TRUE(RSA_recover_crt_params(key2.get()));
// The recovered RSA parameters should work.
EXPECT_TRUE(RSA_check_key(key2.get()));
uint8_t buf[128];
unsigned buf_len = sizeof(buf);
ASSERT_LE(RSA_size(key2.get()), buf_len);
const uint8_t kDummyHash[16] = {0};
EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
&buf_len, key2.get()));
EXPECT_TRUE(RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
buf_len, key2.get()));
}
TEST(RSATest, ASN1) {
// Test that private keys may be decoded.
bssl::UniquePtr<RSA> rsa(
RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1));
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, sizeof(kKey1) - 1), 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();
// But |RSA_parse_public_key_buggy| will accept it.
CBS cbs;
CBS_init(&cbs, kEstonianRSAKey, sizeof(kEstonianRSAKey));
rsa.reset(RSA_parse_public_key_buggy(&cbs));
EXPECT_TRUE(rsa);
EXPECT_EQ(0u, CBS_len(&cbs));
}
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);
EXPECT_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);
EXPECT_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);
EXPECT_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);
EXPECT_TRUE(RSA_generate_key_ex(rsa.get(), 1152, e.get(), nullptr));
EXPECT_EQ(1152u, BN_num_bits(rsa->n));
}
#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 3072-bit RSA key.
EXPECT_EQ(3072u / 2u, bits);
}
TEST(RSATest, LessThanWords) {
// kTestVectors is an array of 256-bit values in sorted order.
static const BN_ULONG kTestVectors[][256 / BN_BITS2] = {
{TOBN(0x00000000, 0x00000000), TOBN(0x00000000, 0x00000000),
TOBN(0x00000000, 0x00000000), TOBN(0x00000000, 0x00000000)},
{TOBN(0x00000000, 0x00000001), TOBN(0x00000000, 0x00000000),
TOBN(0x00000000, 0x00000000), TOBN(0x00000000, 0x00000000)},
{TOBN(0xffffffff, 0xffffffff), TOBN(0x00000000, 0x00000000),
TOBN(0x00000000, 0x00000000), TOBN(0x00000000, 0x00000000)},
{TOBN(0xffffffff, 0xffffffff), TOBN(0xffffffff, 0xffffffff),
TOBN(0x00000000, 0x00000000), TOBN(0x00000000, 0x00000000)},
{TOBN(0xffffffff, 0xffffffff), TOBN(0xffffffff, 0xffffffff),
TOBN(0xffffffff, 0xffffffff), TOBN(0x00000000, 0x00000000)},
{TOBN(0x00000000, 0x00000000), TOBN(0x1d6f60ba, 0x893ba84c),
TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484)},
{TOBN(0x00000000, 0x83339915), TOBN(0x1d6f60ba, 0x893ba84c),
TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484)},
{TOBN(0xed17ac85, 0x00000000), TOBN(0x1d6f60ba, 0x893ba84c),
TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484)},
{TOBN(0xed17ac85, 0x83339915), TOBN(0x1d6f60ba, 0x893ba84c),
TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484)},
{TOBN(0xed17ac85, 0xffffffff), TOBN(0x1d6f60ba, 0x893ba84c),
TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484)},
{TOBN(0xffffffff, 0x83339915), TOBN(0x1d6f60ba, 0x893ba84c),
TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484)},
{TOBN(0xffffffff, 0xffffffff), TOBN(0x1d6f60ba, 0x893ba84c),
TOBN(0x597d89b3, 0x754abe9f), TOBN(0xb504f333, 0xf9de6484)},
{TOBN(0x00000000, 0x00000000), TOBN(0x00000000, 0x00000000),
TOBN(0x00000000, 0x00000000), TOBN(0xffffffff, 0xffffffff)},
{TOBN(0x00000000, 0x00000000), TOBN(0x00000000, 0x00000000),
TOBN(0xffffffff, 0xffffffff), TOBN(0xffffffff, 0xffffffff)},
{TOBN(0x00000000, 0x00000001), TOBN(0x00000000, 0x00000000),
TOBN(0xffffffff, 0xffffffff), TOBN(0xffffffff, 0xffffffff)},
{TOBN(0x00000000, 0x00000000), TOBN(0xffffffff, 0xffffffff),
TOBN(0xffffffff, 0xffffffff), TOBN(0xffffffff, 0xffffffff)},
{TOBN(0xffffffff, 0xffffffff), TOBN(0xffffffff, 0xffffffff),
TOBN(0xffffffff, 0xffffffff), TOBN(0xffffffff, 0xffffffff)},
};
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTestVectors); i++) {
SCOPED_TRACE(i);
for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(kTestVectors); j++) {
SCOPED_TRACE(j);
EXPECT_EQ(i < j ? 1 : 0,
rsa_less_than_words(kTestVectors[i], kTestVectors[j],
OPENSSL_ARRAY_SIZE(kTestVectors[i])));
}
}
EXPECT_EQ(0, rsa_less_than_words(NULL, NULL, 0));
}
TEST(RSATest, GreaterThanPow2) {
bssl::UniquePtr<BIGNUM> b(BN_new());
BN_zero(b.get());
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 0));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 1));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 20));
ASSERT_TRUE(BN_set_word(b.get(), 1));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 0));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 1));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 20));
ASSERT_TRUE(BN_set_word(b.get(), 2));
EXPECT_TRUE(rsa_greater_than_pow2(b.get(), 0));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 1));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 20));
ASSERT_TRUE(BN_set_word(b.get(), 3));
EXPECT_TRUE(rsa_greater_than_pow2(b.get(), 0));
EXPECT_TRUE(rsa_greater_than_pow2(b.get(), 1));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 2));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 20));
BN_set_negative(b.get(), 1);
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 0));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 1));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 2));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), 20));
// Check all bit lengths mod 64.
for (int n = 1024; n < 1024 + 64; n++) {
SCOPED_TRACE(n);
ASSERT_TRUE(BN_set_word(b.get(), 1));
ASSERT_TRUE(BN_lshift(b.get(), b.get(), n));
EXPECT_TRUE(rsa_greater_than_pow2(b.get(), n - 1));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), n));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), n + 1));
ASSERT_TRUE(BN_sub_word(b.get(), 1));
EXPECT_TRUE(rsa_greater_than_pow2(b.get(), n - 1));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), n));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), n + 1));
ASSERT_TRUE(BN_add_word(b.get(), 2));
EXPECT_TRUE(rsa_greater_than_pow2(b.get(), n - 1));
EXPECT_TRUE(rsa_greater_than_pow2(b.get(), n));
EXPECT_FALSE(rsa_greater_than_pow2(b.get(), n + 1));
}
}
#endif // !BORINGSSL_SHARED_LIBRARY