external/boringssl: Sync to 2d98d49cf712ca7dc6f4b23b9c5f5542385d8dbe.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/5ede28c8a422801ace3ba5e466ba963005351145..2d98d49cf712ca7dc6f4b23b9c5f5542385d8dbe

Test: BoringSSL CTS Presubmits
Change-Id: I21750d81b070d7e4741e205f5c2ccd8d541b36d1
diff --git a/src/crypto/x509/by_file.c b/src/crypto/x509/by_file.c
index 555cb85..dfff425 100644
--- a/src/crypto/x509/by_file.c
+++ b/src/crypto/x509/by_file.c
@@ -138,14 +138,15 @@
         for (;;) {
             x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
             if (x == NULL) {
-                if ((ERR_GET_REASON(ERR_peek_last_error()) ==
-                     PEM_R_NO_START_LINE) && (count > 0)) {
+                uint32_t error = ERR_peek_last_error();
+                if (ERR_GET_LIB(error) == ERR_LIB_PEM &&
+                    ERR_GET_REASON(error) == PEM_R_NO_START_LINE &&
+                    count > 0) {
                     ERR_clear_error();
                     break;
-                } else {
-                    OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
-                    goto err;
                 }
+                OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+                goto err;
             }
             i = X509_STORE_add_cert(ctx->store_ctx, x);
             if (!i)
@@ -197,14 +198,15 @@
         for (;;) {
             x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
             if (x == NULL) {
-                if ((ERR_GET_REASON(ERR_peek_last_error()) ==
-                     PEM_R_NO_START_LINE) && (count > 0)) {
+                uint32_t error = ERR_peek_last_error();
+                if (ERR_GET_LIB(error) == ERR_LIB_PEM &&
+                    ERR_GET_REASON(error) == PEM_R_NO_START_LINE &&
+                    count > 0) {
                     ERR_clear_error();
                     break;
-                } else {
-                    OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
-                    goto err;
                 }
+                OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+                goto err;
             }
             i = X509_STORE_add_crl(ctx->store_ctx, x);
             if (!i)
diff --git a/src/crypto/x509/t_crl.c b/src/crypto/x509/t_crl.c
index 6c347cb..dc9b87f 100644
--- a/src/crypto/x509/t_crl.c
+++ b/src/crypto/x509/t_crl.c
@@ -64,17 +64,14 @@
 #ifndef OPENSSL_NO_FP_API
 int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
 {
-    BIO *b;
-    int ret;
-
-    if ((b = BIO_new(BIO_s_file())) == NULL) {
+    BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+    if (b == NULL) {
         OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
-        return (0);
+        return 0;
     }
-    BIO_set_fp(b, fp, BIO_NOCLOSE);
-    ret = X509_CRL_print(b, x);
+    int ret = X509_CRL_print(b, x);
     BIO_free(b);
-    return (ret);
+    return ret;
 }
 #endif
 
diff --git a/src/crypto/x509/t_req.c b/src/crypto/x509/t_req.c
index 39c836c..2fd36f8 100644
--- a/src/crypto/x509/t_req.c
+++ b/src/crypto/x509/t_req.c
@@ -65,13 +65,11 @@
 
 
 int X509_REQ_print_fp(FILE *fp, X509_REQ *x) {
-  BIO *bio = BIO_new(BIO_s_file());
+  BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE);
   if (bio == NULL) {
     OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
     return 0;
   }
-
-  BIO_set_fp(bio, fp, BIO_NOCLOSE);
   int ret = X509_REQ_print(bio, x);
   BIO_free(bio);
   return ret;
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
index 3339523..e45a765 100644
--- a/src/crypto/x509/t_x509.c
+++ b/src/crypto/x509/t_x509.c
@@ -72,17 +72,14 @@
 int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
                      unsigned long cflag)
 {
-    BIO *b;
-    int ret;
-
-    if ((b = BIO_new(BIO_s_file())) == NULL) {
+    BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
+    if (b == NULL) {
         OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
-        return (0);
+        return 0;
     }
-    BIO_set_fp(b, fp, BIO_NOCLOSE);
-    ret = X509_print_ex(b, x, nmflag, cflag);
+    int ret = X509_print_ex(b, x, nmflag, cflag);
     BIO_free(b);
-    return (ret);
+    return ret;
 }
 
 int X509_print_fp(FILE *fp, X509 *x)
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
index 9ed1b52..bf0b29a 100644
--- a/src/crypto/x509/x509_test.cc
+++ b/src/crypto/x509/x509_test.cc
@@ -1549,3 +1549,125 @@
   EXPECT_EQ(ERR_LIB_X509, ERR_GET_LIB(err));
   EXPECT_EQ(X509_R_SIGNATURE_ALGORITHM_MISMATCH, ERR_GET_REASON(err));
 }
+
+TEST(X509Test, PEMX509Info) {
+  std::string cert = kRootCAPEM;
+  auto cert_obj = CertFromPEM(kRootCAPEM);
+  ASSERT_TRUE(cert_obj);
+
+  std::string rsa = kRSAKey;
+  auto rsa_obj = PrivateKeyFromPEM(kRSAKey);
+  ASSERT_TRUE(rsa_obj);
+
+  std::string crl = kBasicCRL;
+  auto crl_obj = CRLFromPEM(kBasicCRL);
+  ASSERT_TRUE(crl_obj);
+
+  std::string unknown =
+      "-----BEGIN UNKNOWN-----\n"
+      "AAAA\n"
+      "-----END UNKNOWN-----\n";
+
+  std::string invalid =
+      "-----BEGIN CERTIFICATE-----\n"
+      "AAAA\n"
+      "-----END CERTIFICATE-----\n";
+
+  // Each X509_INFO contains at most one certificate, CRL, etc. The format
+  // creates a new X509_INFO when a repeated type is seen.
+  std::string pem =
+      // The first few entries have one of everything in different orders.
+      cert + rsa + crl +
+      rsa + crl + cert +
+      // Unknown types are ignored.
+      crl + unknown + cert + rsa +
+      // Seeing a new certificate starts a new entry, so now we have a bunch of
+      // certificate-only entries.
+      cert + cert + cert +
+      // The key folds into the certificate's entry.
+      cert + rsa +
+      // Doubled keys also start new entries.
+      rsa + rsa + rsa + rsa + crl +
+      // As do CRLs.
+      crl + crl;
+
+  const struct ExpectedInfo {
+    const X509 *cert;
+    const EVP_PKEY *key;
+    const X509_CRL *crl;
+  } kExpected[] = {
+    {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
+    {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
+    {cert_obj.get(), rsa_obj.get(), crl_obj.get()},
+    {cert_obj.get(), nullptr, nullptr},
+    {cert_obj.get(), nullptr, nullptr},
+    {cert_obj.get(), nullptr, nullptr},
+    {cert_obj.get(), rsa_obj.get(), nullptr},
+    {nullptr, rsa_obj.get(), nullptr},
+    {nullptr, rsa_obj.get(), nullptr},
+    {nullptr, rsa_obj.get(), nullptr},
+    {nullptr, rsa_obj.get(), crl_obj.get()},
+    {nullptr, nullptr, crl_obj.get()},
+    {nullptr, nullptr, crl_obj.get()},
+  };
+
+  auto check_info = [](const ExpectedInfo *expected, const X509_INFO *info) {
+    if (expected->cert != nullptr) {
+      EXPECT_EQ(0, X509_cmp(expected->cert, info->x509));
+    } else {
+      EXPECT_EQ(nullptr, info->x509);
+    }
+    if (expected->crl != nullptr) {
+      EXPECT_EQ(0, X509_CRL_cmp(expected->crl, info->crl));
+    } else {
+      EXPECT_EQ(nullptr, info->crl);
+    }
+    if (expected->key != nullptr) {
+      ASSERT_NE(nullptr, info->x_pkey);
+      // EVP_PKEY_cmp returns one if the keys are equal.
+      EXPECT_EQ(1, EVP_PKEY_cmp(expected->key, info->x_pkey->dec_pkey));
+    } else {
+      EXPECT_EQ(nullptr, info->x_pkey);
+    }
+  };
+
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem.data(), pem.size()));
+  ASSERT_TRUE(bio);
+  bssl::UniquePtr<STACK_OF(X509_INFO)> infos(
+      PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr));
+  ASSERT_TRUE(infos);
+  ASSERT_EQ(OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) {
+    SCOPED_TRACE(i);
+    check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i));
+  }
+
+  // Passing an existing stack appends to it.
+  bio.reset(BIO_new_mem_buf(pem.data(), pem.size()));
+  ASSERT_TRUE(bio);
+  ASSERT_EQ(infos.get(),
+            PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr));
+  ASSERT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kExpected); i++) {
+    SCOPED_TRACE(i);
+    check_info(&kExpected[i], sk_X509_INFO_value(infos.get(), i));
+    check_info(
+        &kExpected[i],
+        sk_X509_INFO_value(infos.get(), i + OPENSSL_ARRAY_SIZE(kExpected)));
+  }
+
+  // Gracefully handle errors in both the append and fresh cases.
+  std::string bad_pem = cert + cert + invalid;
+
+  bio.reset(BIO_new_mem_buf(bad_pem.data(), bad_pem.size()));
+  ASSERT_TRUE(bio);
+  bssl::UniquePtr<STACK_OF(X509_INFO)> infos2(
+      PEM_X509_INFO_read_bio(bio.get(), nullptr, nullptr, nullptr));
+  EXPECT_FALSE(infos2);
+
+  bio.reset(BIO_new_mem_buf(bad_pem.data(), bad_pem.size()));
+  ASSERT_TRUE(bio);
+  EXPECT_FALSE(
+      PEM_X509_INFO_read_bio(bio.get(), infos.get(), nullptr, nullptr));
+  EXPECT_EQ(2 * OPENSSL_ARRAY_SIZE(kExpected), sk_X509_INFO_num(infos.get()));
+}
diff --git a/src/crypto/x509/x_all.c b/src/crypto/x509/x_all.c
index 064c89c..a37d7bd 100644
--- a/src/crypto/x509/x_all.c
+++ b/src/crypto/x509/x_all.c
@@ -54,14 +54,18 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#include <openssl/x509.h>
+
+#include <limits.h>
+
 #include <openssl/asn1.h>
 #include <openssl/buf.h>
 #include <openssl/digest.h>
 #include <openssl/dsa.h>
 #include <openssl/evp.h>
