[pypy-commit] pypy openssl-1.1: First pass at OpenSSL 1.1 support

stefanor pypy.commits at gmail.com
Thu Oct 27 03:36:58 EDT 2016


Author: Stefano Rivera <stefano at rivera.za.net>
Branch: openssl-1.1
Changeset: r87955:7270dc830901
Date: 2016-10-27 00:31 -0700
http://bitbucket.org/pypy/pypy/changeset/7270dc830901/

Log:	First pass at OpenSSL 1.1 support

diff --git a/pypy/module/_hashlib/interp_hashlib.py b/pypy/module/_hashlib/interp_hashlib.py
--- a/pypy/module/_hashlib/interp_hashlib.py
+++ b/pypy/module/_hashlib/interp_hashlib.py
@@ -58,14 +58,14 @@
     def __init__(self, space, name, copy_from=NULL_CTX):
         self.name = name
         digest_type = self.digest_type_by_name(space)
-        self.digest_size = rffi.getintfield(digest_type, 'c_md_size')
+        self.digest_size = ropenssl.EVP_MD_size(digest_type)
 
         # Allocate a lock for each HASH object.
         # An optimization would be to not release the GIL on small requests,
         # and use a custom lock only when needed.
         self.lock = Lock(space)
 
-        ctx = lltype.malloc(ropenssl.EVP_MD_CTX.TO, flavor='raw')
+        ctx = ropenssl.EVP_MD_CTX_new()
         rgc.add_memory_pressure(ropenssl.HASH_MALLOC_SIZE + self.digest_size)
         try:
             if copy_from:
@@ -74,7 +74,7 @@
                 ropenssl.EVP_DigestInit(ctx, digest_type)
             self.ctx = ctx
         except:
-            lltype.free(ctx, flavor='raw')
+            ropenssl.EVP_MD_CTX_free(ctx)
             raise
         self.register_finalizer(space)
 
@@ -82,8 +82,7 @@
         ctx = self.ctx
         if ctx:
             self.ctx = lltype.nullptr(ropenssl.EVP_MD_CTX.TO)
-            ropenssl.EVP_MD_CTX_cleanup(ctx)
-            lltype.free(ctx, flavor='raw')
+            ropenssl.EVP_MD_CTX_free(ctx)
 
     def digest_type_by_name(self, space):
         digest_type = ropenssl.EVP_get_digestbyname(self.name)
@@ -128,21 +127,23 @@
 
     def get_block_size(self, space):
         digest_type = self.digest_type_by_name(space)
-        block_size = rffi.getintfield(digest_type, 'c_block_size')
+        block_size = ropenssl.EVP_MD_block_size(digest_type)
         return space.wrap(block_size)
 
     def get_name(self, space):
         return space.wrap(self.name)
 
     def _digest(self, space):
-        with lltype.scoped_alloc(ropenssl.EVP_MD_CTX.TO) as ctx:
+        ctx = ropenssl.EVP_MD_CTX_new()
+        try:
             with self.lock:
                 ropenssl.EVP_MD_CTX_copy(ctx, self.ctx)
             digest_size = self.digest_size
             with rffi.scoped_alloc_buffer(digest_size) as buf:
                 ropenssl.EVP_DigestFinal(ctx, buf.raw, None)
-                ropenssl.EVP_MD_CTX_cleanup(ctx)
                 return buf.str(digest_size)
