From c0e245a546b15c6b4219d2f3d5455e417cddc782 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Wed, 17 Jun 2015 00:02:59 -0400 Subject: [PATCH] Parse RSAPublicKey with CBS. BUG=499653 Change-Id: If5d98ed23e65a84f9f0e303024f91cce078f3d18 Reviewed-on: https://boringssl-review.googlesource.com/5272 Reviewed-by: Adam Langley --- crypto/err/rsa.errordata | 8 +++ crypto/evp/p_rsa_asn1.c | 12 ++-- crypto/rsa/rsa_asn1.c | 139 ++++++++++++++++++++++++++++++++++++--- crypto/x509/x_all.c | 9 ++- include/openssl/rsa.h | 58 ++++++++++++---- 5 files changed, 193 insertions(+), 33 deletions(-) diff --git a/crypto/err/rsa.errordata b/crypto/err/rsa.errordata index 94b4bcbb..bb8e4657 100644 --- a/crypto/err/rsa.errordata +++ b/crypto/err/rsa.errordata @@ -5,6 +5,7 @@ RSA,function,103,BN_BLINDING_new RSA,function,104,BN_BLINDING_update RSA,function,123,RSA_add_pkcs1_prefix RSA,function,105,RSA_check_key +RSA,function,129,RSA_marshal_public_key RSA,function,106,RSA_new_method RSA,function,107,RSA_padding_add_PKCS1_OAEP_mgf1 RSA,function,108,RSA_padding_add_PKCS1_PSS_mgf1 @@ -15,18 +16,24 @@ RSA,function,112,RSA_padding_check_PKCS1_OAEP_mgf1 RSA,function,113,RSA_padding_check_PKCS1_type_1 RSA,function,114,RSA_padding_check_PKCS1_type_2 RSA,function,115,RSA_padding_check_none +RSA,function,130,RSA_parse_public_key +RSA,function,131,RSA_public_key_from_bytes +RSA,function,132,RSA_public_key_to_bytes RSA,function,116,RSA_recover_crt_params RSA,function,117,RSA_sign RSA,function,118,RSA_verify RSA,function,119,RSA_verify_PKCS1_PSS_mgf1 RSA,function,120,decrypt RSA,function,121,encrypt +RSA,function,133,i2d_RSAPublicKey RSA,function,122,keygen RSA,function,128,keygen_multiprime +RSA,function,134,marshal_integer RSA,function,124,private_transform RSA,function,125,rsa_setup_blinding RSA,function,126,sign_raw RSA,function,127,verify_raw +RSA,reason,143,BAD_ENCODING RSA,reason,100,BAD_E_VALUE RSA,reason,101,BAD_FIXED_HEADER_DECRYPT RSA,reason,102,BAD_PAD_BYTE_COUNT @@ -46,6 +53,7 @@ RSA,reason,114,DATA_TOO_SMALL_FOR_KEY_SIZE RSA,reason,115,DIGEST_TOO_BIG_FOR_RSA_KEY RSA,reason,116,D_E_NOT_CONGRUENT_TO_1 RSA,reason,117,EMPTY_PUBLIC_KEY +RSA,reason,144,ENCODE_ERROR RSA,reason,118,FIRST_OCTET_INVALID RSA,reason,119,INCONSISTENT_SET_OF_CRT_VALUES RSA,reason,120,INTERNAL_ERROR diff --git a/crypto/evp/p_rsa_asn1.c b/crypto/evp/p_rsa_asn1.c index a966af5b..6fcf2ebf 100644 --- a/crypto/evp/p_rsa_asn1.c +++ b/crypto/evp/p_rsa_asn1.c @@ -69,16 +69,14 @@ static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) { - uint8_t *encoded = NULL; - int len; - len = i2d_RSAPublicKey(pkey->pkey.rsa, &encoded); - - if (len <= 0) { + uint8_t *encoded; + size_t encoded_len; + if (!RSA_public_key_to_bytes(&encoded, &encoded_len, pkey->pkey.rsa)) { return 0; } if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA), V_ASN1_NULL, NULL, - encoded, len)) { + encoded, encoded_len)) { OPENSSL_free(encoded); return 0; } @@ -94,7 +92,7 @@ static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) { if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey)) { return 0; } - rsa = d2i_RSAPublicKey(NULL, &p, pklen); + rsa = RSA_public_key_from_bytes(p, pklen); if (rsa == NULL) { OPENSSL_PUT_ERROR(EVP, rsa_pub_decode, ERR_R_RSA_LIB); return 0; diff --git a/crypto/rsa/rsa_asn1.c b/crypto/rsa/rsa_asn1.c index b8f9d87e..51792146 100644 --- a/crypto/rsa/rsa_asn1.c +++ b/crypto/rsa/rsa_asn1.c @@ -55,12 +55,135 @@ #include +#include +#include +#include + #include #include +#include +#include +#include +#include #include "internal.h" +static int parse_integer(CBS *cbs, BIGNUM **out) { + assert(*out == NULL); + *out = BN_new(); + if (*out == NULL) { + return 0; + } + return BN_cbs2unsigned(cbs, *out); +} + +static int marshal_integer(CBB *cbb, BIGNUM *bn) { + if (bn == NULL) { + /* An RSA object may be missing some components. */ + OPENSSL_PUT_ERROR(RSA, marshal_integer, RSA_R_VALUE_MISSING); + return 0; + } + return BN_bn2cbb(cbb, bn); +} + +RSA *RSA_parse_public_key(CBS *cbs) { + RSA *ret = RSA_new(); + if (ret == NULL) { + return NULL; + } + CBS child; + if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) || + !parse_integer(&child, &ret->n) || + !parse_integer(&child, &ret->e) || + CBS_len(&child) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_parse_public_key, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len) { + CBS cbs; + CBS_init(&cbs, in, in_len); + RSA *ret = RSA_parse_public_key(&cbs); + if (ret == NULL || CBS_len(&cbs) != 0) { + OPENSSL_PUT_ERROR(RSA, RSA_public_key_from_bytes, RSA_R_BAD_ENCODING); + RSA_free(ret); + return NULL; + } + return ret; +} + +int RSA_marshal_public_key(CBB *cbb, const RSA *rsa) { + CBB child; + if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) || + !marshal_integer(&child, rsa->n) || + !marshal_integer(&child, rsa->e) || + !CBB_flush(cbb)) { + OPENSSL_PUT_ERROR(RSA, RSA_marshal_public_key, RSA_R_ENCODE_ERROR); + return 0; + } + return 1; +} + +int RSA_public_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa) { + CBB cbb; + CBB_zero(&cbb); + if (!CBB_init(&cbb, 0) || + !RSA_marshal_public_key(&cbb, rsa) || + !CBB_finish(&cbb, out_bytes, out_len)) { + OPENSSL_PUT_ERROR(RSA, RSA_public_key_to_bytes, RSA_R_ENCODE_ERROR); + CBB_cleanup(&cbb); + return 0; + } + return 1; +} + +RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len) { + if (len < 0) { + return NULL; + } + CBS cbs; + CBS_init(&cbs, *inp, (size_t)len); + RSA *ret = RSA_parse_public_key(&cbs); + if (ret == NULL) { + return NULL; + } + if (out != NULL) { + RSA_free(*out); + *out = ret; + } + *inp += (size_t)len - CBS_len(&cbs); + return ret; +} + +int i2d_RSAPublicKey(const RSA *in, uint8_t **outp) { + uint8_t *der; + size_t der_len; + if (!RSA_public_key_to_bytes(&der, &der_len, in)) { + return -1; + } + if (der_len > INT_MAX) { + OPENSSL_PUT_ERROR(RSA, i2d_RSAPublicKey, ERR_R_OVERFLOW); + OPENSSL_free(der); + return -1; + } + if (outp != NULL) { + if (*outp == NULL) { + *outp = der; + der = NULL; + } else { + memcpy(*outp, der, der_len); + *outp += der_len; + } + } + OPENSSL_free(der); + return (int)der_len; +} + /* Override the default free and new methods */ static int rsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) { @@ -131,11 +254,6 @@ ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = { ASN1_SEQUENCE_OF_OPT(RSA, additional_primes, RSA_additional_prime), } ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey); -ASN1_SEQUENCE_cb(RSAPublicKey, rsa_cb) = { - ASN1_SIMPLE(RSA, n, BIGNUM), - ASN1_SIMPLE(RSA, e, BIGNUM), -} ASN1_SEQUENCE_END_cb(RSA, RSAPublicKey); - ASN1_SEQUENCE(RSA_PSS_PARAMS) = { ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0), ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1), @@ -155,10 +273,15 @@ IMPLEMENT_ASN1_FUNCTIONS(RSA_OAEP_PARAMS); IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey); -IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPublicKey, RSAPublicKey); - RSA *RSAPublicKey_dup(const RSA *rsa) { - return ASN1_item_dup(ASN1_ITEM_rptr(RSAPublicKey), (RSA *) rsa); + uint8_t *der; + size_t der_len; + if (!RSA_public_key_to_bytes(&der, &der_len, rsa)) { + return NULL; + } + RSA *ret = RSA_public_key_from_bytes(der, der_len); + OPENSSL_free(der); + return ret; } RSA *RSAPrivateKey_dup(const RSA *rsa) { diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 32faa557..67980903 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -65,7 +65,6 @@ extern const ASN1_ITEM RSAPrivateKey_it; -extern const ASN1_ITEM RSAPublicKey_it; int X509_verify(X509 *a, EVP_PKEY *r) { @@ -255,7 +254,7 @@ int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa) RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa) { - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa); + return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa); } RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) @@ -267,7 +266,7 @@ RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa) int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa) { - return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa); + return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa); } int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa) @@ -288,7 +287,7 @@ int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa) RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa) { - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa); + return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa); } @@ -299,7 +298,7 @@ RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa) int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa) { - return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa); + return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa); } int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa) diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h index 4a9d36d6..a79f91f9 100644 --- a/include/openssl/rsa.h +++ b/include/openssl/rsa.h @@ -272,7 +272,7 @@ OPENSSL_EXPORT int RSA_is_opaque(const RSA *rsa); * of type |md|. Otherwise it returns zero. */ OPENSSL_EXPORT int RSA_supports_digest(const RSA *rsa, const EVP_MD *md); -/* RSAPublicKey_dup allocates a fresh |RSA| and copies the private key from +/* RSAPublicKey_dup allocates a fresh |RSA| and copies the public key from * |rsa| into it. It returns the fresh |RSA| object, or NULL on error. */ OPENSSL_EXPORT RSA *RSAPublicKey_dup(const RSA *rsa); @@ -332,19 +332,26 @@ OPENSSL_EXPORT int RSA_add_pkcs1_prefix(uint8_t **out_msg, size_t *out_msg_len, /* ASN.1 functions. */ -/* d2i_RSAPublicKey parses an ASN.1, DER-encoded, RSA public key from |len| - * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result - * is in |*out|. If |*out| is already non-NULL on entry then the result is - * written directly into |*out|, otherwise a fresh |RSA| is allocated. On - * successful exit, |*inp| is advanced past the DER structure. It returns the - * result or NULL on error. */ -OPENSSL_EXPORT RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len); +/* RSA_parse_public_key parses a DER-encoded RSAPublicKey structure (RFC 3447) + * from |cbs| and advances |cbs|. It returns a newly-allocated |RSA| or NULL on + * error. */ +OPENSSL_EXPORT RSA *RSA_parse_public_key(CBS *cbs); -/* i2d_RSAPublicKey marshals |in| to an ASN.1, DER structure. If |outp| is not - * NULL then the result is written to |*outp| and |*outp| is advanced just past - * the output. It returns the number of bytes in the result, whether written or - * not, or a negative value on error. */ -OPENSSL_EXPORT int i2d_RSAPublicKey(const RSA *in, uint8_t **outp); +/* RSA_public_key_from_bytes parses |in| as a DER-encoded RSAPublicKey structure + * (RFC 3447). It returns a newly-allocated |RSA| or NULL on error. */ +OPENSSL_EXPORT RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len); + +/* RSA_marshal_public_key marshals |rsa| as a DER-encoded RSAPublicKey structure + * (RFC 3447) and appends the result to |cbb|. It returns one on success and + * zero on failure. */ +OPENSSL_EXPORT int RSA_marshal_public_key(CBB *cbb, const RSA *rsa); + +/* RSA_public_key_to_bytes marshals |rsa| as a DER-encoded RSAPublicKey + * structure (RFC 3447) and, on success, sets |*out_bytes| to a newly allocated + * buffer containing the result and returns one. Otherwise, it returns zero. The + * result should be freed with |OPENSSL_free|. */ +OPENSSL_EXPORT int RSA_public_key_to_bytes(uint8_t **out_bytes, size_t *out_len, + const RSA *rsa); /* d2i_RSAPrivateKey parses an ASN.1, DER-encoded, RSA private key from |len| * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result @@ -361,6 +368,23 @@ OPENSSL_EXPORT RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len); OPENSSL_EXPORT int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp); +/* Deprecated functions. */ + +/* d2i_RSAPublicKey parses an ASN.1, DER-encoded, RSA public key from |len| + * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result + * is in |*out|. If |*out| is already non-NULL on entry then the result is + * written directly into |*out|, otherwise a fresh |RSA| is allocated. On + * successful exit, |*inp| is advanced past the DER structure. It returns the + * result or NULL on error. */ +OPENSSL_EXPORT RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len); + +/* i2d_RSAPublicKey marshals |in| to an ASN.1, DER structure. If |outp| is not + * NULL then the result is written to |*outp| and |*outp| is advanced just past + * the output. It returns the number of bytes in the result, whether written or + * not, or a negative value on error. */ +OPENSSL_EXPORT int i2d_RSAPublicKey(const RSA *in, uint8_t **outp); + + /* ex_data functions. * * See |ex_data.h| for details. */ @@ -558,6 +582,12 @@ struct rsa_st { #define RSA_F_sign_raw 126 #define RSA_F_verify_raw 127 #define RSA_F_keygen_multiprime 128 +#define RSA_F_RSA_marshal_public_key 129 +#define RSA_F_RSA_parse_public_key 130 +#define RSA_F_RSA_public_key_from_bytes 131 +#define RSA_F_RSA_public_key_to_bytes 132 +#define RSA_F_i2d_RSAPublicKey 133 +#define RSA_F_marshal_integer 134 #define RSA_R_BAD_E_VALUE 100 #define RSA_R_BAD_FIXED_HEADER_DECRYPT 101 #define RSA_R_BAD_PAD_BYTE_COUNT 102 @@ -601,5 +631,7 @@ struct rsa_st { #define RSA_R_WRONG_SIGNATURE_LENGTH 140 #define RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES 141 #define RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY 142 +#define RSA_R_BAD_ENCODING 143 +#define RSA_R_ENCODE_ERROR 144 #endif /* OPENSSL_HEADER_RSA_H */