+#include <openssl/mem.h>
 #include <openssl/rsa.h>
 #include <openssl/stack.h>
-#include <openssl/x509.h>
 
 int X509_verify(X509 *a, EVP_PKEY *r)
 {
@@ -201,154 +205,102 @@
 }
 
 #ifndef OPENSSL_NO_FP_API
-RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
-{
-    return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa);
-}
 
-int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
-{
-    return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa);
-}
+#define IMPLEMENT_D2I_FP(type, name, bio_func) \
+  type *name(FILE *fp, type **obj) {           \
+    BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE);    \
+    if (bio == NULL) {                         \
+      return NULL;                             \
+    }                                          \
+    type *ret = bio_func(bio, obj);            \
+    BIO_free(bio);                             \
+    return ret;                                \
+  }
 
-RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
-{
-    return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa);
-}
+#define IMPLEMENT_I2D_FP(type, name, bio_func) \
+  int name(FILE *fp, type *obj) {              \
+    BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE);    \
+    if (bio == NULL) {                         \
+      return 0;                                \
+    }                                          \
+    int ret = bio_func(bio, obj);              \
+    BIO_free(bio);                             \
+    return ret;                                \
+  }
 
-RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
-{
-    return ASN1_d2i_fp((void *(*)(void))
-                       RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp,
-                       (void **)rsa);
-}
+IMPLEMENT_D2I_FP(RSA, d2i_RSAPrivateKey_fp, d2i_RSAPrivateKey_bio)
+IMPLEMENT_I2D_FP(RSA, i2d_RSAPrivateKey_fp, i2d_RSAPrivateKey_bio)
 
