[openssl-users] Loading engines recursively and crypto engine lock
Jakob Bohm
jb-openssl at wisemo.com
Wed Aug 10 13:31:50 UTC 2016
On 08/08/2016 13:39, Krzysztof Konopko wrote:
> Hi,
>
> TL;DR;
> Is it allowed to initialise engines recursively, ie. call
> `engine2->init` from `engine1->init`?
>
> --
>
> I have a solution in a consumer product based on OpenSSL 1.0.2 series
> that uses two engines: one (engine1) for selecting client certificate
> chain (TLS client auth) and another one (engine2) for RPC operations
> on associated private keys stored in H/W. This works only if supplied
> (installed) locks are recursive as for each engine initialisation
> `CRYPTO_LOCK_ENGINE` is taken.
>
> From what I see, OpenSSL 1.1.x onward, provides locking internally and
> it's non-recursive. Also `lock_dbg_cb()` implementation in OpenSSL
> before 1.1.x suggests locks are not expected to be recursive.
>
> Here's some more context of my use case.
>
> OpenSSL loads `engine1` for me automatically (`
>
>
> OPENSSL_SSL_CLIENT_ENGINE_AUTO` variable) which is convenient as I
> don't have control over application's `main()` function. In my case
> it's proprietary code but equally it could be Python script (I do not
> fancy patching Python interpreter to get to its `main()` function and
> load/initialise engines explicitly).
>
> So my _only_ entry point is `engine1->init`. In that entry point I
> initialise engine2 which is a fairly slow operation (need to load
> certs from permanent storage) so definitely want to do this only once.
> Oh, and the app is heavily multi-threaded so I'm glad OpenSSL
> carefully takes crypto engine lock where needed.
>
> But because engines are initialised recursively, the locking
> implementation I supply uses recursive mutex which works very well and
> makes perfect sense to me in this case (I know that the same thread
> calls locked functions recursively for a reason). This works only
> before 1.1.x.
>
> Alternatively I could lazy-initialise engine2 in certificate callback
> function but any initialisation failure here would be less meaningful
> and it would require another lock to protect engine2 handle. In
> `engine1->init` I know a lock is already held so I thought it's safer
> to do more initialisation here. Besides `engine2->init` is not called
> directly but through a layer of application logic so conceptually
> these two engines are orthogonal and know nothing about each other.
>
> I guess initialising engines recursively does not work in OpenSSL
> 1.1.x (it'd be a dead-lock) and I need to seek for a different place
> to initialise engine2, for example in certificate cb? This would mean
> I "leak" some knowledge of engine2 existence into engine1, have
> guarantee that crypto engine lock is not held in certificate callabck
> function and need another lock to protect access to engine2 handle.
>
> Please let me know what your views are and if the above makes sense.
>
I am not part of the OpenSSL team and have no idea what their
thinking or suggestions are.
However the following should be a generic workaround:
1. Create a third engine3 which loads both engine1 and engine2
internally (without going through OpenSSL and its locks).
So for example engine3->init calls both engine2->init and
engine1->init.
2. engine3 would export/provide all the methods from engine1
and engine2 by forwarding or reexporting the calls.
3. OpenSSL itself is instructed to use only your engine3
wrapper.
4. As a more ambitious project, someone could write a generic
"engine3" which loads a list of actual engines from a config
file.
At the OpenSSL design level, the OpenSSL team might extend the
OPENSSL_SSL_CLIENT_ENGINE_AUTOvariable to accept a
colon-separatedlist of engines rather than just a single engine.
Enjoy
Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded
More information about the openssl-users
mailing list