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