-int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
-{
-    return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa);
-}
+IMPLEMENT_D2I_FP(RSA, d2i_RSAPublicKey_fp, d2i_RSAPublicKey_bio)
+IMPLEMENT_I2D_FP(RSA, i2d_RSAPublicKey_fp, i2d_RSAPublicKey_bio)
 
-int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
-{
-    return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY, fp, rsa);
-}
+IMPLEMENT_D2I_FP(RSA, d2i_RSA_PUBKEY_fp, d2i_RSA_PUBKEY_bio)
+IMPLEMENT_I2D_FP(RSA, i2d_RSA_PUBKEY_fp, i2d_RSA_PUBKEY_bio)
 #endif
 
-RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
-{
-    return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa);
-}
+#define IMPLEMENT_D2I_BIO(type, name, d2i_func)         \
+  type *name(BIO *bio, type **obj) {                    \
+    uint8_t *data;                                      \
+    size_t len;                                         \
+    if (!BIO_read_asn1(bio, &data, &len, 100 * 1024)) { \
+      return NULL;                                      \
+    }                                                   \
+    const uint8_t *ptr = data;                          \
+    type *ret = d2i_func(obj, &ptr, (long)len);         \
+    OPENSSL_free(data);                                 \
+    return ret;                                         \
+  }
 
