Use the correct function types in X509V3_EXT_METHODs.

While C allows function pointer casts, it is UB to call a function with
a different type than its actual type signature. That is, even though
`void f(int *)` and `void g(void *)` have the same ABI, it is UB to
cast `f` to a `void(*)(void *)` and then call it through that pointer.
Clang CFI will try to enforce this rule.

The recent CL to call X509_print in tests revealed that all the i2? and
?2i callbacks in X509V3_EXT_METHODs were implemented with functions of
the wrong type, out of some combination of missing consts and void*
turned into T*.

This CL fixes this. Where the function wasn't exported, or had no
callers, I just fixed the function itself. Where it had extension
callers, I added a wrapper function with a void* type.

I'm not positive whether the wrappers are the right call. On the one
hand, keeping the exported functions as-is is more type-safe and more
OpenSSL-compatible. However, most (but not all) uses of these are in
other code defining X509V3_EXT_METHODs themselves, so the void*
signature is more correct for them too. And the functions have a type
signature meant for X509V3_EXT_METHOD, complete with method pointer.

I've gone with leaving the exported ones as-is for now. Probably the
right answer anyway is to migrate the external callers, of either type
signature.

Change-Id: Ib8f2995cbd890221eaa9ac864a7e553cb6711901
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/52686
Commit-Queue: Bob Beck <bbe@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/crypto/x509v3/v3_akey.c b/crypto/x509v3/v3_akey.c
index e64e99f..ca581d9 100644
--- a/crypto/x509v3/v3_akey.c
+++ b/crypto/x509v3/v3_akey.c
@@ -69,30 +69,26 @@
 #include "internal.h"
 
 
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
-                                                 AUTHORITY_KEYID *akeyid,
-                                                 STACK_OF(CONF_VALUE)
-                                                 *extlist);
-static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
-                                            X509V3_CTX *ctx,
-                                            STACK_OF(CONF_VALUE) *values);
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(
+    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist);
+static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method,
+                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
 
 const X509V3_EXT_METHOD v3_akey_id = {
     NID_authority_key_identifier,
     X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
     0, 0, 0, 0,
     0, 0,
-    (X509V3_EXT_I2V) i2v_AUTHORITY_KEYID,
-    (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID,
+    i2v_AUTHORITY_KEYID,
+    v2i_AUTHORITY_KEYID,
     0, 0,
     NULL
 };
 
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
-                                                 AUTHORITY_KEYID *akeyid,
-                                                 STACK_OF(CONF_VALUE)
-                                                 *extlist)
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(
+    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist)
 {
+    const AUTHORITY_KEYID *akeyid = ext;
     int extlist_was_null = extlist == NULL;
     if (akeyid->keyid) {
         char *tmp = x509v3_bytes_to_hex(akeyid->keyid->data,
@@ -133,9 +129,8 @@
  * is always included.
  */
 
-static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
-                                            X509V3_CTX *ctx,
-                                            STACK_OF(CONF_VALUE) *values)
+static void *v2i_AUTHORITY_KEYID(const X509V3_EXT_METHOD *method,
+                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values)
 {
     char keyid = 0, issuer = 0;
     size_t i;
diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509v3/v3_alt.c
index eb9c975..c057da1 100644
--- a/crypto/x509v3/v3_alt.c
+++ b/crypto/x509v3/v3_alt.c
@@ -68,40 +68,44 @@
 #include "internal.h"
 
 
-static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
-                                      X509V3_CTX *ctx,
-                                      STACK_OF(CONF_VALUE) *nval);
-static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
-                                     X509V3_CTX *ctx,
-                                     STACK_OF(CONF_VALUE) *nval);
+static void *v2i_subject_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                             STACK_OF(CONF_VALUE) *nval);
+static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                            STACK_OF(CONF_VALUE) *nval);
 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
 static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
 static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
 
+static STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES_cb(
+    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret)
+{
+    return i2v_GENERAL_NAMES(method, ext, ret);
+}
+
 const X509V3_EXT_METHOD v3_alt[] = {
     {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
      0, 0, 0, 0,
      0, 0,
-     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
-     (X509V3_EXT_V2I)v2i_subject_alt,
+     i2v_GENERAL_NAMES_cb,
+     v2i_subject_alt,
      NULL, NULL, NULL},
 
     {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
      0, 0, 0, 0,
      0, 0,
-     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
-     (X509V3_EXT_V2I)v2i_issuer_alt,
+     i2v_GENERAL_NAMES_cb,
+     v2i_issuer_alt,
      NULL, NULL, NULL},
 
     {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
      0, 0, 0, 0,
      0, 0,
-     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+     i2v_GENERAL_NAMES_cb,
      NULL, NULL, NULL, NULL},
 };
 
-STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
                                         GENERAL_NAMES *gens,
                                         STACK_OF(CONF_VALUE) *ret)
 {
@@ -122,7 +126,7 @@
     return ret;
 }
 
-STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
+STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method,
                                        GENERAL_NAME *gen,
                                        STACK_OF(CONF_VALUE) *ret)
 {
@@ -266,9 +270,8 @@
     return 1;
 }
 
-static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
-                                     X509V3_CTX *ctx,
-                                     STACK_OF(CONF_VALUE) *nval)
+static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                            STACK_OF(CONF_VALUE) *nval)
 {
     GENERAL_NAMES *gens = NULL;
     CONF_VALUE *cnf;
@@ -336,9 +339,8 @@
     return ret;
 }
 
-static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
-                                      X509V3_CTX *ctx,
-                                      STACK_OF(CONF_VALUE) *nval)
+static void *v2i_subject_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                             STACK_OF(CONF_VALUE) *nval)
 {
     GENERAL_NAMES *gens = NULL;
     CONF_VALUE *cnf;
diff --git a/crypto/x509v3/v3_bcons.c b/crypto/x509v3/v3_bcons.c
index aefefdf..4edf27b 100644
--- a/crypto/x509v3/v3_bcons.c
+++ b/crypto/x509v3/v3_bcons.c
@@ -65,21 +65,19 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
-                                                   BASIC_CONSTRAINTS *bcons,
-                                                   STACK_OF(CONF_VALUE)
-                                                   *extlist);
-static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
-                                                X509V3_CTX *ctx,
-                                                STACK_OF(CONF_VALUE) *values);
+static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(
+    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist);
+static void *v2i_BASIC_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+                                   X509V3_CTX *ctx,
+                                   STACK_OF(CONF_VALUE) *values);
 
 const X509V3_EXT_METHOD v3_bcons = {
     NID_basic_constraints, 0,
     ASN1_ITEM_ref(BASIC_CONSTRAINTS),
     0, 0, 0, 0,
     0, 0,
-    (X509V3_EXT_I2V) i2v_BASIC_CONSTRAINTS,
-    (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS,
+    i2v_BASIC_CONSTRAINTS,
+    v2i_BASIC_CONSTRAINTS,
     NULL, NULL,
     NULL
 };
@@ -91,19 +89,18 @@
 
 IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
 
-static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
-                                                   BASIC_CONSTRAINTS *bcons,
-                                                   STACK_OF(CONF_VALUE)
-                                                   *extlist)
+static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(
+    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *extlist)
 {
+    const BASIC_CONSTRAINTS *bcons = ext;
     X509V3_add_value_bool("CA", bcons->ca, &extlist);
     X509V3_add_value_int("pathlen", bcons->pathlen, &extlist);
     return extlist;
 }
 
-static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
-                                                X509V3_CTX *ctx,
-                                                STACK_OF(CONF_VALUE) *values)
+static void *v2i_BASIC_CONSTRAINTS(const X509V3_EXT_METHOD *method,
+                                   X509V3_CTX *ctx,
+                                   STACK_OF(CONF_VALUE) *values)
 {
     BASIC_CONSTRAINTS *bcons = NULL;
     CONF_VALUE *val;
diff --git a/crypto/x509v3/v3_bitst.c b/crypto/x509v3/v3_bitst.c
index 871b776..3420b12 100644
--- a/crypto/x509v3/v3_bitst.c
+++ b/crypto/x509v3/v3_bitst.c
@@ -91,15 +91,10 @@
     {-1, NULL, NULL}
 };
 
-const X509V3_EXT_METHOD v3_nscert =
-EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
-const X509V3_EXT_METHOD v3_key_usage =
-EXT_BITSTRING(NID_key_usage, key_usage_type_table);
-
-STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
-                                          ASN1_BIT_STRING *bits,
-                                          STACK_OF(CONF_VALUE) *ret)
+static STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(
+    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret)
 {
+    const ASN1_BIT_STRING *bits = ext;
     const BIT_STRING_BITNAME *bnam;
     for (bnam = method->usr_data; bnam->lname; bnam++) {
         if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum))
