From 3c2975fd153cf371774e48677147dc8cba19406e Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 11 Mar 2014 15:52:24 +0100 Subject: verify that the algorithm of the received certificate matches the expected. --- lib/algorithms.h | 1 + lib/algorithms/kx.c | 36 ++++++++++++++++++++++-------------- lib/auth/cert.c | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/lib/algorithms.h b/lib/algorithms.h index 394a81fbbd..ae7bbae619 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -257,6 +257,7 @@ inline static int _gnutls_cipher_get_tag_size(const cipher_entry_st * e) /* Functions for key exchange. */ int _gnutls_kx_needs_dh_params(gnutls_kx_algorithm_t algorithm); +int _gnutls_kx_cert_pk_params(gnutls_kx_algorithm_t algorithm); int _gnutls_kx_needs_rsa_params(gnutls_kx_algorithm_t algorithm); mod_auth_st *_gnutls_kx_auth_struct(gnutls_kx_algorithm_t algorithm); int _gnutls_kx_is_ok(gnutls_kx_algorithm_t algorithm); diff --git a/lib/algorithms/kx.c b/lib/algorithms/kx.c index 3fa8a317e0..7302da2967 100644 --- a/lib/algorithms/kx.c +++ b/lib/algorithms/kx.c @@ -87,40 +87,41 @@ struct gnutls_kx_algo_entry { gnutls_kx_algorithm_t algorithm; mod_auth_st *auth_struct; int needs_dh_params; + gnutls_pk_algorithm_t cert_pk; /* the type of certificate required */ }; typedef struct gnutls_kx_algo_entry gnutls_kx_algo_entry; static const gnutls_kx_algo_entry _gnutls_kx_algorithms[] = { #if defined(ENABLE_ANON) && defined(ENABLE_DHE) - {"ANON-DH", GNUTLS_KX_ANON_DH, &anon_auth_struct, 1}, + {"ANON-DH", GNUTLS_KX_ANON_DH, &anon_auth_struct, 1, GNUTLS_PK_UNKNOWN}, #endif #if defined(ENABLE_ANON) && defined(ENABLE_ECDHE) - {"ANON-ECDH", GNUTLS_KX_ANON_ECDH, &anon_ecdh_auth_struct, 0}, + {"ANON-ECDH", GNUTLS_KX_ANON_ECDH, &anon_ecdh_auth_struct, 0, GNUTLS_PK_UNKNOWN}, #endif - {"RSA", GNUTLS_KX_RSA, &rsa_auth_struct}, + {"RSA", GNUTLS_KX_RSA, &rsa_auth_struct, GNUTLS_PK_RSA}, #ifdef ENABLE_DHE - {"DHE-RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct, 1}, - {"DHE-DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1}, + {"DHE-RSA", GNUTLS_KX_DHE_RSA, &dhe_rsa_auth_struct, 1, GNUTLS_PK_RSA}, + {"DHE-DSS", GNUTLS_KX_DHE_DSS, &dhe_dss_auth_struct, 1, GNUTLS_PK_DSA}, #endif #ifdef ENABLE_ECDHE - {"ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, &ecdhe_rsa_auth_struct, 0}, + {"ECDHE-RSA", GNUTLS_KX_ECDHE_RSA, &ecdhe_rsa_auth_struct, 0, GNUTLS_PK_RSA}, {"ECDHE-ECDSA", GNUTLS_KX_ECDHE_ECDSA, &ecdhe_ecdsa_auth_struct, - 0}, + 0, GNUTLS_PK_EC}, #endif #ifdef ENABLE_SRP - {"SRP-DSS", GNUTLS_KX_SRP_DSS, &srp_dss_auth_struct, 0}, - {"SRP-RSA", GNUTLS_KX_SRP_RSA, &srp_rsa_auth_struct, 0}, - {"SRP", GNUTLS_KX_SRP, &srp_auth_struct, 0}, + {"SRP-DSS", GNUTLS_KX_SRP_DSS, &srp_dss_auth_struct, 0, GNUTLS_PK_DSA}, + {"SRP-RSA", GNUTLS_KX_SRP_RSA, &srp_rsa_auth_struct, 0, GNUTLS_PK_RSA}, + {"SRP", GNUTLS_KX_SRP, &srp_auth_struct, 0, GNUTLS_PK_UNKNOWN}, #endif #ifdef ENABLE_PSK - {"PSK", GNUTLS_KX_PSK, &psk_auth_struct, 0}, - {"RSA-PSK", GNUTLS_KX_RSA_PSK, &rsa_psk_auth_struct, 0}, + {"PSK", GNUTLS_KX_PSK, &psk_auth_struct, 0, GNUTLS_PK_UNKNOWN}, + {"RSA-PSK", GNUTLS_KX_RSA_PSK, &rsa_psk_auth_struct, 0, GNUTLS_PK_RSA}, #ifdef ENABLE_DHE {"DHE-PSK", GNUTLS_KX_DHE_PSK, &dhe_psk_auth_struct, - 1 /* needs DHE params */ }, + 1 /* needs DHE params */, GNUTLS_PK_UNKNOWN}, #endif #ifdef ENABLE_ECDHE - {"ECDHE-PSK", GNUTLS_KX_ECDHE_PSK, &ecdhe_psk_auth_struct, 0}, + {"ECDHE-PSK", GNUTLS_KX_ECDHE_PSK, &ecdhe_psk_auth_struct, 0, GNUTLS_PK_UNKNOWN}, #endif #endif {0, 0, 0, 0} @@ -241,6 +242,13 @@ int _gnutls_kx_needs_dh_params(gnutls_kx_algorithm_t algorithm) return ret; } +int _gnutls_kx_cert_pk_params(gnutls_kx_algorithm_t algorithm) +{ + ssize_t ret = 0; + GNUTLS_KX_ALG_LOOP(ret = p->cert_pk); + return ret; +} + /* Type to KX mappings */ gnutls_kx_algorithm_t _gnutls_map_kx_get_kx(gnutls_credentials_type_t type, int server) diff --git a/lib/auth/cert.c b/lib/auth/cert.c index 6e86091b71..4490a075cd 100644 --- a/lib/auth/cert.c +++ b/lib/auth/cert.c @@ -1024,9 +1024,36 @@ _gnutls_gen_cert_server_crt(gnutls_session_t session, } } +static +int check_pk_compat(gnutls_session_t session, gnutls_pubkey_t pubkey) +{ + unsigned cert_pk; + unsigned req_cert_pk; + unsigned kx; + + cert_pk = gnutls_pubkey_get_pk_algorithm(pubkey, NULL); + if (cert_pk == GNUTLS_PK_UNKNOWN) { + gnutls_assert(); + return GNUTLS_E_CERTIFICATE_ERROR; + } + + kx = _gnutls_cipher_suite_get_kx_algo(session->security_parameters.cipher_suite); + + req_cert_pk = _gnutls_kx_cert_pk_params(kx); + + if (req_cert_pk == GNUTLS_PK_UNKNOWN) /* doesn't matter */ + return 0; + + if (req_cert_pk != cert_pk) { + gnutls_assert(); + return GNUTLS_E_CERTIFICATE_ERROR; + } + + return 0; +} + /* Process server certificate */ - #define CLEAR_CERTS for(x=0;x