[Cryptography-dev] Adding set_cert_store to pyOpenSSL - patches

Barry Scott barry.scott at forcepoint.com
Wed Oct 21 06:27:16 EDT 2020


On Wednesday, 14 October 2020 10:52:24 BST Barry Scott wrote:
> In an app that uses twisted that uses pyOpenSSL I found that
> to it takes 1s CPU bound to setup a TLS session because the
> twisted code copies the trust store into the context one cert
> at a time.
> 
> I'm using openssl-1.1.1g and python 2.7.18 (yes I know...).
> 
> Here is the function in twisted that causes the 1s CPU bound loop:
> 
> class OpenSSLCertificateAuthorities(object):
>     def __init__(self, caCerts):
>         self._caCerts = caCerts
> 
>     def _addCACertsToContext(self, context):
>         store = context.get_cert_store()
>         for cert in self._caCerts:
>             store.add_cert(cert)
> 
> The obvious way to fix this is to setup the X509Store at app
> startup with the trusted certs. Then set that store on the context.
> 
> The new code would be:
> 
> class OpenSSLCertificateAuthorities(object):
>     def __init__(self, caCerts):
>         self._caCerts = caCerts
>         self._store = X509Store()
>         for cert in self._caCerts:
>             self._store.add_cert(cert)
> 
>     def _addCACertsToContext(self, context):
>         context.set_cert_store(self._store)
> 
> And the patch to pyOpenSSL is:
> 
> --- tmp1/pyopenssl-19.1.0/src/OpenSSL/SSL.py    2019-11-18 04:47:22.000000000 +0000
> +++ tmp2/pyopenssl-19.1.0/src/OpenSSL/SSL.py    2020-10-13 15:11:02.255560148 +0100
> @@ -1357,6 +1357,14 @@
>          pystore._store = store
>          return pystore
>  
> +    def set_cert_store(self, store):
> +        """
> +        Set the certificate store for the context.
> +
> +        :store: A X509Store object or None if it does not have one.
> +        """
> +        _lib.SSL_CTX_set_cert_store(self._context, store)
> +
>      def set_options(self, options):
>          """
>          Add options. Options set before are not cleared!
> 
> But I see this exception:
> 
>   File "ngtls_context_set.py", line 107, in _addCACertsToContext
>     context.set_cert_store(self._store)
>   File "/usr/local/lib/python2.7/site-packages/OpenSSL/SSL.py", line 1366, in set_cert_store
>     _lib.SSL_CTX_set_cert_store(self._context, store)
> TypeError: initializer for ctype 'X509_STORE *' must be a cdata pointer, not X509Store
> 
> My searching has not lead me to a way to get a cdata pointer fpr X509Store.
> 
> What do I need to do to get set_cert_store working?

Here are the set of patches that I used to add set_cert_store and get the time to setup a context
from ~1000ms to 0.3ms:

Twisted needs access to set_cert_store.

set_cert_store is missing from cryptography
set_cert_store requires the use of X509_STORE_up_ref

X509_STORE_up_ref is missing from cryptography.

diff -r -u tmp1/cryptography-2.1.4/src/_cffi_src/openssl/x509_vfy.py tmp2/cryptography-2.1.4/src/_cffi_src/openssl/x509_vfy.py
--- tmp1/cryptography-2.1.4/src/_cffi_src/openssl/x509_vfy.py   2017-11-30 01:53:32.000000000 +0000
+++ tmp2/cryptography-2.1.4/src/_cffi_src/openssl/x509_vfy.py   2020-10-15 16:56:44.893834630 +0100
@@ -142,6 +142,7 @@
 int X509_STORE_set_default_paths(X509_STORE *);
 int X509_STORE_set_flags(X509_STORE *, unsigned long);
 void X509_STORE_free(X509_STORE *);
+int X509_STORE_up_ref(X509_STORE *);
 
 /* X509_STORE_CTX */
 X509_STORE_CTX *X509_STORE_CTX_new(void);


--- tmp1/pyopenssl-19.1.0/src/OpenSSL/SSL.py    2019-11-18 04:47:22.000000000 +0000
+++ tmp2/pyopenssl-19.1.0/src/OpenSSL/SSL.py    2020-10-16 11:14:06.933208747 +0100
@@ -1357,6 +1357,15 @@
         pystore._store = store
         return pystore
 
+    def set_cert_store(self, store):
+        """
+        Set the certificate store for the context.
+
+        :store: A X509Store object or None if it does not have one.
+        """
+        _lib.X509_STORE_up_ref( store._store )
+        _lib.SSL_CTX_set_cert_store(self._context, store._store)
+
     def set_options(self, options):
         """
         Add options. Options set before are not cleared!

And in twisted:

--- tmp1/twisted-twisted-19.7.0/src/twisted/internet/_sslverify.py      2019-07-28 10:17:29.000000000 +0100
+++ tmp2/twisted-twisted-19.7.0/src/twisted/internet/_sslverify.py      2020-10-16 12:03:54.653035837 +0100
@@ -963,12 +963,13 @@
         @type caCerts: L{list} of L{OpenSSL.crypto.X509}
         """
         self._caCerts = caCerts
+        self._store = X509Store()
 
+        for cert in self._caCerts:
+            self._store.add_cert(cert)
 
     def _addCACertsToContext(self, context):
-        store = context.get_cert_store()
-        for cert in self._caCerts:
-            store.add_cert(cert)
+        context.set_cert_store(self._store)

Do you want these patches as a PR?

Barry





More information about the Cryptography-dev mailing list