]>
Commit | Line | Data |
---|---|---|
6fc6879b JM |
1 | /* |
2 | * TLSv1 server (RFC 2246) | |
3 | * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> | |
4 | * | |
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. | |
8 | * | |
9 | * Alternatively, this software may be distributed under the terms of BSD | |
10 | * license. | |
11 | * | |
12 | * See README and COPYING for more details. | |
13 | */ | |
14 | ||
15 | #include "includes.h" | |
16 | ||
17 | #include "common.h" | |
03da66bd JM |
18 | #include "crypto/sha1.h" |
19 | #include "crypto/tls.h" | |
6fc6879b JM |
20 | #include "tlsv1_common.h" |
21 | #include "tlsv1_record.h" | |
22 | #include "tlsv1_server.h" | |
23 | #include "tlsv1_server_i.h" | |
24 | ||
25 | /* TODO: | |
26 | * Support for a message fragmented across several records (RFC 2246, 6.2.1) | |
27 | */ | |
28 | ||
29 | ||
30 | void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description) | |
31 | { | |
32 | conn->alert_level = level; | |
33 | conn->alert_description = description; | |
34 | } | |
35 | ||
36 | ||
37 | int tlsv1_server_derive_keys(struct tlsv1_server *conn, | |
38 | const u8 *pre_master_secret, | |
39 | size_t pre_master_secret_len) | |
40 | { | |
41 | u8 seed[2 * TLS_RANDOM_LEN]; | |
42 | u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; | |
43 | u8 *pos; | |
44 | size_t key_block_len; | |
45 | ||
46 | if (pre_master_secret) { | |
47 | wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", | |
48 | pre_master_secret, pre_master_secret_len); | |
49 | os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); | |
50 | os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, | |
51 | TLS_RANDOM_LEN); | |
52 | if (tls_prf(pre_master_secret, pre_master_secret_len, | |
53 | "master secret", seed, 2 * TLS_RANDOM_LEN, | |
54 | conn->master_secret, TLS_MASTER_SECRET_LEN)) { | |
55 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " | |
56 | "master_secret"); | |
57 | return -1; | |
58 | } | |
59 | wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", | |
60 | conn->master_secret, TLS_MASTER_SECRET_LEN); | |
61 | } | |
62 | ||
63 | os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); | |
64 | os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); | |
65 | key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + | |
66 | conn->rl.iv_size); | |
67 | if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, | |
68 | "key expansion", seed, 2 * TLS_RANDOM_LEN, | |
69 | key_block, key_block_len)) { | |
70 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); | |
71 | return -1; | |
72 | } | |
73 | wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", | |
74 | key_block, key_block_len); | |
75 | ||
76 | pos = key_block; | |
77 | ||
78 | /* client_write_MAC_secret */ | |
79 | os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); | |
80 | pos += conn->rl.hash_size; | |
81 | /* server_write_MAC_secret */ | |
82 | os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); | |
83 | pos += conn->rl.hash_size; | |
84 | ||
85 | /* client_write_key */ | |
86 | os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); | |
87 | pos += conn->rl.key_material_len; | |
88 | /* server_write_key */ | |
89 | os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); | |
90 | pos += conn->rl.key_material_len; | |
91 | ||
92 | /* client_write_IV */ | |
93 | os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); | |
94 | pos += conn->rl.iv_size; | |
95 | /* server_write_IV */ | |
96 | os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); | |
97 | pos += conn->rl.iv_size; | |
98 | ||
99 | return 0; | |
100 | } | |
101 | ||
102 | ||
103 | /** | |
104 | * tlsv1_server_handshake - Process TLS handshake | |
105 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
106 | * @in_data: Input data from TLS peer | |
107 | * @in_len: Input data length | |
108 | * @out_len: Length of the output buffer. | |
109 | * Returns: Pointer to output data, %NULL on failure | |
110 | */ | |
111 | u8 * tlsv1_server_handshake(struct tlsv1_server *conn, | |
112 | const u8 *in_data, size_t in_len, | |
113 | size_t *out_len) | |
114 | { | |
115 | const u8 *pos, *end; | |
116 | u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; | |
117 | size_t in_msg_len; | |
118 | ||
119 | if (in_data == NULL || in_len == 0) { | |
120 | wpa_printf(MSG_DEBUG, "TLSv1: No input data to server"); | |
121 | return NULL; | |
122 | } | |
123 | ||
124 | pos = in_data; | |
125 | end = in_data + in_len; | |
126 | in_msg = os_malloc(in_len); | |
127 | if (in_msg == NULL) | |
128 | return NULL; | |
129 | ||
130 | /* Each received packet may include multiple records */ | |
131 | while (pos < end) { | |
132 | in_msg_len = in_len; | |
133 | if (tlsv1_record_receive(&conn->rl, pos, end - pos, | |
134 | in_msg, &in_msg_len, &alert)) { | |
135 | wpa_printf(MSG_DEBUG, "TLSv1: Processing received " | |
136 | "record failed"); | |
137 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); | |
138 | goto failed; | |
139 | } | |
140 | ct = pos[0]; | |
141 | ||
142 | in_pos = in_msg; | |
143 | in_end = in_msg + in_msg_len; | |
144 | ||
145 | /* Each received record may include multiple messages of the | |
146 | * same ContentType. */ | |
147 | while (in_pos < in_end) { | |
148 | in_msg_len = in_end - in_pos; | |
149 | if (tlsv1_server_process_handshake(conn, ct, in_pos, | |
150 | &in_msg_len) < 0) | |
151 | goto failed; | |
152 | in_pos += in_msg_len; | |
153 | } | |
154 | ||
155 | pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); | |
156 | } | |
157 | ||
158 | os_free(in_msg); | |
159 | in_msg = NULL; | |
160 | ||
161 | msg = tlsv1_server_handshake_write(conn, out_len); | |
162 | ||
163 | failed: | |
164 | os_free(in_msg); | |
165 | if (conn->alert_level) { | |
166 | if (conn->state == FAILED) { | |
167 | /* Avoid alert loops */ | |
168 | wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop"); | |
169 | os_free(msg); | |
170 | return NULL; | |
171 | } | |
172 | conn->state = FAILED; | |
173 | os_free(msg); | |
174 | msg = tlsv1_server_send_alert(conn, conn->alert_level, | |
175 | conn->alert_description, | |
176 | out_len); | |
177 | } | |
178 | ||
179 | return msg; | |
180 | } | |
181 | ||
182 | ||
183 | /** | |
184 | * tlsv1_server_encrypt - Encrypt data into TLS tunnel | |
185 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
186 | * @in_data: Pointer to plaintext data to be encrypted | |
187 | * @in_len: Input buffer length | |
188 | * @out_data: Pointer to output buffer (encrypted TLS data) | |
189 | * @out_len: Maximum out_data length | |
190 | * Returns: Number of bytes written to out_data, -1 on failure | |
191 | * | |
192 | * This function is used after TLS handshake has been completed successfully to | |
193 | * send data in the encrypted tunnel. | |
194 | */ | |
195 | int tlsv1_server_encrypt(struct tlsv1_server *conn, | |
196 | const u8 *in_data, size_t in_len, | |
197 | u8 *out_data, size_t out_len) | |
198 | { | |
199 | size_t rlen; | |
200 | ||
201 | wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", | |
202 | in_data, in_len); | |
203 | ||
204 | os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); | |
205 | ||
206 | if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, | |
207 | out_data, out_len, in_len, &rlen) < 0) { | |
208 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); | |
209 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, | |
210 | TLS_ALERT_INTERNAL_ERROR); | |
211 | return -1; | |
212 | } | |
213 | ||
214 | return rlen; | |
215 | } | |
216 | ||
217 | ||
218 | /** | |
219 | * tlsv1_server_decrypt - Decrypt data from TLS tunnel | |
220 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
221 | * @in_data: Pointer to input buffer (encrypted TLS data) | |
222 | * @in_len: Input buffer length | |
223 | * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) | |
224 | * @out_len: Maximum out_data length | |
225 | * Returns: Number of bytes written to out_data, -1 on failure | |
226 | * | |
227 | * This function is used after TLS handshake has been completed successfully to | |
228 | * receive data from the encrypted tunnel. | |
229 | */ | |
230 | int tlsv1_server_decrypt(struct tlsv1_server *conn, | |
231 | const u8 *in_data, size_t in_len, | |
232 | u8 *out_data, size_t out_len) | |
233 | { | |
234 | const u8 *in_end, *pos; | |
235 | int res; | |
236 | u8 alert, *out_end, *out_pos; | |
237 | size_t olen; | |
238 | ||
239 | pos = in_data; | |
240 | in_end = in_data + in_len; | |
241 | out_pos = out_data; | |
242 | out_end = out_data + out_len; | |
243 | ||
244 | while (pos < in_end) { | |
245 | if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { | |
246 | wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " | |
247 | "0x%x", pos[0]); | |
248 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, | |
249 | TLS_ALERT_UNEXPECTED_MESSAGE); | |
250 | return -1; | |
251 | } | |
252 | ||
253 | olen = out_end - out_pos; | |
254 | res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, | |
255 | out_pos, &olen, &alert); | |
256 | if (res < 0) { | |
257 | wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " | |
258 | "failed"); | |
259 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); | |
260 | return -1; | |
261 | } | |
262 | out_pos += olen; | |
263 | if (out_pos > out_end) { | |
264 | wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " | |
265 | "for processing the received record"); | |
266 | tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, | |
267 | TLS_ALERT_INTERNAL_ERROR); | |
268 | return -1; | |
269 | } | |
270 | ||
271 | pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); | |
272 | } | |
273 | ||
274 | return out_pos - out_data; | |
275 | } | |
276 | ||
277 | ||
278 | /** | |
279 | * tlsv1_server_global_init - Initialize TLSv1 server | |
280 | * Returns: 0 on success, -1 on failure | |
281 | * | |
282 | * This function must be called before using any other TLSv1 server functions. | |
283 | */ | |
284 | int tlsv1_server_global_init(void) | |
285 | { | |
286 | return crypto_global_init(); | |
287 | } | |
288 | ||
289 | ||
290 | /** | |
291 | * tlsv1_server_global_deinit - Deinitialize TLSv1 server | |
292 | * | |
293 | * This function can be used to deinitialize the TLSv1 server that was | |
294 | * initialized by calling tlsv1_server_global_init(). No TLSv1 server functions | |
295 | * can be called after this before calling tlsv1_server_global_init() again. | |
296 | */ | |
297 | void tlsv1_server_global_deinit(void) | |
298 | { | |
299 | crypto_global_deinit(); | |
300 | } | |
301 | ||
302 | ||
303 | /** | |
304 | * tlsv1_server_init - Initialize TLSv1 server connection | |
305 | * @cred: Pointer to server credentials from tlsv1_server_cred_alloc() | |
306 | * Returns: Pointer to TLSv1 server connection data or %NULL on failure | |
307 | */ | |
308 | struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred) | |
309 | { | |
310 | struct tlsv1_server *conn; | |
311 | size_t count; | |
312 | u16 *suites; | |
313 | ||
314 | conn = os_zalloc(sizeof(*conn)); | |
315 | if (conn == NULL) | |
316 | return NULL; | |
317 | ||
318 | conn->cred = cred; | |
319 | ||
320 | conn->state = CLIENT_HELLO; | |
321 | ||
322 | if (tls_verify_hash_init(&conn->verify) < 0) { | |
323 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " | |
324 | "hash"); | |
325 | os_free(conn); | |
326 | return NULL; | |
327 | } | |
328 | ||
329 | count = 0; | |
330 | suites = conn->cipher_suites; | |
331 | #ifndef CONFIG_CRYPTO_INTERNAL | |
332 | suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; | |
333 | #endif /* CONFIG_CRYPTO_INTERNAL */ | |
334 | suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; | |
335 | suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; | |
336 | suites[count++] = TLS_RSA_WITH_RC4_128_SHA; | |
337 | suites[count++] = TLS_RSA_WITH_RC4_128_MD5; | |
338 | conn->num_cipher_suites = count; | |
339 | ||
340 | return conn; | |
341 | } | |
342 | ||
343 | ||
344 | static void tlsv1_server_clear_data(struct tlsv1_server *conn) | |
345 | { | |
346 | tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); | |
347 | tlsv1_record_change_write_cipher(&conn->rl); | |
348 | tlsv1_record_change_read_cipher(&conn->rl); | |
349 | tls_verify_hash_free(&conn->verify); | |
350 | ||
351 | crypto_public_key_free(conn->client_rsa_key); | |
352 | conn->client_rsa_key = NULL; | |
353 | ||
354 | os_free(conn->session_ticket); | |
355 | conn->session_ticket = NULL; | |
356 | conn->session_ticket_len = 0; | |
357 | conn->use_session_ticket = 0; | |
358 | ||
359 | os_free(conn->dh_secret); | |
360 | conn->dh_secret = NULL; | |
361 | conn->dh_secret_len = 0; | |
362 | } | |
363 | ||
364 | ||
365 | /** | |
366 | * tlsv1_server_deinit - Deinitialize TLSv1 server connection | |
367 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
368 | */ | |
369 | void tlsv1_server_deinit(struct tlsv1_server *conn) | |
370 | { | |
371 | tlsv1_server_clear_data(conn); | |
372 | os_free(conn); | |
373 | } | |
374 | ||
375 | ||
376 | /** | |
377 | * tlsv1_server_established - Check whether connection has been established | |
378 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
379 | * Returns: 1 if connection is established, 0 if not | |
380 | */ | |
381 | int tlsv1_server_established(struct tlsv1_server *conn) | |
382 | { | |
383 | return conn->state == ESTABLISHED; | |
384 | } | |
385 | ||
386 | ||
387 | /** | |
388 | * tlsv1_server_prf - Use TLS-PRF to derive keying material | |
389 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
390 | * @label: Label (e.g., description of the key) for PRF | |
391 | * @server_random_first: seed is 0 = client_random|server_random, | |
392 | * 1 = server_random|client_random | |
393 | * @out: Buffer for output data from TLS-PRF | |
394 | * @out_len: Length of the output buffer | |
395 | * Returns: 0 on success, -1 on failure | |
396 | */ | |
397 | int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, | |
398 | int server_random_first, u8 *out, size_t out_len) | |
399 | { | |
400 | u8 seed[2 * TLS_RANDOM_LEN]; | |
401 | ||
402 | if (conn->state != ESTABLISHED) | |
403 | return -1; | |
404 | ||
405 | if (server_random_first) { | |
406 | os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); | |
407 | os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, | |
408 | TLS_RANDOM_LEN); | |
409 | } else { | |
410 | os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); | |
411 | os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, | |
412 | TLS_RANDOM_LEN); | |
413 | } | |
414 | ||
415 | return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, | |
416 | label, seed, 2 * TLS_RANDOM_LEN, out, out_len); | |
417 | } | |
418 | ||
419 | ||
420 | /** | |
421 | * tlsv1_server_get_cipher - Get current cipher name | |
422 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
423 | * @buf: Buffer for the cipher name | |
424 | * @buflen: buf size | |
425 | * Returns: 0 on success, -1 on failure | |
426 | * | |
427 | * Get the name of the currently used cipher. | |
428 | */ | |
429 | int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, | |
430 | size_t buflen) | |
431 | { | |
432 | char *cipher; | |
433 | ||
434 | switch (conn->rl.cipher_suite) { | |
435 | case TLS_RSA_WITH_RC4_128_MD5: | |
436 | cipher = "RC4-MD5"; | |
437 | break; | |
438 | case TLS_RSA_WITH_RC4_128_SHA: | |
439 | cipher = "RC4-SHA"; | |
440 | break; | |
441 | case TLS_RSA_WITH_DES_CBC_SHA: | |
442 | cipher = "DES-CBC-SHA"; | |
443 | break; | |
444 | case TLS_RSA_WITH_3DES_EDE_CBC_SHA: | |
445 | cipher = "DES-CBC3-SHA"; | |
446 | break; | |
447 | case TLS_DH_anon_WITH_AES_128_CBC_SHA: | |
448 | cipher = "ADH-AES-128-SHA"; | |
449 | break; | |
450 | case TLS_RSA_WITH_AES_256_CBC_SHA: | |
451 | cipher = "AES-256-SHA"; | |
452 | break; | |
453 | case TLS_RSA_WITH_AES_128_CBC_SHA: | |
454 | cipher = "AES-128-SHA"; | |
455 | break; | |
456 | default: | |
457 | return -1; | |
458 | } | |
459 | ||
460 | if (os_strlcpy(buf, cipher, buflen) >= buflen) | |
461 | return -1; | |
462 | return 0; | |
463 | } | |
464 | ||
465 | ||
466 | /** | |
467 | * tlsv1_server_shutdown - Shutdown TLS connection | |
468 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
469 | * Returns: 0 on success, -1 on failure | |
470 | */ | |
471 | int tlsv1_server_shutdown(struct tlsv1_server *conn) | |
472 | { | |
473 | conn->state = CLIENT_HELLO; | |
474 | ||
475 | if (tls_verify_hash_init(&conn->verify) < 0) { | |
476 | wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " | |
477 | "hash"); | |
478 | return -1; | |
479 | } | |
480 | ||
481 | tlsv1_server_clear_data(conn); | |
482 | ||
483 | return 0; | |
484 | } | |
485 | ||
486 | ||
487 | /** | |
488 | * tlsv1_server_resumed - Was session resumption used | |
489 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
490 | * Returns: 1 if current session used session resumption, 0 if not | |
491 | */ | |
492 | int tlsv1_server_resumed(struct tlsv1_server *conn) | |
493 | { | |
494 | return 0; | |
495 | } | |
496 | ||
497 | ||
498 | /** | |
499 | * tlsv1_server_get_keys - Get master key and random data from TLS connection | |
500 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
501 | * @keys: Structure of key/random data (filled on success) | |
502 | * Returns: 0 on success, -1 on failure | |
503 | */ | |
504 | int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys) | |
505 | { | |
506 | os_memset(keys, 0, sizeof(*keys)); | |
507 | if (conn->state == CLIENT_HELLO) | |
508 | return -1; | |
509 | ||
510 | keys->client_random = conn->client_random; | |
511 | keys->client_random_len = TLS_RANDOM_LEN; | |
512 | ||
513 | if (conn->state != SERVER_HELLO) { | |
514 | keys->server_random = conn->server_random; | |
515 | keys->server_random_len = TLS_RANDOM_LEN; | |
516 | keys->master_key = conn->master_secret; | |
517 | keys->master_key_len = TLS_MASTER_SECRET_LEN; | |
518 | } | |
519 | ||
520 | return 0; | |
521 | } | |
522 | ||
523 | ||
524 | /** | |
525 | * tlsv1_server_get_keyblock_size - Get TLS key_block size | |
526 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
527 | * Returns: Size of the key_block for the negotiated cipher suite or -1 on | |
528 | * failure | |
529 | */ | |
530 | int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn) | |
531 | { | |
532 | if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) | |
533 | return -1; | |
534 | ||
535 | return 2 * (conn->rl.hash_size + conn->rl.key_material_len + | |
536 | conn->rl.iv_size); | |
537 | } | |
538 | ||
539 | ||
540 | /** | |
541 | * tlsv1_server_set_cipher_list - Configure acceptable cipher suites | |
542 | * @conn: TLSv1 server connection data from tlsv1_server_init() | |
543 | * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers | |
544 | * (TLS_CIPHER_*). | |
545 | * Returns: 0 on success, -1 on failure | |
546 | */ | |
547 | int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers) | |
548 | { | |
1e5839e0 | 549 | #ifdef EAP_SERVER_FAST |
6fc6879b JM |
550 | size_t count; |
551 | u16 *suites; | |
552 | ||
553 | /* TODO: implement proper configuration of cipher suites */ | |
554 | if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { | |
555 | count = 0; | |
556 | suites = conn->cipher_suites; | |
557 | #ifndef CONFIG_CRYPTO_INTERNAL | |
558 | suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; | |
559 | #endif /* CONFIG_CRYPTO_INTERNAL */ | |
560 | suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; | |
561 | suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; | |
562 | suites[count++] = TLS_RSA_WITH_RC4_128_SHA; | |
563 | suites[count++] = TLS_RSA_WITH_RC4_128_MD5; | |
564 | #ifndef CONFIG_CRYPTO_INTERNAL | |
565 | suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; | |
566 | #endif /* CONFIG_CRYPTO_INTERNAL */ | |
567 | suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; | |
568 | suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; | |
569 | suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; | |
570 | suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; | |
571 | conn->num_cipher_suites = count; | |
572 | } | |
573 | ||
574 | return 0; | |
1e5839e0 | 575 | #else /* EAP_SERVER_FAST */ |
6fc6879b | 576 | return -1; |
1e5839e0 | 577 | #endif /* EAP_SERVER_FAST */ |
6fc6879b JM |
578 | } |
579 | ||
580 | ||
581 | int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer) | |
582 | { | |
583 | conn->verify_peer = verify_peer; | |
584 | return 0; | |
585 | } | |
586 | ||
587 | ||
588 | void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, | |
589 | tlsv1_server_session_ticket_cb cb, | |
590 | void *ctx) | |
591 | { | |
592 | wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", | |
593 | cb, ctx); | |
594 | conn->session_ticket_cb = cb; | |
595 | conn->session_ticket_cb_ctx = ctx; | |
596 | } |