blob: 7ee3fa3a00a0a786e556c75c95d8030890ed0915 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * SSL/TLS interface functions for GnuTLS
Roshan Pius3a1667e2018-07-03 15:17:14 -07003 * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
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 */
Dmitry Shmidtff787d52015-01-12 13:01:47 -080015#if GNUTLS_VERSION_NUMBER >= 0x030103
16#include <gnutls/ocsp.h>
17#endif /* 3.1.3 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070019#include "common.h"
Dmitry Shmidtff787d52015-01-12 13:01:47 -080020#include "crypto/crypto.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "tls.h"
22
23
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024static int tls_gnutls_ref_count = 0;
25
26struct 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;
Dmitry Shmidtff787d52015-01-12 13:01:47 -080035
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;
Dmitry Shmidtd97138d2015-12-28 13:27:49 -080040
41 char *ocsp_stapling_response;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042};
43
44struct tls_connection {
Dmitry Shmidtff787d52015-01-12 13:01:47 -080045 struct tls_global *global;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080046 gnutls_session_t session;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070047 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;
Dmitry Shmidtff787d52015-01-12 13:01:47 -080053 unsigned int disable_time_checks:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070054
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;
Dmitry Shmidtff787d52015-01-12 13:01:47 -080061
62 char *suffix_match;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -080063 char *domain_match;
Dmitry Shmidtff787d52015-01-12 13:01:47 -080064 unsigned int flags;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070065};
66
67
Dmitry Shmidtff787d52015-01-12 13:01:47 -080068static int tls_connection_verify_peer(gnutls_session_t session);
69
70
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071static 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097void * tls_init(const struct tls_config *conf)
98{
99 struct tls_global *global;
100
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800101 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 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700106
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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700117 gnutls_global_set_log_function(tls_log_func);
118 if (wpa_debug_show_keys)
119 gnutls_global_set_log_level(11);
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800120
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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700127 return global;
128}
129
130
131void 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);
Dmitry Shmidtd97138d2015-12-28 13:27:49 -0800138 os_free(global->ocsp_stapling_response);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700139 os_free(global);
140 }
141
142 tls_gnutls_ref_count--;
143 if (tls_gnutls_ref_count == 0)
144 gnutls_global_deinit();
145}
146
147
148int tls_get_errors(void *ssl_ctx)
149{
150 return 0;
151}
152
153
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800154static ssize_t tls_pull_func(gnutls_transport_ptr_t ptr, void *buf,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700155 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
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800183static ssize_t tls_push_func(gnutls_transport_ptr_t ptr, const void *buf,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700184 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
198static int tls_gnutls_init_session(struct tls_global *global,
199 struct tls_connection *conn)
200{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800201 const char *err;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700202 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
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800216 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 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700223
224 gnutls_transport_set_pull_function(conn->session, tls_pull_func);
225 gnutls_transport_set_push_function(conn->session, tls_push_func);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800226 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr_t) conn);
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800227 gnutls_session_set_ptr(conn->session, conn);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700228
229 return 0;
230
231fail:
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
239struct 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;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800248 conn->global = global;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700249
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
276void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
277{
278 if (conn == NULL)
279 return;
280
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700281 gnutls_certificate_free_credentials(conn->xcred);
282 gnutls_deinit(conn->session);
283 os_free(conn->pre_shared_secret);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284 wpabuf_free(conn->push_buf);
285 wpabuf_free(conn->pull_buf);
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800286 os_free(conn->suffix_match);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800287 os_free(conn->domain_match);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700288 os_free(conn);
289}
290
291
292int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
293{
294 return conn ? conn->established : 0;
295}
296
297
298int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
299{
300 struct tls_global *global = ssl_ctx;
301 int ret;
302
303 if (conn == NULL)
304 return -1;
305
306 /* Shutdown previous TLS connection without notifying the peer
307 * because the connection was already terminated in practice
308 * and "close notify" shutdown alert would confuse AS. */
309 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
310 wpabuf_free(conn->push_buf);
311 conn->push_buf = NULL;
312 conn->established = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700313
314 gnutls_deinit(conn->session);
315 if (tls_gnutls_init_session(global, conn)) {
316 wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session "
317 "for session resumption use");
318 return -1;
319 }
320
321 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
322 conn->params_set ? conn->xcred :
323 global->xcred);
324 if (ret < 0) {
325 wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials "
326 "for session resumption: %s", gnutls_strerror(ret));
327 return -1;
328 }
329
330 if (global->session_data) {
331 ret = gnutls_session_set_data(conn->session,
332 global->session_data,
333 global->session_data_size);
334 if (ret < 0) {
335 wpa_printf(MSG_INFO, "GnuTLS: Failed to set session "
336 "data: %s", gnutls_strerror(ret));
337 return -1;
338 }
339 }
340
341 return 0;
342}
343
344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700345int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
346 const struct tls_connection_params *params)
347{
348 int ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700349 const char *err;
350 char prio_buf[100];
351 const char *prio = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700352
353 if (conn == NULL || params == NULL)
354 return -1;
355
Dmitry Shmidtd97138d2015-12-28 13:27:49 -0800356 if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
357 wpa_printf(MSG_INFO,
358 "GnuTLS: ocsp=3 not supported");
359 return -1;
360 }
361
Dmitry Shmidt1b467752015-12-14 12:45:46 -0800362 if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
363 wpa_printf(MSG_INFO,
364 "GnuTLS: tls_ext_cert_check=1 not supported");
365 return -1;
366 }
367
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700368 if (params->subject_match) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800369 wpa_printf(MSG_INFO, "GnuTLS: subject_match not supported");
370 return -1;
371 }
372
373 if (params->altsubject_match) {
374 wpa_printf(MSG_INFO, "GnuTLS: altsubject_match not supported");
375 return -1;
376 }
377
378 os_free(conn->suffix_match);
379 conn->suffix_match = NULL;
380 if (params->suffix_match) {
381 conn->suffix_match = os_strdup(params->suffix_match);
382 if (conn->suffix_match == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383 return -1;
384 }
385
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800386#if GNUTLS_VERSION_NUMBER >= 0x030300
387 os_free(conn->domain_match);
388 conn->domain_match = NULL;
389 if (params->domain_match) {
390 conn->domain_match = os_strdup(params->domain_match);
391 if (conn->domain_match == NULL)
392 return -1;
393 }
394#else /* < 3.3.0 */
395 if (params->domain_match) {
396 wpa_printf(MSG_INFO, "GnuTLS: domain_match not supported");
397 return -1;
398 }
399#endif /* >= 3.3.0 */
400
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800401 conn->flags = params->flags;
402
Roshan Pius3a1667e2018-07-03 15:17:14 -0700403 if (params->flags & (TLS_CONN_DISABLE_TLSv1_0 |
404 TLS_CONN_DISABLE_TLSv1_1 |
405 TLS_CONN_DISABLE_TLSv1_2)) {
406 os_snprintf(prio_buf, sizeof(prio_buf),
407 "NORMAL:-VERS-SSL3.0%s%s%s",
408 params->flags & TLS_CONN_DISABLE_TLSv1_0 ?
409 ":-VERS-TLS1.0" : "",
410 params->flags & TLS_CONN_DISABLE_TLSv1_1 ?
411 ":-VERS-TLS1.1" : "",
412 params->flags & TLS_CONN_DISABLE_TLSv1_2 ?
413 ":-VERS-TLS1.2" : "");
414 prio = prio_buf;
415 }
416
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800417 if (params->openssl_ciphers) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700418 if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) {
419 prio = "SUITEB128";
420 } else if (os_strcmp(params->openssl_ciphers,
421 "SUITEB192") == 0) {
422 prio = "SUITEB192";
423 } else if ((params->flags & TLS_CONN_SUITEB) &&
424 os_strcmp(params->openssl_ciphers,
425 "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
426 prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
427 } else if (os_strcmp(params->openssl_ciphers,
428 "ECDHE-RSA-AES256-GCM-SHA384") == 0) {
429 prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
430 } else if (os_strcmp(params->openssl_ciphers,
431 "DHE-RSA-AES256-GCM-SHA384") == 0) {
432 prio = "NONE:+VERS-TLS1.2:+AEAD:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
433 } else if (os_strcmp(params->openssl_ciphers,
434 "ECDHE-ECDSA-AES256-GCM-SHA384") == 0) {
435 prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL";
436 } else {
437 wpa_printf(MSG_INFO,
438 "GnuTLS: openssl_ciphers not supported");
439 return -1;
440 }
441 } else if (params->flags & TLS_CONN_SUITEB) {
442 prio = "NONE:+VERS-TLS1.2:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+DHE-RSA:+AES-256-GCM:+SIGN-RSA-SHA384:+CURVE-SECP384R1:+COMP-NULL:%PROFILE_HIGH";
443 }
444
445 if (prio) {
446 wpa_printf(MSG_DEBUG, "GnuTLS: Set priority string: %s", prio);
447 ret = gnutls_priority_set_direct(conn->session, prio, &err);
448 if (ret < 0) {
449 wpa_printf(MSG_ERROR,
450 "GnuTLS: Priority string failure at '%s'",
451 err);
452 return -1;
453 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700454 }
455
Dmitry Shmidt29333592017-01-09 12:27:11 -0800456 /* TODO: gnutls_certificate_set_verify_flags(xcred, flags);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457 * to force peer validation(?) */
458
459 if (params->ca_cert) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800460 wpa_printf(MSG_DEBUG, "GnuTLS: Try to parse %s in DER format",
461 params->ca_cert);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700462 ret = gnutls_certificate_set_x509_trust_file(
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800463 conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700464 if (ret < 0) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800465 wpa_printf(MSG_DEBUG,
466 "GnuTLS: Failed to read CA cert '%s' in DER format (%s) - try in PEM format",
467 params->ca_cert,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700468 gnutls_strerror(ret));
469 ret = gnutls_certificate_set_x509_trust_file(
470 conn->xcred, params->ca_cert,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800471 GNUTLS_X509_FMT_PEM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700472 if (ret < 0) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800473 wpa_printf(MSG_DEBUG,
474 "Failed to read CA cert '%s' in PEM format: %s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700475 params->ca_cert,
476 gnutls_strerror(ret));
477 return -1;
478 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700479 wpa_printf(MSG_DEBUG,
480 "GnuTLS: Successfully read CA cert '%s' in PEM format",
481 params->ca_cert);
482 } else {
483 wpa_printf(MSG_DEBUG,
484 "GnuTLS: Successfully read CA cert '%s' in DER format",
485 params->ca_cert);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700486 }
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800487 } else if (params->ca_cert_blob) {
488 gnutls_datum_t ca;
489
490 ca.data = (unsigned char *) params->ca_cert_blob;
491 ca.size = params->ca_cert_blob_len;
492
493 ret = gnutls_certificate_set_x509_trust_mem(
494 conn->xcred, &ca, GNUTLS_X509_FMT_DER);
495 if (ret < 0) {
496 wpa_printf(MSG_DEBUG,
497 "Failed to parse CA cert in DER format: %s",
498 gnutls_strerror(ret));
499 ret = gnutls_certificate_set_x509_trust_mem(
500 conn->xcred, &ca, GNUTLS_X509_FMT_PEM);
501 if (ret < 0) {
502 wpa_printf(MSG_DEBUG,
503 "Failed to parse CA cert in PEM format: %s",
504 gnutls_strerror(ret));
505 return -1;
506 }
507 }
508 } else if (params->ca_path) {
509 wpa_printf(MSG_INFO, "GnuTLS: ca_path not supported");
510 return -1;
511 }
512
513 conn->disable_time_checks = 0;
514 if (params->ca_cert || params->ca_cert_blob) {
515 conn->verify_peer = 1;
516 gnutls_certificate_set_verify_function(
517 conn->xcred, tls_connection_verify_peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700518
519 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
520 gnutls_certificate_set_verify_flags(
521 conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
522 }
523
524 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800525 conn->disable_time_checks = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700526 gnutls_certificate_set_verify_flags(
527 conn->xcred,
528 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
529 }
530 }
531
532 if (params->client_cert && params->private_key) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700533 wpa_printf(MSG_DEBUG,
534 "GnuTLS: Try to parse client cert '%s' and key '%s' in DER format",
535 params->client_cert, params->private_key);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800536#if GNUTLS_VERSION_NUMBER >= 0x03010b
537 ret = gnutls_certificate_set_x509_key_file2(
538 conn->xcred, params->client_cert, params->private_key,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800539 GNUTLS_X509_FMT_DER, params->private_key_passwd, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800540#else
541 /* private_key_passwd not (easily) supported here */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700542 ret = gnutls_certificate_set_x509_key_file(
543 conn->xcred, params->client_cert, params->private_key,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800544 GNUTLS_X509_FMT_DER);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800545#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700546 if (ret < 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700547 wpa_printf(MSG_DEBUG,
548 "GnuTLS: Failed to read client cert/key in DER format (%s) - try in PEM format",
549 gnutls_strerror(ret));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800550#if GNUTLS_VERSION_NUMBER >= 0x03010b
551 ret = gnutls_certificate_set_x509_key_file2(
552 conn->xcred, params->client_cert,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800553 params->private_key, GNUTLS_X509_FMT_PEM,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800554 params->private_key_passwd, 0);
555#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700556 ret = gnutls_certificate_set_x509_key_file(
557 conn->xcred, params->client_cert,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800558 params->private_key, GNUTLS_X509_FMT_PEM);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800559#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700560 if (ret < 0) {
561 wpa_printf(MSG_DEBUG, "Failed to read client "
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800562 "cert/key in PEM format: %s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700563 gnutls_strerror(ret));
564 return ret;
565 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700566 wpa_printf(MSG_DEBUG,
567 "GnuTLS: Successfully read client cert/key in PEM format");
568 } else {
569 wpa_printf(MSG_DEBUG,
570 "GnuTLS: Successfully read client cert/key in DER format");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700571 }
572 } else if (params->private_key) {
573 int pkcs12_ok = 0;
574#ifdef PKCS12_FUNCS
575 /* Try to load in PKCS#12 format */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700576 wpa_printf(MSG_DEBUG,
577 "GnuTLS: Try to parse client cert/key '%s'in PKCS#12 DER format",
578 params->private_key);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700579 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
580 conn->xcred, params->private_key, GNUTLS_X509_FMT_DER,
581 params->private_key_passwd);
582 if (ret != 0) {
583 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
584 "PKCS#12 format: %s", gnutls_strerror(ret));
585 return -1;
586 } else
587 pkcs12_ok = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700588#endif /* PKCS12_FUNCS */
589
590 if (!pkcs12_ok) {
591 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
592 "included");
593 return -1;
594 }
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800595 } else if (params->client_cert_blob && params->private_key_blob) {
596 gnutls_datum_t cert, key;
597
598 cert.data = (unsigned char *) params->client_cert_blob;
599 cert.size = params->client_cert_blob_len;
600 key.data = (unsigned char *) params->private_key_blob;
601 key.size = params->private_key_blob_len;
602
603#if GNUTLS_VERSION_NUMBER >= 0x03010b
604 ret = gnutls_certificate_set_x509_key_mem2(
605 conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER,
606 params->private_key_passwd, 0);
607#else
608 /* private_key_passwd not (easily) supported here */
609 ret = gnutls_certificate_set_x509_key_mem(
610 conn->xcred, &cert, &key, GNUTLS_X509_FMT_DER);
611#endif
612 if (ret < 0) {
613 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
614 "in DER format: %s", gnutls_strerror(ret));
615#if GNUTLS_VERSION_NUMBER >= 0x03010b
616 ret = gnutls_certificate_set_x509_key_mem2(
617 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM,
618 params->private_key_passwd, 0);
619#else
620 /* private_key_passwd not (easily) supported here */
621 ret = gnutls_certificate_set_x509_key_mem(
622 conn->xcred, &cert, &key, GNUTLS_X509_FMT_PEM);
623#endif
624 if (ret < 0) {
625 wpa_printf(MSG_DEBUG, "Failed to read client "
626 "cert/key in PEM format: %s",
627 gnutls_strerror(ret));
628 return ret;
629 }
630 }
631 } else if (params->private_key_blob) {
632#ifdef PKCS12_FUNCS
633 gnutls_datum_t key;
634
635 key.data = (unsigned char *) params->private_key_blob;
636 key.size = params->private_key_blob_len;
637
638 /* Try to load in PKCS#12 format */
639 ret = gnutls_certificate_set_x509_simple_pkcs12_mem(
640 conn->xcred, &key, GNUTLS_X509_FMT_DER,
641 params->private_key_passwd);
642 if (ret != 0) {
643 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
644 "PKCS#12 format: %s", gnutls_strerror(ret));
645 return -1;
646 }
647#else /* PKCS12_FUNCS */
648 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not included");
649 return -1;
650#endif /* PKCS12_FUNCS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700651 }
652
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800653#if GNUTLS_VERSION_NUMBER >= 0x030103
654 if (params->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)) {
655 ret = gnutls_ocsp_status_request_enable_client(conn->session,
656 NULL, 0, NULL);
657 if (ret != GNUTLS_E_SUCCESS) {
658 wpa_printf(MSG_INFO,
659 "GnuTLS: Failed to enable OCSP client");
660 return -1;
661 }
662 }
663#else /* 3.1.3 */
664 if (params->flags & TLS_CONN_REQUIRE_OCSP) {
665 wpa_printf(MSG_INFO,
666 "GnuTLS: OCSP not supported by this version of GnuTLS");
667 return -1;
668 }
669#endif /* 3.1.3 */
670
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700671 conn->params_set = 1;
672
673 ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE,
674 conn->xcred);
675 if (ret < 0) {
676 wpa_printf(MSG_INFO, "Failed to configure credentials: %s",
677 gnutls_strerror(ret));
678 }
679
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700680 return ret;
681}
682
683
Dmitry Shmidtd97138d2015-12-28 13:27:49 -0800684#if GNUTLS_VERSION_NUMBER >= 0x030103
685static int server_ocsp_status_req(gnutls_session_t session, void *ptr,
686 gnutls_datum_t *resp)
687{
688 struct tls_global *global = ptr;
689 char *cached;
690 size_t len;
691
692 if (!global->ocsp_stapling_response) {
693 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP status callback - no response configured");
694 return GNUTLS_E_NO_CERTIFICATE_STATUS;
695 }
696
697 cached = os_readfile(global->ocsp_stapling_response, &len);
698 if (!cached) {
699 wpa_printf(MSG_DEBUG,
700 "GnuTLS: OCSP status callback - could not read response file (%s)",
701 global->ocsp_stapling_response);
702 return GNUTLS_E_NO_CERTIFICATE_STATUS;
703 }
704
705 wpa_printf(MSG_DEBUG,
706 "GnuTLS: OCSP status callback - send cached response");
707 resp->data = gnutls_malloc(len);
708 if (!resp->data) {
709 os_free(resp);
710 return GNUTLS_E_MEMORY_ERROR;
711 }
712
713 os_memcpy(resp->data, cached, len);
714 resp->size = len;
715 os_free(cached);
716
717 return GNUTLS_E_SUCCESS;
718}
719#endif /* 3.1.3 */
720
721
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722int tls_global_set_params(void *tls_ctx,
723 const struct tls_connection_params *params)
724{
725 struct tls_global *global = tls_ctx;
726 int ret;
727
728 /* Currently, global parameters are only set when running in server
729 * mode. */
730 global->server = 1;
731
732 if (global->params_set) {
733 gnutls_certificate_free_credentials(global->xcred);
734 global->params_set = 0;
735 }
736
737 ret = gnutls_certificate_allocate_credentials(&global->xcred);
738 if (ret) {
739 wpa_printf(MSG_DEBUG, "Failed to allocate global credentials "
740 "%s", gnutls_strerror(ret));
741 return -1;
742 }
743
744 if (params->ca_cert) {
745 ret = gnutls_certificate_set_x509_trust_file(
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800746 global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700747 if (ret < 0) {
748 wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' "
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800749 "in DER format: %s", params->ca_cert,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750 gnutls_strerror(ret));
751 ret = gnutls_certificate_set_x509_trust_file(
752 global->xcred, params->ca_cert,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800753 GNUTLS_X509_FMT_PEM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700754 if (ret < 0) {
755 wpa_printf(MSG_DEBUG, "Failed to read CA cert "
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800756 "'%s' in PEM format: %s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757 params->ca_cert,
758 gnutls_strerror(ret));
759 goto fail;
760 }
761 }
762
763 if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) {
764 gnutls_certificate_set_verify_flags(
765 global->xcred,
766 GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5);
767 }
768
769 if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
770 gnutls_certificate_set_verify_flags(
771 global->xcred,
772 GNUTLS_VERIFY_DISABLE_TIME_CHECKS);
773 }
774 }
775
776 if (params->client_cert && params->private_key) {
777 /* TODO: private_key_passwd? */
778 ret = gnutls_certificate_set_x509_key_file(
779 global->xcred, params->client_cert,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800780 params->private_key, GNUTLS_X509_FMT_DER);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781 if (ret < 0) {
782 wpa_printf(MSG_DEBUG, "Failed to read client cert/key "
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800783 "in DER format: %s", gnutls_strerror(ret));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 ret = gnutls_certificate_set_x509_key_file(
785 global->xcred, params->client_cert,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800786 params->private_key, GNUTLS_X509_FMT_PEM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700787 if (ret < 0) {
788 wpa_printf(MSG_DEBUG, "Failed to read client "
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800789 "cert/key in PEM format: %s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700790 gnutls_strerror(ret));
791 goto fail;
792 }
793 }
794 } else if (params->private_key) {
795 int pkcs12_ok = 0;
796#ifdef PKCS12_FUNCS
797 /* Try to load in PKCS#12 format */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798 ret = gnutls_certificate_set_x509_simple_pkcs12_file(
799 global->xcred, params->private_key,
800 GNUTLS_X509_FMT_DER, params->private_key_passwd);
801 if (ret != 0) {
802 wpa_printf(MSG_DEBUG, "Failed to load private_key in "
803 "PKCS#12 format: %s", gnutls_strerror(ret));
804 goto fail;
805 } else
806 pkcs12_ok = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700807#endif /* PKCS12_FUNCS */
808
809 if (!pkcs12_ok) {
810 wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not "
811 "included");
812 goto fail;
813 }
814 }
815
Dmitry Shmidtd97138d2015-12-28 13:27:49 -0800816#if GNUTLS_VERSION_NUMBER >= 0x030103
817 os_free(global->ocsp_stapling_response);
818 if (params->ocsp_stapling_response)
819 global->ocsp_stapling_response =
820 os_strdup(params->ocsp_stapling_response);
821 else
822 global->ocsp_stapling_response = NULL;
823 gnutls_certificate_set_ocsp_status_request_function(
824 global->xcred, server_ocsp_status_req, global);
825#endif /* 3.1.3 */
826
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700827 global->params_set = 1;
828
829 return 0;
830
831fail:
832 gnutls_certificate_free_credentials(global->xcred);
833 return -1;
834}
835
836
837int tls_global_set_verify(void *ssl_ctx, int check_crl)
838{
839 /* TODO */
840 return 0;
841}
842
843
844int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800845 int verify_peer, unsigned int flags,
846 const u8 *session_ctx, size_t session_ctx_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700847{
848 if (conn == NULL || conn->session == NULL)
849 return -1;
850
851 conn->verify_peer = verify_peer;
852 gnutls_certificate_server_set_request(conn->session,
853 verify_peer ? GNUTLS_CERT_REQUIRE
854 : GNUTLS_CERT_REQUEST);
855
856 return 0;
857}
858
859
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800860int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
861 struct tls_random *keys)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700862{
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800863#if GNUTLS_VERSION_NUMBER >= 0x030012
864 gnutls_datum_t client, server;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700865
866 if (conn == NULL || conn->session == NULL || keys == NULL)
867 return -1;
868
869 os_memset(keys, 0, sizeof(*keys));
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800870 gnutls_session_get_random(conn->session, &client, &server);
871 keys->client_random = client.data;
872 keys->server_random = server.data;
873 keys->client_random_len = client.size;
874 keys->server_random_len = client.size;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700875
876 return 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800877#else /* 3.0.18 */
878 return -1;
879#endif /* 3.0.18 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880}
881
882
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700883int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
884 const char *label, u8 *out, size_t out_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885{
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700886 if (conn == NULL || conn->session == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700887 return -1;
888
889 return gnutls_prf(conn->session, os_strlen(label), label,
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700890 0 /* client_random first */, 0, NULL, out_len,
891 (char *) out);
892}
893
894
895int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
896 u8 *out, size_t out_len)
897{
898 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700899}
900
901
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800902static void gnutls_tls_fail_event(struct tls_connection *conn,
903 const gnutls_datum_t *cert, int depth,
904 const char *subject, const char *err_str,
905 enum tls_fail_reason reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700906{
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800907 union tls_event_data ev;
908 struct tls_global *global = conn->global;
909 struct wpabuf *cert_buf = NULL;
910
911 if (global->event_cb == NULL)
912 return;
913
914 os_memset(&ev, 0, sizeof(ev));
915 ev.cert_fail.depth = depth;
916 ev.cert_fail.subject = subject ? subject : "";
917 ev.cert_fail.reason = reason;
918 ev.cert_fail.reason_txt = err_str;
919 if (cert) {
920 cert_buf = wpabuf_alloc_copy(cert->data, cert->size);
921 ev.cert_fail.cert = cert_buf;
922 }
923 global->event_cb(global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
924 wpabuf_free(cert_buf);
925}
926
927
928#if GNUTLS_VERSION_NUMBER < 0x030300
929static int server_eku_purpose(gnutls_x509_crt_t cert)
930{
931 unsigned int i;
932
933 for (i = 0; ; i++) {
934 char oid[128];
935 size_t oid_size = sizeof(oid);
936 int res;
937
938 res = gnutls_x509_crt_get_key_purpose_oid(cert, i, oid,
939 &oid_size, NULL);
940 if (res == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
941 if (i == 0) {
942 /* No EKU - assume any use allowed */
943 return 1;
944 }
945 break;
946 }
947
948 if (res < 0) {
949 wpa_printf(MSG_INFO, "GnuTLS: Failed to get EKU");
950 return 0;
951 }
952
953 wpa_printf(MSG_DEBUG, "GnuTLS: Certificate purpose: %s", oid);
954 if (os_strcmp(oid, GNUTLS_KP_TLS_WWW_SERVER) == 0 ||
955 os_strcmp(oid, GNUTLS_KP_ANY) == 0)
956 return 1;
957 }
958
959 return 0;
960}
961#endif /* < 3.3.0 */
962
963
964static int check_ocsp(struct tls_connection *conn, gnutls_session_t session,
965 gnutls_alert_description_t *err)
966{
967#if GNUTLS_VERSION_NUMBER >= 0x030103
968 gnutls_datum_t response, buf;
969 gnutls_ocsp_resp_t resp;
970 unsigned int cert_status;
971 int res;
972
973 if (!(conn->flags & (TLS_CONN_REQUEST_OCSP | TLS_CONN_REQUIRE_OCSP)))
974 return 0;
975
976 if (!gnutls_ocsp_status_request_is_checked(session, 0)) {
977 if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
978 wpa_printf(MSG_INFO,
979 "GnuTLS: No valid OCSP response received");
980 goto ocsp_error;
981 }
982
983 wpa_printf(MSG_DEBUG,
984 "GnuTLS: Valid OCSP response was not received - continue since OCSP was not required");
985 return 0;
986 }
987
988 /*
989 * GnuTLS has already verified the OCSP response in
990 * check_ocsp_response() and rejected handshake if the certificate was
991 * found to be revoked. However, if the response indicates that the
992 * status is unknown, handshake continues and reaches here. We need to
993 * re-import the OCSP response to check for unknown certificate status,
994 * but we do not need to repeat gnutls_ocsp_resp_check_crt() and
995 * gnutls_ocsp_resp_verify_direct() calls.
996 */
997
998 res = gnutls_ocsp_status_request_get(session, &response);
999 if (res != GNUTLS_E_SUCCESS) {
1000 wpa_printf(MSG_INFO,
1001 "GnuTLS: OCSP response was received, but it was not valid");
1002 goto ocsp_error;
1003 }
1004
1005 if (gnutls_ocsp_resp_init(&resp) != GNUTLS_E_SUCCESS)
1006 goto ocsp_error;
1007
1008 res = gnutls_ocsp_resp_import(resp, &response);
1009 if (res != GNUTLS_E_SUCCESS) {
1010 wpa_printf(MSG_INFO,
1011 "GnuTLS: Could not parse received OCSP response: %s",
1012 gnutls_strerror(res));
1013 gnutls_ocsp_resp_deinit(resp);
1014 goto ocsp_error;
1015 }
1016
1017 res = gnutls_ocsp_resp_print(resp, GNUTLS_OCSP_PRINT_FULL, &buf);
1018 if (res == GNUTLS_E_SUCCESS) {
1019 wpa_printf(MSG_DEBUG, "GnuTLS: %s", buf.data);
1020 gnutls_free(buf.data);
1021 }
1022
1023 res = gnutls_ocsp_resp_get_single(resp, 0, NULL, NULL, NULL,
1024 NULL, &cert_status, NULL,
1025 NULL, NULL, NULL);
1026 gnutls_ocsp_resp_deinit(resp);
1027 if (res != GNUTLS_E_SUCCESS) {
1028 wpa_printf(MSG_INFO,
1029 "GnuTLS: Failed to extract OCSP information: %s",
1030 gnutls_strerror(res));
1031 goto ocsp_error;
1032 }
1033
1034 if (cert_status == GNUTLS_OCSP_CERT_GOOD) {
1035 wpa_printf(MSG_DEBUG, "GnuTLS: OCSP cert status: good");
1036 } else if (cert_status == GNUTLS_OCSP_CERT_REVOKED) {
1037 wpa_printf(MSG_DEBUG,
1038 "GnuTLS: OCSP cert status: revoked");
1039 goto ocsp_error;
1040 } else {
1041 wpa_printf(MSG_DEBUG,
1042 "GnuTLS: OCSP cert status: unknown");
1043 if (conn->flags & TLS_CONN_REQUIRE_OCSP)
1044 goto ocsp_error;
1045 wpa_printf(MSG_DEBUG,
1046 "GnuTLS: OCSP was not required, so allow connection to continue");
1047 }
1048
1049 return 0;
1050
1051ocsp_error:
1052 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1053 "bad certificate status response",
1054 TLS_FAIL_REVOKED);
1055 *err = GNUTLS_A_CERTIFICATE_REVOKED;
1056 return -1;
1057#else /* GnuTLS 3.1.3 or newer */
1058 return 0;
1059#endif /* GnuTLS 3.1.3 or newer */
1060}
1061
1062
1063static int tls_connection_verify_peer(gnutls_session_t session)
1064{
1065 struct tls_connection *conn;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001066 unsigned int status, num_certs, i;
1067 struct os_time now;
1068 const gnutls_datum_t *certs;
1069 gnutls_x509_crt_t cert;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001070 gnutls_alert_description_t err;
1071 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001072
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001073 conn = gnutls_session_get_ptr(session);
1074 if (!conn->verify_peer) {
1075 wpa_printf(MSG_DEBUG,
1076 "GnuTLS: No peer certificate verification enabled");
1077 return 0;
1078 }
1079
1080 wpa_printf(MSG_DEBUG, "GnuTSL: Verifying peer certificate");
1081
1082#if GNUTLS_VERSION_NUMBER >= 0x030300
1083 {
1084 gnutls_typed_vdata_st data[1];
1085 unsigned int elements = 0;
1086
1087 os_memset(data, 0, sizeof(data));
1088 if (!conn->global->server) {
1089 data[elements].type = GNUTLS_DT_KEY_PURPOSE_OID;
1090 data[elements].data = (void *) GNUTLS_KP_TLS_WWW_SERVER;
1091 elements++;
1092 }
1093 res = gnutls_certificate_verify_peers(session, data, 1,
1094 &status);
1095 }
1096#else /* < 3.3.0 */
1097 res = gnutls_certificate_verify_peers2(session, &status);
1098#endif
1099 if (res < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001100 wpa_printf(MSG_INFO, "TLS: Failed to verify peer "
1101 "certificate chain");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001102 err = GNUTLS_A_INTERNAL_ERROR;
1103 goto out;
1104 }
1105
1106#if GNUTLS_VERSION_NUMBER >= 0x030104
1107 {
1108 gnutls_datum_t info;
1109 int ret, type;
1110
1111 type = gnutls_certificate_type_get(session);
1112 ret = gnutls_certificate_verification_status_print(status, type,
1113 &info, 0);
1114 if (ret < 0) {
1115 wpa_printf(MSG_DEBUG,
1116 "GnuTLS: Failed to print verification status");
1117 err = GNUTLS_A_INTERNAL_ERROR;
1118 goto out;
1119 }
1120 wpa_printf(MSG_DEBUG, "GnuTLS: %s", info.data);
1121 gnutls_free(info.data);
1122 }
1123#endif /* GnuTLS 3.1.4 or newer */
1124
1125 certs = gnutls_certificate_get_peers(session, &num_certs);
1126 if (certs == NULL || num_certs == 0) {
1127 wpa_printf(MSG_INFO, "TLS: No peer certificate chain received");
1128 err = GNUTLS_A_UNKNOWN_CA;
1129 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001130 }
1131
1132 if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) {
1133 wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted");
1134 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1135 wpa_printf(MSG_INFO, "TLS: Certificate uses insecure "
1136 "algorithm");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001137 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1138 "certificate uses insecure algorithm",
1139 TLS_FAIL_BAD_CERTIFICATE);
1140 err = GNUTLS_A_INSUFFICIENT_SECURITY;
1141 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142 }
1143 if (status & GNUTLS_CERT_NOT_ACTIVATED) {
1144 wpa_printf(MSG_INFO, "TLS: Certificate not yet "
1145 "activated");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001146 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1147 "certificate not yet valid",
1148 TLS_FAIL_NOT_YET_VALID);
1149 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1150 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001151 }
1152 if (status & GNUTLS_CERT_EXPIRED) {
1153 wpa_printf(MSG_INFO, "TLS: Certificate expired");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001154 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1155 "certificate has expired",
1156 TLS_FAIL_EXPIRED);
1157 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1158 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001159 }
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001160 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1161 "untrusted certificate",
1162 TLS_FAIL_UNTRUSTED);
1163 err = GNUTLS_A_INTERNAL_ERROR;
1164 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001165 }
1166
1167 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1168 wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a "
1169 "known issuer");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001170 gnutls_tls_fail_event(conn, NULL, 0, NULL, "signed not found",
1171 TLS_FAIL_UNTRUSTED);
1172 err = GNUTLS_A_UNKNOWN_CA;
1173 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174 }
1175
1176 if (status & GNUTLS_CERT_REVOKED) {
1177 wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001178 gnutls_tls_fail_event(conn, NULL, 0, NULL,
1179 "certificate revoked",
1180 TLS_FAIL_REVOKED);
1181 err = GNUTLS_A_CERTIFICATE_REVOKED;
1182 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001183 }
1184
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001185 if (status != 0) {
1186 wpa_printf(MSG_INFO, "TLS: Unknown verification status: %d",
1187 status);
1188 err = GNUTLS_A_INTERNAL_ERROR;
1189 goto out;
1190 }
1191
1192 if (check_ocsp(conn, session, &err))
1193 goto out;
1194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001195 os_get_time(&now);
1196
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197 for (i = 0; i < num_certs; i++) {
1198 char *buf;
1199 size_t len;
1200 if (gnutls_x509_crt_init(&cert) < 0) {
1201 wpa_printf(MSG_INFO, "TLS: Certificate initialization "
1202 "failed");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001203 err = GNUTLS_A_BAD_CERTIFICATE;
1204 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001205 }
1206
1207 if (gnutls_x509_crt_import(cert, &certs[i],
1208 GNUTLS_X509_FMT_DER) < 0) {
1209 wpa_printf(MSG_INFO, "TLS: Could not parse peer "
1210 "certificate %d/%d", i + 1, num_certs);
1211 gnutls_x509_crt_deinit(cert);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001212 err = GNUTLS_A_BAD_CERTIFICATE;
1213 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001214 }
1215
1216 gnutls_x509_crt_get_dn(cert, NULL, &len);
1217 len++;
1218 buf = os_malloc(len + 1);
1219 if (buf) {
1220 buf[0] = buf[len] = '\0';
1221 gnutls_x509_crt_get_dn(cert, buf, &len);
1222 }
1223 wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s",
1224 i + 1, num_certs, buf);
1225
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001226 if (conn->global->event_cb) {
1227 struct wpabuf *cert_buf = NULL;
1228 union tls_event_data ev;
1229#ifdef CONFIG_SHA256
1230 u8 hash[32];
1231 const u8 *_addr[1];
1232 size_t _len[1];
1233#endif /* CONFIG_SHA256 */
1234
1235 os_memset(&ev, 0, sizeof(ev));
1236 if (conn->global->cert_in_cb) {
1237 cert_buf = wpabuf_alloc_copy(certs[i].data,
1238 certs[i].size);
1239 ev.peer_cert.cert = cert_buf;
1240 }
1241#ifdef CONFIG_SHA256
1242 _addr[0] = certs[i].data;
1243 _len[0] = certs[i].size;
1244 if (sha256_vector(1, _addr, _len, hash) == 0) {
1245 ev.peer_cert.hash = hash;
1246 ev.peer_cert.hash_len = sizeof(hash);
1247 }
1248#endif /* CONFIG_SHA256 */
1249 ev.peer_cert.depth = i;
1250 ev.peer_cert.subject = buf;
1251 conn->global->event_cb(conn->global->cb_ctx,
1252 TLS_PEER_CERTIFICATE, &ev);
1253 wpabuf_free(cert_buf);
1254 }
1255
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001256 if (i == 0) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001257 if (conn->suffix_match &&
1258 !gnutls_x509_crt_check_hostname(
1259 cert, conn->suffix_match)) {
1260 wpa_printf(MSG_WARNING,
1261 "TLS: Domain suffix match '%s' not found",
1262 conn->suffix_match);
1263 gnutls_tls_fail_event(
1264 conn, &certs[i], i, buf,
1265 "Domain suffix mismatch",
1266 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
1267 err = GNUTLS_A_BAD_CERTIFICATE;
1268 gnutls_x509_crt_deinit(cert);
1269 os_free(buf);
1270 goto out;
1271 }
1272
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001273#if GNUTLS_VERSION_NUMBER >= 0x030300
1274 if (conn->domain_match &&
1275 !gnutls_x509_crt_check_hostname2(
1276 cert, conn->domain_match,
1277 GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
1278 wpa_printf(MSG_WARNING,
1279 "TLS: Domain match '%s' not found",
1280 conn->domain_match);
1281 gnutls_tls_fail_event(
1282 conn, &certs[i], i, buf,
1283 "Domain mismatch",
1284 TLS_FAIL_DOMAIN_MISMATCH);
1285 err = GNUTLS_A_BAD_CERTIFICATE;
1286 gnutls_x509_crt_deinit(cert);
1287 os_free(buf);
1288 goto out;
1289 }
1290#endif /* >= 3.3.0 */
1291
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001292 /* TODO: validate altsubject_match.
1293 * For now, any such configuration is rejected in
1294 * tls_connection_set_params() */
1295
1296#if GNUTLS_VERSION_NUMBER < 0x030300
1297 /*
1298 * gnutls_certificate_verify_peers() not available, so
1299 * need to check EKU separately.
1300 */
1301 if (!conn->global->server &&
1302 !server_eku_purpose(cert)) {
1303 wpa_printf(MSG_WARNING,
1304 "GnuTLS: No server EKU");
1305 gnutls_tls_fail_event(
1306 conn, &certs[i], i, buf,
1307 "No server EKU",
1308 TLS_FAIL_BAD_CERTIFICATE);
1309 err = GNUTLS_A_BAD_CERTIFICATE;
1310 gnutls_x509_crt_deinit(cert);
1311 os_free(buf);
1312 goto out;
1313 }
1314#endif /* < 3.3.0 */
1315 }
1316
1317 if (!conn->disable_time_checks &&
1318 (gnutls_x509_crt_get_expiration_time(cert) < now.sec ||
1319 gnutls_x509_crt_get_activation_time(cert) > now.sec)) {
1320 wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is "
1321 "not valid at this time",
1322 i + 1, num_certs);
1323 gnutls_tls_fail_event(
1324 conn, &certs[i], i, buf,
1325 "Certificate is not valid at this time",
1326 TLS_FAIL_EXPIRED);
1327 gnutls_x509_crt_deinit(cert);
1328 os_free(buf);
1329 err = GNUTLS_A_CERTIFICATE_EXPIRED;
1330 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331 }
1332
1333 os_free(buf);
1334
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001335 gnutls_x509_crt_deinit(cert);
1336 }
1337
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001338 if (conn->global->event_cb != NULL)
1339 conn->global->event_cb(conn->global->cb_ctx,
1340 TLS_CERT_CHAIN_SUCCESS, NULL);
1341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001342 return 0;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001343
1344out:
1345 conn->failed++;
1346 gnutls_alert_send(session, GNUTLS_AL_FATAL, err);
1347 return GNUTLS_E_CERTIFICATE_ERROR;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001348}
1349
1350
1351static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn)
1352{
1353 int res;
1354 struct wpabuf *ad;
1355 wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data");
1356 ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3);
1357 if (ad == NULL)
1358 return NULL;
1359
1360 res = gnutls_record_recv(conn->session, wpabuf_mhead(ad),
1361 wpabuf_size(ad));
1362 wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res);
1363 if (res < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001364 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001365 "(%s)", __func__, (int) res,
1366 gnutls_strerror(res));
1367 wpabuf_free(ad);
1368 return NULL;
1369 }
1370
1371 wpabuf_put(ad, res);
1372 wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data",
1373 res);
1374 return ad;
1375}
1376
1377
1378struct wpabuf * tls_connection_handshake(void *tls_ctx,
1379 struct tls_connection *conn,
1380 const struct wpabuf *in_data,
1381 struct wpabuf **appl_data)
1382{
1383 struct tls_global *global = tls_ctx;
1384 struct wpabuf *out_data;
1385 int ret;
1386
1387 if (appl_data)
1388 *appl_data = NULL;
1389
1390 if (in_data && wpabuf_len(in_data) > 0) {
1391 if (conn->pull_buf) {
1392 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1393 "pull_buf", __func__,
1394 (unsigned long) wpabuf_len(conn->pull_buf));
1395 wpabuf_free(conn->pull_buf);
1396 }
1397 conn->pull_buf = wpabuf_dup(in_data);
1398 if (conn->pull_buf == NULL)
1399 return NULL;
1400 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1401 }
1402
1403 ret = gnutls_handshake(conn->session);
1404 if (ret < 0) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001405 gnutls_alert_description_t alert;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001406 union tls_event_data ev;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001407
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001408 switch (ret) {
1409 case GNUTLS_E_AGAIN:
1410 if (global->server && conn->established &&
1411 conn->push_buf == NULL) {
1412 /* Need to return something to trigger
1413 * completion of EAP-TLS. */
1414 conn->push_buf = wpabuf_alloc(0);
1415 }
1416 break;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001417 case GNUTLS_E_DH_PRIME_UNACCEPTABLE:
1418 wpa_printf(MSG_DEBUG, "GnuTLS: Unacceptable DH prime");
1419 if (conn->global->event_cb) {
1420 os_memset(&ev, 0, sizeof(ev));
1421 ev.alert.is_local = 1;
1422 ev.alert.type = "fatal";
1423 ev.alert.description = "insufficient security";
1424 conn->global->event_cb(conn->global->cb_ctx,
1425 TLS_ALERT, &ev);
1426 }
1427 /*
1428 * Could send a TLS Alert to the server, but for now,
1429 * simply terminate handshake.
1430 */
1431 conn->failed++;
1432 conn->write_alerts++;
1433 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001434 case GNUTLS_E_FATAL_ALERT_RECEIVED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001435 alert = gnutls_alert_get(conn->session);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001436 wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert",
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001437 __func__, gnutls_alert_get_name(alert));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001438 conn->read_alerts++;
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001439 if (conn->global->event_cb != NULL) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001440 os_memset(&ev, 0, sizeof(ev));
1441 ev.alert.is_local = 0;
1442 ev.alert.type = gnutls_alert_get_name(alert);
1443 ev.alert.description = ev.alert.type;
1444 conn->global->event_cb(conn->global->cb_ctx,
1445 TLS_ALERT, &ev);
1446 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001447 /* continue */
1448 default:
1449 wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed "
1450 "-> %s", __func__, gnutls_strerror(ret));
1451 conn->failed++;
1452 }
1453 } else {
1454 size_t size;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001455
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001456 wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001457
1458#if GNUTLS_VERSION_NUMBER >= 0x03010a
1459 {
1460 char *desc;
1461
1462 desc = gnutls_session_get_desc(conn->session);
1463 if (desc) {
1464 wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc);
1465 gnutls_free(desc);
1466 }
1467 }
1468#endif /* GnuTLS 3.1.10 or newer */
1469
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001470 conn->established = 1;
1471 if (conn->push_buf == NULL) {
1472 /* Need to return something to get final TLS ACK. */
1473 conn->push_buf = wpabuf_alloc(0);
1474 }
1475
1476 gnutls_session_get_data(conn->session, NULL, &size);
1477 if (global->session_data == NULL ||
1478 global->session_data_size < size) {
1479 os_free(global->session_data);
1480 global->session_data = os_malloc(size);
1481 }
1482 if (global->session_data) {
1483 global->session_data_size = size;
1484 gnutls_session_get_data(conn->session,
1485 global->session_data,
1486 &global->session_data_size);
1487 }
1488
1489 if (conn->pull_buf && appl_data)
1490 *appl_data = gnutls_get_appl_data(conn);
1491 }
1492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001493 out_data = conn->push_buf;
1494 conn->push_buf = NULL;
1495 return out_data;
1496}
1497
1498
1499struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
1500 struct tls_connection *conn,
1501 const struct wpabuf *in_data,
1502 struct wpabuf **appl_data)
1503{
1504 return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
1505}
1506
1507
1508struct wpabuf * tls_connection_encrypt(void *tls_ctx,
1509 struct tls_connection *conn,
1510 const struct wpabuf *in_data)
1511{
1512 ssize_t res;
1513 struct wpabuf *buf;
1514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001515 res = gnutls_record_send(conn->session, wpabuf_head(in_data),
1516 wpabuf_len(in_data));
1517 if (res < 0) {
1518 wpa_printf(MSG_INFO, "%s: Encryption failed: %s",
1519 __func__, gnutls_strerror(res));
1520 return NULL;
1521 }
1522
1523 buf = conn->push_buf;
1524 conn->push_buf = NULL;
1525 return buf;
1526}
1527
1528
1529struct wpabuf * tls_connection_decrypt(void *tls_ctx,
1530 struct tls_connection *conn,
1531 const struct wpabuf *in_data)
1532{
1533 ssize_t res;
1534 struct wpabuf *out;
1535
1536 if (conn->pull_buf) {
1537 wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in "
1538 "pull_buf", __func__,
1539 (unsigned long) wpabuf_len(conn->pull_buf));
1540 wpabuf_free(conn->pull_buf);
1541 }
1542 conn->pull_buf = wpabuf_dup(in_data);
1543 if (conn->pull_buf == NULL)
1544 return NULL;
1545 conn->pull_buf_offset = wpabuf_head(conn->pull_buf);
1546
1547 /*
1548 * Even though we try to disable TLS compression, it is possible that
1549 * this cannot be done with all TLS libraries. Add extra buffer space
1550 * to handle the possibility of the decrypted data being longer than
1551 * input data.
1552 */
1553 out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
1554 if (out == NULL)
1555 return NULL;
1556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001557 res = gnutls_record_recv(conn->session, wpabuf_mhead(out),
1558 wpabuf_size(out));
1559 if (res < 0) {
1560 wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d "
1561 "(%s)", __func__, (int) res, gnutls_strerror(res));
1562 wpabuf_free(out);
1563 return NULL;
1564 }
1565 wpabuf_put(out, res);
1566
1567 return out;
1568}
1569
1570
1571int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
1572{
1573 if (conn == NULL)
1574 return 0;
1575 return gnutls_session_is_resumed(conn->session);
1576}
1577
1578
1579int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
1580 u8 *ciphers)
1581{
1582 /* TODO */
1583 return -1;
1584}
1585
1586
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001587int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
1588 char *buf, size_t buflen)
1589{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001590 gnutls_protocol_t ver;
1591
1592 ver = gnutls_protocol_get_version(conn->session);
1593 if (ver == GNUTLS_TLS1_0)
1594 os_strlcpy(buf, "TLSv1", buflen);
1595 else if (ver == GNUTLS_TLS1_1)
1596 os_strlcpy(buf, "TLSv1.1", buflen);
1597 else if (ver == GNUTLS_TLS1_2)
1598 os_strlcpy(buf, "TLSv1.2", buflen);
1599 else
1600 return -1;
1601 return 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001602}
1603
1604
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
1606 char *buf, size_t buflen)
1607{
Roshan Pius3a1667e2018-07-03 15:17:14 -07001608 gnutls_cipher_algorithm_t cipher;
1609 gnutls_kx_algorithm_t kx;
1610 gnutls_mac_algorithm_t mac;
1611 const char *kx_str, *cipher_str, *mac_str;
1612 int res;
1613
1614 cipher = gnutls_cipher_get(conn->session);
1615 cipher_str = gnutls_cipher_get_name(cipher);
1616 if (!cipher_str)
1617 cipher_str = "";
1618
1619 kx = gnutls_kx_get(conn->session);
1620 kx_str = gnutls_kx_get_name(kx);
1621 if (!kx_str)
1622 kx_str = "";
1623
1624 mac = gnutls_mac_get(conn->session);
1625 mac_str = gnutls_mac_get_name(mac);
1626 if (!mac_str)
1627 mac_str = "";
1628
1629 if (kx == GNUTLS_KX_RSA)
1630 res = os_snprintf(buf, buflen, "%s-%s", cipher_str, mac_str);
1631 else
1632 res = os_snprintf(buf, buflen, "%s-%s-%s",
1633 kx_str, cipher_str, mac_str);
1634 if (os_snprintf_error(buflen, res))
1635 return -1;
1636
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001637 return 0;
1638}
1639
1640
1641int tls_connection_enable_workaround(void *ssl_ctx,
1642 struct tls_connection *conn)
1643{
1644 gnutls_record_disable_padding(conn->session);
1645 return 0;
1646}
1647
1648
1649int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
1650 int ext_type, const u8 *data,
1651 size_t data_len)
1652{
1653 /* TODO */
1654 return -1;
1655}
1656
1657
1658int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
1659{
1660 if (conn == NULL)
1661 return -1;
1662 return conn->failed;
1663}
1664
1665
1666int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
1667{
1668 if (conn == NULL)
1669 return -1;
1670 return conn->read_alerts;
1671}
1672
1673
1674int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
1675{
1676 if (conn == NULL)
1677 return -1;
1678 return conn->write_alerts;
1679}
1680
1681
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001682int tls_connection_set_session_ticket_cb(void *tls_ctx,
1683 struct tls_connection *conn,
1684 tls_session_ticket_cb cb, void *ctx)
1685{
1686 return -1;
1687}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001688
1689
1690int tls_get_library_version(char *buf, size_t buf_len)
1691{
1692 return os_snprintf(buf, buf_len, "GnuTLS build=%s run=%s",
1693 GNUTLS_VERSION, gnutls_check_version(NULL));
1694}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001695
1696
1697void tls_connection_set_success_data(struct tls_connection *conn,
1698 struct wpabuf *data)
1699{
1700}
1701
1702
1703void tls_connection_set_success_data_resumed(struct tls_connection *conn)
1704{
1705}
1706
1707
1708const struct wpabuf *
1709tls_connection_get_success_data(struct tls_connection *conn)
1710{
1711 return NULL;
1712}
1713
1714
1715void tls_connection_remove_session(struct tls_connection *conn)
1716{
1717}