@@ -108,9 +103,8 @@
     return ret;
 }
 
-ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
-                                     X509V3_CTX *ctx,
-                                     STACK_OF(CONF_VALUE) *nval)
+static void *v2i_ASN1_BIT_STRING(const X509V3_EXT_METHOD *method,
+                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
 {
     CONF_VALUE *val;
     ASN1_BIT_STRING *bs;
@@ -142,3 +136,14 @@
     }
     return bs;
 }
+
+#define EXT_BITSTRING(nid, table)                                             \
+  {                                                                           \
+    nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), 0, 0, 0, 0, 0, 0,                 \
+        i2v_ASN1_BIT_STRING, v2i_ASN1_BIT_STRING, NULL, NULL, (void *)(table) \
+  }
+
+const X509V3_EXT_METHOD v3_nscert =
+EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
+const X509V3_EXT_METHOD v3_key_usage =
+EXT_BITSTRING(NID_key_usage, key_usage_type_table);
diff --git a/crypto/x509v3/v3_cpols.c b/crypto/x509v3/v3_cpols.c
index 6e3eb14..9290556 100644
--- a/crypto/x509v3/v3_cpols.c
+++ b/crypto/x509v3/v3_cpols.c
@@ -73,13 +73,13 @@
 
 /* Certificate policies extension support: this one is a bit complex... */
 
-static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
-                       BIO *out, int indent);
-static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
-                                         X509V3_CTX *ctx, char *value);
-static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
+static int i2r_certpol(const X509V3_EXT_METHOD *method, void *ext, BIO *out,
+                       int indent);
+static void *r2i_certpol(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                         const char *value);
+static void print_qualifiers(BIO *out, const STACK_OF(POLICYQUALINFO) *quals,
                              int indent);
-static void print_notice(BIO *out, USERNOTICE *notice, int indent);
+static void print_notice(BIO *out, const USERNOTICE *notice, int indent);
 static POLICYINFO *policy_section(X509V3_CTX *ctx,
                                   STACK_OF(CONF_VALUE) *polstrs, int ia5org);
 static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
@@ -91,8 +91,8 @@
     0, 0, 0, 0,
     0, 0,
     0, 0,
-    (X509V3_EXT_I2R)i2r_certpol,
-    (X509V3_EXT_R2I)r2i_certpol,
+    i2r_certpol,
+    r2i_certpol,
     NULL
 };
 
@@ -137,8 +137,8 @@
 
 IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
 
-static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
-                                         X509V3_CTX *ctx, char *value)
+static void *r2i_certpol(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                         const char *value)
 {
     STACK_OF(POLICYINFO) *pols = NULL;
     char *pstr;
@@ -405,14 +405,13 @@
     return 0;
 }
 
