Deduplicate d2i and i2d documentation.

There are a lot of d2i and i2d functions, and there will be even more
once asn1.h and x509.h are properly documented. We currently replicate
the text in each, but as a result a miss a few points:

- The i2d outp != NULL, *outp == NULL case isn't documented at all.

- We should call out what to do with *inp after d2i.

- Unlike our rewritten functions, object reuse is still quite rampant
  with the asn1.h functions. I hope we can get rid of that but, until we
  can, it would be nice to describe it in one place.

While I'm here, update a few references to the latest PKCS#1 RFC, and
try to align how we reference ASN.1 structures a bit. The d2i/i2d
functions say "ASN.1, DER-encoded RSA private key" while the CBS/CBB
functions say "DER-encoded RSAPrivateKey structure".

Bug: 426
Change-Id: I8d9a7b0aef3d6d9c8240136053c3b1704b09fd41
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/49906
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/evp/evp_asn1.c b/crypto/evp/evp_asn1.c
index 2f3e115..da09981 100644
--- a/crypto/evp/evp_asn1.c
+++ b/crypto/evp/evp_asn1.c
@@ -369,8 +369,8 @@
     // Unlike OpenSSL, we do not support EC keys with this API. The raw EC
     // public key serialization requires knowing the group. In OpenSSL, calling
     // this function with |EVP_PKEY_EC| and setting |out| to NULL does not work.
-    // It requires |*out| to include a partially-initiazed |EVP_PKEY| to extract
-    // the group.
+    // It requires |*out| to include a partially-initialized |EVP_PKEY| to
+    // extract the group.
     default:
       OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
       goto err;
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index 5ef3742..923e3d3 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -565,6 +565,84 @@
 OPENSSL_EXPORT int CBB_flush_asn1_set_of(CBB *cbb);
 
 
+// Legacy ASN.1 API conventions.
+//
+// The following sample functions document the calling conventions used by
+// legacy ASN.1 APIs.
+//
+// TODO(https://crbug.com/boringssl/426): When asn1.h is fully documented and
+// added to doc.go, move this section to asn1.h.
+
+#if 0  // Sample functions
+
+// d2i_SAMPLE parses a structure from up to |len| bytes at |*inp|. On success,
+// it advances |*inp| by the number of bytes read and returns a newly-allocated
+// |SAMPLE| object containing the parsed structure. If |out| is non-NULL, it
+// additionally frees the previous value at |*out| and updates |*out| to the
+// result. If parsing or allocating the result fails, it returns NULL.
+//
+// This function does not reject trailing data in the input. This allows the
+// caller to parse a sequence of concatenated structures. Callers parsing only
+// one structure should check for trailing data by comparing the updated |*inp|
+// with the end of the input.
+//
+// Note: If |out| and |*out| are both non-NULL, the object at |*out| is not
+// updated in-place. Instead, it is freed, and the pointer is updated to the
+// new object. This differs from OpenSSL, which behaves more like
+// |d2i_SAMPLE_with_reuse|. Callers are recommended to set |out| to NULL and
+// instead use the return value.
+SAMPLE *d2i_SAMPLE(SAMPLE **out, const uint8_t **inp, long len);
+
+// d2i_SAMPLE_with_reuse parses a structure from up to |len| bytes at |*inp|. On
+// success, it advances |*inp| by the number of bytes read and returns a
+// non-NULL pointer to an object containing the parsed structure. The object is
+// determined from |out| as follows:
+//
+// If |out| is NULL, the function places the result in a newly-allocated
+// |SAMPLE| object and returns it. This mode is recommended.
+//
+// If |out| is non-NULL, but |*out| is NULL, the function also places the result
+// in a newly-allocated |SAMPLE| object. It sets |*out| to this object and also
+// returns it.
+//
+// If |out| and |*out| are both non-NULL, the function updates the object at
+// |*out| in-place with the result and returns |*out|.
+//
+// If any of the above fail, the function returns NULL.
+//
+// This function does not reject trailing data in the input. This allows the
+// caller to parse a sequence of concatenated structures. Callers parsing only
+// one structure should check for trailing data by comparing the updated |*inp|
+// with the end of the input.
+//
+// WARNING: Callers should not rely on the in-place update mode. It often
+// produces the wrong result or breaks the type's internal invariants. Future
+// revisions of BoringSSL may standardize on the |d2i_SAMPLE| behavior.
+SAMPLE *d2i_SAMPLE_with_reuse(SAMPLE **out, const uint8_t **inp, long len);
+
+// i2d_SAMPLE marshals |in|. On error, it returns a negative value. On success,
+// it returns the length of the result and outputs it via |outp| as follows:
+//
+// If |outp| is NULL, the function writes nothing. This mode can be used to size
+// buffers.
+//
+// If |outp| is non-NULL but |*outp| is NULL, the function sets |*outp| to a
+// newly-allocated buffer containing the result. The caller is responsible for
+// releasing |*outp| with |OPENSSL_free|. This mode is recommended for most
+// callers.
+//
+// If |outp| and |*outp| are non-NULL, the function writes the result to
+// |*outp|, which must have enough space available, and advances |*outp| just
+// past the output.
+//
+// WARNING: In the third mode, the function does not internally check output
+// bounds. Failing to correctly size the buffer will result in a potentially
+// exploitable memory error.
+int i2d_SAMPLE(const SAMPLE *in, uint8_t **outp);
+
+#endif  // Sample functions
+
+
 #if defined(__cplusplus)
 }  // extern C
 
