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