Const-correct the i2d/dup functions we can.

Types which do not contain an X509_NAME can be const. X509_NAME still
requires some thought. (i2d_X509_NAME can mutate the object and isn't
even thread-safe when modified.)

Bug: 407
Change-Id: Iceafa2b4ea9c4194cfcc3044d90393b5d91f7c11
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/53305
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: Bob Beck <bbe@google.com>
diff --git a/.clang-format b/.clang-format
index 68c331a..0ab585e 100644
--- a/.clang-format
+++ b/.clang-format
@@ -38,6 +38,7 @@
   - "IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname"
   - "IMPLEMENT_ASN1_ALLOC_FUNCTIONS_pfname"
   - "IMPLEMENT_ASN1_DUP_FUNCTION"
+  - "IMPLEMENT_ASN1_DUP_FUNCTION_const"
   - "IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname"
   - "IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname"
   - "IMPLEMENT_ASN1_FUNCTIONS"
diff --git a/crypto/pkcs8/pkcs8_x509.c b/crypto/pkcs8/pkcs8_x509.c
index 3eff87c..5a1d591 100644
--- a/crypto/pkcs8/pkcs8_x509.c
+++ b/crypto/pkcs8/pkcs8_x509.c
@@ -110,7 +110,7 @@
     ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0),
 } ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
 
-IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+IMPLEMENT_ASN1_FUNCTIONS_const(PKCS8_PRIV_KEY_INFO)
 
 int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
                     int ptype, void *pval, uint8_t *penc, int penclen) {
diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h
index 8785949..23c961e 100644
--- a/crypto/x509/internal.h
+++ b/crypto/x509/internal.h
@@ -77,7 +77,7 @@
   ASN1_TIME *notAfter;
 } X509_VAL;
 
-DECLARE_ASN1_FUNCTIONS(X509_VAL)
+DECLARE_ASN1_FUNCTIONS_const(X509_VAL)
 
 struct X509_pubkey_st {
   X509_ALGOR *algor;
@@ -113,7 +113,7 @@
   ASN1_OCTET_STRING *keyid;       // key id of private key
 } X509_CERT_AUX;
 
-DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
+DECLARE_ASN1_FUNCTIONS_const(X509_CERT_AUX)
 
 struct X509_extension_st {
   ASN1_OBJECT *object;
@@ -135,6 +135,8 @@
   ASN1_ENCODING enc;
 } X509_CINF;
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(X509_CINF)
 
 struct x509_st {
@@ -171,6 +173,8 @@
   STACK_OF(X509_ATTRIBUTE) *attributes;  // [ 0 ]
 } X509_REQ_INFO;
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(X509_REQ_INFO)
 
 struct X509_req_st {
@@ -201,6 +205,8 @@
   ASN1_ENCODING enc;
 } X509_CRL_INFO;
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(X509_CRL_INFO)
 
 struct X509_crl_st {
diff --git a/crypto/x509/rsa_pss.c b/crypto/x509/rsa_pss.c
index 38cb028..f5716a6 100644
--- a/crypto/x509/rsa_pss.c
+++ b/crypto/x509/rsa_pss.c
@@ -83,7 +83,7 @@
     ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER, 3),
 } ASN1_SEQUENCE_END_cb(RSA_PSS_PARAMS, RSA_PSS_PARAMS)
 
-IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+IMPLEMENT_ASN1_FUNCTIONS_const(RSA_PSS_PARAMS)
 
 
 // Given an MGF1 Algorithm ID decode to an Algorithm Identifier
