Switch RSA_sign to size_t.
While I'm here, use a fixed-size uint64_t in RSA_generate_key, rather
than unsigned long. This code also assumes unsigned long fits in
BN_ULONG, which is probably true on all platforms we care about, but
unnecessarily fussy.
The RSA_sign -> RSA_METHOD transition does require a cast. Go ahead and
check length/hash_nid consistency so we know it fits in the cast. This
does mean RSA_METHOD-backed keys are restricted to implementing digests
that we support, but that's probably fine. If anything, I think we
should try to shift away from RSA_METHOD as a story for custom keys.
Bug: 516
Change-Id: I3969da67d1daeff882279a534eb48ca831eb16cd
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/54465
Commit-Queue: Bob Beck <bbe@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/crypto/fipsmodule/rsa/internal.h b/crypto/fipsmodule/rsa/internal.h
index 1cb3b5f..d0b5a4a 100644
--- a/crypto/fipsmodule/rsa/internal.h
+++ b/crypto/fipsmodule/rsa/internal.h
@@ -142,7 +142,7 @@
size_t in_len, int padding);
int rsa_sign_no_self_test(int hash_nid, const uint8_t *digest,
- unsigned digest_len, uint8_t *out, unsigned *out_len,
+ size_t digest_len, uint8_t *out, unsigned *out_len,
RSA *rsa);
diff --git a/crypto/fipsmodule/rsa/rsa.c b/crypto/fipsmodule/rsa/rsa.c
index 14cdae5..6b3e228 100644
--- a/crypto/fipsmodule/rsa/rsa.c
+++ b/crypto/fipsmodule/rsa/rsa.c
@@ -56,6 +56,7 @@
#include <openssl/rsa.h>
+#include <assert.h>
#include <limits.h>
#include <string.h>
@@ -470,18 +471,43 @@
},
};
-int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len,
- int *is_alloced, int hash_nid, const uint8_t *digest,
- size_t digest_len) {
+static int rsa_check_digest_size(int hash_nid, size_t digest_len) {
if (hash_nid == NID_md5_sha1) {
- // Special case: SSL signature, just check the length.
if (digest_len != SSL_SIG_LENGTH) {
OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
return 0;
}
+ return 1;
+ }
+ for (size_t i = 0; kPKCS1SigPrefixes[i].nid != NID_undef; i++) {
+ const struct pkcs1_sig_prefix *sig_prefix = &kPKCS1SigPrefixes[i];
+ if (sig_prefix->nid == hash_nid) {
+ if (digest_len != sig_prefix->hash_len) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
+ return 0;
+ }
+ return 1;
+ }
+ }
+
+ OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+
+}
+
+int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len,
+ int *is_alloced, int hash_nid, const uint8_t *digest,
+ size_t digest_len) {
+ if (!rsa_check_digest_size(hash_nid, digest_len)) {
+ return 0;
+ }
+
+ if (hash_nid == NID_md5_sha1) {
+ // The length should already have been checked.
+ assert(digest_len == SSL_SIG_LENGTH);
*out_msg = (uint8_t *)digest;
- *out_msg_len = SSL_SIG_LENGTH;
+ *out_msg_len = digest_len;
*is_alloced = 0;
return 1;
}
@@ -492,11 +518,8 @@
continue;
}
- if (digest_len != sig_prefix->hash_len) {
- OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
- return 0;
- }
-
+ // The length should already have been checked.
+ assert(digest_len == sig_prefix->hash_len);
const uint8_t* prefix = sig_prefix->bytes;
size_t prefix_len = sig_prefix->len;
size_t signed_msg_len = prefix_len + digest_len;
@@ -526,19 +549,25 @@
}
int rsa_sign_no_self_test(int hash_nid, const uint8_t *digest,
- unsigned digest_len, uint8_t *out, unsigned *out_len,
+ size_t digest_len, uint8_t *out, unsigned *out_len,
RSA *rsa) {
+ if (rsa->meth->sign) {
+ if (!rsa_check_digest_size(hash_nid, digest_len)) {
+ return 0;
+ }
+ // All supported digest lengths fit in |unsigned|.
+ assert(digest_len <= EVP_MAX_MD_SIZE);
+ static_assert(EVP_MAX_MD_SIZE <= UINT_MAX, "digest too long");
+ return rsa->meth->sign(hash_nid, digest, (unsigned)digest_len, out, out_len,
+ rsa);
+ }
+
const unsigned rsa_size = RSA_size(rsa);
int ret = 0;
uint8_t *signed_msg = NULL;
size_t signed_msg_len = 0;
int signed_msg_is_alloced = 0;
size_t size_t_out_len;
-
- if (rsa->meth->sign) {
- return rsa->meth->sign(hash_nid, digest, digest_len, out, out_len, rsa);
- }
-
if (!RSA_add_pkcs1_prefix(&signed_msg, &signed_msg_len,
&signed_msg_is_alloced, hash_nid, digest,
digest_len) ||
@@ -563,7 +592,7 @@
return ret;
}
-int RSA_sign(int hash_nid, const uint8_t *digest, unsigned digest_len,
+int RSA_sign(int hash_nid, const uint8_t *digest, size_t digest_len,
uint8_t *out, unsigned *out_len, RSA *rsa) {
boringssl_ensure_rsa_self_test();
diff --git a/decrepit/rsa/rsa_decrepit.c b/decrepit/rsa/rsa_decrepit.c
index 54be9b2..2c06fe3 100644
--- a/decrepit/rsa/rsa_decrepit.c
+++ b/decrepit/rsa/rsa_decrepit.c
@@ -61,7 +61,7 @@
#include <openssl/bn.h>
-RSA *RSA_generate_key(int bits, unsigned long e_value, void *callback,
+RSA *RSA_generate_key(int bits, uint64_t e_value, void *callback,
void *cb_arg) {
assert(callback == NULL);
assert(cb_arg == NULL);
@@ -71,7 +71,7 @@
if (rsa == NULL ||
e == NULL ||
- !BN_set_word(e, e_value) ||
+ !BN_set_u64(e, e_value) ||
!RSA_generate_key_ex(rsa, bits, e, NULL)) {
goto err;
}
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index 57a2cb2..15ce1c7 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -298,8 +298,8 @@
// |hash_nid|. Passing unhashed inputs will not result in a secure signature
// scheme.
OPENSSL_EXPORT int RSA_sign(int hash_nid, const uint8_t *digest,
- unsigned digest_len, uint8_t *out,
- unsigned *out_len, RSA *rsa);
+ size_t digest_len, uint8_t *out, unsigned *out_len,
+ RSA *rsa);
// RSA_sign_pss_mgf1 signs |digest_len| bytes from |digest| with the public key
// from |rsa| using RSASSA-PSS with MGF1 as the mask generation function. It
@@ -625,7 +625,7 @@
// should use instead. It returns NULL on error, or a newly-allocated |RSA| on
// success. This function is provided for compatibility only. The |callback|
// and |cb_arg| parameters must be NULL.
-OPENSSL_EXPORT RSA *RSA_generate_key(int bits, unsigned long e, void *callback,
+OPENSSL_EXPORT RSA *RSA_generate_key(int bits, uint64_t e, void *callback,
void *cb_arg);
// d2i_RSAPublicKey parses a DER-encoded RSAPublicKey structure (RFC 8017) from