+        finally:
+            ropenssl.EVP_MD_CTX_free(ctx)
 
 
 W_Hash.typedef = TypeDef(
diff --git a/pypy/module/_hashlib/test/test_hashlib.py b/pypy/module/_hashlib/test/test_hashlib.py
--- a/pypy/module/_hashlib/test/test_hashlib.py
+++ b/pypy/module/_hashlib/test/test_hashlib.py
@@ -15,17 +15,19 @@
 
     def test_attributes(self):
         import hashlib
-        for name, expected_size in {'md5': 16,
-                                    'sha1': 20,
-                                    'sha224': 28,
-                                    'sha256': 32,
-                                    'sha384': 48,
-                                    'sha512': 64,
-                                    }.items():
+        for name, (expected_size, expected_block_size) in {
+                'md5': (16, 64),
+                'sha1': (20, 64),
+                'sha224': (28, 64),
+                'sha256': (32, 64),
+                'sha384': (48, 128),
+                'sha512': (64, 128),
+                }.items():
             h = hashlib.new(name)
             assert h.name == name
             assert h.digest_size == expected_size
             assert h.digestsize == expected_size
+            assert h.block_size == expected_block_size
             #
             h.update('abc')
             h2 = h.copy()
@@ -46,6 +48,7 @@
             h = py_new(name)('')
             assert h.digest_size == expected_size
             assert h.digestsize == expected_size
+            assert h.block_size == expected_block_size
             #
             h.update('abc')
             h2 = h.copy()
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -33,9 +33,10 @@
 PY_SSL_CLIENT, PY_SSL_SERVER = 0, 1
 
 (PY_SSL_VERSION_SSL2, PY_SSL_VERSION_SSL3,
- PY_SSL_VERSION_SSL23, PY_SSL_VERSION_TLS1, PY_SSL_VERSION_TLS1_1,
+ PY_SSL_VERSION_TLS, PY_SSL_VERSION_TLS1, PY_SSL_VERSION_TLS1_1,
  PY_SSL_VERSION_TLS1_2) = range(6)
 
+
 SOCKET_IS_NONBLOCKING, SOCKET_IS_BLOCKING = 0, 1
 SOCKET_HAS_TIMED_OUT, SOCKET_HAS_BEEN_CLOSED = 2, 3
 SOCKET_TOO_LARGE_FOR_SELECT, SOCKET_OPERATION_OK = 4, 5
@@ -68,11 +69,12 @@
 constants["HAS_NPN"] = HAS_NPN
 constants["HAS_ALPN"] = HAS_ALPN
 
+constants["PROTOCOL_TLS"] = PY_SSL_VERSION_TLS
+constants["PROTOCOL_SSLv23"] = PY_SSL_VERSION_TLS  # Legacy name
 if not OPENSSL_NO_SSL2:
     constants["PROTOCOL_SSLv2"]  = PY_SSL_VERSION_SSL2
 if not OPENSSL_NO_SSL3:
     constants["PROTOCOL_SSLv3"]  = PY_SSL_VERSION_SSL3
-constants["PROTOCOL_SSLv23"] = PY_SSL_VERSION_SSL23
 constants["PROTOCOL_TLSv1"]  = PY_SSL_VERSION_TLS1
 if HAVE_TLSv1_2:
     constants["PROTOCOL_TLSv1_1"] = PY_SSL_VERSION_TLS1_1
@@ -637,9 +639,12 @@
         if not self.ssl:
             return space.w_None
         comp_method = libssl_SSL_get_current_compression(self.ssl)
-        if not comp_method or intmask(comp_method[0].c_type) == NID_undef:
+        if not comp_method:
             return space.w_None
-        short_name = libssl_OBJ_nid2sn(comp_method[0].c_type)
+        method_type = intmask(libssl_COMP_get_type(comp_method))
+        if method_type == NID_undef:
+            return space.w_None
+        short_name = libssl_OBJ_nid2sn(method_type)
         if not short_name:
             return space.w_None
         return space.wrap(rffi.charp2str(short_name))
@@ -795,7 +800,7 @@
     for index in range(entry_count):
         entry = libssl_X509_NAME_get_entry(xname, index)
         # check to see if we've gotten to a new RDN
-        entry_level = intmask(entry[0].c_set)
+        entry_level = intmask(libssl_X509_NAME_ENTRY_set(entry))
         if rdn_level >= 0:
             if rdn_level != entry_level:
                 # yes, new RDN
@@ -846,8 +851,9 @@
                                 "No method for internalizing subjectAltName!'")
 
             with lltype.scoped_alloc(rffi.CCHARPP.TO, 1) as p_ptr:
