Parse RSAPublicKey with CBS.

BUG=499653

Change-Id: If5d98ed23e65a84f9f0e303024f91cce078f3d18
Reviewed-on: https://boringssl-review.googlesource.com/5272
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/err/rsa.errordata b/crypto/err/rsa.errordata
index 94b4bcb..bb8e465 100644
--- a/crypto/err/rsa.errordata
+++ b/crypto/err/rsa.errordata
@@ -5,6 +5,7 @@
 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,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,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 a966af5..6fcf2eb 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 @@
   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 b8f9d87..5179214 100644
--- a/crypto/rsa/rsa_asn1.c
+++ b/crypto/rsa/rsa_asn1.c
@@ -55,12 +55,135 @@
 
 #include <openssl/rsa.h>
 
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
 
 #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_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_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 32faa55..6798090 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 @@
 
 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 @@
 
 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 @@
 
 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 @@
 
 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 4a9d36d..a79f91f 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -272,7 +272,7 @@
  * 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 @@
 
 /* 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 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 @@
 #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 @@
 #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 */