Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Providing SSL Connections in Python using PKCS#11

I have to implement a Python based web server on a Linux based firmware for an embedded system component:

class WebServer(http.server.HTTPServer)
...
...

To enable ssl connections a ssl context is created within the server by

self.ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
self.ssl_context.load_cert_chain(certfile=cert, keyfile=key)
self.ssl_context.verify_mode = ssl.CERT_REQUIRED
self.ssl_context.load_verify_locations(verifyCert)

Note: cert is a file path to the certificate, keyfile is the path to the private key.

Upon a request the method get_request is called:

def get_request(self):
    request = self.socket.accept()
    if self.ssl_context:
        req_socket, addr = request
        connstream = self.ssl_context.wrap_socket(req_socket, server_side=True)
        return connstream, addr
    else:
        return request

The wrap_socket method is used to wrap the original socket into a ssl socket, which is returned instead. That is all to provide a ssl connection.

Now the question:

The solution is a first implementation and not secure. We are oblidged to use a given hardware security module (HSM) to create and store certificates and private keys. Any private keys are completely hidden and will never leave the module. All cryptographic primitives have to be executed directly within the module. The interface to the HSM is PKCS#11, for which a vendor supplied dynamic middle-ware library exists.

How can I use the module instead of the original ssl for setup of the ssl context under python? I know already, that ssl is based on openSSL, for which a PKCS#11 engine exists (libarary opensc-pkcs11.so). The middleware from the vendor provides the PKCS#11 API.

Unfortunately, I have no plan how the PKCS#11 engine is to be integrated into python's ssl/openSSL and how to tie all things together. Is it even possible to transparently use PKCS#11 instead of the native implementation, and if yes, how do I activate it from python? Moreover, how would I have to pass the arguments "certfile" and "keyfile", because both are not available anymore as plain files? In fact I have no access to the private key directly; there are only URL-based references to objects within the HSM used to operate on it.

Can PyKCS11 be a solution instead of ssl?

I just need to know the basic path to solving such problem. I can find all the details on my own.

like image 318
MichaelW Avatar asked Dec 15 '16 18:12

MichaelW


1 Answers

It's not recommended to do this TLS stuff in the webserver with Python. It's better to do it using nginx or apache. They support both the pkcs#11 SSL context and are fast to negociate SSL since they are written in C.

So to resume:

  • Stay on HTTP (not secure) in Python side
  • Install nginx or apache
  • Configure it for HTTPS :
    1. using pkcs#11 SSL cert/key (pkcs#11 URI to your HSM)
    2. reverse proxy it to your HTTP (not secure) Python webserver.
like image 191
Sami ZRAFI Avatar answered Oct 15 '22 09:10

Sami ZRAFI