Make most of crypto/x509 opaque.

This unexports X509, X509_CINF, X509_NAME_ENTRY, X509_NAME, X509_OBJECT,
X509_LOOKUP_METHOD, X509_STORE, X509_LOOKUP, and X509_STORE_CTX.

Note this means X509_STORE_CTX can no longer be stack-allocated.

Update-Note: Patch cl/390055173 into the roll that includes this. This
unexports most of the X.509 structs, aligning with OpenSSL. Use the
accessor APIs instead.

Bug: 425
Change-Id: I53e915bfae3b8dc4b67642279d0e54dc606f2297
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/48985
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/by_file.c b/crypto/x509/by_file.c
index 994beb9..1614c8c 100644
--- a/crypto/x509/by_file.c
+++ b/crypto/x509/by_file.c
@@ -61,6 +61,8 @@
 #include <openssl/pem.h>
 #include <openssl/thread.h>
 
+#include "internal.h"
+
 #ifndef OPENSSL_NO_STDIO
 
 static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h
index 2782f23..ac68755 100644
--- a/crypto/x509/internal.h
+++ b/crypto/x509/internal.h
@@ -81,6 +81,22 @@
   EVP_PKEY *pkey;
 } /* X509_PUBKEY */;
 
+struct X509_name_entry_st {
+  ASN1_OBJECT *object;
+  ASN1_STRING *value;
+  int set;
+} /* X509_NAME_ENTRY */;
+
+// we always keep X509_NAMEs in 2 forms.
+struct X509_name_st {
+  STACK_OF(X509_NAME_ENTRY) *entries;
+  int modified;  // true if 'bytes' needs to be built
+  BUF_MEM *bytes;
+  // unsigned long hash; Keep the hash around for lookups
+  unsigned char *canon_enc;
+  int canon_enclen;
+} /* X509_NAME */;
+
 struct x509_attributes_st {
   ASN1_OBJECT *object;
   STACK_OF(ASN1_TYPE) *set;
@@ -101,6 +117,47 @@
 } /* X509_EXTENSION */;
 
 typedef struct {
+  ASN1_INTEGER *version;  // [ 0 ] default of v1
+  ASN1_INTEGER *serialNumber;
+  X509_ALGOR *signature;
+  X509_NAME *issuer;
+  X509_VAL *validity;
+  X509_NAME *subject;
+  X509_PUBKEY *key;
+  ASN1_BIT_STRING *issuerUID;            // [ 1 ] optional in v2
+  ASN1_BIT_STRING *subjectUID;           // [ 2 ] optional in v2
+  STACK_OF(X509_EXTENSION) *extensions;  // [ 3 ] optional in v3
+  ASN1_ENCODING enc;
+} X509_CINF;
+
+DECLARE_ASN1_FUNCTIONS(X509_CINF)
+
+struct x509_st {
+  X509_CINF *cert_info;
+  X509_ALGOR *sig_alg;
+  ASN1_BIT_STRING *signature;
+  CRYPTO_refcount_t references;
+  CRYPTO_EX_DATA ex_data;
+  // These contain copies of various extension values
+  long ex_pathlen;
+  long ex_pcpathlen;
+  unsigned long ex_flags;
+  unsigned long ex_kusage;
+  unsigned long ex_xkusage;
+  unsigned long ex_nscert;
+  ASN1_OCTET_STRING *skid;
+  AUTHORITY_KEYID *akid;
+  X509_POLICY_CACHE *policy_cache;
+  STACK_OF(DIST_POINT) *crldp;
+  STACK_OF(GENERAL_NAME) *altname;
+  NAME_CONSTRAINTS *nc;
+  unsigned char sha1_hash[SHA_DIGEST_LENGTH];
+  X509_CERT_AUX *aux;
+  CRYPTO_BUFFER *buf;
+  CRYPTO_MUTEX lock;
+} /* X509 */;
+
+typedef struct {
   ASN1_ENCODING enc;
   ASN1_INTEGER *version;
   X509_NAME *subject;
@@ -153,7 +210,6 @@
   void *meth_data;
 } /* X509_CRL */;
 
-
 struct X509_VERIFY_PARAM_st {
   char *name;
   time_t check_time;                // Time to use
@@ -174,6 +230,131 @@
   unsigned char poison;  // Fail all verifications at name checking
 } /* X509_VERIFY_PARAM */;
 
