2 * TLSv1 client (RFC 2246)
3 * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "crypto/sha1.h"
19 #include "crypto/tls.h"
20 #include "tlsv1_common.h"
21 #include "tlsv1_record.h"
22 #include "tlsv1_client.h"
23 #include "tlsv1_client_i.h"
26 * Support for a message fragmented across several records (RFC 2246, 6.2.1)
30 void tls_alert(struct tlsv1_client
*conn
, u8 level
, u8 description
)
32 conn
->alert_level
= level
;
33 conn
->alert_description
= description
;
37 void tlsv1_client_free_dh(struct tlsv1_client
*conn
)
42 conn
->dh_p
= conn
->dh_g
= conn
->dh_ys
= NULL
;
46 int tls_derive_pre_master_secret(u8
*pre_master_secret
)
48 WPA_PUT_BE16(pre_master_secret
, TLS_VERSION
);
49 if (os_get_random(pre_master_secret
+ 2,
50 TLS_PRE_MASTER_SECRET_LEN
- 2))
56 int tls_derive_keys(struct tlsv1_client
*conn
,
57 const u8
*pre_master_secret
, size_t pre_master_secret_len
)
59 u8 seed
[2 * TLS_RANDOM_LEN
];
60 u8 key_block
[TLS_MAX_KEY_BLOCK_LEN
];
64 if (pre_master_secret
) {
65 wpa_hexdump_key(MSG_MSGDUMP
, "TLSv1: pre_master_secret",
66 pre_master_secret
, pre_master_secret_len
);
67 os_memcpy(seed
, conn
->client_random
, TLS_RANDOM_LEN
);
68 os_memcpy(seed
+ TLS_RANDOM_LEN
, conn
->server_random
,
70 if (tls_prf(pre_master_secret
, pre_master_secret_len
,
71 "master secret", seed
, 2 * TLS_RANDOM_LEN
,
72 conn
->master_secret
, TLS_MASTER_SECRET_LEN
)) {
73 wpa_printf(MSG_DEBUG
, "TLSv1: Failed to derive "
77 wpa_hexdump_key(MSG_MSGDUMP
, "TLSv1: master_secret",
78 conn
->master_secret
, TLS_MASTER_SECRET_LEN
);
81 os_memcpy(seed
, conn
->server_random
, TLS_RANDOM_LEN
);
82 os_memcpy(seed
+ TLS_RANDOM_LEN
, conn
->client_random
, TLS_RANDOM_LEN
);
83 key_block_len
= 2 * (conn
->rl
.hash_size
+ conn
->rl
.key_material_len
+
85 if (tls_prf(conn
->master_secret
, TLS_MASTER_SECRET_LEN
,
86 "key expansion", seed
, 2 * TLS_RANDOM_LEN
,
87 key_block
, key_block_len
)) {
88 wpa_printf(MSG_DEBUG
, "TLSv1: Failed to derive key_block");
91 wpa_hexdump_key(MSG_MSGDUMP
, "TLSv1: key_block",
92 key_block
, key_block_len
);
96 /* client_write_MAC_secret */
97 os_memcpy(conn
->rl
.write_mac_secret
, pos
, conn
->rl
.hash_size
);
98 pos
+= conn
->rl
.hash_size
;
99 /* server_write_MAC_secret */
100 os_memcpy(conn
->rl
.read_mac_secret
, pos
, conn
->rl
.hash_size
);
101 pos
+= conn
->rl
.hash_size
;
103 /* client_write_key */
104 os_memcpy(conn
->rl
.write_key
, pos
, conn
->rl
.key_material_len
);
105 pos
+= conn
->rl
.key_material_len
;
106 /* server_write_key */
107 os_memcpy(conn
->rl
.read_key
, pos
, conn
->rl
.key_material_len
);
108 pos
+= conn
->rl
.key_material_len
;
110 /* client_write_IV */
111 os_memcpy(conn
->rl
.write_iv
, pos
, conn
->rl
.iv_size
);
112 pos
+= conn
->rl
.iv_size
;
113 /* server_write_IV */
114 os_memcpy(conn
->rl
.read_iv
, pos
, conn
->rl
.iv_size
);
115 pos
+= conn
->rl
.iv_size
;
122 * tlsv1_client_handshake - Process TLS handshake
123 * @conn: TLSv1 client connection data from tlsv1_client_init()
124 * @in_data: Input data from TLS peer
125 * @in_len: Input data length
126 * @out_len: Length of the output buffer.
127 * @appl_data: Pointer to application data pointer, or %NULL if dropped
128 * @appl_data_len: Pointer to variable that is set to appl_data length
129 * Returns: Pointer to output data, %NULL on failure
131 u8
* tlsv1_client_handshake(struct tlsv1_client
*conn
,
132 const u8
*in_data
, size_t in_len
,
133 size_t *out_len
, u8
**appl_data
,
134 size_t *appl_data_len
)
137 u8
*msg
= NULL
, *in_msg
, *in_pos
, *in_end
, alert
, ct
;
141 if (conn
->state
== CLIENT_HELLO
) {
144 return tls_send_client_hello(conn
, out_len
);
147 if (in_data
== NULL
|| in_len
== 0)
151 end
= in_data
+ in_len
;
152 in_msg
= os_malloc(in_len
);
156 /* Each received packet may include multiple records */
159 if (tlsv1_record_receive(&conn
->rl
, pos
, end
- pos
,
160 in_msg
, &in_msg_len
, &alert
)) {
161 wpa_printf(MSG_DEBUG
, "TLSv1: Processing received "
163 tls_alert(conn
, TLS_ALERT_LEVEL_FATAL
, alert
);
169 in_end
= in_msg
+ in_msg_len
;
171 /* Each received record may include multiple messages of the
172 * same ContentType. */
173 while (in_pos
< in_end
) {
174 in_msg_len
= in_end
- in_pos
;
175 if (tlsv1_client_process_handshake(conn
, ct
, in_pos
,
180 in_pos
+= in_msg_len
;
183 pos
+= TLS_RECORD_HEADER_LEN
+ WPA_GET_BE16(pos
+ 3);
189 no_appl_data
= appl_data
== NULL
|| *appl_data
== NULL
;
190 msg
= tlsv1_client_handshake_write(conn
, out_len
, no_appl_data
);
194 if (conn
->alert_level
) {
195 conn
->state
= FAILED
;
197 msg
= tlsv1_client_send_alert(conn
, conn
->alert_level
,
198 conn
->alert_description
,
200 } else if (msg
== NULL
) {
210 * tlsv1_client_encrypt - Encrypt data into TLS tunnel
211 * @conn: TLSv1 client connection data from tlsv1_client_init()
212 * @in_data: Pointer to plaintext data to be encrypted
213 * @in_len: Input buffer length
214 * @out_data: Pointer to output buffer (encrypted TLS data)
215 * @out_len: Maximum out_data length
216 * Returns: Number of bytes written to out_data, -1 on failure
218 * This function is used after TLS handshake has been completed successfully to
219 * send data in the encrypted tunnel.
221 int tlsv1_client_encrypt(struct tlsv1_client
*conn
,
222 const u8
*in_data
, size_t in_len
,
223 u8
*out_data
, size_t out_len
)
227 wpa_hexdump_key(MSG_MSGDUMP
, "TLSv1: Plaintext AppData",
230 os_memcpy(out_data
+ TLS_RECORD_HEADER_LEN
, in_data
, in_len
);
232 if (tlsv1_record_send(&conn
->rl
, TLS_CONTENT_TYPE_APPLICATION_DATA
,
233 out_data
, out_len
, in_len
, &rlen
) < 0) {
234 wpa_printf(MSG_DEBUG
, "TLSv1: Failed to create a record");
235 tls_alert(conn
, TLS_ALERT_LEVEL_FATAL
,
236 TLS_ALERT_INTERNAL_ERROR
);
245 * tlsv1_client_decrypt - Decrypt data from TLS tunnel
246 * @conn: TLSv1 client connection data from tlsv1_client_init()
247 * @in_data: Pointer to input buffer (encrypted TLS data)
248 * @in_len: Input buffer length
249 * @out_data: Pointer to output buffer (decrypted data from TLS tunnel)
250 * @out_len: Maximum out_data length
251 * Returns: Number of bytes written to out_data, -1 on failure
253 * This function is used after TLS handshake has been completed successfully to
254 * receive data from the encrypted tunnel.
256 int tlsv1_client_decrypt(struct tlsv1_client
*conn
,
257 const u8
*in_data
, size_t in_len
,
258 u8
*out_data
, size_t out_len
)
260 const u8
*in_end
, *pos
;
262 u8 alert
, *out_end
, *out_pos
;
266 in_end
= in_data
+ in_len
;
268 out_end
= out_data
+ out_len
;
270 while (pos
< in_end
) {
271 if (pos
[0] != TLS_CONTENT_TYPE_APPLICATION_DATA
) {
272 wpa_printf(MSG_DEBUG
, "TLSv1: Unexpected content type "
274 tls_alert(conn
, TLS_ALERT_LEVEL_FATAL
,
275 TLS_ALERT_UNEXPECTED_MESSAGE
);
279 olen
= out_end
- out_pos
;
280 res
= tlsv1_record_receive(&conn
->rl
, pos
, in_end
- pos
,
281 out_pos
, &olen
, &alert
);
283 wpa_printf(MSG_DEBUG
, "TLSv1: Record layer processing "
285 tls_alert(conn
, TLS_ALERT_LEVEL_FATAL
, alert
);
289 if (out_pos
> out_end
) {
290 wpa_printf(MSG_DEBUG
, "TLSv1: Buffer not large enough "
291 "for processing the received record");
292 tls_alert(conn
, TLS_ALERT_LEVEL_FATAL
,
293 TLS_ALERT_INTERNAL_ERROR
);
297 pos
+= TLS_RECORD_HEADER_LEN
+ WPA_GET_BE16(pos
+ 3);
300 return out_pos
- out_data
;
305 * tlsv1_client_global_init - Initialize TLSv1 client
306 * Returns: 0 on success, -1 on failure
308 * This function must be called before using any other TLSv1 client functions.
310 int tlsv1_client_global_init(void)
312 return crypto_global_init();
317 * tlsv1_client_global_deinit - Deinitialize TLSv1 client
319 * This function can be used to deinitialize the TLSv1 client that was
320 * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions
321 * can be called after this before calling tlsv1_client_global_init() again.
323 void tlsv1_client_global_deinit(void)
325 crypto_global_deinit();
330 * tlsv1_client_init - Initialize TLSv1 client connection
331 * Returns: Pointer to TLSv1 client connection data or %NULL on failure
333 struct tlsv1_client
* tlsv1_client_init(void)
335 struct tlsv1_client
*conn
;
339 conn
= os_zalloc(sizeof(*conn
));
343 conn
->state
= CLIENT_HELLO
;
345 if (tls_verify_hash_init(&conn
->verify
) < 0) {
346 wpa_printf(MSG_DEBUG
, "TLSv1: Failed to initialize verify "
353 suites
= conn
->cipher_suites
;
354 #ifndef CONFIG_CRYPTO_INTERNAL
355 suites
[count
++] = TLS_RSA_WITH_AES_256_CBC_SHA
;
356 #endif /* CONFIG_CRYPTO_INTERNAL */
357 suites
[count
++] = TLS_RSA_WITH_AES_128_CBC_SHA
;
358 suites
[count
++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA
;
359 suites
[count
++] = TLS_RSA_WITH_RC4_128_SHA
;
360 suites
[count
++] = TLS_RSA_WITH_RC4_128_MD5
;
361 conn
->num_cipher_suites
= count
;
368 * tlsv1_client_deinit - Deinitialize TLSv1 client connection
369 * @conn: TLSv1 client connection data from tlsv1_client_init()
371 void tlsv1_client_deinit(struct tlsv1_client
*conn
)
373 crypto_public_key_free(conn
->server_rsa_key
);
374 tlsv1_record_set_cipher_suite(&conn
->rl
, TLS_NULL_WITH_NULL_NULL
);
375 tlsv1_record_change_write_cipher(&conn
->rl
);
376 tlsv1_record_change_read_cipher(&conn
->rl
);
377 tls_verify_hash_free(&conn
->verify
);
378 os_free(conn
->client_hello_ext
);
379 tlsv1_client_free_dh(conn
);
380 tlsv1_cred_free(conn
->cred
);
386 * tlsv1_client_established - Check whether connection has been established
387 * @conn: TLSv1 client connection data from tlsv1_client_init()
388 * Returns: 1 if connection is established, 0 if not
390 int tlsv1_client_established(struct tlsv1_client
*conn
)
392 return conn
->state
== ESTABLISHED
;
397 * tlsv1_client_prf - Use TLS-PRF to derive keying material
398 * @conn: TLSv1 client connection data from tlsv1_client_init()
399 * @label: Label (e.g., description of the key) for PRF
400 * @server_random_first: seed is 0 = client_random|server_random,
401 * 1 = server_random|client_random
402 * @out: Buffer for output data from TLS-PRF
403 * @out_len: Length of the output buffer
404 * Returns: 0 on success, -1 on failure
406 int tlsv1_client_prf(struct tlsv1_client
*conn
, const char *label
,
407 int server_random_first
, u8
*out
, size_t out_len
)
409 u8 seed
[2 * TLS_RANDOM_LEN
];
411 if (conn
->state
!= ESTABLISHED
)
414 if (server_random_first
) {
415 os_memcpy(seed
, conn
->server_random
, TLS_RANDOM_LEN
);
416 os_memcpy(seed
+ TLS_RANDOM_LEN
, conn
->client_random
,
419 os_memcpy(seed
, conn
->client_random
, TLS_RANDOM_LEN
);
420 os_memcpy(seed
+ TLS_RANDOM_LEN
, conn
->server_random
,
424 return tls_prf(conn
->master_secret
, TLS_MASTER_SECRET_LEN
,
425 label
, seed
, 2 * TLS_RANDOM_LEN
, out
, out_len
);
430 * tlsv1_client_get_cipher - Get current cipher name
431 * @conn: TLSv1 client connection data from tlsv1_client_init()
432 * @buf: Buffer for the cipher name
434 * Returns: 0 on success, -1 on failure
436 * Get the name of the currently used cipher.
438 int tlsv1_client_get_cipher(struct tlsv1_client
*conn
, char *buf
,
443 switch (conn
->rl
.cipher_suite
) {
444 case TLS_RSA_WITH_RC4_128_MD5
:
447 case TLS_RSA_WITH_RC4_128_SHA
:
450 case TLS_RSA_WITH_DES_CBC_SHA
:
451 cipher
= "DES-CBC-SHA";
453 case TLS_RSA_WITH_3DES_EDE_CBC_SHA
:
454 cipher
= "DES-CBC3-SHA";
456 case TLS_DH_anon_WITH_AES_128_CBC_SHA
:
457 cipher
= "ADH-AES-128-SHA";
459 case TLS_RSA_WITH_AES_256_CBC_SHA
:
460 cipher
= "AES-256-SHA";
462 case TLS_RSA_WITH_AES_128_CBC_SHA
:
463 cipher
= "AES-128-SHA";
469 if (os_strlcpy(buf
, cipher
, buflen
) >= buflen
)
476 * tlsv1_client_shutdown - Shutdown TLS connection
477 * @conn: TLSv1 client connection data from tlsv1_client_init()
478 * Returns: 0 on success, -1 on failure
480 int tlsv1_client_shutdown(struct tlsv1_client
*conn
)
482 conn
->state
= CLIENT_HELLO
;
484 if (tls_verify_hash_init(&conn
->verify
) < 0) {
485 wpa_printf(MSG_DEBUG
, "TLSv1: Failed to re-initialize verify "
490 tlsv1_record_set_cipher_suite(&conn
->rl
, TLS_NULL_WITH_NULL_NULL
);
491 tlsv1_record_change_write_cipher(&conn
->rl
);
492 tlsv1_record_change_read_cipher(&conn
->rl
);
494 conn
->certificate_requested
= 0;
495 crypto_public_key_free(conn
->server_rsa_key
);
496 conn
->server_rsa_key
= NULL
;
497 conn
->session_resumed
= 0;
504 * tlsv1_client_resumed - Was session resumption used
505 * @conn: TLSv1 client connection data from tlsv1_client_init()
506 * Returns: 1 if current session used session resumption, 0 if not
508 int tlsv1_client_resumed(struct tlsv1_client
*conn
)
510 return !!conn
->session_resumed
;
515 * tlsv1_client_hello_ext - Set TLS extension for ClientHello
516 * @conn: TLSv1 client connection data from tlsv1_client_init()
517 * @ext_type: Extension type
518 * @data: Extension payload (%NULL to remove extension)
519 * @data_len: Extension payload length
520 * Returns: 0 on success, -1 on failure
522 int tlsv1_client_hello_ext(struct tlsv1_client
*conn
, int ext_type
,
523 const u8
*data
, size_t data_len
)
527 conn
->session_ticket_included
= 0;
528 os_free(conn
->client_hello_ext
);
529 conn
->client_hello_ext
= NULL
;
530 conn
->client_hello_ext_len
= 0;
532 if (data
== NULL
|| data_len
== 0)
535 pos
= conn
->client_hello_ext
= os_malloc(6 + data_len
);
539 WPA_PUT_BE16(pos
, 4 + data_len
);
541 WPA_PUT_BE16(pos
, ext_type
);
543 WPA_PUT_BE16(pos
, data_len
);
545 os_memcpy(pos
, data
, data_len
);
546 conn
->client_hello_ext_len
= 6 + data_len
;
548 if (ext_type
== TLS_EXT_PAC_OPAQUE
) {
549 conn
->session_ticket_included
= 1;
550 wpa_printf(MSG_DEBUG
, "TLSv1: Using session ticket");
558 * tlsv1_client_get_keys - Get master key and random data from TLS connection
559 * @conn: TLSv1 client connection data from tlsv1_client_init()
560 * @keys: Structure of key/random data (filled on success)
561 * Returns: 0 on success, -1 on failure
563 int tlsv1_client_get_keys(struct tlsv1_client
*conn
, struct tls_keys
*keys
)
565 os_memset(keys
, 0, sizeof(*keys
));
566 if (conn
->state
== CLIENT_HELLO
)
569 keys
->client_random
= conn
->client_random
;
570 keys
->client_random_len
= TLS_RANDOM_LEN
;
572 if (conn
->state
!= SERVER_HELLO
) {
573 keys
->server_random
= conn
->server_random
;
574 keys
->server_random_len
= TLS_RANDOM_LEN
;
575 keys
->master_key
= conn
->master_secret
;
576 keys
->master_key_len
= TLS_MASTER_SECRET_LEN
;
584 * tlsv1_client_get_keyblock_size - Get TLS key_block size
585 * @conn: TLSv1 client connection data from tlsv1_client_init()
586 * Returns: Size of the key_block for the negotiated cipher suite or -1 on
589 int tlsv1_client_get_keyblock_size(struct tlsv1_client
*conn
)
591 if (conn
->state
== CLIENT_HELLO
|| conn
->state
== SERVER_HELLO
)
594 return 2 * (conn
->rl
.hash_size
+ conn
->rl
.key_material_len
+
600 * tlsv1_client_set_cipher_list - Configure acceptable cipher suites
601 * @conn: TLSv1 client connection data from tlsv1_client_init()
602 * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers
604 * Returns: 0 on success, -1 on failure
606 int tlsv1_client_set_cipher_list(struct tlsv1_client
*conn
, u8
*ciphers
)
611 /* TODO: implement proper configuration of cipher suites */
612 if (ciphers
[0] == TLS_CIPHER_ANON_DH_AES128_SHA
) {
614 suites
= conn
->cipher_suites
;
615 #ifndef CONFIG_CRYPTO_INTERNAL
616 suites
[count
++] = TLS_DH_anon_WITH_AES_256_CBC_SHA
;
617 #endif /* CONFIG_CRYPTO_INTERNAL */
618 suites
[count
++] = TLS_DH_anon_WITH_AES_128_CBC_SHA
;
619 suites
[count
++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
;
620 suites
[count
++] = TLS_DH_anon_WITH_RC4_128_MD5
;
621 suites
[count
++] = TLS_DH_anon_WITH_DES_CBC_SHA
;
624 * Cisco AP (at least 350 and 1200 series) local authentication
625 * server does not know how to search cipher suites from the
626 * list and seem to require that the last entry in the list is
627 * the one that it wants to use. However, TLS specification
628 * requires the list to be in the client preference order. As a
629 * workaround, add anon-DH AES-128-SHA1 again at the end of the
630 * list to allow the Cisco code to find it.
632 suites
[count
++] = TLS_DH_anon_WITH_AES_128_CBC_SHA
;
633 conn
->num_cipher_suites
= count
;
641 * tlsv1_client_set_cred - Set client credentials
642 * @conn: TLSv1 client connection data from tlsv1_client_init()
643 * @cred: Credentials from tlsv1_cred_alloc()
644 * Returns: 0 on success, -1 on failure
646 * On success, the client takes ownership of the credentials block and caller
647 * must not free it. On failure, caller is responsible for freeing the
650 int tlsv1_client_set_cred(struct tlsv1_client
*conn
,
651 struct tlsv1_credentials
*cred
)
653 tlsv1_cred_free(conn
->cred
);
659 void tlsv1_client_set_session_ticket_cb(struct tlsv1_client
*conn
,
660 tlsv1_client_session_ticket_cb cb
,
663 wpa_printf(MSG_DEBUG
, "TLSv1: SessionTicket callback set %p (ctx %p)",
665 conn
->session_ticket_cb
= cb
;
666 conn
->session_ticket_cb_ctx
= ctx
;