[sr-dev] [kamailio/kamailio] [WIP] tls: add support for OpenSSL engine and private keys in HSM (#1484)

aalba6675 notifications at github.com
Fri Mar 23 14:54:07 CET 2018


Thanks for the comments - I have replaced malloc/free in the mapping utilities with `pkg_malloc()/pkg_free()`. Re: "I did not fully understand why you need this here, maybe you can
elaborate a bit on the requirements of the HSM child_init."

Background: For soft keys, we initialize the SSL_CTX `d->ctx[i]` in PROC_INIT, then fork(). All SSL_CTX objects are now completely initialized and can be used as-is by SSL* objects.

For the HSM case, the private key handle from `ENGINE_load_private_key()` is a proxy for the private key in the HSM. This proxy object is not guaranteed to be  valid in a different process whether by fork() or shared memory.

During `mod_child()` we also cannot load the private key into `SSL_CTX *d->ctx[i]`, as the next child will simply overwrite the value since these are in shared memory. In my first implementation I forgot about shared memory so the keys are what the final child loaded. These keys would only work for the last child and the handle was invalid when other children tried to use them.

In my current implementation, I leave the SSL_CTXs as keyless. Instead loading the private key into a local set, keyed by the SSL_CTX pointer. Therefore SSL_CTX for HSM domains are keyless and incomplete for SSL_accept(). At runtime, just before

    SSL_accept(ssl)

I retrieve the SSL_CTX* from ssl, and check if it is indeed keyless, i.e, it exists in the local key set. Then we retrieve the HSM key in just-in-time mode and load into the `SSL* ssl` object.

Summary:
Soft key: d->ctx[i] fully initialized with private key from PEM file

HSM key: d->ctx[i] keyless, the privatekey  is stored in a local set: as hash table
  { domain0->ctx[0]:  EVP_PKEY*
    domain0->ctx[1]: EVP_PKEY*
    ....
    domain1->ctx[0]: EVP_PKEY*
    domain1->ctx[2]: EVP_PKEY*
   ...
}.

Notes:

1. Most engines that deal with HSM private keys are wrappers around a vendor or OpenSC PKCS 11 library.
1. AWS CloudHSM engine (`libgem.so`) a wrapper around SafeNet Luna HSM `libCryptoki2_64.so` actually produces private keys that work even in a different process. If the last child/master loads its private key into `d->ctx[i]` all the other children can use this `SSL_CTX`. This type of behaviour is due to their special care in implementaion and not mandated.
1. OpenSC/libp11: this engine can wrap any PKCS11 library into an engine. When wrapping `libCryptoki2_64.so` its private keys didn't work in another process. That is why I chose to use a local set. 
1. Interestingly the NGINX developers refused to accept HSM private key handling to the child. They state that is the role of the PKCS 11 library to make sure its objects are valid across a fork(). Sadly, this principle does not accord with reality.
1. Although HAProxy has engine support, they do not use engine private keys yet, so have not addressed this issue.
1. GNUTLS recommends that all PKCS 11 objects be used only in one process; i.e don't try to leak handles across fork() or shared memory.












-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/kamailio/kamailio/pull/1484#issuecomment-375671973
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.kamailio.org/pipermail/sr-dev/attachments/20180323/ed06cd92/attachment-0001.html>


More information about the sr-dev mailing list