+struct x509_object_st {
+  // one of the above types
+  int type;
+  union {
+    char *ptr;
+    X509 *x509;
+    X509_CRL *crl;
+    EVP_PKEY *pkey;
+  } data;
+} /* X509_OBJECT */;
+
+// This is a static that defines the function interface
+struct x509_lookup_method_st {
+  const char *name;
+  int (*new_item)(X509_LOOKUP *ctx);
+  void (*free)(X509_LOOKUP *ctx);
+  int (*init)(X509_LOOKUP *ctx);
+  int (*shutdown)(X509_LOOKUP *ctx);
+  int (*ctrl)(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+              char **ret);
+  int (*get_by_subject)(X509_LOOKUP *ctx, int type, X509_NAME *name,
+                        X509_OBJECT *ret);
+  int (*get_by_issuer_serial)(X509_LOOKUP *ctx, int type, X509_NAME *name,
+                              ASN1_INTEGER *serial, X509_OBJECT *ret);
+  int (*get_by_fingerprint)(X509_LOOKUP *ctx, int type, unsigned char *bytes,
+                            int len, X509_OBJECT *ret);
+  int (*get_by_alias)(X509_LOOKUP *ctx, int type, char *str, int len,
+                      X509_OBJECT *ret);
+} /* X509_LOOKUP_METHOD */;
+
+// This is used to hold everything.  It is used for all certificate
+// validation.  Once we have a certificate chain, the 'verify'
+// function is then called to actually check the cert chain.
+struct x509_store_st {
+  // The following is a cache of trusted certs
+  int cache;                    // if true, stash any hits
+  STACK_OF(X509_OBJECT) *objs;  // Cache of all objects
+  CRYPTO_MUTEX objs_lock;
+  STACK_OF(X509) *additional_untrusted;
+
+  // These are external lookup methods
+  STACK_OF(X509_LOOKUP) *get_cert_methods;
+
+  X509_VERIFY_PARAM *param;
+
+  // Callbacks for various operations
+  X509_STORE_CTX_verify_fn verify;          // called to verify a certificate
+  X509_STORE_CTX_verify_cb verify_cb;       // error callback
+  X509_STORE_CTX_get_issuer_fn get_issuer;  // get issuers cert from ctx
+  X509_STORE_CTX_check_issued_fn check_issued;  // check issued
+  X509_STORE_CTX_check_revocation_fn
+      check_revocation;                   // Check revocation status of chain
+  X509_STORE_CTX_get_crl_fn get_crl;      // retrieve CRL
+  X509_STORE_CTX_check_crl_fn check_crl;  // Check CRL validity
+  X509_STORE_CTX_cert_crl_fn cert_crl;    // Check certificate against CRL
+  X509_STORE_CTX_lookup_certs_fn lookup_certs;
+  X509_STORE_CTX_lookup_crls_fn lookup_crls;
+  X509_STORE_CTX_cleanup_fn cleanup;
+
+  CRYPTO_refcount_t references;
+} /* X509_STORE */;
+
+
+// This is the functions plus an instance of the local variables.
+struct x509_lookup_st {
+  int init;                    // have we been started
+  int skip;                    // don't use us.
+  X509_LOOKUP_METHOD *method;  // the functions
+  char *method_data;           // method data
+
+  X509_STORE *store_ctx;  // who owns us
+} /* X509_LOOKUP */;
+
+// This is a used when verifying cert chains.  Since the
+// gathering of the cert chain can take some time (and have to be
+// 'retried', this needs to be kept and passed around.
+struct x509_store_ctx_st {
+  X509_STORE *ctx;
+
+  // The following are set by the caller
+  X509 *cert;                 // The cert to check
+  STACK_OF(X509) *untrusted;  // chain of X509s - untrusted - passed in
+  STACK_OF(X509_CRL) *crls;   // set of CRLs passed in
+
+  X509_VERIFY_PARAM *param;
+  void *other_ctx;  // Other info for use with get_issuer()
+
+  // Callbacks for various operations
+  X509_STORE_CTX_verify_fn verify;          // called to verify a certificate
+  X509_STORE_CTX_verify_cb verify_cb;       // error callback
+  X509_STORE_CTX_get_issuer_fn get_issuer;  // get issuers cert from ctx
+  X509_STORE_CTX_check_issued_fn check_issued;  // check issued
+  X509_STORE_CTX_check_revocation_fn
+      check_revocation;                   // Check revocation status of chain
+  X509_STORE_CTX_get_crl_fn get_crl;      // retrieve CRL
+  X509_STORE_CTX_check_crl_fn check_crl;  // Check CRL validity
+  X509_STORE_CTX_cert_crl_fn cert_crl;    // Check certificate against CRL
+  X509_STORE_CTX_check_policy_fn check_policy;
+  X509_STORE_CTX_lookup_certs_fn lookup_certs;
+  X509_STORE_CTX_lookup_crls_fn lookup_crls;
+  X509_STORE_CTX_cleanup_fn cleanup;
+
+  // The following is built up
+  int valid;               // if 0, rebuild chain
+  int last_untrusted;      // index of last untrusted cert
+  STACK_OF(X509) *chain;   // chain of X509s - built up and trusted
+  X509_POLICY_TREE *tree;  // Valid policy tree
+
+  int explicit_policy;  // Require explicit policy value
+
+  // When something goes wrong, this is why
+  int error_depth;
+  int error;
+  X509 *current_cert;
+  X509 *current_issuer;   // cert currently being tested as valid issuer
+  X509_CRL *current_crl;  // current CRL
+
+  int current_crl_score;         // score of current CRL
+  unsigned int current_reasons;  // Reason mask
+
+  X509_STORE_CTX *parent;  // For CRL path validation: parent context
+
+  CRYPTO_EX_DATA ex_data;
+} /* X509_STORE_CTX */;
+
 
 /* RSA-PSS functions. */
 
