summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2014-03-11 15:52:24 +0100
committerNikos Mavrogiannopoulos <nmav@redhat.com>2014-03-11 15:52:24 +0100
commit3c2975fd153cf371774e48677147dc8cba19406e (patch)
treea77e58a7f27cbf27d5365ff9c3c3abef1792ae0d
parentc5735514045a5875bc3f37c35cdd350db4879440 (diff)
downloadgnutls-3c2975fd153cf371774e48677147dc8cba19406e.tar.gz
verify that the algorithm of the received certificate matches the expected.
-rw-r--r--lib/algorithms.h1
-rw-r--r--lib/algorithms/kx.c36
-rw-r--r--lib/auth/cert.c34
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<peer_certificate_list_size;x++) gnutls_pcert_deinit(&peer_certificate_list[x])
static int
_gnutls_proc_x509_server_crt(gnutls_session_t session,
@@ -1134,6 +1161,11 @@ _gnutls_proc_x509_server_crt(gnutls_session_t session,
p += len;
}
+ ret = check_pk_compat(session, peer_certificate_list[0].pubkey);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
if ((ret =
_gnutls_copy_certificate_auth_info(info,