1189251Ssam/* 2252726Srpaulo * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246) 3252726Srpaulo * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> 4189251Ssam * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7189251Ssam */ 8189251Ssam 9189251Ssam#include "includes.h" 10189251Ssam 11189251Ssam#include "common.h" 12214734Srpaulo#include "crypto/sha1.h" 13214734Srpaulo#include "crypto/tls.h" 14189251Ssam#include "tlsv1_common.h" 15189251Ssam#include "tlsv1_record.h" 16189251Ssam#include "tlsv1_server.h" 17189251Ssam#include "tlsv1_server_i.h" 18189251Ssam 19189251Ssam/* TODO: 20189251Ssam * Support for a message fragmented across several records (RFC 2246, 6.2.1) 21189251Ssam */ 22189251Ssam 23189251Ssam 24189251Ssamvoid tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description) 25189251Ssam{ 26189251Ssam conn->alert_level = level; 27189251Ssam conn->alert_description = description; 28189251Ssam} 29189251Ssam 30189251Ssam 31189251Ssamint tlsv1_server_derive_keys(struct tlsv1_server *conn, 32189251Ssam const u8 *pre_master_secret, 33189251Ssam size_t pre_master_secret_len) 34189251Ssam{ 35189251Ssam u8 seed[2 * TLS_RANDOM_LEN]; 36189251Ssam u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; 37189251Ssam u8 *pos; 38189251Ssam size_t key_block_len; 39189251Ssam 40189251Ssam if (pre_master_secret) { 41189251Ssam wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", 42189251Ssam pre_master_secret, pre_master_secret_len); 43189251Ssam os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); 44189251Ssam os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, 45189251Ssam TLS_RANDOM_LEN); 46252726Srpaulo if (tls_prf(conn->rl.tls_version, 47252726Srpaulo pre_master_secret, pre_master_secret_len, 48189251Ssam "master secret", seed, 2 * TLS_RANDOM_LEN, 49189251Ssam conn->master_secret, TLS_MASTER_SECRET_LEN)) { 50189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " 51189251Ssam "master_secret"); 52189251Ssam return -1; 53189251Ssam } 54189251Ssam wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", 55189251Ssam conn->master_secret, TLS_MASTER_SECRET_LEN); 56189251Ssam } 57189251Ssam 58189251Ssam os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); 59189251Ssam os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); 60189251Ssam key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + 61189251Ssam conn->rl.iv_size); 62252726Srpaulo if (tls_prf(conn->rl.tls_version, 63252726Srpaulo conn->master_secret, TLS_MASTER_SECRET_LEN, 64189251Ssam "key expansion", seed, 2 * TLS_RANDOM_LEN, 65189251Ssam key_block, key_block_len)) { 66189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); 67189251Ssam return -1; 68189251Ssam } 69189251Ssam wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", 70189251Ssam key_block, key_block_len); 71189251Ssam 72189251Ssam pos = key_block; 73189251Ssam 74189251Ssam /* client_write_MAC_secret */ 75189251Ssam os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); 76189251Ssam pos += conn->rl.hash_size; 77189251Ssam /* server_write_MAC_secret */ 78189251Ssam os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); 79189251Ssam pos += conn->rl.hash_size; 80189251Ssam 81189251Ssam /* client_write_key */ 82189251Ssam os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); 83189251Ssam pos += conn->rl.key_material_len; 84189251Ssam /* server_write_key */ 85189251Ssam os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); 86189251Ssam pos += conn->rl.key_material_len; 87189251Ssam 88189251Ssam /* client_write_IV */ 89189251Ssam os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); 90189251Ssam pos += conn->rl.iv_size; 91189251Ssam /* server_write_IV */ 92189251Ssam os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); 93189251Ssam pos += conn->rl.iv_size; 94189251Ssam 95189251Ssam return 0; 96189251Ssam} 97189251Ssam 98189251Ssam 99189251Ssam/** 100189251Ssam * tlsv1_server_handshake - Process TLS handshake 101189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 102189251Ssam * @in_data: Input data from TLS peer 103189251Ssam * @in_len: Input data length 104189251Ssam * @out_len: Length of the output buffer. 105189251Ssam * Returns: Pointer to output data, %NULL on failure 106189251Ssam */ 107189251Ssamu8 * tlsv1_server_handshake(struct tlsv1_server *conn, 108189251Ssam const u8 *in_data, size_t in_len, 109189251Ssam size_t *out_len) 110189251Ssam{ 111189251Ssam const u8 *pos, *end; 112189251Ssam u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; 113189251Ssam size_t in_msg_len; 114252726Srpaulo int used; 115189251Ssam 116189251Ssam if (in_data == NULL || in_len == 0) { 117189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: No input data to server"); 118189251Ssam return NULL; 119189251Ssam } 120189251Ssam 121189251Ssam pos = in_data; 122189251Ssam end = in_data + in_len; 123189251Ssam in_msg = os_malloc(in_len); 124189251Ssam if (in_msg == NULL) 125189251Ssam return NULL; 126189251Ssam 127189251Ssam /* Each received packet may include multiple records */ 128189251Ssam while (pos < end) { 129189251Ssam in_msg_len = in_len; 130252726Srpaulo used = tlsv1_record_receive(&conn->rl, pos, end - pos, 131252726Srpaulo in_msg, &in_msg_len, &alert); 132252726Srpaulo if (used < 0) { 133189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Processing received " 134189251Ssam "record failed"); 135189251Ssam tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 136189251Ssam goto failed; 137189251Ssam } 138252726Srpaulo if (used == 0) { 139252726Srpaulo /* need more data */ 140252726Srpaulo wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not " 141252726Srpaulo "yet supported"); 142252726Srpaulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 143252726Srpaulo goto failed; 144252726Srpaulo } 145189251Ssam ct = pos[0]; 146189251Ssam 147189251Ssam in_pos = in_msg; 148189251Ssam in_end = in_msg + in_msg_len; 149189251Ssam 150189251Ssam /* Each received record may include multiple messages of the 151189251Ssam * same ContentType. */ 152189251Ssam while (in_pos < in_end) { 153189251Ssam in_msg_len = in_end - in_pos; 154189251Ssam if (tlsv1_server_process_handshake(conn, ct, in_pos, 155189251Ssam &in_msg_len) < 0) 156189251Ssam goto failed; 157189251Ssam in_pos += in_msg_len; 158189251Ssam } 159189251Ssam 160252726Srpaulo pos += used; 161189251Ssam } 162189251Ssam 163189251Ssam os_free(in_msg); 164189251Ssam in_msg = NULL; 165189251Ssam 166189251Ssam msg = tlsv1_server_handshake_write(conn, out_len); 167189251Ssam 168189251Ssamfailed: 169189251Ssam os_free(in_msg); 170189251Ssam if (conn->alert_level) { 171189251Ssam if (conn->state == FAILED) { 172189251Ssam /* Avoid alert loops */ 173189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop"); 174189251Ssam os_free(msg); 175189251Ssam return NULL; 176189251Ssam } 177189251Ssam conn->state = FAILED; 178189251Ssam os_free(msg); 179189251Ssam msg = tlsv1_server_send_alert(conn, conn->alert_level, 180189251Ssam conn->alert_description, 181189251Ssam out_len); 182189251Ssam } 183189251Ssam 184189251Ssam return msg; 185189251Ssam} 186189251Ssam 187189251Ssam 188189251Ssam/** 189189251Ssam * tlsv1_server_encrypt - Encrypt data into TLS tunnel 190189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 191189251Ssam * @in_data: Pointer to plaintext data to be encrypted 192189251Ssam * @in_len: Input buffer length 193189251Ssam * @out_data: Pointer to output buffer (encrypted TLS data) 194189251Ssam * @out_len: Maximum out_data length 195189251Ssam * Returns: Number of bytes written to out_data, -1 on failure 196189251Ssam * 197189251Ssam * This function is used after TLS handshake has been completed successfully to 198189251Ssam * send data in the encrypted tunnel. 199189251Ssam */ 200189251Ssamint tlsv1_server_encrypt(struct tlsv1_server *conn, 201189251Ssam const u8 *in_data, size_t in_len, 202189251Ssam u8 *out_data, size_t out_len) 203189251Ssam{ 204189251Ssam size_t rlen; 205189251Ssam 206189251Ssam wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", 207189251Ssam in_data, in_len); 208189251Ssam 209189251Ssam if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, 210252726Srpaulo out_data, out_len, in_data, in_len, &rlen) < 0) { 211189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 212189251Ssam tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 213189251Ssam TLS_ALERT_INTERNAL_ERROR); 214189251Ssam return -1; 215189251Ssam } 216189251Ssam 217189251Ssam return rlen; 218189251Ssam} 219189251Ssam 220189251Ssam 221189251Ssam/** 222189251Ssam * tlsv1_server_decrypt - Decrypt data from TLS tunnel 223189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 224189251Ssam * @in_data: Pointer to input buffer (encrypted TLS data) 225189251Ssam * @in_len: Input buffer length 226189251Ssam * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) 227189251Ssam * @out_len: Maximum out_data length 228189251Ssam * Returns: Number of bytes written to out_data, -1 on failure 229189251Ssam * 230189251Ssam * This function is used after TLS handshake has been completed successfully to 231189251Ssam * receive data from the encrypted tunnel. 232189251Ssam */ 233189251Ssamint tlsv1_server_decrypt(struct tlsv1_server *conn, 234189251Ssam const u8 *in_data, size_t in_len, 235189251Ssam u8 *out_data, size_t out_len) 236189251Ssam{ 237189251Ssam const u8 *in_end, *pos; 238252726Srpaulo int used; 239252726Srpaulo u8 alert, *out_end, *out_pos, ct; 240189251Ssam size_t olen; 241189251Ssam 242189251Ssam pos = in_data; 243189251Ssam in_end = in_data + in_len; 244189251Ssam out_pos = out_data; 245189251Ssam out_end = out_data + out_len; 246189251Ssam 247189251Ssam while (pos < in_end) { 248252726Srpaulo ct = pos[0]; 249252726Srpaulo olen = out_end - out_pos; 250252726Srpaulo used = tlsv1_record_receive(&conn->rl, pos, in_end - pos, 251252726Srpaulo out_pos, &olen, &alert); 252252726Srpaulo if (used < 0) { 253252726Srpaulo wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " 254252726Srpaulo "failed"); 255252726Srpaulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 256252726Srpaulo return -1; 257252726Srpaulo } 258252726Srpaulo if (used == 0) { 259252726Srpaulo /* need more data */ 260252726Srpaulo wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not " 261252726Srpaulo "yet supported"); 262252726Srpaulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 263252726Srpaulo return -1; 264252726Srpaulo } 265252726Srpaulo 266252726Srpaulo if (ct == TLS_CONTENT_TYPE_ALERT) { 267252726Srpaulo if (olen < 2) { 268252726Srpaulo wpa_printf(MSG_DEBUG, "TLSv1: Alert " 269252726Srpaulo "underflow"); 270252726Srpaulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 271252726Srpaulo TLS_ALERT_DECODE_ERROR); 272252726Srpaulo return -1; 273252726Srpaulo } 274252726Srpaulo wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", 275252726Srpaulo out_pos[0], out_pos[1]); 276252726Srpaulo if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) { 277252726Srpaulo /* Continue processing */ 278252726Srpaulo pos += used; 279252726Srpaulo continue; 280252726Srpaulo } 281252726Srpaulo 282252726Srpaulo tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 283252726Srpaulo out_pos[1]); 284252726Srpaulo return -1; 285252726Srpaulo } 286252726Srpaulo 287252726Srpaulo if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { 288189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " 289189251Ssam "0x%x", pos[0]); 290189251Ssam tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 291189251Ssam TLS_ALERT_UNEXPECTED_MESSAGE); 292189251Ssam return -1; 293189251Ssam } 294189251Ssam 295189251Ssam out_pos += olen; 296189251Ssam if (out_pos > out_end) { 297189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " 298189251Ssam "for processing the received record"); 299189251Ssam tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, 300189251Ssam TLS_ALERT_INTERNAL_ERROR); 301189251Ssam return -1; 302189251Ssam } 303189251Ssam 304252726Srpaulo pos += used; 305189251Ssam } 306189251Ssam 307189251Ssam return out_pos - out_data; 308189251Ssam} 309189251Ssam 310189251Ssam 311189251Ssam/** 312189251Ssam * tlsv1_server_global_init - Initialize TLSv1 server 313189251Ssam * Returns: 0 on success, -1 on failure 314189251Ssam * 315189251Ssam * This function must be called before using any other TLSv1 server functions. 316189251Ssam */ 317189251Ssamint tlsv1_server_global_init(void) 318189251Ssam{ 319189251Ssam return crypto_global_init(); 320189251Ssam} 321189251Ssam 322189251Ssam 323189251Ssam/** 324189251Ssam * tlsv1_server_global_deinit - Deinitialize TLSv1 server 325189251Ssam * 326189251Ssam * This function can be used to deinitialize the TLSv1 server that was 327189251Ssam * initialized by calling tlsv1_server_global_init(). No TLSv1 server functions 328189251Ssam * can be called after this before calling tlsv1_server_global_init() again. 329189251Ssam */ 330189251Ssamvoid tlsv1_server_global_deinit(void) 331189251Ssam{ 332189251Ssam crypto_global_deinit(); 333189251Ssam} 334189251Ssam 335189251Ssam 336189251Ssam/** 337189251Ssam * tlsv1_server_init - Initialize TLSv1 server connection 338189251Ssam * @cred: Pointer to server credentials from tlsv1_server_cred_alloc() 339189251Ssam * Returns: Pointer to TLSv1 server connection data or %NULL on failure 340189251Ssam */ 341189251Ssamstruct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred) 342189251Ssam{ 343189251Ssam struct tlsv1_server *conn; 344189251Ssam size_t count; 345189251Ssam u16 *suites; 346189251Ssam 347189251Ssam conn = os_zalloc(sizeof(*conn)); 348189251Ssam if (conn == NULL) 349189251Ssam return NULL; 350189251Ssam 351189251Ssam conn->cred = cred; 352189251Ssam 353189251Ssam conn->state = CLIENT_HELLO; 354189251Ssam 355189251Ssam if (tls_verify_hash_init(&conn->verify) < 0) { 356189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " 357189251Ssam "hash"); 358189251Ssam os_free(conn); 359189251Ssam return NULL; 360189251Ssam } 361189251Ssam 362189251Ssam count = 0; 363189251Ssam suites = conn->cipher_suites; 364189251Ssam suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; 365189251Ssam suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; 366189251Ssam suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; 367189251Ssam suites[count++] = TLS_RSA_WITH_RC4_128_SHA; 368189251Ssam suites[count++] = TLS_RSA_WITH_RC4_128_MD5; 369189251Ssam conn->num_cipher_suites = count; 370189251Ssam 371189251Ssam return conn; 372189251Ssam} 373189251Ssam 374189251Ssam 375189251Ssamstatic void tlsv1_server_clear_data(struct tlsv1_server *conn) 376189251Ssam{ 377189251Ssam tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); 378189251Ssam tlsv1_record_change_write_cipher(&conn->rl); 379189251Ssam tlsv1_record_change_read_cipher(&conn->rl); 380189251Ssam tls_verify_hash_free(&conn->verify); 381189251Ssam 382189251Ssam crypto_public_key_free(conn->client_rsa_key); 383189251Ssam conn->client_rsa_key = NULL; 384189251Ssam 385189251Ssam os_free(conn->session_ticket); 386189251Ssam conn->session_ticket = NULL; 387189251Ssam conn->session_ticket_len = 0; 388189251Ssam conn->use_session_ticket = 0; 389189251Ssam 390189251Ssam os_free(conn->dh_secret); 391189251Ssam conn->dh_secret = NULL; 392189251Ssam conn->dh_secret_len = 0; 393189251Ssam} 394189251Ssam 395189251Ssam 396189251Ssam/** 397189251Ssam * tlsv1_server_deinit - Deinitialize TLSv1 server connection 398189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 399189251Ssam */ 400189251Ssamvoid tlsv1_server_deinit(struct tlsv1_server *conn) 401189251Ssam{ 402189251Ssam tlsv1_server_clear_data(conn); 403189251Ssam os_free(conn); 404189251Ssam} 405189251Ssam 406189251Ssam 407189251Ssam/** 408189251Ssam * tlsv1_server_established - Check whether connection has been established 409189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 410189251Ssam * Returns: 1 if connection is established, 0 if not 411189251Ssam */ 412189251Ssamint tlsv1_server_established(struct tlsv1_server *conn) 413189251Ssam{ 414189251Ssam return conn->state == ESTABLISHED; 415189251Ssam} 416189251Ssam 417189251Ssam 418189251Ssam/** 419189251Ssam * tlsv1_server_prf - Use TLS-PRF to derive keying material 420189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 421189251Ssam * @label: Label (e.g., description of the key) for PRF 422189251Ssam * @server_random_first: seed is 0 = client_random|server_random, 423189251Ssam * 1 = server_random|client_random 424189251Ssam * @out: Buffer for output data from TLS-PRF 425189251Ssam * @out_len: Length of the output buffer 426189251Ssam * Returns: 0 on success, -1 on failure 427189251Ssam */ 428189251Ssamint tlsv1_server_prf(struct tlsv1_server *conn, const char *label, 429189251Ssam int server_random_first, u8 *out, size_t out_len) 430189251Ssam{ 431189251Ssam u8 seed[2 * TLS_RANDOM_LEN]; 432189251Ssam 433189251Ssam if (conn->state != ESTABLISHED) 434189251Ssam return -1; 435189251Ssam 436189251Ssam if (server_random_first) { 437189251Ssam os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); 438189251Ssam os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, 439189251Ssam TLS_RANDOM_LEN); 440189251Ssam } else { 441189251Ssam os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); 442189251Ssam os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, 443189251Ssam TLS_RANDOM_LEN); 444189251Ssam } 445189251Ssam 446252726Srpaulo return tls_prf(conn->rl.tls_version, 447252726Srpaulo conn->master_secret, TLS_MASTER_SECRET_LEN, 448189251Ssam label, seed, 2 * TLS_RANDOM_LEN, out, out_len); 449189251Ssam} 450189251Ssam 451189251Ssam 452189251Ssam/** 453189251Ssam * tlsv1_server_get_cipher - Get current cipher name 454189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 455189251Ssam * @buf: Buffer for the cipher name 456189251Ssam * @buflen: buf size 457189251Ssam * Returns: 0 on success, -1 on failure 458189251Ssam * 459189251Ssam * Get the name of the currently used cipher. 460189251Ssam */ 461189251Ssamint tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, 462189251Ssam size_t buflen) 463189251Ssam{ 464189251Ssam char *cipher; 465189251Ssam 466189251Ssam switch (conn->rl.cipher_suite) { 467189251Ssam case TLS_RSA_WITH_RC4_128_MD5: 468189251Ssam cipher = "RC4-MD5"; 469189251Ssam break; 470189251Ssam case TLS_RSA_WITH_RC4_128_SHA: 471189251Ssam cipher = "RC4-SHA"; 472189251Ssam break; 473189251Ssam case TLS_RSA_WITH_DES_CBC_SHA: 474189251Ssam cipher = "DES-CBC-SHA"; 475189251Ssam break; 476189251Ssam case TLS_RSA_WITH_3DES_EDE_CBC_SHA: 477189251Ssam cipher = "DES-CBC3-SHA"; 478189251Ssam break; 479189251Ssam case TLS_DH_anon_WITH_AES_128_CBC_SHA: 480189251Ssam cipher = "ADH-AES-128-SHA"; 481189251Ssam break; 482189251Ssam case TLS_RSA_WITH_AES_256_CBC_SHA: 483189251Ssam cipher = "AES-256-SHA"; 484189251Ssam break; 485189251Ssam case TLS_RSA_WITH_AES_128_CBC_SHA: 486189251Ssam cipher = "AES-128-SHA"; 487189251Ssam break; 488189251Ssam default: 489189251Ssam return -1; 490189251Ssam } 491189251Ssam 492189251Ssam if (os_strlcpy(buf, cipher, buflen) >= buflen) 493189251Ssam return -1; 494189251Ssam return 0; 495189251Ssam} 496189251Ssam 497189251Ssam 498189251Ssam/** 499189251Ssam * tlsv1_server_shutdown - Shutdown TLS connection 500189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 501189251Ssam * Returns: 0 on success, -1 on failure 502189251Ssam */ 503189251Ssamint tlsv1_server_shutdown(struct tlsv1_server *conn) 504189251Ssam{ 505189251Ssam conn->state = CLIENT_HELLO; 506189251Ssam 507189251Ssam if (tls_verify_hash_init(&conn->verify) < 0) { 508189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " 509189251Ssam "hash"); 510189251Ssam return -1; 511189251Ssam } 512189251Ssam 513189251Ssam tlsv1_server_clear_data(conn); 514189251Ssam 515189251Ssam return 0; 516189251Ssam} 517189251Ssam 518189251Ssam 519189251Ssam/** 520189251Ssam * tlsv1_server_resumed - Was session resumption used 521189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 522189251Ssam * Returns: 1 if current session used session resumption, 0 if not 523189251Ssam */ 524189251Ssamint tlsv1_server_resumed(struct tlsv1_server *conn) 525189251Ssam{ 526189251Ssam return 0; 527189251Ssam} 528189251Ssam 529189251Ssam 530189251Ssam/** 531189251Ssam * tlsv1_server_get_keys - Get master key and random data from TLS connection 532189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 533189251Ssam * @keys: Structure of key/random data (filled on success) 534189251Ssam * Returns: 0 on success, -1 on failure 535189251Ssam */ 536189251Ssamint tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys) 537189251Ssam{ 538189251Ssam os_memset(keys, 0, sizeof(*keys)); 539189251Ssam if (conn->state == CLIENT_HELLO) 540189251Ssam return -1; 541189251Ssam 542189251Ssam keys->client_random = conn->client_random; 543189251Ssam keys->client_random_len = TLS_RANDOM_LEN; 544189251Ssam 545189251Ssam if (conn->state != SERVER_HELLO) { 546189251Ssam keys->server_random = conn->server_random; 547189251Ssam keys->server_random_len = TLS_RANDOM_LEN; 548189251Ssam keys->master_key = conn->master_secret; 549189251Ssam keys->master_key_len = TLS_MASTER_SECRET_LEN; 550189251Ssam } 551189251Ssam 552189251Ssam return 0; 553189251Ssam} 554189251Ssam 555189251Ssam 556189251Ssam/** 557189251Ssam * tlsv1_server_get_keyblock_size - Get TLS key_block size 558189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 559189251Ssam * Returns: Size of the key_block for the negotiated cipher suite or -1 on 560189251Ssam * failure 561189251Ssam */ 562189251Ssamint tlsv1_server_get_keyblock_size(struct tlsv1_server *conn) 563189251Ssam{ 564189251Ssam if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) 565189251Ssam return -1; 566189251Ssam 567189251Ssam return 2 * (conn->rl.hash_size + conn->rl.key_material_len + 568189251Ssam conn->rl.iv_size); 569189251Ssam} 570189251Ssam 571189251Ssam 572189251Ssam/** 573189251Ssam * tlsv1_server_set_cipher_list - Configure acceptable cipher suites 574189251Ssam * @conn: TLSv1 server connection data from tlsv1_server_init() 575189251Ssam * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers 576189251Ssam * (TLS_CIPHER_*). 577189251Ssam * Returns: 0 on success, -1 on failure 578189251Ssam */ 579189251Ssamint tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers) 580189251Ssam{ 581189251Ssam size_t count; 582189251Ssam u16 *suites; 583189251Ssam 584189251Ssam /* TODO: implement proper configuration of cipher suites */ 585189251Ssam if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { 586189251Ssam count = 0; 587189251Ssam suites = conn->cipher_suites; 588189251Ssam suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; 589189251Ssam suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; 590189251Ssam suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; 591189251Ssam suites[count++] = TLS_RSA_WITH_RC4_128_SHA; 592189251Ssam suites[count++] = TLS_RSA_WITH_RC4_128_MD5; 593189251Ssam suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; 594189251Ssam suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; 595189251Ssam suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; 596189251Ssam suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; 597189251Ssam suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; 598189251Ssam conn->num_cipher_suites = count; 599189251Ssam } 600189251Ssam 601189251Ssam return 0; 602189251Ssam} 603189251Ssam 604189251Ssam 605189251Ssamint tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer) 606189251Ssam{ 607189251Ssam conn->verify_peer = verify_peer; 608189251Ssam return 0; 609189251Ssam} 610189251Ssam 611189251Ssam 612189251Ssamvoid tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, 613189251Ssam tlsv1_server_session_ticket_cb cb, 614189251Ssam void *ctx) 615189251Ssam{ 616189251Ssam wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", 617189251Ssam cb, ctx); 618189251Ssam conn->session_ticket_cb = cb; 619189251Ssam conn->session_ticket_cb_ctx = ctx; 620189251Ssam} 621