diff --git a/crypto/x509/x509cset.c b/crypto/x509/x509cset.c
index 6e81248..9558128 100644
--- a/crypto/x509/x509cset.c
+++ b/crypto/x509/x509cset.c
@@ -245,11 +245,8 @@
 }
 
 int X509_CRL_set1_signature_algo(X509_CRL *crl, const X509_ALGOR *algo) {
-  // TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions
-  // should be const. Alternatively, when we can embed required fields
-  // directly in structs, import |X509_ALGOR_copy| from upstream.
-  X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo);
-  X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo);
+  X509_ALGOR *copy1 = X509_ALGOR_dup(algo);
+  X509_ALGOR *copy2 = X509_ALGOR_dup(algo);
   if (copy1 == NULL || copy2 == NULL) {
     X509_ALGOR_free(copy1);
     X509_ALGOR_free(copy2);
diff --git a/crypto/x509/x509rset.c b/crypto/x509/x509rset.c
index 4c6181e..869bd40 100644
--- a/crypto/x509/x509rset.c
+++ b/crypto/x509/x509rset.c
@@ -88,10 +88,7 @@
 }
 
 int X509_REQ_set1_signature_algo(X509_REQ *req, const X509_ALGOR *algo) {
-  // TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions
-  // should be const. Alternatively, when we can embed required fields
-  // directly in structs, import |X509_ALGOR_copy| from upstream.
-  X509_ALGOR *copy = X509_ALGOR_dup((X509_ALGOR *)algo);
+  X509_ALGOR *copy = X509_ALGOR_dup(algo);
   if (copy == NULL) {
     return 0;
   }
diff --git a/crypto/x509/x_algor.c b/crypto/x509/x_algor.c
index 09a2221..a2d778a 100644
--- a/crypto/x509/x_algor.c
+++ b/crypto/x509/x_algor.c
@@ -74,9 +74,10 @@
                                                         X509_ALGOR)
 ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
-IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
+IMPLEMENT_ASN1_FUNCTIONS_const(X509_ALGOR)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(X509_ALGORS, X509_ALGORS,
+                                            X509_ALGORS)
+IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_ALGOR)
 
 int X509_ALGOR_set0(X509_ALGOR *alg, ASN1_OBJECT *aobj, int ptype, void *pval) {
   if (!alg) {
diff --git a/crypto/x509/x_attrib.c b/crypto/x509/x_attrib.c
index a434bc2..14428b3 100644
--- a/crypto/x509/x_attrib.c
+++ b/crypto/x509/x_attrib.c
@@ -67,8 +67,8 @@
     ASN1_SET_OF(X509_ATTRIBUTE, set, ASN1_ANY),
 } ASN1_SEQUENCE_END(X509_ATTRIBUTE)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE)
-IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
+IMPLEMENT_ASN1_FUNCTIONS_const(X509_ATTRIBUTE)
+IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_ATTRIBUTE)
 
 X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype, void *value) {
   ASN1_OBJECT *obj = OBJ_nid2obj(nid);
diff --git a/crypto/x509/x_exten.c b/crypto/x509/x_exten.c
index 53d2b71..e181d98 100644
--- a/crypto/x509/x_exten.c
+++ b/crypto/x509/x_exten.c
@@ -72,7 +72,7 @@
     ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION)
 ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS,
-                                      X509_EXTENSIONS)
-IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION)
+IMPLEMENT_ASN1_FUNCTIONS_const(X509_EXTENSION)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(X509_EXTENSIONS, X509_EXTENSIONS,
+                                            X509_EXTENSIONS)
+IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_EXTENSION)
diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c
index f54cbe8..a17d9d7 100644
--- a/crypto/x509/x_name.c
+++ b/crypto/x509/x_name.c
@@ -99,8 +99,8 @@
     ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE),
 } ASN1_SEQUENCE_END(X509_NAME_ENTRY)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY)
-IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
+IMPLEMENT_ASN1_FUNCTIONS_const(X509_NAME_ENTRY)
+IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_NAME_ENTRY)
 
 // For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so
 // declare two template wrappers for this
diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c
index 6a1dece..6a6a975 100644
--- a/crypto/x509/x_pubkey.c
+++ b/crypto/x509/x_pubkey.c
@@ -85,7 +85,7 @@
     ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING),
 } ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
+IMPLEMENT_ASN1_FUNCTIONS_const(X509_PUBKEY)
 
 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) {
   X509_PUBKEY *pk = NULL;
diff --git a/crypto/x509/x_sig.c b/crypto/x509/x_sig.c
index b68cb9e..4710cae 100644
--- a/crypto/x509/x_sig.c
+++ b/crypto/x509/x_sig.c
@@ -71,7 +71,7 @@
     ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING),
 } ASN1_SEQUENCE_END(X509_SIG)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509_SIG)
