2 * WPA Supplicant / SSL/TLS interface functions for openssl
3 * Copyright (c) 2004-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.
16 #include <gnutls/gnutls.h>
17 #include <gnutls/x509.h>
19 #include <gnutls/pkcs12.h>
20 #endif /* PKCS12_FUNCS */
22 #ifdef CONFIG_GNUTLS_EXTRA
23 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
25 #include <gnutls/extra.h>
26 #if LIBGNUTLS_VERSION_NUMBER == 0x010302
27 /* This function is not included in the current gnutls/extra.h even though it
28 * should be, so define it here as a workaround for the time being. */
29 int gnutls_ia_verify_endphase(gnutls_session_t session
, char *checksum
);
30 #endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */
31 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
32 #endif /* CONFIG_GNUTLS_EXTRA */
38 #define TLS_RANDOM_SIZE 32
39 #define TLS_MASTER_SIZE 48
42 #if LIBGNUTLS_VERSION_NUMBER < 0x010302
43 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require
44 * use of internal structures to get the master_secret and
45 * {server,client}_random.
47 #define GNUTLS_INTERNAL_STRUCTURE_HACK
48 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
51 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
53 * It looks like gnutls does not provide access to client/server_random and
54 * master_key. This is somewhat unfortunate since these are needed for key
55 * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
56 * hack that copies the gnutls_session_int definition from gnutls_int.h so that
57 * we can get the needed information.
61 typedef unsigned char opaque
;
67 gnutls_connection_end_t entity
;
68 gnutls_kx_algorithm_t kx_algorithm
;
69 gnutls_cipher_algorithm_t read_bulk_cipher_algorithm
;
70 gnutls_mac_algorithm_t read_mac_algorithm
;
71 gnutls_compression_method_t read_compression_algorithm
;
72 gnutls_cipher_algorithm_t write_bulk_cipher_algorithm
;
73 gnutls_mac_algorithm_t write_mac_algorithm
;
74 gnutls_compression_method_t write_compression_algorithm
;
75 cipher_suite_st current_cipher_suite
;
76 opaque master_secret
[TLS_MASTER_SIZE
];
77 opaque client_random
[TLS_RANDOM_SIZE
];
78 opaque server_random
[TLS_RANDOM_SIZE
];
79 /* followed by stuff we are not interested in */
80 } security_parameters_st
;
82 struct gnutls_session_int
{
83 security_parameters_st security_parameters
;
84 /* followed by things we are not interested in */
86 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
88 static int tls_gnutls_ref_count
= 0;
91 /* Data for session resumption */
93 size_t session_data_size
;
98 gnutls_certificate_credentials_t xcred
;
101 struct tls_connection
{
102 gnutls_session session
;
103 char *subject_match
, *altsubject_match
;
104 int read_alerts
, write_alerts
, failed
;
106 u8
*pre_shared_secret
;
107 size_t pre_shared_secret_len
;
111 u8
*push_buf
, *pull_buf
, *pull_buf_offset
;
112 size_t push_buf_len
, pull_buf_len
;
115 gnutls_certificate_credentials_t xcred
;
118 int final_phase_finished
;
121 gnutls_ia_server_credentials_t iacred_srv
;
122 gnutls_ia_client_credentials_t iacred_cli
;
124 /* Session keys generated in the current phase for inner secret
125 * permutation before generating/verifying PhaseFinished. */
127 size_t session_keys_len
;
129 u8 inner_secret
[TLS_MASTER_SIZE
];
130 #endif /* GNUTLS_IA */
134 static void tls_log_func(int level
, const char *msg
)
137 if (level
== 6 || level
== 7) {
138 /* These levels seem to be mostly I/O debug and msg dumps */
147 while (*pos
!= '\0') {
154 wpa_printf(level
> 3 ? MSG_MSGDUMP
: MSG_DEBUG
,
155 "gnutls<%d> %s", level
, s
);
160 extern int wpa_debug_show_keys
;
162 void * tls_init(const struct tls_config
*conf
)
164 struct tls_global
*global
;
166 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
167 /* Because of the horrible hack to get master_secret and client/server
168 * random, we need to make sure that the gnutls version is something
169 * that is expected to have same structure definition for the session
172 const char *ok_ver
[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
176 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
178 global
= os_zalloc(sizeof(*global
));
182 if (tls_gnutls_ref_count
== 0 && gnutls_global_init() < 0) {
186 tls_gnutls_ref_count
++;
188 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
189 ver
= gnutls_check_version(NULL
);
194 wpa_printf(MSG_DEBUG
, "%s - gnutls version %s", __func__
, ver
);
195 for (i
= 0; ok_ver
[i
]; i
++) {
196 if (strcmp(ok_ver
[i
], ver
) == 0)
199 if (ok_ver
[i
] == NULL
) {
200 wpa_printf(MSG_INFO
, "Untested gnutls version %s - this needs "
201 "to be tested and enabled in tls_gnutls.c", ver
);
205 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
207 gnutls_global_set_log_function(tls_log_func
);
208 if (wpa_debug_show_keys
)
209 gnutls_global_set_log_level(11);
214 void tls_deinit(void *ssl_ctx
)
216 struct tls_global
*global
= ssl_ctx
;
218 if (global
->params_set
)
219 gnutls_certificate_free_credentials(global
->xcred
);
220 os_free(global
->session_data
);
224 tls_gnutls_ref_count
--;
225 if (tls_gnutls_ref_count
== 0)
226 gnutls_global_deinit();
230 int tls_get_errors(void *ssl_ctx
)
236 static ssize_t
tls_pull_func(gnutls_transport_ptr ptr
, void *buf
,
239 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
241 if (conn
->pull_buf
== NULL
) {
246 end
= conn
->pull_buf
+ conn
->pull_buf_len
;
247 if ((size_t) (end
- conn
->pull_buf_offset
) < len
)
248 len
= end
- conn
->pull_buf_offset
;
249 os_memcpy(buf
, conn
->pull_buf_offset
, len
);
250 conn
->pull_buf_offset
+= len
;
251 if (conn
->pull_buf_offset
== end
) {
252 wpa_printf(MSG_DEBUG
, "%s - pull_buf consumed", __func__
);
253 os_free(conn
->pull_buf
);
254 conn
->pull_buf
= conn
->pull_buf_offset
= NULL
;
255 conn
->pull_buf_len
= 0;
257 wpa_printf(MSG_DEBUG
, "%s - %d bytes remaining in pull_buf",
258 __func__
, end
- conn
->pull_buf_offset
);
264 static ssize_t
tls_push_func(gnutls_transport_ptr ptr
, const void *buf
,
267 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
270 nbuf
= os_realloc(conn
->push_buf
, conn
->push_buf_len
+ len
);
275 os_memcpy(nbuf
+ conn
->push_buf_len
, buf
, len
);
276 conn
->push_buf
= nbuf
;
277 conn
->push_buf_len
+= len
;
283 static int tls_gnutls_init_session(struct tls_global
*global
,
284 struct tls_connection
*conn
)
286 const int cert_types
[2] = { GNUTLS_CRT_X509
, 0 };
287 const int protos
[2] = { GNUTLS_TLS1
, 0 };
290 ret
= gnutls_init(&conn
->session
,
291 global
->server
? GNUTLS_SERVER
: GNUTLS_CLIENT
);
293 wpa_printf(MSG_INFO
, "TLS: Failed to initialize new TLS "
294 "connection: %s", gnutls_strerror(ret
));
298 ret
= gnutls_set_default_priority(conn
->session
);
302 ret
= gnutls_certificate_type_set_priority(conn
->session
, cert_types
);
306 ret
= gnutls_protocol_set_priority(conn
->session
, protos
);
310 gnutls_transport_set_pull_function(conn
->session
, tls_pull_func
);
311 gnutls_transport_set_push_function(conn
->session
, tls_push_func
);
312 gnutls_transport_set_ptr(conn
->session
, (gnutls_transport_ptr
) conn
);
317 wpa_printf(MSG_INFO
, "TLS: Failed to setup new TLS connection: %s",
318 gnutls_strerror(ret
));
319 gnutls_deinit(conn
->session
);
324 struct tls_connection
* tls_connection_init(void *ssl_ctx
)
326 struct tls_global
*global
= ssl_ctx
;
327 struct tls_connection
*conn
;
330 conn
= os_zalloc(sizeof(*conn
));
334 if (tls_gnutls_init_session(global
, conn
)) {
339 if (global
->params_set
) {
340 ret
= gnutls_credentials_set(conn
->session
,
341 GNUTLS_CRD_CERTIFICATE
,
344 wpa_printf(MSG_INFO
, "Failed to configure "
345 "credentials: %s", gnutls_strerror(ret
));
351 if (gnutls_certificate_allocate_credentials(&conn
->xcred
)) {
360 void tls_connection_deinit(void *ssl_ctx
, struct tls_connection
*conn
)
366 if (conn
->iacred_srv
)
367 gnutls_ia_free_server_credentials(conn
->iacred_srv
);
368 if (conn
->iacred_cli
)
369 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
370 if (conn
->session_keys
) {
371 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
372 os_free(conn
->session_keys
);
374 #endif /* GNUTLS_IA */
376 gnutls_certificate_free_credentials(conn
->xcred
);
377 gnutls_deinit(conn
->session
);
378 os_free(conn
->pre_shared_secret
);
379 os_free(conn
->subject_match
);
380 os_free(conn
->altsubject_match
);
381 os_free(conn
->push_buf
);
382 os_free(conn
->pull_buf
);
387 int tls_connection_established(void *ssl_ctx
, struct tls_connection
*conn
)
389 return conn
? conn
->established
: 0;
393 int tls_connection_shutdown(void *ssl_ctx
, struct tls_connection
*conn
)
395 struct tls_global
*global
= ssl_ctx
;
401 /* Shutdown previous TLS connection without notifying the peer
402 * because the connection was already terminated in practice
403 * and "close notify" shutdown alert would confuse AS. */
404 gnutls_bye(conn
->session
, GNUTLS_SHUT_RDWR
);
405 os_free(conn
->push_buf
);
406 conn
->push_buf
= NULL
;
407 conn
->push_buf_len
= 0;
408 conn
->established
= 0;
409 conn
->final_phase_finished
= 0;
411 if (conn
->session_keys
) {
412 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
413 os_free(conn
->session_keys
);
415 conn
->session_keys_len
= 0;
416 #endif /* GNUTLS_IA */
418 gnutls_deinit(conn
->session
);
419 if (tls_gnutls_init_session(global
, conn
)) {
420 wpa_printf(MSG_INFO
, "GnuTLS: Failed to preparare new session "
421 "for session resumption use");
425 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
426 conn
->params_set
? conn
->xcred
:
429 wpa_printf(MSG_INFO
, "GnuTLS: Failed to configure credentials "
430 "for session resumption: %s", gnutls_strerror(ret
));
434 if (global
->session_data
) {
435 ret
= gnutls_session_set_data(conn
->session
,
436 global
->session_data
,
437 global
->session_data_size
);
439 wpa_printf(MSG_INFO
, "GnuTLS: Failed to set session "
440 "data: %s", gnutls_strerror(ret
));
450 static int tls_match_altsubject(X509
*cert
, const char *match
)
458 ext
= X509_get_ext_d2i(cert
, NID_subject_alt_name
, NULL
, NULL
);
460 for (i
= 0; ext
&& i
< sk_GENERAL_NAME_num(ext
); i
++) {
461 gen
= sk_GENERAL_NAME_value(ext
, i
);
474 wpa_printf(MSG_DEBUG
, "TLS: altSubjectName: "
475 "unsupported type=%d", gen
->type
);
482 wpa_printf(MSG_DEBUG
, "TLS: altSubjectName: %s:%s",
483 field
, gen
->d
.ia5
->data
);
484 len
= os_strlen(field
) + 1 +
485 strlen((char *) gen
->d
.ia5
->data
) + 1;
486 tmp
= os_malloc(len
);
489 snprintf(tmp
, len
, "%s:%s", field
, gen
->d
.ia5
->data
);
490 if (strstr(tmp
, match
))
501 static int tls_verify_cb(int preverify_ok
, X509_STORE_CTX
*x509_ctx
)
507 struct tls_connection
*conn
;
508 char *match
, *altmatch
;
510 err_cert
= X509_STORE_CTX_get_current_cert(x509_ctx
);
511 err
= X509_STORE_CTX_get_error(x509_ctx
);
512 depth
= X509_STORE_CTX_get_error_depth(x509_ctx
);
513 ssl
= X509_STORE_CTX_get_ex_data(x509_ctx
,
514 SSL_get_ex_data_X509_STORE_CTX_idx());
515 X509_NAME_oneline(X509_get_subject_name(err_cert
), buf
, sizeof(buf
));
517 conn
= SSL_get_app_data(ssl
);
518 match
= conn
? conn
->subject_match
: NULL
;
519 altmatch
= conn
? conn
->altsubject_match
: NULL
;
522 wpa_printf(MSG_WARNING
, "TLS: Certificate verification failed,"
523 " error %d (%s) depth %d for '%s'", err
,
524 X509_verify_cert_error_string(err
), depth
, buf
);
526 wpa_printf(MSG_DEBUG
, "TLS: tls_verify_cb - "
527 "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
529 X509_verify_cert_error_string(err
), depth
, buf
);
530 if (depth
== 0 && match
&& strstr(buf
, match
) == NULL
) {
531 wpa_printf(MSG_WARNING
, "TLS: Subject '%s' did not "
532 "match with '%s'", buf
, match
);
534 } else if (depth
== 0 && altmatch
&&
535 !tls_match_altsubject(err_cert
, altmatch
)) {
536 wpa_printf(MSG_WARNING
, "TLS: altSubjectName match "
537 "'%s' not found", altmatch
);
547 int tls_connection_set_params(void *tls_ctx
, struct tls_connection
*conn
,
548 const struct tls_connection_params
*params
)
552 if (conn
== NULL
|| params
== NULL
)
555 os_free(conn
->subject_match
);
556 conn
->subject_match
= NULL
;
557 if (params
->subject_match
) {
558 conn
->subject_match
= os_strdup(params
->subject_match
);
559 if (conn
->subject_match
== NULL
)
563 os_free(conn
->altsubject_match
);
564 conn
->altsubject_match
= NULL
;
565 if (params
->altsubject_match
) {
566 conn
->altsubject_match
= os_strdup(params
->altsubject_match
);
567 if (conn
->altsubject_match
== NULL
)
571 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
572 * to force peer validation(?) */
574 if (params
->ca_cert
) {
575 conn
->verify_peer
= 1;
576 ret
= gnutls_certificate_set_x509_trust_file(
577 conn
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_PEM
);
579 wpa_printf(MSG_DEBUG
, "Failed to read CA cert '%s' "
580 "in PEM format: %s", params
->ca_cert
,
581 gnutls_strerror(ret
));
582 ret
= gnutls_certificate_set_x509_trust_file(
583 conn
->xcred
, params
->ca_cert
,
584 GNUTLS_X509_FMT_DER
);
586 wpa_printf(MSG_DEBUG
, "Failed to read CA cert "
587 "'%s' in DER format: %s",
589 gnutls_strerror(ret
));
595 if (params
->client_cert
&& params
->private_key
) {
596 /* TODO: private_key_passwd? */
597 ret
= gnutls_certificate_set_x509_key_file(
598 conn
->xcred
, params
->client_cert
, params
->private_key
,
599 GNUTLS_X509_FMT_PEM
);
601 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
602 "in PEM format: %s", gnutls_strerror(ret
));
603 ret
= gnutls_certificate_set_x509_key_file(
604 conn
->xcred
, params
->client_cert
,
605 params
->private_key
, GNUTLS_X509_FMT_DER
);
607 wpa_printf(MSG_DEBUG
, "Failed to read client "
608 "cert/key in DER format: %s",
609 gnutls_strerror(ret
));
613 } else if (params
->private_key
) {
616 /* Try to load in PKCS#12 format */
617 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
618 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
619 conn
->xcred
, params
->private_key
, GNUTLS_X509_FMT_DER
,
620 params
->private_key_passwd
);
622 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
623 "PKCS#12 format: %s", gnutls_strerror(ret
));
627 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
628 #endif /* PKCS12_FUNCS */
631 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
637 conn
->tls_ia
= params
->tls_ia
;
638 conn
->params_set
= 1;
640 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
643 wpa_printf(MSG_INFO
, "Failed to configure credentials: %s",
644 gnutls_strerror(ret
));
648 if (conn
->iacred_cli
)
649 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
651 ret
= gnutls_ia_allocate_client_credentials(&conn
->iacred_cli
);
653 wpa_printf(MSG_DEBUG
, "Failed to allocate IA credentials: %s",
654 gnutls_strerror(ret
));
658 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_IA
,
661 wpa_printf(MSG_DEBUG
, "Failed to configure IA credentials: %s",
662 gnutls_strerror(ret
));
663 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
664 conn
->iacred_cli
= NULL
;
667 #endif /* GNUTLS_IE */
673 int tls_global_set_params(void *tls_ctx
,
674 const struct tls_connection_params
*params
)
676 struct tls_global
*global
= tls_ctx
;
679 /* Currently, global parameters are only set when running in server
683 if (global
->params_set
) {
684 gnutls_certificate_free_credentials(global
->xcred
);
685 global
->params_set
= 0;
688 ret
= gnutls_certificate_allocate_credentials(&global
->xcred
);
690 wpa_printf(MSG_DEBUG
, "Failed to allocate global credentials "
691 "%s", gnutls_strerror(ret
));
695 if (params
->ca_cert
) {
696 ret
= gnutls_certificate_set_x509_trust_file(
697 global
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_PEM
);
699 wpa_printf(MSG_DEBUG
, "Failed to read CA cert '%s' "
700 "in PEM format: %s", params
->ca_cert
,
701 gnutls_strerror(ret
));
702 ret
= gnutls_certificate_set_x509_trust_file(
703 global
->xcred
, params
->ca_cert
,
704 GNUTLS_X509_FMT_DER
);
706 wpa_printf(MSG_DEBUG
, "Failed to read CA cert "
707 "'%s' in DER format: %s",
709 gnutls_strerror(ret
));
715 if (params
->client_cert
&& params
->private_key
) {
716 /* TODO: private_key_passwd? */
717 ret
= gnutls_certificate_set_x509_key_file(
718 global
->xcred
, params
->client_cert
,
719 params
->private_key
, GNUTLS_X509_FMT_PEM
);
721 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
722 "in PEM format: %s", gnutls_strerror(ret
));
723 ret
= gnutls_certificate_set_x509_key_file(
724 global
->xcred
, params
->client_cert
,
725 params
->private_key
, GNUTLS_X509_FMT_DER
);
727 wpa_printf(MSG_DEBUG
, "Failed to read client "
728 "cert/key in DER format: %s",
729 gnutls_strerror(ret
));
733 } else if (params
->private_key
) {
736 /* Try to load in PKCS#12 format */
737 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
738 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
739 global
->xcred
, params
->private_key
,
740 GNUTLS_X509_FMT_DER
, params
->private_key_passwd
);
742 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
743 "PKCS#12 format: %s", gnutls_strerror(ret
));
747 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
748 #endif /* PKCS12_FUNCS */
751 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
757 global
->params_set
= 1;
762 gnutls_certificate_free_credentials(global
->xcred
);
767 int tls_global_set_verify(void *ssl_ctx
, int check_crl
)
774 int tls_connection_set_verify(void *ssl_ctx
, struct tls_connection
*conn
,
777 if (conn
== NULL
|| conn
->session
== NULL
)
780 conn
->verify_peer
= verify_peer
;
781 gnutls_certificate_server_set_request(conn
->session
,
782 verify_peer
? GNUTLS_CERT_REQUIRE
783 : GNUTLS_CERT_REQUEST
);
789 int tls_connection_get_keys(void *ssl_ctx
, struct tls_connection
*conn
,
790 struct tls_keys
*keys
)
792 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
793 security_parameters_st
*sec
;
794 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
796 if (conn
== NULL
|| conn
->session
== NULL
|| keys
== NULL
)
799 os_memset(keys
, 0, sizeof(*keys
));
801 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
802 sec
= &conn
->session
->security_parameters
;
803 keys
->master_key
= sec
->master_secret
;
804 keys
->master_key_len
= TLS_MASTER_SIZE
;
805 keys
->client_random
= sec
->client_random
;
806 keys
->server_random
= sec
->server_random
;
807 #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
808 keys
->client_random
=
809 (u8
*) gnutls_session_get_client_random(conn
->session
);
810 keys
->server_random
=
811 (u8
*) gnutls_session_get_server_random(conn
->session
);
812 /* No access to master_secret */
813 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
816 gnutls_ia_extract_inner_secret(conn
->session
,
817 (char *) conn
->inner_secret
);
818 keys
->inner_secret
= conn
->inner_secret
;
819 keys
->inner_secret_len
= TLS_MASTER_SIZE
;
820 #endif /* GNUTLS_IA */
822 keys
->client_random_len
= TLS_RANDOM_SIZE
;
823 keys
->server_random_len
= TLS_RANDOM_SIZE
;
829 int tls_connection_prf(void *tls_ctx
, struct tls_connection
*conn
,
830 const char *label
, int server_random_first
,
831 u8
*out
, size_t out_len
)
833 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
834 if (conn
== NULL
|| conn
->session
== NULL
)
837 return gnutls_prf(conn
->session
, os_strlen(label
), label
,
838 server_random_first
, 0, NULL
, out_len
, (char *) out
);
839 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
841 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
845 static int tls_connection_verify_peer(struct tls_connection
*conn
)
847 unsigned int status
, num_certs
, i
;
849 const gnutls_datum_t
*certs
;
850 gnutls_x509_crt_t cert
;
852 if (gnutls_certificate_verify_peers2(conn
->session
, &status
) < 0) {
853 wpa_printf(MSG_INFO
, "TLS: Failed to verify peer "
854 "certificate chain");
858 if (conn
->verify_peer
&& (status
& GNUTLS_CERT_INVALID
)) {
859 wpa_printf(MSG_INFO
, "TLS: Peer certificate not trusted");
863 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
) {
864 wpa_printf(MSG_INFO
, "TLS: Peer certificate does not have a "
869 if (status
& GNUTLS_CERT_REVOKED
) {
870 wpa_printf(MSG_INFO
, "TLS: Peer certificate has been revoked");
876 certs
= gnutls_certificate_get_peers(conn
->session
, &num_certs
);
878 wpa_printf(MSG_INFO
, "TLS: No peer certificate chain "
883 for (i
= 0; i
< num_certs
; i
++) {
886 if (gnutls_x509_crt_init(&cert
) < 0) {
887 wpa_printf(MSG_INFO
, "TLS: Certificate initialization "
892 if (gnutls_x509_crt_import(cert
, &certs
[i
],
893 GNUTLS_X509_FMT_DER
) < 0) {
894 wpa_printf(MSG_INFO
, "TLS: Could not parse peer "
895 "certificate %d/%d", i
+ 1, num_certs
);
896 gnutls_x509_crt_deinit(cert
);
900 gnutls_x509_crt_get_dn(cert
, NULL
, &len
);
902 buf
= os_malloc(len
+ 1);
904 buf
[0] = buf
[len
] = '\0';
905 gnutls_x509_crt_get_dn(cert
, buf
, &len
);
907 wpa_printf(MSG_DEBUG
, "TLS: Peer cert chain %d/%d: %s",
908 i
+ 1, num_certs
, buf
);
911 /* TODO: validate subject_match and altsubject_match */
916 if (gnutls_x509_crt_get_expiration_time(cert
) < now
.sec
||
917 gnutls_x509_crt_get_activation_time(cert
) > now
.sec
) {
918 wpa_printf(MSG_INFO
, "TLS: Peer certificate %d/%d is "
919 "not valid at this time",
921 gnutls_x509_crt_deinit(cert
);
925 gnutls_x509_crt_deinit(cert
);
932 u8
* tls_connection_handshake(void *ssl_ctx
, struct tls_connection
*conn
,
933 const u8
*in_data
, size_t in_len
,
934 size_t *out_len
, u8
**appl_data
,
935 size_t *appl_data_len
)
937 struct tls_global
*global
= ssl_ctx
;
944 if (in_data
&& in_len
) {
945 if (conn
->pull_buf
) {
946 wpa_printf(MSG_DEBUG
, "%s - %d bytes remaining in "
947 "pull_buf", __func__
, conn
->pull_buf_len
);
948 os_free(conn
->pull_buf
);
950 conn
->pull_buf
= os_malloc(in_len
);
951 if (conn
->pull_buf
== NULL
)
953 os_memcpy(conn
->pull_buf
, in_data
, in_len
);
954 conn
->pull_buf_offset
= conn
->pull_buf
;
955 conn
->pull_buf_len
= in_len
;
958 ret
= gnutls_handshake(conn
->session
);
962 if (global
->server
&& conn
->established
&&
963 conn
->push_buf
== NULL
) {
964 /* Need to return something to trigger
965 * completion of EAP-TLS. */
966 conn
->push_buf
= os_malloc(1);
969 case GNUTLS_E_FATAL_ALERT_RECEIVED
:
970 wpa_printf(MSG_DEBUG
, "%s - received fatal '%s' alert",
971 __func__
, gnutls_alert_get_name(
972 gnutls_alert_get(conn
->session
)));
976 wpa_printf(MSG_DEBUG
, "%s - gnutls_handshake failed "
977 "-> %s", __func__
, gnutls_strerror(ret
));
983 if (conn
->verify_peer
&& tls_connection_verify_peer(conn
)) {
984 wpa_printf(MSG_INFO
, "TLS: Peer certificate chain "
985 "failed validation");
990 if (conn
->tls_ia
&& !gnutls_ia_handshake_p(conn
->session
)) {
991 wpa_printf(MSG_INFO
, "TLS: No TLS/IA negotiation");
997 wpa_printf(MSG_DEBUG
, "TLS: Start TLS/IA handshake");
999 wpa_printf(MSG_DEBUG
, "TLS: Handshake completed "
1002 conn
->established
= 1;
1003 if (conn
->push_buf
== NULL
) {
1004 /* Need to return something to get final TLS ACK. */
1005 conn
->push_buf
= os_malloc(1);
1008 gnutls_session_get_data(conn
->session
, NULL
, &size
);
1009 if (global
->session_data
== NULL
||
1010 global
->session_data_size
< size
) {
1011 os_free(global
->session_data
);
1012 global
->session_data
= os_malloc(size
);
1014 if (global
->session_data
) {
1015 global
->session_data_size
= size
;
1016 gnutls_session_get_data(conn
->session
,
1017 global
->session_data
,
1018 &global
->session_data_size
);
1022 out_data
= conn
->push_buf
;
1023 *out_len
= conn
->push_buf_len
;
1024 conn
->push_buf
= NULL
;
1025 conn
->push_buf_len
= 0;
1030 u8
* tls_connection_server_handshake(void *ssl_ctx
,
1031 struct tls_connection
*conn
,
1032 const u8
*in_data
, size_t in_len
,
1035 return tls_connection_handshake(ssl_ctx
, conn
, in_data
, in_len
,
1036 out_len
, NULL
, NULL
);
1040 int tls_connection_encrypt(void *ssl_ctx
, struct tls_connection
*conn
,
1041 const u8
*in_data
, size_t in_len
,
1042 u8
*out_data
, size_t out_len
)
1048 res
= gnutls_ia_send(conn
->session
, (char *) in_data
, in_len
);
1050 #endif /* GNUTLS_IA */
1051 res
= gnutls_record_send(conn
->session
, in_data
, in_len
);
1053 wpa_printf(MSG_INFO
, "%s: Encryption failed: %s",
1054 __func__
, gnutls_strerror(res
));
1057 if (conn
->push_buf
== NULL
)
1059 if (conn
->push_buf_len
< out_len
)
1060 out_len
= conn
->push_buf_len
;
1061 os_memcpy(out_data
, conn
->push_buf
, out_len
);
1062 os_free(conn
->push_buf
);
1063 conn
->push_buf
= NULL
;
1064 conn
->push_buf_len
= 0;
1069 int tls_connection_decrypt(void *ssl_ctx
, struct tls_connection
*conn
,
1070 const u8
*in_data
, size_t in_len
,
1071 u8
*out_data
, size_t out_len
)
1075 if (conn
->pull_buf
) {
1076 wpa_printf(MSG_DEBUG
, "%s - %d bytes remaining in "
1077 "pull_buf", __func__
, conn
->pull_buf_len
);
1078 os_free(conn
->pull_buf
);
1080 conn
->pull_buf
= os_malloc(in_len
);
1081 if (conn
->pull_buf
== NULL
)
1083 os_memcpy(conn
->pull_buf
, in_data
, in_len
);
1084 conn
->pull_buf_offset
= conn
->pull_buf
;
1085 conn
->pull_buf_len
= in_len
;
1089 res
= gnutls_ia_recv(conn
->session
, (char *) out_data
,
1091 if (out_len
>= 12 &&
1092 (res
== GNUTLS_E_WARNING_IA_IPHF_RECEIVED
||
1093 res
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
)) {
1094 int final
= res
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
;
1095 wpa_printf(MSG_DEBUG
, "%s: Received %sPhaseFinished",
1096 __func__
, final
? "Final" : "Intermediate");
1098 res
= gnutls_ia_permute_inner_secret(
1099 conn
->session
, conn
->session_keys_len
,
1100 (char *) conn
->session_keys
);
1101 if (conn
->session_keys
) {
1102 os_memset(conn
->session_keys
, 0,
1103 conn
->session_keys_len
);
1104 os_free(conn
->session_keys
);
1106 conn
->session_keys
= NULL
;
1107 conn
->session_keys_len
= 0;
1109 wpa_printf(MSG_DEBUG
, "%s: Failed to permute "
1111 __func__
, gnutls_strerror(res
));
1115 res
= gnutls_ia_verify_endphase(conn
->session
,
1118 wpa_printf(MSG_DEBUG
, "%s: Correct endphase "
1119 "checksum", __func__
);
1121 wpa_printf(MSG_INFO
, "%s: Endphase "
1122 "verification failed: %s",
1123 __func__
, gnutls_strerror(res
));
1128 conn
->final_phase_finished
= 1;
1134 wpa_printf(MSG_DEBUG
, "%s - gnutls_ia_recv failed: %d "
1135 "(%s)", __func__
, res
,
1136 gnutls_strerror(res
));
1140 #endif /* GNUTLS_IA */
1142 res
= gnutls_record_recv(conn
->session
, out_data
, out_len
);
1144 wpa_printf(MSG_DEBUG
, "%s - gnutls_record_recv failed: %d "
1145 "(%s)", __func__
, res
, gnutls_strerror(res
));
1152 int tls_connection_resumed(void *ssl_ctx
, struct tls_connection
*conn
)
1156 return gnutls_session_is_resumed(conn
->session
);
1160 int tls_connection_set_master_key(void *ssl_ctx
, struct tls_connection
*conn
,
1161 const u8
*key
, size_t key_len
)
1168 int tls_connection_set_cipher_list(void *tls_ctx
, struct tls_connection
*conn
,
1176 int tls_get_cipher(void *ssl_ctx
, struct tls_connection
*conn
,
1177 char *buf
, size_t buflen
)
1185 int tls_connection_enable_workaround(void *ssl_ctx
,
1186 struct tls_connection
*conn
)
1188 /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
1193 int tls_connection_client_hello_ext(void *ssl_ctx
, struct tls_connection
*conn
,
1194 int ext_type
, const u8
*data
,
1202 int tls_connection_get_failed(void *ssl_ctx
, struct tls_connection
*conn
)
1206 return conn
->failed
;
1210 int tls_connection_get_read_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1214 return conn
->read_alerts
;
1218 int tls_connection_get_write_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1222 return conn
->write_alerts
;
1226 int tls_connection_get_keyblock_size(void *tls_ctx
,
1227 struct tls_connection
*conn
)
1234 unsigned int tls_capabilities(void *tls_ctx
)
1236 unsigned int capa
= 0;
1239 capa
|= TLS_CAPABILITY_IA
;
1240 #endif /* GNUTLS_IA */
1246 int tls_connection_set_ia(void *tls_ctx
, struct tls_connection
*conn
,
1255 conn
->tls_ia
= tls_ia
;
1259 ret
= gnutls_ia_allocate_server_credentials(&conn
->iacred_srv
);
1261 wpa_printf(MSG_DEBUG
, "Failed to allocate IA credentials: %s",
1262 gnutls_strerror(ret
));
1266 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_IA
,
1269 wpa_printf(MSG_DEBUG
, "Failed to configure IA credentials: %s",
1270 gnutls_strerror(ret
));
1271 gnutls_ia_free_server_credentials(conn
->iacred_srv
);
1272 conn
->iacred_srv
= NULL
;
1277 #else /* GNUTLS_IA */
1279 #endif /* GNUTLS_IA */
1283 int tls_connection_ia_send_phase_finished(void *tls_ctx
,
1284 struct tls_connection
*conn
,
1286 u8
*out_data
, size_t out_len
)
1291 if (conn
== NULL
|| conn
->session
== NULL
|| !conn
->tls_ia
)
1294 ret
= gnutls_ia_permute_inner_secret(conn
->session
,
1295 conn
->session_keys_len
,
1296 (char *) conn
->session_keys
);
1297 if (conn
->session_keys
) {
1298 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
1299 os_free(conn
->session_keys
);
1301 conn
->session_keys
= NULL
;
1302 conn
->session_keys_len
= 0;
1304 wpa_printf(MSG_DEBUG
, "%s: Failed to permute inner secret: %s",
1305 __func__
, gnutls_strerror(ret
));
1309 ret
= gnutls_ia_endphase_send(conn
->session
, final
);
1311 wpa_printf(MSG_DEBUG
, "%s: Failed to send endphase: %s",
1312 __func__
, gnutls_strerror(ret
));
1316 if (conn
->push_buf
== NULL
)
1318 if (conn
->push_buf_len
< out_len
)
1319 out_len
= conn
->push_buf_len
;
1320 os_memcpy(out_data
, conn
->push_buf
, out_len
);
1321 os_free(conn
->push_buf
);
1322 conn
->push_buf
= NULL
;
1323 conn
->push_buf_len
= 0;
1325 #else /* GNUTLS_IA */
1327 #endif /* GNUTLS_IA */
1331 int tls_connection_ia_final_phase_finished(void *tls_ctx
,
1332 struct tls_connection
*conn
)
1337 return conn
->final_phase_finished
;
1341 int tls_connection_ia_permute_inner_secret(void *tls_ctx
,
1342 struct tls_connection
*conn
,
1343 const u8
*key
, size_t key_len
)
1346 if (conn
== NULL
|| !conn
->tls_ia
)
1349 if (conn
->session_keys
) {
1350 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
1351 os_free(conn
->session_keys
);
1353 conn
->session_keys_len
= 0;
1356 conn
->session_keys
= os_malloc(key_len
);
1357 if (conn
->session_keys
== NULL
)
1359 os_memcpy(conn
->session_keys
, key
, key_len
);
1360 conn
->session_keys_len
= key_len
;
1362 conn
->session_keys
= NULL
;
1363 conn
->session_keys_len
= 0;
1367 #else /* GNUTLS_IA */
1369 #endif /* GNUTLS_IA */