diff --git a/include/openssl/dh.h b/include/openssl/dh.h
index 9a86e9e..21c9623 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -267,22 +267,14 @@
                                           void (*callback)(int, int, void *),
                                           void *cb_arg);
 
-// d2i_DHparams parses an ASN.1, DER encoded Diffie-Hellman parameters structure
-// from |len| bytes at |*inp|. If |ret| is not NULL then, on exit, a pointer to
-// the result is in |*ret|. Note that, even if |*ret| is already non-NULL on
-// entry, it will not be written to. Rather, a fresh |DH| is allocated and the
-// previous one is freed.
-//
-// On successful exit, |*inp| is advanced past the DER structure. It
-// returns the result or NULL on error.
+// d2i_DHparams parses a DER-encoded DHParameter structure (PKCS #3) from |len|
+// bytes at |*inp|, as in |d2i_SAMPLE|.
 //
 // Use |DH_parse_parameters| instead.
 OPENSSL_EXPORT DH *d2i_DHparams(DH **ret, const unsigned char **inp, long len);
 
-// i2d_DHparams 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.
+// i2d_DHparams marshals |in| to a DER-encoded DHParameter structure (PKCS #3),
+// as described in |i2d_SAMPLE|.
 //
 // Use |DH_marshal_parameters| instead.
 OPENSSL_EXPORT int i2d_DHparams(const DH *in, unsigned char **outp);
diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h
index e8ae88a..1665251 100644
--- a/include/openssl/dsa.h
+++ b/include/openssl/dsa.h
@@ -299,7 +299,7 @@
 OPENSSL_EXPORT DSA *DSA_parse_parameters(CBS *cbs);
 
 // DSA_marshal_parameters marshals |dsa| as a DER-encoded Dss-Parms structure
-// (RFC 3447) and appends the result to |cbb|. It returns one on success and
+// (RFC 3279) and appends the result to |cbb|. It returns one on success and
 // zero on failure.
 OPENSSL_EXPORT int DSA_marshal_parameters(CBB *cbb, const DSA *dsa);
 
@@ -326,75 +326,51 @@
 
 // Deprecated functions.
 
-// d2i_DSA_SIG parses an ASN.1, DER-encoded, DSA signature from |len| bytes at
-// |*inp|. If |out_sig| is not NULL then, on exit, a pointer to the result is
-// in |*out_sig|. Note that, even if |*out_sig| is already non-NULL on entry, it
-// will not be written to. Rather, a fresh |DSA_SIG| is allocated and the
-// previous one is freed. On successful exit, |*inp| is advanced past the DER
-// structure. It returns the result or NULL on error.
+// d2i_DSA_SIG parses a DER-encoded DSA-Sig-Value structure from |len| bytes at
+// |*inp|, as described in |d2i_SAMPLE|.
 //
 // Use |DSA_SIG_parse| instead.
 OPENSSL_EXPORT DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp,
                                     long len);
 
-// i2d_DSA_SIG 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.
+// i2d_DSA_SIG marshals |in| to a DER-encoded DSA-Sig-Value structure, as
+// described in |i2d_SAMPLE|.
 //
 // Use |DSA_SIG_marshal| instead.
 OPENSSL_EXPORT int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp);
 
-// d2i_DSAPublicKey parses an ASN.1, DER-encoded, DSA public key from |len|
-// bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
-// is in |*out|. Note that, even if |*ou| is already non-NULL on entry, it will
-// not be written to. Rather, a fresh |DSA| is allocated and the previous one is
-// freed. On successful exit, |*inp| is advanced past the DER structure. It
-// returns the result or NULL on error.
+// d2i_DSAPublicKey parses a DER-encoded DSA public key from |len| bytes at
+// |*inp|, as described in |d2i_SAMPLE|.
 //
 // Use |DSA_parse_public_key| instead.
 OPENSSL_EXPORT DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len);
 