-static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
+static int i2r_certpol(const X509V3_EXT_METHOD *method, void *ext,
                        BIO *out, int indent)
 {
-    size_t i;
-    POLICYINFO *pinfo;
+    const STACK_OF(POLICYINFO) *pol = ext;
     /* First print out the policy OIDs */
-    for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
-        pinfo = sk_POLICYINFO_value(pol, i);
+    for (size_t i = 0; i < sk_POLICYINFO_num(pol); i++) {
+        const POLICYINFO *pinfo = sk_POLICYINFO_value(pol, i);
         BIO_printf(out, "%*sPolicy: ", indent, "");
         i2a_ASN1_OBJECT(out, pinfo->policyid);
         BIO_puts(out, "\n");
@@ -422,13 +421,11 @@
     return 1;
 }
 
-static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
+static void print_qualifiers(BIO *out, const STACK_OF(POLICYQUALINFO) *quals,
                              int indent)
 {
-    POLICYQUALINFO *qualinfo;
-    size_t i;
-    for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
-        qualinfo = sk_POLICYQUALINFO_value(quals, i);
+    for (size_t i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
+        const POLICYQUALINFO *qualinfo = sk_POLICYQUALINFO_value(quals, i);
         switch (OBJ_obj2nid(qualinfo->pqualid)) {
         case NID_id_qt_cps:
             BIO_printf(out, "%*sCPS: %.*s\n", indent, "",
@@ -450,9 +447,8 @@
     }
 }
 
-static void print_notice(BIO *out, USERNOTICE *notice, int indent)
+static void print_notice(BIO *out, const USERNOTICE *notice, int indent)
 {
-    size_t i;
     if (notice->noticeref) {
         NOTICEREF *ref;
         ref = notice->noticeref;
@@ -460,7 +456,7 @@
                    ref->organization->length, ref->organization->data);
         BIO_printf(out, "%*sNumber%s: ", indent, "",
                    sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
-        for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
+        for (size_t i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
             ASN1_INTEGER *num;
             char *tmp;
             num = sk_ASN1_INTEGER_value(ref->noticenos, i);
diff --git a/crypto/x509v3/v3_enum.c b/crypto/x509v3/v3_enum.c
index 9b222bb..5c95858 100644
--- a/crypto/x509v3/v3_enum.c
+++ b/crypto/x509v3/v3_enum.c
@@ -83,24 +83,23 @@
     {-1, NULL, NULL}
 };
 
-const X509V3_EXT_METHOD v3_crl_reason = {
-    NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
-    0, 0, 0, 0,
-    (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE,
-    0,
-    0, 0, 0, 0,
-    (void *)crl_reasons
-};
-
-char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method,
-                                const ASN1_ENUMERATED *e)
+static char *i2s_ASN1_ENUMERATED_TABLE(const X509V3_EXT_METHOD *method,
+                                       void *ext)
 {
-    const ENUMERATED_NAMES *enam;
-    long strval;
-    strval = ASN1_ENUMERATED_get(e);
-    for (enam = method->usr_data; enam->lname; enam++) {
+    const ASN1_ENUMERATED *e = ext;
+    long strval = ASN1_ENUMERATED_get(e);
+    for (const ENUMERATED_NAMES *enam = method->usr_data; enam->lname; enam++) {
         if (strval == enam->bitnum)
             return OPENSSL_strdup(enam->lname);
     }
     return i2s_ASN1_ENUMERATED(method, e);
 }
+
+const X509V3_EXT_METHOD v3_crl_reason = {
+    NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
+    0, 0, 0, 0,
+    i2s_ASN1_ENUMERATED_TABLE,
+    0,
+    0, 0, 0, 0,
+    (void *)crl_reasons
+};
diff --git a/crypto/x509v3/v3_ia5.c b/crypto/x509v3/v3_ia5.c
index 700200c..6f5ce1d 100644
--- a/crypto/x509v3/v3_ia5.c
+++ b/crypto/x509v3/v3_ia5.c
@@ -70,24 +70,9 @@
 #include "../internal.h"
 
 
-static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
-                                ASN1_IA5STRING *ia5);
-static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
-                                          X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_ns_ia5_list[] = {
-    EXT_IA5STRING(NID_netscape_base_url),
-    EXT_IA5STRING(NID_netscape_revocation_url),
-    EXT_IA5STRING(NID_netscape_ca_revocation_url),
-    EXT_IA5STRING(NID_netscape_renewal_url),
-    EXT_IA5STRING(NID_netscape_ca_policy_url),
-    EXT_IA5STRING(NID_netscape_ssl_server_name),
-    EXT_IA5STRING(NID_netscape_comment),
-    EXT_END
-};
-
-static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
-                                ASN1_IA5STRING *ia5)
+static char *i2s_ASN1_IA5STRING(const X509V3_EXT_METHOD *method, void *ext)
 {
+    const ASN1_IA5STRING *ia5 = ext;
     char *tmp;
     if (!ia5 || !ia5->length)
         return NULL;
@@ -100,8 +85,8 @@
     return tmp;
 }
 
-static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
-                                          X509V3_CTX *ctx, char *str)
+static void *s2i_ASN1_IA5STRING(const X509V3_EXT_METHOD *method,
+                                X509V3_CTX *ctx, const char *str)
 {
     ASN1_IA5STRING *ia5;
     if (!str) {
@@ -119,3 +104,23 @@
     OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
     return NULL;
 }
+
+#define EXT_IA5STRING(nid)                                                 \
+  {                                                                        \
+    nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), 0, 0, 0, 0, i2s_ASN1_IA5STRING, \
+        s2i_ASN1_IA5STRING, 0, 0, 0, 0, NULL                               \
+  }
+
+#define EXT_END \
+  { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+const X509V3_EXT_METHOD v3_ns_ia5_list[] = {
+    EXT_IA5STRING(NID_netscape_base_url),
+    EXT_IA5STRING(NID_netscape_revocation_url),
+    EXT_IA5STRING(NID_netscape_ca_revocation_url),
+    EXT_IA5STRING(NID_netscape_renewal_url),
+    EXT_IA5STRING(NID_netscape_ca_policy_url),
+    EXT_IA5STRING(NID_netscape_ssl_server_name),
+    EXT_IA5STRING(NID_netscape_comment),
+    EXT_END
+};
diff --git a/crypto/x509v3/v3_info.c b/crypto/x509v3/v3_info.c
index 3615c71..e314019 100644
--- a/crypto/x509v3/v3_info.c
+++ b/crypto/x509v3/v3_info.c
@@ -68,22 +68,18 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
-                                                       *method, AUTHORITY_INFO_ACCESS
-                                                       *ainfo, STACK_OF(CONF_VALUE)
-                                                       *ret);
-static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
-                                                        *method,
-                                                        X509V3_CTX *ctx,
-                                                        STACK_OF(CONF_VALUE)
-                                                        *nval);
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(
+    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret);
+static void *v2i_AUTHORITY_INFO_ACCESS(const X509V3_EXT_METHOD *method,
+                                       X509V3_CTX *ctx,
+                                       STACK_OF(CONF_VALUE) *nval);
 
 const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE,
     ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
     0, 0, 0, 0,
     0, 0,
-    (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
-    (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+    i2v_AUTHORITY_INFO_ACCESS,
+    v2i_AUTHORITY_INFO_ACCESS,
     0, 0,
     NULL
 };
@@ -92,8 +88,8 @@
     ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
     0, 0, 0, 0,
     0, 0,
-    (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
-    (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+    i2v_AUTHORITY_INFO_ACCESS,
+    v2i_AUTHORITY_INFO_ACCESS,
     0, 0,
     NULL
 };
@@ -112,17 +108,16 @@
 IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
 
 static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(
-    X509V3_EXT_METHOD *method, AUTHORITY_INFO_ACCESS *ainfo,
-    STACK_OF(CONF_VALUE) *ret)
+    const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret)
 {
+    const AUTHORITY_INFO_ACCESS *ainfo = ext;
     ACCESS_DESCRIPTION *desc;
-    size_t i;
     int nlen;
     char objtmp[80], *ntmp;
     CONF_VALUE *vtmp;
     STACK_OF(CONF_VALUE) *tret = ret;
 
-    for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
+    for (size_t i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
         STACK_OF(CONF_VALUE) *tmp;
 
         desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
@@ -154,24 +149,19 @@
     return NULL;
 }
 
-static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
-                                                        *method,
-                                                        X509V3_CTX *ctx,
-                                                        STACK_OF(CONF_VALUE)
-                                                        *nval)
+static void *v2i_AUTHORITY_INFO_ACCESS(const X509V3_EXT_METHOD *method,
+                                       X509V3_CTX *ctx,
+                                       STACK_OF(CONF_VALUE) *nval)
 {
     AUTHORITY_INFO_ACCESS *ainfo = NULL;
-    CONF_VALUE *cnf, ctmp;
     ACCESS_DESCRIPTION *acc;
-    size_t i;
-    int objlen;
     char *objtmp, *ptmp;
     if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
         OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
-    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-        cnf = sk_CONF_VALUE_value(nval, i);
+    for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
         if (!(acc = ACCESS_DESCRIPTION_new())
             || !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
             OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
@@ -182,7 +172,8 @@
             OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
             goto err;
         }
-        objlen = ptmp - cnf->name;
+        int objlen = ptmp - cnf->name;
+        CONF_VALUE ctmp;
         ctmp.name = ptmp + 1;
         ctmp.value = cnf->value;
         if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
@@ -211,8 +202,5 @@
 int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a)
 {
     i2a_ASN1_OBJECT(bp, a->method);
-#ifdef UNDEF
-    i2a_GENERAL_NAME(bp, a->location);
-#endif
     return 2;
 }
diff --git a/crypto/x509v3/v3_int.c b/crypto/x509v3/v3_int.c
index 7bde446..8b96796 100644
--- a/crypto/x509v3/v3_int.c
+++ b/crypto/x509v3/v3_int.c
@@ -60,10 +60,22 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+
+static char *i2s_ASN1_INTEGER_cb(const X509V3_EXT_METHOD *method, void *ext)
+{
+    return i2s_ASN1_INTEGER(method, ext);
+}
+
+static void *s2i_asn1_int(const X509V3_EXT_METHOD *meth, X509V3_CTX *ctx,
+                          const char *value)
+{
+    return s2i_ASN1_INTEGER(meth, value);
+}
+
 const X509V3_EXT_METHOD v3_crl_num = {
     NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER),
     0, 0, 0, 0,
-    (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+    i2s_ASN1_INTEGER_cb,
     0,
     0, 0, 0, 0, NULL
 };
@@ -71,21 +83,15 @@
 const X509V3_EXT_METHOD v3_delta_crl = {
     NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER),
     0, 0, 0, 0,
-    (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+    i2s_ASN1_INTEGER_cb,
     0,
     0, 0, 0, 0, NULL
 };
 
-static void *s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx,
-                          char *value)
-{
-    return s2i_ASN1_INTEGER(meth, value);
-}
-
 const X509V3_EXT_METHOD v3_inhibit_anyp = {
     NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER),
     0, 0, 0, 0,
-    (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
-    (X509V3_EXT_S2I)s2i_asn1_int,
+    i2s_ASN1_INTEGER_cb,
+    s2i_asn1_int,
     0, 0, 0, 0, NULL
 };
diff --git a/crypto/x509v3/v3_pci.c b/crypto/x509v3/v3_pci.c
index 57b64ef..b6ff148 100644
--- a/crypto/x509v3/v3_pci.c
+++ b/crypto/x509v3/v3_pci.c
@@ -47,24 +47,25 @@
 #include "internal.h"
 
 
-static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
-                   BIO *out, int indent);
-static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
-                                          X509V3_CTX *ctx, char *str);
+static int i2r_pci(const X509V3_EXT_METHOD *method, void *ext, BIO *out,
+                   int indent);
+static void *r2i_pci(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                     const char *str);
 
 const X509V3_EXT_METHOD v3_pci =
     { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
     0, 0, 0, 0,
     0, 0,
     NULL, NULL,
-    (X509V3_EXT_I2R)i2r_pci,
-    (X509V3_EXT_R2I)r2i_pci,
+    i2r_pci,
+    r2i_pci,
     NULL,
 };
 
