From 40059580e10f23cc15d79c37dc6ae59c4626fb4b Mon Sep 17 00:00:00 2001 From: Simon Josefsson Date: Sat, 25 Nov 2006 16:58:19 +0000 Subject: Client TLS 1.2 support. Works against www.mikestoolbox.org:4433. --- lib/auth_cert.c | 14 ++++++++++ lib/gnutls_constate.c | 29 +++++++++----------- lib/gnutls_handshake.c | 34 +++++++++++++++-------- lib/gnutls_kx.c | 4 +-- lib/gnutls_sig.c | 43 +++++++++++++++++++---------- lib/gnutls_state.c | 74 +++++++++++++++++++++++++++++++------------------- lib/gnutls_state.h | 8 ++++-- 7 files changed, 132 insertions(+), 74 deletions(-) diff --git a/lib/auth_cert.c b/lib/auth_cert.c index e63ece39cd..b7f1f596c6 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -1203,6 +1203,7 @@ _gnutls_proc_cert_cert_req (gnutls_session_t session, opaque * data, int i, j; gnutls_pk_algorithm_t pk_algos[MAX_SIGN_ALGOS]; int pk_algos_length; + gnutls_protocol_t ver = gnutls_protocol_get_version (session); cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); @@ -1250,6 +1251,19 @@ _gnutls_proc_cert_cert_req (gnutls_session_t session, opaque * data, return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } + if (ver == GNUTLS_TLS1_2) + { + /* read supported hashes */ + int hash_num; + DECR_LEN (dsize, 1); + + hash_num = p[0] & 0xFF; + p++; + + DECR_LEN (dsize, hash_num); + p+=hash_num; + } + /* read the certificate authorities */ DECR_LEN (dsize, 2); size = _gnutls_read_uint16 (p); diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c index af981af223..e5e70478cb 100644 --- a/lib/gnutls_constate.c +++ b/lib/gnutls_constate.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation + * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation * * Author: Nikos Mavroyanopoulos * @@ -109,7 +109,7 @@ _gnutls_set_keys (gnutls_session_t session, int hash_size, int IV_size, else { /* TLS 1.0 */ ret = - _gnutls_PRF (session->security_parameters.master_secret, + _gnutls_PRF (session, session->security_parameters.master_secret, TLS_MASTER_SIZE, keyexp, keyexp_length, rnd, 2 * TLS_RANDOM_SIZE, block_size, key_block); } @@ -202,7 +202,7 @@ _gnutls_set_keys (gnutls_session_t session, int hash_size, int IV_size, else { /* TLS 1.0 */ ret = - _gnutls_PRF (&key_block[pos], key_size, + _gnutls_PRF (session, &key_block[pos], key_size, cliwrite, cliwrite_length, rrnd, 2 * TLS_RANDOM_SIZE, @@ -232,7 +232,7 @@ _gnutls_set_keys (gnutls_session_t session, int hash_size, int IV_size, else { /* TLS 1.0 */ ret = - _gnutls_PRF (&key_block[pos], key_size, + _gnutls_PRF (session, &key_block[pos], key_size, servwrite, servwrite_length, rrnd, 2 * TLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, server_write_key); @@ -325,10 +325,9 @@ _gnutls_set_keys (gnutls_session_t session, int hash_size, int IV_size, if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ - ret = - _gnutls_ssl3_hash_md5 ("", 0, - rrnd, TLS_RANDOM_SIZE * 2, - IV_size, iv_block); + ret = _gnutls_ssl3_hash_md5 ("", 0, + rrnd, TLS_RANDOM_SIZE * 2, + IV_size, iv_block); if (ret < 0) { @@ -338,18 +337,16 @@ _gnutls_set_keys (gnutls_session_t session, int hash_size, int IV_size, return ret; } - ret = - _gnutls_ssl3_hash_md5 ("", 0, rnd, - TLS_RANDOM_SIZE * 2, - IV_size, &iv_block[IV_size]); + ret = _gnutls_ssl3_hash_md5 ("", 0, rnd, + TLS_RANDOM_SIZE * 2, + IV_size, &iv_block[IV_size]); } else { /* TLS 1.0 */ - ret = - _gnutls_PRF ("", 0, - ivblock, ivblock_length, rrnd, - 2 * TLS_RANDOM_SIZE, IV_size * 2, iv_block); + ret = _gnutls_PRF (session, "", 0, + ivblock, ivblock_length, rrnd, + 2 * TLS_RANDOM_SIZE, IV_size * 2, iv_block); } if (ret < 0) diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 66cec0a9bb..5c318f5a15 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation + * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation * * Author: Nikos Mavroyanopoulos * @@ -196,16 +196,20 @@ _gnutls_finished (gnutls_session_t session, int type, void *ret) { const int siz = TLS_MSG_LEN; opaque concat[36]; + size_t len; const char *mesg; mac_hd_t td_md5; mac_hd_t td_sha; + gnutls_protocol_t ver = gnutls_protocol_get_version (session); - - td_md5 = _gnutls_hash_copy (session->internals.handshake_mac_handle_md5); - if (td_md5 == NULL) + if (ver < GNUTLS_TLS1_2) { - gnutls_assert (); - return GNUTLS_E_HASH_FAILED; + td_md5 = _gnutls_hash_copy (session->internals.handshake_mac_handle_md5); + if (td_md5 == NULL) + { + gnutls_assert (); + return GNUTLS_E_HASH_FAILED; + } } td_sha = _gnutls_hash_copy (session->internals.handshake_mac_handle_sha); @@ -216,9 +220,17 @@ _gnutls_finished (gnutls_session_t session, int type, void *ret) return GNUTLS_E_HASH_FAILED; } - - _gnutls_hash_deinit (td_md5, concat); - _gnutls_hash_deinit (td_sha, &concat[16]); + if (ver < GNUTLS_TLS1_2) + { + _gnutls_hash_deinit (td_md5, concat); + _gnutls_hash_deinit (td_sha, &concat[16]); + len = 20 + 16; + } + else + { + _gnutls_hash_deinit (td_sha, concat); + len = 20; + } if (type == GNUTLS_SERVER) { @@ -229,8 +241,8 @@ _gnutls_finished (gnutls_session_t session, int type, void *ret) mesg = CLIENT_MSG; } - return _gnutls_PRF (session->security_parameters.master_secret, - TLS_MASTER_SIZE, mesg, siz, concat, 36, 12, ret); + return _gnutls_PRF (session, session->security_parameters.master_secret, + TLS_MASTER_SIZE, mesg, siz, concat, len, 12, ret); } /* this function will produce TLS_RANDOM_SIZE==32 bytes of random data diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index f2d1d4b939..edd1fb696a 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2004, 2005 Free Software Foundation + * Copyright (C) 2000, 2001, 2004, 2005, 2006 Free Software Foundation * * Author: Nikos Mavroyanopoulos * @@ -89,7 +89,7 @@ generate_normal_master (gnutls_session_t session, int keep_premaster) else { ret = - _gnutls_PRF (PREMASTER.data, PREMASTER.size, + _gnutls_PRF (session, PREMASTER.data, PREMASTER.size, MASTER_SECRET, strlen (MASTER_SECRET), rnd, 2 * TLS_RANDOM_SIZE, TLS_MASTER_SIZE, session->security_parameters.master_secret); diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index 67a4928531..92c63d1d3f 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001, 2004, 2005 Free Software Foundation + * Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation * * Author: Nikos Mavroyanopoulos * @@ -404,12 +404,22 @@ _gnutls_verify_sig_params (gnutls_session_t session, gnutls_cert * cert, mac_hd_t td_md5; mac_hd_t td_sha; opaque concat[36]; + gnutls_protocol_t ver = gnutls_protocol_get_version (session); - td_md5 = _gnutls_hash_init (GNUTLS_MAC_MD5); - if (td_md5 == NULL) + if (ver < GNUTLS_TLS1_2) { - gnutls_assert (); - return GNUTLS_E_HASH_FAILED; + td_md5 = _gnutls_hash_init (GNUTLS_MAC_MD5); + if (td_md5 == NULL) + { + gnutls_assert (); + return GNUTLS_E_HASH_FAILED; + } + + _gnutls_hash (td_md5, session->security_parameters.client_random, + TLS_RANDOM_SIZE); + _gnutls_hash (td_md5, session->security_parameters.server_random, + TLS_RANDOM_SIZE); + _gnutls_hash (td_md5, params->data, params->size); } td_sha = _gnutls_hash_init (GNUTLS_MAC_SHA1); @@ -420,23 +430,28 @@ _gnutls_verify_sig_params (gnutls_session_t session, gnutls_cert * cert, return GNUTLS_E_HASH_FAILED; } - _gnutls_hash (td_md5, session->security_parameters.client_random, - TLS_RANDOM_SIZE); - _gnutls_hash (td_md5, session->security_parameters.server_random, - TLS_RANDOM_SIZE); - _gnutls_hash (td_md5, params->data, params->size); - _gnutls_hash (td_sha, session->security_parameters.client_random, TLS_RANDOM_SIZE); _gnutls_hash (td_sha, session->security_parameters.server_random, TLS_RANDOM_SIZE); _gnutls_hash (td_sha, params->data, params->size); - _gnutls_hash_deinit (td_md5, concat); - _gnutls_hash_deinit (td_sha, &concat[16]); + if (ver < GNUTLS_TLS1_2) + { + _gnutls_hash_deinit (td_md5, concat); + _gnutls_hash_deinit (td_sha, &concat[16]); + dconcat.size = 36; + } + else + { + memcpy (concat, + "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14", + 15); + _gnutls_hash_deinit (td_sha, &concat[15]); + dconcat.size = 35; + } dconcat.data = concat; - dconcat.size = 36; ret = _gnutls_pkcs1_rsa_verify_sig (cert, &dconcat, signature); if (ret < 0) diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 907421bf73..4e78e3b415 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -836,7 +836,8 @@ _gnutls_xor (opaque * o1, opaque * o2, int length) * available. */ int -_gnutls_PRF (const opaque * secret, int secret_size, const char *label, +_gnutls_PRF (gnutls_session_t session, + const opaque * secret, int secret_size, const char *label, int label_size, const opaque * seed, int seed_size, int total_bytes, void *ret) { @@ -845,6 +846,7 @@ _gnutls_PRF (const opaque * secret, int secret_size, const char *label, opaque s_seed[MAX_SEED_SIZE]; opaque o1[MAX_PRF_BYTES], o2[MAX_PRF_BYTES]; int result; + gnutls_protocol_t ver = gnutls_protocol_get_version (session); if (total_bytes > MAX_PRF_BYTES) { @@ -863,37 +865,52 @@ _gnutls_PRF (const opaque * secret, int secret_size, const char *label, memcpy (s_seed, label, label_size); memcpy (&s_seed[label_size], seed, seed_size); - l_s = secret_size / 2; - - s1 = &secret[0]; - s2 = &secret[l_s]; - - if (secret_size % 2 != 0) + if (ver >= GNUTLS_TLS1_2) { - l_s++; + result = + _gnutls_P_hash (GNUTLS_MAC_SHA1, secret, secret_size, + s_seed, s_seed_size, + total_bytes, ret); + if (result < 0) + { + gnutls_assert (); + return result; + } } - - result = - _gnutls_P_hash (GNUTLS_MAC_MD5, s1, l_s, s_seed, s_seed_size, - total_bytes, o1); - if (result < 0) + else { - gnutls_assert (); - return result; - } + l_s = secret_size / 2; - result = - _gnutls_P_hash (GNUTLS_MAC_SHA1, s2, l_s, s_seed, s_seed_size, - total_bytes, o2); - if (result < 0) - { - gnutls_assert (); - return result; - } + s1 = &secret[0]; + s2 = &secret[l_s]; - _gnutls_xor (o1, o2, total_bytes); + if (secret_size % 2 != 0) + { + l_s++; + } - memcpy (ret, o1, total_bytes); + result = + _gnutls_P_hash (GNUTLS_MAC_MD5, s1, l_s, s_seed, s_seed_size, + total_bytes, o1); + if (result < 0) + { + gnutls_assert (); + return result; + } + + result = + _gnutls_P_hash (GNUTLS_MAC_SHA1, s2, l_s, s_seed, s_seed_size, + total_bytes, o2); + if (result < 0) + { + gnutls_assert (); + return result; + } + + _gnutls_xor (o1, o2, total_bytes); + + memcpy (ret, o1, total_bytes); + } return 0; /* ok */ @@ -936,7 +953,8 @@ gnutls_prf_raw (gnutls_session_t session, { int ret; - ret = _gnutls_PRF (session->security_parameters.master_secret, + ret = _gnutls_PRF (session, + session->security_parameters.master_secret, TLS_MASTER_SIZE, label, label_size, (opaque *) seed, seed_size, outsize, out); @@ -1000,7 +1018,7 @@ gnutls_prf (gnutls_session_t session, memcpy (seed + 2 * TLS_RANDOM_SIZE, extra, extra_size); - ret = _gnutls_PRF (session->security_parameters.master_secret, + ret = _gnutls_PRF (session, session->security_parameters.master_secret, TLS_MASTER_SIZE, label, label_size, seed, seedsize, outsize, out); diff --git a/lib/gnutls_state.h b/lib/gnutls_state.h index b220024b59..0bd9698bd7 100644 --- a/lib/gnutls_state.h +++ b/lib/gnutls_state.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation + * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation * * Author: Nikos Mavroyanopoulos * @@ -61,8 +61,10 @@ int _gnutls_session_is_export (gnutls_session_t session); int _gnutls_openpgp_send_fingerprint (gnutls_session_t session); -int _gnutls_PRF (const opaque * secret, int secret_size, const char *label, - int label_size, const opaque * seed, int seed_size, +int _gnutls_PRF (gnutls_session_t session, + const opaque * secret, int secret_size, + const char *label, int label_size, + const opaque * seed, int seed_size, int total_bytes, void *ret); #define DEFAULT_CERT_TYPE GNUTLS_CRT_X509 -- cgit v1.2.1