-// i2d_DSAPublicKey marshals a public key from |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.
+// i2d_DSAPublicKey marshals |in| as a DER-encoded DSA public key, as described
+// in |i2d_SAMPLE|.
 //
 // Use |DSA_marshal_public_key| instead.
 OPENSSL_EXPORT int i2d_DSAPublicKey(const DSA *in, uint8_t **outp);
 
-// d2i_DSAPrivateKey parses an ASN.1, DER-encoded, DSA private key from |len|
-// bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
-// is in |*out|. Note that, even if |*out| is already non-NULL on entry, it will
-// not be written to. Rather, a fresh |DSA| is allocated and the previous one is
-// freed. On successful exit, |*inp| is advanced past the DER structure. It
-// returns the result or NULL on error.
+// d2i_DSAPrivateKey parses a DER-encoded DSA private key from |len| bytes at
+// |*inp|, as described in |d2i_SAMPLE|.
 //
 // Use |DSA_parse_private_key| instead.
 OPENSSL_EXPORT DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len);
 
-// i2d_DSAPrivateKey marshals a private key from |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.
+// i2d_DSAPrivateKey marshals |in| as a DER-encoded DSA private key, as
+// described in |i2d_SAMPLE|.
 //
 // Use |DSA_marshal_private_key| instead.
 OPENSSL_EXPORT int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp);
 
-// d2i_DSAparams parses ASN.1, DER-encoded, DSA parameters from |len| bytes at
-// |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
-// |*out|. Note that, even if |*out| is already non-NULL on entry, it will not
-// be written to. Rather, a fresh |DSA| is allocated and the previous one is
-// freed. On successful exit, |*inp| is advanced past the DER structure. It
-// returns the result or NULL on error.
+// d2i_DSAparams parses a DER-encoded Dss-Parms structure (RFC 3279) from |len|
+// bytes at |*inp|, as described in |d2i_SAMPLE|.
 //
 // Use |DSA_parse_parameters| instead.
 OPENSSL_EXPORT DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len);
 
-// i2d_DSAparams marshals DSA parameters from |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.
+// i2d_DSAparams marshals |in|'s parameters as a DER-encoded Dss-Parms structure
+// (RFC 3279), as described in |i2d_SAMPLE|.
 //
 // Use |DSA_marshal_parameters| instead.
 OPENSSL_EXPORT int i2d_DSAparams(const DSA *in, uint8_t **outp);
diff --git a/include/openssl/ec_key.h b/include/openssl/ec_key.h
index 932ad8e..3a40856 100644
--- a/include/openssl/ec_key.h
+++ b/include/openssl/ec_key.h
@@ -294,43 +294,30 @@
 // EC_KEY_set_asn1_flag does nothing.
 OPENSSL_EXPORT void EC_KEY_set_asn1_flag(EC_KEY *key, int flag);
 
-// d2i_ECPrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes
-// at |*inp|. If |out_key| is not NULL then, on exit, a pointer to the result
-// is in |*out_key|. Note that, even if |*out_key| is already non-NULL on entry,
-// it * will not be written to. Rather, a fresh |EC_KEY| is allocated and the
-// previous * one is freed. On successful exit, |*inp| is advanced past the DER
-// structure. It returns the result or NULL on error.
-//
-// On input, if |*out_key| is non-NULL and has a group configured, the
-// parameters field may be omitted but must match that group if present.
+// d2i_ECPrivateKey parses a DER-encoded ECPrivateKey structure (RFC 5915) from
+// |len| bytes at |*inp|, as described in |d2i_SAMPLE|. On input, if |*out_key|
+// is non-NULL and has a group configured, the parameters field may be omitted
+// but must match that group if present.
 //
 // Use |EC_KEY_parse_private_key| instead.
 OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey(EC_KEY **out_key, const uint8_t **inp,
                                         long len);
 
-// i2d_ECPrivateKey marshals an EC private key from |key| 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.
+// i2d_ECPrivateKey marshals |key| as a DER-encoded ECPrivateKey structure (RFC
+// 5915), as described in |i2d_SAMPLE|.
 //
 // Use |EC_KEY_marshal_private_key| instead.
 OPENSSL_EXPORT int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp);
 
