Using OpenSSL with Windows cert store
Michael.Wojcik at microfocus.com
Sun Apr 23 21:41:57 UTC 2023
> From: openssl-users <openssl-users-bounces at openssl.org> On Behalf Of Pawel Frankowski
> Sent: Sunday, 23 April, 2023 13:59
> I need to to develop TLS 1.2 application using OpenSSL 1.0.2 (FIPS compliant version)
> on Windows platform.
"FIPS compliant" doesn't mean anything useful. I'm assuming you mean "I have a requirement to develop an application which uses cryptography, and the cryptography must have a FIPS 140 validation". Note that OpenSSL 1.0.2 is out of support unless you have a support contract for it. Also, I think OpenSSL 1.0.2's FIPS validation was moved to historic status, though as I recall there was some kerfuffle around this and perhaps it was restored to active.
In any case, now that we have OpenSSL 3.0 and it has a FIPS 140-validated provider, why do you want to use 1.0.2?
> I have requirement that it should get certificates, keys and
> CRLs from Windows cert store, and it should use TLS 1.2 EC-based suites.
Setting aside the matter of CRLs (because they're terrible and generally useless) this raises another question: if you're using the Windows cryptographic store, why not use Windows cryptography and set *that* to FIPS mode?
> Correct me if I am wrong, but as far as I know there are, at least in theory, 2 ways
> of doing this:
> 1) Get required cert/keys from Windows store using Windows API (Crypto API or CNG ?)
CNG supersedes CAPI and is recommended for new applications. If you're not already using CAPI (e.g. because you're using OpenSSL prior to 3.0 and the CAPI Engine), use CNG.
You can only retrieve keys from the Windows store if they're marked as exportable. It's safer (under some threat models) and generally more sensible to let Windows perform the key-related operations, if you're using the Windows store.
> Getting certificates from there programmatically using WinAPI is quite easy and works
> CertFindCertificateInStore, etc.),
> but is it possible to retrieve also corresponding private keys ?
Only if the keys are marked as exportable, which is not the default. There is also the perennial problem of CAPI/CNG "providers" and incorrectly-labeled keys, which I'll go into below if I remember to.
> Or perhaps it would b e easier to use CNG API to do it ?
Regardless of whether it's easier, it would be better to use CNG. Or the equivalent .NET APIs if you're writing a CLR program.
> 2) Using OpenSSL directly with CryptoAPI engine (capi).
> Setting capi engine I was able to sign and verify signatures using RSA certs/keys,
> but it seems that CryptoAPI (and capi engine using it) does not support EC.
CAPI itself doesn't support anything. It's a framework API. Algorithms are provided by CAPI providers, and Microsoft has published CAPI ECC providers, but I have no idea offhand what's installed by default in current Windows versions. It's been several years since I had to muck around in this stuff.
The OpenSSL 1.x CAPI Engine does not support ECC operations directly. (If you look at the source, you'll see it only implements RSA and DSA as far as algorithms go.) In principle you can use it to extract certificates with ECC public keys, and exportable private ECC keys, *if* you have an appropriate provider, and you tell the engine to use that provider when you go to extract those objects, and the keys were added to the Windows store correctly.
On that last point, the problem I alluded to above rears its ugly head. Private keys in the Windows store are supposed to be labeled with the provider they use. Often they are not. (More specifically, there's both a provider name and a provider type, and braindead software such as Microsoft's certutil will set the provider name correctly, if you tell it to, but always have the provider type wrong.) I ended up tweaking capi_load_privkey in my fork of the OpenSSL CAPI Engine to silently fix the provider type when trying to load a key. Or, actually, looking at my code, in capi_get_key. Whatever.
But, rather than go through the grief of using the OpenSSL CAPI Engine (with a fix similar to mine), or your own code, to extract private keys (which still must be exportable), why not Do The Right Thing and let Windows handle the cryptography, in FIPS mode? (Maybe you don't want to put Windows in FIPS mode, but then the question arises of why you need FIPS 140 validation for your application when the OS and other applications don't.) Either use OpenSSL 1.x and enhance the CAPI Engine to do ECC – it's just a matter of wrapping the relevant CAPI functions, along the same lines as for RSA and DSA – or move to OpenSSL 3.0 and either write or find a CNG Provider. Someone mentioned one on this list some time back.
Having worked with CAPI and the OpenSSL 1.x CAPI Engine, I know I'd rather write a CNG Provider from scratch for 3.0 than go through that again. The OpenSSL CAPI engine isn't very complicated but CAPI itself is a mess with hard-to-diagnose issues like the provider-type problem, and using 1.x is a Bad Idea unless you have a support contract (and, arguably, even then, if you have any scope whatsoever for moving to 3.0). And if the OS vendor will provide FIPS-validated cryptography for you ... well, that's a whole hassle you're avoiding.
More information about the openssl-users