-static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
-                   BIO *out, int indent)
+static int i2r_pci(const X509V3_EXT_METHOD *method, void *ext, BIO *out,
+                   int indent)
 {
+    const PROXY_CERT_INFO_EXTENSION *pci = ext;
     BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
     if (pci->pcPathLengthConstraint)
         i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
@@ -195,8 +196,8 @@
     return 0;
 }
 
-static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
-                                          X509V3_CTX *ctx, char *value)
+static void *r2i_pci(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                     const char *value)
 {
     PROXY_CERT_INFO_EXTENSION *pci = NULL;
     STACK_OF(CONF_VALUE) *vals;
diff --git a/crypto/x509v3/v3_skey.c b/crypto/x509v3/v3_skey.c
index 1cae7e1..926eecd 100644
--- a/crypto/x509v3/v3_skey.c
+++ b/crypto/x509v3/v3_skey.c
@@ -67,23 +67,13 @@
 #include "internal.h"
 
 
-static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
-                                      X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_skey_id = {
-    NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
-    0, 0, 0, 0,
-    (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING,
-    (X509V3_EXT_S2I)s2i_skey_id,
-    0, 0, 0, 0,
-    NULL
-};
-
-char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, const ASN1_OCTET_STRING *oct)
+char *i2s_ASN1_OCTET_STRING(const X509V3_EXT_METHOD *method,
+                            const ASN1_OCTET_STRING *oct)
 {
     return x509v3_bytes_to_hex(oct->data, oct->length);
 }
 
-ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(const X509V3_EXT_METHOD *method,
                                          X509V3_CTX *ctx, const char *str)
 {
     ASN1_OCTET_STRING *oct;
@@ -105,8 +95,14 @@
 
 }
 
-static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
-                                      X509V3_CTX *ctx, char *str)
+static char *i2s_ASN1_OCTET_STRING_cb(const X509V3_EXT_METHOD *method,
+                                      void *ext)
+{
+    return i2s_ASN1_OCTET_STRING(method, ext);
+}
+
+static void *s2i_skey_id(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                         const char *str)
 {
     ASN1_OCTET_STRING *oct;
     ASN1_BIT_STRING *pk;
@@ -154,3 +150,12 @@
     ASN1_OCTET_STRING_free(oct);
     return NULL;
 }
