summaryrefslogtreecommitdiffstats
path: root/src/crypto/rsa
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/rsa')
-rw-r--r--src/crypto/rsa/padding.c191
-rw-r--r--src/crypto/rsa/rsa.c14
-rw-r--r--src/crypto/rsa/rsa_asn1.c8
-rw-r--r--src/crypto/rsa/rsa_impl.c2
-rw-r--r--src/crypto/rsa/rsa_test.cc44
5 files changed, 139 insertions, 120 deletions
diff --git a/src/crypto/rsa/padding.c b/src/crypto/rsa/padding.c
index 5a42e24..032df2e 100644
--- a/src/crypto/rsa/padding.c
+++ b/src/crypto/rsa/padding.c
@@ -56,6 +56,7 @@
#include <openssl/rsa.h>
#include <assert.h>
+#include <limits.h>
#include <string.h>
#include <openssl/digest.h>
@@ -65,20 +66,21 @@
#include <openssl/sha.h>
#include "internal.h"
+#include "../internal.h"
/* TODO(fork): don't the check functions have to be constant time? */
-int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned tlen,
- const uint8_t *from, unsigned flen) {
+int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len) {
unsigned j;
uint8_t *p;
- if (tlen < RSA_PKCS1_PADDING_SIZE) {
+ if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
- if (flen > tlen - RSA_PKCS1_PADDING_SIZE) {
+ if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
@@ -89,20 +91,20 @@ int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned tlen,
*(p++) = 1; /* Private Key BT (Block Type) */
/* pad out with 0xff data */
- j = tlen - 3 - flen;
+ j = to_len - 3 - from_len;
memset(p, 0xff, j);
p += j;
*(p++) = 0;
- memcpy(p, from, (unsigned int)flen);
+ memcpy(p, from, (unsigned int)from_len);
return 1;
}
-int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned tlen,
- const uint8_t *from, unsigned flen) {
+int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len) {
unsigned i, j;
const uint8_t *p;
- if (flen < 2) {
+ if (from_len < 2) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL);
return -1;
}
@@ -114,7 +116,7 @@ int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned tlen,
}
/* scan over padding data */
- j = flen - 2; /* one for leading 00, one for type. */
+ j = from_len - 2; /* one for leading 00, one for type. */
for (i = 0; i < j; i++) {
/* should decrypt to 0xff */
if (*p != 0xff) {
@@ -140,7 +142,7 @@ int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned tlen,
}
i++; /* Skip over the '\0' */
j -= i;
- if (j > tlen) {
+ if (j > to_len) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
return -1;
}
@@ -149,17 +151,17 @@ int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned tlen,
return j;
}
-int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned tlen,
- const uint8_t *from, unsigned flen) {
+int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len) {
unsigned i, j;
uint8_t *p;
- if (tlen < RSA_PKCS1_PADDING_SIZE) {
+ if (to_len < RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
- if (flen > tlen - RSA_PKCS1_PADDING_SIZE) {
+ if (from_len > to_len - RSA_PKCS1_PADDING_SIZE) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
@@ -170,7 +172,7 @@ int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned tlen,
*(p++) = 2; /* Public Key BT (Block Type) */
/* pad out with non-zero random data */
- j = tlen - 3 - flen;
+ j = to_len - 3 - from_len;
if (!RAND_bytes(p, j)) {
return 0;
@@ -187,116 +189,89 @@ int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned tlen,
*(p++) = 0;
- memcpy(p, from, (unsigned int)flen);
+ memcpy(p, from, (unsigned int)from_len);
return 1;
}
-/* constant_time_byte_eq returns 1 if |x| == |y| and 0 otherwise. */
-static int constant_time_byte_eq(unsigned char a, unsigned char b) {
- unsigned char z = ~(a ^ b);
- z &= z >> 4;
- z &= z >> 2;
- z &= z >> 1;
-
- return z;
-}
-
-/* constant_time_select returns |x| if |v| is 1 and |y| if |v| is 0.
- * Its behavior is undefined if |v| takes any other value. */
-static int constant_time_select(int v, int x, int y) {
- return ((~(v - 1)) & x) | ((v - 1) & y);
-}
-
-/* constant_time_le returns 1 if |x| <= |y| and 0 otherwise.
- * |x| and |y| must be positive. */
-static int constant_time_le(int x, int y) {
- return ((x - y - 1) >> (sizeof(int) * 8 - 1)) & 1;
-}
-
-int RSA_message_index_PKCS1_type_2(const uint8_t *from, size_t from_len,
- size_t *out_index) {
- size_t i;
- int first_byte_is_zero, second_byte_is_two, looking_for_index;
- int valid_index, zero_index = 0;
+int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len) {
+ if (from_len == 0) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
+ return -1;
+ }
/* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
* Standard", section 7.2.2. */
if (from_len < RSA_PKCS1_PADDING_SIZE) {
/* |from| is zero-padded to the size of the RSA modulus, a public value, so
* this can be rejected in non-constant time. */
- *out_index = 0;
- return 0;
+ OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+ return -1;
}
- first_byte_is_zero = constant_time_byte_eq(from[0], 0);
- second_byte_is_two = constant_time_byte_eq(from[1], 2);
+ unsigned first_byte_is_zero = constant_time_eq(from[0], 0);
+ unsigned second_byte_is_two = constant_time_eq(from[1], 2);
- looking_for_index = 1;
+ unsigned i, zero_index = 0, looking_for_index = ~0u;
for (i = 2; i < from_len; i++) {
- int equals0 = constant_time_byte_eq(from[i], 0);
- zero_index =
- constant_time_select(looking_for_index & equals0, i, zero_index);
+ unsigned equals0 = constant_time_is_zero(from[i]);
+ zero_index = constant_time_select(looking_for_index & equals0, (unsigned)i,
+ zero_index);
looking_for_index = constant_time_select(equals0, 0, looking_for_index);
}
/* The input must begin with 00 02. */
- valid_index = first_byte_is_zero;
+ unsigned valid_index = first_byte_is_zero;
valid_index &= second_byte_is_two;
/* We must have found the end of PS. */
valid_index &= ~looking_for_index;
/* PS must be at least 8 bytes long, and it starts two bytes into |from|. */
- valid_index &= constant_time_le(2 + 8, zero_index);
+ valid_index &= constant_time_ge(zero_index, 2 + 8);
/* Skip the zero byte. */
zero_index++;
- *out_index = constant_time_select(valid_index, zero_index, 0);
- return valid_index;
-}
-
-int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned tlen,
- const uint8_t *from, unsigned flen) {
- size_t msg_index, msg_len;
-
- if (flen == 0) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
+ /* NOTE: Although this logic attempts to be constant time, the API contracts
+ * of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it
+ * impossible to completely avoid Bleichenbacher's attack. Consumers should
+ * use |RSA_unpad_key_pkcs1|. */
+ if (!valid_index) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
return -1;
}
- /* NOTE: Although |RSA_message_index_PKCS1_type_2| itself is constant time,
- * the API contracts of this function and |RSA_decrypt| with
- * |RSA_PKCS1_PADDING| make it impossible to completely avoid Bleichenbacher's
- * attack. */
- if (!RSA_message_index_PKCS1_type_2(from, flen, &msg_index)) {
+ const unsigned msg_len = from_len - zero_index;
+ if (msg_len > to_len) {
+ /* This shouldn't happen because this function is always called with
+ * |to_len| as the key size and |from_len| is bounded by the key size. */
OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
return -1;
}
- msg_len = flen - msg_index;
- if (msg_len > tlen) {
- /* This shouldn't happen because this function is always called with |tlen|
- * the key size and |flen| is bounded by the key size. */
- OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
+ if (msg_len > INT_MAX) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
return -1;
}
- memcpy(to, &from[msg_index], msg_len);
- return msg_len;
+
+ memcpy(to, &from[zero_index], msg_len);
+ return (int)msg_len;
}
-int RSA_padding_add_none(uint8_t *to, unsigned tlen, const uint8_t *from, unsigned flen) {
- if (flen > tlen) {
+int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
+ unsigned from_len) {
+ if (from_len > to_len) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
- if (flen < tlen) {
+ if (from_len < to_len) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE);
return 0;
}
- memcpy(to, from, (unsigned int)flen);
+ memcpy(to, from, (unsigned int)from_len);
return 1;
}
@@ -319,7 +294,8 @@ int PKCS1_MGF1(uint8_t *mask, unsigned len, const uint8_t *seed,
cnt[2] = (uint8_t)((i >> 8)) & 255;
cnt[3] = (uint8_t)(i & 255);
if (!EVP_DigestInit_ex(&c, dgst, NULL) ||
- !EVP_DigestUpdate(&c, seed, seedlen) || !EVP_DigestUpdate(&c, cnt, 4)) {
+ !EVP_DigestUpdate(&c, seed, seedlen) ||
+ !EVP_DigestUpdate(&c, cnt, 4)) {
goto err;
}
@@ -343,9 +319,9 @@ err:
return ret;
}
-int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
- const uint8_t *from, unsigned flen,
- const uint8_t *param, unsigned plen,
+int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len,
+ const uint8_t *param, unsigned param_len,
const EVP_MD *md, const EVP_MD *mgf1md) {
unsigned i, emlen, mdlen;
uint8_t *db, *seed;
@@ -361,13 +337,13 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
mdlen = EVP_MD_size(md);
- if (tlen < 2 * mdlen + 2) {
+ if (to_len < 2 * mdlen + 2) {
OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
- emlen = tlen - 1;
- if (flen > emlen - 2 * mdlen - 1) {
+ emlen = to_len - 1;
+ if (from_len > emlen - 2 * mdlen - 1) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
@@ -381,12 +357,12 @@ int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
seed = to + 1;
db = to + mdlen + 1;
- if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL)) {
+ if (!EVP_Digest((void *)param, param_len, db, NULL, md, NULL)) {
return 0;
}
- memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
- db[emlen - flen - mdlen - 1] = 0x01;
- memcpy(db + emlen - flen - mdlen, from, flen);
+ memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1);
+ db[emlen - from_len - mdlen - 1] = 0x01;
+ memcpy(db + emlen - from_len - mdlen, from, from_len);
if (!RAND_bytes(seed, mdlen)) {
return 0;
}
@@ -417,14 +393,13 @@ out:
return ret;
}
-int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
- const uint8_t *from, unsigned flen,
- const uint8_t *param, unsigned plen,
+int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
+ const uint8_t *from, unsigned from_len,
+ const uint8_t *param, unsigned param_len,
const EVP_MD *md, const EVP_MD *mgf1md) {
- unsigned i, dblen, mlen = -1, mdlen;
+ unsigned i, dblen, mlen = -1, mdlen, bad, looking_for_one_byte, one_index = 0;
const uint8_t *maskeddb, *maskedseed;
uint8_t *db = NULL, seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE];
- int bad, looking_for_one_byte, one_index = 0;
if (md == NULL) {
md = EVP_sha1();
@@ -438,13 +413,13 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
/* The encoded message is one byte smaller than the modulus to ensure that it
* doesn't end up greater than the modulus. Thus there's an extra "+1" here
* compared to https://tools.ietf.org/html/rfc2437#section-9.1.1.2. */
- if (flen < 1 + 2*mdlen + 1) {
- /* 'flen' is the length of the modulus, i.e. does not depend on the
+ if (from_len < 1 + 2*mdlen + 1) {
+ /* 'from_len' is the length of the modulus, i.e. does not depend on the
* particular ciphertext. */
goto decoding_err;
}
- dblen = flen - mdlen - 1;
+ dblen = from_len - mdlen - 1;
db = OPENSSL_malloc(dblen);
if (db == NULL) {
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
@@ -468,19 +443,19 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
db[i] ^= maskeddb[i];
}
- if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL)) {
+ if (!EVP_Digest((void *)param, param_len, phash, NULL, md, NULL)) {
goto err;
}
- bad = CRYPTO_memcmp(db, phash, mdlen);
- bad |= from[0];
+ bad = ~constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen));
+ bad |= ~constant_time_is_zero(from[0]);
- looking_for_one_byte = 1;
+ looking_for_one_byte = ~0u;
for (i = mdlen; i < dblen; i++) {
- int equals1 = constant_time_byte_eq(db[i], 1);
- int equals0 = constant_time_byte_eq(db[i], 0);
- one_index =
- constant_time_select(looking_for_one_byte & equals1, i, one_index);
+ unsigned equals1 = constant_time_eq(db[i], 1);
+ unsigned equals0 = constant_time_eq(db[i], 0);
+ one_index = constant_time_select(looking_for_one_byte & equals1, i,
+ one_index);
looking_for_one_byte =
constant_time_select(equals1, 0, looking_for_one_byte);
bad |= looking_for_one_byte & ~equals0;
@@ -494,7 +469,7 @@ int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned tlen,
one_index++;
mlen = dblen - one_index;
- if (tlen < mlen) {
+ if (to_len < mlen) {
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
mlen = -1;
} else {
diff --git a/src/crypto/rsa/rsa.c b/src/crypto/rsa/rsa.c
index 49ab27b..6c28ad7 100644
--- a/src/crypto/rsa/rsa.c
+++ b/src/crypto/rsa/rsa.c
@@ -96,13 +96,7 @@ RSA *RSA_new_method(const ENGINE *engine) {
rsa->references = 1;
rsa->flags = rsa->meth->flags;
CRYPTO_MUTEX_init(&rsa->lock);
-
- if (!CRYPTO_new_ex_data(&g_ex_data_class, rsa, &rsa->ex_data)) {
- CRYPTO_MUTEX_cleanup(&rsa->lock);
- METHOD_unref(rsa->meth);
- OPENSSL_free(rsa);
- return NULL;
- }
+ CRYPTO_new_ex_data(&rsa->ex_data);
if (rsa->meth->init && !rsa->meth->init(rsa)) {
CRYPTO_free_ex_data(&g_ex_data_class, rsa, &rsa->ex_data);
@@ -308,11 +302,11 @@ int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) {
return 1;
}
-int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
int index;
- if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, new_func,
- dup_func, free_func)) {
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp, dup_func,
+ free_func)) {
return -1;
}
return index;
diff --git a/src/crypto/rsa/rsa_asn1.c b/src/crypto/rsa/rsa_asn1.c
index 6144e74..b73a0e1 100644
--- a/src/crypto/rsa/rsa_asn1.c
+++ b/src/crypto/rsa/rsa_asn1.c
@@ -108,6 +108,14 @@ static RSA *parse_public_key(CBS *cbs, int buggy) {
RSA_free(ret);
return NULL;
}
+
+ if (!BN_is_odd(ret->e) ||
+ BN_num_bits(ret->e) < 2) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS);
+ RSA_free(ret);
+ return NULL;
+ }
+
return ret;
}
diff --git a/src/crypto/rsa/rsa_impl.c b/src/crypto/rsa/rsa_impl.c
index bee7f22..b1cfaa6 100644
--- a/src/crypto/rsa/rsa_impl.c
+++ b/src/crypto/rsa/rsa_impl.c
@@ -636,7 +636,7 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
BIGNUM *p = NULL, *q = NULL;
/* Make sure BN_mod_inverse in Montgomery intialization uses the
- * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set) */
+ * BN_FLG_CONSTTIME flag. */
BN_init(&local_p);
p = &local_p;
BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
diff --git a/src/crypto/rsa/rsa_test.cc b/src/crypto/rsa/rsa_test.cc
index 57b360c..5545161 100644
--- a/src/crypto/rsa/rsa_test.cc
+++ b/src/crypto/rsa/rsa_test.cc
@@ -495,6 +495,34 @@ static const uint8_t kEstonianRSAKey[] = {
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,
+};
+
static bool TestRSA(const uint8_t *der, size_t der_len,
const uint8_t *oaep_ciphertext,
size_t oaep_ciphertext_len) {
@@ -845,6 +873,19 @@ static bool TestASN1() {
return true;
}
+static bool TestBadExponent() {
+ ScopedRSA rsa(RSA_public_key_from_bytes(kExponent1RSAKey,
+ sizeof(kExponent1RSAKey)));
+
+ if (rsa) {
+ fprintf(stderr, "kExponent1RSAKey parsed but should have failed.\n");
+ return false;
+ }
+
+ ERR_clear_error();
+ return true;
+}
+
int main(int argc, char *argv[]) {
CRYPTO_library_init();
@@ -867,7 +908,8 @@ int main(int argc, char *argv[]) {
kSixPrimeEncryptedMessage,
sizeof(kSixPrimeEncryptedMessage)) ||
!TestMultiPrimeKeygen() ||
- !TestASN1()) {
+ !TestASN1() ||
+ !TestBadExponent()) {
return 1;
}