summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Josefsson <simon@josefsson.org>2006-11-25 16:58:19 +0000
committerSimon Josefsson <simon@josefsson.org>2006-11-25 16:58:19 +0000
commit40059580e10f23cc15d79c37dc6ae59c4626fb4b (patch)
tree91add47c9d98dae7c128a8fbbfbcd272f702060a
parentefa17cda8b7baa17ad7326a1b6157b1e4e6f6b85 (diff)
downloadgnutls-40059580e10f23cc15d79c37dc6ae59c4626fb4b.tar.gz
Client TLS 1.2 support. Works against www.mikestoolbox.org:4433.
-rw-r--r--lib/auth_cert.c14
-rw-r--r--lib/gnutls_constate.c29
-rw-r--r--lib/gnutls_handshake.c34
-rw-r--r--lib/gnutls_kx.c4
-rw-r--r--lib/gnutls_sig.c43
-rw-r--r--lib/gnutls_state.c74
-rw-r--r--lib/gnutls_state.h8
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