Parse RSAPrivateKey with CBS.

This removes the version field from RSA and instead handles versioning
as part of parsing. (As a bonus, we now correctly limit multi-prime RSA
to version 1 keys.)

Most consumers are also converted. old_rsa_priv_{de,en}code are left
alone for now. Those hooks are passed in parameters which match the old
d2i/i2d pattern (they're only used in d2i_PrivateKey and
i2d_PrivateKey).

Include a test which, among other things, checks that public keys being
serialized as private keys are handled properly.

BUG=499653

Change-Id: Icdd5f0382c4a84f9c8867024f29756e1a306ba08
Reviewed-on: https://boringssl-review.googlesource.com/5273
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/err/rsa.errordata b/crypto/err/rsa.errordata
index bb8e465..e4d8e74 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,135,RSA_marshal_private_key
 RSA,function,129,RSA_marshal_public_key
 RSA,function,106,RSA_new_method
 RSA,function,107,RSA_padding_add_PKCS1_OAEP_mgf1
@@ -16,7 +17,10 @@
 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,136,RSA_parse_private_key
 RSA,function,130,RSA_parse_public_key
+RSA,function,137,RSA_private_key_from_bytes
+RSA,function,138,RSA_private_key_to_bytes
 RSA,function,131,RSA_public_key_from_bytes
 RSA,function,132,RSA_public_key_to_bytes
 RSA,function,116,RSA_recover_crt_params
@@ -25,11 +29,13 @@
 RSA,function,119,RSA_verify_PKCS1_PSS_mgf1
 RSA,function,120,decrypt
 RSA,function,121,encrypt
+RSA,function,139,i2d_RSAPrivateKey
 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,140,rsa_parse_additional_prime
 RSA,function,125,rsa_setup_blinding
 RSA,function,126,sign_raw
 RSA,function,127,verify_raw
@@ -39,6 +45,7 @@
 RSA,reason,102,BAD_PAD_BYTE_COUNT
 RSA,reason,103,BAD_RSA_PARAMETERS
 RSA,reason,104,BAD_SIGNATURE
+RSA,reason,145,BAD_VERSION
 RSA,reason,105,BLOCK_TYPE_IS_NOT_01
 RSA,reason,106,BN_NOT_INITIALIZED
 RSA,reason,142,CANNOT_RECOVER_MULTI_PRIME_KEY
diff --git a/crypto/evp/evp_extra_test.cc b/crypto/evp/evp_extra_test.cc
index 674547d..9c955fa 100644
--- a/crypto/evp/evp_extra_test.cc
+++ b/crypto/evp/evp_extra_test.cc
@@ -322,8 +322,8 @@
 };
 
 static ScopedEVP_PKEY LoadExampleRSAKey() {
-  const uint8_t *derp = kExampleRSAKeyDER;
-  ScopedRSA rsa(d2i_RSAPrivateKey(nullptr, &derp, sizeof(kExampleRSAKeyDER)));
+  ScopedRSA rsa(RSA_private_key_from_bytes(kExampleRSAKeyDER,
+                                           sizeof(kExampleRSAKeyDER)));
   if (!rsa) {
     return nullptr;
   }
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h
index 8b755d0..4e1e9c9 100644
--- a/crypto/evp/internal.h
+++ b/crypto/evp/internal.h
@@ -114,8 +114,8 @@
   int (*pkey_size)(const EVP_PKEY *pk);
   int (*pkey_bits)(const EVP_PKEY *pk);
 
-  int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder, int derlen);
-  int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder);
+  int (*param_decode)(EVP_PKEY *pkey, const uint8_t **pder, int derlen);
+  int (*param_encode)(const EVP_PKEY *pkey, uint8_t **pder);
   int (*param_missing)(const EVP_PKEY *pk);
   int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from);
   int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
@@ -129,9 +129,9 @@
 
   /* Legacy functions for old PEM */
 