+IMPLEMENT_ASN1_FUNCTIONS_const(X509_SIG)
 
 void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **out_alg,
                    const ASN1_OCTET_STRING **out_digest) {
diff --git a/crypto/x509/x_spki.c b/crypto/x509/x_spki.c
index 435ff85..5899878 100644
--- a/crypto/x509/x_spki.c
+++ b/crypto/x509/x_spki.c
@@ -67,7 +67,7 @@
     ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING),
 } ASN1_SEQUENCE_END(NETSCAPE_SPKAC)
 
-IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_SPKAC)
 
 ASN1_SEQUENCE(NETSCAPE_SPKI) = {
     ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC),
@@ -75,4 +75,4 @@
     ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING),
 } ASN1_SEQUENCE_END(NETSCAPE_SPKI)
 
-IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI)
+IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_SPKI)
diff --git a/crypto/x509/x_val.c b/crypto/x509/x_val.c
index e317a70..62dbf6f 100644
--- a/crypto/x509/x_val.c
+++ b/crypto/x509/x_val.c
@@ -68,4 +68,4 @@
     ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME),
 } ASN1_SEQUENCE_END(X509_VAL)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509_VAL)
+IMPLEMENT_ASN1_FUNCTIONS_const(X509_VAL)
diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c
index ee558a4..27cbd99 100644
--- a/crypto/x509/x_x509.c
+++ b/crypto/x509/x_x509.c
@@ -338,11 +338,8 @@
 }
 
 int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) {
-  // TODO(https://crbug.com/boringssl/407): Generated ASN.1 dup functions
-  // should be const. Alternatively, when we can embed required fields
-  // directly in structs, import |X509_ALGOR_copy| from upstream.
-  X509_ALGOR *copy1 = X509_ALGOR_dup((X509_ALGOR *)algo);
-  X509_ALGOR *copy2 = X509_ALGOR_dup((X509_ALGOR *)algo);
+  X509_ALGOR *copy1 = X509_ALGOR_dup(algo);
+  X509_ALGOR *copy2 = X509_ALGOR_dup(algo);
   if (copy1 == NULL || copy2 == NULL) {
     X509_ALGOR_free(copy1);
     X509_ALGOR_free(copy2);
diff --git a/crypto/x509/x_x509a.c b/crypto/x509/x_x509a.c
index d372537..c473f93 100644
--- a/crypto/x509/x_x509a.c
+++ b/crypto/x509/x_x509a.c
@@ -78,7 +78,7 @@
     ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING),
 } ASN1_SEQUENCE_END(X509_CERT_AUX)
 
-IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX)
+IMPLEMENT_ASN1_FUNCTIONS_const(X509_CERT_AUX)
 
 static X509_CERT_AUX *aux_get(X509 *x) {
   if (!x) {
diff --git a/crypto/x509v3/v3_bcons.c b/crypto/x509v3/v3_bcons.c
index db55f06..19c1a5d 100644
--- a/crypto/x509v3/v3_bcons.c
+++ b/crypto/x509v3/v3_bcons.c
@@ -93,7 +93,7 @@
     ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER),
 } ASN1_SEQUENCE_END(BASIC_CONSTRAINTS)
 
-IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+IMPLEMENT_ASN1_FUNCTIONS_const(BASIC_CONSTRAINTS)
 
 static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(
     const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist) {
diff --git a/crypto/x509v3/v3_cpols.c b/crypto/x509v3/v3_cpols.c
index 5b6841e..82c68a1 100644
--- a/crypto/x509v3/v3_cpols.c
+++ b/crypto/x509v3/v3_cpols.c
@@ -107,14 +107,14 @@
     ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
 ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
 
-IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
+IMPLEMENT_ASN1_FUNCTIONS_const(CERTIFICATEPOLICIES)
 
 ASN1_SEQUENCE(POLICYINFO) = {
     ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
     ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO),
 } ASN1_SEQUENCE_END(POLICYINFO)
 
-IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
+IMPLEMENT_ASN1_FUNCTIONS_const(POLICYINFO)
 
 ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other,
                                                ASN1_ANY);
@@ -131,21 +131,21 @@
     ASN1_ADB_OBJECT(POLICYQUALINFO),
 } ASN1_SEQUENCE_END(POLICYQUALINFO)
 
-IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
+IMPLEMENT_ASN1_FUNCTIONS_const(POLICYQUALINFO)
 
 ASN1_SEQUENCE(USERNOTICE) = {
     ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
     ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT),
 } ASN1_SEQUENCE_END(USERNOTICE)
 
-IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
+IMPLEMENT_ASN1_FUNCTIONS_const(USERNOTICE)
 
 ASN1_SEQUENCE(NOTICEREF) = {
     ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
     ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER),
 } ASN1_SEQUENCE_END(NOTICEREF)
 
-IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
+IMPLEMENT_ASN1_FUNCTIONS_const(NOTICEREF)
 
 static void *r2i_certpol(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
                          const char *value) {
diff --git a/crypto/x509v3/v3_extku.c b/crypto/x509v3/v3_extku.c
index 7eb7cc8..0305ed2 100644
--- a/crypto/x509v3/v3_extku.c
+++ b/crypto/x509v3/v3_extku.c
@@ -108,7 +108,7 @@
     ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT)
 ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE)
 
-IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+IMPLEMENT_ASN1_FUNCTIONS_const(EXTENDED_KEY_USAGE)
 
 static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(
     const X509V3_EXT_METHOD *method, void *a, STACK_OF(CONF_VALUE) *ext_list) {
diff --git a/crypto/x509v3/v3_genn.c b/crypto/x509v3/v3_genn.c
index bd1aac1..fef0204 100644
--- a/crypto/x509v3/v3_genn.c
+++ b/crypto/x509v3/v3_genn.c
@@ -69,7 +69,7 @@
     ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0),
 } ASN1_SEQUENCE_END(OTHERNAME)
 
-IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
+IMPLEMENT_ASN1_FUNCTIONS_const(OTHERNAME)
 
 ASN1_SEQUENCE(EDIPARTYNAME) = {
     // DirectoryString is a CHOICE type, so use explicit tagging.
@@ -77,7 +77,7 @@
     ASN1_EXP(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1),
 } ASN1_SEQUENCE_END(EDIPARTYNAME)
 
-IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
+IMPLEMENT_ASN1_FUNCTIONS_const(EDIPARTYNAME)
 
 ASN1_CHOICE(GENERAL_NAME) = {
     ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
diff --git a/crypto/x509v3/v3_pcia.c b/crypto/x509v3/v3_pcia.c
index 356fb9d..62893ed 100644
--- a/crypto/x509v3/v3_pcia.c
+++ b/crypto/x509v3/v3_pcia.c
@@ -45,11 +45,11 @@
     ASN1_OPT(PROXY_POLICY, policy, ASN1_OCTET_STRING),
 } ASN1_SEQUENCE_END(PROXY_POLICY)
 
-IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY)
+IMPLEMENT_ASN1_FUNCTIONS_const(PROXY_POLICY)
 
 ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) = {
     ASN1_OPT(PROXY_CERT_INFO_EXTENSION, pcPathLengthConstraint, ASN1_INTEGER),
     ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION, proxyPolicy, PROXY_POLICY),
 } ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION)
 
-IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
+IMPLEMENT_ASN1_FUNCTIONS_const(PROXY_CERT_INFO_EXTENSION)
diff --git a/include/openssl/asn1t.h b/include/openssl/asn1t.h
index 75bc6f0..105cee8 100644
--- a/include/openssl/asn1t.h
+++ b/include/openssl/asn1t.h
@@ -677,13 +677,17 @@
 	int i2d_##fname(const stname *a, unsigned char **out) \
 	{ \
 		return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\
-	} 
+	}
 
-#define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \
-	stname * stname##_dup(stname *x) \
-        { \
-        return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
-        }
+#define IMPLEMENT_ASN1_DUP_FUNCTION(stname)          \
+  stname *stname##_dup(stname *x) {                  \
+    return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
+  }
+
+#define IMPLEMENT_ASN1_DUP_FUNCTION_const(stname)            \
+  stname *stname##_dup(const stname *x) {                    \
+    return ASN1_item_dup(ASN1_ITEM_rptr(stname), (void *)x); \
+  }
 
 #define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
 		IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 526765f..673edfe 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -115,7 +115,7 @@
   ASN1_TYPE *parameter;
 } /* X509_ALGOR */;
 
-DECLARE_ASN1_FUNCTIONS(X509_ALGOR)
+DECLARE_ASN1_FUNCTIONS_const(X509_ALGOR)
 
 DEFINE_STACK_OF(X509_ALGOR)
 