-                p_ptr[0] = ext[0].c_value.c_data
-                length = intmask(ext[0].c_value.c_length)
+                ext_value = libssl_X509_EXTENSION_get_data(ext)
+                p_ptr[0] = ext_value.c_data
+                length = intmask(ext_value.c_length)
                 null = lltype.nullptr(rffi.VOIDP.TO)
                 if method[0].c_it:
                     names = rffi.cast(GENERAL_NAMES, libssl_ASN1_item_d2i(
@@ -967,10 +973,8 @@
     if OPENSSL_VERSION_NUMBER >= 0x10001000:
         # Calls x509v3_cache_extensions and sets up crldp
         libssl_X509_check_ca(certificate)
-        dps = certificate[0].c_crldp
-    else:
-        dps = rffi.cast(stack_st_DIST_POINT, libssl_X509_get_ext_d2i(
-            certificate, NID_crl_distribution_points, None, None))
+    dps = rffi.cast(stack_st_DIST_POINT, libssl_X509_get_ext_d2i(
+        certificate, NID_crl_distribution_points, None, None))
     if not dps:
         return None
 
@@ -1268,14 +1272,14 @@
     @staticmethod
     @unwrap_spec(protocol=int)
     def descr_new(space, w_subtype, protocol):
-        if protocol == PY_SSL_VERSION_TLS1:
+        if protocol == PY_SSL_VERSION_TLS:
+            method = libssl_TLS_method()
+        elif protocol == PY_SSL_VERSION_TLS1:
             method = libssl_TLSv1_method()
         elif protocol == PY_SSL_VERSION_SSL3 and not OPENSSL_NO_SSL3:
             method = libssl_SSLv3_method()
         elif protocol == PY_SSL_VERSION_SSL2 and not OPENSSL_NO_SSL2:
             method = libssl_SSLv2_method()
-        elif protocol == PY_SSL_VERSION_SSL23:
-            method = libssl_SSLv23_method()
         elif protocol == PY_SSL_VERSION_TLS1_1 and HAVE_TLSv1_2:
             method = libssl_TLSv1_1_method()
         elif protocol == PY_SSL_VERSION_TLS1_2 and HAVE_TLSv1_2:
@@ -1390,20 +1394,22 @@
 
     def descr_get_verify_flags(self, space):
         store = libssl_SSL_CTX_get_cert_store(self.ctx)
-        flags = libssl_X509_VERIFY_PARAM_get_flags(store[0].c_param)
+        param = libssl_X509_STORE_get0_param(store)
+        flags = libssl_X509_VERIFY_PARAM_get_flags(param)
         return space.wrap(flags)
 
     def descr_set_verify_flags(self, space, w_obj):
         new_flags = space.int_w(w_obj)
         store = libssl_SSL_CTX_get_cert_store(self.ctx)
-        flags = libssl_X509_VERIFY_PARAM_get_flags(store[0].c_param)
+        param = libssl_X509_STORE_get0_param(store)
+        flags = libssl_X509_VERIFY_PARAM_get_flags(param)
         flags_clear = flags & ~new_flags
         flags_set = ~flags & new_flags
         if flags_clear and not libssl_X509_VERIFY_PARAM_clear_flags(
-                store[0].c_param, flags_clear):
+                param, flags_clear):
             raise _ssl_seterror(space, None, 0)
         if flags_set and not libssl_X509_VERIFY_PARAM_set_flags(
-                store[0].c_param, flags_set):
+                param, flags_set):
             raise _ssl_seterror(space, None, 0)
 
     def descr_get_check_hostname(self, space):
@@ -1614,14 +1620,16 @@
         x509 = 0
         x509_ca = 0
         crl = 0
-        for i in range(libssl_sk_X509_OBJECT_num(store[0].c_objs)):
-            obj = libssl_sk_X509_OBJECT_value(store[0].c_objs, i)
-            if intmask(obj.c_type) == X509_LU_X509:
+        objs = libssl_X509_STORE_get0_objects(store)
+        for i in range(libssl_sk_X509_OBJECT_num(objs)):
+            obj = libssl_sk_X509_OBJECT_value(objs, i)
+            obj_type = intmask(libssl_X509_OBJECT_get_type(obj))
+            if obj_type == X509_LU_X509:
                 x509 += 1
                 if libssl_X509_check_ca(
-                        libssl_pypy_X509_OBJECT_data_x509(obj)):
+                        libssl_X509_OBJECT_get0_X509(obj)):
                     x509_ca += 1
-            elif intmask(obj.c_type) == X509_LU_CRL:
+            elif obj_type == X509_LU_CRL:
                 crl += 1
             else:
                 # Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY.
@@ -1660,13 +1668,14 @@
             binary_mode = False
         rlist = []
         store = libssl_SSL_CTX_get_cert_store(self.ctx)
-        for i in range(libssl_sk_X509_OBJECT_num(store[0].c_objs)):
-            obj = libssl_sk_X509_OBJECT_value(store[0].c_objs, i)
-            if intmask(obj.c_type) != X509_LU_X509:
+        objs = libssl_X509_STORE_get0_objects(store)
+        for i in range(libssl_sk_X509_OBJECT_num(objs)):
+            obj = libssl_sk_X509_OBJECT_value(objs, i)
+            if intmask(libssl_X509_OBJECT_get_type(obj)) != X509_LU_X509:
                 # not a x509 cert
                 continue
             # CA for any purpose
