> On 30 Nov 2022, at 16:59, chris...@weinigel.se wrote: > > Hi all, > > for quite some time I've been working on a Python implementation of a > protocol called NTS which requires access to an API in OpenSSL which is not > provided by the Python ssl module. I added a patch for that which > unfortunately for me the maintainer did not want to accept. Some comments > were made of a possible future way to give more generic access to the openssl > library via ctypes/cffi but I have been unable to find more information about > that. I was home sick last week and decided to take a shot at it and have > built something that I feel is a bit ugly but does seem to work. I'd like to > some feedback on this approach.
We use the pyOpenSSL to access APIs of openssl. No need to use ctypes. Barry > > My patches can be found on github, based on the Python 3.11 tag: > > https://github.com/python/cpython/compare/3.11...wingel:cpython:main > > Here's a short description of each patch on this branch: > > "bpo-37952: SSL: add support for export_keying_material" is my old patch > which adds the method I need to the ssl library just for reference. > > The other commits add the necessary infrastructure with some example code. > These commits are not ready for submission but hopefully they show what I > have in mind. > > "Add CRYPTO_DLL_PATH and SSL_DLL_PATH to the _ssl module. " > > This commit adds two constants to the "_ssl" C module with the paths to > libcrypto and libssl respectively. On Linux dladdr and on Windows > GetModuleHandle/GetModuleFilename are used on a symbol in each library to > find the path to the corresponding DLL. I've verified that this works Debian > Bulleye and on Windows 10 with Visual Studio 2017. I don't own a Mac so I > haven't been able to test this on macOS, but I believe dladdr is available on > modern macOS so it might work out of the box. With the paths it's possible > to use ctypes or cffi get a handle to these libraries. > > "Add API to get the address of the SSL structure" then adds an API to an > SSLSocket which returns the address of the corresponding "SSL" C structure. > This address can be used by ctypes/cffi. One would probably want to expose > SSL_CTX, SSL_SESSION and BIO too but I started with just SSL since that's > what my code needs right now. > > "Add a small test program" is a small test program that uses the > infrastructure from the two above commits to call C functions in > libssl/libcrypto using both ctypes and cffi. It's a bit ugly but hopefully > it's not too hard to understand. > > "Example of how to extend the ssl library using ctypes" is an example of how > a Python module that extends the SSL library using ctypes could look. First > get a handle to libssl using ctypes, set up ctypes with the correct API for > the export_keying_material function, wrap it in a more Pythonic function and > then extend SSLSocket with the new function. A simplified version looks like > this: > > import ssl, ctypes > ssl_lib = ctypes.CDLL(ssl._ssl.SSL_DLL_PATH) > ssl_lib.SSL_export_keying_material.argtypes = ( > ctypes.c_void_p, # SSL pointer > ctypes.c_void_p, ctypes.c_size_t, # out pointer, out length > ctypes.c_void_p, ctypes.c_size_t, # label buffer, label length > ctypes.c_void_p, ctypes.c_size_t, # context, context length > ctypes.c_int) # use context flag > ssl_lib.SSL_export_keying_material.restype = ctypes.c_int > > def SSL_export_keying_material(self, label, key_len, context = None): > c_key = ctypes.create_string_buffer(key_len) > c_label = ctypes.create_string_buffer(len(label)) > c_context = ctypes.create_string_buffer(context, len(context)) > if ssl_lib.SSL_export_keying_material( > self._sslobj.get_internal_addr(), > c_key, key_len, > c_label, len(label), > c_context, len(context), 1); > return bytes(c_key) > > ssl.SSLSocket.export_keying_material = SSL_export_keying_material > > There's a final commit "Expose more OPENSSL_ variables" which add some more > constants to the ssl module which expose the cflags and build information > from OpenSSL. This patch is not really necessary, but it might be a good > idea to compare these constants with the corresponding constants retrieved > using ctypes/cffi to make sure that exactly the same version of the openssl > library is used. > > Does this seem like a good idea? As I said, I feel that it is a bit ugly, > but it does mean that if someone wants to use some > SSL_really_obscure_function in libcrypto or libssl they can do that without > having to rebuild all of CPython themselves. Or if they want to integrate > with some other C library that wants a raw pointer to a SSL socket. > Hopefully this would reduce the burden on the ssl module maintainers a bit. > > Anyway, if you think this is a good approach I could clean up my patches, add > support for SSL_CTX/SSL_SESSION/BIO, document all of this and make it into a > proper pull request. > > /Christer > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/JFUMGTPXEGV63DIY5BNZRRCNADPEQC2O/ > Code of Conduct: http://python.org/psf/codeofconduct/ > _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/ZEMKQD4JTJYLFBSSU4RNF4ZLFAVFX665/ Code of Conduct: http://python.org/psf/codeofconduct/