diff --git a/crypto/x509/name_print.c b/crypto/x509/name_print.c
index 115edde..b5523c0 100644
--- a/crypto/x509/name_print.c
+++ b/crypto/x509/name_print.c
@@ -155,7 +155,7 @@
         else
             ent = X509_NAME_get_entry(n, i);
         if (prev != -1) {
-            if (prev == ent->set) {
+            if (prev == X509_NAME_ENTRY_set(ent)) {
                 if (!maybe_write(out, sep_mv, sep_mv_len))
                     return -1;
                 outlen += sep_mv_len;
@@ -168,7 +168,7 @@
                 outlen += indent;
             }
         }
-        prev = ent->set;
+        prev = X509_NAME_ENTRY_set(ent);
         fn = X509_NAME_ENTRY_get_object(ent);
         val = X509_NAME_ENTRY_get_data(ent);
         fn_nid = OBJ_obj2nid(fn);
diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c
index 80d16c1..df54f77 100644
--- a/crypto/x509/x509_obj.c
+++ b/crypto/x509/x509_obj.c
@@ -64,6 +64,7 @@
 #include <openssl/x509.h>
 
 #include "../internal.h"
+#include "internal.h"
 
 
 /*
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc
index bd77778..848bd07 100644
--- a/crypto/x509/x509_test.cc
+++ b/crypto/x509/x509_test.cc
@@ -32,6 +32,7 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
+#include "internal.h"
 #include "../internal.h"
 #include "../test/test_util.h"
 #include "../x509v3/internal.h"
diff --git a/crypto/x509/x509name.c b/crypto/x509/x509name.c
index 23e7553..6bc0952 100644
--- a/crypto/x509/x509name.c
+++ b/crypto/x509/x509name.c
@@ -64,6 +64,7 @@
 #include <openssl/x509.h>
 
 #include "../internal.h"
+#include "internal.h"
 
 
 int X509_NAME_get_text_by_NID(const X509_NAME *name, int nid, char *buf,
diff --git a/crypto/x509/x_name.c b/crypto/x509/x_name.c
index e56f2c3..e4b5835 100644
--- a/crypto/x509/x_name.c
+++ b/crypto/x509/x_name.c
@@ -68,6 +68,7 @@
 
 #include "../asn1/internal.h"
 #include "../internal.h"
+#include "internal.h"
 
 
 typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c
index 679acb1..38cceb1 100644
--- a/crypto/x509/x_x509.c
+++ b/crypto/x509/x_x509.c
@@ -69,6 +69,7 @@
 #include <openssl/x509v3.h>
 
 #include "../internal.h"
+#include "internal.h"
 
 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
 
diff --git a/crypto/x509v3/pcy_cache.c b/crypto/x509v3/pcy_cache.c
index 755c079..1caea76 100644
--- a/crypto/x509v3/pcy_cache.c
+++ b/crypto/x509v3/pcy_cache.c
@@ -62,6 +62,7 @@
 
 #include "pcy_int.h"
 #include "../internal.h"
+#include "../x509/internal.h"
 
 static int policy_data_cmp(const X509_POLICY_DATA **a,
                            const X509_POLICY_DATA **b);
diff --git a/crypto/x509v3/pcy_map.c b/crypto/x509v3/pcy_map.c
index 7263c69..a4a3601 100644
--- a/crypto/x509v3/pcy_map.c
+++ b/crypto/x509v3/pcy_map.c
@@ -62,6 +62,7 @@
 #include <openssl/x509v3.h>
 
 #include "pcy_int.h"
+#include "../x509/internal.h"
 
 /*
  * Set policy mapping entries in cache. Note: this modifies the passed
diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509v3/pcy_tree.c
index 292cd20..596266b 100644
--- a/crypto/x509v3/pcy_tree.c
+++ b/crypto/x509v3/pcy_tree.c
@@ -67,6 +67,7 @@
 
 #include "pcy_int.h"
 #include "../internal.h"
+#include "../x509/internal.h"
 
 /*
  * Enable this to print out the complete policy tree at various point during
diff --git a/crypto/x509v3/v3_crld.c b/crypto/x509v3/v3_crld.c
index 09d9736..93e5b6d 100644
--- a/crypto/x509v3/v3_crld.c
+++ b/crypto/x509v3/v3_crld.c
@@ -67,6 +67,7 @@
 #include <openssl/x509v3.h>
 
 #include "internal.h"
+#include "../x509/internal.h"
 
 
 static void *v2i_crld(const X509V3_EXT_METHOD *method,
diff --git a/crypto/x509v3/v3_ncons.c b/crypto/x509v3/v3_ncons.c
index 35c826e..739a59e 100644
--- a/crypto/x509v3/v3_ncons.c
+++ b/crypto/x509v3/v3_ncons.c
@@ -66,6 +66,7 @@
 #include <openssl/x509v3.h>
 
 #include "../internal.h"
+#include "../x509/internal.h"
 
 
 static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
diff --git a/crypto/x509v3/v3_purp.c b/crypto/x509v3/v3_purp.c
index 2d7a4db..d1f56f0 100644
--- a/crypto/x509v3/v3_purp.c
+++ b/crypto/x509v3/v3_purp.c
@@ -68,6 +68,7 @@
 #include <openssl/x509v3.h>
 
 #include "../internal.h"
+#include "../x509/internal.h"
 #include "internal.h"
 
 #define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
diff --git a/include/openssl/base.h b/include/openssl/base.h
index ea4366a..dd6a146 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -445,9 +445,10 @@
 typedef struct v3_ext_ctx X509V3_CTX;
 typedef struct x509_attributes_st X509_ATTRIBUTE;
 typedef struct x509_cert_aux_st X509_CERT_AUX;
-typedef struct x509_cinf_st X509_CINF;
 typedef struct x509_crl_method_st X509_CRL_METHOD;
 typedef struct x509_lookup_st X509_LOOKUP;
+typedef struct x509_lookup_method_st X509_LOOKUP_METHOD;
+typedef struct x509_object_st X509_OBJECT;
 typedef struct x509_revoked_st X509_REVOKED;
 typedef struct x509_st X509;
 typedef struct x509_store_ctx_st X509_STORE_CTX;
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index fa333ca..f4444c9 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -121,24 +121,8 @@
 
 typedef STACK_OF(X509_ALGOR) X509_ALGORS;
 
-struct X509_name_entry_st {
-  ASN1_OBJECT *object;
-  ASN1_STRING *value;
-  int set;
-} /* X509_NAME_ENTRY */;
-
 DEFINE_STACK_OF(X509_NAME_ENTRY)
 
-// we always keep X509_NAMEs in 2 forms.
-struct X509_name_st {
-  STACK_OF(X509_NAME_ENTRY) *entries;
-  int modified;  // true if 'bytes' needs to be built
-  BUF_MEM *bytes;
-  // unsigned long hash; Keep the hash around for lookups
-  unsigned char *canon_enc;
-  int canon_enclen;
-} /* X509_NAME */;
-
 DEFINE_STACK_OF(X509_NAME)
 
 typedef STACK_OF(X509_EXTENSION) X509_EXTENSIONS;
@@ -147,20 +131,6 @@
 
 DEFINE_STACK_OF(X509_ATTRIBUTE)
 
-struct x509_cinf_st {
-  ASN1_INTEGER *version;  // [ 0 ] default of v1
-  ASN1_INTEGER *serialNumber;
-  X509_ALGOR *signature;
-  X509_NAME *issuer;
-  X509_VAL *validity;
-  X509_NAME *subject;
-  X509_PUBKEY *key;
-  ASN1_BIT_STRING *issuerUID;            // [ 1 ] optional in v2
-  ASN1_BIT_STRING *subjectUID;           // [ 2 ] optional in v2
-  STACK_OF(X509_EXTENSION) *extensions;  // [ 3 ] optional in v3
-  ASN1_ENCODING enc;
-} /* X509_CINF */;
-
 // This stuff is certificate "auxiliary info"
 // it contains details which are useful in certificate
 // stores and databases. When used this is tagged onto
@@ -169,31 +139,6 @@
 DECLARE_STACK_OF(DIST_POINT)
 DECLARE_STACK_OF(GENERAL_NAME)
 
-struct x509_st {
-  X509_CINF *cert_info;
-  X509_ALGOR *sig_alg;
-  ASN1_BIT_STRING *signature;
-  CRYPTO_refcount_t references;
-  CRYPTO_EX_DATA ex_data;
-  // These contain copies of various extension values
-  long ex_pathlen;
-  long ex_pcpathlen;
-  unsigned long ex_flags;
-  unsigned long ex_kusage;
-  unsigned long ex_xkusage;
-  unsigned long ex_nscert;
-  ASN1_OCTET_STRING *skid;
-  AUTHORITY_KEYID *akid;
-  X509_POLICY_CACHE *policy_cache;
-  STACK_OF(DIST_POINT) *crldp;
-  STACK_OF(GENERAL_NAME) *altname;
-  NAME_CONSTRAINTS *nc;
-  unsigned char sha1_hash[SHA_DIGEST_LENGTH];
-  X509_CERT_AUX *aux;
-  CRYPTO_BUFFER *buf;
-  CRYPTO_MUTEX lock;
-} /* X509 */;
-
 DEFINE_STACK_OF(X509)
 
 // This is used for a table of trust checking functions
@@ -939,8 +884,6 @@
 // to the copy, and returns one. Otherwise, it returns zero.
 OPENSSL_EXPORT int X509_NAME_set(X509_NAME **xn, X509_NAME *name);
 
-DECLARE_ASN1_FUNCTIONS(X509_CINF)
-
 DECLARE_ASN1_FUNCTIONS(X509)
 DECLARE_ASN1_FUNCTIONS(X509_CERT_AUX)
 
@@ -1989,10 +1932,6 @@
 BORINGSSL_MAKE_DELETER(X509_STORE_CTX, X509_STORE_CTX_free)
 BORINGSSL_MAKE_DELETER(X509_VERIFY_PARAM, X509_VERIFY_PARAM_free)
 
-using ScopedX509_STORE_CTX =
-    internal::StackAllocated<X509_STORE_CTX, void, X509_STORE_CTX_zero,
-                             X509_STORE_CTX_cleanup>;
-
 BSSL_NAMESPACE_END
 
 }  // extern C++
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
index 9b99f4a..d8781af 100644
--- a/include/openssl/x509_vfy.h
+++ b/include/openssl/x509_vfy.h
@@ -99,39 +99,8 @@
 #define X509_LU_CRL 2
 #define X509_LU_PKEY 3
 