-            cert = libssl_pypy_X509_OBJECT_data_x509(obj)
+            cert = libssl_X509_OBJECT_get0_X509(obj)
             if not libssl_X509_check_ca(cert):
                 continue
             if binary_mode:
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -77,7 +77,7 @@
         if sys.version_info < (2, 7, 9):
             ss = _ssl.sslwrap(s, 0)
         else:
-            ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+            ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
             ss = ctx._wrap_socket(s, 0)
             assert ss.context is ctx
         exc = raises(_socket.error, ss.do_handshake)
@@ -95,7 +95,7 @@
         if sys.version_info < (2, 7, 9):
             ss = _ssl.sslwrap(s, 0)
         else:
-            ss = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)._wrap_socket(s, 0)
+            ss = _ssl._SSLContext(_ssl.PROTOCOL_TLS)._wrap_socket(s, 0)
         s.close()
         exc = raises(_ssl.SSLError, ss.write, "data")
         assert exc.value.message == 'Underlying socket has been closed.'
@@ -123,13 +123,13 @@
 
     def test_context(self):
         import _ssl
-        s = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        s = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         raises(ValueError, _ssl._SSLContext, -1)
 
         assert type(s.options) is long
-        assert s.options & _ssl.OP_NO_SSLv2
-        s.options &= ~_ssl.OP_NO_SSLv2
-        assert not s.options & _ssl.OP_NO_SSLv2
+        assert s.options & _ssl.OP_NO_SSLv3
+        s.options &= ~_ssl.OP_NO_SSLv3
+        assert not s.options & _ssl.OP_NO_SSLv3
         raises(TypeError, "s.options = 2.5")
 
         assert not s.check_hostname
@@ -159,7 +159,7 @@
 
     def test_set_default_verify_paths(self):
         import _ssl
-        s = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        s = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         s.set_default_verify_paths()
 
 
@@ -253,13 +253,42 @@
         if not _ssl.HAS_NPN:
             skip("NPN requires OpenSSL 1.0.1 or greater")
 
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx._set_npn_protocols(b'\x08http/1.1\x06spdy/2')
         ss = ctx._wrap_socket(self.s._sock, True,
                               server_hostname="svn.python.org")
         self.s.close()
         del ss; gc.collect()
 
+    def test_peer_certificate(self):
+        import _ssl, gc
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
+        ss = ctx._wrap_socket(self.s._sock, False)
+        ss.do_handshake()
+        assert isinstance(ss.peer_certificate(der=True), bytes)
+        assert isinstance(ss.peer_certificate(), dict)
+        self.s.close()
+        del ss; gc.collect()
+
+    def test_peer_certificate_verify(self):
+        import _ssl, ssl, gc
+        paths = ssl.get_default_verify_paths()
+
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
+        ctx.verify_mode = _ssl.CERT_REQUIRED
+        ctx.load_verify_locations(capath=paths.capath, cafile=paths.cafile)
+
+        ss = ctx._wrap_socket(self.s._sock, False)
+        try:
+            ss.do_handshake()
+        except _ssl.SSLError as e:
+            if e.reason == 'CERTIFICATE_VERIFY_FAILED':
+                skip("Certificate verification failed. "
+                     "Most likely we just don't have any CA certificates.")
+        assert ss.peer_certificate()
+        self.s.close()
+        del ss; gc.collect()
+
     def test_tls_unique_cb(self):
         import ssl, sys, gc
         ss = ssl.wrap_socket(self.s)
@@ -325,7 +354,7 @@
 
     def test_load_cert_chain(self):
         import _ssl, errno
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.load_cert_chain(self.keycert)
         ctx.load_cert_chain(self.cert, self.key)
         exc = raises(IOError, ctx.load_cert_chain, "inexistent.pem")
@@ -344,11 +373,11 @@
 
     def test_load_verify_locations(self):
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.load_verify_locations(self.keycert)
         ctx.load_verify_locations(cafile=self.keycert, capath=None)
 
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         with open(self.keycert) as f:
             cacert_pem = f.read().decode('ascii')
         ctx.load_verify_locations(cadata=cacert_pem)
@@ -356,7 +385,7 @@
 
     def test_get_ca_certs(self):
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.load_verify_locations(self.keycert)
         assert ctx.get_ca_certs() == []
         ctx.load_verify_locations(self.python_org_cert)
@@ -370,7 +399,7 @@
 
     def test_cert_store_stats(self):
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         assert ctx.cert_store_stats() == {'x509_ca': 0, 'crl': 0, 'x509': 0}
         ctx.load_cert_chain(self.keycert)
         assert ctx.cert_store_stats() == {'x509_ca': 0, 'crl': 0, 'x509': 0}