-// d2i_ECParameters parses an ASN.1, DER-encoded, set of EC parameters from
-// |len| bytes at |*inp|. If |out_key| is not NULL then, on exit, a pointer to
-// the result is in |*out_key|. Note that, even if |*out_key| is already
-// non-NULL on entry, it will not be written to. Rather, a fresh |EC_KEY| is
-// allocated and the previous one is freed. On successful exit, |*inp| is
-// advanced past the DER structure. It returns the result or NULL on error.
+// d2i_ECParameters parses a DER-encoded ECParameters structure (RFC 5480) from
+// |len| bytes at |*inp|, as described in |d2i_SAMPLE|.
 //
 // Use |EC_KEY_parse_parameters| or |EC_KEY_parse_curve_name| instead.
 OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp,
                                         long len);
 
-// i2d_ECParameters marshals EC parameters from |key| 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.
+// i2d_ECParameters marshals |key|'s parameters as a DER-encoded OBJECT
+// IDENTIFIER, as described in |i2d_SAMPLE|.
 //
 // Use |EC_KEY_marshal_curve_name| instead.
 OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp);
@@ -344,10 +331,8 @@
 OPENSSL_EXPORT EC_KEY *o2i_ECPublicKey(EC_KEY **out_key, const uint8_t **inp,
                                        long len);
 
-// i2o_ECPublicKey marshals an EC point from |key|. 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.
+// i2o_ECPublicKey marshals an EC point from |key|, as described in
+// |i2d_SAMPLE|.
 //
 // Use |EC_POINT_point2cbb| instead.
 OPENSSL_EXPORT int i2o_ECPublicKey(const EC_KEY *key, unsigned char **outp);
diff --git a/include/openssl/ecdsa.h b/include/openssl/ecdsa.h
index 5443ef5..bc0dba5 100644
--- a/include/openssl/ecdsa.h
+++ b/include/openssl/ecdsa.h
@@ -197,19 +197,17 @@
 
 // Deprecated functions.
 
-// d2i_ECDSA_SIG parses an ASN.1, DER-encoded, signature from |len| bytes at
-// |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
-// |*out|. Note that, even if |*out| is already non-NULL on entry, it will not
-// be written to. Rather, a fresh |ECDSA_SIG| is allocated and the previous one
-// is freed. On successful exit, |*inp| is advanced past the DER structure. It
-// returns the result or NULL on error.
+// d2i_ECDSA_SIG parses aa DER-encoded ECDSA-Sig-Value structure from |len|
+// bytes at |*inp|, as described in |d2i_SAMPLE|.
+//
+// Use |ECDSA_SIG_parse| instead.
 OPENSSL_EXPORT ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp,
                                         long len);
 
-// i2d_ECDSA_SIG marshals a signature from |sig| 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.
+// i2d_ECDSA_SIG marshals |sig| as a DER-encoded ECDSA-Sig-Value, as described
+// in |i2d_SAMPLE|.
+//
+// Use |ECDSA_SIG_marshal| instead.
 OPENSSL_EXPORT int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp);
 
 
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index c567875..e195907 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -873,34 +873,27 @@
                                                    void *arg),
                                   void *arg);
 
-// i2d_PrivateKey marshals a private key from |key| 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.
+// i2d_PrivateKey marshals a private key from |key| to type-specific format, as
+// described in |i2d_SAMPLE|.
 //
-// RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 3447) structure.
+// RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 8017) structure.
 // EC keys are serialized as a DER-encoded ECPrivateKey (RFC 5915) structure.
 //
 // Use |RSA_marshal_private_key| or |EC_KEY_marshal_private_key| instead.
 OPENSSL_EXPORT int i2d_PrivateKey(const EVP_PKEY *key, uint8_t **outp);
 
-// i2d_PublicKey marshals a public key from |key| to a type-specific format.
-// 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.
+// i2d_PublicKey marshals a public key from |key| to a type-specific format, as
+// described in |i2d_SAMPLE|.
 //
-// RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 3447) structure.
+// RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 8017) structure.
 // EC keys are serialized as an EC point per SEC 1.
 //
 // Use |RSA_marshal_public_key| or |EC_POINT_point2cbb| instead.
 OPENSSL_EXPORT int i2d_PublicKey(const EVP_PKEY *key, uint8_t **outp);
 
-// d2i_PrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes at
-// |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
-// |*out|. Note that, even if |*out| is already non-NULL on entry, it will not
-// be written to. Rather, a fresh |EVP_PKEY| is allocated and the previous one
-// is freed. On successful exit, |*inp| is advanced past the DER structure. It
-// returns the result or NULL on error.
+// d2i_PrivateKey parses a DER-encoded private key from |len| bytes at |*inp|,
+// as described in |d2i_SAMPLE|. The private key must have type |type|,
+// otherwise it will be rejected.
 //
 // This function tries to detect one of several formats. Instead, use
 // |EVP_parse_private_key| for a PrivateKeyInfo, |RSA_parse_private_key| for an