-typedef struct x509_object_st {
-  // one of the above types
-  int type;
-  union {
-    char *ptr;
-    X509 *x509;
-    X509_CRL *crl;
-    EVP_PKEY *pkey;
-  } data;
-} X509_OBJECT;
-
 DEFINE_STACK_OF(X509_LOOKUP)
 DEFINE_STACK_OF(X509_OBJECT)
-
-// This is a static that defines the function interface
-typedef struct x509_lookup_method_st {
-  const char *name;
-  int (*new_item)(X509_LOOKUP *ctx);
-  void (*free)(X509_LOOKUP *ctx);
-  int (*init)(X509_LOOKUP *ctx);
-  int (*shutdown)(X509_LOOKUP *ctx);
-  int (*ctrl)(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
-              char **ret);
-  int (*get_by_subject)(X509_LOOKUP *ctx, int type, X509_NAME *name,
-                        X509_OBJECT *ret);
-  int (*get_by_issuer_serial)(X509_LOOKUP *ctx, int type, X509_NAME *name,
-                              ASN1_INTEGER *serial, X509_OBJECT *ret);
-  int (*get_by_fingerprint)(X509_LOOKUP *ctx, int type, unsigned char *bytes,
-                            int len, X509_OBJECT *ret);
-  int (*get_by_alias)(X509_LOOKUP *ctx, int type, char *str, int len,
-                      X509_OBJECT *ret);
-} X509_LOOKUP_METHOD;
-
 DEFINE_STACK_OF(X509_VERIFY_PARAM)
 
 typedef int (*X509_STORE_CTX_verify_cb)(int, X509_STORE_CTX *);
