| // Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include <openssl/rsa.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <string> | |
| #include <gtest/gtest.h> | |
| #include <openssl/bio.h> | |
| #include <openssl/bn.h> | |
| #include <openssl/bytestring.h> | |
| #include <openssl/crypto.h> | |
| #include <openssl/digest.h> | |
| #include <openssl/err.h> | |
| #include <openssl/evp.h> | |
| #include <openssl/nid.h> | |
| #include <openssl/pem.h> | |
| #include "../fipsmodule/bn/internal.h" | |
| #include "../fipsmodule/rsa/internal.h" | |
| #include "../internal.h" | |
| #include "../mem_internal.h" | |
| #include "../test/test_data.h" | |
| #include "../test/test_util.h" | |
| #if defined(OPENSSL_THREADS) | |
| #include <thread> | |
| #include <vector> | |
| #endif | |
| BSSL_NAMESPACE_BEGIN | |
| namespace { | |
| // 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 { | |
| Span<const uint8_t> der; | |
| 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 ¶m = GetParam(); | |
| 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())); | |
| 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())); | |
| 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())); | |
| 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())); | |
| // An RSA key with no e is the only type of key that has a private key but no | |
| // public key. | |
| UniquePtr<EVP_PKEY> no_e_pkey(EVP_PKEY_new()); | |
| ASSERT_TRUE(no_e_pkey); | |
| ASSERT_TRUE(EVP_PKEY_set1_RSA(no_e_pkey.get(), no_e.get())); | |
| EXPECT_FALSE(EVP_PKEY_has_public(no_e_pkey.get())); | |
| EXPECT_TRUE(EVP_PKEY_has_private(no_e_pkey.get())); | |
| 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) { | |
| 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) { | |
| 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. | |
| UniquePtr<RSA> pub( | |
| RSA_public_key_from_bytes(kKey1Public, sizeof(kKey1Public))); | |
| ASSERT_TRUE(pub); | |
| EXPECT_TRUE(RSA_check_fips(pub.get())); | |
| } | |
| TEST(RSATest, GenerateFIPS) { | |
| UniquePtr<RSA> rsa_opaque(RSA_new()); | |
| RSAImpl *rsa = FromOpaque(rsa_opaque.get()); | |
| 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, 512, nullptr)); | |
| EXPECT_FALSE(RSA_generate_key_fips(rsa, 1024, nullptr)); | |
| EXPECT_FALSE(RSA_generate_key_fips(rsa, 2047, nullptr)); | |
| EXPECT_FALSE(RSA_generate_key_fips(rsa, 2049, nullptr)); | |
| EXPECT_FALSE(RSA_generate_key_fips(rsa, 3071, nullptr)); | |
| EXPECT_FALSE(RSA_generate_key_fips(rsa, 3073, nullptr)); | |
| EXPECT_FALSE(RSA_generate_key_fips(rsa, 4095, nullptr)); | |
| EXPECT_FALSE(RSA_generate_key_fips(rsa, 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_opaque.reset(RSA_new()); | |
| rsa = FromOpaque(rsa_opaque.get()); | |
| ASSERT_TRUE(rsa); | |
| ASSERT_TRUE(RSA_generate_key_fips(rsa, bits, nullptr)); | |
| EXPECT_EQ(bits, BN_num_bits(rsa->n)); | |
| } | |
| } | |
| TEST(RSATest, BadKey) { | |
| UniquePtr<RSA> key_opaque(RSA_new()); | |
| RSAImpl *key = FromOpaque(key_opaque.get()); | |
| 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, 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)); | |
| EXPECT_FALSE(RSA_check_fips(key)); | |
| // Bad keys may not be parsed. | |
| uint8_t *der; | |
| size_t der_len; | |
| ASSERT_TRUE(RSA_private_key_to_bytes(&der, &der_len, key)); | |
| UniquePtr<uint8_t> delete_der(der); | |
| key_opaque.reset(RSA_private_key_from_bytes(der, der_len)); | |
| key = FromOpaque(key_opaque.get()); | |
| EXPECT_FALSE(key); | |
| } | |
| TEST(RSATest, ASN1) { | |
| // Test that private keys may be decoded. | |
| UniquePtr<RSA> rsa_opaque(RSA_private_key_from_bytes(kKey1, sizeof(kKey1))); | |
| RSAImpl *rsa = FromOpaque(rsa_opaque.get()); | |
| 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)); | |
| 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)); | |
| delete_der.reset(der); | |
| // Public keys may be parsed back out. | |
| rsa_opaque.reset(RSA_public_key_from_bytes(der, der_len)); | |
| rsa = FromOpaque(rsa_opaque.get()); | |
| 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)); | |
| 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); | |
| if (ok) { | |
| OPENSSL_free(der); | |
| } | |
| EXPECT_FALSE(ok); | |
| ERR_clear_error(); | |
| // Public keys with negative moduli are invalid. | |
| rsa_opaque.reset( | |
| RSA_public_key_from_bytes(kEstonianRSAKey, sizeof(kEstonianRSAKey))); | |
| rsa = FromOpaque(rsa_opaque.get()); | |
| EXPECT_FALSE(rsa); | |
| ERR_clear_error(); | |
| } | |
| TEST(RSATest, BadExponent) { | |
| UniquePtr<RSA> rsa( | |
| RSA_public_key_from_bytes(kExponent1RSAKey, sizeof(kExponent1RSAKey))); | |
| EXPECT_FALSE(rsa); | |
| ERR_clear_error(); | |
| } | |
| // Attempting to generate an funny RSA key length should round down. | |
| TEST(RSATest, RoundKeyLengths) { | |
| UniquePtr<BIGNUM> e(BN_new()); | |
| ASSERT_TRUE(e); | |
| ASSERT_TRUE(BN_set_word(e.get(), RSA_F4)); | |
| UniquePtr<RSA> rsa_opaque(RSA_new()); | |
| RSAImpl *rsa = FromOpaque(rsa_opaque.get()); | |
| ASSERT_TRUE(rsa); | |
| ASSERT_TRUE(RSA_generate_key_ex(rsa, 1025, e.get(), nullptr)); | |
| EXPECT_EQ(1024u, BN_num_bits(rsa->n)); | |
| rsa_opaque.reset(RSA_new()); | |
| rsa = FromOpaque(rsa_opaque.get()); | |
| ASSERT_TRUE(rsa); | |
| ASSERT_TRUE(RSA_generate_key_ex(rsa, 1027, e.get(), nullptr)); | |
| EXPECT_EQ(1024u, BN_num_bits(rsa->n)); | |
| rsa_opaque.reset(RSA_new()); | |
| rsa = FromOpaque(rsa_opaque.get()); | |
| ASSERT_TRUE(rsa); | |
| ASSERT_TRUE(RSA_generate_key_ex(rsa, 1151, e.get(), nullptr)); | |
| EXPECT_EQ(1024u, BN_num_bits(rsa->n)); | |
| rsa_opaque.reset(RSA_new()); | |
| rsa = FromOpaque(rsa_opaque.get()); | |
| ASSERT_TRUE(rsa); | |
| ASSERT_TRUE(RSA_generate_key_ex(rsa, 1152, e.get(), nullptr)); | |
| EXPECT_EQ(1152u, BN_num_bits(rsa->n)); | |
| } | |
| 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"; | |
| UniquePtr<RSA> rsa_opaque(RSA_new()); | |
| RSAImpl *rsa = FromOpaque(rsa_opaque.get()); | |
| ASSERT_TRUE(rsa); | |
| // Missing n or e does not pass. | |
| ASSERT_TRUE(BN_hex2bn(&rsa->n, kN)); | |
| EXPECT_FALSE(RSA_check_key(rsa)); | |
| ERR_clear_error(); | |
| BN_free(rsa->n); | |
| rsa->n = nullptr; | |
| ASSERT_TRUE(BN_hex2bn(&rsa->e, kE)); | |
| EXPECT_FALSE(RSA_check_key(rsa)); | |
| ERR_clear_error(); | |
| // Public keys pass. | |
| ASSERT_TRUE(BN_hex2bn(&rsa->n, kN)); | |
| EXPECT_TRUE(RSA_check_key(rsa)); | |
| // Configuring d also passes. | |
| ASSERT_TRUE(BN_hex2bn(&rsa->d, kD)); | |
| EXPECT_TRUE(RSA_check_key(rsa)); | |
| // p and q must be provided together. | |
| ASSERT_TRUE(BN_hex2bn(&rsa->p, kP)); | |
| EXPECT_FALSE(RSA_check_key(rsa)); | |
| ERR_clear_error(); | |
| BN_free(rsa->p); | |
| rsa->p = nullptr; | |
| ASSERT_TRUE(BN_hex2bn(&rsa->q, kQ)); | |
| EXPECT_FALSE(RSA_check_key(rsa)); | |
| ERR_clear_error(); | |
| // Supplying p and q without CRT parameters passes. | |
| ASSERT_TRUE(BN_hex2bn(&rsa->p, kP)); | |
| EXPECT_TRUE(RSA_check_key(rsa)); | |
| // 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)); | |
| 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)); | |
| 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)); | |
| // 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)); | |
| 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)); | |
| ERR_clear_error(); | |
| BN_free(rsa->dmp1); | |
| rsa->dmp1 = nullptr; | |
| ASSERT_TRUE(BN_hex2bn(&rsa->dmq1, kDMQ1)); | |
| EXPECT_FALSE(RSA_check_key(rsa)); | |
| ERR_clear_error(); | |
| BN_free(rsa->dmq1); | |
| rsa->dmq1 = nullptr; | |
| ASSERT_TRUE(BN_hex2bn(&rsa->iqmp, kIQMP)); | |
| EXPECT_FALSE(RSA_check_key(rsa)); | |
| 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)); | |
| // Incorrect CRT values are rejected. | |
| ASSERT_TRUE(BN_add_word(rsa->dmp1, 1)); | |
| EXPECT_FALSE(RSA_check_key(rsa)); | |
| 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)); | |
| 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)); | |
| 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)); | |
| 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)); | |
| 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)); | |
| ERR_clear_error(); | |
| ASSERT_TRUE(BN_sub(rsa->iqmp, rsa->iqmp, rsa->p)); | |
| } | |
| TEST(RSATest, KeygenFail) { | |
| UniquePtr<RSA> rsa_opaque(RSA_new()); | |
| RSAImpl *rsa = FromOpaque(rsa_opaque.get()); | |
| 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); | |
| 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, 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, 2048, e.get(), nullptr)); | |
| uint8_t *der; | |
| size_t der_len; | |
| ASSERT_TRUE(RSA_private_key_to_bytes(&der, &der_len, rsa)); | |
| UniquePtr<uint8_t> delete_der(der); | |
| EXPECT_FALSE(RSA_generate_key_ex(rsa, 2048, e.get(), &cb)); | |
| uint8_t *der2; | |
| size_t der2_len; | |
| ASSERT_TRUE(RSA_private_key_to_bytes(&der2, &der2_len, rsa)); | |
| 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, 2048, e.get(), nullptr)); | |
| EXPECT_TRUE(RSA_check_key(rsa)); | |
| uint8_t *der3; | |
| size_t der3_len; | |
| ASSERT_TRUE(RSA_private_key_to_bytes(&der3, &der3_len, rsa)); | |
| UniquePtr<uint8_t> delete_der3(der3); | |
| EXPECT_NE(Bytes(der, der_len), Bytes(der3, der3_len)); | |
| } | |
| TEST(RSATest, KeygenFailOnce) { | |
| 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. | |
| 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) { | |
| 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. | |
| 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. | |
| 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|. | |
| UniquePtr<RSA> key2(RSA_private_key_from_bytes(kKey2, sizeof(kKey2))); | |
| ASSERT_TRUE(key2); | |
| auto copy_rsa_fields = [](RSA *dst, const RSA *src) { | |
| UniquePtr<BIGNUM> n(BN_dup(RSA_get0_n(src))); | |
| ASSERT_TRUE(n); | |
| UniquePtr<BIGNUM> e(BN_dup(RSA_get0_e(src))); | |
| ASSERT_TRUE(e); | |
| UniquePtr<BIGNUM> d(BN_dup(RSA_get0_d(src))); | |
| ASSERT_TRUE(d); | |
| UniquePtr<BIGNUM> p(BN_dup(RSA_get0_p(src))); | |
| ASSERT_TRUE(p); | |
| UniquePtr<BIGNUM> q(BN_dup(RSA_get0_q(src))); | |
| ASSERT_TRUE(q); | |
| UniquePtr<BIGNUM> dmp1(BN_dup(RSA_get0_dmp1(src))); | |
| ASSERT_TRUE(dmp1); | |
| UniquePtr<BIGNUM> dmq1(BN_dup(RSA_get0_dmq1(src))); | |
| ASSERT_TRUE(dmq1); | |
| 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) { | |
| 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. | |
| 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())); | |
| EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_RSA, RSA_R_VALUE_MISSING)); | |
| size_t len; | |
| EXPECT_FALSE(RSA_decrypt(rsa.get(), &len, out.data(), out.size(), | |
| kOAEPCiphertext1, sizeof(kOAEPCiphertext1), | |
| RSA_PKCS1_OAEP_PADDING)); | |
| EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_RSA, RSA_R_VALUE_MISSING)); | |
| // 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())); | |
| EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_RSA, RSA_R_VALUE_MISSING)); | |
| EXPECT_FALSE(RSA_encrypt(rsa.get(), &len, out.data(), out.size(), kPlaintext, | |
| sizeof(kPlaintext), RSA_PKCS1_OAEP_PADDING)); | |
| EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_RSA, RSA_R_VALUE_MISSING)); | |
| } | |
| TEST(RSATest, Negative) { | |
| auto dup_neg = [](const BIGNUM *bn) -> UniquePtr<BIGNUM> { | |
| UniquePtr<BIGNUM> ret(BN_dup(bn)); | |
| if (!ret) { | |
| return nullptr; | |
| } | |
| BN_set_negative(ret.get(), 1); | |
| return ret; | |
| }; | |
| UniquePtr<RSA> key(RSA_private_key_from_bytes(kKey1, sizeof(kKey1))); | |
| ASSERT_TRUE(key); | |
| const BIGNUM *n = RSA_get0_n(key.get()); | |
| UniquePtr<BIGNUM> neg_n = dup_neg(n); | |
| ASSERT_TRUE(neg_n); | |
| const BIGNUM *e = RSA_get0_e(key.get()); | |
| UniquePtr<BIGNUM> neg_e = dup_neg(e); | |
| ASSERT_TRUE(neg_e); | |
| const BIGNUM *d = RSA_get0_d(key.get()); | |
| UniquePtr<BIGNUM> neg_d = dup_neg(d); | |
| ASSERT_TRUE(neg_d); | |
| const BIGNUM *p = RSA_get0_p(key.get()); | |
| UniquePtr<BIGNUM> neg_p = dup_neg(p); | |
| ASSERT_TRUE(neg_p); | |
| const BIGNUM *q = RSA_get0_q(key.get()); | |
| UniquePtr<BIGNUM> neg_q = dup_neg(q); | |
| ASSERT_TRUE(neg_q); | |
| const BIGNUM *dmp1 = RSA_get0_dmp1(key.get()); | |
| UniquePtr<BIGNUM> neg_dmp1 = dup_neg(dmp1); | |
| ASSERT_TRUE(neg_dmp1); | |
| const BIGNUM *dmq1 = RSA_get0_dmq1(key.get()); | |
| UniquePtr<BIGNUM> neg_dmq1 = dup_neg(dmq1); | |
| ASSERT_TRUE(neg_dmq1); | |
| const BIGNUM *iqmp = RSA_get0_iqmp(key.get()); | |
| 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. | |
| UniquePtr<RSA> key_opaque(RSA_private_key_from_bytes(kKey1, sizeof(kKey1))); | |
| RSAImpl *key = FromOpaque(key_opaque.get()); | |
| ASSERT_TRUE(key); | |
| const BIGNUM *n = RSA_get0_n(key); | |
| const BIGNUM *e = RSA_get0_e(key); | |
| const BIGNUM *d = RSA_get0_d(key); | |
| const BIGNUM *p = RSA_get0_p(key); | |
| const BIGNUM *q = RSA_get0_q(key); | |
| const BIGNUM *iqmp = RSA_get0_iqmp(key); | |
| // By default, the large exponent is not allowed as e. | |
| UniquePtr<RSA> pub(RSA_new_public_key(n, /*e=*/d)); | |
| EXPECT_FALSE(pub); | |
| UniquePtr<RSA> priv_opaque(RSA_new_private_key(n, /*e=*/d, /*d=*/e, p, q, | |
| /*dmp1=*/e, /*dmq1=*/e, iqmp)); | |
| RSAImpl *priv = FromOpaque(priv_opaque.get()); | |
| 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_opaque.reset(RSA_new()); | |
| priv = FromOpaque(priv_opaque.get()); | |
| 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)); | |
| size_t len; | |
| EXPECT_FALSE(RSA_sign_pss_mgf1(priv, &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_opaque.reset(RSA_new_private_key_large_e(n, /*e=*/d, /*d=*/e, p, q, | |
| /*dmp1=*/e, | |
| /*dmq1=*/e, iqmp)); | |
| priv = FromOpaque(priv_opaque.get()); | |
| ASSERT_TRUE(priv); | |
| // Test that operations work correctly. | |
| sig.resize(RSA_size(priv)); | |
| ASSERT_TRUE(RSA_sign_pss_mgf1(priv, &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. | |
| 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(RSATest, KeyLimits) { | |
| auto read_private_key = [](const char *path) -> UniquePtr<RSA> { | |
| std::string data = GetTestData(path); | |
| UniquePtr<BIO> bio(BIO_new_mem_buf(data.data(), data.size())); | |
| if (!bio) { | |
| return nullptr; | |
| } | |
| return UniquePtr<RSA>( | |
| PEM_read_bio_RSAPrivateKey(bio.get(), nullptr, nullptr, nullptr)); | |
| }; | |
| auto read_public_key = [](const char *path) -> UniquePtr<RSA> { | |
| std::string data = GetTestData(path); | |
| UniquePtr<BIO> bio(BIO_new_mem_buf(data.data(), data.size())); | |
| if (!bio) { | |
| return nullptr; | |
| } | |
| return UniquePtr<RSA>( | |
| PEM_read_bio_RSA_PUBKEY(bio.get(), nullptr, nullptr, nullptr)); | |
| }; | |
| auto generate_key = [](unsigned bits) -> bssl::UniquePtr<RSA> { | |
| bssl::UniquePtr<RSA> rsa(RSA_new()); | |
| bssl::UniquePtr<BIGNUM> e(BN_new()); | |
| if (!rsa || !e || !BN_set_word(e.get(), RSA_F4) || | |
| !RSA_generate_key_ex(rsa.get(), bits, e.get(), nullptr)) { | |
| return nullptr; | |
| } | |
| return rsa; | |
| }; | |
| // We support RSA-512 through RSA-16384. | |
| // | |
| // TODO(crbug.com/42290480): Raise the lower bound. 512-bit RSA was factored | |
| // in 1999. | |
| EXPECT_FALSE(generate_key(511u)); | |
| EXPECT_TRUE( | |
| ErrorEquals(ERR_get_error(), ERR_LIB_RSA, RSA_R_KEY_SIZE_TOO_SMALL)); | |
| EXPECT_FALSE(read_private_key("crypto/rsa/test/rsa511.pem")); | |
| EXPECT_FALSE(read_public_key("crypto/rsa/test/rsa511pub.pem")); | |
| UniquePtr<RSA> rsa = read_private_key("crypto/rsa/test/rsa512.pem"); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 512u); | |
| rsa = read_public_key("crypto/rsa/test/rsa512pub.pem"); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 512u); | |
| rsa = generate_key(512u); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 512u); | |
| // RSA-8192 and up take too long to generate, so skip keygen tests. | |
| rsa = read_private_key("crypto/rsa/test/rsa8192.pem"); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 8192u); | |
| rsa = read_public_key("crypto/rsa/test/rsa8192pub.pem"); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 8192u); | |
| rsa = read_private_key("crypto/rsa/test/rsa8193.pem"); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 8193u); | |
| rsa = read_public_key("crypto/rsa/test/rsa8193pub.pem"); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 8193u); | |
| rsa = read_private_key("crypto/rsa/test/rsa16384.pem"); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 16384u); | |
| rsa = read_public_key("crypto/rsa/test/rsa16384pub.pem"); | |
| ASSERT_TRUE(rsa); | |
| EXPECT_EQ(RSA_bits(rsa.get()), 16384u); | |
| EXPECT_FALSE(read_private_key("crypto/rsa/test/rsa16385.pem")); | |
| EXPECT_FALSE(read_public_key("crypto/rsa/test/rsa16385pub.pem")); | |
| EXPECT_FALSE(generate_key(16385u)); | |
| } | |
| #if defined(OPENSSL_THREADS) | |
| TEST(RSATest, Threads) { | |
| UniquePtr<RSA> rsa_template_opaque( | |
| RSA_private_key_from_bytes(kKey1, sizeof(kKey1))); | |
| RSAImpl *rsa_template = FromOpaque(rsa_template_opaque.get()); | |
| ASSERT_TRUE(rsa_template); | |
| const uint8_t kDummyHash[32] = {0}; | |
| std::vector<uint8_t> sig(RSA_size(rsa_template)); | |
| unsigned sig_len; | |
| EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig.data(), | |
| &sig_len, rsa_template)); | |
| 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. | |
| UniquePtr<RSA> rsa_opaque(RSA_new()); | |
| RSAImpl *rsa = FromOpaque(rsa_opaque.get()); | |
| 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, nullptr, nullptr, &d); | |
| EXPECT_EQ(0, BN_cmp(d, rsa_template->d)); | |
| }; | |
| auto sign = [&] { | |
| std::vector<uint8_t> sig2(RSA_size(rsa)); | |
| unsigned sig2_len; | |
| EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), | |
| sig2.data(), &sig2_len, rsa)); | |
| 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)); | |
| }; | |
| 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(); | |
| } | |
| } | |
| #endif // THREADS | |
| } // namespace | |
| BSSL_NAMESPACE_END |