-  int (*old_priv_decode)(EVP_PKEY *pkey, const unsigned char **pder,
+  int (*old_priv_decode)(EVP_PKEY *pkey, const uint8_t **pder,
                          int derlen);
-  int (*old_priv_encode)(const EVP_PKEY *pkey, unsigned char **pder);
+  int (*old_priv_encode)(const EVP_PKEY *pkey, uint8_t **pder);
 
   /* Converting parameters to/from AlgorithmIdentifier (X509_ALGOR). */
   int (*digest_verify_init_from_algorithm)(EVP_MD_CTX *ctx,
@@ -242,23 +242,23 @@
   int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
 
   int (*sign_init)(EVP_PKEY_CTX *ctx);
-  int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
-              const unsigned char *tbs, size_t tbslen);
+  int (*sign)(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
+              const uint8_t *tbs, size_t tbslen);
 
   int (*verify_init)(EVP_PKEY_CTX *ctx);
-  int (*verify)(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
-                const unsigned char *tbs, size_t tbslen);
+  int (*verify)(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen,
+                const uint8_t *tbs, size_t tbslen);
 
   int (*encrypt_init)(EVP_PKEY_CTX *ctx);
-  int (*encrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
-                 const unsigned char *in, size_t inlen);
+  int (*encrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
+                 const uint8_t *in, size_t inlen);
 
   int (*decrypt_init)(EVP_PKEY_CTX *ctx);
-  int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
-                 const unsigned char *in, size_t inlen);
+  int (*decrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
+                 const uint8_t *in, size_t inlen);
 
   int (*derive_init)(EVP_PKEY_CTX *ctx);
-  int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
+  int (*derive)(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *keylen);
 
   int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
   int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value);
diff --git a/crypto/evp/p_rsa_asn1.c b/crypto/evp/p_rsa_asn1.c
index 6fcf2eb..9166c5a 100644
--- a/crypto/evp/p_rsa_asn1.c
+++ b/crypto/evp/p_rsa_asn1.c
@@ -107,20 +107,16 @@
 }
 
 static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
-  uint8_t *rk = NULL;
-  int rklen;
-
-  rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk);
-
-  if (rklen <= 0) {
-    OPENSSL_PUT_ERROR(EVP, rsa_priv_encode, ERR_R_MALLOC_FAILURE);
+  uint8_t *encoded;
+  size_t encoded_len;
+  if (!RSA_private_key_to_bytes(&encoded, &encoded_len, pkey->pkey.rsa)) {
     return 0;
   }
 
   /* TODO(fork): const correctness in next line. */
   if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_rsaEncryption), 0,
-                       V_ASN1_NULL, NULL, rk, rklen)) {
-    OPENSSL_free(rk);
+                       V_ASN1_NULL, NULL, encoded, encoded_len)) {
+    OPENSSL_free(encoded);
     OPENSSL_PUT_ERROR(EVP, rsa_priv_encode, ERR_R_MALLOC_FAILURE);
     return 0;
   }
@@ -131,14 +127,12 @@
 static int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
   const uint8_t *p;
   int pklen;
-  RSA *rsa;
-
   if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8)) {
     OPENSSL_PUT_ERROR(EVP, rsa_priv_decode, ERR_R_MALLOC_FAILURE);
     return 0;
   }
 
-  rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
+  RSA *rsa = RSA_private_key_from_bytes(p, pklen);
   if (rsa == NULL) {
     OPENSSL_PUT_ERROR(EVP, rsa_priv_decode, ERR_R_RSA_LIB);
     return 0;
@@ -227,8 +221,7 @@
   }
 
   if (include_private && rsa->d) {
-    if (BIO_printf(out, "Private-Key: (%d bit)\nversion: %ld\n", mod_len,
-                   rsa->version) <= 0) {
+    if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
       goto err;
     }
     str = "modulus:";
@@ -442,7 +435,7 @@
   return 1;
 }
 