@@ -153,103 +122,8 @@
     X509_STORE_CTX *ctx, X509_NAME *nm);
 typedef int (*X509_STORE_CTX_cleanup_fn)(X509_STORE_CTX *ctx);
 
-// This is used to hold everything.  It is used for all certificate
-// validation.  Once we have a certificate chain, the 'verify'
-// function is then called to actually check the cert chain.
-struct x509_store_st {
-  // The following is a cache of trusted certs
-  int cache;                    // if true, stash any hits
-  STACK_OF(X509_OBJECT) *objs;  // Cache of all objects
-  CRYPTO_MUTEX objs_lock;
-  STACK_OF(X509) *additional_untrusted;
-
-  // These are external lookup methods
-  STACK_OF(X509_LOOKUP) *get_cert_methods;
-
-  X509_VERIFY_PARAM *param;
-
-  // Callbacks for various operations
-  X509_STORE_CTX_verify_fn verify;          // called to verify a certificate
-  X509_STORE_CTX_verify_cb verify_cb;       // error callback
-  X509_STORE_CTX_get_issuer_fn get_issuer;  // get issuers cert from ctx
-  X509_STORE_CTX_check_issued_fn check_issued;  // check issued
-  X509_STORE_CTX_check_revocation_fn
-      check_revocation;                   // Check revocation status of chain
-  X509_STORE_CTX_get_crl_fn get_crl;      // retrieve CRL
-  X509_STORE_CTX_check_crl_fn check_crl;  // Check CRL validity
-  X509_STORE_CTX_cert_crl_fn cert_crl;    // Check certificate against CRL
-  X509_STORE_CTX_lookup_certs_fn lookup_certs;
-  X509_STORE_CTX_lookup_crls_fn lookup_crls;
-  X509_STORE_CTX_cleanup_fn cleanup;
-
-  CRYPTO_refcount_t references;
-} /* X509_STORE */;
-
 OPENSSL_EXPORT int X509_STORE_set_depth(X509_STORE *store, int depth);
 
