18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TLSv1 server - write handshake message 31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/md5.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha1.h" 141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "crypto/sha256.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_common.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_record.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_server_i.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn) 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len = 0; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = conn->cred->cert; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (cert) { 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len += 3 + cert->cert_len; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_certificate_self_signed(cert)) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = x509_certificate_get_subject(conn->cred->trusted_certs, 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->issuer); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return len; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_hello(struct tlsv1_server *conn, 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 **msgpos, u8 *end) 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, *rhdr, *hs_start, *hs_length; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = *msgpos; 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello"); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr = pos; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += TLS_RECORD_HEADER_LEN; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE32(conn->server_random, now.sec); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) { 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TLSv1: Could not generate " 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "server_random"); 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->server_random, TLS_RANDOM_LEN); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_id_len = TLS_SESSION_ID_MAX_LEN; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(conn->session_id, conn->session_id_len)) { 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TLSv1: Could not generate " 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "session_id"); 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_id, conn->session_id_len); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* opaque fragment[TLSPlaintext.length] */ 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Handshake */ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hs_start = pos; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HandshakeType msg_type */ 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* uint24 length (to be filled) */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hs_length = pos; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* body - ServerHello */ 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ProtocolVersion server_version */ 851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_BE16(pos, conn->rl.tls_version); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Random random: uint32 gmt_unix_time, opaque random_bytes */ 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += TLS_RANDOM_LEN; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SessionID session_id */ 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = conn->session_id_len; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, conn->session_id, conn->session_id_len); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += conn->session_id_len; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* CipherSuite cipher_suite */ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, conn->cipher_suite); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* CompressionMethod compression_method */ 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = TLS_COMPRESSION_NULL; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->session_ticket && conn->session_ticket_cb) { 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res = conn->session_ticket_cb( 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_ticket_cb_ctx, 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_ticket, conn->session_ticket_len, 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->client_random, conn->server_random, 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->master_secret); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) { 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "indicated failure"); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_HANDSHAKE_FAILURE); 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->use_session_ticket = res; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->use_session_ticket) { 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) { 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to " 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "derive keys"); 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 4507 specifies that server would include an empty 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SessionTicket extension in ServerHello and a 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * NewSessionTicket message after the ServerHello. However, 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extension at the moment, does not use such extensions. 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: Add support for configuring RFC 4507 behavior and make 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP-FAST disable it. 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE24(hs_length, pos - hs_length - 3); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt rhdr, end - rhdr, hs_start, pos - hs_start, 1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &rlen) < 0) { 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rhdr + rlen; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *msgpos = pos; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_certificate(struct tlsv1_server *conn, 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 **msgpos, u8 *end) 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct tls_cipher_suite *suite; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suite = tls_get_cipher_suite(conn->rl.cipher_suite); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when " 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "using anonymous DH"); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = *msgpos; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr = pos; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += TLS_RECORD_HEADER_LEN; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* opaque fragment[TLSPlaintext.length] */ 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Handshake */ 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hs_start = pos; 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HandshakeType msg_type */ 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* uint24 length (to be filled) */ 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hs_length = pos; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* body - Certificate */ 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* uint24 length (to be filled) */ 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert_start = pos; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = conn->cred->cert; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (cert) { 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 3 + cert->cert_len > end) { 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for Certificate (cert_len=%lu left=%lu)", 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) cert->cert_len, 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) (end - pos)); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE24(pos, cert->cert_len); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, cert->cert_start, cert->cert_len); 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += cert->cert_len; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_certificate_self_signed(cert)) 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = x509_certificate_get_subject(conn->cred->trusted_certs, 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->issuer); 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert == conn->cred->cert || cert == NULL) { 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Server was not configured with all the needed certificates 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to form a full certificate chain. The client may fail to 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * validate the chain unless it is configured with all the 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * missing CA certificates. 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain " 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not configured - validation may fail"); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE24(cert_start, pos - cert_start - 3); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE24(hs_length, pos - hs_length - 3); 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt rhdr, end - rhdr, hs_start, pos - hs_start, 2271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &rlen) < 0) { 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rhdr + rlen; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *msgpos = pos; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_key_exchange(struct tlsv1_server *conn, 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 **msgpos, u8 *end) 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_key_exchange keyx; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct tls_cipher_suite *suite; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, *rhdr, *hs_start, *hs_length; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *dh_ys; 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t dh_ys_len; 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suite = tls_get_cipher_suite(conn->rl.cipher_suite); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (suite == NULL) 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyx = TLS_KEY_X_NULL; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keyx = suite->key_exchange; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (keyx != TLS_KEY_X_DH_anon) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO? */ 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "supported with key exchange type %d", keyx); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->cred == NULL || conn->cred->dh_p == NULL || 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->cred->dh_g == NULL) { 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ServerKeyExhcange"); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->dh_secret); 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_secret_len = conn->cred->dh_p_len; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_secret = os_malloc(conn->dh_secret_len); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->dh_secret == NULL) { 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "memory for secret (Diffie-Hellman)"); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(conn->dh_secret, conn->dh_secret_len)) { 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "data for Diffie-Hellman"); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->dh_secret); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_secret = NULL; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) > 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0) 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_secret[0] = 0; /* make sure secret < p */ 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = conn->dh_secret; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos++; 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos != conn->dh_secret) { 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memmove(conn->dh_secret, pos, 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_secret_len - (pos - conn->dh_secret)); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_secret_len -= pos - conn->dh_secret; 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_secret, conn->dh_secret_len); 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Ys = g^secret mod p */ 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_ys_len = conn->cred->dh_p_len; 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_ys = os_malloc(dh_ys_len); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (dh_ys == NULL) { 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Diffie-Hellman"); 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_secret, conn->dh_secret_len, 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->cred->dh_p, conn->cred->dh_p_len, 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_ys, &dh_ys_len)) { 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dh_ys); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dh_ys, dh_ys_len); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct { 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * select (KeyExchangeAlgorithm) { 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * case diffie_hellman: 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ServerDHParams params; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Signature signed_params; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * case rsa: 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ServerRSAParams params; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Signature signed_params; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * }; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } ServerKeyExchange; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * struct { 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * opaque dh_p<1..2^16-1>; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * opaque dh_g<1..2^16-1>; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * opaque dh_Ys<1..2^16-1>; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } ServerDHParams; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = *msgpos; 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange"); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr = pos; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += TLS_RECORD_HEADER_LEN; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* opaque fragment[TLSPlaintext.length] */ 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Handshake */ 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hs_start = pos; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HandshakeType msg_type */ 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* uint24 length (to be filled) */ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hs_length = pos; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* body - ServerDHParams */ 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dh_p */ 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + conn->cred->dh_p_len > end) { 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dh_p"); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dh_ys); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, conn->cred->dh_p_len); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += conn->cred->dh_p_len; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dh_g */ 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + conn->cred->dh_g_len > end) { 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dh_g"); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dh_ys); 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, conn->cred->dh_g_len); 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += conn->cred->dh_g_len; 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dh_Ys */ 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + 2 + dh_ys_len > end) { 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dh_Ys"); 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dh_ys); 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, dh_ys_len); 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, dh_ys, dh_ys_len); 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += dh_ys_len; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(dh_ys); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE24(hs_length, pos - hs_length - 3); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 4181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt rhdr, end - rhdr, hs_start, pos - hs_start, 4191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &rlen) < 0) { 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rhdr + rlen; 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *msgpos = pos; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_certificate_request(struct tlsv1_server *conn, 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 **msgpos, u8 *end) 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos, *rhdr, *hs_start, *hs_length; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!conn->verify_peer) { 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed"); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = *msgpos; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest"); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rhdr = pos; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += TLS_RECORD_HEADER_LEN; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* opaque fragment[TLSPlaintext.length] */ 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Handshake */ 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hs_start = pos; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HandshakeType msg_type */ 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* uint24 length (to be filled) */ 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hs_length = pos; 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* body - CertificateRequest */ 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * enum { 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (255) 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } ClientCertificateType; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ClientCertificateType certificate_types<1..2^8-1> 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 1; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 1; /* rsa_sign */ 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * opaque DistinguishedName<1..2^16-1> 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * DistinguishedName certificate_authorities<3..2^16-1> 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for listing DNs for trusted CAs */ 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, 0); 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE24(hs_length, pos - hs_length - 3); 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 4841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt rhdr, end - rhdr, hs_start, pos - hs_start, 4851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &rlen) < 0) { 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rhdr + rlen; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *msgpos = pos; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_hello_done(struct tlsv1_server *conn, 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 **msgpos, u8 *end) 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 5061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 payload[4]; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone"); 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* opaque fragment[TLSPlaintext.length] */ 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Handshake */ 5131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = payload; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HandshakeType msg_type */ 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE; 5161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* uint24 length */ 5171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_BE24(pos, 0); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* body - ServerHelloDone (empty) */ 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 5221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *msgpos, end - *msgpos, payload, pos - payload, 5231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &rlen) < 0) { 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tls_verify_hash_add(&conn->verify, payload, pos - payload); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *msgpos += rlen; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_change_cipher_spec(struct tlsv1_server *conn, 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 **msgpos, u8 *end) 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 5421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 payload[1]; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); 5451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt payload[0] = TLS_CHANGE_CIPHER_SPEC; 5471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, 5491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *msgpos, end - *msgpos, payload, sizeof(payload), 5501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &rlen) < 0) { 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "record layer"); 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *msgpos += rlen; 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int tls_write_server_finished(struct tlsv1_server *conn, 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 **msgpos, u8 *end) 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *pos, *hs_start; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen, hlen; 5761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN]; 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = *msgpos; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Encrypted Handshake Message: Finished */ 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12 5861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conn->rl.tls_version >= TLS_VERSION_1_2) { 5871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hlen = SHA256_MAC_LEN; 5881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conn->verify.sha256_server == NULL || 5891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) 5901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt < 0) { 5911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->verify.sha256_server = NULL; 5921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 5931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 5941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return -1; 5951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 5961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->verify.sha256_server = NULL; 5971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 5981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */ 5991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlen = MD5_MAC_LEN; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->verify.md5_server == NULL || 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify.md5_server = NULL; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify.sha1_server = NULL; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify.md5_server = NULL; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hlen = SHA1_MAC_LEN; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->verify.sha1_server == NULL || 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &hlen) < 0) { 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify.sha1_server = NULL; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->verify.sha1_server = NULL; 6211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt hlen = MD5_MAC_LEN + SHA1_MAC_LEN; 6221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 6231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_TLSV12 6241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 6251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_TLSV12 */ 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tls_prf(conn->rl.tls_version, 6281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->master_secret, TLS_MASTER_SECRET_LEN, 6291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "server finished", hash, hlen, 6301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", 6371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Handshake */ 6401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos = hs_start = verify_data; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* HandshakeType msg_type */ 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; 6431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* uint24 length */ 6441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN); 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 3; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += TLS_VERIFY_DATA_LEN; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, 6501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *msgpos, end - *msgpos, hs_start, pos - hs_start, 6511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt &rlen) < 0) { 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *msgpos += rlen; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len) 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *msg, *end, *pos; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t msglen; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_len = 0; 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msglen = 1000 + tls_server_cert_chain_der_len(conn); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = os_malloc(msglen); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = msg; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = msg + msglen; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_write_server_hello(conn, &pos, end) < 0) { 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->use_session_ticket) { 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Abbreviated handshake using session ticket; RFC 4507 */ 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_write_server_finished(conn, &pos, end) < 0) { 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_len = pos - msg; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->state = CHANGE_CIPHER_SPEC; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Full handshake */ 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_write_server_certificate(conn, &pos, end) < 0 || 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_write_server_key_exchange(conn, &pos, end) < 0 || 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_write_server_certificate_request(conn, &pos, end) < 0 || 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_write_server_hello_done(conn, &pos, end) < 0) { 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_len = pos - msg; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->state = CLIENT_CERTIFICATE; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn, 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *out_len) 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *msg, *end, *pos; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_len = 0; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = os_malloc(1000); 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = msg; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = msg + 1000; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_write_server_finished(conn, &pos, end) < 0) { 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_len = pos - msg; 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully"); 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->state = ESTABLISHED; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len) 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (conn->state) { 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SERVER_HELLO: 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tls_send_server_hello(conn, out_len); 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case SERVER_CHANGE_CIPHER_SPEC: 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tls_send_change_cipher_spec(conn, out_len); 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->state == ESTABLISHED && conn->use_session_ticket) { 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Abbreviated handshake was already completed. */ 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "generating reply", conn->state); 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 description, size_t *out_len) 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *alert, *pos, *length; 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_len = 0; 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alert = os_malloc(10); 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (alert == NULL) 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = alert; 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TLSPlaintext */ 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ContentType type */ 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = TLS_CONTENT_TYPE_ALERT; 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* ProtocolVersion version */ 7831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version : 7841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt TLS_VERSION); 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* uint16 length (to be filled) */ 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt length = pos; 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* opaque fragment[TLSPlaintext.length] */ 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Alert */ 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AlertLevel level */ 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = level; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* AlertDescription description */ 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = description; 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(length, pos - length - 2); 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_len = pos - alert; 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return alert; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 802