@@ -379,7 +408,7 @@
 
     def test_load_dh_params(self):
         import _ssl, errno
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.load_dh_params(self.dh512)
         raises(TypeError, ctx.load_dh_params)
         raises(TypeError, ctx.load_dh_params, None)
@@ -389,7 +418,7 @@
 
     def test_set_ecdh_curve(self):
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         ctx.set_ecdh_curve("prime256v1")
         raises(ValueError, ctx.set_ecdh_curve, "foo")
 
@@ -434,7 +463,7 @@
     def test_lib_reason(self):
         # Test the library and reason attributes
         import _ssl
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         exc = raises(_ssl.SSLError, ctx.load_dh_params, self.keycert)
         assert exc.value.library == 'PEM'
         assert exc.value.reason == 'NO_START_LINE'
@@ -445,7 +474,7 @@
         # Check that the appropriate SSLError subclass is raised
         # (this only tests one of them)
         import _ssl, _socket
-        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
+        ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLS)
         s = _socket.socket()
         try:
             s.bind(("127.0.0.1", 0))
diff --git a/rpython/rlib/ropenssl.py b/rpython/rlib/ropenssl.py
--- a/rpython/rlib/ropenssl.py
+++ b/rpython/rlib/ropenssl.py
@@ -57,8 +57,21 @@
         '#define pypy_GENERAL_NAME_dirn(name) (name->d.dirn)',
         '#define pypy_GENERAL_NAME_uri(name) (name->d.uniformResourceIdentifier)',
         '#define pypy_GENERAL_NAME_pop_free(names) (sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free))',
-        '#define pypy_X509_OBJECT_data_x509(obj) (obj->data.x509)',
         '#define pypy_DIST_POINT_fullname(obj) (obj->distpoint->name.fullname)',
+        # Backwards compatibility for functions introduced in 1.1
+        '#if (OPENSSL_VERSION_NUMBER < 0x10100000)',
+        '#  define X509_OBJECT_get0_X509(obj) (obj->data.x509)',
+        '#  define X509_OBJECT_get_type(obj) (obj->type)',
+        '#  define COMP_get_type(meth) (meth->type)',
+        '#  define X509_NAME_ENTRY_set(ne) (ne->set)',
+        '#  define X509_STORE_get0_objects(store) (store->objs)',
+        '#  define X509_STORE_get0_param(store) (store->param)',
+        '#  define TLS_method SSLv23_method',
+        '#  define EVP_MD_CTX_new EVP_MD_CTX_create',
+        '#  define EVP_MD_CTX_free EVP_MD_CTX_destroy',
+        '#else /* (OPENSSL_VERSION_NUMBER < 0x10100000) */',
+        '#  define OPENSSL_NO_SSL2',
+        '#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000) */',
     ],
 )
 
@@ -88,6 +101,7 @@
             "OPENSSL_EXPORT_VAR_AS_FUNCTION")
     OPENSSL_VERSION_NUMBER = rffi_platform.ConstantInteger(
         "OPENSSL_VERSION_NUMBER")
+    LIBRESSL = rffi_platform.Defined("LIBRESSL_VERSION_NUMBER")
 
 cconfig = rffi_platform.configure(CConfigBootstrap)
 if cconfig["OPENSSL_EXPORT_VAR_AS_FUNCTION"]:
@@ -95,23 +109,9 @@
 else:
     ASN1_ITEM_EXP = ASN1_ITEM
 OPENSSL_VERSION_NUMBER = cconfig["OPENSSL_VERSION_NUMBER"]
+LIBRESSL = cconfig["LIBRESSL"]
 HAVE_TLSv1_2 = OPENSSL_VERSION_NUMBER >= 0x10001000
 
-if (OPENSSL_VERSION_NUMBER >= 0x10100000 and
-     OPENSSL_VERSION_NUMBER < 0x20000000):    # <= libressl :-(
-    eci.pre_include_bits = ()
-    eci.post_include_bits = ()
-    raise Exception("""OpenSSL version >= 1.1 not supported yet.
-
-    This program requires OpenSSL version 1.0.x, and may also
-    work with LibreSSL or OpenSSL 0.9.x.  OpenSSL 1.1 is quite
-    some work to update to; contributions are welcome.  Sorry,
-    you need to install an older version of OpenSSL for now.
-    Make sure this older version is the one picked up by this
-    program when it runs the compiler.
-    
-    This is the configuration used: %r""" % (eci,))
-
 
 class CConfig:
     _compilation_info_ = eci
