1 /*
2 * SSL/TLS interface functions for GnuTLS
3 * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10 #include <gnutls/gnutls.h>
11 #include <gnutls/x509.h>
12 #ifdef PKCS12_FUNCS
13 #include <gnutls/pkcs12.h>
14 #endif /* PKCS12_FUNCS */
15 #if GNUTLS_VERSION_NUMBER >= 0x030103
16 #include <gnutls/ocsp.h>
17 #endif /* 3.1.3 */
18
19 #include "common.h"
20 #include "crypto/crypto.h"
21 #include "tls.h"
22
23
24 static int tls_gnutls_ref_count = 0;
25
26 struct tls_global {
27 /* Data for session resumption */
28 void *session_data;
29 size_t session_data_size;
30
31 int server;
32
33 int params_set;
34 gnutls_certificate_credentials_t xcred;
35
36 void (*event_cb)(void *ctx, enum tls_event ev,
37 union tls_event_data *data);
38 void *cb_ctx;
39 int cert_in_cb;
40
41 char *ocsp_stapling_response;
42 };
43
44 struct tls_connection {
45 struct tls_global *global;
46 gnutls_session_t session;
47 int read_alerts, write_alerts, failed;
48
49 u8 *pre_shared_secret;
50 size_t pre_shared_secret_len;
51 int established;
52 int verify_peer;
53 unsigned int disable_time_checks:1;
54
55 struct wpabuf *push_buf;
56 struct wpabuf *pull_buf;
57 const u8 *pull_buf_offset;
58
59 int params_set;
60 gnutls_certificate_credentials_t xcred;
61
62 char *suffix_match;
63 char *domain_match;
64 unsigned int flags;
65
66 char *prio_str;
67 };
68
69
70 static int tls_connection_verify_peer(gnutls_session_t session);
71
72
tls_log_func(int level,const char * msg)73 static void tls_log_func(int level, const char *msg)
74 {
75 char *s, *pos;
76 if (level == 6 || level == 7) {
77 /* These levels seem to be mostly I/O debug and msg dumps */
78 return;
79 }
80
81 s = os_strdup(msg);
82 if (s == NULL)
83 return;
84
85 pos = s;
86 while (*pos != '\0') {
87 if (*pos == '\n') {
88 *pos = '\0';
89 break;
90 }
91 pos++;
92 }
93 wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG,
94 "gnutls<%d> %s", level, s);
95 os_free(s);
96 }
97
98
tls_init(const struct tls_config * conf)99 void * tls_init(const struct tls_config *conf)
100 {
101 struct tls_global *global;
102
103 if (tls_gnutls_ref_count == 0) {
104 wpa_printf(MSG_DEBUG,
105 "GnuTLS: Library version %s (runtime) - %s (build)",
106 gnutls_check_version(NULL), GNUTLS_VERSION);
107 }
108
109 global = os_zalloc(sizeof(*global));
110 if (global == NULL)
111 return NULL;
112
113 if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) {
114 os_free(global);
115 return NULL;
116 }
117 tls_gnutls_ref_count++;
118
119 gnutls_global_set_log_function(tls_log_func);
120 if (wpa_debug_show_keys)
121 gnutls_global_set_log_level(11);
122
123 if (conf) {
124 global->event_cb = conf->event_cb;
125 global->cb_ctx = conf->cb_ctx;
126 global->cert_in_cb = conf->cert_in_cb;
127 }
128
129 return global;
130 }
131
132
tls_deinit(void * ssl_ctx)133 void tls_deinit(void *ssl_ctx)
134 {
135 struct tls_global *global = ssl_ctx;
136 if (global) {
137 if (global->params_set)
138 gnutls_certificate_free_credentials(global->xcred);
139 os_free(global->session_data);
140 os_free(global->ocsp_stapling_response);
141 os_free(global);
142 }
143
144 tls_gnutls_ref_count--;
145 if (tls_gnutls_ref_count == 0)
146 gnutls_global_deinit();
147 }
148
149
tls_get_errors(void * ssl_ctx)150 int tls_get_errors(void *ssl_ctx)
151 {
152 return 0;
153 }
154
155
tls_pull_func(gnutls_transport_ptr_t ptr,void * buf,size_t len)156 static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf,
157 size_t len)
158 {
159 struct tls_connection *conn = (struct tls_connection *) ptr;
160 const u8 *end;
161 if (conn->pull_buf == NULL) {
162 errno = EWOULDBLOCK;
163 return -1;
164 }
165
166 end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf);
167 if ((size_t) (end - conn->pull_buf_offset) < len)
168 len = end - conn->pull_buf_offset;
169 os_memcpy(buf, conn->pull_buf_offset, len);
170 conn->pull_buf_offset += len;
171 if (conn->pull_buf_offset == end) {
172 wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__);
173 wpabuf_free(conn->pull_buf);
174 conn->pull_buf = NULL;
175 conn->pull_buf_offset = NULL;
176 } else {
177 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf",
178 __func__,
179 (unsigned long) (end - conn->pull_buf_offset));
180 }
181 return len;
182 }
183
184
tls_push_func(gnutls_transport_ptr_t ptr,const void * buf,size_t len)185 static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf,
186 size_t len)
187 {
188 struct tls_connection *conn = (struct tls_connection *) ptr;
189
190 if (wpabuf_resize(&conn->push_buf, len) < 0) {
191 errno = ENOMEM;
192 return -1;
193 }
194 wpabuf_put_data(conn->push_buf, buf, len);
195
196 return len;
197 }
198
199
tls_gnutls_init_session(struct tls_global * global,struct tls_connection * conn)200 static int tls_gnutls_init_session(struct tls_global *global,
201 struct tls_connection *conn)
202 {
203 const char *err;
204 int ret;
205
206 ret = gnutls_init(&conn->session,
207 global->server ? GNUTLS_SERVER : GNUTLS_CLIENT);
208 if (ret < 0) {
209 wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS "
210 "connection: %s", gnutls_strerror(ret));
211 return -1;
212 }
213
214 ret = gnutls_set_default_priority(conn->session);
215 if (ret < 0)
216 goto fail;
217
218 ret = gnutls_priority_set_direct(conn->session,
219 conn->prio_str ? conn->prio_str :
220 "NORMAL:-VERS-SSL3.0",
221 &err);
222 if (ret < 0) {
223 wpa_printf(MSG_ERROR, "GnuTLS: Priority string failure at "
224 "'%s'", err);
225 goto fail;
226 }
227
228 gnutls_transport_set_pull_function(conn->session, tls_pull_func);
229 gnutls_transport_set_push_function(conn->session, tls_push_func);
230 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
231 gnutls_session_set_ptr(conn->session, conn);
232
233 return 0;
234
235 fail:
236 wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s",
237 gnutls_strerror(ret));
238 gnutls_deinit(conn->session);
239 return -1;
240 }
241
242
tls_connection_init(void * ssl_ctx)243 struct tls_connection * tls_connection_init(void *ssl_ctx)
244 {
245 struct tls_global *global = ssl_ctx;
246 struct tls_connection *conn;
247 int ret;
248
249 conn = os_zalloc(sizeof(*conn));
250 if (conn == NULL)
251 return NULL;
252 conn->global = global;
253
254 if (tls_gnutls_init_session(global, conn)) {
255 os_free(conn);
256 return NULL;
257 }
258
259 if (global->params_set) {
260 ret = gnutls_credentials_set(conn->session,
261 GNUTLS_CRD_CERTIFICATE,
262 global->xcred);
263 if (ret < 0) {
264 wpa_printf(MSG_INFO, "Failed to configure "
265 "credentials: %s", gnutls_strerror(ret));
266 os_free(conn);
267 return NULL;
268 }
269 }
270
271 if (gnutls_certificate_allocate_credentials(&conn->xcred)) {
272 os_free(conn);
273 return NULL;
274 }
275
276 return conn;
277 }
278
279
tls_connection_deinit(void * ssl_ctx,struct tls_connection * conn)280 void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
281 {
282 if (conn == NULL)
283 return;
284
285 gnutls_certificate_free_credentials(conn->xcred);
286 gnutls_deinit(conn->session);
287 os_free(conn->pre_shared_secret);
288 wpabuf_free(conn->push_buf);
289 wpabuf_free(conn->pull_buf);
290 os_free(conn->suffix_match);
291 os_free(conn->domain_match);
292 os_free(conn->prio_str);
293 os_free(conn);
294 }
295
296
tls_connection_established(void * ssl_ctx,struct tls_connection * conn)297 int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
298 {
299 return conn ? conn->established : 0;
300 }
301
302
tls_connection_peer_serial_num(void * tls_ctx,struct tls_connection * conn)303 char * tls_connection_peer_serial_num(void *tls_ctx,
304 struct tls_connection *conn)
305 {
306 /* TODO */
307 return NULL;
308 }
309
310
tls_connection_shutdown(void * ssl_ctx,struct tls_connection * conn)311 int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
312 {
313 struct tls_global *global = ssl_ctx;
314 int ret;
315
316 if (conn == NULL)
317 return -1;
318
319 /* Shutdown previous TLS connection without notifying the peer
320 * because the connection was already terminated in practice
321 * and "close notify" shutdown alert would confuse AS. */
322 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
323 wpabuf_free(conn->push_buf);
324 conn->push_buf = NULL;
325 conn->established = 0;
326
327 gnutls_deinit(conn->session);
328 if (tls_gnutls_init_session(global, conn)) {
329 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
330 "for session resumption use");
331 return -1;
332 }
333
334 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
335 conn->params_set ? conn->xcred :
336 global->xcred);
337 if (ret < 0) {
338 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
339 "for session resumption: %s", gnutls_strerror(ret));
340 return -1;
341 }
342
343 if (global->session_data) {
344 ret = gnutls_session_set_data(conn->session,
345 global->session_data,
346 global->session_data_size);
347 if (ret < 0) {
348 wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
349 "data: %s", gnutls_strerror(ret));
350 return -1;
351 }
352 }
353
354 return 0;
355 }
356
357
tls_connection_set_params(void * tls_ctx,struct tls_connection * conn,const struct tls_connection_params * params)358 int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
359 const struct tls_connection_params *params)
360 {
361 int ret;
362 const char *err;
363 char prio_buf[100];
364 const char *prio = NULL;
365
366 if (conn == NULL || params == NULL)
367 return -1;
368
369 if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
370 wpa_printf(MSG_INFO,
371 "GnuTLS: ocsp=3 not supported");
372 return -1;
373 }
374
375 if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
376 wpa_printf(MSG_INFO,
377 "GnuTLS: tls_ext_cert_check=1 not supported");
378 return -1;
379 }
380
381 if (params->subject_match) {
382 wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
383 return -1;
384 }
385
386 if (params->altsubject_match) {
387 wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
388 return -1;
389 }
390
391 os_free(conn->suffix_match);
392 conn->suffix_match = NULL;
393 if (params->suffix_match) {
394 conn->suffix_match = os_strdup(params->suffix_match);
395 if (conn->suffix_match == NULL)
396 return -1;
397 }
398
399 #if GNUTLS_VERSION_NUMBER >= 0x030300
400 os_free(conn->domain_match);
401 conn->domain_match = NULL;
402 if (params->domain_match) {
403 conn->domain_match = os_strdup(params->domain_match);
404 if (conn->domain_match == NULL)
405 return -1;
406 }
407 #else /* < 3.3.0 */
408 if (params->domain_match) {
409 wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
410 return -1;
411 }
412 #endif /* >= 3.3.0 */
413
414 conn->flags = params->flags;
415
416 if (params->flags & (TLS_CONN_DISABLE_TLSv1_0 |
417 TLS_CONN_DISABLE_TLSv1_1 |
418 TLS_CONN_DISABLE_TLSv1_2 |
419 TLS_CONN_DISABLE_TLSv1_3)) {
420 os_snprintf(prio_buf, sizeof(prio_buf),
421 "NORMAL:-VERS-SSL3.0%s%s%s%s",
422 params->flags & TLS_CONN_DISABLE_TLSv1_0 ?
423 ":-VERS-TLS1.0" : "",
424 params->flags & TLS_CONN_DISABLE_TLSv1_1 ?
425 ":-VERS-TLS1.1" : "",
426 params->flags & TLS_CONN_DISABLE_TLSv1_2 ?
427 ":-VERS-TLS1.2" : "",
428 params->flags & TLS_CONN_DISABLE_TLSv1_3 ?
429 ":-VERS-TLS1.3" : "");
430 prio = prio_buf;
431 }
432
433 if (params->openssl_ciphers) {
434 if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) {
435 prio = "SUITEB128";
436 } else if (os_strcmp(params->openssl_ciphers,
437 "SUITEB192") == 0) {
438 prio = "SUITEB192";
439 } else if ((params->flags & TLS_CONN_SUITEB) &&
440 os_strcmp(params->openssl_ciphers,
441 "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
442 prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
443 } else if (os_strcmp(params->openssl_ciphers,
444 "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
445 prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
446 } else if (os_strcmp(params->openssl_ciphers,
447 "DHE-RSA-AES256-GCM-SHA384") == 0) {
448 prio = "NONE:+VERS-TLS1.2:+AEAD:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
449 } else if (os_strcmp(params->openssl_ciphers,
450 "ECDHE-ECDSA-AES256-GCM-SHA384") == 0) {
451 prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
452 } else {
453 wpa_printf(MSG_INFO,
454 "GnuTLS: openssl_ciphers not supported");
455 return -1;
456 }
457 } else if (params->flags & TLS_CONN_SUITEB) {
458 prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
459 }
460
461 if (prio) {
462 wpa_printf(MSG_DEBUG, "GnuTLS: Set priority string: %s", prio);
463 ret = gnutls_priority_set_direct(conn->session, prio, &err);
464 if (ret < 0) {
465 wpa_printf(MSG_ERROR,
466 "GnuTLS: Priority string failure at '%s'",
467 err);
468 return -1;
469 }
470 os_free(conn->prio_str);
471 conn->prio_str = os_strdup(prio);
472 }
473
474 if (params->openssl_ecdh_curves) {
475 wpa_printf(MSG_INFO,
476 "GnuTLS: openssl_ecdh_curves not supported");
477 return -1;
478 }
479
480 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
481 * to force peer validation(?) */
482
483 if (params->ca_cert) {
484 wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
485 params->ca_cert);
486 ret = gnutls_certificate_set_x509_trust_file(
487 conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
488 if (ret < 0) {
489 wpa_printf(MSG_DEBUG,
490 "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
491 params->ca_cert,
492 gnutls_strerror(ret));
493 ret = gnutls_certificate_set_x509_trust_file(
494 conn->xcred, params->ca_cert,
495 GNUTLS_X509_FMT_PEM);
496 if (ret < 0) {
497 wpa_printf(MSG_DEBUG,
498 "Failed to read CA cert '%s' in PEM format: %s",
499 params->ca_cert,
500 gnutls_strerror(ret));
501 return -1;
502 }
503 wpa_printf(MSG_DEBUG,
504 "GnuTLS: Successfully read CA cert '%s' in PEM format",
505 params->ca_cert);
506 } else {
507 wpa_printf(MSG_DEBUG,
508 "GnuTLS: Successfully read CA cert '%s' in DER format",
509 params->ca_cert);
510 }
511 } else if (params->ca_cert_blob) {
512 gnutls_datum_t ca;
513
514 ca.data = (unsigned char *) params->ca_cert_blob;
515 ca.size = params->ca_cert_blob_len;
516
517 ret = gnutls_certificate_set_x509_trust_mem(
518 conn->xcred, &ca, GNUTLS_X509_FMT_DER);
519 if (ret < 0) {
520 wpa_printf(MSG_DEBUG,
521 "Failed to parse CA cert in DER format: %s",
522 gnutls_strerror(ret));
523 ret = gnutls_certificate_set_x509_trust_mem(
524 conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
525 if (ret < 0) {
526 wpa_printf(MSG_DEBUG,
527 "Failed to parse CA cert in PEM format: %s",
528 gnutls_strerror(ret));
529 return -1;
530 }
531 }
532 } else if (params->ca_path) {
533 wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
534 return -1;
535 }
536
537 conn->disable_time_checks = 0;
538 if (params->ca_cert || params->ca_cert_blob) {
539 conn->verify_peer = 1;
540 gnutls_certificate_set_verify_function(
541 conn->xcred, tls_connection_verify_peer);
542
543 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
544 gnutls_certificate_set_verify_flags(
545 conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
546 }
547
548 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
549 conn->disable_time_checks = 1;
550 gnutls_certificate_set_verify_flags(
551 conn->xcred,
552 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
553 }
554 }
555
556 if (params->client_cert && params->private_key) {
557 wpa_printf(MSG_DEBUG,
558 "GnuTLS: Try to parse client cert '%s' and key '%s' in DER format",
559 params->client_cert, params->private_key);
560 #if GNUTLS_VERSION_NUMBER >= 0x03010b
561 ret = gnutls_certificate_set_x509_key_file2(
562 conn->xcred, params->client_cert, params->private_key,
563 GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
564 #else
565 /* private_key_passwd not (easily) supported here */
566 ret = gnutls_certificate_set_x509_key_file(
567 conn->xcred, params->client_cert, params->private_key,
568 GNUTLS_X509_FMT_DER);
569 #endif
570 if (ret < 0) {
571 wpa_printf(MSG_DEBUG,
572 "GnuTLS: Failed to read client cert/key in DER format (%s) - try in PEM format",
573 gnutls_strerror(ret));
574 #if GNUTLS_VERSION_NUMBER >= 0x03010b
575 ret = gnutls_certificate_set_x509_key_file2(
576 conn->xcred, params->client_cert,
577 params->private_key, GNUTLS_X509_FMT_PEM,
578 params->private_key_passwd, 0);
579 #else
580 ret = gnutls_certificate_set_x509_key_file(
581 conn->xcred, params->client_cert,
582 params->private_key, GNUTLS_X509_FMT_PEM);
583 #endif
584 if (ret < 0) {
585 wpa_printf(MSG_DEBUG, "Failed to read client "
586 "cert/key in PEM format: %s",
587 gnutls_strerror(ret));
588 return ret;
589 }
590 wpa_printf(MSG_DEBUG,
591 "GnuTLS: Successfully read client cert/key in PEM format");
592 } else {
593 wpa_printf(MSG_DEBUG,
594 "GnuTLS: Successfully read client cert/key in DER format");
595 }
596 } else if (params->private_key) {
597 int pkcs12_ok = 0;
598 #ifdef PKCS12_FUNCS
599 /* Try to load in PKCS#12 format */
600 wpa_printf(MSG_DEBUG,
601 "GnuTLS: Try to parse client cert/key '%s'in PKCS#12 DER format",
602 params->private_key);
603 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
604 conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
605 params->private_key_passwd);
606 if (ret != 0) {
607 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
608 "PKCS#12 format: %s", gnutls_strerror(ret));
609 return -1;
610 } else
611 pkcs12_ok = 1;
612 #endif /* PKCS12_FUNCS */
613
614 if (!pkcs12_ok) {
615 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
616 "included");
617 return -1;
618 }
619 } else if (params->client_cert_blob && params->private_key_blob) {
620 gnutls_datum_t cert, key;
621
622 cert.data = (unsigned char *) params->client_cert_blob;
623 cert.size = params->client_cert_blob_len;
624 key.data = (unsigned char *) params->private_key_blob;
625 key.size = params->private_key_blob_len;
626
627 #if GNUTLS_VERSION_NUMBER >= 0x03010b
628 ret = gnutls_certificate_set_x509_key_mem2(
629 conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
630 params->private_key_passwd, 0);
631 #else
632 /* private_key_passwd not (easily) supported here */
633 ret = gnutls_certificate_set_x509_key_mem(
634 conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
635 #endif
636 if (ret < 0) {
637 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
638 "in DER format: %s", gnutls_strerror(ret));
639 #if GNUTLS_VERSION_NUMBER >= 0x03010b
640 ret = gnutls_certificate_set_x509_key_mem2(
641 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
642 params->private_key_passwd, 0);
643 #else
644 /* private_key_passwd not (easily) supported here */
645 ret = gnutls_certificate_set_x509_key_mem(
646 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
647 #endif
648 if (ret < 0) {
649 wpa_printf(MSG_DEBUG, "Failed to read client "
650 "cert/key in PEM format: %s",
651 gnutls_strerror(ret));
652 return ret;
653 }
654 }
655 } else if (params->private_key_blob) {
656 #ifdef PKCS12_FUNCS
657 gnutls_datum_t key;
658
659 key.data = (unsigned char *) params->private_key_blob;
660 key.size = params->private_key_blob_len;
661
662 /* Try to load in PKCS#12 format */
663 ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
664 conn->xcred, &key, GNUTLS_X509_FMT_DER,
665 params->private_key_passwd);
666 if (ret != 0) {
667 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
668 "PKCS#12 format: %s", gnutls_strerror(ret));
669 return -1;
670 }
671 #else /* PKCS12_FUNCS */
672 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
673 return -1;
674 #endif /* PKCS12_FUNCS */
675 }
676
677 #if GNUTLS_VERSION_NUMBER >= 0x030103
678 if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
679 ret = gnutls_ocsp_status_request_enable_client(conn->session,
680 NULL, 0, NULL);
681 if (ret != GNUTLS_E_SUCCESS) {
682 wpa_printf(MSG_INFO,
683 "GnuTLS: Failed to enable OCSP client");
684 return -1;
685 }
686 }
687 #else /* 3.1.3 */
688 if (params->flags & TLS_CONN_REQUIRE_OCSP) {
689 wpa_printf(MSG_INFO,
690 "GnuTLS: OCSP not supported by this version of GnuTLS");
691 return -1;
692 }
693 #endif /* 3.1.3 */
694
695 conn->params_set = 1;
696
697 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
698 conn->xcred);
699 if (ret < 0) {
700 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
701 gnutls_strerror(ret));
702 }
703
704 return ret;
705 }
706
707
708 #if GNUTLS_VERSION_NUMBER >= 0x030103
server_ocsp_status_req(gnutls_session_t session,void * ptr,gnutls_datum_t * resp)709 static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
710 gnutls_datum_t *resp)
711 {
712 struct tls_global *global = ptr;
713 char *cached;
714 size_t len;
715
716 if (!global->ocsp_stapling_response) {
717 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
718 return GNUTLS_E_NO_CERTIFICATE_STATUS;
719 }
720
721 cached = os_readfile(global->ocsp_stapling_response, &len);
722 if (!cached) {
723 wpa_printf(MSG_DEBUG,
724 "GnuTLS: OCSP status callback - could not read response file (%s)",
725 global->ocsp_stapling_response);
726 return GNUTLS_E_NO_CERTIFICATE_STATUS;
727 }
728
729 wpa_printf(MSG_DEBUG,
730 "GnuTLS: OCSP status callback - send cached response");
731 resp->data = gnutls_malloc(len);
732 if (!resp->data) {
733 os_free(resp);
734 return GNUTLS_E_MEMORY_ERROR;
735 }
736
737 os_memcpy(resp->data, cached, len);
738 resp->size = len;
739 os_free(cached);
740
741 return GNUTLS_E_SUCCESS;
742 }
743 #endif /* 3.1.3 */
744
745
tls_global_set_params(void * tls_ctx,const struct tls_connection_params * params)746 int tls_global_set_params(void *tls_ctx,
747 const struct tls_connection_params *params)
748 {
749 struct tls_global *global = tls_ctx;
750 int ret;
751
752 if (params->check_cert_subject)
753 return -1; /* not yet supported */
754
755 /* Currently, global parameters are only set when running in server
756 * mode. */
757 global->server = 1;
758
759 if (global->params_set) {
760 gnutls_certificate_free_credentials(global->xcred);
761 global->params_set = 0;
762 }
763
764 ret = gnutls_certificate_allocate_credentials(&global->xcred);
765 if (ret) {
766 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
767 "%s", gnutls_strerror(ret));
768 return -1;
769 }
770
771 if (params->ca_cert) {
772 ret = gnutls_certificate_set_x509_trust_file(
773 global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
774 if (ret < 0) {
775 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
776 "in DER format: %s", params->ca_cert,
777 gnutls_strerror(ret));
778 ret = gnutls_certificate_set_x509_trust_file(
779 global->xcred, params->ca_cert,
780 GNUTLS_X509_FMT_PEM);
781 if (ret < 0) {
782 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
783 "'%s' in PEM format: %s",
784 params->ca_cert,
785 gnutls_strerror(ret));
786 goto fail;
787 }
788 }
789
790 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
791 gnutls_certificate_set_verify_flags(
792 global->xcred,
793 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
794 }
795
796 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
797 gnutls_certificate_set_verify_flags(
798 global->xcred,
799 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
800 }
801 }
802
803 if (params->client_cert && params->private_key) {
804 /* TODO: private_key_passwd? */
805 ret = gnutls_certificate_set_x509_key_file(
806 global->xcred, params->client_cert,
807 params->private_key, GNUTLS_X509_FMT_DER);
808 if (ret < 0) {
809 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
810 "in DER format: %s", gnutls_strerror(ret));
811 ret = gnutls_certificate_set_x509_key_file(
812 global->xcred, params->client_cert,
813 params->private_key, GNUTLS_X509_FMT_PEM);
814 if (ret < 0) {
815 wpa_printf(MSG_DEBUG, "Failed to read client "
816 "cert/key in PEM format: %s",
817 gnutls_strerror(ret));
818 goto fail;
819 }
820 }
821 } else if (params->private_key) {
822 int pkcs12_ok = 0;
823 #ifdef PKCS12_FUNCS
824 /* Try to load in PKCS#12 format */
825 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
826 global->xcred, params->private_key,
827 GNUTLS_X509_FMT_DER, params->private_key_passwd);
828 if (ret != 0) {
829 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
830 "PKCS#12 format: %s", gnutls_strerror(ret));
831 goto fail;
832 } else
833 pkcs12_ok = 1;
834 #endif /* PKCS12_FUNCS */
835
836 if (!pkcs12_ok) {
837 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
838 "included");
839 goto fail;
840 }
841 }
842
843 #if GNUTLS_VERSION_NUMBER >= 0x030103
844 os_free(global->ocsp_stapling_response);
845 if (params->ocsp_stapling_response)
846 global->ocsp_stapling_response =
847 os_strdup(params->ocsp_stapling_response);
848 else
849 global->ocsp_stapling_response = NULL;
850 gnutls_certificate_set_ocsp_status_request_function(
851 global->xcred, server_ocsp_status_req, global);
852 #endif /* 3.1.3 */
853
854 global->params_set = 1;
855
856 return 0;
857
858 fail:
859 gnutls_certificate_free_credentials(global->xcred);
860 return -1;
861 }
862
863
tls_global_set_verify(void * ssl_ctx,int check_crl,int strict)864 int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
865 {
866 /* TODO */
867 return 0;
868 }
869
870
tls_connection_set_verify(void * ssl_ctx,struct tls_connection * conn,int verify_peer,unsigned int flags,const u8 * session_ctx,size_t session_ctx_len)871 int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
872 int verify_peer, unsigned int flags,
873 const u8 *session_ctx, size_t session_ctx_len)
874 {
875 if (conn == NULL || conn->session == NULL)
876 return -1;
877
878 conn->verify_peer = verify_peer;
879 gnutls_certificate_server_set_request(conn->session,
880 verify_peer ? GNUTLS_CERT_REQUIRE
881 : GNUTLS_CERT_REQUEST);
882
883 return 0;
884 }
885
886
tls_connection_get_random(void * ssl_ctx,struct tls_connection * conn,struct tls_random * keys)887 int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
888 struct tls_random *keys)
889 {
890 #if GNUTLS_VERSION_NUMBER >= 0x030012
891 gnutls_datum_t client, server;
892
893 if (conn == NULL || conn->session == NULL || keys == NULL)
894 return -1;
895
896 os_memset(keys, 0, sizeof(*keys));
897 gnutls_session_get_random(conn->session, &client, &server);
898 keys->client_random = client.data;
899 keys->server_random = server.data;
900 keys->client_random_len = client.size;
901 keys->server_random_len = client.size;
902
903 return 0;
904 #else /* 3.0.18 */
905 return -1;
906 #endif /* 3.0.18 */
907 }
908
909
tls_connection_export_key(void * tls_ctx,struct tls_connection * conn,const char * label,const u8 * context,size_t context_len,u8 * out,size_t out_len)910 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
911 const char *label, const u8 *context,
912 size_t context_len, u8 *out, size_t out_len)
913 {
914 if (conn == NULL || conn->session == NULL)
915 return -1;
916
917 #if GNUTLS_VERSION_NUMBER >= 0x030404
918 return gnutls_prf_rfc5705(conn->session, os_strlen(label), label,
919 context_len, (const char *) context,
920 out_len, (char *) out);
921 #else /* 3.4.4 */
922 if (context)
923 return -1;
924 return gnutls_prf(conn->session, os_strlen(label), label,
925 0 /* client_random first */, 0, NULL, out_len,
926 (char *) out);
927 #endif /* 3.4.4 */
928 }
929
930
tls_connection_get_eap_fast_key(void * tls_ctx,struct tls_connection * conn,u8 * out,size_t out_len)931 int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
932 u8 *out, size_t out_len)
933 {
934 return -1;
935 }
936
937
gnutls_tls_fail_event(struct tls_connection * conn,const gnutls_datum_t * cert,int depth,const char * subject,const char * err_str,enum tls_fail_reason reason)938 static void gnutls_tls_fail_event(struct tls_connection *conn,
939 const gnutls_datum_t *cert, int depth,
940 const char *subject, const char *err_str,
941 enum tls_fail_reason reason)
942 {
943 union tls_event_data ev;
944 struct tls_global *global = conn->global;
945 struct wpabuf *cert_buf = NULL;
946
947 if (global->event_cb == NULL)
948 return;
949
950 os_memset(&ev, 0, sizeof(ev));
951 ev.cert_fail.depth = depth;
952 ev.cert_fail.subject = subject ? subject : "";
953 ev.cert_fail.reason = reason;
954 ev.cert_fail.reason_txt = err_str;
955 if (cert) {
956 cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
957 ev.cert_fail.cert = cert_buf;
958 }
959 global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
960 wpabuf_free(cert_buf);
961 }
962
963
964 #if GNUTLS_VERSION_NUMBER < 0x030300
server_eku_purpose(gnutls_x509_crt_t cert)965 static int server_eku_purpose(gnutls_x509_crt_t cert)
966 {
967 unsigned int i;
968
969 for (i = 0; ; i++) {
970 char oid[128];
971 size_t oid_size = sizeof(oid);
972 int res;
973
974 res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
975 &oid_size, NULL);
976 if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
977 if (i == 0) {
978 /* No EKU - assume any use allowed */
979 return 1;
980 }
981 break;
982 }
983
984 if (res < 0) {
985 wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
986 return 0;
987 }
988
989 wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
990 if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
991 os_strcmp(oid, GNUTLS_KP_ANY) == 0)
992 return 1;
993 }
994
995 return 0;
996 }
997 #endif /* < 3.3.0 */
998
999
check_ocsp(struct tls_connection * conn,gnutls_session_t session,gnutls_alert_description_t * err)1000 static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
1001 gnutls_alert_description_t *err)
1002 {
1003 #if GNUTLS_VERSION_NUMBER >= 0x030103
1004 gnutls_datum_t response, buf;
1005 gnutls_ocsp_resp_t resp;
1006 unsigned int cert_status;
1007 int res;
1008
1009 if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
1010 return 0;
1011
1012 if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
1013 if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
1014 wpa_printf(MSG_INFO,
1015 "GnuTLS: No valid OCSP response received");
1016 goto ocsp_error;
1017 }
1018
1019 wpa_printf(MSG_DEBUG,
1020 "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
1021 return 0;
1022 }
1023
1024 /*
1025 * GnuTLS has already verified the OCSP response in
1026 * check_ocsp_response() and rejected handshake if the certificate was
1027 * found to be revoked. However, if the response indicates that the
1028 * status is unknown, handshake continues and reaches here. We need to
1029 * re-import the OCSP response to check for unknown certificate status,
1030 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
1031 * gnutls_ocsp_resp_verify_direct() calls.
1032 */
1033
1034 res = gnutls_ocsp_status_request_get(session, &response);
1035 if (res != GNUTLS_E_SUCCESS) {
1036 wpa_printf(MSG_INFO,
1037 "GnuTLS: OCSP response was received, but it was not valid");
1038 goto ocsp_error;
1039 }
1040
1041 if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
1042 goto ocsp_error;
1043
1044 res = gnutls_ocsp_resp_import(resp, &response);
1045 if (res != GNUTLS_E_SUCCESS) {
1046 wpa_printf(MSG_INFO,
1047 "GnuTLS: Could not parse received OCSP response: %s",
1048 gnutls_strerror(res));
1049 gnutls_ocsp_resp_deinit(resp);
1050 goto ocsp_error;
1051 }
1052
1053 res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
1054 if (res == GNUTLS_E_SUCCESS) {
1055 wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
1056 gnutls_free(buf.data);
1057 }
1058
1059 res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
1060 NULL, &cert_status, NULL,
1061 NULL, NULL, NULL);
1062 gnutls_ocsp_resp_deinit(resp);
1063 if (res != GNUTLS_E_SUCCESS) {
1064 wpa_printf(MSG_INFO,
1065 "GnuTLS: Failed to extract OCSP information: %s",
1066 gnutls_strerror(res));
1067 goto ocsp_error;
1068 }
1069
1070 if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
1071 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
1072 } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
1073 wpa_printf(MSG_DEBUG,
1074 "GnuTLS: OCSP cert status: revoked");
1075 goto ocsp_error;
1076 } else {
1077 wpa_printf(MSG_DEBUG,
1078 "GnuTLS: OCSP cert status: unknown");
1079 if (conn->flags & TLS_CONN_REQUIRE_OCSP)
1080 goto ocsp_error;
1081 wpa_printf(MSG_DEBUG,
1082 "GnuTLS: OCSP was not required, so allow connection to continue");
1083 }
1084
1085 return 0;
1086
1087 ocsp_error:
1088 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1089 "bad certificate status response",
1090 TLS_FAIL_REVOKED);
1091 *err = GNUTLS_A_CERTIFICATE_REVOKED;
1092 return -1;
1093 #else /* GnuTLS 3.1.3 or newer */
1094 return 0;
1095 #endif /* GnuTLS 3.1.3 or newer */
1096 }
1097
1098
tls_match_suffix_helper(gnutls_x509_crt_t cert,const char * match,int full)1099 static int tls_match_suffix_helper(gnutls_x509_crt_t cert, const char *match,
1100 int full)
1101 {
1102 int res = -1;
1103
1104 #if GNUTLS_VERSION_NUMBER >= 0x030300
1105 if (full)
1106 res = gnutls_x509_crt_check_hostname2(
1107 cert, match,
1108 GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS);
1109 #endif /* >= 3.3.0 */
1110 if (res == -1)
1111 res = gnutls_x509_crt_check_hostname(cert, match);
1112
1113 wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s --> res=%d",
1114 full ? "": "suffix ", match, res);
1115 return res;
1116 }
1117
1118
tls_match_suffix(gnutls_x509_crt_t cert,const char * match,int full)1119 static int tls_match_suffix(gnutls_x509_crt_t cert, const char *match,
1120 int full)
1121 {
1122 char *values, *token, *context = NULL;
1123 int ret = 0;
1124
1125 if (!os_strchr(match, ';'))
1126 return tls_match_suffix_helper(cert, match, full);
1127
1128 values = os_strdup(match);
1129 if (!values)
1130 return 0;
1131
1132 /* Process each match alternative separately until a match is found */
1133 while ((token = str_token(values, ";", &context))) {
1134 if (tls_match_suffix_helper(cert, token, full)) {
1135 ret = 1;
1136 break;
1137 }
1138 }
1139
1140 os_free(values);
1141 return ret;
1142 }
1143
1144
tls_connection_verify_peer(gnutls_session_t session)1145 static int tls_connection_verify_peer(gnutls_session_t session)
1146 {
1147 struct tls_connection *conn;
1148 unsigned int status, num_certs, i;
1149 struct os_time now;
1150 const gnutls_datum_t *certs;
1151 gnutls_x509_crt_t cert;
1152 gnutls_alert_description_t err;
1153 int res;
1154
1155 conn = gnutls_session_get_ptr(session);
1156 if (!conn->verify_peer) {
1157 wpa_printf(MSG_DEBUG,
1158 "GnuTLS: No peer certificate verification enabled");
1159 return 0;
1160 }
1161
1162 wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
1163
1164 #if GNUTLS_VERSION_NUMBER >= 0x030300
1165 {
1166 gnutls_typed_vdata_st data[1];
1167 unsigned int elements = 0;
1168
1169 os_memset(data, 0, sizeof(data));
1170 if (!conn->global->server) {
1171 data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
1172 data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
1173 elements++;
1174 }
1175 res = gnutls_certificate_verify_peers(session, data, 1,
1176 &status);
1177 }
1178 #else /* < 3.3.0 */
1179 res = gnutls_certificate_verify_peers2(session, &status);
1180 #endif
1181 if (res < 0) {
1182 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
1183 "certificate chain");
1184 err = GNUTLS_A_INTERNAL_ERROR;
1185 goto out;
1186 }
1187
1188 #if GNUTLS_VERSION_NUMBER >= 0x030104
1189 {
1190 gnutls_datum_t info;
1191 int ret, type;
1192
1193 type = gnutls_certificate_type_get(session);
1194 ret = gnutls_certificate_verification_status_print(status, type,
1195 &info, 0);
1196 if (ret < 0) {
1197 wpa_printf(MSG_DEBUG,
1198 "GnuTLS: Failed to print verification status");
1199 err = GNUTLS_A_INTERNAL_ERROR;
1200 goto out;
1201 }
1202 wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
1203 gnutls_free(info.data);
1204 }
1205 #endif /* GnuTLS 3.1.4 or newer */
1206
1207 certs = gnutls_certificate_get_peers(session, &num_certs);
1208 if (certs == NULL || num_certs == 0) {
1209 wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
1210 err = GNUTLS_A_UNKNOWN_CA;
1211 goto out;
1212 }
1213
1214 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
1215 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
1216 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1217 wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
1218 "algorithm");
1219 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1220 "certificate uses insecure algorithm",
1221 TLS_FAIL_BAD_CERTIFICATE);
1222 err = GNUTLS_A_INSUFFICIENT_SECURITY;
1223 goto out;
1224 }
1225 if (status & GNUTLS_CERT_NOT_ACTIVATED) {
1226 wpa_printf(MSG_INFO, "TLS: Certificate not yet "
1227 "activated");
1228 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1229 "certificate not yet valid",
1230 TLS_FAIL_NOT_YET_VALID);
1231 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1232 goto out;
1233 }
1234 if (status & GNUTLS_CERT_EXPIRED) {
1235 wpa_printf(MSG_INFO, "TLS: Certificate expired");
1236 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1237 "certificate has expired",
1238 TLS_FAIL_EXPIRED);
1239 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1240 goto out;
1241 }
1242 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1243 "untrusted certificate",
1244 TLS_FAIL_UNTRUSTED);
1245 err = GNUTLS_A_INTERNAL_ERROR;
1246 goto out;
1247 }
1248
1249 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1250 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
1251 "known issuer");
1252 gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1253 TLS_FAIL_UNTRUSTED);
1254 err = GNUTLS_A_UNKNOWN_CA;
1255 goto out;
1256 }
1257
1258 if (status & GNUTLS_CERT_REVOKED) {
1259 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
1260 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1261 "certificate revoked",
1262 TLS_FAIL_REVOKED);
1263 err = GNUTLS_A_CERTIFICATE_REVOKED;
1264 goto out;
1265 }
1266
1267 if (status != 0) {
1268 wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1269 status);
1270 err = GNUTLS_A_INTERNAL_ERROR;
1271 goto out;
1272 }
1273
1274 if (check_ocsp(conn, session, &err))
1275 goto out;
1276
1277 os_get_time(&now);
1278
1279 for (i = 0; i < num_certs; i++) {
1280 char *buf;
1281 size_t len;
1282 if (gnutls_x509_crt_init(&cert) < 0) {
1283 wpa_printf(MSG_INFO, "TLS: Certificate initialization "
1284 "failed");
1285 err = GNUTLS_A_BAD_CERTIFICATE;
1286 goto out;
1287 }
1288
1289 if (gnutls_x509_crt_import(cert, &certs[i],
1290 GNUTLS_X509_FMT_DER) < 0) {
1291 wpa_printf(MSG_INFO, "TLS: Could not parse peer "
1292 "certificate %d/%d", i + 1, num_certs);
1293 gnutls_x509_crt_deinit(cert);
1294 err = GNUTLS_A_BAD_CERTIFICATE;
1295 goto out;
1296 }
1297
1298 gnutls_x509_crt_get_dn(cert, NULL, &len);
1299 len++;
1300 buf = os_malloc(len + 1);
1301 if (buf) {
1302 buf[0] = buf[len] = '\0';
1303 gnutls_x509_crt_get_dn(cert, buf, &len);
1304 }
1305 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
1306 i + 1, num_certs, buf);
1307
1308 if (conn->global->event_cb) {
1309 struct wpabuf *cert_buf = NULL;
1310 union tls_event_data ev;
1311 #ifdef CONFIG_SHA256
1312 u8 hash[32];
1313 const u8 *_addr[1];
1314 size_t _len[1];
1315 #endif /* CONFIG_SHA256 */
1316
1317 os_memset(&ev, 0, sizeof(ev));
1318 if (conn->global->cert_in_cb) {
1319 cert_buf = wpabuf_alloc_copy(certs[i].data,
1320 certs[i].size);
1321 ev.peer_cert.cert = cert_buf;
1322 }
1323 #ifdef CONFIG_SHA256
1324 _addr[0] = certs[i].data;
1325 _len[0] = certs[i].size;
1326 if (sha256_vector(1, _addr, _len, hash) == 0) {
1327 ev.peer_cert.hash = hash;
1328 ev.peer_cert.hash_len = sizeof(hash);
1329 }
1330 #endif /* CONFIG_SHA256 */
1331 ev.peer_cert.depth = i;
1332 ev.peer_cert.subject = buf;
1333 conn->global->event_cb(conn->global->cb_ctx,
1334 TLS_PEER_CERTIFICATE, &ev);
1335 wpabuf_free(cert_buf);
1336 }
1337
1338 if (i == 0) {
1339 if (conn->suffix_match &&
1340 !tls_match_suffix(cert, conn->suffix_match, 0)) {
1341 wpa_printf(MSG_WARNING,
1342 "TLS: Domain suffix match '%s' not found",
1343 conn->suffix_match);
1344 gnutls_tls_fail_event(
1345 conn, &certs[i], i, buf,
1346 "Domain suffix mismatch",
1347 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1348 err = GNUTLS_A_BAD_CERTIFICATE;
1349 gnutls_x509_crt_deinit(cert);
1350 os_free(buf);
1351 goto out;
1352 }
1353
1354 #if GNUTLS_VERSION_NUMBER >= 0x030300
1355 if (conn->domain_match &&
1356 !tls_match_suffix(cert, conn->domain_match, 1)) {
1357 wpa_printf(MSG_WARNING,
1358 "TLS: Domain match '%s' not found",
1359 conn->domain_match);
1360 gnutls_tls_fail_event(
1361 conn, &certs[i], i, buf,
1362 "Domain mismatch",
1363 TLS_FAIL_DOMAIN_MISMATCH);
1364 err = GNUTLS_A_BAD_CERTIFICATE;
1365 gnutls_x509_crt_deinit(cert);
1366 os_free(buf);
1367 goto out;
1368 }
1369 #endif /* >= 3.3.0 */
1370
1371 /* TODO: validate altsubject_match.
1372 * For now, any such configuration is rejected in
1373 * tls_connection_set_params() */
1374
1375 #if GNUTLS_VERSION_NUMBER < 0x030300
1376 /*
1377 * gnutls_certificate_verify_peers() not available, so
1378 * need to check EKU separately.
1379 */
1380 if (!conn->global->server &&
1381 !server_eku_purpose(cert)) {
1382 wpa_printf(MSG_WARNING,
1383 "GnuTLS: No server EKU");
1384 gnutls_tls_fail_event(
1385 conn, &certs[i], i, buf,
1386 "No server EKU",
1387 TLS_FAIL_BAD_CERTIFICATE);
1388 err = GNUTLS_A_BAD_CERTIFICATE;
1389 gnutls_x509_crt_deinit(cert);
1390 os_free(buf);
1391 goto out;
1392 }
1393 #endif /* < 3.3.0 */
1394 }
1395
1396 if (!conn->disable_time_checks &&
1397 (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1398 gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1399 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1400 "not valid at this time",
1401 i + 1, num_certs);
1402 gnutls_tls_fail_event(
1403 conn, &certs[i], i, buf,
1404 "Certificate is not valid at this time",
1405 TLS_FAIL_EXPIRED);
1406 gnutls_x509_crt_deinit(cert);
1407 os_free(buf);
1408 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1409 goto out;
1410 }
1411
1412 os_free(buf);
1413
1414 gnutls_x509_crt_deinit(cert);
1415 }
1416
1417 if (conn->global->event_cb != NULL)
1418 conn->global->event_cb(conn->global->cb_ctx,
1419 TLS_CERT_CHAIN_SUCCESS, NULL);
1420
1421 return 0;
1422
1423 out:
1424 conn->failed++;
1425 gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1426 return GNUTLS_E_CERTIFICATE_ERROR;
1427 }
1428
1429
gnutls_get_appl_data(struct tls_connection * conn)1430 static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
1431 {
1432 int res;
1433 struct wpabuf *ad;
1434 wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
1435 ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
1436 if (ad == NULL)
1437 return NULL;
1438
1439 res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
1440 wpabuf_size(ad));
1441 wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
1442 if (res < 0) {
1443 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1444 "(%s)", __func__, (int) res,
1445 gnutls_strerror(res));
1446 wpabuf_free(ad);
1447 return NULL;
1448 }
1449
1450 wpabuf_put(ad, res);
1451 wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
1452 res);
1453 return ad;
1454 }
1455
1456
tls_connection_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)1457 struct wpabuf * tls_connection_handshake(void *tls_ctx,
1458 struct tls_connection *conn,
1459 const struct wpabuf *in_data,
1460 struct wpabuf **appl_data)
1461 {
1462 struct tls_global *global = tls_ctx;
1463 struct wpabuf *out_data;
1464 int ret;
1465
1466 if (appl_data)
1467 *appl_data = NULL;
1468
1469 if (in_data && wpabuf_len(in_data) > 0) {
1470 if (conn->pull_buf) {
1471 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1472 "pull_buf", __func__,
1473 (unsigned long) wpabuf_len(conn->pull_buf));
1474 wpabuf_free(conn->pull_buf);
1475 }
1476 conn->pull_buf = wpabuf_dup(in_data);
1477 if (conn->pull_buf == NULL)
1478 return NULL;
1479 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1480 }
1481
1482 ret = gnutls_handshake(conn->session);
1483 if (ret < 0) {
1484 gnutls_alert_description_t alert;
1485 union tls_event_data ev;
1486
1487 switch (ret) {
1488 case GNUTLS_E_AGAIN:
1489 if (global->server && conn->established &&
1490 conn->push_buf == NULL) {
1491 /* Need to return something to trigger
1492 * completion of EAP-TLS. */
1493 conn->push_buf = wpabuf_alloc(0);
1494 }
1495 break;
1496 case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
1497 wpa_printf(MSG_DEBUG, "GnuTLS: Unacceptable DH prime");
1498 if (conn->global->event_cb) {
1499 os_memset(&ev, 0, sizeof(ev));
1500 ev.alert.is_local = 1;
1501 ev.alert.type = "fatal";
1502 ev.alert.description = "insufficient security";
1503 conn->global->event_cb(conn->global->cb_ctx,
1504 TLS_ALERT, &ev);
1505 }
1506 /*
1507 * Could send a TLS Alert to the server, but for now,
1508 * simply terminate handshake.
1509 */
1510 conn->failed++;
1511 conn->write_alerts++;
1512 break;
1513 case GNUTLS_E_FATAL_ALERT_RECEIVED:
1514 alert = gnutls_alert_get(conn->session);
1515 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
1516 __func__, gnutls_alert_get_name(alert));
1517 conn->read_alerts++;
1518 if (conn->global->event_cb != NULL) {
1519 os_memset(&ev, 0, sizeof(ev));
1520 ev.alert.is_local = 0;
1521 ev.alert.type = gnutls_alert_get_name(alert);
1522 ev.alert.description = ev.alert.type;
1523 conn->global->event_cb(conn->global->cb_ctx,
1524 TLS_ALERT, &ev);
1525 }
1526 /* fallthrough */
1527 default:
1528 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
1529 "-> %s", __func__, gnutls_strerror(ret));
1530 conn->failed++;
1531 }
1532 } else {
1533 size_t size;
1534
1535 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
1536
1537 #if GNUTLS_VERSION_NUMBER >= 0x03010a
1538 {
1539 char *desc;
1540
1541 desc = gnutls_session_get_desc(conn->session);
1542 if (desc) {
1543 wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1544 gnutls_free(desc);
1545 }
1546 }
1547 #endif /* GnuTLS 3.1.10 or newer */
1548
1549 conn->established = 1;
1550 if (conn->push_buf == NULL) {
1551 /* Need to return something to get final TLS ACK. */
1552 conn->push_buf = wpabuf_alloc(0);
1553 }
1554
1555 gnutls_session_get_data(conn->session, NULL, &size);
1556 if (global->session_data == NULL ||
1557 global->session_data_size < size) {
1558 os_free(global->session_data);
1559 global->session_data = os_malloc(size);
1560 }
1561 if (global->session_data) {
1562 global->session_data_size = size;
1563 gnutls_session_get_data(conn->session,
1564 global->session_data,
1565 &global->session_data_size);
1566 }
1567
1568 if (conn->pull_buf && appl_data)
1569 *appl_data = gnutls_get_appl_data(conn);
1570 }
1571
1572 out_data = conn->push_buf;
1573 conn->push_buf = NULL;
1574 return out_data;
1575 }
1576
1577
tls_connection_server_handshake(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data,struct wpabuf ** appl_data)1578 struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1579 struct tls_connection *conn,
1580 const struct wpabuf *in_data,
1581 struct wpabuf **appl_data)
1582 {
1583 return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1584 }
1585
1586
tls_connection_encrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)1587 struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1588 struct tls_connection *conn,
1589 const struct wpabuf *in_data)
1590 {
1591 ssize_t res;
1592 struct wpabuf *buf;
1593
1594 res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1595 wpabuf_len(in_data));
1596 if (res < 0) {
1597 wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1598 __func__, gnutls_strerror(res));
1599 return NULL;
1600 }
1601
1602 buf = conn->push_buf;
1603 conn->push_buf = NULL;
1604 return buf;
1605 }
1606
1607
tls_connection_decrypt(void * tls_ctx,struct tls_connection * conn,const struct wpabuf * in_data)1608 struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1609 struct tls_connection *conn,
1610 const struct wpabuf *in_data)
1611 {
1612 ssize_t res;
1613 struct wpabuf *out;
1614
1615 if (conn->pull_buf) {
1616 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1617 "pull_buf", __func__,
1618 (unsigned long) wpabuf_len(conn->pull_buf));
1619 wpabuf_free(conn->pull_buf);
1620 }
1621 conn->pull_buf = wpabuf_dup(in_data);
1622 if (conn->pull_buf == NULL)
1623 return NULL;
1624 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1625
1626 /*
1627 * Even though we try to disable TLS compression, it is possible that
1628 * this cannot be done with all TLS libraries. Add extra buffer space
1629 * to handle the possibility of the decrypted data being longer than
1630 * input data.
1631 */
1632 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1633 if (out == NULL)
1634 return NULL;
1635
1636 res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1637 wpabuf_size(out));
1638 if (res < 0) {
1639 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1640 "(%s)", __func__, (int) res, gnutls_strerror(res));
1641 wpabuf_free(out);
1642 return NULL;
1643 }
1644 wpabuf_put(out, res);
1645
1646 return out;
1647 }
1648
1649
tls_connection_resumed(void * ssl_ctx,struct tls_connection * conn)1650 int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1651 {
1652 if (conn == NULL)
1653 return 0;
1654 return gnutls_session_is_resumed(conn->session);
1655 }
1656
1657
tls_connection_set_cipher_list(void * tls_ctx,struct tls_connection * conn,u8 * ciphers)1658 int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1659 u8 *ciphers)
1660 {
1661 /* TODO */
1662 return -1;
1663 }
1664
1665
tls_get_version(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)1666 int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1667 char *buf, size_t buflen)
1668 {
1669 gnutls_protocol_t ver;
1670
1671 ver = gnutls_protocol_get_version(conn->session);
1672 if (ver == GNUTLS_TLS1_0)
1673 os_strlcpy(buf, "TLSv1", buflen);
1674 else if (ver == GNUTLS_TLS1_1)
1675 os_strlcpy(buf, "TLSv1.1", buflen);
1676 else if (ver == GNUTLS_TLS1_2)
1677 os_strlcpy(buf, "TLSv1.2", buflen);
1678 else
1679 return -1;
1680 return 0;
1681 }
1682
1683
tls_get_cipher(void * ssl_ctx,struct tls_connection * conn,char * buf,size_t buflen)1684 int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1685 char *buf, size_t buflen)
1686 {
1687 gnutls_cipher_algorithm_t cipher;
1688 gnutls_kx_algorithm_t kx;
1689 gnutls_mac_algorithm_t mac;
1690 const char *kx_str, *cipher_str, *mac_str;
1691 int res;
1692
1693 cipher = gnutls_cipher_get(conn->session);
1694 cipher_str = gnutls_cipher_get_name(cipher);
1695 if (!cipher_str)
1696 cipher_str = "";
1697
1698 kx = gnutls_kx_get(conn->session);
1699 kx_str = gnutls_kx_get_name(kx);
1700 if (!kx_str)
1701 kx_str = "";
1702
1703 mac = gnutls_mac_get(conn->session);
1704 mac_str = gnutls_mac_get_name(mac);
1705 if (!mac_str)
1706 mac_str = "";
1707
1708 if (kx == GNUTLS_KX_RSA)
1709 res = os_snprintf(buf, buflen, "%s-%s", cipher_str, mac_str);
1710 else
1711 res = os_snprintf(buf, buflen, "%s-%s-%s",
1712 kx_str, cipher_str, mac_str);
1713 if (os_snprintf_error(buflen, res))
1714 return -1;
1715
1716 return 0;
1717 }
1718
1719
tls_connection_enable_workaround(void * ssl_ctx,struct tls_connection * conn)1720 int tls_connection_enable_workaround(void *ssl_ctx,
1721 struct tls_connection *conn)
1722 {
1723 gnutls_record_disable_padding(conn->session);
1724 return 0;
1725 }
1726
1727
tls_connection_client_hello_ext(void * ssl_ctx,struct tls_connection * conn,int ext_type,const u8 * data,size_t data_len)1728 int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1729 int ext_type, const u8 *data,
1730 size_t data_len)
1731 {
1732 /* TODO */
1733 return -1;
1734 }
1735
1736
tls_connection_get_failed(void * ssl_ctx,struct tls_connection * conn)1737 int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1738 {
1739 if (conn == NULL)
1740 return -1;
1741 return conn->failed;
1742 }
1743
1744
tls_connection_get_read_alerts(void * ssl_ctx,struct tls_connection * conn)1745 int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1746 {
1747 if (conn == NULL)
1748 return -1;
1749 return conn->read_alerts;
1750 }
1751
1752
tls_connection_get_write_alerts(void * ssl_ctx,struct tls_connection * conn)1753 int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1754 {
1755 if (conn == NULL)
1756 return -1;
1757 return conn->write_alerts;
1758 }
1759
1760
tls_connection_set_session_ticket_cb(void * tls_ctx,struct tls_connection * conn,tls_session_ticket_cb cb,void * ctx)1761 int tls_connection_set_session_ticket_cb(void *tls_ctx,
1762 struct tls_connection *conn,
1763 tls_session_ticket_cb cb, void *ctx)
1764 {
1765 return -1;
1766 }
1767
1768
tls_get_library_version(char * buf,size_t buf_len)1769 int tls_get_library_version(char *buf, size_t buf_len)
1770 {
1771 return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1772 GNUTLS_VERSION, gnutls_check_version(NULL));
1773 }
1774
1775
tls_connection_set_success_data(struct tls_connection * conn,struct wpabuf * data)1776 void tls_connection_set_success_data(struct tls_connection *conn,
1777 struct wpabuf *data)
1778 {
1779 wpabuf_free(data);
1780 }
1781
1782
tls_connection_set_success_data_resumed(struct tls_connection * conn)1783 void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1784 {
1785 }
1786
1787
1788 const struct wpabuf *
tls_connection_get_success_data(struct tls_connection * conn)1789 tls_connection_get_success_data(struct tls_connection *conn)
1790 {
1791 return NULL;
1792 }
1793
1794
tls_connection_remove_session(struct tls_connection * conn)1795 void tls_connection_remove_session(struct tls_connection *conn)
1796 {
1797 }
1798