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
_______________________________________________
Kamailio (SER) - Development Mailing List
sr-dev@lists.kamailio.org
https://lists.kamailio.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to