@@ -704,12 +704,12 @@
 OPENSSL_EXPORT int i2d_DHparams_bio(BIO *bp, const DH *dh);
 
 OPENSSL_EXPORT X509 *X509_dup(X509 *x509);
-OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_dup(X509_ATTRIBUTE *xa);
-OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *ex);
+OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_dup(const X509_ATTRIBUTE *xa);
+OPENSSL_EXPORT X509_EXTENSION *X509_EXTENSION_dup(const X509_EXTENSION *ex);
 OPENSSL_EXPORT X509_CRL *X509_CRL_dup(X509_CRL *crl);
 OPENSSL_EXPORT X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *rev);
 OPENSSL_EXPORT X509_REQ *X509_REQ_dup(X509_REQ *req);
-OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_dup(X509_ALGOR *xn);
+OPENSSL_EXPORT X509_ALGOR *X509_ALGOR_dup(const X509_ALGOR *xn);
 
 // X509_ALGOR_set0 sets |alg| to an AlgorithmIdentifier with algorithm |obj| and
 // parameter determined by |param_type| and |param_value|. It returns one on
@@ -761,7 +761,7 @@
 OPENSSL_EXPORT int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b);
 
 OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *xn);
-OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
+OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_dup(const X509_NAME_ENTRY *ne);
 OPENSSL_EXPORT int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne);
 
 OPENSSL_EXPORT int X509_NAME_get0_der(X509_NAME *nm, const unsigned char **pder,
@@ -799,9 +799,9 @@
 OPENSSL_EXPORT const char *X509_get_default_cert_file_env(void);
 OPENSSL_EXPORT const char *X509_get_default_private_dir(void);
 
-DECLARE_ASN1_ENCODE_FUNCTIONS(X509_ALGORS, X509_ALGORS, X509_ALGORS)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(X509_ALGORS, X509_ALGORS)
 
-DECLARE_ASN1_FUNCTIONS(X509_PUBKEY)
+DECLARE_ASN1_FUNCTIONS_const(X509_PUBKEY)
 
 // X509_PUBKEY_set serializes |pkey| into a newly-allocated |X509_PUBKEY|
 // structure. On success, it frees |*x|, sets |*x| to the new object, and
@@ -814,10 +814,13 @@
 // not mutate the result.
 OPENSSL_EXPORT EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key);
 
-DECLARE_ASN1_FUNCTIONS(X509_SIG)
+DECLARE_ASN1_FUNCTIONS_const(X509_SIG)
+
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(X509_REQ)
 
-DECLARE_ASN1_FUNCTIONS(X509_ATTRIBUTE)
+DECLARE_ASN1_FUNCTIONS_const(X509_ATTRIBUTE)
 
 // X509_ATTRIBUTE_create returns a newly-allocated |X509_ATTRIBUTE|, or NULL on
 // error. The attribute has type |nid| and contains a single value determined by
@@ -826,17 +829,21 @@
 OPENSSL_EXPORT X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int attrtype,
                                                      void *value);
 
-DECLARE_ASN1_FUNCTIONS(X509_EXTENSION)
-DECLARE_ASN1_ENCODE_FUNCTIONS(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
+DECLARE_ASN1_FUNCTIONS_const(X509_EXTENSION)
+DECLARE_ASN1_ENCODE_FUNCTIONS_const(X509_EXTENSIONS, X509_EXTENSIONS)
 
-DECLARE_ASN1_FUNCTIONS(X509_NAME_ENTRY)
+DECLARE_ASN1_FUNCTIONS_const(X509_NAME_ENTRY)
 
+// TODO(https://crbug.com/boringssl/407): This is not const because serializing
+// an |X509_NAME| is sometimes not thread-safe.
 DECLARE_ASN1_FUNCTIONS(X509_NAME)
 
 // X509_NAME_set makes a copy of |name|. On success, it frees |*xn|, sets |*xn|
 // to the copy, and returns one. Otherwise, it returns zero.
 OPENSSL_EXPORT int X509_NAME_set(X509_NAME **xn, X509_NAME *name);
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(X509)
 
 // X509_up_ref adds one to the reference count of |x509| and returns one.
@@ -975,7 +982,11 @@
 
 OPENSSL_EXPORT int X509_TRUST_set(int *t, int trust);
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(X509_REVOKED)
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(X509_CRL)
 
 OPENSSL_EXPORT int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev);
