18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246) 3c55524ad84d13014e8019491c2b17e5dcf13545aDmitry 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/sha1.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/tls.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_record.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_client.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tlsv1_client_i.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TODO: 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Support for a message fragmented across several records (RFC 2246, 6.2.1) 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tls_alert(struct tlsv1_client *conn, u8 level, u8 description) 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->alert_level = level; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->alert_description = description; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tlsv1_client_free_dh(struct tlsv1_client *conn) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->dh_p); 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->dh_g); 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->dh_ys); 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->dh_p = conn->dh_g = conn->dh_ys = NULL; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_derive_pre_master_secret(u8 *pre_master_secret) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pre_master_secret, TLS_VERSION); 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_get_random(pre_master_secret + 2, 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_PRE_MASTER_SECRET_LEN - 2)) 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tls_derive_keys(struct tlsv1_client *conn, 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pre_master_secret, size_t pre_master_secret_len) 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 seed[2 * TLS_RANDOM_LEN]; 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t key_block_len; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pre_master_secret) { 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pre_master_secret, pre_master_secret_len); 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_RANDOM_LEN); 641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tls_prf(conn->rl.tls_version, 651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pre_master_secret, pre_master_secret_len, 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "master secret", seed, 2 * TLS_RANDOM_LEN, 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->master_secret, TLS_MASTER_SECRET_LEN)) { 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "master_secret"); 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->master_secret, TLS_MASTER_SECRET_LEN); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); 781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len); 791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conn->rl.tls_version == TLS_VERSION_1) 801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt key_block_len += 2 * conn->rl.iv_size; 811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (tls_prf(conn->rl.tls_version, 821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->master_secret, TLS_MASTER_SECRET_LEN, 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key expansion", seed, 2 * TLS_RANDOM_LEN, 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_block, key_block_len)) { 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_block, key_block_len); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = key_block; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* client_write_MAC_secret */ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += conn->rl.hash_size; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* server_write_MAC_secret */ 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += conn->rl.hash_size; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* client_write_key */ 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += conn->rl.key_material_len; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* server_write_key */ 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += conn->rl.key_material_len; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conn->rl.tls_version == TLS_VERSION_1) { 1081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* client_write_IV */ 1091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); 1101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += conn->rl.iv_size; 1111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* server_write_IV */ 1121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += conn->rl.iv_size; 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Use IV field to set the mask value for TLS v1.1. A fixed 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * mask of zero is used per the RFC 4346, 6.2.3.2 CBC Block 1181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Cipher option 2a. 1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memset(conn->rl.write_iv, 0, conn->rl.iv_size); 1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_handshake - Process TLS handshake 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Input data from TLS peer 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_len: Input data length 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_len: Length of the output buffer. 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @appl_data: Pointer to application data pointer, or %NULL if dropped 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @appl_data_len: Pointer to variable that is set to appl_data length 1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @need_more_data: Set to 1 if more data would be needed to complete 1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * processing 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to output data, %NULL on failure 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtu8 * tlsv1_client_handshake(struct tlsv1_client *conn, 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *in_data, size_t in_len, 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t *out_len, u8 **appl_data, 1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t *appl_data_len, int *need_more_data) 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *msg = NULL, *in_msg = NULL, *in_pos, *in_end, alert, ct; 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t in_msg_len; 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int no_appl_data; 1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int used; 1491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (need_more_data) 1511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *need_more_data = 0; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->state == CLIENT_HELLO) { 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_len) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return tls_send_client_hello(conn, out_len); 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conn->partial_input) { 1601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_resize(&conn->partial_input, in_len) < 0) { 1611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 1621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "memory for pending record"); 1631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 1641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 1651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto failed; 1661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_data(conn->partial_input, in_data, in_len); 1681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt in_data = wpabuf_head(conn->partial_input); 1691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt in_len = wpabuf_len(conn->partial_input); 1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 1711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_data == NULL || in_len == 0) 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = in_data; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = in_data + in_len; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_msg = os_malloc(in_len); 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (in_msg == NULL) 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Each received packet may include multiple records */ 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos < end) { 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_msg_len = in_len; 1841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt used = tlsv1_record_receive(&conn->rl, pos, end - pos, 1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt in_msg, &in_msg_len, &alert); 1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (used < 0) { 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Processing received " 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "record failed"); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (used == 0) { 1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *partial; 1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Need more data"); 1951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt partial = wpabuf_alloc_copy(pos, end - pos); 1961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(conn->partial_input); 1971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->partial_input = partial; 1981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conn->partial_input == NULL) { 1991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to " 2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "allocate memory for pending " 2011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "record"); 2021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 2041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto failed; 2051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(in_msg); 2071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (need_more_data) 2081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *need_more_data = 1; 2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 2101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ct = pos[0]; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_pos = in_msg; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_end = in_msg + in_msg_len; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Each received record may include multiple messages of the 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * same ContentType. */ 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (in_pos < in_end) { 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_msg_len = in_end - in_pos; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_client_process_handshake(conn, ct, in_pos, 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &in_msg_len, 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt appl_data, 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt appl_data_len) < 0) 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto failed; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_pos += in_msg_len; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += used; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(in_msg); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_msg = NULL; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt no_appl_data = appl_data == NULL || *appl_data == NULL; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data); 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfailed: 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(in_msg); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->alert_level) { 2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(conn->partial_input); 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->partial_input = NULL; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->state = FAILED; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(msg); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = tlsv1_client_send_alert(conn, conn->alert_level, 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->alert_description, 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt out_len); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (msg == NULL) { 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = os_zalloc(1); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *out_len = 0; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (need_more_data == NULL || !(*need_more_data)) { 2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(conn->partial_input); 2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->partial_input = NULL; 2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_encrypt - Encrypt data into TLS tunnel 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Pointer to plaintext data to be encrypted 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_len: Input buffer length 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_data: Pointer to output buffer (encrypted TLS data) 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_len: Maximum out_data length 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Number of bytes written to out_data, -1 on failure 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used after TLS handshake has been completed successfully to 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * send data in the encrypted tunnel. 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_encrypt(struct tlsv1_client *conn, 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *in_data, size_t in_len, 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *out_data, size_t out_len) 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rlen; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_data, in_len); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, 2831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt out_data, out_len, in_data, in_len, &rlen) < 0) { 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_ALERT_INTERNAL_ERROR); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return rlen; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_decrypt - Decrypt data from TLS tunnel 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_data: Pointer to input buffer (encrypted TLS data) 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @in_len: Input buffer length 2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @need_more_data: Set to 1 if more data would be needed to complete 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * processing 3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Returns: Decrypted data or %NULL on failure 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used after TLS handshake has been completed successfully to 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * receive data from the encrypted tunnel. 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpabuf * tlsv1_client_decrypt(struct tlsv1_client *conn, 3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt const u8 *in_data, size_t in_len, 3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int *need_more_data) 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *in_end, *pos; 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int used; 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 alert, *out_pos, ct; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t olen; 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf = NULL; 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (need_more_data) 3171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *need_more_data = 0; 3181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conn->partial_input) { 3201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_resize(&conn->partial_input, in_len) < 0) { 3211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " 3221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "memory for pending record"); 3231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt alert = TLS_ALERT_INTERNAL_ERROR; 3241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 3251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_data(conn->partial_input, in_data, in_len); 3271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt in_data = wpabuf_head(conn->partial_input); 3281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt in_len = wpabuf_len(conn->partial_input); 3291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = in_data; 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt in_end = in_data + in_len; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos < in_end) { 3351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt ct = pos[0]; 3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_resize(&buf, in_end - pos) < 0) { 3371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt alert = TLS_ALERT_INTERNAL_ERROR; 3381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt out_pos = wpabuf_put(buf, 0); 3411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt olen = wpabuf_tailroom(buf); 3421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt used = tlsv1_record_receive(&conn->rl, pos, in_end - pos, 3431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt out_pos, &olen, &alert); 3441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (used < 0) { 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "failed"); 3471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (used == 0) { 3501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *partial; 3511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Need more data"); 3521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt partial = wpabuf_alloc_copy(pos, in_end - pos); 3531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(conn->partial_input); 3541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->partial_input = partial; 3551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (conn->partial_input == NULL) { 3561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to " 3571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "allocate memory for pending " 3581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "record"); 3591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt alert = TLS_ALERT_INTERNAL_ERROR; 3601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 3611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (need_more_data) 3631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt *need_more_data = 1; 3641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ct == TLS_CONTENT_TYPE_ALERT) { 3681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (olen < 2) { 3691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Alert " 3701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "underflow"); 3711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt alert = TLS_ALERT_DECODE_ERROR; 3721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", 3751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt out_pos[0], out_pos[1]); 3761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) { 3771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Continue processing */ 3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += used; 3791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt continue; 3801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt alert = out_pos[1]; 3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { 3871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " 3881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "0x%x when decrypting application data", 3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos[0]); 3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt alert = TLS_ALERT_UNEXPECTED_MESSAGE; 3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt goto fail; 3921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put(buf, olen); 3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pos += used; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(conn->partial_input); 4001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->partial_input = NULL; 4011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 4021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtfail: 4041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(buf); 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(conn->partial_input); 4061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->partial_input = NULL; 4071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 4081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_global_init - Initialize TLSv1 client 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function must be called before using any other TLSv1 client functions. 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_global_init(void) 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return crypto_global_init(); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_global_deinit - Deinitialize TLSv1 client 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function can be used to deinitialize the TLSv1 client that was 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * can be called after this before calling tlsv1_client_global_init() again. 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tlsv1_client_global_deinit(void) 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_global_deinit(); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_init - Initialize TLSv1 client connection 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to TLSv1 client connection data or %NULL on failure 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct tlsv1_client * tlsv1_client_init(void) 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tlsv1_client *conn; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t count; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 *suites; 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn = os_zalloc(sizeof(*conn)); 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn == NULL) 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->state = CLIENT_HELLO; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_verify_hash_init(&conn->verify) < 0) { 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hash"); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 0; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites = conn->cipher_suites; 4621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA256; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; 4641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_RSA_WITH_RC4_128_SHA; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_RSA_WITH_RC4_128_MD5; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->num_cipher_suites = count; 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->rl.tls_version = TLS_VERSION; 4721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_deinit - Deinitialize TLSv1 client connection 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tlsv1_client_deinit(struct tlsv1_client *conn) 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_public_key_free(conn->server_rsa_key); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_record_change_write_cipher(&conn->rl); 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_record_change_read_cipher(&conn->rl); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tls_verify_hash_free(&conn->verify); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->client_hello_ext); 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_client_free_dh(conn); 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_cred_free(conn->cred); 4911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_free(conn->partial_input); 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_established - Check whether connection has been established 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if connection is established, 0 if not 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_established(struct tlsv1_client *conn) 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return conn->state == ESTABLISHED; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_prf - Use TLS-PRF to derive keying material 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @label: Label (e.g., description of the key) for PRF 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @server_random_first: seed is 0 = client_random|server_random, 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1 = server_random|client_random 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out: Buffer for output data from TLS-PRF 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @out_len: Length of the output buffer 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_prf(struct tlsv1_client *conn, const char *label, 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int server_random_first, u8 *out, size_t out_len) 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 seed[2 * TLS_RANDOM_LEN]; 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->state != ESTABLISHED) 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (server_random_first) { 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_RANDOM_LEN); 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt TLS_RANDOM_LEN); 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return tls_prf(conn->rl.tls_version, 5361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt conn->master_secret, TLS_MASTER_SECRET_LEN, 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt label, seed, 2 * TLS_RANDOM_LEN, out, out_len); 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_get_cipher - Get current cipher name 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for the cipher name 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buflen: buf size 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Get the name of the currently used cipher. 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buflen) 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *cipher; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (conn->rl.cipher_suite) { 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TLS_RSA_WITH_RC4_128_MD5: 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = "RC4-MD5"; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TLS_RSA_WITH_RC4_128_SHA: 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = "RC4-SHA"; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TLS_RSA_WITH_DES_CBC_SHA: 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = "DES-CBC-SHA"; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TLS_RSA_WITH_3DES_EDE_CBC_SHA: 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = "DES-CBC3-SHA"; 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case TLS_DH_anon_WITH_AES_128_CBC_SHA256: 5691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cipher = "ADH-AES-128-SHA256"; 5701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TLS_DH_anon_WITH_AES_128_CBC_SHA: 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = "ADH-AES-128-SHA"; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TLS_RSA_WITH_AES_256_CBC_SHA: 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = "AES-256-SHA"; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case TLS_RSA_WITH_AES_256_CBC_SHA256: 5781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cipher = "AES-256-SHA256"; 5791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TLS_RSA_WITH_AES_128_CBC_SHA: 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = "AES-128-SHA"; 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case TLS_RSA_WITH_AES_128_CBC_SHA256: 5841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt cipher = "AES-128-SHA256"; 5851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlcpy(buf, cipher, buflen) >= buflen) 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_shutdown - Shutdown TLS connection 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_shutdown(struct tlsv1_client *conn) 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->state = CLIENT_HELLO; 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tls_verify_hash_init(&conn->verify) < 0) { 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "hash"); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_record_change_write_cipher(&conn->rl); 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_record_change_read_cipher(&conn->rl); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->certificate_requested = 0; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_public_key_free(conn->server_rsa_key); 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->server_rsa_key = NULL; 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_resumed = 0; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_resumed - Was session resumption used 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if current session used session resumption, 0 if not 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_resumed(struct tlsv1_client *conn) 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return !!conn->session_resumed; 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_hello_ext - Set TLS extension for ClientHello 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ext_type: Extension type 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Extension payload (%NULL to remove extension) 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data_len: Extension payload length 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *data, size_t data_len) 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_ticket_included = 0; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(conn->client_hello_ext); 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->client_hello_ext = NULL; 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->client_hello_ext_len = 0; 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL || data_len == 0) 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = conn->client_hello_ext = os_malloc(6 + data_len); 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, 4 + data_len); 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, ext_type); 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_BE16(pos, data_len); 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, data, data_len); 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->client_hello_ext_len = 6 + data_len; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ext_type == TLS_EXT_PAC_OPAQUE) { 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_ticket_included = 1; 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket"); 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_get_keys - Get master key and random data from TLS connection 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @keys: Structure of key/random data (filled on success) 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys) 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(keys, 0, sizeof(*keys)); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->state == CLIENT_HELLO) 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->client_random = conn->client_random; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->client_random_len = TLS_RANDOM_LEN; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->state != SERVER_HELLO) { 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->server_random = conn->server_random; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->server_random_len = TLS_RANDOM_LEN; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->master_key = conn->master_secret; 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt keys->master_key_len = TLS_MASTER_SECRET_LEN; 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_get_keyblock_size - Get TLS key_block size 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Size of the key_block for the negotiated cipher suite or -1 on 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * failure 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_get_keyblock_size(struct tlsv1_client *conn) 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 2 * (conn->rl.hash_size + conn->rl.key_material_len + 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->rl.iv_size); 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_set_cipher_list - Configure acceptable cipher suites 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (TLS_CIPHER_*). 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers) 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t count; 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 *suites; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: implement proper configuration of cipher suites */ 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 0; 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites = conn->cipher_suites; 7361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA256; 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; 7381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA256; 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Cisco AP (at least 350 and 1200 series) local authentication 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * server does not know how to search cipher suites from the 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * list and seem to require that the last entry in the list is 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the one that it wants to use. However, TLS specification 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * requires the list to be in the client preference order. As a 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * workaround, add anon-DH AES-128-SHA1 again at the end of the 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * list to allow the Cisco code to find it. 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->num_cipher_suites = count; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * tlsv1_client_set_cred - Set client credentials 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @conn: TLSv1 client connection data from tlsv1_client_init() 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cred: Credentials from tlsv1_cred_alloc() 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * On success, the client takes ownership of the credentials block and caller 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * must not free it. On failure, caller is responsible for freeing the 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * credential block. 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint tlsv1_client_set_cred(struct tlsv1_client *conn, 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tlsv1_credentials *cred) 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_cred_free(conn->cred); 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->cred = cred; 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 780c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidtvoid tlsv1_client_set_time_checks(struct tlsv1_client *conn, int enabled) 781c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt{ 782c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt conn->disable_time_checks = !enabled; 783c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt} 784c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 785c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tlsv1_client_session_ticket_cb cb, 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx) 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cb, ctx); 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_ticket_cb = cb; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt conn->session_ticket_cb_ctx = ctx; 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 795