@@ -139,7 +139,7 @@
     SSL_OP_SINGLE_ECDH_USE = rffi_platform.ConstantInteger(
         "SSL_OP_SINGLE_ECDH_USE")
     SSL_OP_NO_COMPRESSION = rffi_platform.DefinedConstantInteger(
-        "SSL_OP_NO_COMPRESSION")
+         "SSL_OP_NO_COMPRESSION")
     SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = rffi_platform.ConstantInteger(
         "SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS")
     SSL_OP_CIPHER_SERVER_PREFERENCE = rffi_platform.ConstantInteger(
@@ -210,28 +210,10 @@
     OBJ_NAME_TYPE_MD_METH = rffi_platform.ConstantInteger(
         "OBJ_NAME_TYPE_MD_METH")
 
-    if OPENSSL_VERSION_NUMBER >= 0x10001000:
-        X509_st = rffi_platform.Struct(
-            'struct x509_st',
-            [('crldp', stack_st_DIST_POINT)])
-
     # Some structures, with only the fields used in the _ssl module
-    X509_name_entry_st = rffi_platform.Struct('struct X509_name_entry_st',
-                                              [('set', rffi.INT)])
     asn1_string_st = rffi_platform.Struct('struct asn1_string_st',
                                           [('length', rffi.INT),
                                            ('data', rffi.CCHARP)])
-    X509_extension_st = rffi_platform.Struct(
-        'struct X509_extension_st',
-        [('value', ASN1_STRING)])
-    x509_store_st = rffi_platform.Struct(
-        'struct x509_store_st',
-        [('objs', stack_st_X509_OBJECT),
-         ('param', X509_VERIFY_PARAM)])
-    x509_object_st = rffi_platform.Struct(
-        'struct x509_object_st',
-        [('type', rffi.INT)])
-
     X509_LU_X509 = rffi_platform.ConstantInteger("X509_LU_X509")
     X509_LU_CRL = rffi_platform.ConstantInteger("X509_LU_CRL")
 
@@ -244,12 +226,6 @@
     GENERAL_NAME_st = rffi_platform.Struct(
         'struct GENERAL_NAME_st',
         [('type', rffi.INT)])
-    EVP_MD_st = rffi_platform.Struct(
-        'EVP_MD',
-        [('md_size', rffi.INT),
-         ('block_size', rffi.INT)])
-    EVP_MD_SIZE = rffi_platform.SizeOf('EVP_MD')
-    EVP_MD_CTX_SIZE = rffi_platform.SizeOf('EVP_MD_CTX')
 
     OBJ_NAME_st = rffi_platform.Struct(
         'OBJ_NAME',
@@ -257,10 +233,6 @@
          ('name', rffi.CCHARP),
          ])
 