-int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
-{
-    return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa);
-}
+#define IMPLEMENT_I2D_BIO(type, name, i2d_func) \
+  int name(BIO *bio, type *obj) {               \
+    uint8_t *data = NULL;                       \
+    int len = i2d_func(obj, &data);             \
+    if (len < 0) {                              \
+      return 0;                                 \
+    }                                           \
+    int ret = BIO_write_all(bio, data, len);    \
+    OPENSSL_free(data);                         \
+    return ret;                                 \
+  }
 
-RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
-{
-    return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa);
-}
+IMPLEMENT_D2I_BIO(RSA, d2i_RSAPrivateKey_bio, d2i_RSAPrivateKey)
+IMPLEMENT_I2D_BIO(RSA, i2d_RSAPrivateKey_bio, i2d_RSAPrivateKey)
 
-RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
-{
-    return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa);
-}
+IMPLEMENT_D2I_BIO(RSA, d2i_RSAPublicKey_bio, d2i_RSAPublicKey)
+IMPLEMENT_I2D_BIO(RSA, i2d_RSAPublicKey_bio, i2d_RSAPublicKey)
 
-int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
-{
-    return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa);
-}
-
-int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
-{
-    return ASN1_i2d_bio_of_const(RSA, i2d_RSA_PUBKEY, bp, rsa);
-}
+IMPLEMENT_D2I_BIO(RSA, d2i_RSA_PUBKEY_bio, d2i_RSA_PUBKEY)
+IMPLEMENT_I2D_BIO(RSA, i2d_RSA_PUBKEY_bio, i2d_RSA_PUBKEY)
 
 #ifndef OPENSSL_NO_DSA
 # ifndef OPENSSL_NO_FP_API
-DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
-{
-    return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa);
-}
+IMPLEMENT_D2I_FP(DSA, d2i_DSAPrivateKey_fp, d2i_DSAPrivateKey_bio)
+IMPLEMENT_I2D_FP(DSA, i2d_DSAPrivateKey_fp, i2d_DSAPrivateKey_bio)
 
