-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
Description
Rather than continuing to pollute #964 I'll open a new ticket. This command line works when curl is built against GnuTLS or a suitably fixed NSS:
curl -E pkcs11:manufacturer=piv_II;id=%01;pin-value=1234 $URL
It doesn't work with OpenSSL, for a number of reasons.
One of the simple problems is that the curl command-line tool will automatically assume you want CURLOPT_SSLENGINE_DEFAULT
if you pass --engine
. This seems wrong, and it makes the SSL connection fail because you really don't ever want that:
* TLSv1.2 (OUT), TLS handshake, Certificate (11):
* error:2D06D075:FIPS routines:fips_pkey_signature_test:test failure
* Marked for [closure]: Failed HTTPS connection
@nased0 I'm assuming this isn't a problem for you because you're using libcurl and not setting CURLOPT_SSLENGINE_DEFAULT
? I can't understand why anyone would want that option, although it's been present in curl(1) since the ENGINE support was first merged in commit af6c394. Can we just make the tool stop doing that?
Next we have to specify the ENGINE explicitly by adding --engine pkcs11
. We'll want to automatically infer that from the 'pkcs11:' at the beginning of the command line. Which brings me to the CURLOPT_SSLCERTTYPE
and CURLOPT_SSLKEYTYPE
options...
I also need to pass --certtype ENG
. OK, suboptimal but I can fix that (and let's fix it to automatically determine PKCS#12 vs. PEM files while we're at it, shall we? Just how much do we hate our users, to make them do that manually?).
So now maybe with --engine pkcs11 --cert-type ENG
it'll work...
curl: (58) unable to set private key file: 'pkcs11:manufacturer=piv_II;id=%01;pin-value=1234' type PEM
Oh, that's cute. We must really hate our users :)
We "assume" that the key identifier string (usually filename) is the same as the cert, but we don't assume that it's the same type? Really? OK, let's tell it that the key is the same type as the cert...
curl $URL --engine pkcs11 --cert-type ENG -E 'pkcs11:manufacturer=piv_II;id=%01;pin-value=1234' --key-type ENG
No keys found.
PKCS11_get_private_key returned NULL
curl: (58) failed to load private key from crypto engine
This is getting surreal now... if I specify the key type you forget what the key was. Finally, if I spell everything out (and patch out the ENGINE_set_default()
call as discussed above), it does actually work:
curl -k https://localhost:4443/data.txt --engine pkcs11 \
--cert-type ENG -E 'pkcs11:manufacturer=piv_II;id=%01;pin-value=1234' \
--key-type ENG --key 'pkcs11:manufacturer=piv_II;id=%01;pin-value=1234'
So... rants about hating users aside, what can we do about this? What part of this utter clusterf*ck do we need to preserve in the name of backward-compatibility, and what can we fix? :)
My suggestion would be to add a cert and key type of 'AUTO', which will be the default, and will work it out automatically. If it's a filename, then look in the file to see if it's PKCS#12 or PEM and act accordingly. And then only if your crypto library is insane enough to make you choose, rather than silently just doing the right thing with the filename you give it.
And if the string starts "pkcs11:" then it's fairly obviously a PKCS#11 URI so treat it as such. Which means setting the engine to 'pkcs11' in the OpenSSL case, but other libraries should cope automatically. Although that's partly because the NSS back end treats it as an NSS identifier even when the type is PEM
... but OK, whatever.
It's possible to fix this up in the tool, and have it inspect the --cert
argument and manually set the type(s) accordingly... but I think it's much better off in the library.