diff --git a/configure.ac b/configure.ac index bf8f6c55..9db65418 100644 --- a/configure.ac +++ b/configure.ac @@ -289,6 +289,8 @@ if test "$with_gnutls" = "yes"; then [AC_DEFINE(HAVE_GNUTLS_PKCS12_SIMPLE_PARSE, 1)], []) AC_CHECK_FUNC(gnutls_certificate_set_key, [AC_DEFINE(HAVE_GNUTLS_CERTIFICATE_SET_KEY, 1)], []) + AC_CHECK_FUNC(gnutls_pubkey_verify_data2, + [AC_DEFINE(HAVE_GNUTLS_PUBKEY_VERIFY_DATA2, 1)], []) if test "$with_openssl" = "" || test "$with_openssl" = "no"; then AC_CHECK_FUNC(gnutls_session_set_premaster, [have_gnutls_dtls=yes], [have_gnutls_dtls=no]) @@ -299,7 +301,7 @@ if test "$with_gnutls" = "yes"; then if test "$with_openssl" = "" || test "$with_openssl" = "no"; then # They either said no OpenSSL or didn't specify, and GnuTLS can # do DTLS, so just use GnuTLS. - AC_DEFINE(HAVE_GNUTLS_SESSION_SET_PREMASTER, 1) + AC_DEFINE(HAVE_GNUTLS_SESSION_SET_PREMASTER, 1) ssl_library=gnutls with_openssl=no else diff --git a/gnutls.c b/gnutls.c index dbc6d125..d787ee23 100644 --- a/gnutls.c +++ b/gnutls.c @@ -1333,6 +1333,8 @@ static int load_certificate(struct openconnect_info *vpninfo) match. So sign some dummy data and then check the signature against each of the available certificates until we find the right one. */ if (pkey) { + gnutls_sign_algorithm_t algo = GNUTLS_SIGN_RSA_SHA1; // TPM + /* The TPM code may have already signed it, to test authorisation. We only sign here for PKCS#11 keys, in which case fdata might be empty too so point it at dummy data. */ @@ -1342,7 +1344,7 @@ static int load_certificate(struct openconnect_info *vpninfo) fdata.size = 20; } - err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig); + err = sign_dummy_data(vpninfo, pkey, &fdata, &pkey_sig, &algo); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Error signing test data with private key: %s\n"), @@ -1366,7 +1368,7 @@ static int load_certificate(struct openconnect_info *vpninfo) gnutls_pubkey_deinit(pubkey); continue; } - err = gnutls_pubkey_verify_data(pubkey, 0, &fdata, &pkey_sig); + err = gnutls_pubkey_verify_data2(pubkey, 0, algo, &fdata, &pkey_sig); gnutls_pubkey_deinit(pubkey); if (err >= 0) { diff --git a/gnutls.h b/gnutls.h index 68d59d2e..5b121aff 100644 --- a/gnutls.h +++ b/gnutls.h @@ -45,6 +45,16 @@ int gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12, const char *password, #endif /* !HAVE_GNUTLS_PKCS12_SIMPLE_PARSE */ +#ifndef HAVE_GNUTLS_PUBKEY_VERIFY_DATA2 +static inline int gnutls_pubkey_verify_data2 (gnutls_pubkey_t pubkey, + gnutls_sign_algorithm_t algo, + unsigned int flags, + const gnutls_datum_t *data, + const gnutls_datum_t *sig) +{ + return gnutls_pubkey_verify_data(pubkey, flags, data, sig); +} +#endif /* !HAVE_GNUTLS_PUBKEY_VERIFY_DATA2 */ #ifndef HAVE_GNUTLS_CERTIFICATE_SET_KEY int gtls2_tpm_sign_cb(gnutls_session_t sess, void *_vpninfo, @@ -64,12 +74,18 @@ int gtls2_tpm_sign_dummy_data(struct openconnect_info *vpninfo, static inline int sign_dummy_data(struct openconnect_info *vpninfo, gnutls_privkey_t pkey, const gnutls_datum_t *data, - gnutls_datum_t *sig) + gnutls_datum_t *sig, + gnutls_sign_algorithm_t *algo) { #if defined (HAVE_TROUSERS) && !defined(HAVE_GNUTLS_CERTIFICATE_SET_KEY) - if (pkey == OPENCONNECT_TPM_PKEY) + if (pkey == OPENCONNECT_TPM_PKEY) { + if (algo) + *algo = GNUTLS_SIGN_RSA_SHA1; return gtls2_tpm_sign_dummy_data(vpninfo, data, sig); + } #endif + if (algo) + *algo = gnutls_pk_to_sign(gnutls_privkey_get_pk_algorithm(pkey, NULL), GNUTLS_DIG_SHA1); return gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA1, 0, data, sig); } diff --git a/gnutls_tpm.c b/gnutls_tpm.c index bc62d769..bf3e7965 100644 --- a/gnutls_tpm.c +++ b/gnutls_tpm.c @@ -274,7 +274,7 @@ int load_tpm_key(struct openconnect_info *vpninfo, gnutls_datum_t *fdata, #endif retry_sign: - err = sign_dummy_data(vpninfo, *pkey, fdata, pkey_sig); + err = sign_dummy_data(vpninfo, *pkey, fdata, pkey_sig, NULL); if (err == GNUTLS_E_INSUFFICIENT_CREDENTIALS) { if (!vpninfo->tpm_key_policy) { err = Tspi_Context_CreateObject(vpninfo->tpm_context,