bpo-18233: Add internal methods to access peer chain (GH-25467)

The internal `_ssl._SSLSocket` object now provides methods to retrieve
the peer cert chain and verified cert chain as a list of Certificate
objects. Certificate objects have methods to convert the cert to a dict,
PEM, or DER (ASN.1).

These are private APIs for now. There is a slim chance to stabilize the
approach and provide a public API for 3.10. Otherwise I'll provide a
stable API in 3.11.

Signed-off-by: Christian Heimes <christian@python.org>
diff --git a/Modules/_ssl.h b/Modules/_ssl.h
index 3fd517b..5fe6504 100644
--- a/Modules/_ssl.h
+++ b/Modules/_ssl.h
@@ -1,6 +1,10 @@
 #ifndef Py_SSL_H
 #define Py_SSL_H
 
+/* OpenSSL header files */
+#include "openssl/evp.h"
+#include "openssl/x509.h"
+
 /*
  * ssl module state
  */
@@ -10,6 +14,7 @@ typedef struct {
     PyTypeObject *PySSLSocket_Type;
     PyTypeObject *PySSLMemoryBIO_Type;
     PyTypeObject *PySSLSession_Type;
+    PyTypeObject *PySSLCertificate_Type;
     /* SSL error object */
     PyObject *PySSLErrorObject;
     PyObject *PySSLCertVerificationErrorObject;
@@ -40,6 +45,30 @@ get_ssl_state(PyObject *module)
     (get_ssl_state(_PyType_GetModuleByDef(type, &_sslmodule_def)))
 #define get_state_ctx(c) (((PySSLContext *)(c))->state)
 #define get_state_sock(s) (((PySSLSocket *)(s))->ctx->state)
-#define get_state_mbio(b) ((_sslmodulestate *)PyType_GetModuleState(Py_TYPE(b)))
+#define get_state_obj(o) ((_sslmodulestate *)PyType_GetModuleState(Py_TYPE(o)))
+#define get_state_mbio(b) get_state_obj(b)
+#define get_state_cert(c) get_state_obj(c)
+
+/* ************************************************************************
+ * certificate
+ */
+
+enum py_ssl_encoding {
+    PY_SSL_ENCODING_PEM=X509_FILETYPE_PEM,
+    PY_SSL_ENCODING_DER=X509_FILETYPE_ASN1,
+    PY_SSL_ENCODING_PEM_AUX=X509_FILETYPE_PEM + 0x100,
+};
+
+typedef struct {
+    PyObject_HEAD
+    X509 *cert;
+    Py_hash_t hash;
+} PySSLCertificate;
+
+/* ************************************************************************
+ * helpers and utils
+ */
+static PyObject *_PySSL_BytesFromBIO(_sslmodulestate *state, BIO *bio);
+static PyObject *_PySSL_UnicodeFromBIO(_sslmodulestate *state, BIO *bio, const char *error);
 
 #endif /* Py_SSL_H */