@@ -917,15 +910,12 @@
 OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp,
                                             long len);
 
-// d2i_PublicKey parse a public key from |len| bytes at |*inp| in a type-
-// specific format specified by |type|. If |out| is not NULL then, on exit, a
-// pointer to the result is in |*out|. Note that, even if |*out| is already non-
-// NULL on entry, it will not be written to. Rather, a fresh |EVP_PKEY| is
-// allocated and the previous one is freed. On successful exit, |*inp| is
-// advanced past the decoded key. It returns the result or NULL on error.
+// d2i_PublicKey parses a public key from |len| bytes at |*inp| in a type-
+// specific format specified by |type|, as described in |d2i_SAMPLE|.
 //
-// RSA keys are parsed as a DER-encoded RSAPublicKey (RFC 3447) structure.
-// Parsing EC keys is not supported by this function.
+// The only supported value for |type| is |EVP_PKEY_RSA|, which parses a
+// DER-encoded RSAPublicKey (RFC 8017) structure. Parsing EC keys is not
+// supported by this function.
 //
 // Use |RSA_parse_public_key| instead.
 OPENSSL_EXPORT EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **out,
@@ -974,70 +964,54 @@
 OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(EVP_PKEY_CTX *ctx,
                                                            const EVP_MD *md);
 
-// i2d_PUBKEY marshals a public key from |pkey| as a DER-encoded
-// SubjectPublicKeyInfo. If |outp| is not NULL, 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.
+// i2d_PUBKEY marshals |pkey| as a DER-encoded SubjectPublicKeyInfo, as
+// described in |i2d_SAMPLE|.
 //
 // Use |EVP_marshal_public_key| instead.
 OPENSSL_EXPORT int i2d_PUBKEY(const EVP_PKEY *pkey, uint8_t **outp);
 
 // d2i_PUBKEY parses a DER-encoded SubjectPublicKeyInfo from |len| bytes at
-// |*inp|. It returns a newly-allocated result, or NULL on error. On success,
-// |*inp| is advanced past the DER structure. If |out| is not NULL, it also
-// frees any existing object pointed by |*out| and writes the result.
+// |*inp|, as described in |d2i_SAMPLE|.
 //
 // Use |EVP_parse_public_key| instead.
 OPENSSL_EXPORT EVP_PKEY *d2i_PUBKEY(EVP_PKEY **out, const uint8_t **inp,
                                     long len);
 
-// i2d_RSA_PUBKEY marshals |rsa| as a DER-encoded SubjectPublicKeyInfo. If
-// |outp| is not NULL, 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.
+// i2d_RSA_PUBKEY marshals |rsa| as a DER-encoded SubjectPublicKeyInfo
+// structure, as described in |i2d_SAMPLE|.
 //
 // Use |EVP_marshal_public_key| instead.
 OPENSSL_EXPORT int i2d_RSA_PUBKEY(const RSA *rsa, uint8_t **outp);
 
 // d2i_RSA_PUBKEY parses an RSA public key as a DER-encoded SubjectPublicKeyInfo
-// from |len| bytes at |*inp|. It returns a newly-allocated result, or NULL on
-// error. On success, |*inp| is advanced past the DER structure. If |out| is not
-// NULL, it also frees any existing object pointed by |*out| and writes the
-// result.
+// from |len| bytes at |*inp|, as described in |d2i_SAMPLE|.
+// SubjectPublicKeyInfo structures containing other key types are rejected.
 //
 // Use |EVP_parse_public_key| instead.
 OPENSSL_EXPORT RSA *d2i_RSA_PUBKEY(RSA **out, const uint8_t **inp, long len);
 
-// i2d_DSA_PUBKEY marshals |dsa| as a DER-encoded SubjectPublicKeyInfo. If
-// |outp| is not NULL, 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.
+// i2d_DSA_PUBKEY marshals |dsa| as a DER-encoded SubjectPublicKeyInfo, as
+// described in |i2d_SAMPLE|.
 //
 // Use |EVP_marshal_public_key| instead.
 OPENSSL_EXPORT int i2d_DSA_PUBKEY(const DSA *dsa, uint8_t **outp);
 
 // d2i_DSA_PUBKEY parses a DSA public key as a DER-encoded SubjectPublicKeyInfo
