18dbcf02cSchristos /*
262a52023Schristos * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246)
3*0d69f216Schristos * Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos *
562a52023Schristos * This software may be distributed under the terms of the BSD license.
662a52023Schristos * See README for more details.
78dbcf02cSchristos */
88dbcf02cSchristos
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos
118dbcf02cSchristos #include "common.h"
128dbcf02cSchristos #include "crypto/sha1.h"
138dbcf02cSchristos #include "crypto/tls.h"
14928750b6Schristos #include "x509v3.h"
158dbcf02cSchristos #include "tlsv1_common.h"
168dbcf02cSchristos #include "tlsv1_record.h"
178dbcf02cSchristos #include "tlsv1_client.h"
188dbcf02cSchristos #include "tlsv1_client_i.h"
198dbcf02cSchristos
208dbcf02cSchristos /* TODO:
218dbcf02cSchristos * Support for a message fragmented across several records (RFC 2246, 6.2.1)
228dbcf02cSchristos */
238dbcf02cSchristos
248dbcf02cSchristos
tls_alert(struct tlsv1_client * conn,u8 level,u8 description)258dbcf02cSchristos void tls_alert(struct tlsv1_client *conn, u8 level, u8 description)
268dbcf02cSchristos {
278dbcf02cSchristos conn->alert_level = level;
288dbcf02cSchristos conn->alert_description = description;
298dbcf02cSchristos }
308dbcf02cSchristos
318dbcf02cSchristos
tlsv1_client_free_dh(struct tlsv1_client * conn)328dbcf02cSchristos void tlsv1_client_free_dh(struct tlsv1_client *conn)
338dbcf02cSchristos {
348dbcf02cSchristos os_free(conn->dh_p);
358dbcf02cSchristos os_free(conn->dh_g);
368dbcf02cSchristos os_free(conn->dh_ys);
378dbcf02cSchristos conn->dh_p = conn->dh_g = conn->dh_ys = NULL;
388dbcf02cSchristos }
398dbcf02cSchristos
408dbcf02cSchristos
tls_derive_pre_master_secret(u8 * pre_master_secret)418dbcf02cSchristos int tls_derive_pre_master_secret(u8 *pre_master_secret)
428dbcf02cSchristos {
438dbcf02cSchristos WPA_PUT_BE16(pre_master_secret, TLS_VERSION);
448dbcf02cSchristos if (os_get_random(pre_master_secret + 2,
458dbcf02cSchristos TLS_PRE_MASTER_SECRET_LEN - 2))
468dbcf02cSchristos return -1;
478dbcf02cSchristos return 0;
488dbcf02cSchristos }
498dbcf02cSchristos
508dbcf02cSchristos
tls_derive_keys(struct tlsv1_client * conn,const u8 * pre_master_secret,size_t pre_master_secret_len)518dbcf02cSchristos int tls_derive_keys(struct tlsv1_client *conn,
528dbcf02cSchristos const u8 *pre_master_secret, size_t pre_master_secret_len)
538dbcf02cSchristos {
548dbcf02cSchristos u8 seed[2 * TLS_RANDOM_LEN];
558dbcf02cSchristos u8 key_block[TLS_MAX_KEY_BLOCK_LEN];
568dbcf02cSchristos u8 *pos;
578dbcf02cSchristos size_t key_block_len;
588dbcf02cSchristos
598dbcf02cSchristos if (pre_master_secret) {
608dbcf02cSchristos wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret",
618dbcf02cSchristos pre_master_secret, pre_master_secret_len);
628dbcf02cSchristos os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
638dbcf02cSchristos os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
648dbcf02cSchristos TLS_RANDOM_LEN);
6562a52023Schristos if (tls_prf(conn->rl.tls_version,
6662a52023Schristos pre_master_secret, pre_master_secret_len,
678dbcf02cSchristos "master secret", seed, 2 * TLS_RANDOM_LEN,
688dbcf02cSchristos conn->master_secret, TLS_MASTER_SECRET_LEN)) {
698dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive "
708dbcf02cSchristos "master_secret");
718dbcf02cSchristos return -1;
728dbcf02cSchristos }
738dbcf02cSchristos wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret",
748dbcf02cSchristos conn->master_secret, TLS_MASTER_SECRET_LEN);
758dbcf02cSchristos }
768dbcf02cSchristos
778dbcf02cSchristos os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
788dbcf02cSchristos os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN);
7942669be3Schristos key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len);
8042669be3Schristos if (conn->rl.tls_version == TLS_VERSION_1)
8142669be3Schristos key_block_len += 2 * conn->rl.iv_size;
8262a52023Schristos if (tls_prf(conn->rl.tls_version,
8362a52023Schristos conn->master_secret, TLS_MASTER_SECRET_LEN,
848dbcf02cSchristos "key expansion", seed, 2 * TLS_RANDOM_LEN,
858dbcf02cSchristos key_block, key_block_len)) {
868dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block");
878dbcf02cSchristos return -1;
888dbcf02cSchristos }
898dbcf02cSchristos wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block",
908dbcf02cSchristos key_block, key_block_len);
918dbcf02cSchristos
928dbcf02cSchristos pos = key_block;
938dbcf02cSchristos
948dbcf02cSchristos /* client_write_MAC_secret */
958dbcf02cSchristos os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size);
968dbcf02cSchristos pos += conn->rl.hash_size;
978dbcf02cSchristos /* server_write_MAC_secret */
988dbcf02cSchristos os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size);
998dbcf02cSchristos pos += conn->rl.hash_size;
1008dbcf02cSchristos
1018dbcf02cSchristos /* client_write_key */
1028dbcf02cSchristos os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len);
1038dbcf02cSchristos pos += conn->rl.key_material_len;
1048dbcf02cSchristos /* server_write_key */
1058dbcf02cSchristos os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len);
1068dbcf02cSchristos pos += conn->rl.key_material_len;
1078dbcf02cSchristos
10842669be3Schristos if (conn->rl.tls_version == TLS_VERSION_1) {
1098dbcf02cSchristos /* client_write_IV */
1108dbcf02cSchristos os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size);
1118dbcf02cSchristos pos += conn->rl.iv_size;
1128dbcf02cSchristos /* server_write_IV */
1138dbcf02cSchristos os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size);
11442669be3Schristos } else {
11542669be3Schristos /*
11642669be3Schristos * Use IV field to set the mask value for TLS v1.1. A fixed
11742669be3Schristos * mask of zero is used per the RFC 4346, 6.2.3.2 CBC Block
11842669be3Schristos * Cipher option 2a.
11942669be3Schristos */
12042669be3Schristos os_memset(conn->rl.write_iv, 0, conn->rl.iv_size);
12142669be3Schristos }
1228dbcf02cSchristos
1238dbcf02cSchristos return 0;
1248dbcf02cSchristos }
1258dbcf02cSchristos
1268dbcf02cSchristos
1278dbcf02cSchristos /**
1288dbcf02cSchristos * tlsv1_client_handshake - Process TLS handshake
1298dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
1308dbcf02cSchristos * @in_data: Input data from TLS peer
1318dbcf02cSchristos * @in_len: Input data length
1328dbcf02cSchristos * @out_len: Length of the output buffer.
1338dbcf02cSchristos * @appl_data: Pointer to application data pointer, or %NULL if dropped
1348dbcf02cSchristos * @appl_data_len: Pointer to variable that is set to appl_data length
13562a52023Schristos * @need_more_data: Set to 1 if more data would be needed to complete
13662a52023Schristos * processing
1378dbcf02cSchristos * Returns: Pointer to output data, %NULL on failure
1388dbcf02cSchristos */
tlsv1_client_handshake(struct tlsv1_client * conn,const u8 * in_data,size_t in_len,size_t * out_len,u8 ** appl_data,size_t * appl_data_len,int * need_more_data)1398dbcf02cSchristos u8 * tlsv1_client_handshake(struct tlsv1_client *conn,
1408dbcf02cSchristos const u8 *in_data, size_t in_len,
1418dbcf02cSchristos size_t *out_len, u8 **appl_data,
14262a52023Schristos size_t *appl_data_len, int *need_more_data)
1438dbcf02cSchristos {
1448dbcf02cSchristos const u8 *pos, *end;
14562a52023Schristos u8 *msg = NULL, *in_msg = NULL, *in_pos, *in_end, alert, ct;
1468dbcf02cSchristos size_t in_msg_len;
1478dbcf02cSchristos int no_appl_data;
14862a52023Schristos int used;
14962a52023Schristos
15062a52023Schristos if (need_more_data)
15162a52023Schristos *need_more_data = 0;
1528dbcf02cSchristos
1538dbcf02cSchristos if (conn->state == CLIENT_HELLO) {
1548dbcf02cSchristos if (in_len)
1558dbcf02cSchristos return NULL;
1568dbcf02cSchristos return tls_send_client_hello(conn, out_len);
1578dbcf02cSchristos }
1588dbcf02cSchristos
15962a52023Schristos if (conn->partial_input) {
16062a52023Schristos if (wpabuf_resize(&conn->partial_input, in_len) < 0) {
16162a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
16262a52023Schristos "memory for pending record");
16362a52023Schristos tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
16462a52023Schristos TLS_ALERT_INTERNAL_ERROR);
16562a52023Schristos goto failed;
16662a52023Schristos }
16762a52023Schristos wpabuf_put_data(conn->partial_input, in_data, in_len);
16862a52023Schristos in_data = wpabuf_head(conn->partial_input);
16962a52023Schristos in_len = wpabuf_len(conn->partial_input);
17062a52023Schristos }
17162a52023Schristos
1728dbcf02cSchristos if (in_data == NULL || in_len == 0)
1738dbcf02cSchristos return NULL;
1748dbcf02cSchristos
1758dbcf02cSchristos pos = in_data;
1768dbcf02cSchristos end = in_data + in_len;
1778dbcf02cSchristos in_msg = os_malloc(in_len);
1788dbcf02cSchristos if (in_msg == NULL)
1798dbcf02cSchristos return NULL;
1808dbcf02cSchristos
1818dbcf02cSchristos /* Each received packet may include multiple records */
1828dbcf02cSchristos while (pos < end) {
1838dbcf02cSchristos in_msg_len = in_len;
18462a52023Schristos used = tlsv1_record_receive(&conn->rl, pos, end - pos,
18562a52023Schristos in_msg, &in_msg_len, &alert);
18662a52023Schristos if (used < 0) {
1878dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: Processing received "
1888dbcf02cSchristos "record failed");
1898dbcf02cSchristos tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
1908dbcf02cSchristos goto failed;
1918dbcf02cSchristos }
19262a52023Schristos if (used == 0) {
19362a52023Schristos struct wpabuf *partial;
19462a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Need more data");
19562a52023Schristos partial = wpabuf_alloc_copy(pos, end - pos);
19662a52023Schristos wpabuf_free(conn->partial_input);
19762a52023Schristos conn->partial_input = partial;
19862a52023Schristos if (conn->partial_input == NULL) {
19962a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
20062a52023Schristos "allocate memory for pending "
20162a52023Schristos "record");
20262a52023Schristos tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
20362a52023Schristos TLS_ALERT_INTERNAL_ERROR);
20462a52023Schristos goto failed;
20562a52023Schristos }
20662a52023Schristos os_free(in_msg);
20762a52023Schristos if (need_more_data)
20862a52023Schristos *need_more_data = 1;
20962a52023Schristos return NULL;
21062a52023Schristos }
2118dbcf02cSchristos ct = pos[0];
2128dbcf02cSchristos
2138dbcf02cSchristos in_pos = in_msg;
2148dbcf02cSchristos in_end = in_msg + in_msg_len;
2158dbcf02cSchristos
2168dbcf02cSchristos /* Each received record may include multiple messages of the
2178dbcf02cSchristos * same ContentType. */
2188dbcf02cSchristos while (in_pos < in_end) {
2198dbcf02cSchristos in_msg_len = in_end - in_pos;
2208dbcf02cSchristos if (tlsv1_client_process_handshake(conn, ct, in_pos,
2218dbcf02cSchristos &in_msg_len,
2228dbcf02cSchristos appl_data,
2238dbcf02cSchristos appl_data_len) < 0)
2248dbcf02cSchristos goto failed;
2258dbcf02cSchristos in_pos += in_msg_len;
2268dbcf02cSchristos }
2278dbcf02cSchristos
22862a52023Schristos pos += used;
2298dbcf02cSchristos }
2308dbcf02cSchristos
2318dbcf02cSchristos os_free(in_msg);
2328dbcf02cSchristos in_msg = NULL;
2338dbcf02cSchristos
2348dbcf02cSchristos no_appl_data = appl_data == NULL || *appl_data == NULL;
2358dbcf02cSchristos msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data);
2368dbcf02cSchristos
2378dbcf02cSchristos failed:
2388dbcf02cSchristos os_free(in_msg);
2398dbcf02cSchristos if (conn->alert_level) {
24062a52023Schristos wpabuf_free(conn->partial_input);
24162a52023Schristos conn->partial_input = NULL;
2428dbcf02cSchristos conn->state = FAILED;
2438dbcf02cSchristos os_free(msg);
2448dbcf02cSchristos msg = tlsv1_client_send_alert(conn, conn->alert_level,
2458dbcf02cSchristos conn->alert_description,
2468dbcf02cSchristos out_len);
2478dbcf02cSchristos } else if (msg == NULL) {
2488dbcf02cSchristos msg = os_zalloc(1);
2498dbcf02cSchristos *out_len = 0;
2508dbcf02cSchristos }
2518dbcf02cSchristos
25262a52023Schristos if (need_more_data == NULL || !(*need_more_data)) {
25362a52023Schristos wpabuf_free(conn->partial_input);
25462a52023Schristos conn->partial_input = NULL;
25562a52023Schristos }
25662a52023Schristos
2578dbcf02cSchristos return msg;
2588dbcf02cSchristos }
2598dbcf02cSchristos
2608dbcf02cSchristos
2618dbcf02cSchristos /**
2628dbcf02cSchristos * tlsv1_client_encrypt - Encrypt data into TLS tunnel
2638dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
2648dbcf02cSchristos * @in_data: Pointer to plaintext data to be encrypted
2658dbcf02cSchristos * @in_len: Input buffer length
2668dbcf02cSchristos * @out_data: Pointer to output buffer (encrypted TLS data)
2678dbcf02cSchristos * @out_len: Maximum out_data length
2688dbcf02cSchristos * Returns: Number of bytes written to out_data, -1 on failure
2698dbcf02cSchristos *
2708dbcf02cSchristos * This function is used after TLS handshake has been completed successfully to
2718dbcf02cSchristos * send data in the encrypted tunnel.
2728dbcf02cSchristos */
tlsv1_client_encrypt(struct tlsv1_client * conn,const u8 * in_data,size_t in_len,u8 * out_data,size_t out_len)2738dbcf02cSchristos int tlsv1_client_encrypt(struct tlsv1_client *conn,
2748dbcf02cSchristos const u8 *in_data, size_t in_len,
2758dbcf02cSchristos u8 *out_data, size_t out_len)
2768dbcf02cSchristos {
2778dbcf02cSchristos size_t rlen;
2788dbcf02cSchristos
2798dbcf02cSchristos wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData",
2808dbcf02cSchristos in_data, in_len);
2818dbcf02cSchristos
2828dbcf02cSchristos if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA,
28342669be3Schristos out_data, out_len, in_data, in_len, &rlen) < 0) {
2848dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record");
2858dbcf02cSchristos tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
2868dbcf02cSchristos TLS_ALERT_INTERNAL_ERROR);
2878dbcf02cSchristos return -1;
2888dbcf02cSchristos }
2898dbcf02cSchristos
2908dbcf02cSchristos return rlen;
2918dbcf02cSchristos }
2928dbcf02cSchristos
2938dbcf02cSchristos
2948dbcf02cSchristos /**
2958dbcf02cSchristos * tlsv1_client_decrypt - Decrypt data from TLS tunnel
2968dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
2978dbcf02cSchristos * @in_data: Pointer to input buffer (encrypted TLS data)
2988dbcf02cSchristos * @in_len: Input buffer length
29962a52023Schristos * @need_more_data: Set to 1 if more data would be needed to complete
30062a52023Schristos * processing
30162a52023Schristos * Returns: Decrypted data or %NULL on failure
3028dbcf02cSchristos *
3038dbcf02cSchristos * This function is used after TLS handshake has been completed successfully to
3048dbcf02cSchristos * receive data from the encrypted tunnel.
3058dbcf02cSchristos */
tlsv1_client_decrypt(struct tlsv1_client * conn,const u8 * in_data,size_t in_len,int * need_more_data)30662a52023Schristos struct wpabuf * tlsv1_client_decrypt(struct tlsv1_client *conn,
3078dbcf02cSchristos const u8 *in_data, size_t in_len,
30862a52023Schristos int *need_more_data)
3098dbcf02cSchristos {
3108dbcf02cSchristos const u8 *in_end, *pos;
31162a52023Schristos int used;
31262a52023Schristos u8 alert, *out_pos, ct;
3138dbcf02cSchristos size_t olen;
31462a52023Schristos struct wpabuf *buf = NULL;
31562a52023Schristos
31662a52023Schristos if (need_more_data)
31762a52023Schristos *need_more_data = 0;
31862a52023Schristos
31962a52023Schristos if (conn->partial_input) {
32062a52023Schristos if (wpabuf_resize(&conn->partial_input, in_len) < 0) {
32162a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate "
32262a52023Schristos "memory for pending record");
32362a52023Schristos alert = TLS_ALERT_INTERNAL_ERROR;
32462a52023Schristos goto fail;
32562a52023Schristos }
32662a52023Schristos wpabuf_put_data(conn->partial_input, in_data, in_len);
32762a52023Schristos in_data = wpabuf_head(conn->partial_input);
32862a52023Schristos in_len = wpabuf_len(conn->partial_input);
32962a52023Schristos }
3308dbcf02cSchristos
3318dbcf02cSchristos pos = in_data;
3328dbcf02cSchristos in_end = in_data + in_len;
3338dbcf02cSchristos
3348dbcf02cSchristos while (pos < in_end) {
33562a52023Schristos ct = pos[0];
33662a52023Schristos if (wpabuf_resize(&buf, in_end - pos) < 0) {
33762a52023Schristos alert = TLS_ALERT_INTERNAL_ERROR;
33862a52023Schristos goto fail;
3398dbcf02cSchristos }
34062a52023Schristos out_pos = wpabuf_put(buf, 0);
34162a52023Schristos olen = wpabuf_tailroom(buf);
34262a52023Schristos used = tlsv1_record_receive(&conn->rl, pos, in_end - pos,
3438dbcf02cSchristos out_pos, &olen, &alert);
34462a52023Schristos if (used < 0) {
3458dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing "
3468dbcf02cSchristos "failed");
34762a52023Schristos goto fail;
34862a52023Schristos }
34962a52023Schristos if (used == 0) {
35062a52023Schristos struct wpabuf *partial;
35162a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Need more data");
35262a52023Schristos partial = wpabuf_alloc_copy(pos, in_end - pos);
35362a52023Schristos wpabuf_free(conn->partial_input);
35462a52023Schristos conn->partial_input = partial;
35562a52023Schristos if (conn->partial_input == NULL) {
35662a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to "
35762a52023Schristos "allocate memory for pending "
35862a52023Schristos "record");
35962a52023Schristos alert = TLS_ALERT_INTERNAL_ERROR;
36062a52023Schristos goto fail;
36162a52023Schristos }
36262a52023Schristos if (need_more_data)
36362a52023Schristos *need_more_data = 1;
36462a52023Schristos return buf;
36562a52023Schristos }
36662a52023Schristos
36762a52023Schristos if (ct == TLS_CONTENT_TYPE_ALERT) {
36862a52023Schristos if (olen < 2) {
36962a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Alert "
37062a52023Schristos "underflow");
37162a52023Schristos alert = TLS_ALERT_DECODE_ERROR;
37262a52023Schristos goto fail;
37362a52023Schristos }
37462a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d",
37562a52023Schristos out_pos[0], out_pos[1]);
37662a52023Schristos if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) {
37762a52023Schristos /* Continue processing */
37862a52023Schristos pos += used;
37962a52023Schristos continue;
38062a52023Schristos }
38162a52023Schristos
38262a52023Schristos alert = out_pos[1];
38362a52023Schristos goto fail;
38462a52023Schristos }
38562a52023Schristos
38662a52023Schristos if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) {
38762a52023Schristos wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type "
38862a52023Schristos "0x%x when decrypting application data",
38962a52023Schristos pos[0]);
39062a52023Schristos alert = TLS_ALERT_UNEXPECTED_MESSAGE;
39162a52023Schristos goto fail;
39262a52023Schristos }
39362a52023Schristos
39462a52023Schristos wpabuf_put(buf, olen);
39562a52023Schristos
39662a52023Schristos pos += used;
39762a52023Schristos }
39862a52023Schristos
39962a52023Schristos wpabuf_free(conn->partial_input);
40062a52023Schristos conn->partial_input = NULL;
40162a52023Schristos return buf;
40262a52023Schristos
40362a52023Schristos fail:
40462a52023Schristos wpabuf_free(buf);
40562a52023Schristos wpabuf_free(conn->partial_input);
40662a52023Schristos conn->partial_input = NULL;
4078dbcf02cSchristos tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert);
40862a52023Schristos return NULL;
4098dbcf02cSchristos }
4108dbcf02cSchristos
4118dbcf02cSchristos
4128dbcf02cSchristos /**
4138dbcf02cSchristos * tlsv1_client_global_init - Initialize TLSv1 client
4148dbcf02cSchristos * Returns: 0 on success, -1 on failure
4158dbcf02cSchristos *
4168dbcf02cSchristos * This function must be called before using any other TLSv1 client functions.
4178dbcf02cSchristos */
tlsv1_client_global_init(void)4188dbcf02cSchristos int tlsv1_client_global_init(void)
4198dbcf02cSchristos {
4208dbcf02cSchristos return crypto_global_init();
4218dbcf02cSchristos }
4228dbcf02cSchristos
4238dbcf02cSchristos
4248dbcf02cSchristos /**
4258dbcf02cSchristos * tlsv1_client_global_deinit - Deinitialize TLSv1 client
4268dbcf02cSchristos *
4278dbcf02cSchristos * This function can be used to deinitialize the TLSv1 client that was
4288dbcf02cSchristos * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions
4298dbcf02cSchristos * can be called after this before calling tlsv1_client_global_init() again.
4308dbcf02cSchristos */
tlsv1_client_global_deinit(void)4318dbcf02cSchristos void tlsv1_client_global_deinit(void)
4328dbcf02cSchristos {
4338dbcf02cSchristos crypto_global_deinit();
4348dbcf02cSchristos }
4358dbcf02cSchristos
4368dbcf02cSchristos
4378dbcf02cSchristos /**
4388dbcf02cSchristos * tlsv1_client_init - Initialize TLSv1 client connection
4398dbcf02cSchristos * Returns: Pointer to TLSv1 client connection data or %NULL on failure
4408dbcf02cSchristos */
tlsv1_client_init(void)4418dbcf02cSchristos struct tlsv1_client * tlsv1_client_init(void)
4428dbcf02cSchristos {
4438dbcf02cSchristos struct tlsv1_client *conn;
4448dbcf02cSchristos size_t count;
4458dbcf02cSchristos u16 *suites;
4468dbcf02cSchristos
4478dbcf02cSchristos conn = os_zalloc(sizeof(*conn));
4488dbcf02cSchristos if (conn == NULL)
4498dbcf02cSchristos return NULL;
4508dbcf02cSchristos
4518dbcf02cSchristos conn->state = CLIENT_HELLO;
4528dbcf02cSchristos
4538dbcf02cSchristos if (tls_verify_hash_init(&conn->verify) < 0) {
4548dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify "
4558dbcf02cSchristos "hash");
4568dbcf02cSchristos os_free(conn);
4578dbcf02cSchristos return NULL;
4588dbcf02cSchristos }
4598dbcf02cSchristos
4608dbcf02cSchristos count = 0;
4618dbcf02cSchristos suites = conn->cipher_suites;
46236d97821Schristos suites[count++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
46362a52023Schristos suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA256;
46436d97821Schristos suites[count++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
4658dbcf02cSchristos suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA;
46636d97821Schristos suites[count++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
46762a52023Schristos suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256;
46836d97821Schristos suites[count++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
4698dbcf02cSchristos suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA;
47036d97821Schristos suites[count++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
4718dbcf02cSchristos suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA;
4728dbcf02cSchristos suites[count++] = TLS_RSA_WITH_RC4_128_SHA;
4738dbcf02cSchristos suites[count++] = TLS_RSA_WITH_RC4_128_MD5;
4748dbcf02cSchristos conn->num_cipher_suites = count;
4758dbcf02cSchristos
47642669be3Schristos conn->rl.tls_version = TLS_VERSION;
47742669be3Schristos
4788dbcf02cSchristos return conn;
4798dbcf02cSchristos }
4808dbcf02cSchristos
4818dbcf02cSchristos
4828dbcf02cSchristos /**
4838dbcf02cSchristos * tlsv1_client_deinit - Deinitialize TLSv1 client connection
4848dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
4858dbcf02cSchristos */
tlsv1_client_deinit(struct tlsv1_client * conn)4868dbcf02cSchristos void tlsv1_client_deinit(struct tlsv1_client *conn)
4878dbcf02cSchristos {
4888dbcf02cSchristos crypto_public_key_free(conn->server_rsa_key);
4898dbcf02cSchristos tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
4908dbcf02cSchristos tlsv1_record_change_write_cipher(&conn->rl);
4918dbcf02cSchristos tlsv1_record_change_read_cipher(&conn->rl);
4928dbcf02cSchristos tls_verify_hash_free(&conn->verify);
4938dbcf02cSchristos os_free(conn->client_hello_ext);
4948dbcf02cSchristos tlsv1_client_free_dh(conn);
4958dbcf02cSchristos tlsv1_cred_free(conn->cred);
49662a52023Schristos wpabuf_free(conn->partial_input);
497928750b6Schristos x509_certificate_chain_free(conn->server_cert);
4988dbcf02cSchristos os_free(conn);
4998dbcf02cSchristos }
5008dbcf02cSchristos
5018dbcf02cSchristos
5028dbcf02cSchristos /**
5038dbcf02cSchristos * tlsv1_client_established - Check whether connection has been established
5048dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
5058dbcf02cSchristos * Returns: 1 if connection is established, 0 if not
5068dbcf02cSchristos */
tlsv1_client_established(struct tlsv1_client * conn)5078dbcf02cSchristos int tlsv1_client_established(struct tlsv1_client *conn)
5088dbcf02cSchristos {
5098dbcf02cSchristos return conn->state == ESTABLISHED;
5108dbcf02cSchristos }
5118dbcf02cSchristos
5128dbcf02cSchristos
5138dbcf02cSchristos /**
5148dbcf02cSchristos * tlsv1_client_prf - Use TLS-PRF to derive keying material
5158dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
5168dbcf02cSchristos * @label: Label (e.g., description of the key) for PRF
517*0d69f216Schristos * @context: Optional extra upper-layer context (max len 2^16)
518*0d69f216Schristos * @context_len: The length of the context value
5198dbcf02cSchristos * @server_random_first: seed is 0 = client_random|server_random,
5208dbcf02cSchristos * 1 = server_random|client_random
5218dbcf02cSchristos * @out: Buffer for output data from TLS-PRF
5228dbcf02cSchristos * @out_len: Length of the output buffer
5238dbcf02cSchristos * Returns: 0 on success, -1 on failure
5248dbcf02cSchristos */
tlsv1_client_prf(struct tlsv1_client * conn,const char * label,const u8 * context,size_t context_len,int server_random_first,u8 * out,size_t out_len)5258dbcf02cSchristos int tlsv1_client_prf(struct tlsv1_client *conn, const char *label,
526*0d69f216Schristos const u8 *context, size_t context_len,
5278dbcf02cSchristos int server_random_first, u8 *out, size_t out_len)
5288dbcf02cSchristos {
529*0d69f216Schristos u8 *seed, *pos;
530*0d69f216Schristos size_t seed_len = 2 * TLS_RANDOM_LEN;
531*0d69f216Schristos int res;
5328dbcf02cSchristos
5338dbcf02cSchristos if (conn->state != ESTABLISHED)
5348dbcf02cSchristos return -1;
5358dbcf02cSchristos
536*0d69f216Schristos if (context_len > 65535)
537*0d69f216Schristos return -1;
538*0d69f216Schristos
539*0d69f216Schristos if (context)
540*0d69f216Schristos seed_len += 2 + context_len;
541*0d69f216Schristos
542*0d69f216Schristos seed = os_malloc(seed_len);
543*0d69f216Schristos if (!seed)
544*0d69f216Schristos return -1;
545*0d69f216Schristos
5468dbcf02cSchristos if (server_random_first) {
5478dbcf02cSchristos os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN);
5488dbcf02cSchristos os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random,
5498dbcf02cSchristos TLS_RANDOM_LEN);
5508dbcf02cSchristos } else {
5518dbcf02cSchristos os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN);
5528dbcf02cSchristos os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random,
5538dbcf02cSchristos TLS_RANDOM_LEN);
5548dbcf02cSchristos }
5558dbcf02cSchristos
556*0d69f216Schristos if (context) {
557*0d69f216Schristos pos = seed + 2 * TLS_RANDOM_LEN;
558*0d69f216Schristos WPA_PUT_BE16(pos, context_len);
559*0d69f216Schristos pos += 2;
560*0d69f216Schristos os_memcpy(pos, context, context_len);
561*0d69f216Schristos }
562*0d69f216Schristos
563*0d69f216Schristos res = tls_prf(conn->rl.tls_version,
56462a52023Schristos conn->master_secret, TLS_MASTER_SECRET_LEN,
565*0d69f216Schristos label, seed, seed_len, out, out_len);
566*0d69f216Schristos os_free(seed);
567*0d69f216Schristos return res;
5688dbcf02cSchristos }
5698dbcf02cSchristos
5708dbcf02cSchristos
5718dbcf02cSchristos /**
5728dbcf02cSchristos * tlsv1_client_get_cipher - Get current cipher name
5738dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
5748dbcf02cSchristos * @buf: Buffer for the cipher name
5758dbcf02cSchristos * @buflen: buf size
5768dbcf02cSchristos * Returns: 0 on success, -1 on failure
5778dbcf02cSchristos *
5788dbcf02cSchristos * Get the name of the currently used cipher.
5798dbcf02cSchristos */
tlsv1_client_get_cipher(struct tlsv1_client * conn,char * buf,size_t buflen)5808dbcf02cSchristos int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf,
5818dbcf02cSchristos size_t buflen)
5828dbcf02cSchristos {
5838dbcf02cSchristos char *cipher;
5848dbcf02cSchristos
5858dbcf02cSchristos switch (conn->rl.cipher_suite) {
5868dbcf02cSchristos case TLS_RSA_WITH_RC4_128_MD5:
5878dbcf02cSchristos cipher = "RC4-MD5";
5888dbcf02cSchristos break;
5898dbcf02cSchristos case TLS_RSA_WITH_RC4_128_SHA:
5908dbcf02cSchristos cipher = "RC4-SHA";
5918dbcf02cSchristos break;
5928dbcf02cSchristos case TLS_RSA_WITH_DES_CBC_SHA:
5938dbcf02cSchristos cipher = "DES-CBC-SHA";
5948dbcf02cSchristos break;
5958dbcf02cSchristos case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
5968dbcf02cSchristos cipher = "DES-CBC3-SHA";
5978dbcf02cSchristos break;
5989a53cbbeSchristos case TLS_DHE_RSA_WITH_DES_CBC_SHA:
5999a53cbbeSchristos cipher = "DHE-RSA-DES-CBC-SHA";
6009a53cbbeSchristos break;
6019a53cbbeSchristos case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
6029a53cbbeSchristos cipher = "DHE-RSA-DES-CBC3-SHA";
6039a53cbbeSchristos break;
6049a53cbbeSchristos case TLS_DH_anon_WITH_RC4_128_MD5:
6059a53cbbeSchristos cipher = "ADH-RC4-MD5";
6069a53cbbeSchristos break;
6079a53cbbeSchristos case TLS_DH_anon_WITH_DES_CBC_SHA:
6089a53cbbeSchristos cipher = "ADH-DES-SHA";
6099a53cbbeSchristos break;
6109a53cbbeSchristos case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
6119a53cbbeSchristos cipher = "ADH-DES-CBC3-SHA";
6129a53cbbeSchristos break;
6139a53cbbeSchristos case TLS_RSA_WITH_AES_128_CBC_SHA:
6149a53cbbeSchristos cipher = "AES-128-SHA";
6159a53cbbeSchristos break;
6169a53cbbeSchristos case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
6179a53cbbeSchristos cipher = "DHE-RSA-AES-128-SHA";
61862a52023Schristos break;
6198dbcf02cSchristos case TLS_DH_anon_WITH_AES_128_CBC_SHA:
6208dbcf02cSchristos cipher = "ADH-AES-128-SHA";
6218dbcf02cSchristos break;
6228dbcf02cSchristos case TLS_RSA_WITH_AES_256_CBC_SHA:
6238dbcf02cSchristos cipher = "AES-256-SHA";
6248dbcf02cSchristos break;
6259a53cbbeSchristos case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
6269a53cbbeSchristos cipher = "DHE-RSA-AES-256-SHA";
62762a52023Schristos break;
6289a53cbbeSchristos case TLS_DH_anon_WITH_AES_256_CBC_SHA:
6299a53cbbeSchristos cipher = "ADH-AES-256-SHA";
6308dbcf02cSchristos break;
63162a52023Schristos case TLS_RSA_WITH_AES_128_CBC_SHA256:
63262a52023Schristos cipher = "AES-128-SHA256";
63362a52023Schristos break;
6349a53cbbeSchristos case TLS_RSA_WITH_AES_256_CBC_SHA256:
6359a53cbbeSchristos cipher = "AES-256-SHA256";
6369a53cbbeSchristos break;
6379a53cbbeSchristos case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
6389a53cbbeSchristos cipher = "DHE-RSA-AES-128-SHA256";
6399a53cbbeSchristos break;
6409a53cbbeSchristos case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
6419a53cbbeSchristos cipher = "DHE-RSA-AES-256-SHA256";
6429a53cbbeSchristos break;
6439a53cbbeSchristos case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
6449a53cbbeSchristos cipher = "ADH-AES-128-SHA256";
6459a53cbbeSchristos break;
6469a53cbbeSchristos case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
6479a53cbbeSchristos cipher = "ADH-AES-256-SHA256";
6489a53cbbeSchristos break;
6498dbcf02cSchristos default:
6508dbcf02cSchristos return -1;
6518dbcf02cSchristos }
6528dbcf02cSchristos
6538dbcf02cSchristos if (os_strlcpy(buf, cipher, buflen) >= buflen)
6548dbcf02cSchristos return -1;
6558dbcf02cSchristos return 0;
6568dbcf02cSchristos }
6578dbcf02cSchristos
6588dbcf02cSchristos
6598dbcf02cSchristos /**
6608dbcf02cSchristos * tlsv1_client_shutdown - Shutdown TLS connection
6618dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
6628dbcf02cSchristos * Returns: 0 on success, -1 on failure
6638dbcf02cSchristos */
tlsv1_client_shutdown(struct tlsv1_client * conn)6648dbcf02cSchristos int tlsv1_client_shutdown(struct tlsv1_client *conn)
6658dbcf02cSchristos {
6668dbcf02cSchristos conn->state = CLIENT_HELLO;
6678dbcf02cSchristos
6688dbcf02cSchristos if (tls_verify_hash_init(&conn->verify) < 0) {
6698dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify "
6708dbcf02cSchristos "hash");
6718dbcf02cSchristos return -1;
6728dbcf02cSchristos }
6738dbcf02cSchristos
6748dbcf02cSchristos tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL);
6758dbcf02cSchristos tlsv1_record_change_write_cipher(&conn->rl);
6768dbcf02cSchristos tlsv1_record_change_read_cipher(&conn->rl);
6778dbcf02cSchristos
6788dbcf02cSchristos conn->certificate_requested = 0;
6798dbcf02cSchristos crypto_public_key_free(conn->server_rsa_key);
6808dbcf02cSchristos conn->server_rsa_key = NULL;
6818dbcf02cSchristos conn->session_resumed = 0;
6828dbcf02cSchristos
6838dbcf02cSchristos return 0;
6848dbcf02cSchristos }
6858dbcf02cSchristos
6868dbcf02cSchristos
6878dbcf02cSchristos /**
6888dbcf02cSchristos * tlsv1_client_resumed - Was session resumption used
6898dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
6908dbcf02cSchristos * Returns: 1 if current session used session resumption, 0 if not
6918dbcf02cSchristos */
tlsv1_client_resumed(struct tlsv1_client * conn)6928dbcf02cSchristos int tlsv1_client_resumed(struct tlsv1_client *conn)
6938dbcf02cSchristos {
6948dbcf02cSchristos return !!conn->session_resumed;
6958dbcf02cSchristos }
6968dbcf02cSchristos
6978dbcf02cSchristos
6988dbcf02cSchristos /**
6998dbcf02cSchristos * tlsv1_client_hello_ext - Set TLS extension for ClientHello
7008dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
7018dbcf02cSchristos * @ext_type: Extension type
7028dbcf02cSchristos * @data: Extension payload (%NULL to remove extension)
7038dbcf02cSchristos * @data_len: Extension payload length
7048dbcf02cSchristos * Returns: 0 on success, -1 on failure
7058dbcf02cSchristos */
tlsv1_client_hello_ext(struct tlsv1_client * conn,int ext_type,const u8 * data,size_t data_len)7068dbcf02cSchristos int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type,
7078dbcf02cSchristos const u8 *data, size_t data_len)
7088dbcf02cSchristos {
7098dbcf02cSchristos u8 *pos;
7108dbcf02cSchristos
7118dbcf02cSchristos conn->session_ticket_included = 0;
7128dbcf02cSchristos os_free(conn->client_hello_ext);
7138dbcf02cSchristos conn->client_hello_ext = NULL;
7148dbcf02cSchristos conn->client_hello_ext_len = 0;
7158dbcf02cSchristos
7168dbcf02cSchristos if (data == NULL || data_len == 0)
7178dbcf02cSchristos return 0;
7188dbcf02cSchristos
719928750b6Schristos pos = conn->client_hello_ext = os_malloc(4 + data_len);
7208dbcf02cSchristos if (pos == NULL)
7218dbcf02cSchristos return -1;
7228dbcf02cSchristos
7238dbcf02cSchristos WPA_PUT_BE16(pos, ext_type);
7248dbcf02cSchristos pos += 2;
7258dbcf02cSchristos WPA_PUT_BE16(pos, data_len);
7268dbcf02cSchristos pos += 2;
7278dbcf02cSchristos os_memcpy(pos, data, data_len);
728928750b6Schristos conn->client_hello_ext_len = 4 + data_len;
7298dbcf02cSchristos
7308dbcf02cSchristos if (ext_type == TLS_EXT_PAC_OPAQUE) {
7318dbcf02cSchristos conn->session_ticket_included = 1;
7328dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket");
7338dbcf02cSchristos }
7348dbcf02cSchristos
7358dbcf02cSchristos return 0;
7368dbcf02cSchristos }
7378dbcf02cSchristos
7388dbcf02cSchristos
7398dbcf02cSchristos /**
740928750b6Schristos * tlsv1_client_get_random - Get random data from TLS connection
7418dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
742928750b6Schristos * @keys: Structure of random data (filled on success)
7438dbcf02cSchristos * Returns: 0 on success, -1 on failure
7448dbcf02cSchristos */
tlsv1_client_get_random(struct tlsv1_client * conn,struct tls_random * keys)745928750b6Schristos int tlsv1_client_get_random(struct tlsv1_client *conn, struct tls_random *keys)
7468dbcf02cSchristos {
7478dbcf02cSchristos os_memset(keys, 0, sizeof(*keys));
7488dbcf02cSchristos if (conn->state == CLIENT_HELLO)
7498dbcf02cSchristos return -1;
7508dbcf02cSchristos
7518dbcf02cSchristos keys->client_random = conn->client_random;
7528dbcf02cSchristos keys->client_random_len = TLS_RANDOM_LEN;
7538dbcf02cSchristos
7548dbcf02cSchristos if (conn->state != SERVER_HELLO) {
7558dbcf02cSchristos keys->server_random = conn->server_random;
7568dbcf02cSchristos keys->server_random_len = TLS_RANDOM_LEN;
7578dbcf02cSchristos }
7588dbcf02cSchristos
7598dbcf02cSchristos return 0;
7608dbcf02cSchristos }
7618dbcf02cSchristos
7628dbcf02cSchristos
7638dbcf02cSchristos /**
7648dbcf02cSchristos * tlsv1_client_get_keyblock_size - Get TLS key_block size
7658dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
7668dbcf02cSchristos * Returns: Size of the key_block for the negotiated cipher suite or -1 on
7678dbcf02cSchristos * failure
7688dbcf02cSchristos */
tlsv1_client_get_keyblock_size(struct tlsv1_client * conn)7698dbcf02cSchristos int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn)
7708dbcf02cSchristos {
7718dbcf02cSchristos if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO)
7728dbcf02cSchristos return -1;
7738dbcf02cSchristos
7748dbcf02cSchristos return 2 * (conn->rl.hash_size + conn->rl.key_material_len +
7758dbcf02cSchristos conn->rl.iv_size);
7768dbcf02cSchristos }
7778dbcf02cSchristos
7788dbcf02cSchristos
7798dbcf02cSchristos /**
7808dbcf02cSchristos * tlsv1_client_set_cipher_list - Configure acceptable cipher suites
7818dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
7828dbcf02cSchristos * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
7838dbcf02cSchristos * (TLS_CIPHER_*).
7848dbcf02cSchristos * Returns: 0 on success, -1 on failure
7858dbcf02cSchristos */
tlsv1_client_set_cipher_list(struct tlsv1_client * conn,u8 * ciphers)7868dbcf02cSchristos int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers)
7878dbcf02cSchristos {
7888dbcf02cSchristos size_t count;
7898dbcf02cSchristos u16 *suites;
7908dbcf02cSchristos
7918dbcf02cSchristos /* TODO: implement proper configuration of cipher suites */
7928dbcf02cSchristos if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) {
7938dbcf02cSchristos count = 0;
7948dbcf02cSchristos suites = conn->cipher_suites;
79562a52023Schristos suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA256;
7968dbcf02cSchristos suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA;
79762a52023Schristos suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA256;
7988dbcf02cSchristos suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
7998dbcf02cSchristos suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA;
8008dbcf02cSchristos suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5;
8018dbcf02cSchristos suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA;
8028dbcf02cSchristos
8038dbcf02cSchristos /*
8048dbcf02cSchristos * Cisco AP (at least 350 and 1200 series) local authentication
8058dbcf02cSchristos * server does not know how to search cipher suites from the
8068dbcf02cSchristos * list and seem to require that the last entry in the list is
8078dbcf02cSchristos * the one that it wants to use. However, TLS specification
8088dbcf02cSchristos * requires the list to be in the client preference order. As a
8098dbcf02cSchristos * workaround, add anon-DH AES-128-SHA1 again at the end of the
8108dbcf02cSchristos * list to allow the Cisco code to find it.
8118dbcf02cSchristos */
8128dbcf02cSchristos suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA;
8138dbcf02cSchristos conn->num_cipher_suites = count;
8148dbcf02cSchristos }
8158dbcf02cSchristos
8168dbcf02cSchristos return 0;
8178dbcf02cSchristos }
8188dbcf02cSchristos
8198dbcf02cSchristos
8208dbcf02cSchristos /**
8218dbcf02cSchristos * tlsv1_client_set_cred - Set client credentials
8228dbcf02cSchristos * @conn: TLSv1 client connection data from tlsv1_client_init()
8238dbcf02cSchristos * @cred: Credentials from tlsv1_cred_alloc()
8248dbcf02cSchristos * Returns: 0 on success, -1 on failure
8258dbcf02cSchristos *
8268dbcf02cSchristos * On success, the client takes ownership of the credentials block and caller
8278dbcf02cSchristos * must not free it. On failure, caller is responsible for freeing the
8288dbcf02cSchristos * credential block.
8298dbcf02cSchristos */
tlsv1_client_set_cred(struct tlsv1_client * conn,struct tlsv1_credentials * cred)8308dbcf02cSchristos int tlsv1_client_set_cred(struct tlsv1_client *conn,
8318dbcf02cSchristos struct tlsv1_credentials *cred)
8328dbcf02cSchristos {
8338dbcf02cSchristos tlsv1_cred_free(conn->cred);
8348dbcf02cSchristos conn->cred = cred;
8358dbcf02cSchristos return 0;
8368dbcf02cSchristos }
8378dbcf02cSchristos
8388dbcf02cSchristos
839928750b6Schristos /**
840928750b6Schristos * tlsv1_client_set_flags - Set connection flags
841928750b6Schristos * @conn: TLSv1 client connection data from tlsv1_client_init()
842928750b6Schristos * @flags: TLS_CONN_* bitfield
843928750b6Schristos */
tlsv1_client_set_flags(struct tlsv1_client * conn,unsigned int flags)844928750b6Schristos void tlsv1_client_set_flags(struct tlsv1_client *conn, unsigned int flags)
84542669be3Schristos {
846928750b6Schristos conn->flags = flags;
84742669be3Schristos }
84842669be3Schristos
84942669be3Schristos
tlsv1_client_set_session_ticket_cb(struct tlsv1_client * conn,tlsv1_client_session_ticket_cb cb,void * ctx)8508dbcf02cSchristos void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn,
8518dbcf02cSchristos tlsv1_client_session_ticket_cb cb,
8528dbcf02cSchristos void *ctx)
8538dbcf02cSchristos {
8548dbcf02cSchristos wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)",
8558dbcf02cSchristos cb, ctx);
8568dbcf02cSchristos conn->session_ticket_cb = cb;
8578dbcf02cSchristos conn->session_ticket_cb_ctx = ctx;
8588dbcf02cSchristos }
859928750b6Schristos
860928750b6Schristos
tlsv1_client_set_cb(struct tlsv1_client * conn,void (* event_cb)(void * ctx,enum tls_event ev,union tls_event_data * data),void * cb_ctx,int cert_in_cb)861928750b6Schristos void tlsv1_client_set_cb(struct tlsv1_client *conn,
862928750b6Schristos void (*event_cb)(void *ctx, enum tls_event ev,
863928750b6Schristos union tls_event_data *data),
864928750b6Schristos void *cb_ctx,
865928750b6Schristos int cert_in_cb)
866928750b6Schristos {
867928750b6Schristos conn->event_cb = event_cb;
868928750b6Schristos conn->cb_ctx = cb_ctx;
869928750b6Schristos conn->cert_in_cb = !!cert_in_cb;
870928750b6Schristos }
871928750b6Schristos
872928750b6Schristos
tlsv1_client_get_version(struct tlsv1_client * conn,char * buf,size_t buflen)873928750b6Schristos int tlsv1_client_get_version(struct tlsv1_client *conn, char *buf,
874928750b6Schristos size_t buflen)
875928750b6Schristos {
876928750b6Schristos if (!conn)
877928750b6Schristos return -1;
878928750b6Schristos switch (conn->rl.tls_version) {
879928750b6Schristos case TLS_VERSION_1:
880928750b6Schristos os_strlcpy(buf, "TLSv1", buflen);
881928750b6Schristos break;
882928750b6Schristos case TLS_VERSION_1_1:
883928750b6Schristos os_strlcpy(buf, "TLSv1.1", buflen);
884928750b6Schristos break;
885928750b6Schristos case TLS_VERSION_1_2:
886928750b6Schristos os_strlcpy(buf, "TLSv1.2", buflen);
887928750b6Schristos break;
888928750b6Schristos default:
889928750b6Schristos return -1;
890928750b6Schristos }
891928750b6Schristos
892928750b6Schristos return 0;
893928750b6Schristos }
894