summaryrefslogtreecommitdiff
path: root/src/tls/tlsv1_server_write.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls/tlsv1_server_write.c')
-rw-r--r--src/tls/tlsv1_server_write.c125
1 files changed, 68 insertions, 57 deletions
diff --git a/src/tls/tlsv1_server_write.c b/src/tls/tlsv1_server_write.c
index 6d1df7ff34f4d..6d8e55ed49a09 100644
--- a/src/tls/tlsv1_server_write.c
+++ b/src/tls/tlsv1_server_write.c
@@ -1,15 +1,9 @@
/*
* TLSv1 server - write handshake message
- * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
@@ -17,7 +11,9 @@
#include "common.h"
#include "crypto/md5.h"
#include "crypto/sha1.h"
+#include "crypto/sha256.h"
#include "crypto/tls.h"
+#include "crypto/random.h"
#include "x509v3.h"
#include "tlsv1_common.h"
#include "tlsv1_record.h"
@@ -58,7 +54,7 @@ static int tls_write_server_hello(struct tlsv1_server *conn,
os_get_time(&now);
WPA_PUT_BE32(conn->server_random, now.sec);
- if (os_get_random(conn->server_random + 4, TLS_RANDOM_LEN - 4)) {
+ if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) {
wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
"server_random");
return -1;
@@ -67,7 +63,7 @@ static int tls_write_server_hello(struct tlsv1_server *conn,
conn->server_random, TLS_RANDOM_LEN);
conn->session_id_len = TLS_SESSION_ID_MAX_LEN;
- if (os_get_random(conn->session_id, conn->session_id_len)) {
+ if (random_get_bytes(conn->session_id, conn->session_id_len)) {
wpa_printf(MSG_ERROR, "TLSv1: Could not generate "
"session_id");
return -1;
@@ -86,7 +82,7 @@ static int tls_write_server_hello(struct tlsv1_server *conn,
pos += 3;
/* body - ServerHello */
/* ProtocolVersion server_version */
- WPA_PUT_BE16(pos, TLS_VERSION);
+ WPA_PUT_BE16(pos, conn->rl.tls_version);
pos += 2;
/* Random random: uint32 gmt_unix_time, opaque random_bytes */
os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN);
@@ -142,7 +138,8 @@ static int tls_write_server_hello(struct tlsv1_server *conn,
tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
- rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
+ rhdr, end - rhdr, hs_start, pos - hs_start,
+ &rlen) < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
@@ -226,7 +223,8 @@ static int tls_write_server_certificate(struct tlsv1_server *conn,
WPA_PUT_BE24(hs_length, pos - hs_length - 3);
if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
- rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
+ rhdr, end - rhdr, hs_start, pos - hs_start,
+ &rlen) < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
@@ -287,7 +285,7 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
TLS_ALERT_INTERNAL_ERROR);
return -1;
}
- if (os_get_random(conn->dh_secret, conn->dh_secret_len)) {
+ if (random_get_bytes(conn->dh_secret, conn->dh_secret_len)) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random "
"data for Diffie-Hellman");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
@@ -417,7 +415,8 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
WPA_PUT_BE24(hs_length, pos - hs_length - 3);
if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
- rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
+ rhdr, end - rhdr, hs_start, pos - hs_start,
+ &rlen) < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
@@ -482,7 +481,8 @@ static int tls_write_server_certificate_request(struct tlsv1_server *conn,
WPA_PUT_BE24(hs_length, pos - hs_length - 3);
if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
- rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
+ rhdr, end - rhdr, hs_start, pos - hs_start,
+ &rlen) < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
@@ -501,40 +501,35 @@ static int tls_write_server_certificate_request(struct tlsv1_server *conn,
static int tls_write_server_hello_done(struct tlsv1_server *conn,
u8 **msgpos, u8 *end)
{
- u8 *pos, *rhdr, *hs_start, *hs_length;
+ u8 *pos;
size_t rlen;
-
- pos = *msgpos;
+ u8 payload[4];
wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone");
- rhdr = pos;
- pos += TLS_RECORD_HEADER_LEN;
/* opaque fragment[TLSPlaintext.length] */
/* Handshake */
- hs_start = pos;
+ pos = payload;
/* HandshakeType msg_type */
*pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE;
- /* uint24 length (to be filled) */
- hs_length = pos;
+ /* uint24 length */
+ WPA_PUT_BE24(pos, 0);
pos += 3;
/* body - ServerHelloDone (empty) */
- WPA_PUT_BE24(hs_length, pos - hs_length - 3);
-
if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
- rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
+ *msgpos, end - *msgpos, payload, pos - payload,
+ &rlen) < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
return -1;
}
- pos = rhdr + rlen;
- tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
+ tls_verify_hash_add(&conn->verify, payload, pos - payload);
- *msgpos = pos;
+ *msgpos += rlen;
return 0;
}
@@ -543,17 +538,16 @@ static int tls_write_server_hello_done(struct tlsv1_server *conn,
static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn,
u8 **msgpos, u8 *end)
{
- u8 *pos, *rhdr;
size_t rlen;
-
- pos = *msgpos;
+ u8 payload[1];
wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec");
- rhdr = pos;
- pos += TLS_RECORD_HEADER_LEN;
- *pos = TLS_CHANGE_CIPHER_SPEC;
+
+ payload[0] = TLS_CHANGE_CIPHER_SPEC;
+
if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC,
- rhdr, end - rhdr, 1, &rlen) < 0) {
+ *msgpos, end - *msgpos, payload, sizeof(payload),
+ &rlen) < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
@@ -568,7 +562,7 @@ static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn,
return -1;
}
- *msgpos = rhdr + rlen;
+ *msgpos += rlen;
return 0;
}
@@ -577,9 +571,9 @@ static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn,
static int tls_write_server_finished(struct tlsv1_server *conn,
u8 **msgpos, u8 *end)
{
- u8 *pos, *rhdr, *hs_start, *hs_length;
+ u8 *pos, *hs_start;
size_t rlen, hlen;
- u8 verify_data[TLS_VERIFY_DATA_LEN];
+ u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN];
u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN];
pos = *msgpos;
@@ -588,6 +582,21 @@ static int tls_write_server_finished(struct tlsv1_server *conn,
/* Encrypted Handshake Message: Finished */
+#ifdef CONFIG_TLSV12
+ if (conn->rl.tls_version >= TLS_VERSION_1_2) {
+ hlen = SHA256_MAC_LEN;
+ if (conn->verify.sha256_server == NULL ||
+ crypto_hash_finish(conn->verify.sha256_server, hash, &hlen)
+ < 0) {
+ conn->verify.sha256_server = NULL;
+ tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
+ TLS_ALERT_INTERNAL_ERROR);
+ return -1;
+ }
+ conn->verify.sha256_server = NULL;
+ } else {
+#endif /* CONFIG_TLSV12 */
+
hlen = MD5_MAC_LEN;
if (conn->verify.md5_server == NULL ||
crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) {
@@ -609,43 +618,44 @@ static int tls_write_server_finished(struct tlsv1_server *conn,
return -1;
}
conn->verify.sha1_server = NULL;
+ hlen = MD5_MAC_LEN + SHA1_MAC_LEN;
+
+#ifdef CONFIG_TLSV12
+ }
+#endif /* CONFIG_TLSV12 */
- if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN,
- "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN,
- verify_data, TLS_VERIFY_DATA_LEN)) {
+ if (tls_prf(conn->rl.tls_version,
+ conn->master_secret, TLS_MASTER_SECRET_LEN,
+ "server finished", hash, hlen,
+ verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
return -1;
}
wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)",
- verify_data, TLS_VERIFY_DATA_LEN);
+ verify_data + 1 + 3, TLS_VERIFY_DATA_LEN);
- rhdr = pos;
- pos += TLS_RECORD_HEADER_LEN;
/* Handshake */
- hs_start = pos;
+ pos = hs_start = verify_data;
/* HandshakeType msg_type */
*pos++ = TLS_HANDSHAKE_TYPE_FINISHED;
- /* uint24 length (to be filled) */
- hs_length = pos;
+ /* uint24 length */
+ WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN);
pos += 3;
- os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN);
pos += TLS_VERIFY_DATA_LEN;
- WPA_PUT_BE24(hs_length, pos - hs_length - 3);
tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start);
if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE,
- rhdr, end - rhdr, pos - hs_start, &rlen) < 0) {
+ *msgpos, end - *msgpos, hs_start, pos - hs_start,
+ &rlen) < 0) {
wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
TLS_ALERT_INTERNAL_ERROR);
return -1;
}
- pos = rhdr + rlen;
-
- *msgpos = pos;
+ *msgpos += rlen;
return 0;
}
@@ -770,7 +780,8 @@ u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level,
/* ContentType type */
*pos++ = TLS_CONTENT_TYPE_ALERT;
/* ProtocolVersion version */
- WPA_PUT_BE16(pos, TLS_VERSION);
+ WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version :
+ TLS_VERSION);
pos += 2;
/* uint16 length (to be filled) */
length = pos;