-// This is the functions plus an instance of the local variables.
-struct x509_lookup_st {
-  int init;                    // have we been started
-  int skip;                    // don't use us.
-  X509_LOOKUP_METHOD *method;  // the functions
-  char *method_data;           // method data
-
-  X509_STORE *store_ctx;  // who owns us
-} /* X509_LOOKUP */;
-
-// This is a used when verifying cert chains.  Since the
-// gathering of the cert chain can take some time (and have to be
-// 'retried', this needs to be kept and passed around.
-struct x509_store_ctx_st  // X509_STORE_CTX
-{
-  X509_STORE *ctx;
-
-  // The following are set by the caller
-  X509 *cert;                 // The cert to check
-  STACK_OF(X509) *untrusted;  // chain of X509s - untrusted - passed in
-  STACK_OF(X509_CRL) *crls;   // set of CRLs passed in
-
-  X509_VERIFY_PARAM *param;
-  void *other_ctx;  // Other info for use with get_issuer()
-
-  // Callbacks for various operations
-  X509_STORE_CTX_verify_fn verify;          // called to verify a certificate
-  X509_STORE_CTX_verify_cb verify_cb;       // error callback
-  X509_STORE_CTX_get_issuer_fn get_issuer;  // get issuers cert from ctx
-  X509_STORE_CTX_check_issued_fn check_issued;  // check issued
-  X509_STORE_CTX_check_revocation_fn
-      check_revocation;                   // Check revocation status of chain
-  X509_STORE_CTX_get_crl_fn get_crl;      // retrieve CRL
-  X509_STORE_CTX_check_crl_fn check_crl;  // Check CRL validity
-  X509_STORE_CTX_cert_crl_fn cert_crl;    // Check certificate against CRL
-  X509_STORE_CTX_check_policy_fn check_policy;
-  X509_STORE_CTX_lookup_certs_fn lookup_certs;
-  X509_STORE_CTX_lookup_crls_fn lookup_crls;
-  X509_STORE_CTX_cleanup_fn cleanup;
-
-  // The following is built up
-  int valid;               // if 0, rebuild chain
-  int last_untrusted;      // index of last untrusted cert
-  STACK_OF(X509) *chain;   // chain of X509s - built up and trusted
-  X509_POLICY_TREE *tree;  // Valid policy tree
-
-  int explicit_policy;  // Require explicit policy value
-
-  // When something goes wrong, this is why
-  int error_depth;
-  int error;
-  X509 *current_cert;
-  X509 *current_issuer;   // cert currently being tested as valid issuer
-  X509_CRL *current_crl;  // current CRL
-
-  int current_crl_score;         // score of current CRL
-  unsigned int current_reasons;  // Reason mask
-
-  X509_STORE_CTX *parent;  // For CRL path validation: parent context
-
-  CRYPTO_EX_DATA ex_data;
-} /* X509_STORE_CTX */;
-
 OPENSSL_EXPORT void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
 
 #define X509_STORE_CTX_set_app_data(ctx, data) \