+
+const X509V3_EXT_METHOD v3_skey_id = {
+    NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
+    0, 0, 0, 0,
+    i2s_ASN1_OCTET_STRING_cb,
+    s2i_skey_id,
+    0, 0, 0, 0,
+    NULL
+};
diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c
index 960c407..064e71b 100644
--- a/crypto/x509v3/v3_utl.c
+++ b/crypto/x509v3/v3_utl.c
@@ -222,7 +222,8 @@
     return ret;
 }
 
-char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a)
+char *i2s_ASN1_ENUMERATED(const X509V3_EXT_METHOD *method,
+                          const ASN1_ENUMERATED *a)
 {
     BIGNUM *bntmp = NULL;
     char *strtmp = NULL;
@@ -235,7 +236,7 @@
     return strtmp;
 }
 
-char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a)
+char *i2s_ASN1_INTEGER(const X509V3_EXT_METHOD *method, const ASN1_INTEGER *a)
 {
     BIGNUM *bntmp = NULL;
     char *strtmp = NULL;
@@ -248,7 +249,8 @@
     return strtmp;
 }
 
-ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
+ASN1_INTEGER *s2i_ASN1_INTEGER(const X509V3_EXT_METHOD *method,
+                               const char *value)
 {
     BIGNUM *bn = NULL;
     ASN1_INTEGER *aint;
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
index c67dde6..afaf172 100644
--- a/include/openssl/x509v3.h
+++ b/include/openssl/x509v3.h
@@ -79,23 +79,24 @@
 
 // Useful typedefs
 
+typedef struct v3_ext_method X509V3_EXT_METHOD;
+
 typedef void *(*X509V3_EXT_NEW)(void);
 typedef void (*X509V3_EXT_FREE)(void *);
 typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long);
 typedef int (*X509V3_EXT_I2D)(void *, unsigned char **);