-int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa)
-{
-    return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa);
-}
-
-DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
-{
-    return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa);
-}
-
-int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
-{
-    return ASN1_i2d_fp_of_const(DSA, i2d_DSA_PUBKEY, fp, dsa);
-}
+IMPLEMENT_D2I_FP(DSA, d2i_DSA_PUBKEY_fp, d2i_DSA_PUBKEY_bio)
+IMPLEMENT_I2D_FP(DSA, i2d_DSA_PUBKEY_fp, i2d_DSA_PUBKEY_bio)
 # endif
 
-DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
-{
-    return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa);
-}
+IMPLEMENT_D2I_BIO(DSA, d2i_DSAPrivateKey_bio, d2i_DSAPrivateKey)
+IMPLEMENT_I2D_BIO(DSA, i2d_DSAPrivateKey_bio, i2d_DSAPrivateKey)
 
-int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa)
-{
-    return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa);
-}
-
-DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
-{
-    return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa);
-}
-
-int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
-{
-    return ASN1_i2d_bio_of_const(DSA, i2d_DSA_PUBKEY, bp, dsa);
-}
-
+IMPLEMENT_D2I_BIO(DSA, d2i_DSA_PUBKEY_bio, d2i_DSA_PUBKEY)
+IMPLEMENT_I2D_BIO(DSA, i2d_DSA_PUBKEY_bio, i2d_DSA_PUBKEY)
 #endif
 
 #ifndef OPENSSL_NO_FP_API
-EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
-{
-    return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey);
-}
+IMPLEMENT_D2I_FP(EC_KEY, d2i_ECPrivateKey_fp, d2i_ECPrivateKey_bio)
+IMPLEMENT_I2D_FP(EC_KEY, i2d_ECPrivateKey_fp, i2d_ECPrivateKey_bio)
 
-int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey)
-{
-    return ASN1_i2d_fp_of_const(EC_KEY, i2d_EC_PUBKEY, fp, eckey);
-}
-
-EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
-{
-    return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey);
-}
-
-int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey)
-{
-    return ASN1_i2d_fp_of_const(EC_KEY, i2d_ECPrivateKey, fp, eckey);
-}
+IMPLEMENT_D2I_FP(EC_KEY, d2i_EC_PUBKEY_fp, d2i_EC_PUBKEY_bio)
+IMPLEMENT_I2D_FP(EC_KEY, i2d_EC_PUBKEY_fp, i2d_EC_PUBKEY_bio)
 #endif
-EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
-{
-    return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey);
-}
 
-int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa)
-{
-    return ASN1_i2d_bio_of_const(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa);
-}
+IMPLEMENT_D2I_BIO(EC_KEY, d2i_ECPrivateKey_bio, d2i_ECPrivateKey)
+IMPLEMENT_I2D_BIO(EC_KEY, i2d_ECPrivateKey_bio, i2d_ECPrivateKey)
 
-EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
-{
-    return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey);
-}
-
-int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
-{
-    return ASN1_i2d_bio_of_const(EC_KEY, i2d_ECPrivateKey, bp, eckey);
-}
+IMPLEMENT_D2I_BIO(EC_KEY, d2i_EC_PUBKEY_bio, d2i_EC_PUBKEY)
+IMPLEMENT_I2D_BIO(EC_KEY, i2d_EC_PUBKEY_bio, i2d_EC_PUBKEY)
 
 int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
                        unsigned char *md, unsigned int *len)
@@ -389,40 +341,18 @@
 }
 
 #ifndef OPENSSL_NO_FP_API
-X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
-{
-    return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8);
-}
-
-int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8)
-{
-    return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8);
-}
+IMPLEMENT_D2I_FP(X509_SIG, d2i_PKCS8_fp, d2i_PKCS8_bio)
+IMPLEMENT_I2D_FP(X509_SIG, i2d_PKCS8_fp, i2d_PKCS8_bio)
 #endif
 