diff --git a/ssl/ssl_x509.cc b/ssl/ssl_x509.cc
index 98f1f6a..8d340d3 100644
--- a/ssl/ssl_x509.cc
+++ b/ssl/ssl_x509.cc
@@ -379,8 +379,9 @@
   const char *name;
   size_t name_len;
   SSL_get0_ech_name_override(ssl, &name, &name_len);
-  ScopedX509_STORE_CTX ctx;
-  if (!X509_STORE_CTX_init(ctx.get(), verify_store, leaf, cert_chain) ||
+  UniquePtr<X509_STORE_CTX> ctx(X509_STORE_CTX_new());
+  if (!ctx ||
+      !X509_STORE_CTX_init(ctx.get(), verify_store, leaf, cert_chain) ||
       !X509_STORE_CTX_set_ex_data(ctx.get(),
                                   SSL_get_ex_data_X509_STORE_CTX_idx(), ssl) ||
       // We need to inherit the verify parameters. These can be determined by
@@ -411,11 +412,11 @@
     verify_ret = X509_verify_cert(ctx.get());
   }
 
-  session->verify_result = ctx->error;
+  session->verify_result = X509_STORE_CTX_get_error(ctx.get());
 
   // If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result.
   if (verify_ret <= 0 && hs->config->verify_mode != SSL_VERIFY_NONE) {
-    *out_alert = SSL_alert_from_verify_result(ctx->error);
+    *out_alert = SSL_alert_from_verify_result(session->verify_result);
     return false;
   }
 
@@ -464,9 +465,9 @@
     return false;
   }
 
-  ScopedX509_STORE_CTX ctx;
-  if (!X509_STORE_CTX_init(ctx.get(), hs->ssl->ctx->cert_store, leaf.get(),
-                           NULL)) {
+  UniquePtr<X509_STORE_CTX> ctx(X509_STORE_CTX_new());
+  if (!ctx || !X509_STORE_CTX_init(ctx.get(), hs->ssl->ctx->cert_store,
+                                   leaf.get(), nullptr)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
     return false;
   }
@@ -476,9 +477,13 @@
   ERR_clear_error();
 
   // Remove the leaf from the generated chain.
-  X509_free(sk_X509_shift(ctx->chain));
+  UniquePtr<STACK_OF(X509)> chain(X509_STORE_CTX_get1_chain(ctx.get()));
+  if (!chain) {
+    return false;
+  }
+  X509_free(sk_X509_shift(chain.get()));
 
-  if (!ssl_cert_set_chain(hs->config->cert.get(), ctx->chain)) {
+  if (!ssl_cert_set_chain(hs->config->cert.get(), chain.get())) {
     return false;
   }
 
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 12a9f7a..7d1cefa 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -810,7 +810,7 @@
 
   GetTestState(ssl)->cert_verified = true;
   if (config->verify_fail) {
-    store_ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+    X509_STORE_CTX_set_error(store_ctx, X509_V_ERR_APPLICATION_VERIFICATION);
     return 0;
   }