-typedef STACK_OF(CONF_VALUE) *(*X509V3_EXT_I2V)(
-    const struct v3_ext_method *method, void *ext,
-    STACK_OF(CONF_VALUE) *extlist);
-typedef void *(*X509V3_EXT_V2I)(const struct v3_ext_method *method,
-                                struct v3_ext_ctx *ctx,
-                                STACK_OF(CONF_VALUE) *values);
-typedef char *(*X509V3_EXT_I2S)(const struct v3_ext_method *method, void *ext);
-typedef void *(*X509V3_EXT_S2I)(const struct v3_ext_method *method,
-                                struct v3_ext_ctx *ctx, const char *str);
-typedef int (*X509V3_EXT_I2R)(const struct v3_ext_method *method, void *ext,
+typedef STACK_OF(CONF_VALUE) *(*X509V3_EXT_I2V)(const X509V3_EXT_METHOD *method,
+                                                void *ext,
+                                                STACK_OF(CONF_VALUE) *extlist);
+typedef void *(*X509V3_EXT_V2I)(const X509V3_EXT_METHOD *method,
+                                X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+typedef char *(*X509V3_EXT_I2S)(const X509V3_EXT_METHOD *method, void *ext);
+typedef void *(*X509V3_EXT_S2I)(const X509V3_EXT_METHOD *method,
+                                X509V3_CTX *ctx, const char *str);
+typedef int (*X509V3_EXT_I2R)(const X509V3_EXT_METHOD *method, void *ext,
                               BIO *out, int indent);
-typedef void *(*X509V3_EXT_R2I)(const struct v3_ext_method *method,
-                                struct v3_ext_ctx *ctx, const char *str);
+typedef void *(*X509V3_EXT_R2I)(const X509V3_EXT_METHOD *method,
+                                X509V3_CTX *ctx, const char *str);
 
 // V3 extension structure
 
@@ -145,8 +146,6 @@
   // Maybe more here
 };
 
-typedef struct v3_ext_method X509V3_EXT_METHOD;
-
 DEFINE_STACK_OF(X509V3_EXT_METHOD)
 
 // ext_flags values
@@ -365,23 +364,6 @@
   X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
 #define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL;
 
-#define EXT_BITSTRING(nid, table)                                        \
-  {                                                                      \
-    nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), 0, 0, 0, 0, 0, 0,            \
-        (X509V3_EXT_I2V)i2v_ASN1_BIT_STRING,                             \
-        (X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, NULL, NULL, (void *)(table) \
-  }
-
-#define EXT_IA5STRING(nid)                                   \
-  {                                                          \
-    nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), 0, 0, 0, 0,       \
-        (X509V3_EXT_I2S)i2s_ASN1_IA5STRING,                  \
-        (X509V3_EXT_S2I)s2i_ASN1_IA5STRING, 0, 0, 0, 0, NULL \
-  }
-
-#define EXT_END \
-  { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
-
 
 // X509_PURPOSE stuff
 
@@ -474,15 +456,6 @@
 OPENSSL_EXPORT int GENERAL_NAME_cmp(const GENERAL_NAME *a,
                                     const GENERAL_NAME *b);
 
-
-
-OPENSSL_EXPORT ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
-                                                    X509V3_CTX *ctx,
-                                                    STACK_OF(CONF_VALUE) *nval);
-OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(
-    X509V3_EXT_METHOD *method, ASN1_BIT_STRING *bits,
-    STACK_OF(CONF_VALUE) *extlist);
-
 // i2v_GENERAL_NAME serializes |gen| as a |CONF_VALUE|. If |ret| is non-NULL, it
 // appends the value to |ret| and returns |ret| on success or NULL on error. If
 // it returns NULL, the caller is still responsible for freeing |ret|. If |ret|
