Description of problem: On updating from gnutls-3.6.4-1.fc28 to gnutls-3.6.4-1.fc29, the auth-pkcs11 test in openconnect's "make check" stops working. Steps to Reproduce (on Fedora 28): 1. git clone git://git.infradead.org/users/dwmw2/openconnect 2. autogen/configure --disable-dsa-tests/make check (see it work) 3. dnf --releasever=29 update gnutls 4. make check (see it fail) 5. fedpkg clone gnutls, git reset --hard 1e094600038 (Build and run against that, and it works.) 6. Comment out Patch3: gnutls-3.6.4-disable-tls13.patch (Run against that one, and it fails.) Additional info: OpenConnect's PKCS#11 test uses three SoftHSM tokens. The actual SoftHSM tokens are stored in git for repeatability, but the commands originally used to create them (with comments about which ones have the public key missing) are at http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/tests/Makefile.am#l188 With the broken GnuTLS, the first token (created by softhsm2-util) works but the other two (created by p11tool) don't. Debug output from running the test at http://david.woodhou.se/auth-pkcs11.log.token http://david.woodhou.se/auth-pkcs11.log.token1 This looks like the interesting part of the difference (with the 'token1' file obviously being one of the failing ones): $ diff -up auth-pkcs11.log.token auth-pkcs11.log.token1 --- auth-pkcs11.log.token 2019-01-02 18:02:17.027013696 +0000 +++ auth-pkcs11.log.token1 2019-01-02 17:47:45.806635465 +0000 ... @@ -321,36 +321,40 @@ Signature algorithm RSA-SHA256 is not en checking cert compat with RSA-PSS-SHA256 checking cert compat with RSA-PSS-RSAE-SHA256 HSK[0x8006c0]: signing TLS 1.3 handshake data: using RSA-PSS-RSAE-SHA256 and PRF: SHA256 -HSK[0x8006c0]: CERTIFICATE VERIFY was queued [312 bytes] -HWRITE: enqueued [CERTIFICATE VERIFY] 312. Total 1237 bytes. +ASSERT: pkcs11_privkey.c[_gnutls_pkcs11_privkey_sign]:416 +ASSERT: privkey.c[privkey_sign_and_hash_data]:1289 +ASSERT: tls13-sig.c[_gnutls13_handshake_sign_data]:200 +HSK[0x8006c0]: CERTIFICATE VERIFY was queued [8 bytes] +HWRITE: enqueued [CERTIFICATE VERIFY] 8. Total 933 bytes. HSK[0x8006c0]: sending finished HSK[0x8006c0]: FINISHED was queued [36 bytes]
Der... obviously the issue here is that it's using TLSv1.3 and for some reason the key in the two offending tokens isn't working for that signature. That first assert is from a pkcs11_sign() call failing.
Back to testing on plain Fedora 29. With the 'openconnect-test' token (objects imported by softhsm2-util) I see this: checking cert compat with RSA-PSS-SHA256 checking cert compat with RSA-PSS-RSAE-SHA256 HSK[0x1922460]: signing TLS 1.3 handshake data: using RSA-PSS-RSAE-SHA256 and PRF: SHA256 C_SignInit IN: hSession = S3 IN: pMechanism = { mechanism: CKM_RSA_PKCS_PSS pParameter: (24) "P\x02\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00" } IN: hKey = H4 C_SignInit = CKR_OK C_Sign IN: hSession = S3 IN: pData = (32) "(s\x8C\xCC\xCC2.\xF9F\xF7\x1A`:r\xFD+\xBF)U^t\x05\xFB\x91\x10R\xF1u\xD2\x9EK\x13" OUT: pSignature = (304) NOTHING C_Sign = CKR_OK C_Sign IN: hSession = S3 IN: pData = (32) "(s\x8C\xCC\xCC2.\xF9F\xF7\x1A`:r\xFD+\xBF)U^t\x05\xFB\x91\x10R\xF1u\xD2\x9EK\x13" OUT: pSignature = (304) "\x82\xBE1\r\x1A\xAF\x8E\x0C\xD5HM\xF2k\xE0\xBC\x80\x91\xF9\xDBh\xDB\xEC\x1FL\xB6\xD6\xF2\xE6\xEC\xE4\x9BX\xC03\xB1a\xF7..." C_Sign = CKR_OK HSK[0x1922460]: CERTIFICATE VERIFY was queued [312 bytes]
With 'openconnect-test1' token imported with GnuTLS p11tool, I get this: checking cert compat with RSA-PSS-SHA256 checking cert compat with RSA-PSS-RSAE-SHA256 HSK[0x1380ea0]: signing TLS 1.3 handshake data: using RSA-PSS-RSAE-SHA256 and PRF: SHA256 C_SignInit IN: hSession = S3 IN: pMechanism = { mechanism: CKM_RSA_PKCS_PSS pParameter: (24) "P\x02\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00" } IN: hKey = H4 C_SignInit = CKR_OK C_Sign IN: hSession = S3 IN: pData = (32) "y\xE5\xD0\xED\x8E\xA3@\xF8\x05\xC2\xE4|\x97%\x0B\x8B\xC7!\x1Bn\xEC\xE2\x0C\xC7L\xB3\x11\xAD\xEA4l\xB2" OUT: pSignature = (304) NOTHING C_Sign = CKR_OK C_Sign IN: hSession = S3 IN: pData = (32) "y\xE5\xD0\xED\x8E\xA3@\xF8\x05\xC2\xE4|\x97%\x0B\x8B\xC7!\x1Bn\xEC\xE2\x0C\xC7L\xB3\x11\xAD\xEA4l\xB2" C_Sign = CKR_GENERAL_ERROR ASSERT: pkcs11_privkey.c[_gnutls_pkcs11_privkey_sign]:416 ASSERT: privkey.c[privkey_sign_and_hash_data]:1289 ASSERT: tls13-sig.c[_gnutls13_handshake_sign_data]:200 HSK[0x1380ea0]: CERTIFICATE VERIFY was queued [8 bytes]
The failing key is of type "CKA_WRAP/UNWRAP; CKA_SENSITIVE;". That prompts softhsm2 not to do a digital signature as CKA_WRAP/UNWRAP is for decryption/encryption. This means that this key cannot be be used for TLS1.3 RSA-PSS, but only with the TLS1.2 RSA (encryption) ciphersuites. GnuTLS has already a check to see whether the token supports RSA-PSS and if not it disables TLS1.3; it would be nice to extend that check to disable TLS1.3 also if the key flags do not allow for digital signatures. I'm not sure whether that will save this use-case though, because this is using client certificates which are used long after TLS version negotiation.
The client cert is present in the credentials before we establish the TLS session. You ought to be able to take it into account during TLS version negotiation, even though it isn't actually *used* until later. I would obviously prefer this to be handled in GnuTLS, so that we don't have to work around it in all applications which want to do the right thing. Equally obviously, I'll probably work around it in OpenConnect *anyway*, so that OpenConnect works out of the box with as many versions of GnuTLS as possible, even those which don't have their own fix. I suppose the logic should be something along the lines of if (gnutls supports TLSv1.3 AND we have a hardware RSA key) { attempt a PSS signature (on dummy data). if it fails, set GnuTLS priorities to eschew TLSv1.3 } Doing it empirically by attempting the PSS signature means I'd cover TPM keys too. Unless you feel strongly that this should be done based on the PKCS#11 object flags instead?
https://gitlab.com/openconnect/openconnect/merge_requests/23
gnutls-3.6.6-1.fc29 has been submitted as an update to Fedora 29. https://bodhi.fedoraproject.org/updates/FEDORA-2019-5dd203b1e1
gnutls-3.6.6-1.fc29 has been pushed to the Fedora 29 testing repository. If problems still persist, please make note of it in this bug report. See https://fedoraproject.org/wiki/QA:Updates_Testing for instructions on how to install test updates. You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2019-5dd203b1e1
gnutls-3.6.6-1.fc29 has been pushed to the Fedora 29 stable repository. If problems still persist, please make note of it in this bug report.