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 #ifndef TLS_RANDOM_SIZE
39 #define TLS_RANDOM_SIZE 32
41 #ifndef TLS_MASTER_SIZE
42 #define TLS_MASTER_SIZE 48
46 #if LIBGNUTLS_VERSION_NUMBER < 0x010302
47 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require
48 * use of internal structures to get the master_secret and
49 * {server,client}_random.
51 #define GNUTLS_INTERNAL_STRUCTURE_HACK
52 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
55 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
57 * It looks like gnutls does not provide access to client/server_random and
58 * master_key. This is somewhat unfortunate since these are needed for key
59 * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible
60 * hack that copies the gnutls_session_int definition from gnutls_int.h so that
61 * we can get the needed information.
65 typedef unsigned char opaque
;
71 gnutls_connection_end_t entity
;
72 gnutls_kx_algorithm_t kx_algorithm
;
73 gnutls_cipher_algorithm_t read_bulk_cipher_algorithm
;
74 gnutls_mac_algorithm_t read_mac_algorithm
;
75 gnutls_compression_method_t read_compression_algorithm
;
76 gnutls_cipher_algorithm_t write_bulk_cipher_algorithm
;
77 gnutls_mac_algorithm_t write_mac_algorithm
;
78 gnutls_compression_method_t write_compression_algorithm
;
79 cipher_suite_st current_cipher_suite
;
80 opaque master_secret
[TLS_MASTER_SIZE
];
81 opaque client_random
[TLS_RANDOM_SIZE
];
82 opaque server_random
[TLS_RANDOM_SIZE
];
83 /* followed by stuff we are not interested in */
84 } security_parameters_st
;
86 struct gnutls_session_int
{
87 security_parameters_st security_parameters
;
88 /* followed by things we are not interested in */
90 #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */
92 static int tls_gnutls_ref_count
= 0;
95 /* Data for session resumption */
97 size_t session_data_size
;
102 gnutls_certificate_credentials_t xcred
;
105 struct tls_connection
{
106 gnutls_session session
;
107 char *subject_match
, *altsubject_match
;
108 int read_alerts
, write_alerts
, failed
;
110 u8
*pre_shared_secret
;
111 size_t pre_shared_secret_len
;
115 u8
*push_buf
, *pull_buf
, *pull_buf_offset
;
116 size_t push_buf_len
, pull_buf_len
;
119 gnutls_certificate_credentials_t xcred
;
122 int final_phase_finished
;
125 gnutls_ia_server_credentials_t iacred_srv
;
126 gnutls_ia_client_credentials_t iacred_cli
;
128 /* Session keys generated in the current phase for inner secret
129 * permutation before generating/verifying PhaseFinished. */
131 size_t session_keys_len
;
133 u8 inner_secret
[TLS_MASTER_SIZE
];
134 #endif /* GNUTLS_IA */
138 static void tls_log_func(int level
, const char *msg
)
141 if (level
== 6 || level
== 7) {
142 /* These levels seem to be mostly I/O debug and msg dumps */
151 while (*pos
!= '\0') {
158 wpa_printf(level
> 3 ? MSG_MSGDUMP
: MSG_DEBUG
,
159 "gnutls<%d> %s", level
, s
);
164 extern int wpa_debug_show_keys
;
166 void * tls_init(const struct tls_config
*conf
)
168 struct tls_global
*global
;
170 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
171 /* Because of the horrible hack to get master_secret and client/server
172 * random, we need to make sure that the gnutls version is something
173 * that is expected to have same structure definition for the session
176 const char *ok_ver
[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9",
180 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
182 global
= os_zalloc(sizeof(*global
));
186 if (tls_gnutls_ref_count
== 0 && gnutls_global_init() < 0) {
190 tls_gnutls_ref_count
++;
192 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
193 ver
= gnutls_check_version(NULL
);
198 wpa_printf(MSG_DEBUG
, "%s - gnutls version %s", __func__
, ver
);
199 for (i
= 0; ok_ver
[i
]; i
++) {
200 if (strcmp(ok_ver
[i
], ver
) == 0)
203 if (ok_ver
[i
] == NULL
) {
204 wpa_printf(MSG_INFO
, "Untested gnutls version %s - this needs "
205 "to be tested and enabled in tls_gnutls.c", ver
);
209 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
211 gnutls_global_set_log_function(tls_log_func
);
212 if (wpa_debug_show_keys
)
213 gnutls_global_set_log_level(11);
218 void tls_deinit(void *ssl_ctx
)
220 struct tls_global
*global
= ssl_ctx
;
222 if (global
->params_set
)
223 gnutls_certificate_free_credentials(global
->xcred
);
224 os_free(global
->session_data
);
228 tls_gnutls_ref_count
--;
229 if (tls_gnutls_ref_count
== 0)
230 gnutls_global_deinit();
234 int tls_get_errors(void *ssl_ctx
)
240 static ssize_t
tls_pull_func(gnutls_transport_ptr ptr
, void *buf
,
243 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
245 if (conn
->pull_buf
== NULL
) {
250 end
= conn
->pull_buf
+ conn
->pull_buf_len
;
251 if ((size_t) (end
- conn
->pull_buf_offset
) < len
)
252 len
= end
- conn
->pull_buf_offset
;
253 os_memcpy(buf
, conn
->pull_buf_offset
, len
);
254 conn
->pull_buf_offset
+= len
;
255 if (conn
->pull_buf_offset
== end
) {
256 wpa_printf(MSG_DEBUG
, "%s - pull_buf consumed", __func__
);
257 os_free(conn
->pull_buf
);
258 conn
->pull_buf
= conn
->pull_buf_offset
= NULL
;
259 conn
->pull_buf_len
= 0;
261 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in pull_buf",
263 (unsigned long) (end
- conn
->pull_buf_offset
));
269 static ssize_t
tls_push_func(gnutls_transport_ptr ptr
, const void *buf
,
272 struct tls_connection
*conn
= (struct tls_connection
*) ptr
;
275 nbuf
= os_realloc(conn
->push_buf
, conn
->push_buf_len
+ len
);
280 os_memcpy(nbuf
+ conn
->push_buf_len
, buf
, len
);
281 conn
->push_buf
= nbuf
;
282 conn
->push_buf_len
+= len
;
288 static int tls_gnutls_init_session(struct tls_global
*global
,
289 struct tls_connection
*conn
)
291 const int cert_types
[2] = { GNUTLS_CRT_X509
, 0 };
292 const int protos
[2] = { GNUTLS_TLS1
, 0 };
295 ret
= gnutls_init(&conn
->session
,
296 global
->server
? GNUTLS_SERVER
: GNUTLS_CLIENT
);
298 wpa_printf(MSG_INFO
, "TLS: Failed to initialize new TLS "
299 "connection: %s", gnutls_strerror(ret
));
303 ret
= gnutls_set_default_priority(conn
->session
);
307 ret
= gnutls_certificate_type_set_priority(conn
->session
, cert_types
);
311 ret
= gnutls_protocol_set_priority(conn
->session
, protos
);
315 gnutls_transport_set_pull_function(conn
->session
, tls_pull_func
);
316 gnutls_transport_set_push_function(conn
->session
, tls_push_func
);
317 gnutls_transport_set_ptr(conn
->session
, (gnutls_transport_ptr
) conn
);
322 wpa_printf(MSG_INFO
, "TLS: Failed to setup new TLS connection: %s",
323 gnutls_strerror(ret
));
324 gnutls_deinit(conn
->session
);
329 struct tls_connection
* tls_connection_init(void *ssl_ctx
)
331 struct tls_global
*global
= ssl_ctx
;
332 struct tls_connection
*conn
;
335 conn
= os_zalloc(sizeof(*conn
));
339 if (tls_gnutls_init_session(global
, conn
)) {
344 if (global
->params_set
) {
345 ret
= gnutls_credentials_set(conn
->session
,
346 GNUTLS_CRD_CERTIFICATE
,
349 wpa_printf(MSG_INFO
, "Failed to configure "
350 "credentials: %s", gnutls_strerror(ret
));
356 if (gnutls_certificate_allocate_credentials(&conn
->xcred
)) {
365 void tls_connection_deinit(void *ssl_ctx
, struct tls_connection
*conn
)
371 if (conn
->iacred_srv
)
372 gnutls_ia_free_server_credentials(conn
->iacred_srv
);
373 if (conn
->iacred_cli
)
374 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
375 if (conn
->session_keys
) {
376 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
377 os_free(conn
->session_keys
);
379 #endif /* GNUTLS_IA */
381 gnutls_certificate_free_credentials(conn
->xcred
);
382 gnutls_deinit(conn
->session
);
383 os_free(conn
->pre_shared_secret
);
384 os_free(conn
->subject_match
);
385 os_free(conn
->altsubject_match
);
386 os_free(conn
->push_buf
);
387 os_free(conn
->pull_buf
);
392 int tls_connection_established(void *ssl_ctx
, struct tls_connection
*conn
)
394 return conn
? conn
->established
: 0;
398 int tls_connection_shutdown(void *ssl_ctx
, struct tls_connection
*conn
)
400 struct tls_global
*global
= ssl_ctx
;
406 /* Shutdown previous TLS connection without notifying the peer
407 * because the connection was already terminated in practice
408 * and "close notify" shutdown alert would confuse AS. */
409 gnutls_bye(conn
->session
, GNUTLS_SHUT_RDWR
);
410 os_free(conn
->push_buf
);
411 conn
->push_buf
= NULL
;
412 conn
->push_buf_len
= 0;
413 conn
->established
= 0;
414 conn
->final_phase_finished
= 0;
416 if (conn
->session_keys
) {
417 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
418 os_free(conn
->session_keys
);
420 conn
->session_keys_len
= 0;
421 #endif /* GNUTLS_IA */
423 gnutls_deinit(conn
->session
);
424 if (tls_gnutls_init_session(global
, conn
)) {
425 wpa_printf(MSG_INFO
, "GnuTLS: Failed to preparare new session "
426 "for session resumption use");
430 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
431 conn
->params_set
? conn
->xcred
:
434 wpa_printf(MSG_INFO
, "GnuTLS: Failed to configure credentials "
435 "for session resumption: %s", gnutls_strerror(ret
));
439 if (global
->session_data
) {
440 ret
= gnutls_session_set_data(conn
->session
,
441 global
->session_data
,
442 global
->session_data_size
);
444 wpa_printf(MSG_INFO
, "GnuTLS: Failed to set session "
445 "data: %s", gnutls_strerror(ret
));
455 static int tls_match_altsubject(X509
*cert
, const char *match
)
463 ext
= X509_get_ext_d2i(cert
, NID_subject_alt_name
, NULL
, NULL
);
465 for (i
= 0; ext
&& i
< sk_GENERAL_NAME_num(ext
); i
++) {
466 gen
= sk_GENERAL_NAME_value(ext
, i
);
479 wpa_printf(MSG_DEBUG
, "TLS: altSubjectName: "
480 "unsupported type=%d", gen
->type
);
487 wpa_printf(MSG_DEBUG
, "TLS: altSubjectName: %s:%s",
488 field
, gen
->d
.ia5
->data
);
489 len
= os_strlen(field
) + 1 +
490 strlen((char *) gen
->d
.ia5
->data
) + 1;
491 tmp
= os_malloc(len
);
494 snprintf(tmp
, len
, "%s:%s", field
, gen
->d
.ia5
->data
);
495 if (strstr(tmp
, match
))
506 static int tls_verify_cb(int preverify_ok
, X509_STORE_CTX
*x509_ctx
)
512 struct tls_connection
*conn
;
513 char *match
, *altmatch
;
515 err_cert
= X509_STORE_CTX_get_current_cert(x509_ctx
);
516 err
= X509_STORE_CTX_get_error(x509_ctx
);
517 depth
= X509_STORE_CTX_get_error_depth(x509_ctx
);
518 ssl
= X509_STORE_CTX_get_ex_data(x509_ctx
,
519 SSL_get_ex_data_X509_STORE_CTX_idx());
520 X509_NAME_oneline(X509_get_subject_name(err_cert
), buf
, sizeof(buf
));
522 conn
= SSL_get_app_data(ssl
);
523 match
= conn
? conn
->subject_match
: NULL
;
524 altmatch
= conn
? conn
->altsubject_match
: NULL
;
527 wpa_printf(MSG_WARNING
, "TLS: Certificate verification failed,"
528 " error %d (%s) depth %d for '%s'", err
,
529 X509_verify_cert_error_string(err
), depth
, buf
);
531 wpa_printf(MSG_DEBUG
, "TLS: tls_verify_cb - "
532 "preverify_ok=%d err=%d (%s) depth=%d buf='%s'",
534 X509_verify_cert_error_string(err
), depth
, buf
);
535 if (depth
== 0 && match
&& strstr(buf
, match
) == NULL
) {
536 wpa_printf(MSG_WARNING
, "TLS: Subject '%s' did not "
537 "match with '%s'", buf
, match
);
539 } else if (depth
== 0 && altmatch
&&
540 !tls_match_altsubject(err_cert
, altmatch
)) {
541 wpa_printf(MSG_WARNING
, "TLS: altSubjectName match "
542 "'%s' not found", altmatch
);
552 int tls_connection_set_params(void *tls_ctx
, struct tls_connection
*conn
,
553 const struct tls_connection_params
*params
)
557 if (conn
== NULL
|| params
== NULL
)
560 os_free(conn
->subject_match
);
561 conn
->subject_match
= NULL
;
562 if (params
->subject_match
) {
563 conn
->subject_match
= os_strdup(params
->subject_match
);
564 if (conn
->subject_match
== NULL
)
568 os_free(conn
->altsubject_match
);
569 conn
->altsubject_match
= NULL
;
570 if (params
->altsubject_match
) {
571 conn
->altsubject_match
= os_strdup(params
->altsubject_match
);
572 if (conn
->altsubject_match
== NULL
)
576 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
577 * to force peer validation(?) */
579 if (params
->ca_cert
) {
580 conn
->verify_peer
= 1;
581 ret
= gnutls_certificate_set_x509_trust_file(
582 conn
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_PEM
);
584 wpa_printf(MSG_DEBUG
, "Failed to read CA cert '%s' "
585 "in PEM format: %s", params
->ca_cert
,
586 gnutls_strerror(ret
));
587 ret
= gnutls_certificate_set_x509_trust_file(
588 conn
->xcred
, params
->ca_cert
,
589 GNUTLS_X509_FMT_DER
);
591 wpa_printf(MSG_DEBUG
, "Failed to read CA cert "
592 "'%s' in DER format: %s",
594 gnutls_strerror(ret
));
599 if (params
->flags
& TLS_CONN_ALLOW_SIGN_RSA_MD5
) {
600 gnutls_certificate_set_verify_flags(
601 conn
->xcred
, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5
);
604 if (params
->flags
& TLS_CONN_DISABLE_TIME_CHECKS
) {
605 gnutls_certificate_set_verify_flags(
607 GNUTLS_VERIFY_DISABLE_TIME_CHECKS
);
611 if (params
->client_cert
&& params
->private_key
) {
612 /* TODO: private_key_passwd? */
613 ret
= gnutls_certificate_set_x509_key_file(
614 conn
->xcred
, params
->client_cert
, params
->private_key
,
615 GNUTLS_X509_FMT_PEM
);
617 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
618 "in PEM format: %s", gnutls_strerror(ret
));
619 ret
= gnutls_certificate_set_x509_key_file(
620 conn
->xcred
, params
->client_cert
,
621 params
->private_key
, GNUTLS_X509_FMT_DER
);
623 wpa_printf(MSG_DEBUG
, "Failed to read client "
624 "cert/key in DER format: %s",
625 gnutls_strerror(ret
));
629 } else if (params
->private_key
) {
632 /* Try to load in PKCS#12 format */
633 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
634 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
635 conn
->xcred
, params
->private_key
, GNUTLS_X509_FMT_DER
,
636 params
->private_key_passwd
);
638 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
639 "PKCS#12 format: %s", gnutls_strerror(ret
));
643 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
644 #endif /* PKCS12_FUNCS */
647 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
653 conn
->tls_ia
= params
->tls_ia
;
654 conn
->params_set
= 1;
656 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_CERTIFICATE
,
659 wpa_printf(MSG_INFO
, "Failed to configure credentials: %s",
660 gnutls_strerror(ret
));
664 if (conn
->iacred_cli
)
665 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
667 ret
= gnutls_ia_allocate_client_credentials(&conn
->iacred_cli
);
669 wpa_printf(MSG_DEBUG
, "Failed to allocate IA credentials: %s",
670 gnutls_strerror(ret
));
674 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_IA
,
677 wpa_printf(MSG_DEBUG
, "Failed to configure IA credentials: %s",
678 gnutls_strerror(ret
));
679 gnutls_ia_free_client_credentials(conn
->iacred_cli
);
680 conn
->iacred_cli
= NULL
;
683 #endif /* GNUTLS_IE */
689 int tls_global_set_params(void *tls_ctx
,
690 const struct tls_connection_params
*params
)
692 struct tls_global
*global
= tls_ctx
;
695 /* Currently, global parameters are only set when running in server
699 if (global
->params_set
) {
700 gnutls_certificate_free_credentials(global
->xcred
);
701 global
->params_set
= 0;
704 ret
= gnutls_certificate_allocate_credentials(&global
->xcred
);
706 wpa_printf(MSG_DEBUG
, "Failed to allocate global credentials "
707 "%s", gnutls_strerror(ret
));
711 if (params
->ca_cert
) {
712 ret
= gnutls_certificate_set_x509_trust_file(
713 global
->xcred
, params
->ca_cert
, GNUTLS_X509_FMT_PEM
);
715 wpa_printf(MSG_DEBUG
, "Failed to read CA cert '%s' "
716 "in PEM format: %s", params
->ca_cert
,
717 gnutls_strerror(ret
));
718 ret
= gnutls_certificate_set_x509_trust_file(
719 global
->xcred
, params
->ca_cert
,
720 GNUTLS_X509_FMT_DER
);
722 wpa_printf(MSG_DEBUG
, "Failed to read CA cert "
723 "'%s' in DER format: %s",
725 gnutls_strerror(ret
));
730 if (params
->flags
& TLS_CONN_ALLOW_SIGN_RSA_MD5
) {
731 gnutls_certificate_set_verify_flags(
733 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5
);
736 if (params
->flags
& TLS_CONN_DISABLE_TIME_CHECKS
) {
737 gnutls_certificate_set_verify_flags(
739 GNUTLS_VERIFY_DISABLE_TIME_CHECKS
);
743 if (params
->client_cert
&& params
->private_key
) {
744 /* TODO: private_key_passwd? */
745 ret
= gnutls_certificate_set_x509_key_file(
746 global
->xcred
, params
->client_cert
,
747 params
->private_key
, GNUTLS_X509_FMT_PEM
);
749 wpa_printf(MSG_DEBUG
, "Failed to read client cert/key "
750 "in PEM format: %s", gnutls_strerror(ret
));
751 ret
= gnutls_certificate_set_x509_key_file(
752 global
->xcred
, params
->client_cert
,
753 params
->private_key
, GNUTLS_X509_FMT_DER
);
755 wpa_printf(MSG_DEBUG
, "Failed to read client "
756 "cert/key in DER format: %s",
757 gnutls_strerror(ret
));
761 } else if (params
->private_key
) {
764 /* Try to load in PKCS#12 format */
765 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
766 ret
= gnutls_certificate_set_x509_simple_pkcs12_file(
767 global
->xcred
, params
->private_key
,
768 GNUTLS_X509_FMT_DER
, params
->private_key_passwd
);
770 wpa_printf(MSG_DEBUG
, "Failed to load private_key in "
771 "PKCS#12 format: %s", gnutls_strerror(ret
));
775 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
776 #endif /* PKCS12_FUNCS */
779 wpa_printf(MSG_DEBUG
, "GnuTLS: PKCS#12 support not "
785 global
->params_set
= 1;
790 gnutls_certificate_free_credentials(global
->xcred
);
795 int tls_global_set_verify(void *ssl_ctx
, int check_crl
)
802 int tls_connection_set_verify(void *ssl_ctx
, struct tls_connection
*conn
,
805 if (conn
== NULL
|| conn
->session
== NULL
)
808 conn
->verify_peer
= verify_peer
;
809 gnutls_certificate_server_set_request(conn
->session
,
810 verify_peer
? GNUTLS_CERT_REQUIRE
811 : GNUTLS_CERT_REQUEST
);
817 int tls_connection_get_keys(void *ssl_ctx
, struct tls_connection
*conn
,
818 struct tls_keys
*keys
)
820 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
821 security_parameters_st
*sec
;
822 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
824 if (conn
== NULL
|| conn
->session
== NULL
|| keys
== NULL
)
827 os_memset(keys
, 0, sizeof(*keys
));
829 #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK
830 sec
= &conn
->session
->security_parameters
;
831 keys
->master_key
= sec
->master_secret
;
832 keys
->master_key_len
= TLS_MASTER_SIZE
;
833 keys
->client_random
= sec
->client_random
;
834 keys
->server_random
= sec
->server_random
;
835 #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */
836 keys
->client_random
=
837 (u8
*) gnutls_session_get_client_random(conn
->session
);
838 keys
->server_random
=
839 (u8
*) gnutls_session_get_server_random(conn
->session
);
840 /* No access to master_secret */
841 #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */
844 gnutls_ia_extract_inner_secret(conn
->session
,
845 (char *) conn
->inner_secret
);
846 keys
->inner_secret
= conn
->inner_secret
;
847 keys
->inner_secret_len
= TLS_MASTER_SIZE
;
848 #endif /* GNUTLS_IA */
850 keys
->client_random_len
= TLS_RANDOM_SIZE
;
851 keys
->server_random_len
= TLS_RANDOM_SIZE
;
857 int tls_connection_prf(void *tls_ctx
, struct tls_connection
*conn
,
858 const char *label
, int server_random_first
,
859 u8
*out
, size_t out_len
)
861 #if LIBGNUTLS_VERSION_NUMBER >= 0x010302
862 if (conn
== NULL
|| conn
->session
== NULL
)
865 return gnutls_prf(conn
->session
, os_strlen(label
), label
,
866 server_random_first
, 0, NULL
, out_len
, (char *) out
);
867 #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
869 #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */
873 static int tls_connection_verify_peer(struct tls_connection
*conn
,
874 gnutls_alert_description_t
*err
)
876 unsigned int status
, num_certs
, i
;
878 const gnutls_datum_t
*certs
;
879 gnutls_x509_crt_t cert
;
881 if (gnutls_certificate_verify_peers2(conn
->session
, &status
) < 0) {
882 wpa_printf(MSG_INFO
, "TLS: Failed to verify peer "
883 "certificate chain");
884 *err
= GNUTLS_A_INTERNAL_ERROR
;
888 if (conn
->verify_peer
&& (status
& GNUTLS_CERT_INVALID
)) {
889 wpa_printf(MSG_INFO
, "TLS: Peer certificate not trusted");
890 if (status
& GNUTLS_CERT_INSECURE_ALGORITHM
) {
891 wpa_printf(MSG_INFO
, "TLS: Certificate uses insecure "
893 *err
= GNUTLS_A_INSUFFICIENT_SECURITY
;
895 if (status
& GNUTLS_CERT_NOT_ACTIVATED
) {
896 wpa_printf(MSG_INFO
, "TLS: Certificate not yet "
898 *err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
900 if (status
& GNUTLS_CERT_EXPIRED
) {
901 wpa_printf(MSG_INFO
, "TLS: Certificate expired");
902 *err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
907 if (status
& GNUTLS_CERT_SIGNER_NOT_FOUND
) {
908 wpa_printf(MSG_INFO
, "TLS: Peer certificate does not have a "
910 *err
= GNUTLS_A_UNKNOWN_CA
;
914 if (status
& GNUTLS_CERT_REVOKED
) {
915 wpa_printf(MSG_INFO
, "TLS: Peer certificate has been revoked");
916 *err
= GNUTLS_A_CERTIFICATE_REVOKED
;
922 certs
= gnutls_certificate_get_peers(conn
->session
, &num_certs
);
924 wpa_printf(MSG_INFO
, "TLS: No peer certificate chain "
926 *err
= GNUTLS_A_UNKNOWN_CA
;
930 for (i
= 0; i
< num_certs
; i
++) {
933 if (gnutls_x509_crt_init(&cert
) < 0) {
934 wpa_printf(MSG_INFO
, "TLS: Certificate initialization "
936 *err
= GNUTLS_A_BAD_CERTIFICATE
;
940 if (gnutls_x509_crt_import(cert
, &certs
[i
],
941 GNUTLS_X509_FMT_DER
) < 0) {
942 wpa_printf(MSG_INFO
, "TLS: Could not parse peer "
943 "certificate %d/%d", i
+ 1, num_certs
);
944 gnutls_x509_crt_deinit(cert
);
945 *err
= GNUTLS_A_BAD_CERTIFICATE
;
949 gnutls_x509_crt_get_dn(cert
, NULL
, &len
);
951 buf
= os_malloc(len
+ 1);
953 buf
[0] = buf
[len
] = '\0';
954 gnutls_x509_crt_get_dn(cert
, buf
, &len
);
956 wpa_printf(MSG_DEBUG
, "TLS: Peer cert chain %d/%d: %s",
957 i
+ 1, num_certs
, buf
);
960 /* TODO: validate subject_match and altsubject_match */
965 if (gnutls_x509_crt_get_expiration_time(cert
) < now
.sec
||
966 gnutls_x509_crt_get_activation_time(cert
) > now
.sec
) {
967 wpa_printf(MSG_INFO
, "TLS: Peer certificate %d/%d is "
968 "not valid at this time",
970 gnutls_x509_crt_deinit(cert
);
971 *err
= GNUTLS_A_CERTIFICATE_EXPIRED
;
975 gnutls_x509_crt_deinit(cert
);
982 u8
* tls_connection_handshake(void *ssl_ctx
, struct tls_connection
*conn
,
983 const u8
*in_data
, size_t in_len
,
984 size_t *out_len
, u8
**appl_data
,
985 size_t *appl_data_len
)
987 struct tls_global
*global
= ssl_ctx
;
994 if (in_data
&& in_len
) {
995 if (conn
->pull_buf
) {
996 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in "
997 "pull_buf", __func__
,
998 (unsigned long) conn
->pull_buf_len
);
999 os_free(conn
->pull_buf
);
1001 conn
->pull_buf
= os_malloc(in_len
);
1002 if (conn
->pull_buf
== NULL
)
1004 os_memcpy(conn
->pull_buf
, in_data
, in_len
);
1005 conn
->pull_buf_offset
= conn
->pull_buf
;
1006 conn
->pull_buf_len
= in_len
;
1009 ret
= gnutls_handshake(conn
->session
);
1012 case GNUTLS_E_AGAIN
:
1013 if (global
->server
&& conn
->established
&&
1014 conn
->push_buf
== NULL
) {
1015 /* Need to return something to trigger
1016 * completion of EAP-TLS. */
1017 conn
->push_buf
= os_malloc(1);
1020 case GNUTLS_E_FATAL_ALERT_RECEIVED
:
1021 wpa_printf(MSG_DEBUG
, "%s - received fatal '%s' alert",
1022 __func__
, gnutls_alert_get_name(
1023 gnutls_alert_get(conn
->session
)));
1024 conn
->read_alerts
++;
1027 wpa_printf(MSG_DEBUG
, "%s - gnutls_handshake failed "
1028 "-> %s", __func__
, gnutls_strerror(ret
));
1033 gnutls_alert_description_t err
;
1035 if (conn
->verify_peer
&&
1036 tls_connection_verify_peer(conn
, &err
)) {
1037 wpa_printf(MSG_INFO
, "TLS: Peer certificate chain "
1038 "failed validation");
1040 gnutls_alert_send(conn
->session
, GNUTLS_AL_FATAL
, err
);
1044 #ifdef CONFIG_GNUTLS_EXTRA
1045 if (conn
->tls_ia
&& !gnutls_ia_handshake_p(conn
->session
)) {
1046 wpa_printf(MSG_INFO
, "TLS: No TLS/IA negotiation");
1050 #endif /* CONFIG_GNUTLS_EXTRA */
1053 wpa_printf(MSG_DEBUG
, "TLS: Start TLS/IA handshake");
1055 wpa_printf(MSG_DEBUG
, "TLS: Handshake completed "
1058 conn
->established
= 1;
1059 if (conn
->push_buf
== NULL
) {
1060 /* Need to return something to get final TLS ACK. */
1061 conn
->push_buf
= os_malloc(1);
1064 gnutls_session_get_data(conn
->session
, NULL
, &size
);
1065 if (global
->session_data
== NULL
||
1066 global
->session_data_size
< size
) {
1067 os_free(global
->session_data
);
1068 global
->session_data
= os_malloc(size
);
1070 if (global
->session_data
) {
1071 global
->session_data_size
= size
;
1072 gnutls_session_get_data(conn
->session
,
1073 global
->session_data
,
1074 &global
->session_data_size
);
1079 out_data
= conn
->push_buf
;
1080 *out_len
= conn
->push_buf_len
;
1081 conn
->push_buf
= NULL
;
1082 conn
->push_buf_len
= 0;
1087 u8
* tls_connection_server_handshake(void *ssl_ctx
,
1088 struct tls_connection
*conn
,
1089 const u8
*in_data
, size_t in_len
,
1092 return tls_connection_handshake(ssl_ctx
, conn
, in_data
, in_len
,
1093 out_len
, NULL
, NULL
);
1097 int tls_connection_encrypt(void *ssl_ctx
, struct tls_connection
*conn
,
1098 const u8
*in_data
, size_t in_len
,
1099 u8
*out_data
, size_t out_len
)
1105 res
= gnutls_ia_send(conn
->session
, (char *) in_data
, in_len
);
1107 #endif /* GNUTLS_IA */
1108 res
= gnutls_record_send(conn
->session
, in_data
, in_len
);
1110 wpa_printf(MSG_INFO
, "%s: Encryption failed: %s",
1111 __func__
, gnutls_strerror(res
));
1114 if (conn
->push_buf
== NULL
)
1116 if (conn
->push_buf_len
< out_len
)
1117 out_len
= conn
->push_buf_len
;
1118 else if (conn
->push_buf_len
> out_len
) {
1119 wpa_printf(MSG_INFO
, "GnuTLS: Not enough buffer space for "
1120 "encrypted message (in_len=%lu push_buf_len=%lu "
1122 (unsigned long) in_len
,
1123 (unsigned long) conn
->push_buf_len
,
1124 (unsigned long) out_len
);
1126 os_memcpy(out_data
, conn
->push_buf
, out_len
);
1127 os_free(conn
->push_buf
);
1128 conn
->push_buf
= NULL
;
1129 conn
->push_buf_len
= 0;
1134 int tls_connection_decrypt(void *ssl_ctx
, struct tls_connection
*conn
,
1135 const u8
*in_data
, size_t in_len
,
1136 u8
*out_data
, size_t out_len
)
1140 if (conn
->pull_buf
) {
1141 wpa_printf(MSG_DEBUG
, "%s - %lu bytes remaining in "
1142 "pull_buf", __func__
,
1143 (unsigned long) conn
->pull_buf_len
);
1144 os_free(conn
->pull_buf
);
1146 conn
->pull_buf
= os_malloc(in_len
);
1147 if (conn
->pull_buf
== NULL
)
1149 os_memcpy(conn
->pull_buf
, in_data
, in_len
);
1150 conn
->pull_buf_offset
= conn
->pull_buf
;
1151 conn
->pull_buf_len
= in_len
;
1155 res
= gnutls_ia_recv(conn
->session
, (char *) out_data
,
1157 if (out_len
>= 12 &&
1158 (res
== GNUTLS_E_WARNING_IA_IPHF_RECEIVED
||
1159 res
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
)) {
1160 int final
= res
== GNUTLS_E_WARNING_IA_FPHF_RECEIVED
;
1161 wpa_printf(MSG_DEBUG
, "%s: Received %sPhaseFinished",
1162 __func__
, final
? "Final" : "Intermediate");
1164 res
= gnutls_ia_permute_inner_secret(
1165 conn
->session
, conn
->session_keys_len
,
1166 (char *) conn
->session_keys
);
1167 if (conn
->session_keys
) {
1168 os_memset(conn
->session_keys
, 0,
1169 conn
->session_keys_len
);
1170 os_free(conn
->session_keys
);
1172 conn
->session_keys
= NULL
;
1173 conn
->session_keys_len
= 0;
1175 wpa_printf(MSG_DEBUG
, "%s: Failed to permute "
1177 __func__
, gnutls_strerror(res
));
1181 res
= gnutls_ia_verify_endphase(conn
->session
,
1184 wpa_printf(MSG_DEBUG
, "%s: Correct endphase "
1185 "checksum", __func__
);
1187 wpa_printf(MSG_INFO
, "%s: Endphase "
1188 "verification failed: %s",
1189 __func__
, gnutls_strerror(res
));
1194 conn
->final_phase_finished
= 1;
1200 wpa_printf(MSG_DEBUG
, "%s - gnutls_ia_recv failed: %d "
1201 "(%s)", __func__
, (int) res
,
1202 gnutls_strerror(res
));
1206 #endif /* GNUTLS_IA */
1208 res
= gnutls_record_recv(conn
->session
, out_data
, out_len
);
1210 wpa_printf(MSG_DEBUG
, "%s - gnutls_record_recv failed: %d "
1211 "(%s)", __func__
, (int) res
, gnutls_strerror(res
));
1218 int tls_connection_resumed(void *ssl_ctx
, struct tls_connection
*conn
)
1222 return gnutls_session_is_resumed(conn
->session
);
1226 int tls_connection_set_cipher_list(void *tls_ctx
, struct tls_connection
*conn
,
1234 int tls_get_cipher(void *ssl_ctx
, struct tls_connection
*conn
,
1235 char *buf
, size_t buflen
)
1243 int tls_connection_enable_workaround(void *ssl_ctx
,
1244 struct tls_connection
*conn
)
1246 /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */
1251 int tls_connection_client_hello_ext(void *ssl_ctx
, struct tls_connection
*conn
,
1252 int ext_type
, const u8
*data
,
1260 int tls_connection_get_failed(void *ssl_ctx
, struct tls_connection
*conn
)
1264 return conn
->failed
;
1268 int tls_connection_get_read_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1272 return conn
->read_alerts
;
1276 int tls_connection_get_write_alerts(void *ssl_ctx
, struct tls_connection
*conn
)
1280 return conn
->write_alerts
;
1284 int tls_connection_get_keyblock_size(void *tls_ctx
,
1285 struct tls_connection
*conn
)
1292 unsigned int tls_capabilities(void *tls_ctx
)
1294 unsigned int capa
= 0;
1297 capa
|= TLS_CAPABILITY_IA
;
1298 #endif /* GNUTLS_IA */
1304 int tls_connection_set_ia(void *tls_ctx
, struct tls_connection
*conn
,
1313 conn
->tls_ia
= tls_ia
;
1317 ret
= gnutls_ia_allocate_server_credentials(&conn
->iacred_srv
);
1319 wpa_printf(MSG_DEBUG
, "Failed to allocate IA credentials: %s",
1320 gnutls_strerror(ret
));
1324 ret
= gnutls_credentials_set(conn
->session
, GNUTLS_CRD_IA
,
1327 wpa_printf(MSG_DEBUG
, "Failed to configure IA credentials: %s",
1328 gnutls_strerror(ret
));
1329 gnutls_ia_free_server_credentials(conn
->iacred_srv
);
1330 conn
->iacred_srv
= NULL
;
1335 #else /* GNUTLS_IA */
1337 #endif /* GNUTLS_IA */
1341 int tls_connection_ia_send_phase_finished(void *tls_ctx
,
1342 struct tls_connection
*conn
,
1344 u8
*out_data
, size_t out_len
)
1349 if (conn
== NULL
|| conn
->session
== NULL
|| !conn
->tls_ia
)
1352 ret
= gnutls_ia_permute_inner_secret(conn
->session
,
1353 conn
->session_keys_len
,
1354 (char *) conn
->session_keys
);
1355 if (conn
->session_keys
) {
1356 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
1357 os_free(conn
->session_keys
);
1359 conn
->session_keys
= NULL
;
1360 conn
->session_keys_len
= 0;
1362 wpa_printf(MSG_DEBUG
, "%s: Failed to permute inner secret: %s",
1363 __func__
, gnutls_strerror(ret
));
1367 ret
= gnutls_ia_endphase_send(conn
->session
, final
);
1369 wpa_printf(MSG_DEBUG
, "%s: Failed to send endphase: %s",
1370 __func__
, gnutls_strerror(ret
));
1374 if (conn
->push_buf
== NULL
)
1376 if (conn
->push_buf_len
< out_len
)
1377 out_len
= conn
->push_buf_len
;
1378 os_memcpy(out_data
, conn
->push_buf
, out_len
);
1379 os_free(conn
->push_buf
);
1380 conn
->push_buf
= NULL
;
1381 conn
->push_buf_len
= 0;
1383 #else /* GNUTLS_IA */
1385 #endif /* GNUTLS_IA */
1389 int tls_connection_ia_final_phase_finished(void *tls_ctx
,
1390 struct tls_connection
*conn
)
1395 return conn
->final_phase_finished
;
1399 int tls_connection_ia_permute_inner_secret(void *tls_ctx
,
1400 struct tls_connection
*conn
,
1401 const u8
*key
, size_t key_len
)
1404 if (conn
== NULL
|| !conn
->tls_ia
)
1407 if (conn
->session_keys
) {
1408 os_memset(conn
->session_keys
, 0, conn
->session_keys_len
);
1409 os_free(conn
->session_keys
);
1411 conn
->session_keys_len
= 0;
1414 conn
->session_keys
= os_malloc(key_len
);
1415 if (conn
->session_keys
== NULL
)
1417 os_memcpy(conn
->session_keys
, key
, key_len
);
1418 conn
->session_keys_len
= key_len
;
1420 conn
->session_keys
= NULL
;
1421 conn
->session_keys_len
= 0;
1425 #else /* GNUTLS_IA */
1427 #endif /* GNUTLS_IA */