-    COMP_METHOD_st = rffi_platform.Struct(
-        'struct comp_method_st',
-        [('type', rffi.INT),])
-
     ACCESS_DESCRIPTION_st = rffi_platform.Struct(
         'struct ACCESS_DESCRIPTION_st',
         [('method', ASN1_OBJECT),
@@ -275,14 +247,12 @@
 SSL_CIPHER = rffi.COpaquePtr('SSL_CIPHER')
 SSL = rffi.COpaquePtr('SSL')
 BIO = rffi.COpaquePtr('BIO')
-if OPENSSL_VERSION_NUMBER >= 0x10001000:
-    X509 = rffi.CArrayPtr(X509_st)
-else:
-    X509 = rffi.COpaquePtr('X509')
-X509_NAME_ENTRY = rffi.CArrayPtr(X509_name_entry_st)
-X509_EXTENSION = rffi.CArrayPtr(X509_extension_st)
-X509_STORE = rffi.CArrayPtr(x509_store_st)
-X509_OBJECT = lltype.Ptr(x509_object_st)
+X509 = rffi.COpaquePtr('X509')
+X509_OBJECT = rffi.COpaquePtr('X509_OBJECT')
+COMP_METHOD = rffi.COpaquePtr('COMP_METHOD')
+X509_NAME_ENTRY = rffi.COpaquePtr('X509_NAME_ENTRY')
+X509_EXTENSION = rffi.COpaquePtr('X509_EXTENSION')
+X509_STORE = rffi.COpaquePtr('X509_STORE')
 X509V3_EXT_METHOD = rffi.CArrayPtr(v3_ext_method)
 ASN1_STRING.TO.become(asn1_string_st)
 ASN1_TIME = rffi.COpaquePtr('ASN1_TIME')
@@ -290,9 +260,9 @@
 GENERAL_NAMES = rffi.COpaquePtr('GENERAL_NAMES')
 GENERAL_NAME.TO.become(GENERAL_NAME_st)
 OBJ_NAME = rffi.CArrayPtr(OBJ_NAME_st)
-COMP_METHOD = rffi.CArrayPtr(COMP_METHOD_st)
 ACCESS_DESCRIPTION = rffi.CArrayPtr(ACCESS_DESCRIPTION_st)
 
+
 HAVE_OPENSSL_RAND = OPENSSL_VERSION_NUMBER >= 0x0090500f
 HAVE_OPENSSL_FINISHED = OPENSSL_VERSION_NUMBER >= 0x0090500f
 HAVE_SSL_CTX_CLEAR_OPTIONS = OPENSSL_VERSION_NUMBER >= 0x009080df and \
@@ -314,8 +284,10 @@
     globals()['libssl_' + name] = external(
         name, argtypes, restype, **kw)
 
-ssl_external('SSL_load_error_strings', [], lltype.Void)
-ssl_external('SSL_library_init', [], rffi.INT)
+ssl_external('SSL_load_error_strings', [], lltype.Void,
+    macro=bool(OPENSSL_VERSION_NUMBER >= 0x10100000 and not LIBRESSL) or None)
+ssl_external('SSL_library_init', [], rffi.INT,
+    macro=bool(OPENSSL_VERSION_NUMBER >= 0x10100000 and not LIBRESSL) or None)
 ssl_external('CRYPTO_num_locks', [], rffi.INT)
 ssl_external('CRYPTO_set_locking_callback',
              [lltype.Ptr(lltype.FuncType(
@@ -341,7 +313,8 @@
     ssl_external('TLSv1_2_method', [], SSL_METHOD)
 ssl_external('SSLv2_method', [], SSL_METHOD)
 ssl_external('SSLv3_method', [], SSL_METHOD)
-ssl_external('SSLv23_method', [], SSL_METHOD)
+ssl_external('TLS_method', [], SSL_METHOD,
+    macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
 ssl_external('SSL_CTX_use_PrivateKey_file', [SSL_CTX, rffi.CCHARP, rffi.INT], rffi.INT,
              save_err=rffi.RFFI_FULL_ERRNO_ZERO)
 ssl_external('SSL_CTX_use_certificate_chain_file', [SSL_CTX, rffi.CCHARP], rffi.INT,
@@ -416,6 +389,8 @@
 ssl_external('X509_NAME_get_entry', [X509_NAME, rffi.INT], X509_NAME_ENTRY)
 ssl_external('X509_NAME_ENTRY_get_object', [X509_NAME_ENTRY], ASN1_OBJECT)
 ssl_external('X509_NAME_ENTRY_get_data', [X509_NAME_ENTRY], ASN1_STRING)
+ssl_external('X509_NAME_ENTRY_set', [X509_NAME_ENTRY], rffi.INT,
+    macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
 ssl_external('i2d_X509', [X509, rffi.CCHARPP], rffi.INT, save_err=SAVE_ERR)
 ssl_external('X509_free', [X509], lltype.Void, releasegil=False)
 ssl_external('X509_check_ca', [X509], rffi.INT)
@@ -427,11 +402,16 @@
 ssl_external('X509_get_ext', [X509, rffi.INT], X509_EXTENSION)
 ssl_external('X509_get_ext_d2i', [X509, rffi.INT, rffi.VOIDP, rffi.VOIDP], rffi.VOIDP)
 ssl_external('X509V3_EXT_get', [X509_EXTENSION], X509V3_EXT_METHOD)
+ssl_external('X509_EXTENSION_get_data', [X509_EXTENSION], ASN1_STRING)
 
 ssl_external('X509_VERIFY_PARAM_get_flags', [X509_VERIFY_PARAM], rffi.ULONG)
 ssl_external('X509_VERIFY_PARAM_set_flags', [X509_VERIFY_PARAM, rffi.ULONG], rffi.INT)
 ssl_external('X509_VERIFY_PARAM_clear_flags', [X509_VERIFY_PARAM, rffi.ULONG], rffi.INT)
 ssl_external('X509_STORE_add_cert', [X509_STORE, X509], rffi.INT)
+ssl_external('X509_STORE_get0_objects', [X509_STORE], stack_st_X509_OBJECT,
+    macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
+ssl_external('X509_STORE_get0_param', [X509_STORE], X509_VERIFY_PARAM,
+    macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
 
 ssl_external('X509_get_default_cert_file_env', [], rffi.CCHARP)
 ssl_external('X509_get_default_cert_file', [], rffi.CCHARP)
@@ -468,8 +448,12 @@
              macro=True)
 ssl_external('sk_X509_OBJECT_value', [stack_st_X509_OBJECT, rffi.INT],
              X509_OBJECT, macro=True)
-ssl_external('pypy_X509_OBJECT_data_x509', [X509_OBJECT], X509,
-             macro=True)
+ssl_external('X509_OBJECT_get0_X509', [X509_OBJECT], X509,
+             macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
+ssl_external('X509_OBJECT_get_type', [X509_OBJECT], rffi.INT,
+             macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
+ssl_external('COMP_get_type', [COMP_METHOD], rffi.INT,
+             macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
 ssl_external('sk_DIST_POINT_num', [stack_st_DIST_POINT], rffi.INT,
              macro=True)
 ssl_external('sk_DIST_POINT_value', [stack_st_DIST_POINT, rffi.INT], DIST_POINT,
@@ -511,8 +495,7 @@
 # with the GIL held, and so is allowed to run in a RPython __del__ method.
 ssl_external('SSL_free', [SSL], lltype.Void, releasegil=False)
 ssl_external('SSL_CTX_free', [SSL_CTX], lltype.Void, releasegil=False)
-ssl_external('CRYPTO_free', [rffi.VOIDP], lltype.Void)
-libssl_OPENSSL_free = libssl_CRYPTO_free
+ssl_external('OPENSSL_free', [rffi.VOIDP], lltype.Void, macro=True)
 
 ssl_external('SSL_write', [SSL, rffi.CCHARP, rffi.INT], rffi.INT,
              save_err=SAVE_ERR)
@@ -576,10 +559,11 @@
             SSL, rffi.CCHARPP, rffi.UINTP], lltype.Void)
 
 EVP_MD_CTX = rffi.COpaquePtr('EVP_MD_CTX', compilation_info=eci)
-EVP_MD     = lltype.Ptr(EVP_MD_st)
+EVP_MD = rffi.COpaquePtr('EVP_MD')
 
 OpenSSL_add_all_digests = external(
-    'OpenSSL_add_all_digests', [], lltype.Void)
+    'OpenSSL_add_all_digests', [], lltype.Void,
+    macro=bool(OPENSSL_VERSION_NUMBER >= 0x10100000 and not LIBRESSL) or None)
 EVP_get_digestbyname = external(
     'EVP_get_digestbyname',
     [rffi.CCHARP], EVP_MD)
@@ -592,10 +576,18 @@
 EVP_DigestFinal = external(
     'EVP_DigestFinal',
     [EVP_MD_CTX, rffi.CCHARP, rffi.VOIDP], rffi.INT)
+EVP_MD_size = external(
+    'EVP_MD_size', [EVP_MD], rffi.INT)
+EVP_MD_block_size = external(
+    'EVP_MD_block_size', [EVP_MD], rffi.INT)
 EVP_MD_CTX_copy = external(
     'EVP_MD_CTX_copy', [EVP_MD_CTX, EVP_MD_CTX], rffi.INT)
-EVP_MD_CTX_cleanup = external(
-    'EVP_MD_CTX_cleanup', [EVP_MD_CTX], rffi.INT, releasegil=False)
+EVP_MD_CTX_new = external(
+    'EVP_MD_CTX_new', [], EVP_MD_CTX,
+    macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
+EVP_MD_CTX_free = external(
+    'EVP_MD_CTX_free', [EVP_MD_CTX], lltype.Void, releasegil=False,
+    macro=bool(OPENSSL_VERSION_NUMBER < 0x10100000) or None)
 
 OBJ_NAME_CALLBACK = lltype.Ptr(lltype.FuncType(
         [OBJ_NAME, rffi.VOIDP], lltype.Void))
@@ -606,7 +598,7 @@
 # Used for adding memory pressure. Last number is an (under?)estimate of
 # EVP_PKEY_CTX's size.
 # XXX: Make a better estimate here
-HASH_MALLOC_SIZE = EVP_MD_SIZE + EVP_MD_CTX_SIZE \
+HASH_MALLOC_SIZE = 120 + 48 \
         + rffi.sizeof(EVP_MD) * 2 + 208
 
 def init_ssl():


More information about the pypy-commit mailing list