-// from |len| bytes at |*inp|. It returns a newly-allocated result, or NULL on
-// error. On success, |*inp| is advanced past the DER structure. If |out| is not
-// NULL, it also frees any existing object pointed by |*out| and writes the
-// result.
+// from |len| bytes at |*inp|, as described in |d2i_SAMPLE|.
+// SubjectPublicKeyInfo structures containing other key types are rejected.
 //
 // Use |EVP_parse_public_key| instead.
 OPENSSL_EXPORT DSA *d2i_DSA_PUBKEY(DSA **out, const uint8_t **inp, long len);
 
-// i2d_EC_PUBKEY marshals |ec_key| as a DER-encoded SubjectPublicKeyInfo. If
-// |outp| is not NULL, 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.
+// i2d_EC_PUBKEY marshals |ec_key| as a DER-encoded SubjectPublicKeyInfo, as
+// described in |i2d_SAMPLE|.
 //
 // Use |EVP_marshal_public_key| instead.
 OPENSSL_EXPORT int i2d_EC_PUBKEY(const EC_KEY *ec_key, uint8_t **outp);
 
 // d2i_EC_PUBKEY parses an EC public key as a DER-encoded SubjectPublicKeyInfo
-// from |len| bytes at |*inp|. It returns a newly-allocated result, or NULL on
-// error. On success, |*inp| is advanced past the DER structure. If |out| is not
-// NULL, it also frees any existing object pointed by |*out| and writes the
-// result.
+// from |len| bytes at |*inp|, as described in |d2i_SAMPLE|.
+// SubjectPublicKeyInfo structures containing other key types are rejected.
 //
 // Use |EVP_parse_public_key| instead.
 OPENSSL_EXPORT EC_KEY *d2i_EC_PUBKEY(EC_KEY **out, const uint8_t **inp,
diff --git a/include/openssl/pkcs7.h b/include/openssl/pkcs7.h
index 77e13d7..429e91c 100644
--- a/include/openssl/pkcs7.h
+++ b/include/openssl/pkcs7.h
@@ -137,11 +137,7 @@
 } PKCS7;
 
 // d2i_PKCS7 parses a BER-encoded, PKCS#7 signed data ContentInfo structure from
-// |len| bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the
-// result is in |*out|. Note that, even if |*out| is already non-NULL on entry,
-// it will not be written to. Rather, a fresh |PKCS7| is allocated and the
-// previous one is freed. On successful exit, |*inp| is advanced past the BER
-// structure.  It returns the result or NULL on error.
+// |len| bytes at |*inp|, as described in |d2i_SAMPLE|.
 OPENSSL_EXPORT PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp,
                                 size_t len);
 
@@ -152,10 +148,8 @@
 // from |bio|.
 OPENSSL_EXPORT PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out);
 
-// i2d_PKCS7 is a dummy function which copies the contents of |p7|. If |out| is
-// not NULL then the result is written to |*out| and |*out| 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.
+// i2d_PKCS7 marshals |p7| as a DER-encoded PKCS#7 ContentInfo structure, as
+// described in |i2d_SAMPLE|.
 OPENSSL_EXPORT int i2d_PKCS7(const PKCS7 *p7, uint8_t **out);
 
 // i2d_PKCS7_bio writes |p7| to |bio|. It returns one on success and zero on
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index 95a478a..b1336dd 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -526,44 +526,44 @@
 
 // ASN.1 functions.
 
-// RSA_parse_public_key parses a DER-encoded RSAPublicKey structure (RFC 3447)
+// RSA_parse_public_key parses a DER-encoded RSAPublicKey structure (RFC 8017)
 // from |cbs| and advances |cbs|. It returns a newly-allocated |RSA| or NULL on
 // error.
 OPENSSL_EXPORT RSA *RSA_parse_public_key(CBS *cbs);
 
 // 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.
+// (RFC 8017). 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
+// (RFC 8017) 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
+// structure (RFC 8017) 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);
 
-// RSA_parse_private_key parses a DER-encoded RSAPrivateKey structure (RFC 3447)
+// RSA_parse_private_key parses a DER-encoded RSAPrivateKey structure (RFC 8017)
 // from |cbs| and advances |cbs|. It returns a newly-allocated |RSA| or NULL on
 // error.
 OPENSSL_EXPORT RSA *RSA_parse_private_key(CBS *cbs);
 
 // RSA_private_key_from_bytes parses |in| as a DER-encoded RSAPrivateKey
-// structure (RFC 3447). It returns a newly-allocated |RSA| or NULL on error.
+// structure (RFC 8017). It returns a newly-allocated |RSA| or NULL on error.
 OPENSSL_EXPORT RSA *RSA_private_key_from_bytes(const uint8_t *in,
                                                size_t in_len);
 
 // RSA_marshal_private_key marshals |rsa| as a DER-encoded RSAPrivateKey