-X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
-{
-    return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8);
-}
-
-int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8)
-{
-    return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8);
-}
+IMPLEMENT_D2I_BIO(X509_SIG, d2i_PKCS8_bio, d2i_X509_SIG)
+IMPLEMENT_I2D_BIO(X509_SIG, i2d_PKCS8_bio, i2d_X509_SIG)
 
 #ifndef OPENSSL_NO_FP_API
-PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
-                                                PKCS8_PRIV_KEY_INFO **p8inf)
-{
-    return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
-                          d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf);
-}
-
-int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf)
-{
-    return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp,
-                          p8inf);
-}
+IMPLEMENT_D2I_FP(PKCS8_PRIV_KEY_INFO, d2i_PKCS8_PRIV_KEY_INFO_fp,
+                 d2i_PKCS8_PRIV_KEY_INFO_bio)
+IMPLEMENT_I2D_FP(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO_fp,
+                 i2d_PKCS8_PRIV_KEY_INFO_bio)
 
 int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key)
 {
@@ -436,38 +366,16 @@
     return ret;
 }
 
-int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey)
-{
-    return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PrivateKey, fp, pkey);
-}
+IMPLEMENT_D2I_FP(EVP_PKEY, d2i_PrivateKey_fp, d2i_PrivateKey_bio)
+IMPLEMENT_I2D_FP(EVP_PKEY, i2d_PrivateKey_fp, i2d_PrivateKey_bio)
 
-EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
-{
-    return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a);
-}
+IMPLEMENT_D2I_FP(EVP_PKEY, d2i_PUBKEY_fp, d2i_PUBKEY_bio)
+IMPLEMENT_I2D_FP(EVP_PKEY, i2d_PUBKEY_fp, i2d_PUBKEY_bio)
 
-int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
-{
-    return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PUBKEY, fp, pkey);
-}
-
-EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
-{
-    return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a);
-}
-
-PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
-                                                 PKCS8_PRIV_KEY_INFO **p8inf)
-{
-    return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
-                           d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf);
-}
-
-int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf)
-{
-    return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp,
-                           p8inf);
-}
+IMPLEMENT_D2I_BIO(PKCS8_PRIV_KEY_INFO, d2i_PKCS8_PRIV_KEY_INFO_bio,
+                  d2i_PKCS8_PRIV_KEY_INFO)
+IMPLEMENT_I2D_BIO(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO_bio,
+                  i2d_PKCS8_PRIV_KEY_INFO)
 
 int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key)
 {
@@ -482,32 +390,11 @@
 }
 #endif
 
-int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey)
-{
-    return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PrivateKey, bp, pkey);
-}
+IMPLEMENT_D2I_BIO(EVP_PKEY, d2i_PrivateKey_bio, d2i_AutoPrivateKey)
+IMPLEMENT_I2D_BIO(EVP_PKEY, i2d_PrivateKey_bio, i2d_PrivateKey)
 
-EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
-{
-    return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a);
-}
+IMPLEMENT_D2I_BIO(EVP_PKEY, d2i_PUBKEY_bio, d2i_PUBKEY)
+IMPLEMENT_I2D_BIO(EVP_PKEY, i2d_PUBKEY_bio, i2d_PUBKEY)
 
-int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
-{
-    return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PUBKEY, bp, pkey);
-}
-
-EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
-{
-    return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a);
-}
-
-DH *d2i_DHparams_bio(BIO *bp, DH **dh)
-{
-    return ASN1_d2i_bio_of(DH, DH_new, d2i_DHparams, bp, dh);
-}
-
-int i2d_DHparams_bio(BIO *bp, const DH *dh)
-{
-    return ASN1_i2d_bio_of_const(DH, i2d_DHparams, bp, dh);
-}
+IMPLEMENT_D2I_BIO(DH, d2i_DHparams_bio, d2i_DHparams)
+IMPLEMENT_I2D_BIO(const DH, i2d_DHparams_bio, i2d_DHparams)