-static int old_rsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder,
+static int old_rsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
                                int derlen) {
   RSA *rsa = d2i_RSAPrivateKey(NULL, pder, derlen);
   if (rsa == NULL) {
@@ -453,7 +446,7 @@
   return 1;
 }
 
-static int old_rsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) {
+static int old_rsa_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
   return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
 }
 
diff --git a/crypto/rsa/rsa_asn1.c b/crypto/rsa/rsa_asn1.c
index 5179214..97f940e 100644
--- a/crypto/rsa/rsa_asn1.c
+++ b/crypto/rsa/rsa_asn1.c
@@ -142,6 +142,195 @@
   return 1;
 }
 
+/* kVersionTwoPrime and kVersionMulti are the supported values of the version
+ * field of an RSAPrivateKey structure (RFC 3447). */
+static const uint64_t kVersionTwoPrime = 0;
+static const uint64_t kVersionMulti = 1;
+
+/* rsa_parse_additional_prime parses a DER-encoded OtherPrimeInfo from |cbs| and
+ * advances |cbs|. It returns a newly-allocated |RSA_additional_prime| on
+ * success or NULL on error. The |r| and |method_mod| fields of the result are
+ * set to NULL. */
+static RSA_additional_prime *rsa_parse_additional_prime(CBS *cbs) {
+  RSA_additional_prime *ret = OPENSSL_malloc(sizeof(RSA_additional_prime));
+  if (ret == NULL) {
+    OPENSSL_PUT_ERROR(RSA, rsa_parse_additional_prime, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+  memset(ret, 0, sizeof(RSA_additional_prime));
+
+  CBS child;
+  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+      !parse_integer(&child, &ret->prime) ||
+      !parse_integer(&child, &ret->exp) ||
+      !parse_integer(&child, &ret->coeff) ||
+      CBS_len(&child) != 0) {
+    OPENSSL_PUT_ERROR(RSA, rsa_parse_additional_prime, RSA_R_BAD_ENCODING);
+    RSA_additional_prime_free(ret);
+    return NULL;
+  }
+
+  return ret;
+}
+
+RSA *RSA_parse_private_key(CBS *cbs) {
+  BN_CTX *ctx = NULL;
+  BIGNUM *product_of_primes_so_far = NULL;
+  RSA *ret = RSA_new();
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  CBS child;
+  uint64_t version;
+  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1_uint64(&child, &version) ||
+      (version != kVersionTwoPrime && version != kVersionMulti) ||
+      !parse_integer(&child, &ret->n) ||
+      !parse_integer(&child, &ret->e) ||
+      !parse_integer(&child, &ret->d) ||
+      !parse_integer(&child, &ret->p) ||
+      !parse_integer(&child, &ret->q) ||
+      !parse_integer(&child, &ret->dmp1) ||
+      !parse_integer(&child, &ret->dmq1) ||
+      !parse_integer(&child, &ret->iqmp)) {
+    OPENSSL_PUT_ERROR(RSA, RSA_parse_private_key, RSA_R_BAD_VERSION);
+    goto err;
+  }
+
+  /* Multi-prime RSA requires a newer version. */
+  if (version == kVersionMulti &&
+      CBS_peek_asn1_tag(&child, CBS_ASN1_SEQUENCE)) {
+    CBS other_prime_infos;
+    if (!CBS_get_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE) ||
+        CBS_len(&other_prime_infos) == 0) {
+      OPENSSL_PUT_ERROR(RSA, RSA_parse_private_key, RSA_R_BAD_ENCODING);
+      goto err;
+    }
+    ret->additional_primes = sk_RSA_additional_prime_new_null();
+    if (ret->additional_primes == NULL) {
+      OPENSSL_PUT_ERROR(RSA, RSA_parse_private_key, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+
+    ctx = BN_CTX_new();
+    product_of_primes_so_far = BN_new();
+    if (ctx == NULL ||
+        product_of_primes_so_far == NULL ||
+        !BN_mul(product_of_primes_so_far, ret->p, ret->q, ctx)) {
+      goto err;
+    }
+
+    while (CBS_len(&other_prime_infos) > 0) {
+      RSA_additional_prime *ap = rsa_parse_additional_prime(&other_prime_infos);
+      if (ap == NULL) {
+        goto err;
+      }
+      if (!sk_RSA_additional_prime_push(ret->additional_primes, ap)) {
+        OPENSSL_PUT_ERROR(RSA, RSA_parse_private_key, ERR_R_MALLOC_FAILURE);
+        RSA_additional_prime_free(ap);
+        goto err;
+      }
+      ap->r = BN_dup(product_of_primes_so_far);
+      if (ap->r == NULL ||
+          !BN_mul(product_of_primes_so_far, product_of_primes_so_far,
+                  ap->prime, ctx)) {
+        goto err;
+      }
+    }
+  }
+
+  if (CBS_len(&child) != 0) {
+    OPENSSL_PUT_ERROR(RSA, RSA_parse_private_key, RSA_R_BAD_ENCODING);
+    goto err;
+  }
+
+  BN_CTX_free(ctx);
+  BN_free(product_of_primes_so_far);
+  return ret;
+
+err:
+  BN_CTX_free(ctx);
+  BN_free(product_of_primes_so_far);
+  RSA_free(ret);
+  return NULL;
+}
+
+RSA *RSA_private_key_from_bytes(const uint8_t *in, size_t in_len) {
+  CBS cbs;
+  CBS_init(&cbs, in, in_len);
+  RSA *ret = RSA_parse_private_key(&cbs);
+  if (ret == NULL || CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(RSA, RSA_private_key_from_bytes, RSA_R_BAD_ENCODING);
+    RSA_free(ret);
+    return NULL;
+  }
+  return ret;
+}
+
+int RSA_marshal_private_key(CBB *cbb, const RSA *rsa) {
+  const int is_multiprime =
+      sk_RSA_additional_prime_num(rsa->additional_primes) > 0;
+
+  CBB child;
+  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1_uint64(&child,
+                           is_multiprime ? kVersionMulti : kVersionTwoPrime) ||
+      !marshal_integer(&child, rsa->n) ||
+      !marshal_integer(&child, rsa->e) ||
+      !marshal_integer(&child, rsa->d) ||
+      !marshal_integer(&child, rsa->p) ||
+      !marshal_integer(&child, rsa->q) ||
+      !marshal_integer(&child, rsa->dmp1) ||
+      !marshal_integer(&child, rsa->dmq1) ||
+      !marshal_integer(&child, rsa->iqmp)) {
+    OPENSSL_PUT_ERROR(RSA, RSA_marshal_private_key, RSA_R_ENCODE_ERROR);
+    return 0;
+  }
+
+  if (is_multiprime) {
+    CBB other_prime_infos;
+    if (!CBB_add_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE)) {
+      OPENSSL_PUT_ERROR(RSA, RSA_marshal_private_key, RSA_R_ENCODE_ERROR);
+      return 0;
+    }
+    size_t i;
+    for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) {
+      RSA_additional_prime *ap =
+              sk_RSA_additional_prime_value(rsa->additional_primes, i);
+      CBB other_prime_info;
+      if (!CBB_add_asn1(&other_prime_infos, &other_prime_info,
+                        CBS_ASN1_SEQUENCE) ||
+          !marshal_integer(&other_prime_info, ap->prime) ||
+          !marshal_integer(&other_prime_info, ap->exp) ||
+          !marshal_integer(&other_prime_info, ap->coeff)) {
+        OPENSSL_PUT_ERROR(RSA, RSA_marshal_private_key, RSA_R_ENCODE_ERROR);
+        return 0;
+      }
+    }
+  }
+
+  if (!CBB_flush(cbb)) {
+    OPENSSL_PUT_ERROR(RSA, RSA_marshal_private_key, RSA_R_ENCODE_ERROR);
+    return 0;
+  }
+  return 1;
+}
+
+int RSA_private_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_private_key(&cbb, rsa) ||
+      !CBB_finish(&cbb, out_bytes, out_len)) {
+    OPENSSL_PUT_ERROR(RSA, RSA_private_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;
@@ -184,75 +373,47 @@
   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) {
-  RSA *rsa = (RSA *)*pval;
-  BN_CTX *ctx = NULL;
-  BIGNUM *product_of_primes_so_far = NULL;
-  int ret = 0;
-
-  if (operation == ASN1_OP_NEW_PRE) {
-    *pval = (ASN1_VALUE *)RSA_new();
-    if (*pval) {
-      return 2;
-    }
-    return 0;
-  } else if (operation == ASN1_OP_FREE_PRE) {
-    RSA_free(rsa);
-    *pval = NULL;
-    return 2;
-  } else if (operation == ASN1_OP_D2I_POST) {
-    if (rsa->additional_primes != NULL) {
-      ctx = BN_CTX_new();
-      product_of_primes_so_far = BN_new();
-      if (ctx == NULL ||
-          product_of_primes_so_far == NULL ||
-          !BN_mul(product_of_primes_so_far, rsa->p, rsa->q, ctx)) {
-        goto err;
-      }
-
-      size_t i;
-      for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) {
-        RSA_additional_prime *ap =
-            sk_RSA_additional_prime_value(rsa->additional_primes, i);
-        ap->r = BN_dup(product_of_primes_so_far);
-        if (ap->r == NULL ||
-            !BN_mul(product_of_primes_so_far, product_of_primes_so_far,
-                    ap->prime, ctx)) {
-          goto err;
-        }
-      }
-    }
-    ret = 2;
-  } else {
-    return 1;
+RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len) {
+  if (len < 0) {
+    return NULL;
   }
-
-err:
-  BN_CTX_free(ctx);
-  BN_free(product_of_primes_so_far);
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  RSA *ret = RSA_parse_private_key(&cbs);
+  if (ret == NULL) {
+    return NULL;
+  }
+  if (out != NULL) {
+    RSA_free(*out);
+    *out = ret;
+  }
+  *inp += (size_t)len - CBS_len(&cbs);
   return ret;
 }
 
-ASN1_SEQUENCE(RSA_additional_prime) = {
-    ASN1_SIMPLE(RSA_additional_prime, prime, BIGNUM),
-    ASN1_SIMPLE(RSA_additional_prime, exp, BIGNUM),
-    ASN1_SIMPLE(RSA_additional_prime, coeff, BIGNUM),
-} ASN1_SEQUENCE_END(RSA_additional_prime);
-
-ASN1_SEQUENCE_cb(RSAPrivateKey, rsa_cb) = {
-  ASN1_SIMPLE(RSA, version, LONG),
-  ASN1_SIMPLE(RSA, n, BIGNUM),
-  ASN1_SIMPLE(RSA, e, BIGNUM),
-  ASN1_SIMPLE(RSA, d, BIGNUM),
-  ASN1_SIMPLE(RSA, p, BIGNUM),
-  ASN1_SIMPLE(RSA, q, BIGNUM),
-  ASN1_SIMPLE(RSA, dmp1, BIGNUM),
-  ASN1_SIMPLE(RSA, dmq1, BIGNUM),
-  ASN1_SIMPLE(RSA, iqmp, BIGNUM),
-  ASN1_SEQUENCE_OF_OPT(RSA, additional_primes, RSA_additional_prime),
-} ASN1_SEQUENCE_END_cb(RSA, RSAPrivateKey);
+int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp) {
+  uint8_t *der;
+  size_t der_len;
+  if (!RSA_private_key_to_bytes(&der, &der_len, in)) {
+    return -1;
+  }
+  if (der_len > INT_MAX) {
+    OPENSSL_PUT_ERROR(RSA, i2d_RSAPrivateKey, 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;
+}
 
 ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
   ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
@@ -271,8 +432,6 @@
 
 IMPLEMENT_ASN1_FUNCTIONS(RSA_OAEP_PARAMS);
 
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(RSA, RSAPrivateKey, RSAPrivateKey);
-
 RSA *RSAPublicKey_dup(const RSA *rsa) {
   uint8_t *der;
   size_t der_len;
@@ -285,5 +444,12 @@
 }
 
 RSA *RSAPrivateKey_dup(const RSA *rsa) {
-  return ASN1_item_dup(ASN1_ITEM_rptr(RSAPrivateKey), (RSA *) rsa);
+  uint8_t *der;
+  size_t der_len;
+  if (!RSA_private_key_to_bytes(&der, &der_len, rsa)) {
+    return NULL;
+  }
+  RSA *ret = RSA_private_key_from_bytes(der, der_len);
+  OPENSSL_free(der);
+  return ret;
 }
diff --git a/crypto/rsa/rsa_test.cc b/crypto/rsa/rsa_test.cc
index e0fa77c..9d44e2c 100644
--- a/crypto/rsa/rsa_test.cc
+++ b/crypto/rsa/rsa_test.cc
@@ -742,6 +742,57 @@
   return true;
 }
 
+static bool TestASN1() {
+  // Test that private keys may be decoded.
+  ScopedRSA rsa(RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1));
+  if (!rsa) {
+    return false;
+  }
+
+  // Test that the serialization round-trips.
+  uint8_t *der;
+  size_t der_len;
+  if (!RSA_private_key_to_bytes(&der, &der_len, rsa.get())) {
+    return false;
+  }
+  ScopedOpenSSLBytes delete_der(der);
+  if (der_len != sizeof(kKey1) - 1 || memcmp(der, kKey1, der_len) != 0) {
+    return false;
+  }
+
+  // Test that serializing public keys works.
+  if (!RSA_public_key_to_bytes(&der, &der_len, rsa.get())) {
+    return false;
+  }
+  delete_der.reset(der);
+
+  // Public keys may be parsed back out.
+  rsa.reset(RSA_public_key_from_bytes(der, der_len));
+  if (!rsa || rsa->p != NULL || rsa->q != NULL) {
+    return false;
+  }
+
+  // Serializing the result round-trips.
+  uint8_t *der2;
+  size_t der2_len;
+  if (!RSA_public_key_to_bytes(&der2, &der2_len, rsa.get())) {
+    return false;
+  }
+  ScopedOpenSSLBytes delete_der2(der2);
+  if (der_len != der2_len || memcmp(der, der2, der_len) != 0) {
+    return false;
+  }
+
+  // Public keys cannot be serialized as private keys.
+  if (RSA_private_key_to_bytes(&der, &der_len, rsa.get())) {
+    OPENSSL_free(der);
+    return false;
+  }
+  ERR_clear_error();
+
+  return true;
+}
+
 int main(int argc, char *argv[]) {
   CRYPTO_library_init();
 
@@ -763,7 +814,8 @@
       !TestMultiPrimeKey(6, kSixPrimeKey, sizeof(kSixPrimeKey) - 1,
                             kSixPrimeEncryptedMessage,
                             sizeof(kSixPrimeEncryptedMessage)) ||
-      !TestMultiPrimeKeygen()) {
+      !TestMultiPrimeKeygen() ||
+      !TestASN1()) {
     return 1;
   }
 
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index 6798090..d7f2d29 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -64,8 +64,6 @@
 #include <openssl/x509.h>
 
 
-extern const ASN1_ITEM RSAPrivateKey_it;
-
 int X509_verify(X509 *a, EVP_PKEY *r)
 	{
 	if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
@@ -244,12 +242,12 @@
 #ifndef OPENSSL_NO_FP_API
 RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
 	{
-	return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
+	return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa);
 	}
 
 int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
 	{
-	return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
+	return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa);
 	}
 
 RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
@@ -277,12 +275,12 @@
 
 RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
 	{
-	return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
+	return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa);
 	}
 
 int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
 	{
-	return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
+	return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa);
 	}
 
 RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)