-// structure (RFC 3447) and appends the result to |cbb|. It returns one on
+// structure (RFC 8017) and appends the result to |cbb|. It returns one on
 // success and zero on failure.
 OPENSSL_EXPORT int RSA_marshal_private_key(CBB *cbb, const RSA *rsa);
 
 // RSA_private_key_to_bytes marshals |rsa| as a DER-encoded RSAPrivateKey
-// structure (RFC 3447) and, on success, sets |*out_bytes| to a newly allocated
+// structure (RFC 8017) 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_private_key_to_bytes(uint8_t **out_bytes,
@@ -625,32 +625,28 @@
 OPENSSL_EXPORT RSA *RSA_generate_key(int bits, unsigned long e, void *callback,
                                      void *cb_arg);
 
-// 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|. Note that, even if |*out| is already non-NULL on entry, it
-// will not be written to. Rather, a fresh |RSA| is allocated and the previous
-// one is freed. On successful exit, |*inp| is advanced past the DER structure.
-// It returns the result or NULL on error.
+// d2i_RSAPublicKey parses a DER-encoded RSAPublicKey structure (RFC 8017) from
+// |len| bytes at |*inp|, as described in |d2i_SAMPLE|.
+//
+// Use |RSA_parse_public_key| instead.
 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.
+// i2d_RSAPublicKey marshals |in| to a DER-encoded RSAPublicKey structure (RFC
+// 8017), as described in |i2d_SAMPLE|.
+//
+// Use |RSA_marshal_public_key| instead.
 OPENSSL_EXPORT int i2d_RSAPublicKey(const RSA *in, uint8_t **outp);
 
-// 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
-// is in |*out|. Note that, even if |*out| is already non-NULL on entry, it
-// will not be written to. Rather, a fresh |RSA| is allocated and the previous
-// one is freed. On successful exit, |*inp| is advanced past the DER structure.
-// It returns the result or NULL on error.
+// d2i_RSAPrivateKey parses a DER-encoded RSAPrivateKey structure (RFC 8017)
+// from |len| bytes at |*inp|, as described in |d2i_SAMPLE|.
+//
+// Use |RSA_parse_private_key| instead.
 OPENSSL_EXPORT RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len);
 
-// i2d_RSAPrivateKey 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.
+// i2d_RSAPrivateKey marshals |in| to a DER-encoded RSAPrivateKey structure (RFC
+// 8017), as described in |i2d_SAMPLE|.
+//
+// Use |RSA_marshal_private_key| instead.
 OPENSSL_EXPORT int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp);
 
 // RSA_padding_add_PKCS1_PSS acts like |RSA_padding_add_PKCS1_PSS_mgf1| but the
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index f421538..f731f8f 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -4575,20 +4575,13 @@
 // SSL_MODE_HANDSHAKE_CUTTHROUGH is the same as SSL_MODE_ENABLE_FALSE_START.
 #define SSL_MODE_HANDSHAKE_CUTTHROUGH SSL_MODE_ENABLE_FALSE_START
 
-// i2d_SSL_SESSION serializes |in| to the bytes pointed to by |*pp|. On success,
-// it returns the number of bytes written and advances |*pp| by that many bytes.
-// On failure, it returns -1. If |pp| is NULL, no bytes are written and only the
-// length is returned.
+// i2d_SSL_SESSION serializes |in|, as described in |i2d_SAMPLE|.
 //
 // Use |SSL_SESSION_to_bytes| instead.
 OPENSSL_EXPORT int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp);
 
 // d2i_SSL_SESSION parses a serialized session from the |length| bytes pointed
-// to by |*pp|. It returns the new |SSL_SESSION| and advances |*pp| by the
-// number of bytes consumed on success and NULL on failure. The caller takes
-// ownership of the new session and must call |SSL_SESSION_free| when done.
-//
-// If |a| is non-NULL, |*a| is released and set the new |SSL_SESSION|.
+// to by |*pp|, as described in |d2i_SAMPLE|.
 //
 // Use |SSL_SESSION_from_bytes| instead.
 OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp,
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index db6edde..59f2adf 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -885,28 +885,16 @@
 OPENSSL_EXPORT X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp,
                                   long length);
 
