1*6d49e1aeSJan Lentfer /* 2*6d49e1aeSJan Lentfer * TLSv1 client (RFC 2246) 3*6d49e1aeSJan Lentfer * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> 4*6d49e1aeSJan Lentfer * 5*6d49e1aeSJan Lentfer * This program is free software; you can redistribute it and/or modify 6*6d49e1aeSJan Lentfer * it under the terms of the GNU General Public License version 2 as 7*6d49e1aeSJan Lentfer * published by the Free Software Foundation. 8*6d49e1aeSJan Lentfer * 9*6d49e1aeSJan Lentfer * Alternatively, this software may be distributed under the terms of BSD 10*6d49e1aeSJan Lentfer * license. 11*6d49e1aeSJan Lentfer * 12*6d49e1aeSJan Lentfer * See README and COPYING for more details. 13*6d49e1aeSJan Lentfer */ 14*6d49e1aeSJan Lentfer 15*6d49e1aeSJan Lentfer #include "includes.h" 16*6d49e1aeSJan Lentfer 17*6d49e1aeSJan Lentfer #include "common.h" 18*6d49e1aeSJan Lentfer #include "sha1.h" 19*6d49e1aeSJan Lentfer #include "tls.h" 20*6d49e1aeSJan Lentfer #include "tlsv1_common.h" 21*6d49e1aeSJan Lentfer #include "tlsv1_record.h" 22*6d49e1aeSJan Lentfer #include "tlsv1_client.h" 23*6d49e1aeSJan Lentfer #include "tlsv1_client_i.h" 24*6d49e1aeSJan Lentfer 25*6d49e1aeSJan Lentfer /* TODO: 26*6d49e1aeSJan Lentfer * Support for a message fragmented across several records (RFC 2246, 6.2.1) 27*6d49e1aeSJan Lentfer */ 28*6d49e1aeSJan Lentfer 29*6d49e1aeSJan Lentfer 30*6d49e1aeSJan Lentfer void tls_alert(struct tlsv1_client *conn, u8 level, u8 description) 31*6d49e1aeSJan Lentfer { 32*6d49e1aeSJan Lentfer conn->alert_level = level; 33*6d49e1aeSJan Lentfer conn->alert_description = description; 34*6d49e1aeSJan Lentfer } 35*6d49e1aeSJan Lentfer 36*6d49e1aeSJan Lentfer 37*6d49e1aeSJan Lentfer void tlsv1_client_free_dh(struct tlsv1_client *conn) 38*6d49e1aeSJan Lentfer { 39*6d49e1aeSJan Lentfer os_free(conn->dh_p); 40*6d49e1aeSJan Lentfer os_free(conn->dh_g); 41*6d49e1aeSJan Lentfer os_free(conn->dh_ys); 42*6d49e1aeSJan Lentfer conn->dh_p = conn->dh_g = conn->dh_ys = NULL; 43*6d49e1aeSJan Lentfer } 44*6d49e1aeSJan Lentfer 45*6d49e1aeSJan Lentfer 46*6d49e1aeSJan Lentfer int tls_derive_pre_master_secret(u8 *pre_master_secret) 47*6d49e1aeSJan Lentfer { 48*6d49e1aeSJan Lentfer WPA_PUT_BE16(pre_master_secret, TLS_VERSION); 49*6d49e1aeSJan Lentfer if (os_get_random(pre_master_secret + 2, 50*6d49e1aeSJan Lentfer TLS_PRE_MASTER_SECRET_LEN - 2)) 51*6d49e1aeSJan Lentfer return -1; 52*6d49e1aeSJan Lentfer return 0; 53*6d49e1aeSJan Lentfer } 54*6d49e1aeSJan Lentfer 55*6d49e1aeSJan Lentfer 56*6d49e1aeSJan Lentfer int tls_derive_keys(struct tlsv1_client *conn, 57*6d49e1aeSJan Lentfer const u8 *pre_master_secret, size_t pre_master_secret_len) 58*6d49e1aeSJan Lentfer { 59*6d49e1aeSJan Lentfer u8 seed[2 * TLS_RANDOM_LEN]; 60*6d49e1aeSJan Lentfer u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; 61*6d49e1aeSJan Lentfer u8 *pos; 62*6d49e1aeSJan Lentfer size_t key_block_len; 63*6d49e1aeSJan Lentfer 64*6d49e1aeSJan Lentfer if (pre_master_secret) { 65*6d49e1aeSJan Lentfer wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", 66*6d49e1aeSJan Lentfer pre_master_secret, pre_master_secret_len); 67*6d49e1aeSJan Lentfer os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); 68*6d49e1aeSJan Lentfer os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, 69*6d49e1aeSJan Lentfer TLS_RANDOM_LEN); 70*6d49e1aeSJan Lentfer if (tls_prf(pre_master_secret, pre_master_secret_len, 71*6d49e1aeSJan Lentfer "master secret", seed, 2 * TLS_RANDOM_LEN, 72*6d49e1aeSJan Lentfer conn->master_secret, TLS_MASTER_SECRET_LEN)) { 73*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " 74*6d49e1aeSJan Lentfer "master_secret"); 75*6d49e1aeSJan Lentfer return -1; 76*6d49e1aeSJan Lentfer } 77*6d49e1aeSJan Lentfer wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", 78*6d49e1aeSJan Lentfer conn->master_secret, TLS_MASTER_SECRET_LEN); 79*6d49e1aeSJan Lentfer } 80*6d49e1aeSJan Lentfer 81*6d49e1aeSJan Lentfer os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); 82*6d49e1aeSJan Lentfer os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); 83*6d49e1aeSJan Lentfer key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + 84*6d49e1aeSJan Lentfer conn->rl.iv_size); 85*6d49e1aeSJan Lentfer if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, 86*6d49e1aeSJan Lentfer "key expansion", seed, 2 * TLS_RANDOM_LEN, 87*6d49e1aeSJan Lentfer key_block, key_block_len)) { 88*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); 89*6d49e1aeSJan Lentfer return -1; 90*6d49e1aeSJan Lentfer } 91*6d49e1aeSJan Lentfer wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", 92*6d49e1aeSJan Lentfer key_block, key_block_len); 93*6d49e1aeSJan Lentfer 94*6d49e1aeSJan Lentfer pos = key_block; 95*6d49e1aeSJan Lentfer 96*6d49e1aeSJan Lentfer /* client_write_MAC_secret */ 97*6d49e1aeSJan Lentfer os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); 98*6d49e1aeSJan Lentfer pos += conn->rl.hash_size; 99*6d49e1aeSJan Lentfer /* server_write_MAC_secret */ 100*6d49e1aeSJan Lentfer os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); 101*6d49e1aeSJan Lentfer pos += conn->rl.hash_size; 102*6d49e1aeSJan Lentfer 103*6d49e1aeSJan Lentfer /* client_write_key */ 104*6d49e1aeSJan Lentfer os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); 105*6d49e1aeSJan Lentfer pos += conn->rl.key_material_len; 106*6d49e1aeSJan Lentfer /* server_write_key */ 107*6d49e1aeSJan Lentfer os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); 108*6d49e1aeSJan Lentfer pos += conn->rl.key_material_len; 109*6d49e1aeSJan Lentfer 110*6d49e1aeSJan Lentfer /* client_write_IV */ 111*6d49e1aeSJan Lentfer os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); 112*6d49e1aeSJan Lentfer pos += conn->rl.iv_size; 113*6d49e1aeSJan Lentfer /* server_write_IV */ 114*6d49e1aeSJan Lentfer os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); 115*6d49e1aeSJan Lentfer pos += conn->rl.iv_size; 116*6d49e1aeSJan Lentfer 117*6d49e1aeSJan Lentfer return 0; 118*6d49e1aeSJan Lentfer } 119*6d49e1aeSJan Lentfer 120*6d49e1aeSJan Lentfer 121*6d49e1aeSJan Lentfer /** 122*6d49e1aeSJan Lentfer * tlsv1_client_handshake - Process TLS handshake 123*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 124*6d49e1aeSJan Lentfer * @in_data: Input data from TLS peer 125*6d49e1aeSJan Lentfer * @in_len: Input data length 126*6d49e1aeSJan Lentfer * @out_len: Length of the output buffer. 127*6d49e1aeSJan Lentfer * @appl_data: Pointer to application data pointer, or %NULL if dropped 128*6d49e1aeSJan Lentfer * @appl_data_len: Pointer to variable that is set to appl_data length 129*6d49e1aeSJan Lentfer * Returns: Pointer to output data, %NULL on failure 130*6d49e1aeSJan Lentfer */ 131*6d49e1aeSJan Lentfer u8 * tlsv1_client_handshake(struct tlsv1_client *conn, 132*6d49e1aeSJan Lentfer const u8 *in_data, size_t in_len, 133*6d49e1aeSJan Lentfer size_t *out_len, u8 **appl_data, 134*6d49e1aeSJan Lentfer size_t *appl_data_len) 135*6d49e1aeSJan Lentfer { 136*6d49e1aeSJan Lentfer const u8 *pos, *end; 137*6d49e1aeSJan Lentfer u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; 138*6d49e1aeSJan Lentfer size_t in_msg_len; 139*6d49e1aeSJan Lentfer int no_appl_data; 140*6d49e1aeSJan Lentfer 141*6d49e1aeSJan Lentfer if (conn->state == CLIENT_HELLO) { 142*6d49e1aeSJan Lentfer if (in_len) 143*6d49e1aeSJan Lentfer return NULL; 144*6d49e1aeSJan Lentfer return tls_send_client_hello(conn, out_len); 145*6d49e1aeSJan Lentfer } 146*6d49e1aeSJan Lentfer 147*6d49e1aeSJan Lentfer if (in_data == NULL || in_len == 0) 148*6d49e1aeSJan Lentfer return NULL; 149*6d49e1aeSJan Lentfer 150*6d49e1aeSJan Lentfer pos = in_data; 151*6d49e1aeSJan Lentfer end = in_data + in_len; 152*6d49e1aeSJan Lentfer in_msg = os_malloc(in_len); 153*6d49e1aeSJan Lentfer if (in_msg == NULL) 154*6d49e1aeSJan Lentfer return NULL; 155*6d49e1aeSJan Lentfer 156*6d49e1aeSJan Lentfer /* Each received packet may include multiple records */ 157*6d49e1aeSJan Lentfer while (pos < end) { 158*6d49e1aeSJan Lentfer in_msg_len = in_len; 159*6d49e1aeSJan Lentfer if (tlsv1_record_receive(&conn->rl, pos, end - pos, 160*6d49e1aeSJan Lentfer in_msg, &in_msg_len, &alert)) { 161*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Processing received " 162*6d49e1aeSJan Lentfer "record failed"); 163*6d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 164*6d49e1aeSJan Lentfer goto failed; 165*6d49e1aeSJan Lentfer } 166*6d49e1aeSJan Lentfer ct = pos[0]; 167*6d49e1aeSJan Lentfer 168*6d49e1aeSJan Lentfer in_pos = in_msg; 169*6d49e1aeSJan Lentfer in_end = in_msg + in_msg_len; 170*6d49e1aeSJan Lentfer 171*6d49e1aeSJan Lentfer /* Each received record may include multiple messages of the 172*6d49e1aeSJan Lentfer * same ContentType. */ 173*6d49e1aeSJan Lentfer while (in_pos < in_end) { 174*6d49e1aeSJan Lentfer in_msg_len = in_end - in_pos; 175*6d49e1aeSJan Lentfer if (tlsv1_client_process_handshake(conn, ct, in_pos, 176*6d49e1aeSJan Lentfer &in_msg_len, 177*6d49e1aeSJan Lentfer appl_data, 178*6d49e1aeSJan Lentfer appl_data_len) < 0) 179*6d49e1aeSJan Lentfer goto failed; 180*6d49e1aeSJan Lentfer in_pos += in_msg_len; 181*6d49e1aeSJan Lentfer } 182*6d49e1aeSJan Lentfer 183*6d49e1aeSJan Lentfer pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); 184*6d49e1aeSJan Lentfer } 185*6d49e1aeSJan Lentfer 186*6d49e1aeSJan Lentfer os_free(in_msg); 187*6d49e1aeSJan Lentfer in_msg = NULL; 188*6d49e1aeSJan Lentfer 189*6d49e1aeSJan Lentfer no_appl_data = appl_data == NULL || *appl_data == NULL; 190*6d49e1aeSJan Lentfer msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data); 191*6d49e1aeSJan Lentfer 192*6d49e1aeSJan Lentfer failed: 193*6d49e1aeSJan Lentfer os_free(in_msg); 194*6d49e1aeSJan Lentfer if (conn->alert_level) { 195*6d49e1aeSJan Lentfer conn->state = FAILED; 196*6d49e1aeSJan Lentfer os_free(msg); 197*6d49e1aeSJan Lentfer msg = tlsv1_client_send_alert(conn, conn->alert_level, 198*6d49e1aeSJan Lentfer conn->alert_description, 199*6d49e1aeSJan Lentfer out_len); 200*6d49e1aeSJan Lentfer } else if (msg == NULL) { 201*6d49e1aeSJan Lentfer msg = os_zalloc(1); 202*6d49e1aeSJan Lentfer *out_len = 0; 203*6d49e1aeSJan Lentfer } 204*6d49e1aeSJan Lentfer 205*6d49e1aeSJan Lentfer return msg; 206*6d49e1aeSJan Lentfer } 207*6d49e1aeSJan Lentfer 208*6d49e1aeSJan Lentfer 209*6d49e1aeSJan Lentfer /** 210*6d49e1aeSJan Lentfer * tlsv1_client_encrypt - Encrypt data into TLS tunnel 211*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 212*6d49e1aeSJan Lentfer * @in_data: Pointer to plaintext data to be encrypted 213*6d49e1aeSJan Lentfer * @in_len: Input buffer length 214*6d49e1aeSJan Lentfer * @out_data: Pointer to output buffer (encrypted TLS data) 215*6d49e1aeSJan Lentfer * @out_len: Maximum out_data length 216*6d49e1aeSJan Lentfer * Returns: Number of bytes written to out_data, -1 on failure 217*6d49e1aeSJan Lentfer * 218*6d49e1aeSJan Lentfer * This function is used after TLS handshake has been completed successfully to 219*6d49e1aeSJan Lentfer * send data in the encrypted tunnel. 220*6d49e1aeSJan Lentfer */ 221*6d49e1aeSJan Lentfer int tlsv1_client_encrypt(struct tlsv1_client *conn, 222*6d49e1aeSJan Lentfer const u8 *in_data, size_t in_len, 223*6d49e1aeSJan Lentfer u8 *out_data, size_t out_len) 224*6d49e1aeSJan Lentfer { 225*6d49e1aeSJan Lentfer size_t rlen; 226*6d49e1aeSJan Lentfer 227*6d49e1aeSJan Lentfer wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", 228*6d49e1aeSJan Lentfer in_data, in_len); 229*6d49e1aeSJan Lentfer 230*6d49e1aeSJan Lentfer os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); 231*6d49e1aeSJan Lentfer 232*6d49e1aeSJan Lentfer if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, 233*6d49e1aeSJan Lentfer out_data, out_len, in_len, &rlen) < 0) { 234*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); 235*6d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 236*6d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR); 237*6d49e1aeSJan Lentfer return -1; 238*6d49e1aeSJan Lentfer } 239*6d49e1aeSJan Lentfer 240*6d49e1aeSJan Lentfer return rlen; 241*6d49e1aeSJan Lentfer } 242*6d49e1aeSJan Lentfer 243*6d49e1aeSJan Lentfer 244*6d49e1aeSJan Lentfer /** 245*6d49e1aeSJan Lentfer * tlsv1_client_decrypt - Decrypt data from TLS tunnel 246*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 247*6d49e1aeSJan Lentfer * @in_data: Pointer to input buffer (encrypted TLS data) 248*6d49e1aeSJan Lentfer * @in_len: Input buffer length 249*6d49e1aeSJan Lentfer * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) 250*6d49e1aeSJan Lentfer * @out_len: Maximum out_data length 251*6d49e1aeSJan Lentfer * Returns: Number of bytes written to out_data, -1 on failure 252*6d49e1aeSJan Lentfer * 253*6d49e1aeSJan Lentfer * This function is used after TLS handshake has been completed successfully to 254*6d49e1aeSJan Lentfer * receive data from the encrypted tunnel. 255*6d49e1aeSJan Lentfer */ 256*6d49e1aeSJan Lentfer int tlsv1_client_decrypt(struct tlsv1_client *conn, 257*6d49e1aeSJan Lentfer const u8 *in_data, size_t in_len, 258*6d49e1aeSJan Lentfer u8 *out_data, size_t out_len) 259*6d49e1aeSJan Lentfer { 260*6d49e1aeSJan Lentfer const u8 *in_end, *pos; 261*6d49e1aeSJan Lentfer int res; 262*6d49e1aeSJan Lentfer u8 alert, *out_end, *out_pos; 263*6d49e1aeSJan Lentfer size_t olen; 264*6d49e1aeSJan Lentfer 265*6d49e1aeSJan Lentfer pos = in_data; 266*6d49e1aeSJan Lentfer in_end = in_data + in_len; 267*6d49e1aeSJan Lentfer out_pos = out_data; 268*6d49e1aeSJan Lentfer out_end = out_data + out_len; 269*6d49e1aeSJan Lentfer 270*6d49e1aeSJan Lentfer while (pos < in_end) { 271*6d49e1aeSJan Lentfer if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { 272*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " 273*6d49e1aeSJan Lentfer "0x%x", pos[0]); 274*6d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 275*6d49e1aeSJan Lentfer TLS_ALERT_UNEXPECTED_MESSAGE); 276*6d49e1aeSJan Lentfer return -1; 277*6d49e1aeSJan Lentfer } 278*6d49e1aeSJan Lentfer 279*6d49e1aeSJan Lentfer olen = out_end - out_pos; 280*6d49e1aeSJan Lentfer res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, 281*6d49e1aeSJan Lentfer out_pos, &olen, &alert); 282*6d49e1aeSJan Lentfer if (res < 0) { 283*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " 284*6d49e1aeSJan Lentfer "failed"); 285*6d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); 286*6d49e1aeSJan Lentfer return -1; 287*6d49e1aeSJan Lentfer } 288*6d49e1aeSJan Lentfer out_pos += olen; 289*6d49e1aeSJan Lentfer if (out_pos > out_end) { 290*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " 291*6d49e1aeSJan Lentfer "for processing the received record"); 292*6d49e1aeSJan Lentfer tls_alert(conn, TLS_ALERT_LEVEL_FATAL, 293*6d49e1aeSJan Lentfer TLS_ALERT_INTERNAL_ERROR); 294*6d49e1aeSJan Lentfer return -1; 295*6d49e1aeSJan Lentfer } 296*6d49e1aeSJan Lentfer 297*6d49e1aeSJan Lentfer pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); 298*6d49e1aeSJan Lentfer } 299*6d49e1aeSJan Lentfer 300*6d49e1aeSJan Lentfer return out_pos - out_data; 301*6d49e1aeSJan Lentfer } 302*6d49e1aeSJan Lentfer 303*6d49e1aeSJan Lentfer 304*6d49e1aeSJan Lentfer /** 305*6d49e1aeSJan Lentfer * tlsv1_client_global_init - Initialize TLSv1 client 306*6d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure 307*6d49e1aeSJan Lentfer * 308*6d49e1aeSJan Lentfer * This function must be called before using any other TLSv1 client functions. 309*6d49e1aeSJan Lentfer */ 310*6d49e1aeSJan Lentfer int tlsv1_client_global_init(void) 311*6d49e1aeSJan Lentfer { 312*6d49e1aeSJan Lentfer return crypto_global_init(); 313*6d49e1aeSJan Lentfer } 314*6d49e1aeSJan Lentfer 315*6d49e1aeSJan Lentfer 316*6d49e1aeSJan Lentfer /** 317*6d49e1aeSJan Lentfer * tlsv1_client_global_deinit - Deinitialize TLSv1 client 318*6d49e1aeSJan Lentfer * 319*6d49e1aeSJan Lentfer * This function can be used to deinitialize the TLSv1 client that was 320*6d49e1aeSJan Lentfer * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions 321*6d49e1aeSJan Lentfer * can be called after this before calling tlsv1_client_global_init() again. 322*6d49e1aeSJan Lentfer */ 323*6d49e1aeSJan Lentfer void tlsv1_client_global_deinit(void) 324*6d49e1aeSJan Lentfer { 325*6d49e1aeSJan Lentfer crypto_global_deinit(); 326*6d49e1aeSJan Lentfer } 327*6d49e1aeSJan Lentfer 328*6d49e1aeSJan Lentfer 329*6d49e1aeSJan Lentfer /** 330*6d49e1aeSJan Lentfer * tlsv1_client_init - Initialize TLSv1 client connection 331*6d49e1aeSJan Lentfer * Returns: Pointer to TLSv1 client connection data or %NULL on failure 332*6d49e1aeSJan Lentfer */ 333*6d49e1aeSJan Lentfer struct tlsv1_client * tlsv1_client_init(void) 334*6d49e1aeSJan Lentfer { 335*6d49e1aeSJan Lentfer struct tlsv1_client *conn; 336*6d49e1aeSJan Lentfer size_t count; 337*6d49e1aeSJan Lentfer u16 *suites; 338*6d49e1aeSJan Lentfer 339*6d49e1aeSJan Lentfer conn = os_zalloc(sizeof(*conn)); 340*6d49e1aeSJan Lentfer if (conn == NULL) 341*6d49e1aeSJan Lentfer return NULL; 342*6d49e1aeSJan Lentfer 343*6d49e1aeSJan Lentfer conn->state = CLIENT_HELLO; 344*6d49e1aeSJan Lentfer 345*6d49e1aeSJan Lentfer if (tls_verify_hash_init(&conn->verify) < 0) { 346*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " 347*6d49e1aeSJan Lentfer "hash"); 348*6d49e1aeSJan Lentfer os_free(conn); 349*6d49e1aeSJan Lentfer return NULL; 350*6d49e1aeSJan Lentfer } 351*6d49e1aeSJan Lentfer 352*6d49e1aeSJan Lentfer count = 0; 353*6d49e1aeSJan Lentfer suites = conn->cipher_suites; 354*6d49e1aeSJan Lentfer #ifndef CONFIG_CRYPTO_INTERNAL 355*6d49e1aeSJan Lentfer suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; 356*6d49e1aeSJan Lentfer #endif /* CONFIG_CRYPTO_INTERNAL */ 357*6d49e1aeSJan Lentfer suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; 358*6d49e1aeSJan Lentfer suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; 359*6d49e1aeSJan Lentfer suites[count++] = TLS_RSA_WITH_RC4_128_SHA; 360*6d49e1aeSJan Lentfer suites[count++] = TLS_RSA_WITH_RC4_128_MD5; 361*6d49e1aeSJan Lentfer conn->num_cipher_suites = count; 362*6d49e1aeSJan Lentfer 363*6d49e1aeSJan Lentfer return conn; 364*6d49e1aeSJan Lentfer } 365*6d49e1aeSJan Lentfer 366*6d49e1aeSJan Lentfer 367*6d49e1aeSJan Lentfer /** 368*6d49e1aeSJan Lentfer * tlsv1_client_deinit - Deinitialize TLSv1 client connection 369*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 370*6d49e1aeSJan Lentfer */ 371*6d49e1aeSJan Lentfer void tlsv1_client_deinit(struct tlsv1_client *conn) 372*6d49e1aeSJan Lentfer { 373*6d49e1aeSJan Lentfer crypto_public_key_free(conn->server_rsa_key); 374*6d49e1aeSJan Lentfer tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); 375*6d49e1aeSJan Lentfer tlsv1_record_change_write_cipher(&conn->rl); 376*6d49e1aeSJan Lentfer tlsv1_record_change_read_cipher(&conn->rl); 377*6d49e1aeSJan Lentfer tls_verify_hash_free(&conn->verify); 378*6d49e1aeSJan Lentfer os_free(conn->client_hello_ext); 379*6d49e1aeSJan Lentfer tlsv1_client_free_dh(conn); 380*6d49e1aeSJan Lentfer tlsv1_cred_free(conn->cred); 381*6d49e1aeSJan Lentfer os_free(conn); 382*6d49e1aeSJan Lentfer } 383*6d49e1aeSJan Lentfer 384*6d49e1aeSJan Lentfer 385*6d49e1aeSJan Lentfer /** 386*6d49e1aeSJan Lentfer * tlsv1_client_established - Check whether connection has been established 387*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 388*6d49e1aeSJan Lentfer * Returns: 1 if connection is established, 0 if not 389*6d49e1aeSJan Lentfer */ 390*6d49e1aeSJan Lentfer int tlsv1_client_established(struct tlsv1_client *conn) 391*6d49e1aeSJan Lentfer { 392*6d49e1aeSJan Lentfer return conn->state == ESTABLISHED; 393*6d49e1aeSJan Lentfer } 394*6d49e1aeSJan Lentfer 395*6d49e1aeSJan Lentfer 396*6d49e1aeSJan Lentfer /** 397*6d49e1aeSJan Lentfer * tlsv1_client_prf - Use TLS-PRF to derive keying material 398*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 399*6d49e1aeSJan Lentfer * @label: Label (e.g., description of the key) for PRF 400*6d49e1aeSJan Lentfer * @server_random_first: seed is 0 = client_random|server_random, 401*6d49e1aeSJan Lentfer * 1 = server_random|client_random 402*6d49e1aeSJan Lentfer * @out: Buffer for output data from TLS-PRF 403*6d49e1aeSJan Lentfer * @out_len: Length of the output buffer 404*6d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure 405*6d49e1aeSJan Lentfer */ 406*6d49e1aeSJan Lentfer int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, 407*6d49e1aeSJan Lentfer int server_random_first, u8 *out, size_t out_len) 408*6d49e1aeSJan Lentfer { 409*6d49e1aeSJan Lentfer u8 seed[2 * TLS_RANDOM_LEN]; 410*6d49e1aeSJan Lentfer 411*6d49e1aeSJan Lentfer if (conn->state != ESTABLISHED) 412*6d49e1aeSJan Lentfer return -1; 413*6d49e1aeSJan Lentfer 414*6d49e1aeSJan Lentfer if (server_random_first) { 415*6d49e1aeSJan Lentfer os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); 416*6d49e1aeSJan Lentfer os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, 417*6d49e1aeSJan Lentfer TLS_RANDOM_LEN); 418*6d49e1aeSJan Lentfer } else { 419*6d49e1aeSJan Lentfer os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); 420*6d49e1aeSJan Lentfer os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, 421*6d49e1aeSJan Lentfer TLS_RANDOM_LEN); 422*6d49e1aeSJan Lentfer } 423*6d49e1aeSJan Lentfer 424*6d49e1aeSJan Lentfer return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, 425*6d49e1aeSJan Lentfer label, seed, 2 * TLS_RANDOM_LEN, out, out_len); 426*6d49e1aeSJan Lentfer } 427*6d49e1aeSJan Lentfer 428*6d49e1aeSJan Lentfer 429*6d49e1aeSJan Lentfer /** 430*6d49e1aeSJan Lentfer * tlsv1_client_get_cipher - Get current cipher name 431*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 432*6d49e1aeSJan Lentfer * @buf: Buffer for the cipher name 433*6d49e1aeSJan Lentfer * @buflen: buf size 434*6d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure 435*6d49e1aeSJan Lentfer * 436*6d49e1aeSJan Lentfer * Get the name of the currently used cipher. 437*6d49e1aeSJan Lentfer */ 438*6d49e1aeSJan Lentfer int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, 439*6d49e1aeSJan Lentfer size_t buflen) 440*6d49e1aeSJan Lentfer { 441*6d49e1aeSJan Lentfer char *cipher; 442*6d49e1aeSJan Lentfer 443*6d49e1aeSJan Lentfer switch (conn->rl.cipher_suite) { 444*6d49e1aeSJan Lentfer case TLS_RSA_WITH_RC4_128_MD5: 445*6d49e1aeSJan Lentfer cipher = "RC4-MD5"; 446*6d49e1aeSJan Lentfer break; 447*6d49e1aeSJan Lentfer case TLS_RSA_WITH_RC4_128_SHA: 448*6d49e1aeSJan Lentfer cipher = "RC4-SHA"; 449*6d49e1aeSJan Lentfer break; 450*6d49e1aeSJan Lentfer case TLS_RSA_WITH_DES_CBC_SHA: 451*6d49e1aeSJan Lentfer cipher = "DES-CBC-SHA"; 452*6d49e1aeSJan Lentfer break; 453*6d49e1aeSJan Lentfer case TLS_RSA_WITH_3DES_EDE_CBC_SHA: 454*6d49e1aeSJan Lentfer cipher = "DES-CBC3-SHA"; 455*6d49e1aeSJan Lentfer break; 456*6d49e1aeSJan Lentfer case TLS_DH_anon_WITH_AES_128_CBC_SHA: 457*6d49e1aeSJan Lentfer cipher = "ADH-AES-128-SHA"; 458*6d49e1aeSJan Lentfer break; 459*6d49e1aeSJan Lentfer case TLS_RSA_WITH_AES_256_CBC_SHA: 460*6d49e1aeSJan Lentfer cipher = "AES-256-SHA"; 461*6d49e1aeSJan Lentfer break; 462*6d49e1aeSJan Lentfer case TLS_RSA_WITH_AES_128_CBC_SHA: 463*6d49e1aeSJan Lentfer cipher = "AES-128-SHA"; 464*6d49e1aeSJan Lentfer break; 465*6d49e1aeSJan Lentfer default: 466*6d49e1aeSJan Lentfer return -1; 467*6d49e1aeSJan Lentfer } 468*6d49e1aeSJan Lentfer 469*6d49e1aeSJan Lentfer if (os_strlcpy(buf, cipher, buflen) >= buflen) 470*6d49e1aeSJan Lentfer return -1; 471*6d49e1aeSJan Lentfer return 0; 472*6d49e1aeSJan Lentfer } 473*6d49e1aeSJan Lentfer 474*6d49e1aeSJan Lentfer 475*6d49e1aeSJan Lentfer /** 476*6d49e1aeSJan Lentfer * tlsv1_client_shutdown - Shutdown TLS connection 477*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 478*6d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure 479*6d49e1aeSJan Lentfer */ 480*6d49e1aeSJan Lentfer int tlsv1_client_shutdown(struct tlsv1_client *conn) 481*6d49e1aeSJan Lentfer { 482*6d49e1aeSJan Lentfer conn->state = CLIENT_HELLO; 483*6d49e1aeSJan Lentfer 484*6d49e1aeSJan Lentfer if (tls_verify_hash_init(&conn->verify) < 0) { 485*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " 486*6d49e1aeSJan Lentfer "hash"); 487*6d49e1aeSJan Lentfer return -1; 488*6d49e1aeSJan Lentfer } 489*6d49e1aeSJan Lentfer 490*6d49e1aeSJan Lentfer tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); 491*6d49e1aeSJan Lentfer tlsv1_record_change_write_cipher(&conn->rl); 492*6d49e1aeSJan Lentfer tlsv1_record_change_read_cipher(&conn->rl); 493*6d49e1aeSJan Lentfer 494*6d49e1aeSJan Lentfer conn->certificate_requested = 0; 495*6d49e1aeSJan Lentfer crypto_public_key_free(conn->server_rsa_key); 496*6d49e1aeSJan Lentfer conn->server_rsa_key = NULL; 497*6d49e1aeSJan Lentfer conn->session_resumed = 0; 498*6d49e1aeSJan Lentfer 499*6d49e1aeSJan Lentfer return 0; 500*6d49e1aeSJan Lentfer } 501*6d49e1aeSJan Lentfer 502*6d49e1aeSJan Lentfer 503*6d49e1aeSJan Lentfer /** 504*6d49e1aeSJan Lentfer * tlsv1_client_resumed - Was session resumption used 505*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 506*6d49e1aeSJan Lentfer * Returns: 1 if current session used session resumption, 0 if not 507*6d49e1aeSJan Lentfer */ 508*6d49e1aeSJan Lentfer int tlsv1_client_resumed(struct tlsv1_client *conn) 509*6d49e1aeSJan Lentfer { 510*6d49e1aeSJan Lentfer return !!conn->session_resumed; 511*6d49e1aeSJan Lentfer } 512*6d49e1aeSJan Lentfer 513*6d49e1aeSJan Lentfer 514*6d49e1aeSJan Lentfer /** 515*6d49e1aeSJan Lentfer * tlsv1_client_hello_ext - Set TLS extension for ClientHello 516*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 517*6d49e1aeSJan Lentfer * @ext_type: Extension type 518*6d49e1aeSJan Lentfer * @data: Extension payload (%NULL to remove extension) 519*6d49e1aeSJan Lentfer * @data_len: Extension payload length 520*6d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure 521*6d49e1aeSJan Lentfer */ 522*6d49e1aeSJan Lentfer int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, 523*6d49e1aeSJan Lentfer const u8 *data, size_t data_len) 524*6d49e1aeSJan Lentfer { 525*6d49e1aeSJan Lentfer u8 *pos; 526*6d49e1aeSJan Lentfer 527*6d49e1aeSJan Lentfer conn->session_ticket_included = 0; 528*6d49e1aeSJan Lentfer os_free(conn->client_hello_ext); 529*6d49e1aeSJan Lentfer conn->client_hello_ext = NULL; 530*6d49e1aeSJan Lentfer conn->client_hello_ext_len = 0; 531*6d49e1aeSJan Lentfer 532*6d49e1aeSJan Lentfer if (data == NULL || data_len == 0) 533*6d49e1aeSJan Lentfer return 0; 534*6d49e1aeSJan Lentfer 535*6d49e1aeSJan Lentfer pos = conn->client_hello_ext = os_malloc(6 + data_len); 536*6d49e1aeSJan Lentfer if (pos == NULL) 537*6d49e1aeSJan Lentfer return -1; 538*6d49e1aeSJan Lentfer 539*6d49e1aeSJan Lentfer WPA_PUT_BE16(pos, 4 + data_len); 540*6d49e1aeSJan Lentfer pos += 2; 541*6d49e1aeSJan Lentfer WPA_PUT_BE16(pos, ext_type); 542*6d49e1aeSJan Lentfer pos += 2; 543*6d49e1aeSJan Lentfer WPA_PUT_BE16(pos, data_len); 544*6d49e1aeSJan Lentfer pos += 2; 545*6d49e1aeSJan Lentfer os_memcpy(pos, data, data_len); 546*6d49e1aeSJan Lentfer conn->client_hello_ext_len = 6 + data_len; 547*6d49e1aeSJan Lentfer 548*6d49e1aeSJan Lentfer if (ext_type == TLS_EXT_PAC_OPAQUE) { 549*6d49e1aeSJan Lentfer conn->session_ticket_included = 1; 550*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket"); 551*6d49e1aeSJan Lentfer } 552*6d49e1aeSJan Lentfer 553*6d49e1aeSJan Lentfer return 0; 554*6d49e1aeSJan Lentfer } 555*6d49e1aeSJan Lentfer 556*6d49e1aeSJan Lentfer 557*6d49e1aeSJan Lentfer /** 558*6d49e1aeSJan Lentfer * tlsv1_client_get_keys - Get master key and random data from TLS connection 559*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 560*6d49e1aeSJan Lentfer * @keys: Structure of key/random data (filled on success) 561*6d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure 562*6d49e1aeSJan Lentfer */ 563*6d49e1aeSJan Lentfer int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys) 564*6d49e1aeSJan Lentfer { 565*6d49e1aeSJan Lentfer os_memset(keys, 0, sizeof(*keys)); 566*6d49e1aeSJan Lentfer if (conn->state == CLIENT_HELLO) 567*6d49e1aeSJan Lentfer return -1; 568*6d49e1aeSJan Lentfer 569*6d49e1aeSJan Lentfer keys->client_random = conn->client_random; 570*6d49e1aeSJan Lentfer keys->client_random_len = TLS_RANDOM_LEN; 571*6d49e1aeSJan Lentfer 572*6d49e1aeSJan Lentfer if (conn->state != SERVER_HELLO) { 573*6d49e1aeSJan Lentfer keys->server_random = conn->server_random; 574*6d49e1aeSJan Lentfer keys->server_random_len = TLS_RANDOM_LEN; 575*6d49e1aeSJan Lentfer keys->master_key = conn->master_secret; 576*6d49e1aeSJan Lentfer keys->master_key_len = TLS_MASTER_SECRET_LEN; 577*6d49e1aeSJan Lentfer } 578*6d49e1aeSJan Lentfer 579*6d49e1aeSJan Lentfer return 0; 580*6d49e1aeSJan Lentfer } 581*6d49e1aeSJan Lentfer 582*6d49e1aeSJan Lentfer 583*6d49e1aeSJan Lentfer /** 584*6d49e1aeSJan Lentfer * tlsv1_client_get_keyblock_size - Get TLS key_block size 585*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 586*6d49e1aeSJan Lentfer * Returns: Size of the key_block for the negotiated cipher suite or -1 on 587*6d49e1aeSJan Lentfer * failure 588*6d49e1aeSJan Lentfer */ 589*6d49e1aeSJan Lentfer int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn) 590*6d49e1aeSJan Lentfer { 591*6d49e1aeSJan Lentfer if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) 592*6d49e1aeSJan Lentfer return -1; 593*6d49e1aeSJan Lentfer 594*6d49e1aeSJan Lentfer return 2 * (conn->rl.hash_size + conn->rl.key_material_len + 595*6d49e1aeSJan Lentfer conn->rl.iv_size); 596*6d49e1aeSJan Lentfer } 597*6d49e1aeSJan Lentfer 598*6d49e1aeSJan Lentfer 599*6d49e1aeSJan Lentfer /** 600*6d49e1aeSJan Lentfer * tlsv1_client_set_cipher_list - Configure acceptable cipher suites 601*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 602*6d49e1aeSJan Lentfer * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers 603*6d49e1aeSJan Lentfer * (TLS_CIPHER_*). 604*6d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure 605*6d49e1aeSJan Lentfer */ 606*6d49e1aeSJan Lentfer int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers) 607*6d49e1aeSJan Lentfer { 608*6d49e1aeSJan Lentfer #ifdef EAP_FAST 609*6d49e1aeSJan Lentfer size_t count; 610*6d49e1aeSJan Lentfer u16 *suites; 611*6d49e1aeSJan Lentfer 612*6d49e1aeSJan Lentfer /* TODO: implement proper configuration of cipher suites */ 613*6d49e1aeSJan Lentfer if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { 614*6d49e1aeSJan Lentfer count = 0; 615*6d49e1aeSJan Lentfer suites = conn->cipher_suites; 616*6d49e1aeSJan Lentfer #ifndef CONFIG_CRYPTO_INTERNAL 617*6d49e1aeSJan Lentfer suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; 618*6d49e1aeSJan Lentfer #endif /* CONFIG_CRYPTO_INTERNAL */ 619*6d49e1aeSJan Lentfer suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; 620*6d49e1aeSJan Lentfer suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; 621*6d49e1aeSJan Lentfer suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; 622*6d49e1aeSJan Lentfer suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; 623*6d49e1aeSJan Lentfer 624*6d49e1aeSJan Lentfer /* 625*6d49e1aeSJan Lentfer * Cisco AP (at least 350 and 1200 series) local authentication 626*6d49e1aeSJan Lentfer * server does not know how to search cipher suites from the 627*6d49e1aeSJan Lentfer * list and seem to require that the last entry in the list is 628*6d49e1aeSJan Lentfer * the one that it wants to use. However, TLS specification 629*6d49e1aeSJan Lentfer * requires the list to be in the client preference order. As a 630*6d49e1aeSJan Lentfer * workaround, add anon-DH AES-128-SHA1 again at the end of the 631*6d49e1aeSJan Lentfer * list to allow the Cisco code to find it. 632*6d49e1aeSJan Lentfer */ 633*6d49e1aeSJan Lentfer suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; 634*6d49e1aeSJan Lentfer conn->num_cipher_suites = count; 635*6d49e1aeSJan Lentfer } 636*6d49e1aeSJan Lentfer 637*6d49e1aeSJan Lentfer return 0; 638*6d49e1aeSJan Lentfer #else /* EAP_FAST */ 639*6d49e1aeSJan Lentfer return -1; 640*6d49e1aeSJan Lentfer #endif /* EAP_FAST */ 641*6d49e1aeSJan Lentfer } 642*6d49e1aeSJan Lentfer 643*6d49e1aeSJan Lentfer 644*6d49e1aeSJan Lentfer /** 645*6d49e1aeSJan Lentfer * tlsv1_client_set_cred - Set client credentials 646*6d49e1aeSJan Lentfer * @conn: TLSv1 client connection data from tlsv1_client_init() 647*6d49e1aeSJan Lentfer * @cred: Credentials from tlsv1_cred_alloc() 648*6d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure 649*6d49e1aeSJan Lentfer * 650*6d49e1aeSJan Lentfer * On success, the client takes ownership of the credentials block and caller 651*6d49e1aeSJan Lentfer * must not free it. On failure, caller is responsible for freeing the 652*6d49e1aeSJan Lentfer * credential block. 653*6d49e1aeSJan Lentfer */ 654*6d49e1aeSJan Lentfer int tlsv1_client_set_cred(struct tlsv1_client *conn, 655*6d49e1aeSJan Lentfer struct tlsv1_credentials *cred) 656*6d49e1aeSJan Lentfer { 657*6d49e1aeSJan Lentfer tlsv1_cred_free(conn->cred); 658*6d49e1aeSJan Lentfer conn->cred = cred; 659*6d49e1aeSJan Lentfer return 0; 660*6d49e1aeSJan Lentfer } 661*6d49e1aeSJan Lentfer 662*6d49e1aeSJan Lentfer 663*6d49e1aeSJan Lentfer void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, 664*6d49e1aeSJan Lentfer tlsv1_client_session_ticket_cb cb, 665*6d49e1aeSJan Lentfer void *ctx) 666*6d49e1aeSJan Lentfer { 667*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", 668*6d49e1aeSJan Lentfer cb, ctx); 669*6d49e1aeSJan Lentfer conn->session_ticket_cb = cb; 670*6d49e1aeSJan Lentfer conn->session_ticket_cb_ctx = ctx; 671*6d49e1aeSJan Lentfer } 672