From Fedora Project Wiki
Line 51: Line 51:
Yes, it failed to actually make a VPN connection, but that's expected — that server isn't running an AnyConnect VPN service. The important part is that the VPN client '''was''' attempting to use the correct client certificate.
Yes, it failed to actually make a VPN connection, but that's expected — that server isn't running an AnyConnect VPN service. The important part is that the VPN client '''was''' attempting to use the correct client certificate.


Now let's pretend that I'm packaging curl. Let's have a look...
Now let's pretend that I'm packaging curl. Curl uses a colon to separate the certificate and the password so we'll need to escape the colon in the URI...


<pre>
<pre>
$ curl -E 'pkcs11:token=Gnome2%20Key%20Storage;id=%59%ae%17%70%af%e8%af%9f%5b%94%fb%c6%89%f6%f1%4c%11%5c%36%0e' -I -v https://auth.startssl.com* Rebuilt URL to: https://auth.startssl.com/
$ curl -E 'pkcs11\:token=Gnome2%20Key%20Storage;id=%59%ae%17%70%af%e8%af%9f%5b%94%fb%c6%89%f6%f1%4c%11%5c%36%0e' -I -v https://auth.startssl.com* Rebuilt URL to: https://auth.startssl.com/
*  Trying 192.116.242.27...
*  Trying 192.116.242.27...
* Connected to auth.startssl.com (192.116.242.27) port 443 (#0)
* Connected to auth.startssl.com (192.116.242.27) port 443 (#0)
Line 60: Line 60:
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
   CApath: none
   CApath: none
* NSS: client certificate not found: pkcs11
* NSS: client certificate not found: pkcs11:token=Gnome2%20Key%20Storage;id=%e6%34%78%b5%fd%86%77%ba%b9%86%95%c3%19%02%74%d1%f5%33%9a%97
* NSS error -12227 (SSL_ERROR_HANDSHAKE_FAILURE_ALERT)
* NSS error -12227 (SSL_ERROR_HANDSHAKE_FAILURE_ALERT)
* SSL peer was unable to negotiate an acceptable set of security parameters.
* SSL peer was unable to negotiate an acceptable set of security parameters.
* Closing connection 0
* Closing connection 0
curl: (35) NSS: client certificate not found: pkcs11
curl: (35) NSS: client certificate not found: pkcs11:token=Gnome2%20Key%20Storage;id=%e6%34%78%b5%fd%86%77%ba%b9%86%95%c3%19%02%74%d1%f5%33%9a%97
</pre>
</pre>


Oops, that 'client certificate not found' doesn't look good. If curl was built with GnuTLS instead of NSS that probably would have worked fine. As it is, let's file [https://bugzilla.redhat.com/show_bug.cgi?id=1219544 bug 1219544] against curl...
Oops, that 'client certificate not found' doesn't look good. If curl was built with GnuTLS instead of NSS that probably would have worked fine. As it is, let's file [https://bugzilla.redhat.com/show_bug.cgi?id=1219544 bug 1219544] against curl...

Revision as of 16:14, 7 May 2015

Testing PKCS#11 support

The proposed packaging guidelines say that any program which can accept SSL certificates from a file should also allow them to come from a PKCS#11 token. This page exists to help packagers understand those guidelines and test their packages.

But I don't have any PKCS#11 hardware

You don't need hardware. There are plenty of PKCS#11 providers which are purely software. These include

  • NSS Certificate Database (Firefox, Evolution, Chrome)
  • GNOME keyring
  • SoftHSM

The simplest one to test with is probably GNOME keyring. Obviously not everyone will be running GNOME for their day-to-day usage but it shouldn't be too hard to use GNOME keyring just for a simple test.

Import certificate

The seahorse GUI tool allows you to browse the contents of PKCS#11 tokens and import certificates and keys. If you simply run seahorse under GNOME you should see a 'Gnome2 Key Storage' token listed under the 'Certificates' heading. You can select the 'File'... 'Import' menu item to import a certificate from a file into the GNOME keyring (or indeed any other provider you choose to use).

Determine the PKCS#11 URI of your certificate

Unfortunately, seahorse doesn't show the PKCS#11 URI of the objects when you're browsing (bug #749071). So you'll want to use p11tool to list them and find the URI:

$ p11tool --list-certs --login pkcs11:token=Gnome2%20Key%20Storage
Object 0:
	URL: pkcs11:model=1.0;manufacturer=Gnome%20Keyring;serial=1%3aUSER%3aDEFAULT;token=Gnome2%20Key%20Storage;id=%59%ae%17%70%af%e8%af%9f%5b%94%fb%c6%89%f6%f1%4c%11%5c%36%0e;object=Woodhouse%2c%20David;type=cert
	Type: X.509 Certificate
	Label: Woodhouse, David
	ID: 59:ae:17:70:af:e8:af:9f:5b:94:fb:c6:89:f6:f1:4c:11:5c:36:0e

The interesting part there is the URL. In fact a lot of the information there is redundant; all you probably need is the token and id parts:

pkcs11:token=Gnome2%20Key%20Storage;id=%59%ae%17%70%af%e8%af%9f%5b%94%fb%c6%89%f6%f1%4c%11%5c%36%0e

See if you can use it

Now let's pretend I'm packaging the OpenConnect VPN client. It has fairly reasonable documentation (if I do say so myself) on how to use it with PKCS#11. It looks like it should comply with the Fedora guidelines and just accept a PKCS#11 URI on the command line with the -c option, in place of a filename.

Let's test...

$ openconnect -c 'pkcs11:token=Gnome2%20Key%20Storage;id=%59%ae%17%70%af%e8%af%9f%5b%94%fb%c6%89%f6%f1%4c%11%5c%36%0e'  https://auth.startssl.comPOST https://auth.startssl.com/
Attempting to connect to server 192.116.242.27:443
Using client certificate 'Woodhouse\, David'
SSL negotiation with auth.startssl.com
SSL connection failure: A TLS fatal alert has been received.
Failed to open HTTPS connection to auth.startssl.com
Failed to obtain WebVPN cookie

Yes, it failed to actually make a VPN connection, but that's expected — that server isn't running an AnyConnect VPN service. The important part is that the VPN client was attempting to use the correct client certificate.

Now let's pretend that I'm packaging curl. Curl uses a colon to separate the certificate and the password so we'll need to escape the colon in the URI...

$ curl -E 'pkcs11\:token=Gnome2%20Key%20Storage;id=%59%ae%17%70%af%e8%af%9f%5b%94%fb%c6%89%f6%f1%4c%11%5c%36%0e' -I -v https://auth.startssl.com* Rebuilt URL to: https://auth.startssl.com/
*   Trying 192.116.242.27...
* Connected to auth.startssl.com (192.116.242.27) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* NSS: client certificate not found: pkcs11:token=Gnome2%20Key%20Storage;id=%e6%34%78%b5%fd%86%77%ba%b9%86%95%c3%19%02%74%d1%f5%33%9a%97
* NSS error -12227 (SSL_ERROR_HANDSHAKE_FAILURE_ALERT)
* SSL peer was unable to negotiate an acceptable set of security parameters.
* Closing connection 0
curl: (35) NSS: client certificate not found: pkcs11:token=Gnome2%20Key%20Storage;id=%e6%34%78%b5%fd%86%77%ba%b9%86%95%c3%19%02%74%d1%f5%33%9a%97

Oops, that 'client certificate not found' doesn't look good. If curl was built with GnuTLS instead of NSS that probably would have worked fine. As it is, let's file bug 1219544 against curl...