From ffa6125c74d24e31659390e8bcaf330f941a0cc5 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 12 Feb 2013 23:59:34 +0000 Subject: [PATCH] Use gnutls_pubkey_verify_data2() where possible Unfortunately, gnutls_pubkey_verify_data() is deprecated. Which is a pain; the 'threat model' that led to that deprecation doesn't apply here, and it just means we have to jump through hoops to find the 'intended' algorithm instead of letting it be inferred from the signature. Signed-off-by: David Woodhouse --- configure.ac | 4 +++- gnutls.c | 6 ++++-- gnutls.h | 20 ++++++++++++++++++-- gnutls_tpm.c | 2 +- 4 files changed, 26 insertions(+), 6 deletions(-) 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,