@@ -493,7 +466,8 @@
 // human-readable print functions. If extracting a SAN list from a certificate,
 // look at |gen| directly.
 OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(
-    X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret);
+    const X509V3_EXT_METHOD *method, GENERAL_NAME *gen,
+    STACK_OF(CONF_VALUE) *ret);
 OPENSSL_EXPORT int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
 
 DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
@@ -508,7 +482,7 @@
 // human-readable print functions. If extracting a SAN list from a certificate,
 // look at |gen| directly.
 OPENSSL_EXPORT STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(
-    X509V3_EXT_METHOD *method, GENERAL_NAMES *gen,
+    const X509V3_EXT_METHOD *method, GENERAL_NAMES *gen,
     STACK_OF(CONF_VALUE) *extlist);
 OPENSSL_EXPORT GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
                                                 X509V3_CTX *ctx,
@@ -527,10 +501,10 @@
                                                ASN1_OBJECT **poid,
                                                ASN1_TYPE **pvalue);
 
-OPENSSL_EXPORT char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
+OPENSSL_EXPORT char *i2s_ASN1_OCTET_STRING(const X509V3_EXT_METHOD *method,
                                            const ASN1_OCTET_STRING *ia5);
 OPENSSL_EXPORT ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(
-    X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str);
+    const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, const char *str);
 
 DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
 OPENSSL_EXPORT int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a);
@@ -649,14 +623,12 @@
                                         const ASN1_INTEGER *aint,
                                         STACK_OF(CONF_VALUE) **extlist);
 
-OPENSSL_EXPORT char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth,
+OPENSSL_EXPORT char *i2s_ASN1_INTEGER(const X509V3_EXT_METHOD *meth,
                                       const ASN1_INTEGER *aint);
-OPENSSL_EXPORT ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth,
+OPENSSL_EXPORT ASN1_INTEGER *s2i_ASN1_INTEGER(const X509V3_EXT_METHOD *meth,
                                               const char *value);
-OPENSSL_EXPORT char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth,
+OPENSSL_EXPORT char *i2s_ASN1_ENUMERATED(const X509V3_EXT_METHOD *meth,
                                          const ASN1_ENUMERATED *aint);
-OPENSSL_EXPORT char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth,
-                                               const ASN1_ENUMERATED *aint);
 OPENSSL_EXPORT int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
 OPENSSL_EXPORT int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
 OPENSSL_EXPORT int X509V3_EXT_add_alias(int nid_to, int nid_from);