[PATCH 0/4] SSL: Add support for loading X.509 certificates from openssl engine

Vesa Jääskeläinen vesa.jaaskelainen at vaisala.com
Thu Jul 13 07:38:02 UTC 2023


Hi Maxim,

On 13.7.2023 3.48, Maxim Dounin wrote:
> Hello!
>
> On Wed, Jul 12, 2023 at 05:07:03PM +0300, Vesa Jääskeläinen via nginx-devel wrote:
>
>> (I hope this goes properly out as I had major issues with hg email so
>> combined hg export + git send-email)
>>
>> It is convenient to keep X.509 certificates related to key pairs stored in
>> openssl engine within the engine.
>>
>> Implementation uses 'LOAD_CERT_CTRL' extension to fetch certificate from
>> the engine. This extension is not supported by all engines and in those
>> cases it should report with an error.
>>
>> Configuration is similar to what it is for 'ssl_certificate_key'.
>>
>> First certificate must match with ssl_certificate_key's key pair rest of
>> the certificiates are added to the certificate chain.
>>
>> Example configuration with libp11's pkcs11 engine:
>>
>>    ssl_certificate      "engine:pkcs11:pkcs11:token=mytoken;object=mykey
>>                          engine:pkcs11:pkcs11:token=mytoken;object=int-ca";
>>    ssl_certificate_key  "engine:pkcs11:pkcs11:token=mytoken;object=mykey?pin-value=mypin";
>>
>> Tested the loading with two pkcs11 implementations SoftHSMv2 and with
>> OP-TEE's PKCS11 Trusted Application running on Embedded Linux device.
>>
>> First three commits is the main beef and in order to make it more flexible
>> added also last commit allowing intermediate certificates loaded from file
>> system.
>>
>> Separator of space is used as there was already existing use of array for
>> ssl_certificate configuration.
> Just in case, a similar proposal was previously discussed here:
>
> https://mailman.nginx.org/pipermail/nginx-devel/2020-April/013130.html
> https://mailman.nginx.org/pipermail/nginx-devel/2020-May/013142.html
>
> Notably, the review is here:
>
> https://mailman.nginx.org/pipermail/nginx-devel/2020-May/013152.html
>
> I'm additionally sceptical about this given that engine interface
> is deprecated by OpenSSL.

Thanks for the links.

The provider interface in OpenSSL 3 is yet to be matured for PKCS11 usage.

libp11 so far seems to have stayed with "legacy" engine and just adapted 
for OpenSSL 3.

Then there is new project that is still in development phase but looks 
promising:

https://github.com/latchset/pkcs11-provider

But before that provider implementation matures and is available in 
distributions it takes one or more major LTS releases.

While waiting for that it would be nice to have the support.

What is interesting that the CMD extension is already being integrated 
to other software like curl, wpa-supplicant/hostapd, stunnel, ppp, 
M2Crypto -- so I would say the feature is there to stay for a while. 
Even not documented as official openssl "extension" it is there and is 
being used.

Now openssl also has "store" API which can be extended with different 
schemes too but in example libp11 does not today support that.

https://www.openssl.org/docs/man1.1.1/man7/ossl_store.html
https://www.openssl.org/docs/man1.1.1/man3/OSSL_STORE_LOADER.html

Now the Nginx is already using the "legacy" interface so if it is enable 
why not then support the certificate loading when it is available.

I believe these can even coexist.

   provider:<provider>:<object id>
   provider:pkcs11:<your pkcs11 uri>

and

   engine:<engine>:<object id>
   engine:pkcs11:<your pkcs11 uri>

or even:

   store:<scheme>:<object id>
   store:pkcs11:<your pkcs11 uri>
   store:file:/path/to/your/pem-file

Now the problem of these all is what certificate to load and what 
certificates from the chain to load if any.

"The correct way" is to load all certificates till the root (excluding 
the root) but this is not how some people setup the stuff. So you need a 
way to be able to specify the chain.

With PEM files this is easy as one can craft them freely.

With other providers you need to either configure (like what M2Crypto 
uses) or be simple only use the certificate without chain (a bit ugly 
approach).

   ssl_certificate "engine:pkcs11:<your pkcs11 uri> engine:pkcs11:<your 
pkcs11 uri> engine:pkcs11:<your pkcs11 uri>"

or you could even mix'n'match if you have go good idea:

   ssl_certificate "provider:<provider>:<object id> 
store:<scheme>:<object id> /my/pem/file/here.pem"

For this I used the white space(s) as a separator in order to be able to 
configure the chain.

Alternative for that would have been:

   ssl_certificate "engine:pkcs11:<your pkcs11 uri>" 
"engine:pkcs11:<your pkcs11 uri>" "engine:pkcs11:<your pkcs11 uri>"

But that would have created array of array of strings as there was 
support to configure multiple certificate chains+key pairs and let the 
nginx pick which to serve.

Why I believe it is a good idea to support engine/or in future the 
provider interface is that to keep the certificates in one place next to 
the keys. With this if the key pair gets re-created or new certificates 
to be updated if you have the labels there you just need to trigger the 
refresh. Then there is no extra data to extract or such as then those 
could be out-of-sync and people try to figure out problems with that.

If I am not mistaken the previous discussion comments has been addressed 
in this change set.

I am happy to test out the provider with pkcs11-provider too but I would 
recommend that we also support today's methods so people can start using 
the feature.

Thanks,
Vesa Jääskeläinen


More information about the nginx-devel mailing list