@@ -987,8 +998,8 @@
 OPENSSL_EXPORT X509_PKEY *X509_PKEY_new(void);
 OPENSSL_EXPORT void X509_PKEY_free(X509_PKEY *a);
 
-DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKI)
-DECLARE_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_SPKI)
+DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_SPKAC)
 
 OPENSSL_EXPORT X509_INFO *X509_INFO_new(void);
 OPENSSL_EXPORT void X509_INFO_free(X509_INFO *a);
@@ -1830,7 +1841,7 @@
 
 // PKCS#8 utilities
 
-DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+DECLARE_ASN1_FUNCTIONS_const(PKCS8_PRIV_KEY_INFO)
 
 OPENSSL_EXPORT EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8);
 OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
@@ -1897,7 +1908,7 @@
   X509_ALGOR *maskHash;
 } /* RSA_PSS_PARAMS */;
 
-DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+DECLARE_ASN1_FUNCTIONS_const(RSA_PSS_PARAMS)
 
 /*
 SSL_CTX -> X509_STORE
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
index afaf172..0ae9613 100644
--- a/include/openssl/x509v3.h
+++ b/include/openssl/x509v3.h
@@ -328,8 +328,8 @@
   PROXY_POLICY *proxyPolicy;
 } PROXY_CERT_INFO_EXTENSION;
 
-DECLARE_ASN1_FUNCTIONS(PROXY_POLICY)
-DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
+DECLARE_ASN1_FUNCTIONS_const(PROXY_POLICY)
+DECLARE_ASN1_FUNCTIONS_const(PROXY_CERT_INFO_EXTENSION)
 
 struct ISSUING_DIST_POINT_st {
   DIST_POINT_NAME *distpoint;
@@ -443,10 +443,14 @@
 
 DEFINE_STACK_OF(X509_PURPOSE)
 
-DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
+DECLARE_ASN1_FUNCTIONS_const(BASIC_CONSTRAINTS)
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
 OPENSSL_EXPORT GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a);
 
@@ -470,6 +474,8 @@
     STACK_OF(CONF_VALUE) *ret);
 OPENSSL_EXPORT int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
 
 // i2v_GENERAL_NAMES serializes |gen| as a list of |CONF_VALUE|s. If |ret| is
@@ -488,8 +494,8 @@
                                                 X509V3_CTX *ctx,
                                                 STACK_OF(CONF_VALUE) *nval);
 
-DECLARE_ASN1_FUNCTIONS(OTHERNAME)
-DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
+DECLARE_ASN1_FUNCTIONS_const(OTHERNAME)
+DECLARE_ASN1_FUNCTIONS_const(EDIPARTYNAME)
 OPENSSL_EXPORT int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b);
 OPENSSL_EXPORT void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type,
                                             void *value);
@@ -506,18 +512,26 @@
 OPENSSL_EXPORT ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(
     const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str);
 
-DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
+DECLARE_ASN1_FUNCTIONS_const(EXTENDED_KEY_USAGE)
 OPENSSL_EXPORT int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a);
 
-DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
-DECLARE_ASN1_FUNCTIONS(POLICYINFO)
-DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO)
-DECLARE_ASN1_FUNCTIONS(USERNOTICE)
-DECLARE_ASN1_FUNCTIONS(NOTICEREF)
+DECLARE_ASN1_FUNCTIONS_const(CERTIFICATEPOLICIES)
+DECLARE_ASN1_FUNCTIONS_const(POLICYINFO)
+DECLARE_ASN1_FUNCTIONS_const(POLICYQUALINFO)
+DECLARE_ASN1_FUNCTIONS_const(USERNOTICE)
+DECLARE_ASN1_FUNCTIONS_const(NOTICEREF)
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS)
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(DIST_POINT)
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
 
 OPENSSL_EXPORT int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn,
@@ -525,7 +539,11 @@
 
 OPENSSL_EXPORT int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc);
 
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
+// TODO(https://crbug.com/boringssl/407): This is not const because it contains
+// an |X509_NAME|.
 DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
 
 DECLARE_ASN1_ITEM(POLICY_MAPPING)