-// i2d_re_X509_tbs serializes the TBSCertificate portion of |x509|. If |outp| is
-// NULL, nothing is written. Otherwise, if |*outp| is not NULL, the result is
-// written to |*outp|, which must have enough space available, and |*outp| is
-// advanced just past the output. If |outp| is non-NULL and |*outp| is NULL, it
-// sets |*outp| to a newly-allocated buffer containing the result. The caller is
-// responsible for releasing the buffer with |OPENSSL_free|. In all cases, this
-// function returns the number of bytes in the result, whether written or not,
-// or a negative value on error.
+// i2d_re_X509_tbs serializes the TBSCertificate portion of |x509|, as described
+// in |i2d_SAMPLE|.
 //
 // This function re-encodes the TBSCertificate and may not reflect |x509|'s
 // original encoding. It may be used to manually generate a signature for a new
 // certificate. To verify certificates, use |i2d_X509_tbs| instead.
 OPENSSL_EXPORT int i2d_re_X509_tbs(X509 *x509, unsigned char **outp);
 
-// i2d_X509_tbs serializes the TBSCertificate portion of |x509|. If |outp| is
-// NULL, nothing is written. Otherwise, if |*outp| is not NULL, the result is
-// written to |*outp|, which must have enough space available, and |*outp| is
-// advanced just past the output. If |outp| is non-NULL and |*outp| is NULL, it
-// sets |*outp| to a newly-allocated buffer containing the result. The caller is
-// responsible for releasing the buffer with |OPENSSL_free|. In all cases, this
-// function returns the number of bytes in the result, whether written or not,
-// or a negative value on error.
+// i2d_X509_tbs serializes the TBSCertificate portion of |x509|, as described in
+// |i2d_SAMPLE|.
 //
 // This function preserves the original encoding of the TBSCertificate and may
 // not reflect modifications made to |x509|. It may be used to manually verify
@@ -1073,13 +1061,7 @@
 OPENSSL_EXPORT int X509_REQ_get_signature_nid(const X509_REQ *req);
 
 // i2d_re_X509_REQ_tbs serializes the CertificationRequestInfo (see RFC 2986)
-// portion of |req|. If |outp| is NULL, nothing is written. Otherwise, if
-// |*outp| is not NULL, the result is written to |*outp|, which must have enough
-// space available, and |*outp| is advanced just past the output. If |outp| is
-// non-NULL and |*outp| is NULL, it sets |*outp| to a newly-allocated buffer
-// containing the result. The caller is responsible for releasing the buffer
-// with |OPENSSL_free|. In all cases, this function returns the number of bytes
-// in the result, whether written or not, or a negative value on error.
+// portion of |req|, as described in |i2d_SAMPLE|.
 //
 // This function re-encodes the CertificationRequestInfo and may not reflect
 // |req|'s original encoding. It may be used to manually generate a signature
@@ -1217,28 +1199,16 @@
 // a known NID.
 OPENSSL_EXPORT int X509_CRL_get_signature_nid(const X509_CRL *crl);
 
-// i2d_re_X509_CRL_tbs serializes the TBSCertList portion of |crl|. If |outp| is
-// NULL, nothing is written. Otherwise, if |*outp| is not NULL, the result is
-// written to |*outp|, which must have enough space available, and |*outp| is
-// advanced just past the output. If |outp| is non-NULL and |*outp| is NULL, it
-// sets |*outp| to a newly-allocated buffer containing the result. The caller is
-// responsible for releasing the buffer with |OPENSSL_free|. In all cases, this
-// function returns the number of bytes in the result, whether written or not,
-// or a negative value on error.
+// i2d_re_X509_CRL_tbs serializes the TBSCertList portion of |crl|, as described
+// in |i2d_SAMPLE|.
 //
 // This function re-encodes the TBSCertList and may not reflect |crl|'s original
 // encoding. It may be used to manually generate a signature for a new CRL. To
 // verify CRLs, use |i2d_X509_CRL_tbs| instead.
 OPENSSL_EXPORT int i2d_re_X509_CRL_tbs(X509_CRL *crl, unsigned char **outp);
 
-// i2d_X509_CRL_tbs serializes the TBSCertList portion of |crl|. If |outp| is
-// NULL, nothing is written. Otherwise, if |*outp| is not NULL, the result is
-// written to |*outp|, which must have enough space available, and |*outp| is
-// advanced just past the output. If |outp| is non-NULL and |*outp| is NULL, it
-// sets |*outp| to a newly-allocated buffer containing the result. The caller is
-// responsible for releasing the buffer with |OPENSSL_free|. In all cases, this
-// function returns the number of bytes in the result, whether written or not,
-// or a negative value on error.
+// i2d_X509_CRL_tbs serializes the TBSCertList portion of |crl|, as described in
+// |i2d_SAMPLE|.
 //
 // This function preserves the original encoding of the TBSCertList and may not
 // reflect modifications made to |crl|. It may be used to manually verify the