blob: 013ea30097ec21ae4181d9012e9b18b408d78cd6 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * SSL/TLS interface functions for OpenSSL
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003 * Copyright (c) 2004-2015, 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
11#ifndef CONFIG_SMARTCARD
12#ifndef OPENSSL_NO_ENGINE
Kenny Rootdb3c5a42012-03-20 17:00:47 -070013#ifndef ANDROID
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#define OPENSSL_NO_ENGINE
15#endif
16#endif
Kenny Rootdb3c5a42012-03-20 17:00:47 -070017#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018
19#include <openssl/ssl.h>
20#include <openssl/err.h>
Dmitry Shmidt849734c2016-05-27 09:59:01 -070021#include <openssl/opensslv.h>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include <openssl/pkcs12.h>
23#include <openssl/x509v3.h>
24#ifndef OPENSSL_NO_ENGINE
25#include <openssl/engine.h>
26#endif /* OPENSSL_NO_ENGINE */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080027#ifndef OPENSSL_NO_DSA
28#include <openssl/dsa.h>
29#endif
30#ifndef OPENSSL_NO_DH
31#include <openssl/dh.h>
32#endif
33
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034#include "common.h"
35#include "crypto.h"
Dmitry Shmidtaf9da312015-04-03 10:03:11 -070036#include "sha1.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080037#include "sha256.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070038#include "tls.h"
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -080039#include "tls_openssl.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040
Dmitry Shmidt849734c2016-05-27 09:59:01 -070041#if !defined(CONFIG_FIPS) && \
42 (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \
43 defined(EAP_SERVER_FAST))
44#define OPENSSL_NEED_EAP_FAST_PRF
45#endif
46
Hai Shalom81f62d82019-07-22 12:10:00 -070047#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \
48 defined(EAP_SERVER_FAST) || defined(EAP_TEAP) || \
49 defined(EAP_SERVER_TEAP)
50#define EAP_FAST_OR_TEAP
51#endif
52
53
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -070054#if defined(OPENSSL_IS_BORINGSSL)
55/* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
56typedef size_t stack_index_t;
57#else
58typedef int stack_index_t;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070059#endif
60
Dmitry Shmidt34af3062013-07-11 10:46:32 -070061#ifdef SSL_set_tlsext_status_type
62#ifndef OPENSSL_NO_TLSEXT
63#define HAVE_OCSP
64#include <openssl/ocsp.h>
65#endif /* OPENSSL_NO_TLSEXT */
66#endif /* SSL_set_tlsext_status_type */
67
Dmitry Shmidt849734c2016-05-27 09:59:01 -070068#if (OPENSSL_VERSION_NUMBER < 0x10100000L || \
Roshan Pius3a1667e2018-07-03 15:17:14 -070069 (defined(LIBRESSL_VERSION_NUMBER) && \
70 LIBRESSL_VERSION_NUMBER < 0x20700000L)) && \
Dmitry Shmidt849734c2016-05-27 09:59:01 -070071 !defined(BORINGSSL_API_VERSION)
Dmitry Shmidtde47be72016-01-07 12:52:55 -080072/*
73 * SSL_get_client_random() and SSL_get_server_random() were added in OpenSSL
Dmitry Shmidt849734c2016-05-27 09:59:01 -070074 * 1.1.0 and newer BoringSSL revisions. Provide compatibility wrappers for
75 * older versions.
Dmitry Shmidtde47be72016-01-07 12:52:55 -080076 */
77
78static size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
79 size_t outlen)
80{
81 if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
82 return 0;
83 os_memcpy(out, ssl->s3->client_random, SSL3_RANDOM_SIZE);
84 return SSL3_RANDOM_SIZE;
85}
86
87
88static size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
89 size_t outlen)
90{
91 if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE)
92 return 0;
93 os_memcpy(out, ssl->s3->server_random, SSL3_RANDOM_SIZE);
94 return SSL3_RANDOM_SIZE;
95}
96
97
Dmitry Shmidt849734c2016-05-27 09:59:01 -070098#ifdef OPENSSL_NEED_EAP_FAST_PRF
Dmitry Shmidtde47be72016-01-07 12:52:55 -080099static size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
100 unsigned char *out, size_t outlen)
101{
102 if (!session || session->master_key_length < 0 ||
103 (size_t) session->master_key_length > outlen)
104 return 0;
105 if ((size_t) session->master_key_length < outlen)
106 outlen = session->master_key_length;
107 os_memcpy(out, session->master_key, outlen);
108 return outlen;
109}
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700110#endif /* OPENSSL_NEED_EAP_FAST_PRF */
Dmitry Shmidtde47be72016-01-07 12:52:55 -0800111
112#endif
113
Hai Shalom74f70d42019-02-11 14:42:39 -0800114#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
115 (defined(LIBRESSL_VERSION_NUMBER) && \
116 LIBRESSL_VERSION_NUMBER < 0x20700000L)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700117#ifdef CONFIG_SUITEB
118static int RSA_bits(const RSA *r)
119{
120 return BN_num_bits(r->n);
121}
122#endif /* CONFIG_SUITEB */
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800123
124
125static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
126{
127 return ASN1_STRING_data((ASN1_STRING *) x);
128}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700129#endif
130
Dmitry Shmidtff079172013-11-08 14:10:30 -0800131#ifdef ANDROID
132#include <openssl/pem.h>
133#include <keystore/keystore_get.h>
134
Pavel Grafov4d8552e2018-02-06 11:28:29 +0000135#include <log/log.h>
136#include <log/log_event_list.h>
137
138#define CERT_VALIDATION_FAILURE 210033
139
140static void log_cert_validation_failure(const char *reason)
141{
142 android_log_context ctx = create_android_logger(CERT_VALIDATION_FAILURE);
143 android_log_write_string8(ctx, reason);
144 android_log_write_list(ctx, LOG_ID_SECURITY);
145 android_log_destroy(&ctx);
146}
147
148
Dmitry Shmidtff079172013-11-08 14:10:30 -0800149static BIO * BIO_from_keystore(const char *key)
150{
151 BIO *bio = NULL;
152 uint8_t *value = NULL;
153 int length = keystore_get(key, strlen(key), &value);
154 if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
155 BIO_write(bio, value, length);
156 free(value);
157 return bio;
158}
Dmitry Shmidtb97e4282016-02-08 10:16:07 -0800159
160
161static int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias)
162{
163 BIO *bio = BIO_from_keystore(key_alias);
164 STACK_OF(X509_INFO) *stack = NULL;
165 stack_index_t i;
Hai Shalom22171592021-04-02 16:05:23 -0700166 int ret = 0;
Dmitry Shmidtb97e4282016-02-08 10:16:07 -0800167
Hai Shalom22171592021-04-02 16:05:23 -0700168 if (!bio) {
169 wpa_printf(MSG_ERROR, "TLS: Failed to parse certificate: %s",
170 key_alias);
171 return -1;
Dmitry Shmidtb97e4282016-02-08 10:16:07 -0800172 }
173
Hai Shalom22171592021-04-02 16:05:23 -0700174 // Try DER encoding first
175 X509 *x509 = d2i_X509_bio(bio, NULL);
176 if (x509) {
177 while (x509) {
178 if (!X509_STORE_add_cert(ctx, x509)) {
179 wpa_printf(MSG_ERROR, "TLS: Failed to add Root CA certificate");
180 ret = -1;
181 break;
182 }
183 x509 = d2i_X509_bio(bio, NULL);
184 }
185 BIO_free(bio);
186 return ret;
187 }
188
189 // Try PEM encoding
190 stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
191 BIO_free(bio);
192
Dmitry Shmidtb97e4282016-02-08 10:16:07 -0800193 if (!stack) {
194 wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s",
195 key_alias);
196 return -1;
197 }
198
199 for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
200 X509_INFO *info = sk_X509_INFO_value(stack, i);
201
202 if (info->x509)
Hai Shalom22171592021-04-02 16:05:23 -0700203 if (!X509_STORE_add_cert(ctx, info->x509)) {
204 wpa_printf(MSG_ERROR, "TLS: Failed to add Root CA certificate");
205 ret = -1;
206 break;
207 }
Dmitry Shmidtb97e4282016-02-08 10:16:07 -0800208 if (info->crl)
209 X509_STORE_add_crl(ctx, info->crl);
210 }
211
212 sk_X509_INFO_pop_free(stack, X509_INFO_free);
Hai Shalom22171592021-04-02 16:05:23 -0700213 return ret;
Dmitry Shmidtb97e4282016-02-08 10:16:07 -0800214}
215
216
217static int tls_add_ca_from_keystore_encoded(X509_STORE *ctx,
218 const char *encoded_key_alias)
219{
220 int rc = -1;
221 int len = os_strlen(encoded_key_alias);
222 unsigned char *decoded_alias;
223
224 if (len & 1) {
225 wpa_printf(MSG_WARNING, "Invalid hex-encoded alias: %s",
226 encoded_key_alias);
227 return rc;
228 }
229
230 decoded_alias = os_malloc(len / 2 + 1);
231 if (decoded_alias) {
232 if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) {
233 decoded_alias[len / 2] = '\0';
234 rc = tls_add_ca_from_keystore(
235 ctx, (const char *) decoded_alias);
236 }
237 os_free(decoded_alias);
238 }
239
240 return rc;
241}
242
Dmitry Shmidtff079172013-11-08 14:10:30 -0800243#endif /* ANDROID */
244
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700245static int tls_openssl_ref_count = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800246static int tls_ex_idx_session = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700247
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700248struct tls_context {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700249 void (*event_cb)(void *ctx, enum tls_event ev,
250 union tls_event_data *data);
251 void *cb_ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800252 int cert_in_cb;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700253 char *ocsp_stapling_response;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254};
255
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700256static struct tls_context *tls_global = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257
258
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800259struct tls_data {
260 SSL_CTX *ssl;
261 unsigned int tls_session_lifetime;
Hai Shalom74f70d42019-02-11 14:42:39 -0800262 int check_crl;
263 int check_crl_strict;
264 char *ca_cert;
265 unsigned int crl_reload_interval;
266 struct os_reltime crl_last_reload;
Hai Shalom021b0b52019-04-10 11:17:58 -0700267 char *check_cert_subject;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800268};
269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700270struct tls_connection {
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700271 struct tls_context *context;
Hai Shalom74f70d42019-02-11 14:42:39 -0800272 struct tls_data *data;
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800273 SSL_CTX *ssl_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700274 SSL *ssl;
275 BIO *ssl_in, *ssl_out;
Adam Langley1eb02ed2015-04-21 19:00:05 -0700276#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700277 ENGINE *engine; /* functional reference to the engine */
278 EVP_PKEY *private_key; /* the private key if using engine */
279#endif /* OPENSSL_NO_ENGINE */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800280 char *subject_match, *altsubject_match, *suffix_match, *domain_match;
Hai Shalom021b0b52019-04-10 11:17:58 -0700281 char *check_cert_subject;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700282 int read_alerts, write_alerts, failed;
283
284 tls_session_ticket_cb session_ticket_cb;
285 void *session_ticket_cb_ctx;
286
287 /* SessionTicket received from OpenSSL hello_extension_cb (server) */
288 u8 *session_ticket;
289 size_t session_ticket_len;
290
291 unsigned int ca_cert_verify:1;
292 unsigned int cert_probe:1;
293 unsigned int server_cert_only:1;
Jouni Malinen26af48b2014-04-09 13:02:53 +0300294 unsigned int invalid_hb_used:1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800295 unsigned int success_data:1;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700296 unsigned int client_hello_generated:1;
297 unsigned int server:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298
299 u8 srv_cert_hash[32];
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700300
301 unsigned int flags;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700302
303 X509 *peer_cert;
304 X509 *peer_issuer;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800305 X509 *peer_issuer_issuer;
Hai Shalom899fcc72020-10-19 14:38:18 -0700306 char *peer_subject; /* peer subject info for authenticated peer */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800307
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800308 unsigned char client_random[SSL3_RANDOM_SIZE];
309 unsigned char server_random[SSL3_RANDOM_SIZE];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700310
311 u16 cipher_suite;
312 int server_dh_prime_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700313};
314
315
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700316static struct tls_context * tls_context_new(const struct tls_config *conf)
317{
318 struct tls_context *context = os_zalloc(sizeof(*context));
319 if (context == NULL)
320 return NULL;
321 if (conf) {
322 context->event_cb = conf->event_cb;
323 context->cb_ctx = conf->cb_ctx;
324 context->cert_in_cb = conf->cert_in_cb;
325 }
326 return context;
327}
328
329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700330#ifdef CONFIG_NO_STDOUT_DEBUG
331
332static void _tls_show_errors(void)
333{
334 unsigned long err;
335
336 while ((err = ERR_get_error())) {
337 /* Just ignore the errors, since stdout is disabled */
338 }
339}
340#define tls_show_errors(l, f, t) _tls_show_errors()
341
342#else /* CONFIG_NO_STDOUT_DEBUG */
343
344static void tls_show_errors(int level, const char *func, const char *txt)
345{
346 unsigned long err;
347
348 wpa_printf(level, "OpenSSL: %s - %s %s",
349 func, txt, ERR_error_string(ERR_get_error(), NULL));
350
351 while ((err = ERR_get_error())) {
352 wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",
353 ERR_error_string(err, NULL));
354 }
355}
356
357#endif /* CONFIG_NO_STDOUT_DEBUG */
358
359
Hai Shalom74f70d42019-02-11 14:42:39 -0800360static X509_STORE * tls_crl_cert_reload(const char *ca_cert, int check_crl)
361{
362 int flags;
363 X509_STORE *store;
364
365 store = X509_STORE_new();
366 if (!store) {
367 wpa_printf(MSG_DEBUG,
368 "OpenSSL: %s - failed to allocate new certificate store",
369 __func__);
370 return NULL;
371 }
372
373 if (ca_cert && X509_STORE_load_locations(store, ca_cert, NULL) != 1) {
374 tls_show_errors(MSG_WARNING, __func__,
375 "Failed to load root certificates");
376 X509_STORE_free(store);
377 return NULL;
378 }
379
380 flags = check_crl ? X509_V_FLAG_CRL_CHECK : 0;
381 if (check_crl == 2)
382 flags |= X509_V_FLAG_CRL_CHECK_ALL;
383
384 X509_STORE_set_flags(store, flags);
385
386 return store;
387}
388
389
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700390#ifdef CONFIG_NATIVE_WINDOWS
391
392/* Windows CryptoAPI and access to certificate stores */
393#include <wincrypt.h>
394
395#ifdef __MINGW32_VERSION
396/*
397 * MinGW does not yet include all the needed definitions for CryptoAPI, so
398 * define here whatever extra is needed.
399 */
400#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16)
401#define CERT_STORE_READONLY_FLAG 0x00008000
402#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
403
404#endif /* __MINGW32_VERSION */
405
406
407struct cryptoapi_rsa_data {
408 const CERT_CONTEXT *cert;
409 HCRYPTPROV crypt_prov;
410 DWORD key_spec;
411 BOOL free_crypt_prov;
412};
413
414
415static void cryptoapi_error(const char *msg)
416{
417 wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u",
418 msg, (unsigned int) GetLastError());
419}
420
421
422static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from,
423 unsigned char *to, RSA *rsa, int padding)
424{
425 wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
426 return 0;
427}
428
429
430static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from,
431 unsigned char *to, RSA *rsa, int padding)
432{
433 wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
434 return 0;
435}
436
437
438static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from,
439 unsigned char *to, RSA *rsa, int padding)
440{
441 struct cryptoapi_rsa_data *priv =
442 (struct cryptoapi_rsa_data *) rsa->meth->app_data;
443 HCRYPTHASH hash;
444 DWORD hash_size, len, i;
445 unsigned char *buf = NULL;
446 int ret = 0;
447
448 if (priv == NULL) {
449 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
450 ERR_R_PASSED_NULL_PARAMETER);
451 return 0;
452 }
453
454 if (padding != RSA_PKCS1_PADDING) {
455 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
456 RSA_R_UNKNOWN_PADDING_TYPE);
457 return 0;
458 }
459
460 if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) {
461 wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported",
462 __func__);
463 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
464 RSA_R_INVALID_MESSAGE_LENGTH);
465 return 0;
466 }
467
468 if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
469 {
470 cryptoapi_error("CryptCreateHash failed");
471 return 0;
472 }
473
474 len = sizeof(hash_size);
475 if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len,
476 0)) {
477 cryptoapi_error("CryptGetHashParam failed");
478 goto err;
479 }
480
481 if ((int) hash_size != flen) {
482 wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)",
483 (unsigned) hash_size, flen);
484 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
485 RSA_R_INVALID_MESSAGE_LENGTH);
486 goto err;
487 }
488 if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {
489 cryptoapi_error("CryptSetHashParam failed");
490 goto err;
491 }
492
493 len = RSA_size(rsa);
494 buf = os_malloc(len);
495 if (buf == NULL) {
496 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
497 goto err;
498 }
499
500 if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) {
501 cryptoapi_error("CryptSignHash failed");
502 goto err;
503 }
504
505 for (i = 0; i < len; i++)
506 to[i] = buf[len - i - 1];
507 ret = len;
508
509err:
510 os_free(buf);
511 CryptDestroyHash(hash);
512
513 return ret;
514}
515
516
517static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from,
518 unsigned char *to, RSA *rsa, int padding)
519{
520 wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
521 return 0;
522}
523
524
525static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv)
526{
527 if (priv == NULL)
528 return;
529 if (priv->crypt_prov && priv->free_crypt_prov)
530 CryptReleaseContext(priv->crypt_prov, 0);
531 if (priv->cert)
532 CertFreeCertificateContext(priv->cert);
533 os_free(priv);
534}
535
536
537static int cryptoapi_finish(RSA *rsa)
538{
539 cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data);
540 os_free((void *) rsa->meth);
541 rsa->meth = NULL;
542 return 1;
543}
544
545
546static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store)
547{
548 HCERTSTORE cs;
549 const CERT_CONTEXT *ret = NULL;
550
551 cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0,
552 store | CERT_STORE_OPEN_EXISTING_FLAG |
553 CERT_STORE_READONLY_FLAG, L"MY");
554 if (cs == NULL) {
555 cryptoapi_error("Failed to open 'My system store'");
556 return NULL;
557 }
558
559 if (strncmp(name, "cert://", 7) == 0) {
560 unsigned short wbuf[255];
561 MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255);
562 ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING |
563 PKCS_7_ASN_ENCODING,
564 0, CERT_FIND_SUBJECT_STR,
565 wbuf, NULL);
566 } else if (strncmp(name, "hash://", 7) == 0) {
567 CRYPT_HASH_BLOB blob;
568 int len;
569 const char *hash = name + 7;
570 unsigned char *buf;
571
572 len = os_strlen(hash) / 2;
573 buf = os_malloc(len);
574 if (buf && hexstr2bin(hash, buf, len) == 0) {
575 blob.cbData = len;
576 blob.pbData = buf;
577 ret = CertFindCertificateInStore(cs,
578 X509_ASN_ENCODING |
579 PKCS_7_ASN_ENCODING,
580 0, CERT_FIND_HASH,
581 &blob, NULL);
582 }
583 os_free(buf);
584 }
585
586 CertCloseStore(cs, 0);
587
588 return ret;
589}
590
591
592static int tls_cryptoapi_cert(SSL *ssl, const char *name)
593{
594 X509 *cert = NULL;
595 RSA *rsa = NULL, *pub_rsa;
596 struct cryptoapi_rsa_data *priv;
597 RSA_METHOD *rsa_meth;
598
599 if (name == NULL ||
600 (strncmp(name, "cert://", 7) != 0 &&
601 strncmp(name, "hash://", 7) != 0))
602 return -1;
603
604 priv = os_zalloc(sizeof(*priv));
605 rsa_meth = os_zalloc(sizeof(*rsa_meth));
606 if (priv == NULL || rsa_meth == NULL) {
607 wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory "
608 "for CryptoAPI RSA method");
609 os_free(priv);
610 os_free(rsa_meth);
611 return -1;
612 }
613
614 priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER);
615 if (priv->cert == NULL) {
616 priv->cert = cryptoapi_find_cert(
617 name, CERT_SYSTEM_STORE_LOCAL_MACHINE);
618 }
619 if (priv->cert == NULL) {
620 wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate "
621 "'%s'", name);
622 goto err;
623 }
624
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800625 cert = d2i_X509(NULL,
626 (const unsigned char **) &priv->cert->pbCertEncoded,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700627 priv->cert->cbCertEncoded);
628 if (cert == NULL) {
629 wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER "
630 "encoding");
631 goto err;
632 }
633
634 if (!CryptAcquireCertificatePrivateKey(priv->cert,
635 CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
636 NULL, &priv->crypt_prov,
637 &priv->key_spec,
638 &priv->free_crypt_prov)) {
639 cryptoapi_error("Failed to acquire a private key for the "
640 "certificate");
641 goto err;
642 }
643
644 rsa_meth->name = "Microsoft CryptoAPI RSA Method";
645 rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc;
646 rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec;
647 rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc;
648 rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec;
649 rsa_meth->finish = cryptoapi_finish;
650 rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;
651 rsa_meth->app_data = (char *) priv;
652
653 rsa = RSA_new();
654 if (rsa == NULL) {
655 SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,
656 ERR_R_MALLOC_FAILURE);
657 goto err;
658 }
659
660 if (!SSL_use_certificate(ssl, cert)) {
661 RSA_free(rsa);
662 rsa = NULL;
663 goto err;
664 }
665 pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
666 X509_free(cert);
667 cert = NULL;
668
669 rsa->n = BN_dup(pub_rsa->n);
670 rsa->e = BN_dup(pub_rsa->e);
671 if (!RSA_set_method(rsa, rsa_meth))
672 goto err;
673
674 if (!SSL_use_RSAPrivateKey(ssl, rsa))
675 goto err;
676 RSA_free(rsa);
677
678 return 0;
679
680err:
681 if (cert)
682 X509_free(cert);
683 if (rsa)
684 RSA_free(rsa);
685 else {
686 os_free(rsa_meth);
687 cryptoapi_free_data(priv);
688 }
689 return -1;
690}
691
692
693static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name)
694{
695 HCERTSTORE cs;
696 PCCERT_CONTEXT ctx = NULL;
697 X509 *cert;
698 char buf[128];
699 const char *store;
700#ifdef UNICODE
701 WCHAR *wstore;
702#endif /* UNICODE */
703
704 if (name == NULL || strncmp(name, "cert_store://", 13) != 0)
705 return -1;
706
707 store = name + 13;
708#ifdef UNICODE
709 wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR));
710 if (wstore == NULL)
711 return -1;
712 wsprintf(wstore, L"%S", store);
713 cs = CertOpenSystemStore(0, wstore);
714 os_free(wstore);
715#else /* UNICODE */
716 cs = CertOpenSystemStore(0, store);
717#endif /* UNICODE */
718 if (cs == NULL) {
719 wpa_printf(MSG_DEBUG, "%s: failed to open system cert store "
720 "'%s': error=%d", __func__, store,
721 (int) GetLastError());
722 return -1;
723 }
724
725 while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800726 cert = d2i_X509(NULL,
727 (const unsigned char **) &ctx->pbCertEncoded,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700728 ctx->cbCertEncoded);
729 if (cert == NULL) {
730 wpa_printf(MSG_INFO, "CryptoAPI: Could not process "
731 "X509 DER encoding for CA cert");
732 continue;
733 }
734
735 X509_NAME_oneline(X509_get_subject_name(cert), buf,
736 sizeof(buf));
737 wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for "
738 "system certificate store: subject='%s'", buf);
739
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700740 if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
741 cert)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700742 tls_show_errors(MSG_WARNING, __func__,
743 "Failed to add ca_cert to OpenSSL "
744 "certificate store");
745 }
746
747 X509_free(cert);
748 }
749
750 if (!CertCloseStore(cs, 0)) {
751 wpa_printf(MSG_DEBUG, "%s: failed to close system cert store "
752 "'%s': error=%d", __func__, name + 13,
753 (int) GetLastError());
754 }
755
756 return 0;
757}
758
759
760#else /* CONFIG_NATIVE_WINDOWS */
761
762static int tls_cryptoapi_cert(SSL *ssl, const char *name)
763{
764 return -1;
765}
766
767#endif /* CONFIG_NATIVE_WINDOWS */
768
769
770static void ssl_info_cb(const SSL *ssl, int where, int ret)
771{
772 const char *str;
773 int w;
774
775 wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret);
776 w = where & ~SSL_ST_MASK;
777 if (w & SSL_ST_CONNECT)
778 str = "SSL_connect";
779 else if (w & SSL_ST_ACCEPT)
780 str = "SSL_accept";
781 else
782 str = "undefined";
783
784 if (where & SSL_CB_LOOP) {
785 wpa_printf(MSG_DEBUG, "SSL: %s:%s",
786 str, SSL_state_string_long(ssl));
787 } else if (where & SSL_CB_ALERT) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700788 struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700789 wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
790 where & SSL_CB_READ ?
791 "read (remote end reported an error)" :
792 "write (local SSL3 detected an error)",
793 SSL_alert_type_string_long(ret),
794 SSL_alert_desc_string_long(ret));
795 if ((ret >> 8) == SSL3_AL_FATAL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700796 if (where & SSL_CB_READ)
797 conn->read_alerts++;
798 else
799 conn->write_alerts++;
800 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700801 if (conn->context->event_cb != NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700802 union tls_event_data ev;
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700803 struct tls_context *context = conn->context;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700804 os_memset(&ev, 0, sizeof(ev));
805 ev.alert.is_local = !(where & SSL_CB_READ);
806 ev.alert.type = SSL_alert_type_string_long(ret);
807 ev.alert.description = SSL_alert_desc_string_long(ret);
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700808 context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700809 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700810 } else if (where & SSL_CB_EXIT && ret <= 0) {
811 wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
812 str, ret == 0 ? "failed" : "error",
813 SSL_state_string_long(ssl));
814 }
815}
816
817
818#ifndef OPENSSL_NO_ENGINE
819/**
820 * tls_engine_load_dynamic_generic - load any openssl engine
821 * @pre: an array of commands and values that load an engine initialized
822 * in the engine specific function
823 * @post: an array of commands and values that initialize an already loaded
824 * engine (or %NULL if not required)
825 * @id: the engine id of the engine to load (only required if post is not %NULL
826 *
827 * This function is a generic function that loads any openssl engine.
828 *
829 * Returns: 0 on success, -1 on failure
830 */
831static int tls_engine_load_dynamic_generic(const char *pre[],
832 const char *post[], const char *id)
833{
834 ENGINE *engine;
835 const char *dynamic_id = "dynamic";
836
837 engine = ENGINE_by_id(id);
838 if (engine) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700839 wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already "
840 "available", id);
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700841 /*
842 * If it was auto-loaded by ENGINE_by_id() we might still
843 * need to tell it which PKCS#11 module to use in legacy
844 * (non-p11-kit) environments. Do so now; even if it was
845 * properly initialised before, setting it again will be
846 * harmless.
847 */
848 goto found;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849 }
850 ERR_clear_error();
851
852 engine = ENGINE_by_id(dynamic_id);
853 if (engine == NULL) {
854 wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
855 dynamic_id,
856 ERR_error_string(ERR_get_error(), NULL));
857 return -1;
858 }
859
860 /* Perform the pre commands. This will load the engine. */
861 while (pre && pre[0]) {
862 wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]);
863 if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) {
864 wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: "
865 "%s %s [%s]", pre[0], pre[1],
866 ERR_error_string(ERR_get_error(), NULL));
867 ENGINE_free(engine);
868 return -1;
869 }
870 pre += 2;
871 }
872
873 /*
874 * Free the reference to the "dynamic" engine. The loaded engine can
875 * now be looked up using ENGINE_by_id().
876 */
877 ENGINE_free(engine);
878
879 engine = ENGINE_by_id(id);
880 if (engine == NULL) {
881 wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
882 id, ERR_error_string(ERR_get_error(), NULL));
883 return -1;
884 }
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700885 found:
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700886 while (post && post[0]) {
887 wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]);
888 if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) {
889 wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:"
890 " %s %s [%s]", post[0], post[1],
891 ERR_error_string(ERR_get_error(), NULL));
892 ENGINE_remove(engine);
893 ENGINE_free(engine);
894 return -1;
895 }
896 post += 2;
897 }
898 ENGINE_free(engine);
899
900 return 0;
901}
902
903
904/**
905 * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc
906 * @pkcs11_so_path: pksc11_so_path from the configuration
907 * @pcks11_module_path: pkcs11_module_path from the configuration
908 */
909static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,
910 const char *pkcs11_module_path)
911{
912 char *engine_id = "pkcs11";
913 const char *pre_cmd[] = {
914 "SO_PATH", NULL /* pkcs11_so_path */,
915 "ID", NULL /* engine_id */,
916 "LIST_ADD", "1",
917 /* "NO_VCHECK", "1", */
918 "LOAD", NULL,
919 NULL, NULL
920 };
921 const char *post_cmd[] = {
922 "MODULE_PATH", NULL /* pkcs11_module_path */,
923 NULL, NULL
924 };
925
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800926 if (!pkcs11_so_path)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700927 return 0;
928
929 pre_cmd[1] = pkcs11_so_path;
930 pre_cmd[3] = engine_id;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800931 if (pkcs11_module_path)
932 post_cmd[1] = pkcs11_module_path;
933 else
934 post_cmd[0] = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935
936 wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",
937 pkcs11_so_path);
938
939 return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id);
940}
941
942
943/**
944 * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc
945 * @opensc_so_path: opensc_so_path from the configuration
946 */
947static int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
948{
949 char *engine_id = "opensc";
950 const char *pre_cmd[] = {
951 "SO_PATH", NULL /* opensc_so_path */,
952 "ID", NULL /* engine_id */,
953 "LIST_ADD", "1",
954 "LOAD", NULL,
955 NULL, NULL
956 };
957
958 if (!opensc_so_path)
959 return 0;
960
961 pre_cmd[1] = opensc_so_path;
962 pre_cmd[3] = engine_id;
963
964 wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s",
965 opensc_so_path);
966
967 return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id);
968}
969#endif /* OPENSSL_NO_ENGINE */
970
971
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800972static void remove_session_cb(SSL_CTX *ctx, SSL_SESSION *sess)
973{
974 struct wpabuf *buf;
975
976 if (tls_ex_idx_session < 0)
977 return;
978 buf = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
979 if (!buf)
980 return;
981 wpa_printf(MSG_DEBUG,
982 "OpenSSL: Free application session data %p (sess %p)",
983 buf, sess);
984 wpabuf_free(buf);
985
986 SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, NULL);
987}
988
989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700990void * tls_init(const struct tls_config *conf)
991{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800992 struct tls_data *data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 SSL_CTX *ssl;
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700994 struct tls_context *context;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800995 const char *ciphers;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996
997 if (tls_openssl_ref_count == 0) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700998 tls_global = context = tls_context_new(conf);
999 if (context == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001#ifdef CONFIG_FIPS
1002#ifdef OPENSSL_FIPS
1003 if (conf && conf->fips_mode) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001004 static int fips_enabled = 0;
1005
1006 if (!fips_enabled && !FIPS_mode_set(1)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 wpa_printf(MSG_ERROR, "Failed to enable FIPS "
1008 "mode");
1009 ERR_load_crypto_strings();
1010 ERR_print_errors_fp(stderr);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001011 os_free(tls_global);
1012 tls_global = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001013 return NULL;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001014 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001015 wpa_printf(MSG_INFO, "Running in FIPS mode");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001016 fips_enabled = 1;
1017 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001018 }
1019#else /* OPENSSL_FIPS */
1020 if (conf && conf->fips_mode) {
1021 wpa_printf(MSG_ERROR, "FIPS mode requested, but not "
1022 "supported");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001023 os_free(tls_global);
1024 tls_global = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025 return NULL;
1026 }
1027#endif /* OPENSSL_FIPS */
1028#endif /* CONFIG_FIPS */
Roshan Pius3a1667e2018-07-03 15:17:14 -07001029#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
1030 (defined(LIBRESSL_VERSION_NUMBER) && \
1031 LIBRESSL_VERSION_NUMBER < 0x20700000L)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032 SSL_load_error_strings();
1033 SSL_library_init();
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001034#ifndef OPENSSL_NO_SHA256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001035 EVP_add_digest(EVP_sha256());
1036#endif /* OPENSSL_NO_SHA256 */
1037 /* TODO: if /dev/urandom is available, PRNG is seeded
1038 * automatically. If this is not the case, random data should
1039 * be added here. */
1040
1041#ifdef PKCS12_FUNCS
1042#ifndef OPENSSL_NO_RC2
1043 /*
1044 * 40-bit RC2 is commonly used in PKCS#12 files, so enable it.
1045 * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8
1046 * versions, but it looks like OpenSSL 1.0.0 does not do that
1047 * anymore.
1048 */
1049 EVP_add_cipher(EVP_rc2_40_cbc());
1050#endif /* OPENSSL_NO_RC2 */
1051 PKCS12_PBE_add();
1052#endif /* PKCS12_FUNCS */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001053#endif /* < 1.1.0 */
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001054 } else {
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001055 context = tls_context_new(conf);
1056 if (context == NULL)
1057 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001058 }
1059 tls_openssl_ref_count++;
1060
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001061 data = os_zalloc(sizeof(*data));
1062 if (data)
1063 ssl = SSL_CTX_new(SSLv23_method());
1064 else
1065 ssl = NULL;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001066 if (ssl == NULL) {
1067 tls_openssl_ref_count--;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07001068 if (context != tls_global)
1069 os_free(context);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001070 if (tls_openssl_ref_count == 0) {
1071 os_free(tls_global);
1072 tls_global = NULL;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001073 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001074 os_free(data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001075 return NULL;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001076 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001077 data->ssl = ssl;
Hai Shalom74f70d42019-02-11 14:42:39 -08001078 if (conf) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001079 data->tls_session_lifetime = conf->tls_session_lifetime;
Hai Shalom74f70d42019-02-11 14:42:39 -08001080 data->crl_reload_interval = conf->crl_reload_interval;
1081 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001082
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001083 SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2);
1084 SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
1085
Hai Shalom60840252021-02-19 19:02:11 -08001086 SSL_CTX_set_mode(ssl, SSL_MODE_AUTO_RETRY);
1087
Dmitry Shmidt29333592017-01-09 12:27:11 -08001088#ifdef SSL_MODE_NO_AUTO_CHAIN
1089 /* Number of deployed use cases assume the default OpenSSL behavior of
1090 * auto chaining the local certificate is in use. BoringSSL removed this
1091 * functionality by default, so we need to restore it here to avoid
1092 * breaking existing use cases. */
1093 SSL_CTX_clear_mode(ssl, SSL_MODE_NO_AUTO_CHAIN);
1094#endif /* SSL_MODE_NO_AUTO_CHAIN */
1095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096 SSL_CTX_set_info_callback(ssl, ssl_info_cb);
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001097 SSL_CTX_set_app_data(ssl, context);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001098 if (data->tls_session_lifetime > 0) {
1099 SSL_CTX_set_quiet_shutdown(ssl, 1);
1100 /*
1101 * Set default context here. In practice, this will be replaced
1102 * by the per-EAP method context in tls_connection_set_verify().
1103 */
1104 SSL_CTX_set_session_id_context(ssl, (u8 *) "hostapd", 7);
1105 SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_SERVER);
1106 SSL_CTX_set_timeout(ssl, data->tls_session_lifetime);
1107 SSL_CTX_sess_set_remove_cb(ssl, remove_session_cb);
1108 } else {
1109 SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_OFF);
1110 }
1111
1112 if (tls_ex_idx_session < 0) {
1113 tls_ex_idx_session = SSL_SESSION_get_ex_new_index(
1114 0, NULL, NULL, NULL, NULL);
1115 if (tls_ex_idx_session < 0) {
1116 tls_deinit(data);
1117 return NULL;
1118 }
1119 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001120
1121#ifndef OPENSSL_NO_ENGINE
Hai Shalom81f62d82019-07-22 12:10:00 -07001122 wpa_printf(MSG_DEBUG, "ENGINE: Loading builtin engines");
1123 ENGINE_load_builtin_engines();
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001124
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001125 if (conf &&
1126 (conf->opensc_engine_path || conf->pkcs11_engine_path ||
1127 conf->pkcs11_module_path)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001128 if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) ||
1129 tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path,
1130 conf->pkcs11_module_path)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001131 tls_deinit(data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001132 return NULL;
1133 }
1134 }
1135#endif /* OPENSSL_NO_ENGINE */
1136
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001137 if (conf && conf->openssl_ciphers)
1138 ciphers = conf->openssl_ciphers;
1139 else
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001140 ciphers = TLS_DEFAULT_CIPHERS;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001141 if (SSL_CTX_set_cipher_list(ssl, ciphers) != 1) {
1142 wpa_printf(MSG_ERROR,
1143 "OpenSSL: Failed to set cipher string '%s'",
1144 ciphers);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001145 tls_deinit(data);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001146 return NULL;
1147 }
1148
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001149 return data;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001150}
1151
1152
1153void tls_deinit(void *ssl_ctx)
1154{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001155 struct tls_data *data = ssl_ctx;
1156 SSL_CTX *ssl = data->ssl;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001157 struct tls_context *context = SSL_CTX_get_app_data(ssl);
1158 if (context != tls_global)
1159 os_free(context);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001160 if (data->tls_session_lifetime > 0)
1161 SSL_CTX_flush_sessions(ssl, 0);
Hai Shalom74f70d42019-02-11 14:42:39 -08001162 os_free(data->ca_cert);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001163 SSL_CTX_free(ssl);
1164
1165 tls_openssl_ref_count--;
1166 if (tls_openssl_ref_count == 0) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001167#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
1168 (defined(LIBRESSL_VERSION_NUMBER) && \
1169 LIBRESSL_VERSION_NUMBER < 0x20700000L)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001170#ifndef OPENSSL_NO_ENGINE
1171 ENGINE_cleanup();
1172#endif /* OPENSSL_NO_ENGINE */
1173 CRYPTO_cleanup_all_ex_data();
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001174 ERR_remove_thread_state(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001175 ERR_free_strings();
1176 EVP_cleanup();
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001177#endif /* < 1.1.0 */
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001178 os_free(tls_global->ocsp_stapling_response);
1179 tls_global->ocsp_stapling_response = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001180 os_free(tls_global);
1181 tls_global = NULL;
1182 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001183
Hai Shalom021b0b52019-04-10 11:17:58 -07001184 os_free(data->check_cert_subject);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001185 os_free(data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001186}
1187
1188
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07001189#ifndef OPENSSL_NO_ENGINE
1190
1191/* Cryptoki return values */
1192#define CKR_PIN_INCORRECT 0x000000a0
1193#define CKR_PIN_INVALID 0x000000a1
1194#define CKR_PIN_LEN_RANGE 0x000000a2
1195
1196/* libp11 */
1197#define ERR_LIB_PKCS11 ERR_LIB_USER
1198
1199static int tls_is_pin_error(unsigned int err)
1200{
1201 return ERR_GET_LIB(err) == ERR_LIB_PKCS11 &&
1202 (ERR_GET_REASON(err) == CKR_PIN_INCORRECT ||
1203 ERR_GET_REASON(err) == CKR_PIN_INVALID ||
1204 ERR_GET_REASON(err) == CKR_PIN_LEN_RANGE);
1205}
1206
1207#endif /* OPENSSL_NO_ENGINE */
1208
1209
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001210#ifdef ANDROID
1211/* EVP_PKEY_from_keystore comes from system/security/keystore-engine. */
1212EVP_PKEY * EVP_PKEY_from_keystore(const char *key_id);
1213#endif /* ANDROID */
1214
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001215static int tls_engine_init(struct tls_connection *conn, const char *engine_id,
1216 const char *pin, const char *key_id,
1217 const char *cert_id, const char *ca_cert_id)
1218{
Adam Langley1eb02ed2015-04-21 19:00:05 -07001219#if defined(ANDROID) && defined(OPENSSL_IS_BORINGSSL)
1220#if !defined(OPENSSL_NO_ENGINE)
1221#error "This code depends on OPENSSL_NO_ENGINE being defined by BoringSSL."
1222#endif
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001223 if (!key_id)
1224 return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
Adam Langley1eb02ed2015-04-21 19:00:05 -07001225 conn->engine = NULL;
1226 conn->private_key = EVP_PKEY_from_keystore(key_id);
1227 if (!conn->private_key) {
1228 wpa_printf(MSG_ERROR,
1229 "ENGINE: cannot load private key with id '%s' [%s]",
1230 key_id,
1231 ERR_error_string(ERR_get_error(), NULL));
1232 return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
1233 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001234#endif /* ANDROID && OPENSSL_IS_BORINGSSL */
Adam Langley1eb02ed2015-04-21 19:00:05 -07001235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236#ifndef OPENSSL_NO_ENGINE
1237 int ret = -1;
1238 if (engine_id == NULL) {
1239 wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set");
1240 return -1;
1241 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001242
1243 ERR_clear_error();
Kenny Rootdb3c5a42012-03-20 17:00:47 -07001244#ifdef ANDROID
1245 ENGINE_load_dynamic();
1246#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001247 conn->engine = ENGINE_by_id(engine_id);
1248 if (!conn->engine) {
1249 wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]",
1250 engine_id, ERR_error_string(ERR_get_error(), NULL));
1251 goto err;
1252 }
1253 if (ENGINE_init(conn->engine) != 1) {
1254 wpa_printf(MSG_ERROR, "ENGINE: engine init failed "
1255 "(engine: %s) [%s]", engine_id,
1256 ERR_error_string(ERR_get_error(), NULL));
1257 goto err;
1258 }
1259 wpa_printf(MSG_DEBUG, "ENGINE: engine initialized");
1260
Kenny Rootdb3c5a42012-03-20 17:00:47 -07001261#ifndef ANDROID
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001262 if (pin && ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001263 wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]",
1264 ERR_error_string(ERR_get_error(), NULL));
1265 goto err;
1266 }
Kenny Rootdb3c5a42012-03-20 17:00:47 -07001267#endif
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001268 if (key_id) {
1269 /*
1270 * Ensure that the ENGINE does not attempt to use the OpenSSL
1271 * UI system to obtain a PIN, if we didn't provide one.
1272 */
1273 struct {
1274 const void *password;
1275 const char *prompt_info;
1276 } key_cb = { "", NULL };
1277
1278 /* load private key first in-case PIN is required for cert */
1279 conn->private_key = ENGINE_load_private_key(conn->engine,
1280 key_id, NULL,
1281 &key_cb);
1282 if (!conn->private_key) {
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07001283 unsigned long err = ERR_get_error();
1284
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001285 wpa_printf(MSG_ERROR,
1286 "ENGINE: cannot load private key with id '%s' [%s]",
1287 key_id,
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07001288 ERR_error_string(err, NULL));
1289 if (tls_is_pin_error(err))
1290 ret = TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN;
1291 else
1292 ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001293 goto err;
1294 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001295 }
1296
1297 /* handle a certificate and/or CA certificate */
1298 if (cert_id || ca_cert_id) {
1299 const char *cmd_name = "LOAD_CERT_CTRL";
1300
1301 /* test if the engine supports a LOAD_CERT_CTRL */
1302 if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
1303 0, (void *)cmd_name, NULL)) {
1304 wpa_printf(MSG_ERROR, "ENGINE: engine does not support"
1305 " loading certificates");
1306 ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
1307 goto err;
1308 }
1309 }
1310
1311 return 0;
1312
1313err:
1314 if (conn->engine) {
1315 ENGINE_free(conn->engine);
1316 conn->engine = NULL;
1317 }
1318
1319 if (conn->private_key) {
1320 EVP_PKEY_free(conn->private_key);
1321 conn->private_key = NULL;
1322 }
1323
1324 return ret;
1325#else /* OPENSSL_NO_ENGINE */
1326 return 0;
1327#endif /* OPENSSL_NO_ENGINE */
1328}
1329
1330
1331static void tls_engine_deinit(struct tls_connection *conn)
1332{
Adam Langley1eb02ed2015-04-21 19:00:05 -07001333#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001334 wpa_printf(MSG_DEBUG, "ENGINE: engine deinit");
1335 if (conn->private_key) {
1336 EVP_PKEY_free(conn->private_key);
1337 conn->private_key = NULL;
1338 }
1339 if (conn->engine) {
Adam Langley1eb02ed2015-04-21 19:00:05 -07001340#if !defined(OPENSSL_IS_BORINGSSL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001341 ENGINE_finish(conn->engine);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001342#endif /* !OPENSSL_IS_BORINGSSL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001343 conn->engine = NULL;
1344 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001345#endif /* ANDROID || !OPENSSL_NO_ENGINE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346}
1347
1348
1349int tls_get_errors(void *ssl_ctx)
1350{
1351 int count = 0;
1352 unsigned long err;
1353
1354 while ((err = ERR_get_error())) {
1355 wpa_printf(MSG_INFO, "TLS - SSL error: %s",
1356 ERR_error_string(err, NULL));
1357 count++;
1358 }
1359
1360 return count;
1361}
1362
Jouni Malinen26af48b2014-04-09 13:02:53 +03001363
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001364static const char * openssl_content_type(int content_type)
1365{
1366 switch (content_type) {
1367 case 20:
1368 return "change cipher spec";
1369 case 21:
1370 return "alert";
1371 case 22:
1372 return "handshake";
1373 case 23:
1374 return "application data";
1375 case 24:
1376 return "heartbeat";
1377 case 256:
1378 return "TLS header info"; /* pseudo content type */
Hai Shalom81f62d82019-07-22 12:10:00 -07001379 case 257:
1380 return "inner content type"; /* pseudo content type */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001381 default:
1382 return "?";
1383 }
1384}
1385
1386
1387static const char * openssl_handshake_type(int content_type, const u8 *buf,
1388 size_t len)
1389{
Hai Shalom81f62d82019-07-22 12:10:00 -07001390 if (content_type == 257 && buf && len == 1)
1391 return openssl_content_type(buf[0]);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001392 if (content_type != 22 || !buf || len == 0)
1393 return "";
1394 switch (buf[0]) {
1395 case 0:
1396 return "hello request";
1397 case 1:
1398 return "client hello";
1399 case 2:
1400 return "server hello";
Hai Shalom74f70d42019-02-11 14:42:39 -08001401 case 3:
1402 return "hello verify request";
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001403 case 4:
1404 return "new session ticket";
Hai Shalom74f70d42019-02-11 14:42:39 -08001405 case 5:
1406 return "end of early data";
1407 case 6:
1408 return "hello retry request";
1409 case 8:
1410 return "encrypted extensions";
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001411 case 11:
1412 return "certificate";
1413 case 12:
1414 return "server key exchange";
1415 case 13:
1416 return "certificate request";
1417 case 14:
1418 return "server hello done";
1419 case 15:
1420 return "certificate verify";
1421 case 16:
1422 return "client key exchange";
1423 case 20:
1424 return "finished";
1425 case 21:
1426 return "certificate url";
1427 case 22:
1428 return "certificate status";
Hai Shalom74f70d42019-02-11 14:42:39 -08001429 case 23:
1430 return "supplemental data";
1431 case 24:
1432 return "key update";
1433 case 254:
1434 return "message hash";
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001435 default:
1436 return "?";
1437 }
1438}
1439
1440
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001441#ifdef CONFIG_SUITEB
1442
1443static void check_server_hello(struct tls_connection *conn,
1444 const u8 *pos, const u8 *end)
1445{
1446 size_t payload_len, id_len;
1447
1448 /*
1449 * Parse ServerHello to get the selected cipher suite since OpenSSL does
1450 * not make it cleanly available during handshake and we need to know
1451 * whether DHE was selected.
1452 */
1453
1454 if (end - pos < 3)
1455 return;
1456 payload_len = WPA_GET_BE24(pos);
1457 pos += 3;
1458
1459 if ((size_t) (end - pos) < payload_len)
1460 return;
1461 end = pos + payload_len;
1462
1463 /* Skip Version and Random */
1464 if (end - pos < 2 + SSL3_RANDOM_SIZE)
1465 return;
1466 pos += 2 + SSL3_RANDOM_SIZE;
1467
1468 /* Skip Session ID */
1469 if (end - pos < 1)
1470 return;
1471 id_len = *pos++;
1472 if ((size_t) (end - pos) < id_len)
1473 return;
1474 pos += id_len;
1475
1476 if (end - pos < 2)
1477 return;
1478 conn->cipher_suite = WPA_GET_BE16(pos);
1479 wpa_printf(MSG_DEBUG, "OpenSSL: Server selected cipher suite 0x%x",
1480 conn->cipher_suite);
1481}
1482
1483
1484static void check_server_key_exchange(SSL *ssl, struct tls_connection *conn,
1485 const u8 *pos, const u8 *end)
1486{
1487 size_t payload_len;
1488 u16 dh_len;
1489 BIGNUM *p;
1490 int bits;
1491
1492 if (!(conn->flags & TLS_CONN_SUITEB))
1493 return;
1494
1495 /* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */
1496 if (conn->cipher_suite != 0x9f)
1497 return;
1498
1499 if (end - pos < 3)
1500 return;
1501 payload_len = WPA_GET_BE24(pos);
1502 pos += 3;
1503
1504 if ((size_t) (end - pos) < payload_len)
1505 return;
1506 end = pos + payload_len;
1507
1508 if (end - pos < 2)
1509 return;
1510 dh_len = WPA_GET_BE16(pos);
1511 pos += 2;
1512
1513 if ((size_t) (end - pos) < dh_len)
1514 return;
1515 p = BN_bin2bn(pos, dh_len, NULL);
1516 if (!p)
1517 return;
1518
1519 bits = BN_num_bits(p);
1520 BN_free(p);
1521
1522 conn->server_dh_prime_len = bits;
1523 wpa_printf(MSG_DEBUG, "OpenSSL: Server DH prime length: %d bits",
1524 conn->server_dh_prime_len);
1525}
1526
1527#endif /* CONFIG_SUITEB */
1528
1529
Jouni Malinen26af48b2014-04-09 13:02:53 +03001530static void tls_msg_cb(int write_p, int version, int content_type,
1531 const void *buf, size_t len, SSL *ssl, void *arg)
1532{
1533 struct tls_connection *conn = arg;
1534 const u8 *pos = buf;
1535
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001536 if (write_p == 2) {
1537 wpa_printf(MSG_DEBUG,
1538 "OpenSSL: session ver=0x%x content_type=%d",
1539 version, content_type);
1540 wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Data", buf, len);
1541 return;
1542 }
1543
1544 wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d (%s/%s)",
1545 write_p ? "TX" : "RX", version, content_type,
1546 openssl_content_type(content_type),
1547 openssl_handshake_type(content_type, buf, len));
Jouni Malinen26af48b2014-04-09 13:02:53 +03001548 wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len);
1549 if (content_type == 24 && len >= 3 && pos[0] == 1) {
1550 size_t payload_len = WPA_GET_BE16(pos + 1);
1551 if (payload_len + 3 > len) {
1552 wpa_printf(MSG_ERROR, "OpenSSL: Heartbeat attack detected");
1553 conn->invalid_hb_used = 1;
1554 }
1555 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001556
1557#ifdef CONFIG_SUITEB
1558 /*
1559 * Need to parse these handshake messages to be able to check DH prime
1560 * length since OpenSSL does not expose the new cipher suite and DH
1561 * parameters during handshake (e.g., for cert_cb() callback).
1562 */
1563 if (content_type == 22 && pos && len > 0 && pos[0] == 2)
1564 check_server_hello(conn, pos + 1, pos + len);
1565 if (content_type == 22 && pos && len > 0 && pos[0] == 12)
1566 check_server_key_exchange(ssl, conn, pos + 1, pos + len);
1567#endif /* CONFIG_SUITEB */
Jouni Malinen26af48b2014-04-09 13:02:53 +03001568}
1569
1570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001571struct tls_connection * tls_connection_init(void *ssl_ctx)
1572{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001573 struct tls_data *data = ssl_ctx;
1574 SSL_CTX *ssl = data->ssl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575 struct tls_connection *conn;
1576 long options;
Hai Shalom74f70d42019-02-11 14:42:39 -08001577 X509_STORE *new_cert_store;
1578 struct os_reltime now;
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001579 struct tls_context *context = SSL_CTX_get_app_data(ssl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580
Hai Shalom74f70d42019-02-11 14:42:39 -08001581 /* Replace X509 store if it is time to update CRL. */
1582 if (data->crl_reload_interval > 0 && os_get_reltime(&now) == 0 &&
1583 os_reltime_expired(&now, &data->crl_last_reload,
1584 data->crl_reload_interval)) {
1585 wpa_printf(MSG_INFO,
1586 "OpenSSL: Flushing X509 store with ca_cert file");
1587 new_cert_store = tls_crl_cert_reload(data->ca_cert,
1588 data->check_crl);
1589 if (!new_cert_store) {
1590 wpa_printf(MSG_ERROR,
1591 "OpenSSL: Error replacing X509 store with ca_cert file");
1592 } else {
1593 /* Replace old store */
1594 SSL_CTX_set_cert_store(ssl, new_cert_store);
1595 data->crl_last_reload = now;
1596 }
1597 }
1598
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001599 conn = os_zalloc(sizeof(*conn));
1600 if (conn == NULL)
1601 return NULL;
Hai Shalom74f70d42019-02-11 14:42:39 -08001602 conn->data = data;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001603 conn->ssl_ctx = ssl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604 conn->ssl = SSL_new(ssl);
1605 if (conn->ssl == NULL) {
1606 tls_show_errors(MSG_INFO, __func__,
1607 "Failed to initialize new SSL connection");
1608 os_free(conn);
1609 return NULL;
1610 }
1611
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001612 conn->context = context;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001613 SSL_set_app_data(conn->ssl, conn);
Jouni Malinen26af48b2014-04-09 13:02:53 +03001614 SSL_set_msg_callback(conn->ssl, tls_msg_cb);
1615 SSL_set_msg_callback_arg(conn->ssl, conn);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001616 options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
1617 SSL_OP_SINGLE_DH_USE;
1618#ifdef SSL_OP_NO_COMPRESSION
1619 options |= SSL_OP_NO_COMPRESSION;
1620#endif /* SSL_OP_NO_COMPRESSION */
1621 SSL_set_options(conn->ssl, options);
Hai Shalom81f62d82019-07-22 12:10:00 -07001622#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT
1623 /* Hopefully there is no need for middlebox compatibility mechanisms
1624 * when going through EAP authentication. */
1625 SSL_clear_options(conn->ssl, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
1626#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001627
1628 conn->ssl_in = BIO_new(BIO_s_mem());
1629 if (!conn->ssl_in) {
1630 tls_show_errors(MSG_INFO, __func__,
1631 "Failed to create a new BIO for ssl_in");
1632 SSL_free(conn->ssl);
1633 os_free(conn);
1634 return NULL;
1635 }
1636
1637 conn->ssl_out = BIO_new(BIO_s_mem());
1638 if (!conn->ssl_out) {
1639 tls_show_errors(MSG_INFO, __func__,
1640 "Failed to create a new BIO for ssl_out");
1641 SSL_free(conn->ssl);
1642 BIO_free(conn->ssl_in);
1643 os_free(conn);
1644 return NULL;
1645 }
1646
1647 SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out);
1648
1649 return conn;
1650}
1651
1652
1653void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
1654{
1655 if (conn == NULL)
1656 return;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001657 if (conn->success_data) {
1658 /*
1659 * Make sure ssl_clear_bad_session() does not remove this
1660 * session.
1661 */
1662 SSL_set_quiet_shutdown(conn->ssl, 1);
1663 SSL_shutdown(conn->ssl);
1664 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001665 SSL_free(conn->ssl);
1666 tls_engine_deinit(conn);
1667 os_free(conn->subject_match);
1668 os_free(conn->altsubject_match);
Dmitry Shmidt051af732013-10-22 13:52:46 -07001669 os_free(conn->suffix_match);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001670 os_free(conn->domain_match);
Hai Shalom021b0b52019-04-10 11:17:58 -07001671 os_free(conn->check_cert_subject);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001672 os_free(conn->session_ticket);
Hai Shalom899fcc72020-10-19 14:38:18 -07001673 os_free(conn->peer_subject);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001674 os_free(conn);
1675}
1676
1677
1678int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
1679{
1680 return conn ? SSL_is_init_finished(conn->ssl) : 0;
1681}
1682
1683
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001684char * tls_connection_peer_serial_num(void *tls_ctx,
1685 struct tls_connection *conn)
1686{
1687 ASN1_INTEGER *ser;
1688 char *serial_num;
1689 size_t len;
1690
1691 if (!conn->peer_cert)
1692 return NULL;
1693
1694 ser = X509_get_serialNumber(conn->peer_cert);
1695 if (!ser)
1696 return NULL;
1697
1698 len = ASN1_STRING_length(ser) * 2 + 1;
1699 serial_num = os_malloc(len);
1700 if (!serial_num)
1701 return NULL;
1702 wpa_snprintf_hex_uppercase(serial_num, len,
1703 ASN1_STRING_get0_data(ser),
1704 ASN1_STRING_length(ser));
1705 return serial_num;
1706}
1707
1708
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001709int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
1710{
1711 if (conn == NULL)
1712 return -1;
1713
1714 /* Shutdown previous TLS connection without notifying the peer
1715 * because the connection was already terminated in practice
1716 * and "close notify" shutdown alert would confuse AS. */
1717 SSL_set_quiet_shutdown(conn->ssl, 1);
1718 SSL_shutdown(conn->ssl);
Jouni Malinenf291c682015-08-17 22:50:41 +03001719 return SSL_clear(conn->ssl) == 1 ? 0 : -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720}
1721
1722
1723static int tls_match_altsubject_component(X509 *cert, int type,
1724 const char *value, size_t len)
1725{
1726 GENERAL_NAME *gen;
1727 void *ext;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001728 int found = 0;
1729 stack_index_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730
1731 ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1732
1733 for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
1734 gen = sk_GENERAL_NAME_value(ext, i);
1735 if (gen->type != type)
1736 continue;
1737 if (os_strlen((char *) gen->d.ia5->data) == len &&
1738 os_memcmp(value, gen->d.ia5->data, len) == 0)
1739 found++;
1740 }
1741
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001742 sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
1743
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744 return found;
1745}
1746
1747
1748static int tls_match_altsubject(X509 *cert, const char *match)
1749{
1750 int type;
1751 const char *pos, *end;
1752 size_t len;
1753
1754 pos = match;
1755 do {
1756 if (os_strncmp(pos, "EMAIL:", 6) == 0) {
1757 type = GEN_EMAIL;
1758 pos += 6;
1759 } else if (os_strncmp(pos, "DNS:", 4) == 0) {
1760 type = GEN_DNS;
1761 pos += 4;
1762 } else if (os_strncmp(pos, "URI:", 4) == 0) {
1763 type = GEN_URI;
1764 pos += 4;
1765 } else {
1766 wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName "
1767 "match '%s'", pos);
1768 return 0;
1769 }
1770 end = os_strchr(pos, ';');
1771 while (end) {
1772 if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||
1773 os_strncmp(end + 1, "DNS:", 4) == 0 ||
1774 os_strncmp(end + 1, "URI:", 4) == 0)
1775 break;
1776 end = os_strchr(end + 1, ';');
1777 }
1778 if (end)
1779 len = end - pos;
1780 else
1781 len = os_strlen(pos);
1782 if (tls_match_altsubject_component(cert, type, pos, len) > 0)
1783 return 1;
1784 pos = end + 1;
1785 } while (end);
1786
1787 return 0;
1788}
1789
1790
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08001791#ifndef CONFIG_NATIVE_WINDOWS
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001792static int domain_suffix_match(const u8 *val, size_t len, const char *match,
Hai Shalom021b0b52019-04-10 11:17:58 -07001793 size_t match_len, int full)
Dmitry Shmidt051af732013-10-22 13:52:46 -07001794{
Hai Shalom021b0b52019-04-10 11:17:58 -07001795 size_t i;
Dmitry Shmidt051af732013-10-22 13:52:46 -07001796
1797 /* Check for embedded nuls that could mess up suffix matching */
1798 for (i = 0; i < len; i++) {
1799 if (val[i] == '\0') {
1800 wpa_printf(MSG_DEBUG, "TLS: Embedded null in a string - reject");
1801 return 0;
1802 }
1803 }
1804
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001805 if (match_len > len || (full && match_len != len))
Dmitry Shmidt051af732013-10-22 13:52:46 -07001806 return 0;
1807
1808 if (os_strncasecmp((const char *) val + len - match_len, match,
1809 match_len) != 0)
1810 return 0; /* no match */
1811
1812 if (match_len == len)
1813 return 1; /* exact match */
1814
1815 if (val[len - match_len - 1] == '.')
1816 return 1; /* full label match completes suffix match */
1817
1818 wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match");
1819 return 0;
1820}
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08001821#endif /* CONFIG_NATIVE_WINDOWS */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001822
1823
Hai Shalom021b0b52019-04-10 11:17:58 -07001824struct tls_dn_field_order_cnt {
1825 u8 cn;
1826 u8 c;
1827 u8 l;
1828 u8 st;
1829 u8 o;
1830 u8 ou;
1831 u8 email;
1832};
1833
1834
1835static int get_dn_field_index(const struct tls_dn_field_order_cnt *dn_cnt,
1836 int nid)
Dmitry Shmidt051af732013-10-22 13:52:46 -07001837{
Hai Shalom021b0b52019-04-10 11:17:58 -07001838 switch (nid) {
1839 case NID_commonName:
1840 return dn_cnt->cn;
1841 case NID_countryName:
1842 return dn_cnt->c;
1843 case NID_localityName:
1844 return dn_cnt->l;
1845 case NID_stateOrProvinceName:
1846 return dn_cnt->st;
1847 case NID_organizationName:
1848 return dn_cnt->o;
1849 case NID_organizationalUnitName:
1850 return dn_cnt->ou;
1851 case NID_pkcs9_emailAddress:
1852 return dn_cnt->email;
1853 default:
1854 wpa_printf(MSG_ERROR,
1855 "TLS: Unknown NID '%d' in check_cert_subject",
1856 nid);
1857 return -1;
1858 }
1859}
1860
1861
1862/**
1863 * match_dn_field - Match configuration DN field against Certificate DN field
1864 * @cert: Certificate
1865 * @nid: NID of DN field
1866 * @field: Field name
1867 * @value DN field value which is passed from configuration
1868 * e.g., if configuration have C=US and this argument will point to US.
1869 * @dn_cnt: DN matching context
1870 * Returns: 1 on success and 0 on failure
1871 */
1872static int match_dn_field(const X509 *cert, int nid, const char *field,
1873 const char *value,
1874 const struct tls_dn_field_order_cnt *dn_cnt)
1875{
1876 int i, ret = 0, len, config_dn_field_index, match_index = 0;
1877 X509_NAME *name;
1878
1879 len = os_strlen(value);
1880 name = X509_get_subject_name((X509 *) cert);
1881
1882 /* Assign incremented cnt for every field of DN to check DN field in
1883 * right order */
1884 config_dn_field_index = get_dn_field_index(dn_cnt, nid);
1885 if (config_dn_field_index < 0)
1886 return 0;
1887
1888 /* Fetch value based on NID */
1889 for (i = -1; (i = X509_NAME_get_index_by_NID(name, nid, i)) > -1;) {
1890 X509_NAME_ENTRY *e;
1891 ASN1_STRING *cn;
1892
1893 e = X509_NAME_get_entry(name, i);
1894 if (!e)
1895 continue;
1896
1897 cn = X509_NAME_ENTRY_get_data(e);
1898 if (!cn)
1899 continue;
1900
1901 match_index++;
1902
1903 /* check for more than one DN field with same name */
1904 if (match_index != config_dn_field_index)
1905 continue;
1906
1907 /* Check wildcard at the right end side */
1908 /* E.g., if OU=develop* mentioned in configuration, allow 'OU'
1909 * of the subject in the client certificate to start with
1910 * 'develop' */
1911 if (len > 0 && value[len - 1] == '*') {
1912 /* Compare actual certificate DN field value with
1913 * configuration DN field value up to the specified
1914 * length. */
1915 ret = ASN1_STRING_length(cn) >= len - 1 &&
1916 os_memcmp(ASN1_STRING_get0_data(cn), value,
1917 len - 1) == 0;
1918 } else {
1919 /* Compare actual certificate DN field value with
1920 * configuration DN field value */
1921 ret = ASN1_STRING_length(cn) == len &&
1922 os_memcmp(ASN1_STRING_get0_data(cn), value,
1923 len) == 0;
1924 }
1925 if (!ret) {
1926 wpa_printf(MSG_ERROR,
1927 "OpenSSL: Failed to match %s '%s' with certificate DN field value '%s'",
1928 field, value, ASN1_STRING_get0_data(cn));
1929 }
1930 break;
1931 }
1932
1933 return ret;
1934}
1935
1936
1937/**
1938 * get_value_from_field - Get value from DN field
1939 * @cert: Certificate
1940 * @field_str: DN field string which is passed from configuration file (e.g.,
1941 * C=US)
1942 * @dn_cnt: DN matching context
1943 * Returns: 1 on success and 0 on failure
1944 */
1945static int get_value_from_field(const X509 *cert, char *field_str,
1946 struct tls_dn_field_order_cnt *dn_cnt)
1947{
1948 int nid;
1949 char *context = NULL, *name, *value;
1950
1951 if (os_strcmp(field_str, "*") == 0)
1952 return 1; /* wildcard matches everything */
1953
1954 name = str_token(field_str, "=", &context);
1955 if (!name)
1956 return 0;
1957
1958 /* Compare all configured DN fields and assign nid based on that to
1959 * fetch correct value from certificate subject */
1960 if (os_strcmp(name, "CN") == 0) {
1961 nid = NID_commonName;
1962 dn_cnt->cn++;
1963 } else if(os_strcmp(name, "C") == 0) {
1964 nid = NID_countryName;
1965 dn_cnt->c++;
1966 } else if (os_strcmp(name, "L") == 0) {
1967 nid = NID_localityName;
1968 dn_cnt->l++;
1969 } else if (os_strcmp(name, "ST") == 0) {
1970 nid = NID_stateOrProvinceName;
1971 dn_cnt->st++;
1972 } else if (os_strcmp(name, "O") == 0) {
1973 nid = NID_organizationName;
1974 dn_cnt->o++;
1975 } else if (os_strcmp(name, "OU") == 0) {
1976 nid = NID_organizationalUnitName;
1977 dn_cnt->ou++;
1978 } else if (os_strcmp(name, "emailAddress") == 0) {
1979 nid = NID_pkcs9_emailAddress;
1980 dn_cnt->email++;
1981 } else {
1982 wpa_printf(MSG_ERROR,
1983 "TLS: Unknown field '%s' in check_cert_subject", name);
1984 return 0;
1985 }
1986
1987 value = str_token(field_str, "=", &context);
1988 if (!value) {
1989 wpa_printf(MSG_ERROR,
1990 "TLS: Distinguished Name field '%s' value is not defined in check_cert_subject",
1991 name);
1992 return 0;
1993 }
1994
1995 return match_dn_field(cert, nid, name, value, dn_cnt);
1996}
1997
1998
1999/**
2000 * tls_match_dn_field - Match subject DN field with check_cert_subject
2001 * @cert: Certificate
2002 * @match: check_cert_subject string
2003 * Returns: Return 1 on success and 0 on failure
2004*/
2005static int tls_match_dn_field(X509 *cert, const char *match)
2006{
2007 const char *token, *last = NULL;
2008 char field[256];
2009 struct tls_dn_field_order_cnt dn_cnt;
2010
2011 os_memset(&dn_cnt, 0, sizeof(dn_cnt));
2012
2013 /* Maximum length of each DN field is 255 characters */
2014
2015 /* Process each '/' delimited field */
2016 while ((token = cstr_token(match, "/", &last))) {
2017 if (last - token >= (int) sizeof(field)) {
2018 wpa_printf(MSG_ERROR,
2019 "OpenSSL: Too long DN matching field value in '%s'",
2020 match);
2021 return 0;
2022 }
2023 os_memcpy(field, token, last - token);
2024 field[last - token] = '\0';
2025
2026 if (!get_value_from_field(cert, field, &dn_cnt)) {
2027 wpa_printf(MSG_DEBUG, "OpenSSL: No match for DN '%s'",
2028 field);
2029 return 0;
2030 }
2031 }
2032
2033 return 1;
2034}
2035
2036
2037#ifndef CONFIG_NATIVE_WINDOWS
2038static int tls_match_suffix_helper(X509 *cert, const char *match,
2039 size_t match_len, int full)
2040{
Dmitry Shmidt051af732013-10-22 13:52:46 -07002041 GENERAL_NAME *gen;
2042 void *ext;
2043 int i;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002044 stack_index_t j;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002045 int dns_name = 0;
2046 X509_NAME *name;
2047
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002048 wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s",
2049 full ? "": "suffix ", match);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002050
2051 ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
2052
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002053 for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
2054 gen = sk_GENERAL_NAME_value(ext, j);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002055 if (gen->type != GEN_DNS)
2056 continue;
2057 dns_name++;
2058 wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
2059 gen->d.dNSName->data,
2060 gen->d.dNSName->length);
2061 if (domain_suffix_match(gen->d.dNSName->data,
Hai Shalom021b0b52019-04-10 11:17:58 -07002062 gen->d.dNSName->length,
2063 match, match_len, full) == 1) {
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002064 wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
2065 full ? "Match" : "Suffix match");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002066 sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002067 return 1;
2068 }
2069 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002070 sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002071
2072 if (dns_name) {
2073 wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
2074 return 0;
2075 }
2076
2077 name = X509_get_subject_name(cert);
2078 i = -1;
2079 for (;;) {
2080 X509_NAME_ENTRY *e;
2081 ASN1_STRING *cn;
2082
2083 i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
2084 if (i == -1)
2085 break;
2086 e = X509_NAME_get_entry(name, i);
2087 if (e == NULL)
2088 continue;
2089 cn = X509_NAME_ENTRY_get_data(e);
2090 if (cn == NULL)
2091 continue;
2092 wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
2093 cn->data, cn->length);
Hai Shalom021b0b52019-04-10 11:17:58 -07002094 if (domain_suffix_match(cn->data, cn->length,
2095 match, match_len, full) == 1) {
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002096 wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
2097 full ? "Match" : "Suffix match");
Dmitry Shmidt051af732013-10-22 13:52:46 -07002098 return 1;
2099 }
2100 }
2101
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002102 wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found",
2103 full ? "": "suffix ");
Dmitry Shmidt051af732013-10-22 13:52:46 -07002104 return 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07002105}
2106#endif /* CONFIG_NATIVE_WINDOWS */
2107
2108
2109static int tls_match_suffix(X509 *cert, const char *match, int full)
2110{
2111#ifdef CONFIG_NATIVE_WINDOWS
2112 /* wincrypt.h has conflicting X509_NAME definition */
2113 return -1;
2114#else /* CONFIG_NATIVE_WINDOWS */
2115 const char *token, *last = NULL;
2116
2117 /* Process each match alternative separately until a match is found */
2118 while ((token = cstr_token(match, ";", &last))) {
2119 if (tls_match_suffix_helper(cert, token, last - token, full))
2120 return 1;
2121 }
2122
2123 return 0;
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08002124#endif /* CONFIG_NATIVE_WINDOWS */
Dmitry Shmidt051af732013-10-22 13:52:46 -07002125}
2126
2127
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002128static enum tls_fail_reason openssl_tls_fail_reason(int err)
2129{
2130 switch (err) {
2131 case X509_V_ERR_CERT_REVOKED:
2132 return TLS_FAIL_REVOKED;
2133 case X509_V_ERR_CERT_NOT_YET_VALID:
2134 case X509_V_ERR_CRL_NOT_YET_VALID:
2135 return TLS_FAIL_NOT_YET_VALID;
2136 case X509_V_ERR_CERT_HAS_EXPIRED:
2137 case X509_V_ERR_CRL_HAS_EXPIRED:
2138 return TLS_FAIL_EXPIRED;
2139 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
2140 case X509_V_ERR_UNABLE_TO_GET_CRL:
2141 case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
2142 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
2143 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2144 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2145 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2146 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
2147 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
2148 case X509_V_ERR_INVALID_CA:
2149 return TLS_FAIL_UNTRUSTED;
2150 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
2151 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
2152 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
2153 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
2154 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
2155 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
2156 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
2157 case X509_V_ERR_CERT_UNTRUSTED:
2158 case X509_V_ERR_CERT_REJECTED:
2159 return TLS_FAIL_BAD_CERTIFICATE;
2160 default:
2161 return TLS_FAIL_UNSPECIFIED;
2162 }
2163}
2164
2165
2166static struct wpabuf * get_x509_cert(X509 *cert)
2167{
2168 struct wpabuf *buf;
2169 u8 *tmp;
2170
2171 int cert_len = i2d_X509(cert, NULL);
2172 if (cert_len <= 0)
2173 return NULL;
2174
2175 buf = wpabuf_alloc(cert_len);
2176 if (buf == NULL)
2177 return NULL;
2178
2179 tmp = wpabuf_put(buf, cert_len);
2180 i2d_X509(cert, &tmp);
2181 return buf;
2182}
2183
2184
2185static void openssl_tls_fail_event(struct tls_connection *conn,
2186 X509 *err_cert, int err, int depth,
2187 const char *subject, const char *err_str,
2188 enum tls_fail_reason reason)
2189{
2190 union tls_event_data ev;
2191 struct wpabuf *cert = NULL;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002192 struct tls_context *context = conn->context;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002193
Pavel Grafov4d8552e2018-02-06 11:28:29 +00002194#ifdef ANDROID
2195 log_cert_validation_failure(err_str);
2196#endif
2197
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002198 if (context->event_cb == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002199 return;
2200
2201 cert = get_x509_cert(err_cert);
2202 os_memset(&ev, 0, sizeof(ev));
2203 ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ?
2204 reason : openssl_tls_fail_reason(err);
2205 ev.cert_fail.depth = depth;
2206 ev.cert_fail.subject = subject;
2207 ev.cert_fail.reason_txt = err_str;
2208 ev.cert_fail.cert = cert;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002209 context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002210 wpabuf_free(cert);
2211}
2212
2213
Hai Shalom81f62d82019-07-22 12:10:00 -07002214static int openssl_cert_tod(X509 *cert)
2215{
2216 CERTIFICATEPOLICIES *ext;
2217 stack_index_t i;
2218 char buf[100];
2219 int res;
2220 int tod = 0;
2221
2222 ext = X509_get_ext_d2i(cert, NID_certificate_policies, NULL, NULL);
2223 if (!ext)
2224 return 0;
2225
2226 for (i = 0; i < sk_POLICYINFO_num(ext); i++) {
2227 POLICYINFO *policy;
2228
2229 policy = sk_POLICYINFO_value(ext, i);
2230 res = OBJ_obj2txt(buf, sizeof(buf), policy->policyid, 0);
2231 if (res < 0 || (size_t) res >= sizeof(buf))
2232 continue;
2233 wpa_printf(MSG_DEBUG, "OpenSSL: Certificate Policy %s", buf);
2234 if (os_strcmp(buf, "1.3.6.1.4.1.40808.1.3.1") == 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002235 tod = 1; /* TOD-STRICT */
2236 else if (os_strcmp(buf, "1.3.6.1.4.1.40808.1.3.2") == 0 && !tod)
2237 tod = 2; /* TOD-TOFU */
Hai Shalom81f62d82019-07-22 12:10:00 -07002238 }
Hai Shalomfdcde762020-04-02 11:19:20 -07002239 sk_POLICYINFO_pop_free(ext, POLICYINFO_free);
Hai Shalom81f62d82019-07-22 12:10:00 -07002240
2241 return tod;
2242}
2243
2244
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002245static void openssl_tls_cert_event(struct tls_connection *conn,
2246 X509 *err_cert, int depth,
2247 const char *subject)
2248{
2249 struct wpabuf *cert = NULL;
2250 union tls_event_data ev;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002251 struct tls_context *context = conn->context;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002252 char *altsubject[TLS_MAX_ALT_SUBJECT];
2253 int alt, num_altsubject = 0;
2254 GENERAL_NAME *gen;
2255 void *ext;
2256 stack_index_t i;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002257 ASN1_INTEGER *ser;
2258 char serial_num[128];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002259#ifdef CONFIG_SHA256
2260 u8 hash[32];
2261#endif /* CONFIG_SHA256 */
2262
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002263 if (context->event_cb == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002264 return;
2265
2266 os_memset(&ev, 0, sizeof(ev));
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002267 if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) ||
2268 context->cert_in_cb) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002269 cert = get_x509_cert(err_cert);
2270 ev.peer_cert.cert = cert;
2271 }
2272#ifdef CONFIG_SHA256
2273 if (cert) {
2274 const u8 *addr[1];
2275 size_t len[1];
2276 addr[0] = wpabuf_head(cert);
2277 len[0] = wpabuf_len(cert);
2278 if (sha256_vector(1, addr, len, hash) == 0) {
2279 ev.peer_cert.hash = hash;
2280 ev.peer_cert.hash_len = sizeof(hash);
2281 }
2282 }
2283#endif /* CONFIG_SHA256 */
2284 ev.peer_cert.depth = depth;
2285 ev.peer_cert.subject = subject;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002286
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002287 ser = X509_get_serialNumber(err_cert);
2288 if (ser) {
2289 wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
2290 ASN1_STRING_get0_data(ser),
2291 ASN1_STRING_length(ser));
2292 ev.peer_cert.serial_num = serial_num;
2293 }
2294
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002295 ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
2296 for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
2297 char *pos;
2298
2299 if (num_altsubject == TLS_MAX_ALT_SUBJECT)
2300 break;
2301 gen = sk_GENERAL_NAME_value(ext, i);
2302 if (gen->type != GEN_EMAIL &&
2303 gen->type != GEN_DNS &&
2304 gen->type != GEN_URI)
2305 continue;
2306
2307 pos = os_malloc(10 + gen->d.ia5->length + 1);
2308 if (pos == NULL)
2309 break;
2310 altsubject[num_altsubject++] = pos;
2311
2312 switch (gen->type) {
2313 case GEN_EMAIL:
2314 os_memcpy(pos, "EMAIL:", 6);
2315 pos += 6;
2316 break;
2317 case GEN_DNS:
2318 os_memcpy(pos, "DNS:", 4);
2319 pos += 4;
2320 break;
2321 case GEN_URI:
2322 os_memcpy(pos, "URI:", 4);
2323 pos += 4;
2324 break;
2325 }
2326
2327 os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length);
2328 pos += gen->d.ia5->length;
2329 *pos = '\0';
2330 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002331 sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002332
2333 for (alt = 0; alt < num_altsubject; alt++)
2334 ev.peer_cert.altsubject[alt] = altsubject[alt];
2335 ev.peer_cert.num_altsubject = num_altsubject;
2336
Hai Shalom81f62d82019-07-22 12:10:00 -07002337 ev.peer_cert.tod = openssl_cert_tod(err_cert);
2338
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002339 context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340 wpabuf_free(cert);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002341 for (alt = 0; alt < num_altsubject; alt++)
2342 os_free(altsubject[alt]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002343}
2344
2345
Hai Shalomc3565922019-10-28 11:58:20 -07002346static void debug_print_cert(X509 *cert, const char *title)
2347{
2348#ifndef CONFIG_NO_STDOUT_DEBUG
2349 BIO *out;
2350 size_t rlen;
2351 char *txt;
2352 int res;
2353
2354 if (wpa_debug_level > MSG_DEBUG)
2355 return;
2356
2357 out = BIO_new(BIO_s_mem());
2358 if (!out)
2359 return;
2360
2361 X509_print(out, cert);
2362 rlen = BIO_ctrl_pending(out);
2363 txt = os_malloc(rlen + 1);
2364 if (txt) {
2365 res = BIO_read(out, txt, rlen);
2366 if (res > 0) {
2367 txt[res] = '\0';
2368 wpa_printf(MSG_DEBUG, "OpenSSL: %s\n%s", title, txt);
2369 }
2370 os_free(txt);
2371 }
2372
2373 BIO_free(out);
2374#endif /* CONFIG_NO_STDOUT_DEBUG */
2375}
2376
2377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
2379{
2380 char buf[256];
2381 X509 *err_cert;
2382 int err, depth;
2383 SSL *ssl;
2384 struct tls_connection *conn;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002385 struct tls_context *context;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002386 char *match, *altmatch, *suffix_match, *domain_match;
Hai Shalom021b0b52019-04-10 11:17:58 -07002387 const char *check_cert_subject;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002388 const char *err_str;
2389
2390 err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08002391 if (!err_cert)
2392 return 0;
2393
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002394 err = X509_STORE_CTX_get_error(x509_ctx);
2395 depth = X509_STORE_CTX_get_error_depth(x509_ctx);
2396 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
2397 SSL_get_ex_data_X509_STORE_CTX_idx());
Hai Shalomc3565922019-10-28 11:58:20 -07002398 os_snprintf(buf, sizeof(buf), "Peer certificate - depth %d", depth);
2399 debug_print_cert(err_cert, buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
2401
2402 conn = SSL_get_app_data(ssl);
2403 if (conn == NULL)
2404 return 0;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002405
2406 if (depth == 0)
2407 conn->peer_cert = err_cert;
2408 else if (depth == 1)
2409 conn->peer_issuer = err_cert;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002410 else if (depth == 2)
2411 conn->peer_issuer_issuer = err_cert;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07002412
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002413 context = conn->context;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002414 match = conn->subject_match;
2415 altmatch = conn->altsubject_match;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002416 suffix_match = conn->suffix_match;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002417 domain_match = conn->domain_match;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418
2419 if (!preverify_ok && !conn->ca_cert_verify)
2420 preverify_ok = 1;
2421 if (!preverify_ok && depth > 0 && conn->server_cert_only)
2422 preverify_ok = 1;
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07002423 if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
2424 (err == X509_V_ERR_CERT_HAS_EXPIRED ||
2425 err == X509_V_ERR_CERT_NOT_YET_VALID)) {
2426 wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity "
2427 "time mismatch");
2428 preverify_ok = 1;
2429 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002430 if (!preverify_ok && !conn->data->check_crl_strict &&
2431 (err == X509_V_ERR_CRL_HAS_EXPIRED ||
2432 err == X509_V_ERR_CRL_NOT_YET_VALID)) {
2433 wpa_printf(MSG_DEBUG,
2434 "OpenSSL: Ignore certificate validity CRL time mismatch");
2435 preverify_ok = 1;
2436 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437
2438 err_str = X509_verify_cert_error_string(err);
2439
2440#ifdef CONFIG_SHA256
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07002441 /*
2442 * Do not require preverify_ok so we can explicity allow otherwise
2443 * invalid pinned server certificates.
2444 */
2445 if (depth == 0 && conn->server_cert_only) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002446 struct wpabuf *cert;
2447 cert = get_x509_cert(err_cert);
2448 if (!cert) {
2449 wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch "
2450 "server certificate data");
2451 preverify_ok = 0;
2452 } else {
2453 u8 hash[32];
2454 const u8 *addr[1];
2455 size_t len[1];
2456 addr[0] = wpabuf_head(cert);
2457 len[0] = wpabuf_len(cert);
2458 if (sha256_vector(1, addr, len, hash) < 0 ||
2459 os_memcmp(conn->srv_cert_hash, hash, 32) != 0) {
2460 err_str = "Server certificate mismatch";
2461 err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
2462 preverify_ok = 0;
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07002463 } else if (!preverify_ok) {
2464 /*
2465 * Certificate matches pinned certificate, allow
2466 * regardless of other problems.
2467 */
2468 wpa_printf(MSG_DEBUG,
2469 "OpenSSL: Ignore validation issues for a pinned server certificate");
2470 preverify_ok = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 }
2472 wpabuf_free(cert);
2473 }
2474 }
2475#endif /* CONFIG_SHA256 */
2476
Hai Shalom81f62d82019-07-22 12:10:00 -07002477 openssl_tls_cert_event(conn, err_cert, depth, buf);
2478
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479 if (!preverify_ok) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002480 if (depth > 0) {
2481 /* Send cert event for the peer certificate so that
2482 * the upper layers get information about it even if
2483 * validation of a CA certificate fails. */
2484 STACK_OF(X509) *chain;
2485
2486 chain = X509_STORE_CTX_get1_chain(x509_ctx);
2487 if (chain && sk_X509_num(chain) > 0) {
2488 char buf2[256];
2489 X509 *cert;
2490
2491 cert = sk_X509_value(chain, 0);
2492 X509_NAME_oneline(X509_get_subject_name(cert),
2493 buf2, sizeof(buf2));
2494
2495 openssl_tls_cert_event(conn, cert, 0, buf2);
2496 }
2497 if (chain)
2498 sk_X509_pop_free(chain, X509_free);
2499 }
2500
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
2502 " error %d (%s) depth %d for '%s'", err, err_str,
2503 depth, buf);
2504 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2505 err_str, TLS_FAIL_UNSPECIFIED);
2506 return preverify_ok;
2507 }
2508
2509 wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d "
2510 "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
2511 preverify_ok, err, err_str,
2512 conn->ca_cert_verify, depth, buf);
Hai Shalom021b0b52019-04-10 11:17:58 -07002513 check_cert_subject = conn->check_cert_subject;
2514 if (!check_cert_subject)
2515 check_cert_subject = conn->data->check_cert_subject;
2516 if (check_cert_subject) {
2517 if (depth == 0 &&
2518 !tls_match_dn_field(err_cert, check_cert_subject)) {
2519 preverify_ok = 0;
2520 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2521 "Distinguished Name",
2522 TLS_FAIL_DN_MISMATCH);
2523 }
2524 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002525 if (depth == 0 && match && os_strstr(buf, match) == NULL) {
2526 wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
2527 "match with '%s'", buf, match);
2528 preverify_ok = 0;
2529 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2530 "Subject mismatch",
2531 TLS_FAIL_SUBJECT_MISMATCH);
2532 } else if (depth == 0 && altmatch &&
2533 !tls_match_altsubject(err_cert, altmatch)) {
2534 wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
2535 "'%s' not found", altmatch);
2536 preverify_ok = 0;
2537 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2538 "AltSubject mismatch",
2539 TLS_FAIL_ALTSUBJECT_MISMATCH);
Dmitry Shmidt051af732013-10-22 13:52:46 -07002540 } else if (depth == 0 && suffix_match &&
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002541 !tls_match_suffix(err_cert, suffix_match, 0)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07002542 wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
2543 suffix_match);
2544 preverify_ok = 0;
2545 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2546 "Domain suffix mismatch",
2547 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002548 } else if (depth == 0 && domain_match &&
2549 !tls_match_suffix(err_cert, domain_match, 1)) {
2550 wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
2551 domain_match);
2552 preverify_ok = 0;
2553 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2554 "Domain mismatch",
2555 TLS_FAIL_DOMAIN_MISMATCH);
Hai Shalom81f62d82019-07-22 12:10:00 -07002556 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557
2558 if (conn->cert_probe && preverify_ok && depth == 0) {
2559 wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
2560 "on probe-only run");
2561 preverify_ok = 0;
2562 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2563 "Server certificate chain probe",
2564 TLS_FAIL_SERVER_CHAIN_PROBE);
2565 }
2566
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002567#ifdef CONFIG_SUITEB
2568 if (conn->flags & TLS_CONN_SUITEB) {
2569 EVP_PKEY *pk;
2570 RSA *rsa;
2571 int len = -1;
2572
2573 pk = X509_get_pubkey(err_cert);
2574 if (pk) {
2575 rsa = EVP_PKEY_get1_RSA(pk);
2576 if (rsa) {
2577 len = RSA_bits(rsa);
2578 RSA_free(rsa);
2579 }
2580 EVP_PKEY_free(pk);
2581 }
2582
2583 if (len >= 0) {
2584 wpa_printf(MSG_DEBUG,
2585 "OpenSSL: RSA modulus size: %d bits", len);
2586 if (len < 3072) {
2587 preverify_ok = 0;
2588 openssl_tls_fail_event(
2589 conn, err_cert, err,
2590 depth, buf,
2591 "Insufficient RSA modulus size",
2592 TLS_FAIL_INSUFFICIENT_KEY_LEN);
2593 }
2594 }
2595 }
2596#endif /* CONFIG_SUITEB */
2597
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002598#ifdef OPENSSL_IS_BORINGSSL
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002599 if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) &&
2600 preverify_ok) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002601 enum ocsp_result res;
2602
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08002603 res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert,
2604 conn->peer_issuer,
2605 conn->peer_issuer_issuer);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002606 if (res == OCSP_REVOKED) {
2607 preverify_ok = 0;
2608 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2609 "certificate revoked",
2610 TLS_FAIL_REVOKED);
2611 if (err == X509_V_OK)
2612 X509_STORE_CTX_set_error(
2613 x509_ctx, X509_V_ERR_CERT_REVOKED);
2614 } else if (res != OCSP_GOOD &&
2615 (conn->flags & TLS_CONN_REQUIRE_OCSP)) {
2616 preverify_ok = 0;
2617 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
2618 "bad certificate status response",
2619 TLS_FAIL_UNSPECIFIED);
2620 }
2621 }
2622#endif /* OPENSSL_IS_BORINGSSL */
2623
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08002624 if (depth == 0 && preverify_ok && context->event_cb != NULL)
Dmitry Shmidtea69e842013-05-13 14:52:28 -07002625 context->event_cb(context->cb_ctx,
2626 TLS_CERT_CHAIN_SUCCESS, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002627
Hai Shalom899fcc72020-10-19 14:38:18 -07002628 if (depth == 0 && preverify_ok) {
2629 os_free(conn->peer_subject);
2630 conn->peer_subject = os_strdup(buf);
2631 }
2632
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 return preverify_ok;
2634}
2635
2636
2637#ifndef OPENSSL_NO_STDIO
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002638static int tls_load_ca_der(struct tls_data *data, const char *ca_cert)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002639{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002640 SSL_CTX *ssl_ctx = data->ssl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 X509_LOOKUP *lookup;
2642 int ret = 0;
2643
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002644 lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(ssl_ctx),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 X509_LOOKUP_file());
2646 if (lookup == NULL) {
2647 tls_show_errors(MSG_WARNING, __func__,
2648 "Failed add lookup for X509 store");
2649 return -1;
2650 }
2651
2652 if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) {
2653 unsigned long err = ERR_peek_error();
2654 tls_show_errors(MSG_WARNING, __func__,
2655 "Failed load CA in DER format");
2656 if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
2657 ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
2658 wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
2659 "cert already in hash table error",
2660 __func__);
2661 } else
2662 ret = -1;
2663 }
2664
2665 return ret;
2666}
2667#endif /* OPENSSL_NO_STDIO */
2668
2669
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002670static int tls_connection_ca_cert(struct tls_data *data,
2671 struct tls_connection *conn,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 const char *ca_cert, const u8 *ca_cert_blob,
2673 size_t ca_cert_blob_len, const char *ca_path)
2674{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002675 SSL_CTX *ssl_ctx = data->ssl;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002676 X509_STORE *store;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677
2678 /*
2679 * Remove previously configured trusted CA certificates before adding
2680 * new ones.
2681 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002682 store = X509_STORE_new();
2683 if (store == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
2685 "certificate store", __func__);
2686 return -1;
2687 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002688 SSL_CTX_set_cert_store(ssl_ctx, store);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689
2690 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2691 conn->ca_cert_verify = 1;
2692
2693 if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
2694 wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate "
2695 "chain");
2696 conn->cert_probe = 1;
2697 conn->ca_cert_verify = 0;
2698 return 0;
2699 }
2700
2701 if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) {
2702#ifdef CONFIG_SHA256
2703 const char *pos = ca_cert + 7;
2704 if (os_strncmp(pos, "server/sha256/", 14) != 0) {
2705 wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert "
2706 "hash value '%s'", ca_cert);
2707 return -1;
2708 }
2709 pos += 14;
2710 if (os_strlen(pos) != 32 * 2) {
2711 wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 "
2712 "hash length in ca_cert '%s'", ca_cert);
2713 return -1;
2714 }
2715 if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) {
2716 wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash "
2717 "value in ca_cert '%s'", ca_cert);
2718 return -1;
2719 }
2720 conn->server_cert_only = 1;
2721 wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server "
2722 "certificate match");
2723 return 0;
2724#else /* CONFIG_SHA256 */
2725 wpa_printf(MSG_INFO, "No SHA256 included in the build - "
2726 "cannot validate server certificate hash");
2727 return -1;
2728#endif /* CONFIG_SHA256 */
2729 }
2730
2731 if (ca_cert_blob) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002732 X509 *cert = d2i_X509(NULL,
2733 (const unsigned char **) &ca_cert_blob,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 ca_cert_blob_len);
2735 if (cert == NULL) {
Hai Shalom81f62d82019-07-22 12:10:00 -07002736 BIO *bio = BIO_new_mem_buf(ca_cert_blob,
2737 ca_cert_blob_len);
2738
2739 if (bio) {
2740 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
2741 BIO_free(bio);
2742 }
2743
2744 if (!cert) {
2745 tls_show_errors(MSG_WARNING, __func__,
2746 "Failed to parse ca_cert_blob");
2747 return -1;
2748 }
2749
2750 while (ERR_get_error()) {
2751 /* Ignore errors from DER conversion. */
2752 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002753 }
2754
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002755 if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
2756 cert)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757 unsigned long err = ERR_peek_error();
2758 tls_show_errors(MSG_WARNING, __func__,
2759 "Failed to add ca_cert_blob to "
2760 "certificate store");
2761 if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
2762 ERR_GET_REASON(err) ==
2763 X509_R_CERT_ALREADY_IN_HASH_TABLE) {
2764 wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
2765 "cert already in hash table error",
2766 __func__);
2767 } else {
2768 X509_free(cert);
2769 return -1;
2770 }
2771 }
2772 X509_free(cert);
2773 wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
2774 "to certificate store", __func__);
2775 return 0;
2776 }
2777
2778#ifdef ANDROID
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08002779 /* Single alias */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780 if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002781 if (tls_add_ca_from_keystore(SSL_CTX_get_cert_store(ssl_ctx),
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08002782 &ca_cert[11]) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 return -1;
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08002784 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2785 return 0;
2786 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002787
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08002788 /* Multiple aliases separated by space */
2789 if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) {
2790 char *aliases = os_strdup(&ca_cert[12]);
2791 const char *delim = " ";
2792 int rc = 0;
2793 char *savedptr;
2794 char *alias;
2795
2796 if (!aliases)
2797 return -1;
2798 alias = strtok_r(aliases, delim, &savedptr);
2799 for (; alias; alias = strtok_r(NULL, delim, &savedptr)) {
2800 if (tls_add_ca_from_keystore_encoded(
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002801 SSL_CTX_get_cert_store(ssl_ctx), alias)) {
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08002802 wpa_printf(MSG_WARNING,
2803 "OpenSSL: %s - Failed to add ca_cert %s from keystore",
2804 __func__, alias);
2805 rc = -1;
2806 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002807 }
2808 }
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08002809 os_free(aliases);
2810 if (rc)
2811 return rc;
2812
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002813 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
2814 return 0;
2815 }
2816#endif /* ANDROID */
2817
2818#ifdef CONFIG_NATIVE_WINDOWS
2819 if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==
2820 0) {
2821 wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from "
2822 "system certificate store");
2823 return 0;
2824 }
2825#endif /* CONFIG_NATIVE_WINDOWS */
2826
2827 if (ca_cert || ca_path) {
2828#ifndef OPENSSL_NO_STDIO
2829 if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) !=
2830 1) {
2831 tls_show_errors(MSG_WARNING, __func__,
2832 "Failed to load root certificates");
2833 if (ca_cert &&
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002834 tls_load_ca_der(data, ca_cert) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835 wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded "
2836 "DER format CA certificate",
2837 __func__);
2838 } else
2839 return -1;
2840 } else {
2841 wpa_printf(MSG_DEBUG, "TLS: Trusted root "
2842 "certificate(s) loaded");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002843 tls_get_errors(data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002844 }
2845#else /* OPENSSL_NO_STDIO */
2846 wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
2847 __func__);
2848 return -1;
2849#endif /* OPENSSL_NO_STDIO */
2850 } else {
2851 /* No ca_cert configured - do not try to verify server
2852 * certificate */
2853 conn->ca_cert_verify = 0;
2854 }
2855
2856 return 0;
2857}
2858
2859
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002860static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002861{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002862 SSL_CTX *ssl_ctx = data->ssl;
2863
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002864 if (ca_cert) {
2865 if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1)
2866 {
2867 tls_show_errors(MSG_WARNING, __func__,
2868 "Failed to load root certificates");
2869 return -1;
2870 }
2871
2872 wpa_printf(MSG_DEBUG, "TLS: Trusted root "
2873 "certificate(s) loaded");
2874
2875#ifndef OPENSSL_NO_STDIO
2876 /* Add the same CAs to the client certificate requests */
2877 SSL_CTX_set_client_CA_list(ssl_ctx,
2878 SSL_load_client_CA_file(ca_cert));
2879#endif /* OPENSSL_NO_STDIO */
Hai Shalom74f70d42019-02-11 14:42:39 -08002880
2881 os_free(data->ca_cert);
2882 data->ca_cert = os_strdup(ca_cert);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002883 }
2884
2885 return 0;
2886}
2887
2888
Hai Shalom74f70d42019-02-11 14:42:39 -08002889int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890{
2891 int flags;
2892
2893 if (check_crl) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002894 struct tls_data *data = ssl_ctx;
2895 X509_STORE *cs = SSL_CTX_get_cert_store(data->ssl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002896 if (cs == NULL) {
2897 tls_show_errors(MSG_INFO, __func__, "Failed to get "
2898 "certificate store when enabling "
2899 "check_crl");
2900 return -1;
2901 }
2902 flags = X509_V_FLAG_CRL_CHECK;
2903 if (check_crl == 2)
2904 flags |= X509_V_FLAG_CRL_CHECK_ALL;
2905 X509_STORE_set_flags(cs, flags);
Hai Shalom74f70d42019-02-11 14:42:39 -08002906
2907 data->check_crl = check_crl;
2908 data->check_crl_strict = strict;
2909 os_get_reltime(&data->crl_last_reload);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002910 }
2911 return 0;
2912}
2913
2914
2915static int tls_connection_set_subject_match(struct tls_connection *conn,
2916 const char *subject_match,
Dmitry Shmidt051af732013-10-22 13:52:46 -07002917 const char *altsubject_match,
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002918 const char *suffix_match,
Hai Shalom021b0b52019-04-10 11:17:58 -07002919 const char *domain_match,
2920 const char *check_cert_subject)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921{
2922 os_free(conn->subject_match);
2923 conn->subject_match = NULL;
2924 if (subject_match) {
2925 conn->subject_match = os_strdup(subject_match);
2926 if (conn->subject_match == NULL)
2927 return -1;
2928 }
2929
2930 os_free(conn->altsubject_match);
2931 conn->altsubject_match = NULL;
2932 if (altsubject_match) {
2933 conn->altsubject_match = os_strdup(altsubject_match);
2934 if (conn->altsubject_match == NULL)
2935 return -1;
2936 }
2937
Dmitry Shmidt051af732013-10-22 13:52:46 -07002938 os_free(conn->suffix_match);
2939 conn->suffix_match = NULL;
2940 if (suffix_match) {
2941 conn->suffix_match = os_strdup(suffix_match);
2942 if (conn->suffix_match == NULL)
2943 return -1;
2944 }
2945
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002946 os_free(conn->domain_match);
2947 conn->domain_match = NULL;
2948 if (domain_match) {
2949 conn->domain_match = os_strdup(domain_match);
2950 if (conn->domain_match == NULL)
2951 return -1;
2952 }
2953
Hai Shalom021b0b52019-04-10 11:17:58 -07002954 os_free(conn->check_cert_subject);
2955 conn->check_cert_subject = NULL;
2956 if (check_cert_subject) {
2957 conn->check_cert_subject = os_strdup(check_cert_subject);
2958 if (!conn->check_cert_subject)
2959 return -1;
2960 }
2961
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002962 return 0;
2963}
2964
2965
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002966#ifdef CONFIG_SUITEB
2967#if OPENSSL_VERSION_NUMBER >= 0x10002000L
2968static int suiteb_cert_cb(SSL *ssl, void *arg)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002969{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002970 struct tls_connection *conn = arg;
2971
2972 /*
2973 * This cert_cb() is not really the best location for doing a
2974 * constraint check for the ServerKeyExchange message, but this seems to
2975 * be the only place where the current OpenSSL sequence can be
2976 * terminated cleanly with an TLS alert going out to the server.
2977 */
2978
2979 if (!(conn->flags & TLS_CONN_SUITEB))
2980 return 1;
2981
2982 /* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */
2983 if (conn->cipher_suite != 0x9f)
2984 return 1;
2985
2986 if (conn->server_dh_prime_len >= 3072)
2987 return 1;
2988
2989 wpa_printf(MSG_DEBUG,
2990 "OpenSSL: Server DH prime length (%d bits) not sufficient for Suite B RSA - reject handshake",
2991 conn->server_dh_prime_len);
2992 return 0;
2993}
2994#endif /* OPENSSL_VERSION_NUMBER */
2995#endif /* CONFIG_SUITEB */
2996
2997
Roshan Pius3a1667e2018-07-03 15:17:14 -07002998static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags,
2999 const char *openssl_ciphers)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003000{
3001 SSL *ssl = conn->ssl;
3002
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003003#ifdef SSL_OP_NO_TICKET
3004 if (flags & TLS_CONN_DISABLE_SESSION_TICKET)
3005 SSL_set_options(ssl, SSL_OP_NO_TICKET);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003006 else
3007 SSL_clear_options(ssl, SSL_OP_NO_TICKET);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003008#endif /* SSL_OP_NO_TICKET */
3009
3010#ifdef SSL_OP_NO_TLSv1
3011 if (flags & TLS_CONN_DISABLE_TLSv1_0)
3012 SSL_set_options(ssl, SSL_OP_NO_TLSv1);
3013 else
3014 SSL_clear_options(ssl, SSL_OP_NO_TLSv1);
3015#endif /* SSL_OP_NO_TLSv1 */
3016#ifdef SSL_OP_NO_TLSv1_1
3017 if (flags & TLS_CONN_DISABLE_TLSv1_1)
3018 SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
3019 else
3020 SSL_clear_options(ssl, SSL_OP_NO_TLSv1_1);
3021#endif /* SSL_OP_NO_TLSv1_1 */
3022#ifdef SSL_OP_NO_TLSv1_2
3023 if (flags & TLS_CONN_DISABLE_TLSv1_2)
3024 SSL_set_options(ssl, SSL_OP_NO_TLSv1_2);
3025 else
3026 SSL_clear_options(ssl, SSL_OP_NO_TLSv1_2);
3027#endif /* SSL_OP_NO_TLSv1_2 */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003028#ifdef SSL_OP_NO_TLSv1_3
3029 if (flags & TLS_CONN_DISABLE_TLSv1_3)
3030 SSL_set_options(ssl, SSL_OP_NO_TLSv1_3);
3031 else
3032 SSL_clear_options(ssl, SSL_OP_NO_TLSv1_3);
3033#endif /* SSL_OP_NO_TLSv1_3 */
Hai Shalom74f70d42019-02-11 14:42:39 -08003034#if OPENSSL_VERSION_NUMBER >= 0x10100000L
3035 if (flags & (TLS_CONN_ENABLE_TLSv1_0 |
3036 TLS_CONN_ENABLE_TLSv1_1 |
3037 TLS_CONN_ENABLE_TLSv1_2)) {
3038 int version = 0;
3039
3040 /* Explicit request to enable TLS versions even if needing to
3041 * override systemwide policies. */
Hai Shalom899fcc72020-10-19 14:38:18 -07003042 if (flags & TLS_CONN_ENABLE_TLSv1_0)
Hai Shalom74f70d42019-02-11 14:42:39 -08003043 version = TLS1_VERSION;
Hai Shalom899fcc72020-10-19 14:38:18 -07003044 else if (flags & TLS_CONN_ENABLE_TLSv1_1)
3045 version = TLS1_1_VERSION;
3046 else if (flags & TLS_CONN_ENABLE_TLSv1_2)
3047 version = TLS1_2_VERSION;
Hai Shalom74f70d42019-02-11 14:42:39 -08003048 if (!version) {
3049 wpa_printf(MSG_DEBUG,
3050 "OpenSSL: Invalid TLS version configuration");
3051 return -1;
3052 }
3053
3054 if (SSL_set_min_proto_version(ssl, version) != 1) {
3055 wpa_printf(MSG_DEBUG,
3056 "OpenSSL: Failed to set minimum TLS version");
3057 return -1;
3058 }
3059 }
3060#endif /* >= 1.1.0 */
Hai Shalom899fcc72020-10-19 14:38:18 -07003061#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
3062 !defined(LIBRESSL_VERSION_NUMBER) && \
3063 !defined(OPENSSL_IS_BORINGSSL)
3064 if ((flags & (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) &&
3065 SSL_get_security_level(ssl) >= 2) {
3066 /*
3067 * Need to drop to security level 1 to allow TLS versions older
3068 * than 1.2 to be used when explicitly enabled in configuration.
3069 */
3070 SSL_set_security_level(conn->ssl, 1);
3071 }
3072#endif
Hai Shalom74f70d42019-02-11 14:42:39 -08003073
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003074#ifdef CONFIG_SUITEB
Roshan Pius3a1667e2018-07-03 15:17:14 -07003075#ifdef OPENSSL_IS_BORINGSSL
3076 /* Start with defaults from BoringSSL */
3077 SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, NULL, 0);
3078#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003079#if OPENSSL_VERSION_NUMBER >= 0x10002000L
3080 if (flags & TLS_CONN_SUITEB_NO_ECDH) {
3081 const char *ciphers = "DHE-RSA-AES256-GCM-SHA384";
3082
Roshan Pius3a1667e2018-07-03 15:17:14 -07003083 if (openssl_ciphers) {
3084 wpa_printf(MSG_DEBUG,
3085 "OpenSSL: Override ciphers for Suite B (no ECDH): %s",
3086 openssl_ciphers);
3087 ciphers = openssl_ciphers;
3088 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003089 if (SSL_set_cipher_list(ssl, ciphers) != 1) {
3090 wpa_printf(MSG_INFO,
3091 "OpenSSL: Failed to set Suite B ciphers");
3092 return -1;
3093 }
3094 } else if (flags & TLS_CONN_SUITEB) {
3095 EC_KEY *ecdh;
3096 const char *ciphers =
3097 "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384";
Roshan Pius3a1667e2018-07-03 15:17:14 -07003098 int nid[1] = { NID_secp384r1 };
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003099
Roshan Pius3a1667e2018-07-03 15:17:14 -07003100 if (openssl_ciphers) {
3101 wpa_printf(MSG_DEBUG,
3102 "OpenSSL: Override ciphers for Suite B: %s",
3103 openssl_ciphers);
3104 ciphers = openssl_ciphers;
3105 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003106 if (SSL_set_cipher_list(ssl, ciphers) != 1) {
3107 wpa_printf(MSG_INFO,
3108 "OpenSSL: Failed to set Suite B ciphers");
3109 return -1;
3110 }
3111
Roshan Pius3a1667e2018-07-03 15:17:14 -07003112 if (SSL_set1_curves(ssl, nid, 1) != 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003113 wpa_printf(MSG_INFO,
3114 "OpenSSL: Failed to set Suite B curves");
3115 return -1;
3116 }
3117
3118 ecdh = EC_KEY_new_by_curve_name(NID_secp384r1);
3119 if (!ecdh || SSL_set_tmp_ecdh(ssl, ecdh) != 1) {
3120 EC_KEY_free(ecdh);
3121 wpa_printf(MSG_INFO,
3122 "OpenSSL: Failed to set ECDH parameter");
3123 return -1;
3124 }
3125 EC_KEY_free(ecdh);
3126 }
3127 if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003128#ifdef OPENSSL_IS_BORINGSSL
3129 uint16_t sigalgs[1] = { SSL_SIGN_RSA_PKCS1_SHA384 };
3130
3131 if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs,
3132 1) != 1) {
3133 wpa_printf(MSG_INFO,
3134 "OpenSSL: Failed to set Suite B sigalgs");
3135 return -1;
3136 }
3137#else /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003138 /* ECDSA+SHA384 if need to add EC support here */
3139 if (SSL_set1_sigalgs_list(ssl, "RSA+SHA384") != 1) {
3140 wpa_printf(MSG_INFO,
3141 "OpenSSL: Failed to set Suite B sigalgs");
3142 return -1;
3143 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003144#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003145
3146 SSL_set_options(ssl, SSL_OP_NO_TLSv1);
3147 SSL_set_options(ssl, SSL_OP_NO_TLSv1_1);
3148 SSL_set_cert_cb(ssl, suiteb_cert_cb, conn);
3149 }
3150#else /* OPENSSL_VERSION_NUMBER < 0x10002000L */
3151 if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) {
3152 wpa_printf(MSG_ERROR,
3153 "OpenSSL: Suite B RSA case not supported with this OpenSSL version");
3154 return -1;
3155 }
3156#endif /* OPENSSL_VERSION_NUMBER */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003157
3158#ifdef OPENSSL_IS_BORINGSSL
3159 if (openssl_ciphers && os_strcmp(openssl_ciphers, "SUITEB192") == 0) {
3160 uint16_t sigalgs[1] = { SSL_SIGN_ECDSA_SECP384R1_SHA384 };
3161 int nid[1] = { NID_secp384r1 };
3162
3163 if (SSL_set1_curves(ssl, nid, 1) != 1) {
3164 wpa_printf(MSG_INFO,
3165 "OpenSSL: Failed to set Suite B curves");
3166 return -1;
3167 }
3168
3169 if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs,
3170 1) != 1) {
3171 wpa_printf(MSG_INFO,
3172 "OpenSSL: Failed to set Suite B sigalgs");
3173 return -1;
3174 }
3175 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003176#else /* OPENSSL_IS_BORINGSSL */
3177 if (!(flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) &&
3178 openssl_ciphers && SSL_set_cipher_list(ssl, openssl_ciphers) != 1) {
3179 wpa_printf(MSG_INFO,
3180 "OpenSSL: Failed to set openssl_ciphers '%s'",
3181 openssl_ciphers);
3182 return -1;
3183 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003184#endif /* OPENSSL_IS_BORINGSSL */
Hai Shalom74f70d42019-02-11 14:42:39 -08003185#else /* CONFIG_SUITEB */
3186 if (openssl_ciphers && SSL_set_cipher_list(ssl, openssl_ciphers) != 1) {
3187 wpa_printf(MSG_INFO,
3188 "OpenSSL: Failed to set openssl_ciphers '%s'",
3189 openssl_ciphers);
3190 return -1;
3191 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003192#endif /* CONFIG_SUITEB */
3193
Hai Shalom81f62d82019-07-22 12:10:00 -07003194 if (flags & TLS_CONN_TEAP_ANON_DH) {
3195#ifndef TEAP_DH_ANON_CS
3196#define TEAP_DH_ANON_CS \
3197 "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:" \
3198 "ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:" \
3199 "ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:" \
3200 "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" \
3201 "DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:" \
3202 "DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:" \
3203 "ADH-AES256-GCM-SHA384:ADH-AES128-GCM-SHA256:" \
3204 "ADH-AES256-SHA256:ADH-AES128-SHA256:ADH-AES256-SHA:ADH-AES128-SHA"
3205#endif
3206 static const char *cs = TEAP_DH_ANON_CS;
3207
3208#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
3209 !defined(LIBRESSL_VERSION_NUMBER) && \
3210 !defined(OPENSSL_IS_BORINGSSL)
3211 /*
3212 * Need to drop to security level 0 to allow anonymous
3213 * cipher suites for EAP-TEAP.
3214 */
3215 SSL_set_security_level(conn->ssl, 0);
3216#endif
3217
3218 wpa_printf(MSG_DEBUG,
3219 "OpenSSL: Enable cipher suites for anonymous EAP-TEAP provisioning: %s",
3220 cs);
3221 if (SSL_set_cipher_list(conn->ssl, cs) != 1) {
3222 tls_show_errors(MSG_INFO, __func__,
3223 "Cipher suite configuration failed");
3224 return -1;
3225 }
3226 }
3227
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003228 return 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003229}
3230
3231
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003232int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003233 int verify_peer, unsigned int flags,
3234 const u8 *session_ctx, size_t session_ctx_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003235{
3236 static int counter = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003237 struct tls_data *data = ssl_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003238
3239 if (conn == NULL)
3240 return -1;
3241
Hai Shalom899fcc72020-10-19 14:38:18 -07003242 if (verify_peer == 2) {
3243 conn->ca_cert_verify = 1;
3244 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
3245 SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
3246 } else if (verify_peer) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003247 conn->ca_cert_verify = 1;
3248 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
3249 SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
3250 SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
3251 } else {
3252 conn->ca_cert_verify = 0;
3253 SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
3254 }
3255
Roshan Pius3a1667e2018-07-03 15:17:14 -07003256 if (tls_set_conn_flags(conn, flags, NULL) < 0)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003257 return -1;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003258 conn->flags = flags;
3259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260 SSL_set_accept_state(conn->ssl);
3261
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003262 if (data->tls_session_lifetime == 0) {
3263 /*
3264 * Set session id context to a unique value to make sure
3265 * session resumption cannot be used either through session
3266 * caching or TLS ticket extension.
3267 */
3268 counter++;
3269 SSL_set_session_id_context(conn->ssl,
3270 (const unsigned char *) &counter,
3271 sizeof(counter));
3272 } else if (session_ctx) {
3273 SSL_set_session_id_context(conn->ssl, session_ctx,
3274 session_ctx_len);
3275 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003276
3277 return 0;
3278}
3279
3280
3281static int tls_connection_client_cert(struct tls_connection *conn,
3282 const char *client_cert,
3283 const u8 *client_cert_blob,
3284 size_t client_cert_blob_len)
3285{
3286 if (client_cert == NULL && client_cert_blob == NULL)
3287 return 0;
3288
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003289#ifdef PKCS12_FUNCS
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003290#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER)
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003291 /*
3292 * Clear previously set extra chain certificates, if any, from PKCS#12
3293 * processing in tls_parse_pkcs12() to allow OpenSSL to build a new
3294 * chain properly.
3295 */
3296 SSL_CTX_clear_extra_chain_certs(conn->ssl_ctx);
3297#endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */
3298#endif /* PKCS12_FUNCS */
3299
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003300 if (client_cert_blob &&
3301 SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob,
3302 client_cert_blob_len) == 1) {
3303 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> "
3304 "OK");
3305 return 0;
3306 } else if (client_cert_blob) {
Hai Shalom899fcc72020-10-19 14:38:18 -07003307#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20901000L
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003308 tls_show_errors(MSG_DEBUG, __func__,
3309 "SSL_use_certificate_ASN1 failed");
Hai Shalom899fcc72020-10-19 14:38:18 -07003310#else
3311 BIO *bio;
3312 X509 *x509;
3313
3314 tls_show_errors(MSG_DEBUG, __func__,
3315 "SSL_use_certificate_ASN1 failed");
3316 bio = BIO_new(BIO_s_mem());
3317 if (!bio)
3318 return -1;
3319 BIO_write(bio, client_cert_blob, client_cert_blob_len);
3320 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
3321 if (!x509 || SSL_use_certificate(conn->ssl, x509) != 1) {
3322 X509_free(x509);
3323 BIO_free(bio);
3324 return -1;
3325 }
3326 X509_free(x509);
3327 wpa_printf(MSG_DEBUG,
3328 "OpenSSL: Found PEM encoded certificate from blob");
3329 while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL))) {
3330 wpa_printf(MSG_DEBUG,
3331 "OpenSSL: Added an additional certificate into the chain");
3332 SSL_add0_chain_cert(conn->ssl, x509);
3333 }
3334 BIO_free(bio);
3335 return 0;
3336#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003337 }
3338
3339 if (client_cert == NULL)
3340 return -1;
3341
3342#ifdef ANDROID
3343 if (os_strncmp("keystore://", client_cert, 11) == 0) {
3344 BIO *bio = BIO_from_keystore(&client_cert[11]);
3345 X509 *x509 = NULL;
3346 int ret = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003347 if (bio) {
Hai Shalom22171592021-04-02 16:05:23 -07003348 // Try DER encoding first
3349 x509 = d2i_X509_bio(bio, NULL);
3350 if (!x509) {
3351 // Maybe this bio is actually PEM encoded.
3352 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
3353 if (!x509) {
3354 wpa_printf(MSG_ERROR, "tls_connection_client_cert: "
3355 "Unknown certificate encoding.");
3356 }
3357 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003358 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003359 if (x509) {
3360 if (SSL_use_certificate(conn->ssl, x509) == 1)
3361 ret = 0;
3362 X509_free(x509);
3363 }
Paul Stewart50772e82017-01-25 13:59:16 -08003364
3365 /* Read additional certificates into the chain. */
3366 while (bio) {
3367 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
3368 if (x509) {
3369 /* Takes ownership of x509 */
3370 SSL_add0_chain_cert(conn->ssl, x509);
3371 } else {
3372 BIO_free(bio);
3373 bio = NULL;
3374 }
3375 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003376 return ret;
3377 }
3378#endif /* ANDROID */
3379
3380#ifndef OPENSSL_NO_STDIO
3381 if (SSL_use_certificate_file(conn->ssl, client_cert,
3382 SSL_FILETYPE_ASN1) == 1) {
3383 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)"
3384 " --> OK");
3385 return 0;
3386 }
3387
Hai Shalom021b0b52019-04-10 11:17:58 -07003388#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
3389 !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL)
Hai Shalom74f70d42019-02-11 14:42:39 -08003390 if (SSL_use_certificate_chain_file(conn->ssl, client_cert) == 1) {
3391 ERR_clear_error();
3392 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_chain_file"
3393 " --> OK");
3394 return 0;
3395 }
3396#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003397 if (SSL_use_certificate_file(conn->ssl, client_cert,
3398 SSL_FILETYPE_PEM) == 1) {
3399 ERR_clear_error();
3400 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)"
3401 " --> OK");
3402 return 0;
3403 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003404#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003405
3406 tls_show_errors(MSG_DEBUG, __func__,
3407 "SSL_use_certificate_file failed");
3408#else /* OPENSSL_NO_STDIO */
3409 wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
3410#endif /* OPENSSL_NO_STDIO */
3411
3412 return -1;
3413}
3414
3415
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003416static int tls_global_client_cert(struct tls_data *data,
3417 const char *client_cert)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418{
3419#ifndef OPENSSL_NO_STDIO
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003420 SSL_CTX *ssl_ctx = data->ssl;
3421
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003422 if (client_cert == NULL)
3423 return 0;
3424
3425 if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
3426 SSL_FILETYPE_ASN1) != 1 &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003427 SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003428 SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
3429 SSL_FILETYPE_PEM) != 1) {
3430 tls_show_errors(MSG_INFO, __func__,
3431 "Failed to load client certificate");
3432 return -1;
3433 }
3434 return 0;
3435#else /* OPENSSL_NO_STDIO */
3436 if (client_cert == NULL)
3437 return 0;
3438 wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
3439 return -1;
3440#endif /* OPENSSL_NO_STDIO */
3441}
3442
3443
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003444#ifdef PKCS12_FUNCS
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003445static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003446 const char *passwd)
3447{
3448 EVP_PKEY *pkey;
3449 X509 *cert;
3450 STACK_OF(X509) *certs;
3451 int res = 0;
3452 char buf[256];
3453
3454 pkey = NULL;
3455 cert = NULL;
3456 certs = NULL;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003457 if (!passwd)
3458 passwd = "";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003459 if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
3460 tls_show_errors(MSG_DEBUG, __func__,
3461 "Failed to parse PKCS12 file");
3462 PKCS12_free(p12);
3463 return -1;
3464 }
3465 wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data");
3466
3467 if (cert) {
3468 X509_NAME_oneline(X509_get_subject_name(cert), buf,
3469 sizeof(buf));
3470 wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: "
3471 "subject='%s'", buf);
3472 if (ssl) {
3473 if (SSL_use_certificate(ssl, cert) != 1)
3474 res = -1;
3475 } else {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003476 if (SSL_CTX_use_certificate(data->ssl, cert) != 1)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 res = -1;
3478 }
3479 X509_free(cert);
3480 }
3481
3482 if (pkey) {
3483 wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12");
3484 if (ssl) {
3485 if (SSL_use_PrivateKey(ssl, pkey) != 1)
3486 res = -1;
3487 } else {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003488 if (SSL_CTX_use_PrivateKey(data->ssl, pkey) != 1)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 res = -1;
3490 }
3491 EVP_PKEY_free(pkey);
3492 }
3493
3494 if (certs) {
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08003495#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08003496 if (ssl)
3497 SSL_clear_chain_certs(ssl);
3498 else
3499 SSL_CTX_clear_chain_certs(data->ssl);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003500 while ((cert = sk_X509_pop(certs)) != NULL) {
3501 X509_NAME_oneline(X509_get_subject_name(cert), buf,
3502 sizeof(buf));
3503 wpa_printf(MSG_DEBUG, "TLS: additional certificate"
3504 " from PKCS12: subject='%s'", buf);
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08003505 if ((ssl && SSL_add1_chain_cert(ssl, cert) != 1) ||
3506 (!ssl && SSL_CTX_add1_chain_cert(data->ssl,
3507 cert) != 1)) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003508 tls_show_errors(MSG_DEBUG, __func__,
3509 "Failed to add additional certificate");
3510 res = -1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003511 X509_free(cert);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003512 break;
3513 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003514 X509_free(cert);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003515 }
3516 if (!res) {
3517 /* Try to continue anyway */
3518 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003519 sk_X509_pop_free(certs, X509_free);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003520#ifndef OPENSSL_IS_BORINGSSL
Dmitry Shmidtb97e4282016-02-08 10:16:07 -08003521 if (ssl)
3522 res = SSL_build_cert_chain(
3523 ssl,
3524 SSL_BUILD_CHAIN_FLAG_CHECK |
3525 SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
3526 else
3527 res = SSL_CTX_build_cert_chain(
3528 data->ssl,
3529 SSL_BUILD_CHAIN_FLAG_CHECK |
3530 SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003531 if (!res) {
3532 tls_show_errors(MSG_DEBUG, __func__,
3533 "Failed to build certificate chain");
3534 } else if (res == 2) {
3535 wpa_printf(MSG_DEBUG,
3536 "TLS: Ignore certificate chain verification error when building chain with PKCS#12 extra certificates");
3537 }
3538#endif /* OPENSSL_IS_BORINGSSL */
3539 /*
3540 * Try to continue regardless of result since it is possible for
3541 * the extra certificates not to be required.
3542 */
3543 res = 0;
3544#else /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003545 SSL_CTX_clear_extra_chain_certs(data->ssl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003546 while ((cert = sk_X509_pop(certs)) != NULL) {
3547 X509_NAME_oneline(X509_get_subject_name(cert), buf,
3548 sizeof(buf));
3549 wpa_printf(MSG_DEBUG, "TLS: additional certificate"
3550 " from PKCS12: subject='%s'", buf);
3551 /*
3552 * There is no SSL equivalent for the chain cert - so
3553 * always add it to the context...
3554 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003555 if (SSL_CTX_add_extra_chain_cert(data->ssl, cert) != 1)
3556 {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003557 X509_free(cert);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003558 res = -1;
3559 break;
3560 }
3561 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003562 sk_X509_pop_free(certs, X509_free);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003563#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003564 }
3565
3566 PKCS12_free(p12);
3567
3568 if (res < 0)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003569 tls_get_errors(data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003570
3571 return res;
3572}
3573#endif /* PKCS12_FUNCS */
3574
3575
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003576static int tls_read_pkcs12(struct tls_data *data, SSL *ssl,
3577 const char *private_key, const char *passwd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003578{
3579#ifdef PKCS12_FUNCS
3580 FILE *f;
3581 PKCS12 *p12;
3582
3583 f = fopen(private_key, "rb");
3584 if (f == NULL)
3585 return -1;
3586
3587 p12 = d2i_PKCS12_fp(f, NULL);
3588 fclose(f);
3589
3590 if (p12 == NULL) {
3591 tls_show_errors(MSG_INFO, __func__,
3592 "Failed to use PKCS#12 file");
3593 return -1;
3594 }
3595
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003596 return tls_parse_pkcs12(data, ssl, p12, passwd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003597
3598#else /* PKCS12_FUNCS */
3599 wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read "
3600 "p12/pfx files");
3601 return -1;
3602#endif /* PKCS12_FUNCS */
3603}
3604
3605
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003606static int tls_read_pkcs12_blob(struct tls_data *data, SSL *ssl,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003607 const u8 *blob, size_t len, const char *passwd)
3608{
3609#ifdef PKCS12_FUNCS
3610 PKCS12 *p12;
3611
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003612 p12 = d2i_PKCS12(NULL, (const unsigned char **) &blob, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613 if (p12 == NULL) {
3614 tls_show_errors(MSG_INFO, __func__,
3615 "Failed to use PKCS#12 blob");
3616 return -1;
3617 }
3618
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003619 return tls_parse_pkcs12(data, ssl, p12, passwd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003620
3621#else /* PKCS12_FUNCS */
3622 wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse "
3623 "p12/pfx blobs");
3624 return -1;
3625#endif /* PKCS12_FUNCS */
3626}
3627
3628
3629#ifndef OPENSSL_NO_ENGINE
3630static int tls_engine_get_cert(struct tls_connection *conn,
3631 const char *cert_id,
3632 X509 **cert)
3633{
3634 /* this runs after the private key is loaded so no PIN is required */
3635 struct {
3636 const char *cert_id;
3637 X509 *cert;
3638 } params;
3639 params.cert_id = cert_id;
3640 params.cert = NULL;
3641
3642 if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL",
3643 0, &params, NULL, 1)) {
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003644 unsigned long err = ERR_get_error();
3645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646 wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id"
3647 " '%s' [%s]", cert_id,
Dmitry Shmidt1d755d02015-04-28 10:34:29 -07003648 ERR_error_string(err, NULL));
3649 if (tls_is_pin_error(err))
3650 return TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003651 return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
3652 }
3653 if (!params.cert) {
3654 wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id"
3655 " '%s'", cert_id);
3656 return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
3657 }
3658 *cert = params.cert;
3659 return 0;
3660}
3661#endif /* OPENSSL_NO_ENGINE */
3662
3663
3664static int tls_connection_engine_client_cert(struct tls_connection *conn,
3665 const char *cert_id)
3666{
3667#ifndef OPENSSL_NO_ENGINE
3668 X509 *cert;
3669
3670 if (tls_engine_get_cert(conn, cert_id, &cert))
3671 return -1;
3672
3673 if (!SSL_use_certificate(conn->ssl, cert)) {
3674 tls_show_errors(MSG_ERROR, __func__,
3675 "SSL_use_certificate failed");
3676 X509_free(cert);
3677 return -1;
3678 }
3679 X509_free(cert);
3680 wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> "
3681 "OK");
3682 return 0;
3683
3684#else /* OPENSSL_NO_ENGINE */
3685 return -1;
3686#endif /* OPENSSL_NO_ENGINE */
3687}
3688
3689
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003690static int tls_connection_engine_ca_cert(struct tls_data *data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003691 struct tls_connection *conn,
3692 const char *ca_cert_id)
3693{
3694#ifndef OPENSSL_NO_ENGINE
3695 X509 *cert;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003696 SSL_CTX *ssl_ctx = data->ssl;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003697 X509_STORE *store;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003698
3699 if (tls_engine_get_cert(conn, ca_cert_id, &cert))
3700 return -1;
3701
3702 /* start off the same as tls_connection_ca_cert */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003703 store = X509_STORE_new();
3704 if (store == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003705 wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
3706 "certificate store", __func__);
3707 X509_free(cert);
3708 return -1;
3709 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003710 SSL_CTX_set_cert_store(ssl_ctx, store);
3711 if (!X509_STORE_add_cert(store, cert)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003712 unsigned long err = ERR_peek_error();
3713 tls_show_errors(MSG_WARNING, __func__,
3714 "Failed to add CA certificate from engine "
3715 "to certificate store");
3716 if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
3717 ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
3718 wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert"
3719 " already in hash table error",
3720 __func__);
3721 } else {
3722 X509_free(cert);
3723 return -1;
3724 }
3725 }
3726 X509_free(cert);
3727 wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine "
3728 "to certificate store", __func__);
3729 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003730 conn->ca_cert_verify = 1;
3731
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003732 return 0;
3733
3734#else /* OPENSSL_NO_ENGINE */
3735 return -1;
3736#endif /* OPENSSL_NO_ENGINE */
3737}
3738
3739
3740static int tls_connection_engine_private_key(struct tls_connection *conn)
3741{
Adam Langley1eb02ed2015-04-21 19:00:05 -07003742#if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743 if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) {
3744 tls_show_errors(MSG_ERROR, __func__,
3745 "ENGINE: cannot use private key for TLS");
3746 return -1;
3747 }
3748 if (!SSL_check_private_key(conn->ssl)) {
3749 tls_show_errors(MSG_INFO, __func__,
3750 "Private key failed verification");
3751 return -1;
3752 }
3753 return 0;
3754#else /* OPENSSL_NO_ENGINE */
3755 wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but "
3756 "engine support was not compiled in");
3757 return -1;
3758#endif /* OPENSSL_NO_ENGINE */
3759}
3760
3761
Roshan Pius3a1667e2018-07-03 15:17:14 -07003762#ifndef OPENSSL_NO_STDIO
3763static int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003764{
Roshan Pius3a1667e2018-07-03 15:17:14 -07003765 if (!password)
3766 return 0;
3767 os_strlcpy(buf, (const char *) password, size);
3768 return os_strlen(buf);
3769}
3770#endif /* OPENSSL_NO_STDIO */
3771
3772
3773static int tls_use_private_key_file(struct tls_data *data, SSL *ssl,
3774 const char *private_key,
3775 const char *private_key_passwd)
3776{
3777#ifndef OPENSSL_NO_STDIO
3778 BIO *bio;
3779 EVP_PKEY *pkey;
3780 int ret;
3781
3782 /* First try ASN.1 (DER). */
3783 bio = BIO_new_file(private_key, "r");
3784 if (!bio)
3785 return -1;
3786 pkey = d2i_PrivateKey_bio(bio, NULL);
3787 BIO_free(bio);
3788
3789 if (pkey) {
3790 wpa_printf(MSG_DEBUG, "OpenSSL: %s (DER) --> loaded", __func__);
3791 } else {
3792 /* Try PEM with the provided password. */
3793 bio = BIO_new_file(private_key, "r");
3794 if (!bio)
3795 return -1;
3796 pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_passwd_cb,
3797 (void *) private_key_passwd);
3798 BIO_free(bio);
3799 if (!pkey)
3800 return -1;
3801 wpa_printf(MSG_DEBUG, "OpenSSL: %s (PEM) --> loaded", __func__);
3802 /* Clear errors from the previous failed load. */
3803 ERR_clear_error();
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003804 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003805
3806 if (ssl)
3807 ret = SSL_use_PrivateKey(ssl, pkey);
3808 else
3809 ret = SSL_CTX_use_PrivateKey(data->ssl, pkey);
3810
3811 EVP_PKEY_free(pkey);
3812 return ret == 1 ? 0 : -1;
3813#else /* OPENSSL_NO_STDIO */
3814 wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
3815 return -1;
3816#endif /* OPENSSL_NO_STDIO */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003817}
3818
3819
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003820static int tls_connection_private_key(struct tls_data *data,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003821 struct tls_connection *conn,
3822 const char *private_key,
3823 const char *private_key_passwd,
3824 const u8 *private_key_blob,
3825 size_t private_key_blob_len)
3826{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003827 int ok;
3828
3829 if (private_key == NULL && private_key_blob == NULL)
3830 return 0;
3831
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003832 ok = 0;
3833 while (private_key_blob) {
3834 if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl,
3835 (u8 *) private_key_blob,
3836 private_key_blob_len) == 1) {
3837 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
3838 "ASN1(EVP_PKEY_RSA) --> OK");
3839 ok = 1;
3840 break;
3841 }
3842
3843 if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl,
3844 (u8 *) private_key_blob,
3845 private_key_blob_len) == 1) {
3846 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
3847 "ASN1(EVP_PKEY_DSA) --> OK");
3848 ok = 1;
3849 break;
3850 }
3851
Hai Shalom899fcc72020-10-19 14:38:18 -07003852#ifndef OPENSSL_NO_EC
3853 if (SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, conn->ssl,
3854 (u8 *) private_key_blob,
3855 private_key_blob_len) == 1) {
3856 wpa_printf(MSG_DEBUG,
3857 "OpenSSL: SSL_use_PrivateKey_ASN1(EVP_PKEY_EC) --> OK");
3858 ok = 1;
3859 break;
3860 }
3861#endif /* OPENSSL_NO_EC */
3862
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003863 if (SSL_use_RSAPrivateKey_ASN1(conn->ssl,
3864 (u8 *) private_key_blob,
3865 private_key_blob_len) == 1) {
3866 wpa_printf(MSG_DEBUG, "OpenSSL: "
3867 "SSL_use_RSAPrivateKey_ASN1 --> OK");
3868 ok = 1;
3869 break;
3870 }
3871
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003872 if (tls_read_pkcs12_blob(data, conn->ssl, private_key_blob,
Roshan Pius3a1667e2018-07-03 15:17:14 -07003873 private_key_blob_len,
3874 private_key_passwd) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003875 wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> "
3876 "OK");
3877 ok = 1;
3878 break;
3879 }
3880
3881 break;
3882 }
3883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003884 while (!ok && private_key) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003885 if (tls_use_private_key_file(data, conn->ssl, private_key,
3886 private_key_passwd) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003887 ok = 1;
3888 break;
3889 }
3890
Roshan Pius3a1667e2018-07-03 15:17:14 -07003891 if (tls_read_pkcs12(data, conn->ssl, private_key,
3892 private_key_passwd) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003893 wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file "
3894 "--> OK");
3895 ok = 1;
3896 break;
3897 }
3898
3899 if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) {
3900 wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to "
3901 "access certificate store --> OK");
3902 ok = 1;
3903 break;
3904 }
3905
3906 break;
3907 }
3908
3909 if (!ok) {
3910 tls_show_errors(MSG_INFO, __func__,
3911 "Failed to load private key");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003912 return -1;
3913 }
3914 ERR_clear_error();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003915
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916 if (!SSL_check_private_key(conn->ssl)) {
3917 tls_show_errors(MSG_INFO, __func__, "Private key failed "
3918 "verification");
3919 return -1;
3920 }
3921
3922 wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully");
3923 return 0;
3924}
3925
3926
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003927static int tls_global_private_key(struct tls_data *data,
3928 const char *private_key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929 const char *private_key_passwd)
3930{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003931 SSL_CTX *ssl_ctx = data->ssl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003932
3933 if (private_key == NULL)
3934 return 0;
3935
Roshan Pius3a1667e2018-07-03 15:17:14 -07003936 if (tls_use_private_key_file(data, NULL, private_key,
3937 private_key_passwd) &&
3938 tls_read_pkcs12(data, NULL, private_key, private_key_passwd)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003939 tls_show_errors(MSG_INFO, __func__,
3940 "Failed to load private key");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003941 ERR_clear_error();
3942 return -1;
3943 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003944 ERR_clear_error();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003945
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003946 if (!SSL_CTX_check_private_key(ssl_ctx)) {
3947 tls_show_errors(MSG_INFO, __func__,
3948 "Private key failed verification");
3949 return -1;
3950 }
3951
3952 return 0;
3953}
3954
3955
3956static int tls_connection_dh(struct tls_connection *conn, const char *dh_file)
3957{
3958#ifdef OPENSSL_NO_DH
3959 if (dh_file == NULL)
3960 return 0;
3961 wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
3962 "dh_file specified");
3963 return -1;
3964#else /* OPENSSL_NO_DH */
3965 DH *dh;
3966 BIO *bio;
3967
3968 /* TODO: add support for dh_blob */
3969 if (dh_file == NULL)
3970 return 0;
3971 if (conn == NULL)
3972 return -1;
3973
3974 bio = BIO_new_file(dh_file, "r");
3975 if (bio == NULL) {
3976 wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
3977 dh_file, ERR_error_string(ERR_get_error(), NULL));
3978 return -1;
3979 }
3980 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3981 BIO_free(bio);
3982#ifndef OPENSSL_NO_DSA
3983 while (dh == NULL) {
3984 DSA *dsa;
3985 wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
3986 " trying to parse as DSA params", dh_file,
3987 ERR_error_string(ERR_get_error(), NULL));
3988 bio = BIO_new_file(dh_file, "r");
3989 if (bio == NULL)
3990 break;
3991 dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
3992 BIO_free(bio);
3993 if (!dsa) {
3994 wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
3995 "'%s': %s", dh_file,
3996 ERR_error_string(ERR_get_error(), NULL));
3997 break;
3998 }
3999
4000 wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
4001 dh = DSA_dup_DH(dsa);
4002 DSA_free(dsa);
4003 if (dh == NULL) {
4004 wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
4005 "params into DH params");
4006 break;
4007 }
4008 break;
4009 }
4010#endif /* !OPENSSL_NO_DSA */
4011 if (dh == NULL) {
4012 wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
4013 "'%s'", dh_file);
4014 return -1;
4015 }
4016
4017 if (SSL_set_tmp_dh(conn->ssl, dh) != 1) {
4018 wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
4019 "%s", dh_file,
4020 ERR_error_string(ERR_get_error(), NULL));
4021 DH_free(dh);
4022 return -1;
4023 }
4024 DH_free(dh);
4025 return 0;
4026#endif /* OPENSSL_NO_DH */
4027}
4028
4029
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004030static int tls_global_dh(struct tls_data *data, const char *dh_file)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004031{
4032#ifdef OPENSSL_NO_DH
4033 if (dh_file == NULL)
4034 return 0;
4035 wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
4036 "dh_file specified");
4037 return -1;
4038#else /* OPENSSL_NO_DH */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004039 SSL_CTX *ssl_ctx = data->ssl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004040 DH *dh;
4041 BIO *bio;
4042
4043 /* TODO: add support for dh_blob */
4044 if (dh_file == NULL)
4045 return 0;
4046 if (ssl_ctx == NULL)
4047 return -1;
4048
4049 bio = BIO_new_file(dh_file, "r");
4050 if (bio == NULL) {
4051 wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
4052 dh_file, ERR_error_string(ERR_get_error(), NULL));
4053 return -1;
4054 }
4055 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
4056 BIO_free(bio);
4057#ifndef OPENSSL_NO_DSA
4058 while (dh == NULL) {
4059 DSA *dsa;
4060 wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
4061 " trying to parse as DSA params", dh_file,
4062 ERR_error_string(ERR_get_error(), NULL));
4063 bio = BIO_new_file(dh_file, "r");
4064 if (bio == NULL)
4065 break;
4066 dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
4067 BIO_free(bio);
4068 if (!dsa) {
4069 wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
4070 "'%s': %s", dh_file,
4071 ERR_error_string(ERR_get_error(), NULL));
4072 break;
4073 }
4074
4075 wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
4076 dh = DSA_dup_DH(dsa);
4077 DSA_free(dsa);
4078 if (dh == NULL) {
4079 wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
4080 "params into DH params");
4081 break;
4082 }
4083 break;
4084 }
4085#endif /* !OPENSSL_NO_DSA */
4086 if (dh == NULL) {
4087 wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
4088 "'%s'", dh_file);
4089 return -1;
4090 }
4091
4092 if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) {
4093 wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
4094 "%s", dh_file,
4095 ERR_error_string(ERR_get_error(), NULL));
4096 DH_free(dh);
4097 return -1;
4098 }
4099 DH_free(dh);
4100 return 0;
4101#endif /* OPENSSL_NO_DH */
4102}
4103
4104
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004105int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
4106 struct tls_random *keys)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004107{
4108 SSL *ssl;
4109
4110 if (conn == NULL || keys == NULL)
4111 return -1;
4112 ssl = conn->ssl;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004113 if (ssl == NULL)
4114 return -1;
4115
4116 os_memset(keys, 0, sizeof(*keys));
4117 keys->client_random = conn->client_random;
4118 keys->client_random_len = SSL_get_client_random(
4119 ssl, conn->client_random, sizeof(conn->client_random));
4120 keys->server_random = conn->server_random;
4121 keys->server_random_len = SSL_get_server_random(
4122 ssl, conn->server_random, sizeof(conn->server_random));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004123
4124 return 0;
4125}
4126
4127
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004128#ifdef OPENSSL_NEED_EAP_FAST_PRF
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004129static int openssl_get_keyblock_size(SSL *ssl)
4130{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004131#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
4132 (defined(LIBRESSL_VERSION_NUMBER) && \
4133 LIBRESSL_VERSION_NUMBER < 0x20700000L)
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004134 const EVP_CIPHER *c;
4135 const EVP_MD *h;
4136 int md_size;
4137
4138 if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
4139 ssl->read_hash == NULL)
4140 return -1;
4141
4142 c = ssl->enc_read_ctx->cipher;
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004143 h = EVP_MD_CTX_md(ssl->read_hash);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004144 if (h)
4145 md_size = EVP_MD_size(h);
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004146 else if (ssl->s3)
4147 md_size = ssl->s3->tmp.new_mac_secret_size;
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004148 else
4149 return -1;
4150
4151 wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
4152 "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
4153 EVP_CIPHER_iv_length(c));
4154 return 2 * (EVP_CIPHER_key_length(c) +
4155 md_size +
4156 EVP_CIPHER_iv_length(c));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004157#else
4158 const SSL_CIPHER *ssl_cipher;
4159 int cipher, digest;
4160 const EVP_CIPHER *c;
4161 const EVP_MD *h;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004162 int mac_key_len, enc_key_len, fixed_iv_len;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004163
4164 ssl_cipher = SSL_get_current_cipher(ssl);
4165 if (!ssl_cipher)
4166 return -1;
4167 cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher);
4168 digest = SSL_CIPHER_get_digest_nid(ssl_cipher);
4169 wpa_printf(MSG_DEBUG, "OpenSSL: cipher nid %d digest nid %d",
4170 cipher, digest);
4171 if (cipher < 0 || digest < 0)
4172 return -1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004173 if (cipher == NID_undef) {
4174 wpa_printf(MSG_DEBUG, "OpenSSL: no cipher in use?!");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004175 return -1;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004176 }
4177 c = EVP_get_cipherbynid(cipher);
4178 if (!c)
4179 return -1;
4180 enc_key_len = EVP_CIPHER_key_length(c);
4181 if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE ||
4182 EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE)
4183 fixed_iv_len = 4; /* only part of IV from PRF */
4184 else
4185 fixed_iv_len = EVP_CIPHER_iv_length(c);
4186 if (digest == NID_undef) {
4187 wpa_printf(MSG_DEBUG, "OpenSSL: no digest in use (e.g., AEAD)");
4188 mac_key_len = 0;
4189 } else {
4190 h = EVP_get_digestbynid(digest);
4191 if (!h)
4192 return -1;
4193 mac_key_len = EVP_MD_size(h);
4194 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004195
4196 wpa_printf(MSG_DEBUG,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08004197 "OpenSSL: keyblock size: mac_key_len=%d enc_key_len=%d fixed_iv_len=%d",
4198 mac_key_len, enc_key_len, fixed_iv_len);
4199 return 2 * (mac_key_len + enc_key_len + fixed_iv_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004200#endif
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004201}
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004202#endif /* OPENSSL_NEED_EAP_FAST_PRF */
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004203
4204
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004205int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
Hai Shalom021b0b52019-04-10 11:17:58 -07004206 const char *label, const u8 *context,
4207 size_t context_len, u8 *out, size_t out_len)
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07004208{
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004209 if (!conn ||
4210 SSL_export_keying_material(conn->ssl, out, out_len, label,
Hai Shalom021b0b52019-04-10 11:17:58 -07004211 os_strlen(label), context, context_len,
4212 context != NULL) != 1)
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004213 return -1;
4214 return 0;
4215}
4216
4217
4218int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
4219 u8 *out, size_t out_len)
4220{
4221#ifdef OPENSSL_NEED_EAP_FAST_PRF
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004222 SSL *ssl;
4223 SSL_SESSION *sess;
4224 u8 *rnd;
4225 int ret = -1;
4226 int skip = 0;
4227 u8 *tmp_out = NULL;
4228 u8 *_out = out;
4229 unsigned char client_random[SSL3_RANDOM_SIZE];
4230 unsigned char server_random[SSL3_RANDOM_SIZE];
4231 unsigned char master_key[64];
4232 size_t master_key_len;
4233 const char *ver;
4234
4235 /*
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004236 * TLS library did not support EAP-FAST key generation, so get the
4237 * needed TLS session parameters and use an internal implementation of
4238 * TLS PRF to derive the key.
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004239 */
4240
4241 if (conn == NULL)
4242 return -1;
4243 ssl = conn->ssl;
4244 if (ssl == NULL)
4245 return -1;
4246 ver = SSL_get_version(ssl);
4247 sess = SSL_get_session(ssl);
4248 if (!ver || !sess)
4249 return -1;
4250
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004251 skip = openssl_get_keyblock_size(ssl);
4252 if (skip < 0)
4253 return -1;
4254 tmp_out = os_malloc(skip + out_len);
4255 if (!tmp_out)
4256 return -1;
4257 _out = tmp_out;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004258
4259 rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
4260 if (!rnd) {
4261 os_free(tmp_out);
4262 return -1;
4263 }
4264
4265 SSL_get_client_random(ssl, client_random, sizeof(client_random));
4266 SSL_get_server_random(ssl, server_random, sizeof(server_random));
4267 master_key_len = SSL_SESSION_get_master_key(sess, master_key,
4268 sizeof(master_key));
4269
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004270 os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE);
4271 os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random, SSL3_RANDOM_SIZE);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004272
4273 if (os_strcmp(ver, "TLSv1.2") == 0) {
4274 tls_prf_sha256(master_key, master_key_len,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004275 "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004276 _out, skip + out_len);
4277 ret = 0;
4278 } else if (tls_prf_sha1_md5(master_key, master_key_len,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004279 "key expansion", rnd, 2 * SSL3_RANDOM_SIZE,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004280 _out, skip + out_len) == 0) {
4281 ret = 0;
4282 }
Hai Shalom81f62d82019-07-22 12:10:00 -07004283 forced_memzero(master_key, sizeof(master_key));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004284 os_free(rnd);
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004285 if (ret == 0)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004286 os_memcpy(out, _out + skip, out_len);
4287 bin_clear_free(tmp_out, skip);
4288
4289 return ret;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004290#else /* OPENSSL_NEED_EAP_FAST_PRF */
4291 wpa_printf(MSG_ERROR,
4292 "OpenSSL: EAP-FAST keys cannot be exported in FIPS mode");
4293 return -1;
4294#endif /* OPENSSL_NEED_EAP_FAST_PRF */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004295}
4296
4297
4298static struct wpabuf *
Roshan Pius3a1667e2018-07-03 15:17:14 -07004299openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004300{
4301 int res;
4302 struct wpabuf *out_data;
4303
4304 /*
4305 * Give TLS handshake data from the server (if available) to OpenSSL
4306 * for processing.
4307 */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004308 if (in_data && wpabuf_len(in_data) > 0 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004309 BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
4310 < 0) {
4311 tls_show_errors(MSG_INFO, __func__,
4312 "Handshake failed - BIO_write");
4313 return NULL;
4314 }
4315
4316 /* Initiate TLS handshake or continue the existing handshake */
Roshan Pius3a1667e2018-07-03 15:17:14 -07004317 if (conn->server)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004318 res = SSL_accept(conn->ssl);
4319 else
4320 res = SSL_connect(conn->ssl);
4321 if (res != 1) {
4322 int err = SSL_get_error(conn->ssl, res);
4323 if (err == SSL_ERROR_WANT_READ)
4324 wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want "
4325 "more data");
4326 else if (err == SSL_ERROR_WANT_WRITE)
4327 wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to "
4328 "write");
4329 else {
4330 tls_show_errors(MSG_INFO, __func__, "SSL_connect");
4331 conn->failed++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004332 if (!conn->server && !conn->client_hello_generated) {
4333 /* The server would not understand TLS Alert
4334 * before ClientHello, so simply terminate
4335 * handshake on this type of error case caused
4336 * by a likely internal error like no ciphers
4337 * available. */
4338 wpa_printf(MSG_DEBUG,
4339 "OpenSSL: Could not generate ClientHello");
4340 conn->write_alerts++;
4341 return NULL;
4342 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004343 }
4344 }
4345
Roshan Pius3a1667e2018-07-03 15:17:14 -07004346 if (!conn->server && !conn->failed)
4347 conn->client_hello_generated = 1;
4348
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004349#ifdef CONFIG_SUITEB
Roshan Pius3a1667e2018-07-03 15:17:14 -07004350 if ((conn->flags & TLS_CONN_SUITEB) && !conn->server &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004351 os_strncmp(SSL_get_cipher(conn->ssl), "DHE-", 4) == 0 &&
4352 conn->server_dh_prime_len < 3072) {
4353 struct tls_context *context = conn->context;
4354
4355 /*
4356 * This should not be reached since earlier cert_cb should have
4357 * terminated the handshake. Keep this check here for extra
4358 * protection if anything goes wrong with the more low-level
4359 * checks based on having to parse the TLS handshake messages.
4360 */
4361 wpa_printf(MSG_DEBUG,
4362 "OpenSSL: Server DH prime length: %d bits",
4363 conn->server_dh_prime_len);
4364
4365 if (context->event_cb) {
4366 union tls_event_data ev;
4367
4368 os_memset(&ev, 0, sizeof(ev));
4369 ev.alert.is_local = 1;
4370 ev.alert.type = "fatal";
4371 ev.alert.description = "insufficient security";
4372 context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
4373 }
4374 /*
4375 * Could send a TLS Alert to the server, but for now, simply
4376 * terminate handshake.
4377 */
4378 conn->failed++;
4379 conn->write_alerts++;
4380 return NULL;
4381 }
4382#endif /* CONFIG_SUITEB */
4383
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004384 /* Get the TLS handshake data to be sent to the server */
4385 res = BIO_ctrl_pending(conn->ssl_out);
4386 wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
4387 out_data = wpabuf_alloc(res);
4388 if (out_data == NULL) {
4389 wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
4390 "handshake output (%d bytes)", res);
4391 if (BIO_reset(conn->ssl_out) < 0) {
4392 tls_show_errors(MSG_INFO, __func__,
4393 "BIO_reset failed");
4394 }
4395 return NULL;
4396 }
4397 res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
4398 res);
4399 if (res < 0) {
4400 tls_show_errors(MSG_INFO, __func__,
4401 "Handshake failed - BIO_read");
4402 if (BIO_reset(conn->ssl_out) < 0) {
4403 tls_show_errors(MSG_INFO, __func__,
4404 "BIO_reset failed");
4405 }
4406 wpabuf_free(out_data);
4407 return NULL;
4408 }
4409 wpabuf_put(out_data, res);
4410
4411 return out_data;
4412}
4413
4414
4415static struct wpabuf *
4416openssl_get_appl_data(struct tls_connection *conn, size_t max_len)
4417{
4418 struct wpabuf *appl_data;
4419 int res;
4420
4421 appl_data = wpabuf_alloc(max_len + 100);
4422 if (appl_data == NULL)
4423 return NULL;
4424
4425 res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
4426 wpabuf_size(appl_data));
4427 if (res < 0) {
4428 int err = SSL_get_error(conn->ssl, res);
4429 if (err == SSL_ERROR_WANT_READ ||
4430 err == SSL_ERROR_WANT_WRITE) {
4431 wpa_printf(MSG_DEBUG, "SSL: No Application Data "
4432 "included");
4433 } else {
4434 tls_show_errors(MSG_INFO, __func__,
4435 "Failed to read possible "
4436 "Application Data");
4437 }
4438 wpabuf_free(appl_data);
4439 return NULL;
4440 }
4441
4442 wpabuf_put(appl_data, res);
4443 wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
4444 "message", appl_data);
4445
4446 return appl_data;
4447}
4448
4449
4450static struct wpabuf *
4451openssl_connection_handshake(struct tls_connection *conn,
4452 const struct wpabuf *in_data,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004453 struct wpabuf **appl_data)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004454{
4455 struct wpabuf *out_data;
4456
4457 if (appl_data)
4458 *appl_data = NULL;
4459
Roshan Pius3a1667e2018-07-03 15:17:14 -07004460 out_data = openssl_handshake(conn, in_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004461 if (out_data == NULL)
4462 return NULL;
Jouni Malinen26af48b2014-04-09 13:02:53 +03004463 if (conn->invalid_hb_used) {
4464 wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
4465 wpabuf_free(out_data);
4466 return NULL;
4467 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004468
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004469 if (SSL_is_init_finished(conn->ssl)) {
4470 wpa_printf(MSG_DEBUG,
4471 "OpenSSL: Handshake finished - resumed=%d",
4472 tls_connection_resumed(conn->ssl_ctx, conn));
Hai Shalom81f62d82019-07-22 12:10:00 -07004473 if (conn->server) {
4474 char *buf;
4475 size_t buflen = 2000;
4476
4477 buf = os_malloc(buflen);
4478 if (buf) {
4479 if (SSL_get_shared_ciphers(conn->ssl, buf,
4480 buflen)) {
4481 buf[buflen - 1] = '\0';
4482 wpa_printf(MSG_DEBUG,
4483 "OpenSSL: Shared ciphers: %s",
4484 buf);
4485 }
4486 os_free(buf);
4487 }
4488 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004489 if (appl_data && in_data)
4490 *appl_data = openssl_get_appl_data(conn,
4491 wpabuf_len(in_data));
4492 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004493
Jouni Malinen26af48b2014-04-09 13:02:53 +03004494 if (conn->invalid_hb_used) {
4495 wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
4496 if (appl_data) {
4497 wpabuf_free(*appl_data);
4498 *appl_data = NULL;
4499 }
4500 wpabuf_free(out_data);
4501 return NULL;
4502 }
4503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004504 return out_data;
4505}
4506
4507
4508struct wpabuf *
4509tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
4510 const struct wpabuf *in_data,
4511 struct wpabuf **appl_data)
4512{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004513 return openssl_connection_handshake(conn, in_data, appl_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004514}
4515
4516
4517struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
4518 struct tls_connection *conn,
4519 const struct wpabuf *in_data,
4520 struct wpabuf **appl_data)
4521{
Roshan Pius3a1667e2018-07-03 15:17:14 -07004522 conn->server = 1;
4523 return openssl_connection_handshake(conn, in_data, appl_data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004524}
4525
4526
4527struct wpabuf * tls_connection_encrypt(void *tls_ctx,
4528 struct tls_connection *conn,
4529 const struct wpabuf *in_data)
4530{
4531 int res;
4532 struct wpabuf *buf;
4533
4534 if (conn == NULL)
4535 return NULL;
4536
4537 /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
4538 if ((res = BIO_reset(conn->ssl_in)) < 0 ||
4539 (res = BIO_reset(conn->ssl_out)) < 0) {
4540 tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
4541 return NULL;
4542 }
4543 res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
4544 if (res < 0) {
4545 tls_show_errors(MSG_INFO, __func__,
4546 "Encryption failed - SSL_write");
4547 return NULL;
4548 }
4549
4550 /* Read encrypted data to be sent to the server */
4551 buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
4552 if (buf == NULL)
4553 return NULL;
4554 res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
4555 if (res < 0) {
4556 tls_show_errors(MSG_INFO, __func__,
4557 "Encryption failed - BIO_read");
4558 wpabuf_free(buf);
4559 return NULL;
4560 }
4561 wpabuf_put(buf, res);
4562
4563 return buf;
4564}
4565
4566
4567struct wpabuf * tls_connection_decrypt(void *tls_ctx,
4568 struct tls_connection *conn,
4569 const struct wpabuf *in_data)
4570{
4571 int res;
4572 struct wpabuf *buf;
4573
4574 /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
4575 res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
4576 wpabuf_len(in_data));
4577 if (res < 0) {
4578 tls_show_errors(MSG_INFO, __func__,
4579 "Decryption failed - BIO_write");
4580 return NULL;
4581 }
4582 if (BIO_reset(conn->ssl_out) < 0) {
4583 tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
4584 return NULL;
4585 }
4586
4587 /* Read decrypted data for further processing */
4588 /*
4589 * Even though we try to disable TLS compression, it is possible that
4590 * this cannot be done with all TLS libraries. Add extra buffer space
4591 * to handle the possibility of the decrypted data being longer than
4592 * input data.
4593 */
4594 buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
4595 if (buf == NULL)
4596 return NULL;
4597 res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
4598 if (res < 0) {
Hai Shalom60840252021-02-19 19:02:11 -08004599 int err = SSL_get_error(conn->ssl, res);
4600
4601 if (err == SSL_ERROR_WANT_READ) {
4602 wpa_printf(MSG_DEBUG,
4603 "SSL: SSL_connect - want more data");
4604 res = 0;
4605 } else {
4606 tls_show_errors(MSG_INFO, __func__,
4607 "Decryption failed - SSL_read");
4608 wpabuf_free(buf);
4609 return NULL;
4610 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004611 }
4612 wpabuf_put(buf, res);
4613
Jouni Malinen26af48b2014-04-09 13:02:53 +03004614 if (conn->invalid_hb_used) {
4615 wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
4616 wpabuf_free(buf);
4617 return NULL;
4618 }
4619
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004620 return buf;
4621}
4622
4623
4624int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
4625{
Hai Shalomce48b4a2018-09-05 11:41:35 -07004626 return conn ? SSL_session_reused(conn->ssl) : 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004627}
4628
4629
4630int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
4631 u8 *ciphers)
4632{
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004633 char buf[500], *pos, *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004634 u8 *c;
4635 int ret;
4636
4637 if (conn == NULL || conn->ssl == NULL || ciphers == NULL)
4638 return -1;
4639
4640 buf[0] = '\0';
4641 pos = buf;
4642 end = pos + sizeof(buf);
4643
4644 c = ciphers;
4645 while (*c != TLS_CIPHER_NONE) {
4646 const char *suite;
4647
4648 switch (*c) {
4649 case TLS_CIPHER_RC4_SHA:
4650 suite = "RC4-SHA";
4651 break;
4652 case TLS_CIPHER_AES128_SHA:
4653 suite = "AES128-SHA";
4654 break;
4655 case TLS_CIPHER_RSA_DHE_AES128_SHA:
4656 suite = "DHE-RSA-AES128-SHA";
4657 break;
4658 case TLS_CIPHER_ANON_DH_AES128_SHA:
4659 suite = "ADH-AES128-SHA";
4660 break;
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004661 case TLS_CIPHER_RSA_DHE_AES256_SHA:
4662 suite = "DHE-RSA-AES256-SHA";
4663 break;
4664 case TLS_CIPHER_AES256_SHA:
4665 suite = "AES256-SHA";
4666 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004667 default:
4668 wpa_printf(MSG_DEBUG, "TLS: Unsupported "
4669 "cipher selection: %d", *c);
4670 return -1;
4671 }
4672 ret = os_snprintf(pos, end - pos, ":%s", suite);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004673 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004674 break;
4675 pos += ret;
4676
4677 c++;
4678 }
Hai Shalom81f62d82019-07-22 12:10:00 -07004679 if (!buf[0]) {
4680 wpa_printf(MSG_DEBUG, "OpenSSL: No ciphers listed");
4681 return -1;
4682 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004683
4684 wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
4685
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08004686#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
Hai Shalom81f62d82019-07-22 12:10:00 -07004687#ifdef EAP_FAST_OR_TEAP
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004688 if (os_strstr(buf, ":ADH-")) {
4689 /*
4690 * Need to drop to security level 0 to allow anonymous
4691 * cipher suites for EAP-FAST.
4692 */
4693 SSL_set_security_level(conn->ssl, 0);
4694 } else if (SSL_get_security_level(conn->ssl) == 0) {
4695 /* Force at least security level 1 */
4696 SSL_set_security_level(conn->ssl, 1);
4697 }
Hai Shalom81f62d82019-07-22 12:10:00 -07004698#endif /* EAP_FAST_OR_TEAP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004699#endif
4700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004701 if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
4702 tls_show_errors(MSG_INFO, __func__,
4703 "Cipher suite configuration failed");
4704 return -1;
4705 }
4706
4707 return 0;
4708}
4709
4710
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004711int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
4712 char *buf, size_t buflen)
4713{
4714 const char *name;
4715 if (conn == NULL || conn->ssl == NULL)
4716 return -1;
4717
4718 name = SSL_get_version(conn->ssl);
4719 if (name == NULL)
4720 return -1;
4721
4722 os_strlcpy(buf, name, buflen);
4723 return 0;
4724}
4725
4726
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004727int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
4728 char *buf, size_t buflen)
4729{
4730 const char *name;
4731 if (conn == NULL || conn->ssl == NULL)
4732 return -1;
4733
4734 name = SSL_get_cipher(conn->ssl);
4735 if (name == NULL)
4736 return -1;
4737
4738 os_strlcpy(buf, name, buflen);
4739 return 0;
4740}
4741
4742
4743int tls_connection_enable_workaround(void *ssl_ctx,
4744 struct tls_connection *conn)
4745{
4746 SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
4747
4748 return 0;
4749}
4750
4751
Hai Shalom81f62d82019-07-22 12:10:00 -07004752#ifdef EAP_FAST_OR_TEAP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004753/* ClientHello TLS extensions require a patch to openssl, so this function is
4754 * commented out unless explicitly needed for EAP-FAST in order to be able to
4755 * build this file with unmodified openssl. */
4756int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
4757 int ext_type, const u8 *data,
4758 size_t data_len)
4759{
4760 if (conn == NULL || conn->ssl == NULL || ext_type != 35)
4761 return -1;
4762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004763 if (SSL_set_session_ticket_ext(conn->ssl, (void *) data,
4764 data_len) != 1)
4765 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766
4767 return 0;
4768}
Hai Shalom81f62d82019-07-22 12:10:00 -07004769#endif /* EAP_FAST_OR_TEAP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004770
4771
4772int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
4773{
4774 if (conn == NULL)
4775 return -1;
4776 return conn->failed;
4777}
4778
4779
4780int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
4781{
4782 if (conn == NULL)
4783 return -1;
4784 return conn->read_alerts;
4785}
4786
4787
4788int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
4789{
4790 if (conn == NULL)
4791 return -1;
4792 return conn->write_alerts;
4793}
4794
4795
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004796#ifdef HAVE_OCSP
4797
4798static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
4799{
4800#ifndef CONFIG_NO_STDOUT_DEBUG
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004801 BIO *out;
4802 size_t rlen;
4803 char *txt;
4804 int res;
4805
4806 if (wpa_debug_level > MSG_DEBUG)
4807 return;
4808
4809 out = BIO_new(BIO_s_mem());
4810 if (!out)
4811 return;
4812
4813 OCSP_RESPONSE_print(out, rsp, 0);
4814 rlen = BIO_ctrl_pending(out);
4815 txt = os_malloc(rlen + 1);
4816 if (!txt) {
4817 BIO_free(out);
4818 return;
4819 }
4820
4821 res = BIO_read(out, txt, rlen);
4822 if (res > 0) {
4823 txt[res] = '\0';
4824 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt);
4825 }
4826 os_free(txt);
4827 BIO_free(out);
4828#endif /* CONFIG_NO_STDOUT_DEBUG */
4829}
4830
4831
4832static int ocsp_resp_cb(SSL *s, void *arg)
4833{
4834 struct tls_connection *conn = arg;
4835 const unsigned char *p;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004836 int len, status, reason, res;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004837 OCSP_RESPONSE *rsp;
4838 OCSP_BASICRESP *basic;
4839 OCSP_CERTID *id;
4840 ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004841 X509_STORE *store;
4842 STACK_OF(X509) *certs = NULL;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004843
4844 len = SSL_get_tlsext_status_ocsp_resp(s, &p);
4845 if (!p) {
4846 wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
4847 return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
4848 }
4849
4850 wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
4851
4852 rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
4853 if (!rsp) {
4854 wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
4855 return 0;
4856 }
4857
4858 ocsp_debug_print_resp(rsp);
4859
4860 status = OCSP_response_status(rsp);
4861 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
4862 wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
4863 status, OCSP_response_status_str(status));
4864 return 0;
4865 }
4866
4867 basic = OCSP_response_get1_basic(rsp);
4868 if (!basic) {
4869 wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
4870 return 0;
4871 }
4872
Dmitry Shmidt216983b2015-02-06 10:50:36 -08004873 store = SSL_CTX_get_cert_store(conn->ssl_ctx);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004874 if (conn->peer_issuer) {
Dmitry Shmidt71757432014-06-02 13:50:35 -07004875 debug_print_cert(conn->peer_issuer, "Add OCSP issuer");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004876
4877 if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
4878 tls_show_errors(MSG_INFO, __func__,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004879 "OpenSSL: Could not add issuer to certificate store");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004880 }
4881 certs = sk_X509_new_null();
4882 if (certs) {
4883 X509 *cert;
4884 cert = X509_dup(conn->peer_issuer);
4885 if (cert && !sk_X509_push(certs, cert)) {
4886 tls_show_errors(
4887 MSG_INFO, __func__,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004888 "OpenSSL: Could not add issuer to OCSP responder trust store");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004889 X509_free(cert);
4890 sk_X509_free(certs);
4891 certs = NULL;
4892 }
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004893 if (certs && conn->peer_issuer_issuer) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004894 cert = X509_dup(conn->peer_issuer_issuer);
4895 if (cert && !sk_X509_push(certs, cert)) {
4896 tls_show_errors(
4897 MSG_INFO, __func__,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08004898 "OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004899 X509_free(cert);
4900 }
4901 }
4902 }
4903 }
4904
4905 status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
4906 sk_X509_pop_free(certs, X509_free);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004907 if (status <= 0) {
4908 tls_show_errors(MSG_INFO, __func__,
4909 "OpenSSL: OCSP response failed verification");
4910 OCSP_BASICRESP_free(basic);
4911 OCSP_RESPONSE_free(rsp);
4912 return 0;
4913 }
4914
4915 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
4916
Dmitry Shmidt56052862013-10-04 10:23:25 -07004917 if (!conn->peer_cert) {
4918 wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
4919 OCSP_BASICRESP_free(basic);
4920 OCSP_RESPONSE_free(rsp);
4921 return 0;
4922 }
4923
4924 if (!conn->peer_issuer) {
4925 wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004926 OCSP_BASICRESP_free(basic);
4927 OCSP_RESPONSE_free(rsp);
4928 return 0;
4929 }
4930
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004931 id = OCSP_cert_to_id(EVP_sha256(), conn->peer_cert, conn->peer_issuer);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004932 if (!id) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004933 wpa_printf(MSG_DEBUG,
4934 "OpenSSL: Could not create OCSP certificate identifier (SHA256)");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004935 OCSP_BASICRESP_free(basic);
4936 OCSP_RESPONSE_free(rsp);
4937 return 0;
4938 }
4939
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004940 res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
4941 &this_update, &next_update);
4942 if (!res) {
Hai Shalom81f62d82019-07-22 12:10:00 -07004943 OCSP_CERTID_free(id);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004944 id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
4945 if (!id) {
4946 wpa_printf(MSG_DEBUG,
4947 "OpenSSL: Could not create OCSP certificate identifier (SHA1)");
4948 OCSP_BASICRESP_free(basic);
4949 OCSP_RESPONSE_free(rsp);
4950 return 0;
4951 }
4952
4953 res = OCSP_resp_find_status(basic, id, &status, &reason,
4954 &produced_at, &this_update,
4955 &next_update);
4956 }
4957
4958 if (!res) {
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004959 wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
4960 (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
4961 " (OCSP not required)");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004962 OCSP_CERTID_free(id);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004963 OCSP_BASICRESP_free(basic);
4964 OCSP_RESPONSE_free(rsp);
4965 return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
4966 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004967 OCSP_CERTID_free(id);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004968
4969 if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
4970 tls_show_errors(MSG_INFO, __func__,
4971 "OpenSSL: OCSP status times invalid");
4972 OCSP_BASICRESP_free(basic);
4973 OCSP_RESPONSE_free(rsp);
4974 return 0;
4975 }
4976
4977 OCSP_BASICRESP_free(basic);
4978 OCSP_RESPONSE_free(rsp);
4979
4980 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
4981 OCSP_cert_status_str(status));
4982
4983 if (status == V_OCSP_CERTSTATUS_GOOD)
4984 return 1;
4985 if (status == V_OCSP_CERTSTATUS_REVOKED)
4986 return 0;
4987 if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
4988 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
4989 return 0;
4990 }
Dmitry Shmidt051af732013-10-22 13:52:46 -07004991 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07004992 return 1;
4993}
4994
4995
4996static int ocsp_status_cb(SSL *s, void *arg)
4997{
4998 char *tmp;
4999 char *resp;
5000 size_t len;
5001
5002 if (tls_global->ocsp_stapling_response == NULL) {
5003 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured");
5004 return SSL_TLSEXT_ERR_OK;
5005 }
5006
5007 resp = os_readfile(tls_global->ocsp_stapling_response, &len);
5008 if (resp == NULL) {
5009 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file");
5010 /* TODO: Build OCSPResponse with responseStatus = internalError
5011 */
5012 return SSL_TLSEXT_ERR_OK;
5013 }
5014 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response");
5015 tmp = OPENSSL_malloc(len);
5016 if (tmp == NULL) {
5017 os_free(resp);
5018 return SSL_TLSEXT_ERR_ALERT_FATAL;
5019 }
5020
5021 os_memcpy(tmp, resp, len);
5022 os_free(resp);
5023 SSL_set_tlsext_status_ocsp_resp(s, tmp, len);
5024
5025 return SSL_TLSEXT_ERR_OK;
5026}
5027
5028#endif /* HAVE_OCSP */
5029
5030
Hai Shalomfdcde762020-04-02 11:19:20 -07005031static size_t max_str_len(const char **lines)
5032{
5033 const char **p;
5034 size_t max_len = 0;
5035
5036 for (p = lines; *p; p++) {
5037 size_t len = os_strlen(*p);
5038
5039 if (len > max_len)
5040 max_len = len;
5041 }
5042
5043 return max_len;
5044}
5045
5046
5047static int match_lines_in_file(const char *path, const char **lines)
5048{
5049 FILE *f;
5050 char *buf;
5051 size_t bufsize;
5052 int found = 0, is_linestart = 1;
5053
5054 bufsize = max_str_len(lines) + sizeof("\r\n");
5055 buf = os_malloc(bufsize);
5056 if (!buf)
5057 return 0;
5058
5059 f = fopen(path, "r");
5060 if (!f) {
5061 os_free(buf);
5062 return 0;
5063 }
5064
5065 while (!found && fgets(buf, bufsize, f)) {
5066 int is_lineend;
5067 size_t len;
5068 const char **p;
5069
5070 len = strcspn(buf, "\r\n");
5071 is_lineend = buf[len] != '\0';
5072 buf[len] = '\0';
5073
5074 if (is_linestart && is_lineend) {
5075 for (p = lines; !found && *p; p++)
5076 found = os_strcmp(buf, *p) == 0;
5077 }
5078 is_linestart = is_lineend;
5079 }
5080
5081 fclose(f);
5082 bin_clear_free(buf, bufsize);
5083
5084 return found;
5085}
5086
5087
5088static int is_tpm2_key(const char *path)
5089{
5090 /* Check both new and old format of TPM2 PEM guard tag */
5091 static const char *tpm2_tags[] = {
5092 "-----BEGIN TSS2 PRIVATE KEY-----",
5093 "-----BEGIN TSS2 KEY BLOB-----",
5094 NULL
5095 };
5096
5097 return match_lines_in_file(path, tpm2_tags);
5098}
5099
5100
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005101int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
5102 const struct tls_connection_params *params)
5103{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005104 struct tls_data *data = tls_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005105 int ret;
5106 unsigned long err;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005107 int can_pkcs11 = 0;
5108 const char *key_id = params->key_id;
5109 const char *cert_id = params->cert_id;
5110 const char *ca_cert_id = params->ca_cert_id;
5111 const char *engine_id = params->engine ? params->engine_id : NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005112 const char *ciphers;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005113
5114 if (conn == NULL)
5115 return -1;
5116
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -08005117 if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
5118 wpa_printf(MSG_INFO,
5119 "OpenSSL: ocsp=3 not supported");
5120 return -1;
5121 }
5122
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005123 /*
5124 * If the engine isn't explicitly configured, and any of the
5125 * cert/key fields are actually PKCS#11 URIs, then automatically
5126 * use the PKCS#11 ENGINE.
5127 */
5128 if (!engine_id || os_strcmp(engine_id, "pkcs11") == 0)
5129 can_pkcs11 = 1;
5130
5131 if (!key_id && params->private_key && can_pkcs11 &&
5132 os_strncmp(params->private_key, "pkcs11:", 7) == 0) {
5133 can_pkcs11 = 2;
5134 key_id = params->private_key;
5135 }
5136
5137 if (!cert_id && params->client_cert && can_pkcs11 &&
5138 os_strncmp(params->client_cert, "pkcs11:", 7) == 0) {
5139 can_pkcs11 = 2;
5140 cert_id = params->client_cert;
5141 }
5142
5143 if (!ca_cert_id && params->ca_cert && can_pkcs11 &&
5144 os_strncmp(params->ca_cert, "pkcs11:", 7) == 0) {
5145 can_pkcs11 = 2;
5146 ca_cert_id = params->ca_cert;
5147 }
5148
5149 /* If we need to automatically enable the PKCS#11 ENGINE, do so. */
5150 if (can_pkcs11 == 2 && !engine_id)
5151 engine_id = "pkcs11";
5152
Hai Shalomfdcde762020-04-02 11:19:20 -07005153 /* If private_key points to a TPM2-wrapped key, automatically enable
5154 * tpm2 engine and use it to unwrap the key. */
5155 if (params->private_key &&
5156 (!engine_id || os_strcmp(engine_id, "tpm2") == 0) &&
5157 is_tpm2_key(params->private_key)) {
5158 wpa_printf(MSG_DEBUG, "OpenSSL: Found TPM2 wrapped key %s",
5159 params->private_key);
5160 key_id = key_id ? key_id : params->private_key;
5161 engine_id = engine_id ? engine_id : "tpm2";
5162 }
5163
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005164#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005165#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005166 if (params->flags & TLS_CONN_EAP_FAST) {
5167 wpa_printf(MSG_DEBUG,
5168 "OpenSSL: Use TLSv1_method() for EAP-FAST");
5169 if (SSL_set_ssl_method(conn->ssl, TLSv1_method()) != 1) {
5170 tls_show_errors(MSG_INFO, __func__,
5171 "Failed to set TLSv1_method() for EAP-FAST");
5172 return -1;
5173 }
5174 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005175#endif
Roshan Pius3a1667e2018-07-03 15:17:14 -07005176#if OPENSSL_VERSION_NUMBER >= 0x10101000L
5177#ifdef SSL_OP_NO_TLSv1_3
5178 if (params->flags & TLS_CONN_EAP_FAST) {
5179 /* Need to disable TLS v1.3 at least for now since OpenSSL 1.1.1
5180 * refuses to start the handshake with the modified ciphersuite
5181 * list (no TLS v1.3 ciphersuites included) for EAP-FAST. */
5182 wpa_printf(MSG_DEBUG, "OpenSSL: Disable TLSv1.3 for EAP-FAST");
5183 SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_3);
5184 }
5185#endif /* SSL_OP_NO_TLSv1_3 */
5186#endif
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005187#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005188
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005189 while ((err = ERR_get_error())) {
5190 wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
5191 __func__, ERR_error_string(err, NULL));
5192 }
5193
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005194 if (engine_id) {
Hai Shalomfdcde762020-04-02 11:19:20 -07005195 wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine %s",
5196 engine_id);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005197 ret = tls_engine_init(conn, engine_id, params->pin,
5198 key_id, cert_id, ca_cert_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005199 if (ret)
5200 return ret;
5201 }
5202 if (tls_connection_set_subject_match(conn,
5203 params->subject_match,
Dmitry Shmidt051af732013-10-22 13:52:46 -07005204 params->altsubject_match,
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08005205 params->suffix_match,
Hai Shalom021b0b52019-04-10 11:17:58 -07005206 params->domain_match,
Hai Shalom22171592021-04-02 16:05:23 -07005207 params->check_cert_subject)) {
5208 wpa_printf(MSG_ERROR, "TLS: Failed to set subject match");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005209 return -1;
Hai Shalom22171592021-04-02 16:05:23 -07005210 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005211
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005212 if (engine_id && ca_cert_id) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005213 if (tls_connection_engine_ca_cert(data, conn, ca_cert_id))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005214 return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005215 } else if (tls_connection_ca_cert(data, conn, params->ca_cert,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005216 params->ca_cert_blob,
5217 params->ca_cert_blob_len,
Hai Shalom22171592021-04-02 16:05:23 -07005218 params->ca_path)) {
5219 wpa_printf(MSG_ERROR, "TLS: Failed to parse Root CA certificate");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005220 return -1;
Hai Shalom22171592021-04-02 16:05:23 -07005221 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005222
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005223 if (engine_id && cert_id) {
5224 if (tls_connection_engine_client_cert(conn, cert_id))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005225 return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
5226 } else if (tls_connection_client_cert(conn, params->client_cert,
5227 params->client_cert_blob,
Hai Shalom22171592021-04-02 16:05:23 -07005228 params->client_cert_blob_len)) {
5229 wpa_printf(MSG_ERROR, "TLS: Failed to parse client certificate");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005230 return -1;
Hai Shalom22171592021-04-02 16:05:23 -07005231 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005232
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005233 if (engine_id && key_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005234 wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
5235 if (tls_connection_engine_private_key(conn))
5236 return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005237 } else if (tls_connection_private_key(data, conn,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005238 params->private_key,
5239 params->private_key_passwd,
5240 params->private_key_blob,
5241 params->private_key_blob_len)) {
5242 wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'",
5243 params->private_key);
5244 return -1;
5245 }
5246
5247 if (tls_connection_dh(conn, params->dh_file)) {
5248 wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
5249 params->dh_file);
5250 return -1;
5251 }
5252
Roshan Pius3a1667e2018-07-03 15:17:14 -07005253 ciphers = params->openssl_ciphers;
5254#ifdef CONFIG_SUITEB
5255#ifdef OPENSSL_IS_BORINGSSL
5256 if (ciphers && os_strcmp(ciphers, "SUITEB192") == 0) {
5257 /* BoringSSL removed support for SUITEB192, so need to handle
5258 * this with hardcoded ciphersuite and additional checks for
5259 * other parameters. */
5260 ciphers = "ECDHE-ECDSA-AES256-GCM-SHA384";
5261 }
5262#endif /* OPENSSL_IS_BORINGSSL */
5263#endif /* CONFIG_SUITEB */
5264 if (ciphers && SSL_set_cipher_list(conn->ssl, ciphers) != 1) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005265 wpa_printf(MSG_INFO,
5266 "OpenSSL: Failed to set cipher string '%s'",
Roshan Pius3a1667e2018-07-03 15:17:14 -07005267 ciphers);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005268 return -1;
5269 }
5270
Hai Shalom74f70d42019-02-11 14:42:39 -08005271 if (!params->openssl_ecdh_curves) {
5272#ifndef OPENSSL_IS_BORINGSSL
5273#ifndef OPENSSL_NO_EC
5274#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
5275 (OPENSSL_VERSION_NUMBER < 0x10100000L)
5276 if (SSL_set_ecdh_auto(conn->ssl, 1) != 1) {
5277 wpa_printf(MSG_INFO,
5278 "OpenSSL: Failed to set ECDH curves to auto");
5279 return -1;
5280 }
5281#endif /* >= 1.0.2 && < 1.1.0 */
5282#endif /* OPENSSL_NO_EC */
5283#endif /* OPENSSL_IS_BORINGSSL */
5284 } else if (params->openssl_ecdh_curves[0]) {
5285#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER < 0x10002000L)
5286 wpa_printf(MSG_INFO,
5287 "OpenSSL: ECDH configuration nnot supported");
5288 return -1;
5289#else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */
5290#ifndef OPENSSL_NO_EC
5291 if (SSL_set1_curves_list(conn->ssl,
5292 params->openssl_ecdh_curves) != 1) {
5293 wpa_printf(MSG_INFO,
5294 "OpenSSL: Failed to set ECDH curves '%s'",
5295 params->openssl_ecdh_curves);
5296 return -1;
5297 }
5298#else /* OPENSSL_NO_EC */
5299 wpa_printf(MSG_INFO, "OpenSSL: ECDH not supported");
5300 return -1;
5301#endif /* OPENSSL_NO_EC */
5302#endif /* OPENSSL_IS_BORINGSSL */
5303 }
5304
Roshan Pius3a1667e2018-07-03 15:17:14 -07005305 if (tls_set_conn_flags(conn, params->flags,
Hai Shalom22171592021-04-02 16:05:23 -07005306 params->openssl_ciphers) < 0) {
5307 wpa_printf(MSG_ERROR, "TLS: Failed to set connection flags");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005308 return -1;
Hai Shalom22171592021-04-02 16:05:23 -07005309 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005310
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005311#ifdef OPENSSL_IS_BORINGSSL
5312 if (params->flags & TLS_CONN_REQUEST_OCSP) {
5313 SSL_enable_ocsp_stapling(conn->ssl);
5314 }
5315#else /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005316#ifdef HAVE_OCSP
5317 if (params->flags & TLS_CONN_REQUEST_OCSP) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005318 SSL_CTX *ssl_ctx = data->ssl;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005319 SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp);
5320 SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
5321 SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn);
5322 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005323#else /* HAVE_OCSP */
5324 if (params->flags & TLS_CONN_REQUIRE_OCSP) {
5325 wpa_printf(MSG_INFO,
5326 "OpenSSL: No OCSP support included - reject configuration");
5327 return -1;
5328 }
5329 if (params->flags & TLS_CONN_REQUEST_OCSP) {
5330 wpa_printf(MSG_DEBUG,
5331 "OpenSSL: No OCSP support included - allow optional OCSP case to continue");
5332 }
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005333#endif /* HAVE_OCSP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005334#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005335
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07005336 conn->flags = params->flags;
5337
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005338 tls_get_errors(data);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005339
5340 return 0;
5341}
5342
5343
Hai Shalom81f62d82019-07-22 12:10:00 -07005344static void openssl_debug_dump_cipher_list(SSL_CTX *ssl_ctx)
5345{
5346 SSL *ssl;
5347 int i;
5348
5349 ssl = SSL_new(ssl_ctx);
5350 if (!ssl)
5351 return;
5352
5353 wpa_printf(MSG_DEBUG,
5354 "OpenSSL: Enabled cipher suites in priority order");
5355 for (i = 0; ; i++) {
5356 const char *cipher;
5357
5358 cipher = SSL_get_cipher_list(ssl, i);
5359 if (!cipher)
5360 break;
5361 wpa_printf(MSG_DEBUG, "Cipher %d: %s", i, cipher);
5362 }
5363
5364 SSL_free(ssl);
5365}
5366
5367
5368#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
5369
5370static const char * openssl_pkey_type_str(const EVP_PKEY *pkey)
5371{
5372 if (!pkey)
5373 return "NULL";
5374 switch (EVP_PKEY_type(EVP_PKEY_id(pkey))) {
5375 case EVP_PKEY_RSA:
5376 return "RSA";
5377 case EVP_PKEY_DSA:
5378 return "DSA";
5379 case EVP_PKEY_DH:
5380 return "DH";
5381 case EVP_PKEY_EC:
5382 return "EC";
5383 }
5384 return "?";
5385}
5386
5387
5388static void openssl_debug_dump_certificate(int i, X509 *cert)
5389{
5390 char buf[256];
5391 EVP_PKEY *pkey;
5392 ASN1_INTEGER *ser;
5393 char serial_num[128];
5394
Hai Shalom60840252021-02-19 19:02:11 -08005395 if (!cert)
5396 return;
5397
Hai Shalom81f62d82019-07-22 12:10:00 -07005398 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
5399
5400 ser = X509_get_serialNumber(cert);
5401 if (ser)
5402 wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
5403 ASN1_STRING_get0_data(ser),
5404 ASN1_STRING_length(ser));
5405 else
5406 serial_num[0] = '\0';
5407
5408 pkey = X509_get_pubkey(cert);
5409 wpa_printf(MSG_DEBUG, "%d: %s (%s) %s", i, buf,
5410 openssl_pkey_type_str(pkey), serial_num);
5411 EVP_PKEY_free(pkey);
5412}
5413
5414
5415static void openssl_debug_dump_certificates(SSL_CTX *ssl_ctx)
5416{
5417 STACK_OF(X509) *certs;
5418
5419 wpa_printf(MSG_DEBUG, "OpenSSL: Configured certificate chain");
5420 if (SSL_CTX_get0_chain_certs(ssl_ctx, &certs) == 1) {
5421 int i;
5422
5423 for (i = sk_X509_num(certs); i > 0; i--)
5424 openssl_debug_dump_certificate(i, sk_X509_value(certs,
5425 i - 1));
5426 }
5427 openssl_debug_dump_certificate(0, SSL_CTX_get0_certificate(ssl_ctx));
5428}
5429
5430#endif
5431
5432
5433static void openssl_debug_dump_certificate_chains(SSL_CTX *ssl_ctx)
5434{
5435#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
5436 int res;
5437
5438 for (res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST);
5439 res == 1;
5440 res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_NEXT))
5441 openssl_debug_dump_certificates(ssl_ctx);
5442
5443 SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST);
5444#endif
5445}
5446
5447
5448static void openssl_debug_dump_ctx(SSL_CTX *ssl_ctx)
5449{
5450 openssl_debug_dump_cipher_list(ssl_ctx);
5451 openssl_debug_dump_certificate_chains(ssl_ctx);
5452}
5453
5454
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005455int tls_global_set_params(void *tls_ctx,
5456 const struct tls_connection_params *params)
5457{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005458 struct tls_data *data = tls_ctx;
5459 SSL_CTX *ssl_ctx = data->ssl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005460 unsigned long err;
5461
5462 while ((err = ERR_get_error())) {
5463 wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
5464 __func__, ERR_error_string(err, NULL));
5465 }
5466
Hai Shalom021b0b52019-04-10 11:17:58 -07005467 os_free(data->check_cert_subject);
5468 data->check_cert_subject = NULL;
5469 if (params->check_cert_subject) {
5470 data->check_cert_subject =
5471 os_strdup(params->check_cert_subject);
5472 if (!data->check_cert_subject)
5473 return -1;
5474 }
5475
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005476 if (tls_global_ca_cert(data, params->ca_cert) ||
5477 tls_global_client_cert(data, params->client_cert) ||
5478 tls_global_private_key(data, params->private_key,
5479 params->private_key_passwd) ||
Hai Shalom81f62d82019-07-22 12:10:00 -07005480 tls_global_client_cert(data, params->client_cert2) ||
5481 tls_global_private_key(data, params->private_key2,
5482 params->private_key_passwd2) ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005483 tls_global_dh(data, params->dh_file)) {
5484 wpa_printf(MSG_INFO, "TLS: Failed to set global parameters");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005485 return -1;
5486 }
5487
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005488 if (params->openssl_ciphers &&
5489 SSL_CTX_set_cipher_list(ssl_ctx, params->openssl_ciphers) != 1) {
5490 wpa_printf(MSG_INFO,
5491 "OpenSSL: Failed to set cipher string '%s'",
5492 params->openssl_ciphers);
5493 return -1;
5494 }
5495
Hai Shalom74f70d42019-02-11 14:42:39 -08005496 if (!params->openssl_ecdh_curves) {
5497#ifndef OPENSSL_IS_BORINGSSL
5498#ifndef OPENSSL_NO_EC
5499#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
5500 (OPENSSL_VERSION_NUMBER < 0x10100000L)
5501 if (SSL_CTX_set_ecdh_auto(ssl_ctx, 1) != 1) {
5502 wpa_printf(MSG_INFO,
5503 "OpenSSL: Failed to set ECDH curves to auto");
5504 return -1;
5505 }
5506#endif /* >= 1.0.2 && < 1.1.0 */
5507#endif /* OPENSSL_NO_EC */
5508#endif /* OPENSSL_IS_BORINGSSL */
5509 } else if (params->openssl_ecdh_curves[0]) {
5510#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER < 0x10002000L)
5511 wpa_printf(MSG_INFO,
5512 "OpenSSL: ECDH configuration nnot supported");
5513 return -1;
5514#else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */
5515#ifndef OPENSSL_NO_EC
Hai Shalom5f92bc92019-04-18 11:54:11 -07005516#if OPENSSL_VERSION_NUMBER < 0x10100000L
5517 SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
5518#endif
Hai Shalom74f70d42019-02-11 14:42:39 -08005519 if (SSL_CTX_set1_curves_list(ssl_ctx,
5520 params->openssl_ecdh_curves) !=
5521 1) {
5522 wpa_printf(MSG_INFO,
5523 "OpenSSL: Failed to set ECDH curves '%s'",
5524 params->openssl_ecdh_curves);
5525 return -1;
5526 }
5527#else /* OPENSSL_NO_EC */
5528 wpa_printf(MSG_INFO, "OpenSSL: ECDH not supported");
5529 return -1;
5530#endif /* OPENSSL_NO_EC */
5531#endif /* OPENSSL_IS_BORINGSSL */
5532 }
5533
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005534#ifdef SSL_OP_NO_TICKET
5535 if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
5536 SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
5537 else
5538 SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET);
5539#endif /* SSL_OP_NO_TICKET */
5540
Dmitry Shmidt34af3062013-07-11 10:46:32 -07005541#ifdef HAVE_OCSP
5542 SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb);
5543 SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx);
5544 os_free(tls_global->ocsp_stapling_response);
5545 if (params->ocsp_stapling_response)
5546 tls_global->ocsp_stapling_response =
5547 os_strdup(params->ocsp_stapling_response);
5548 else
5549 tls_global->ocsp_stapling_response = NULL;
5550#endif /* HAVE_OCSP */
5551
Hai Shalom81f62d82019-07-22 12:10:00 -07005552 openssl_debug_dump_ctx(ssl_ctx);
5553
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005554 return 0;
5555}
5556
5557
Hai Shalom81f62d82019-07-22 12:10:00 -07005558#ifdef EAP_FAST_OR_TEAP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005559/* Pre-shared secred requires a patch to openssl, so this function is
5560 * commented out unless explicitly needed for EAP-FAST in order to be able to
5561 * build this file with unmodified openssl. */
5562
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -08005563#if (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07005564static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
5565 STACK_OF(SSL_CIPHER) *peer_ciphers,
5566 const SSL_CIPHER **cipher, void *arg)
5567#else /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005568static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
5569 STACK_OF(SSL_CIPHER) *peer_ciphers,
5570 SSL_CIPHER **cipher, void *arg)
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07005571#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005572{
5573 struct tls_connection *conn = arg;
5574 int ret;
5575
Roshan Pius3a1667e2018-07-03 15:17:14 -07005576#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
5577 (defined(LIBRESSL_VERSION_NUMBER) && \
5578 LIBRESSL_VERSION_NUMBER < 0x20700000L)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005579 if (conn == NULL || conn->session_ticket_cb == NULL)
5580 return 0;
5581
5582 ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
5583 conn->session_ticket,
5584 conn->session_ticket_len,
5585 s->s3->client_random,
5586 s->s3->server_random, secret);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005587#else
5588 unsigned char client_random[SSL3_RANDOM_SIZE];
5589 unsigned char server_random[SSL3_RANDOM_SIZE];
5590
5591 if (conn == NULL || conn->session_ticket_cb == NULL)
5592 return 0;
5593
5594 SSL_get_client_random(s, client_random, sizeof(client_random));
5595 SSL_get_server_random(s, server_random, sizeof(server_random));
5596
5597 ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
5598 conn->session_ticket,
5599 conn->session_ticket_len,
5600 client_random,
5601 server_random, secret);
5602#endif
5603
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005604 os_free(conn->session_ticket);
5605 conn->session_ticket = NULL;
5606
5607 if (ret <= 0)
5608 return 0;
5609
5610 *secret_len = SSL_MAX_MASTER_KEY_LENGTH;
5611 return 1;
5612}
5613
5614
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005615static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data,
5616 int len, void *arg)
5617{
5618 struct tls_connection *conn = arg;
5619
5620 if (conn == NULL || conn->session_ticket_cb == NULL)
5621 return 0;
5622
5623 wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len);
5624
5625 os_free(conn->session_ticket);
5626 conn->session_ticket = NULL;
5627
5628 wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
5629 "extension", data, len);
5630
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005631 conn->session_ticket = os_memdup(data, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005632 if (conn->session_ticket == NULL)
5633 return 0;
5634
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005635 conn->session_ticket_len = len;
5636
5637 return 1;
5638}
Hai Shalom81f62d82019-07-22 12:10:00 -07005639#endif /* EAP_FAST_OR_TEAP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005640
5641
5642int tls_connection_set_session_ticket_cb(void *tls_ctx,
5643 struct tls_connection *conn,
5644 tls_session_ticket_cb cb,
5645 void *ctx)
5646{
Hai Shalom81f62d82019-07-22 12:10:00 -07005647#ifdef EAP_FAST_OR_TEAP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005648 conn->session_ticket_cb = cb;
5649 conn->session_ticket_cb_ctx = ctx;
5650
5651 if (cb) {
5652 if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
5653 conn) != 1)
5654 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005655 SSL_set_session_ticket_ext_cb(conn->ssl,
5656 tls_session_ticket_ext_cb, conn);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005657 } else {
5658 if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
5659 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005660 SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005661 }
5662
5663 return 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07005664#else /* EAP_FAST_OR_TEAP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005665 return -1;
Hai Shalom81f62d82019-07-22 12:10:00 -07005666#endif /* EAP_FAST_OR_TEAP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005667}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005668
5669
5670int tls_get_library_version(char *buf, size_t buf_len)
5671{
Dmitry Shmidt1d6bf422016-01-19 15:51:35 -08005672#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005673 return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
5674 OPENSSL_VERSION_TEXT,
5675 OpenSSL_version(OPENSSL_VERSION));
5676#else
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005677 return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
5678 OPENSSL_VERSION_TEXT,
5679 SSLeay_version(SSLEAY_VERSION));
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08005680#endif
Dmitry Shmidtff787d52015-01-12 13:01:47 -08005681}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08005682
5683
5684void tls_connection_set_success_data(struct tls_connection *conn,
5685 struct wpabuf *data)
5686{
5687 SSL_SESSION *sess;
5688 struct wpabuf *old;
5689
5690 if (tls_ex_idx_session < 0)
5691 goto fail;
5692 sess = SSL_get_session(conn->ssl);
5693 if (!sess)
5694 goto fail;
5695 old = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
5696 if (old) {
5697 wpa_printf(MSG_DEBUG, "OpenSSL: Replacing old success data %p",
5698 old);
5699 wpabuf_free(old);
5700 }
5701 if (SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, data) != 1)
5702 goto fail;
5703
5704 wpa_printf(MSG_DEBUG, "OpenSSL: Stored success data %p", data);
5705 conn->success_data = 1;
5706 return;
5707
5708fail:
5709 wpa_printf(MSG_INFO, "OpenSSL: Failed to store success data");
5710 wpabuf_free(data);
5711}
5712
5713
5714void tls_connection_set_success_data_resumed(struct tls_connection *conn)
5715{
5716 wpa_printf(MSG_DEBUG,
5717 "OpenSSL: Success data accepted for resumed session");
5718 conn->success_data = 1;
5719}
5720
5721
5722const struct wpabuf *
5723tls_connection_get_success_data(struct tls_connection *conn)
5724{
5725 SSL_SESSION *sess;
5726
5727 if (tls_ex_idx_session < 0 ||
5728 !(sess = SSL_get_session(conn->ssl)))
5729 return NULL;
5730 return SSL_SESSION_get_ex_data(sess, tls_ex_idx_session);
5731}
5732
5733
5734void tls_connection_remove_session(struct tls_connection *conn)
5735{
5736 SSL_SESSION *sess;
5737
5738 sess = SSL_get_session(conn->ssl);
5739 if (!sess)
5740 return;
5741
5742 if (SSL_CTX_remove_session(conn->ssl_ctx, sess) != 1)
5743 wpa_printf(MSG_DEBUG,
5744 "OpenSSL: Session was not cached");
5745 else
5746 wpa_printf(MSG_DEBUG,
5747 "OpenSSL: Removed cached session to disable session resumption");
5748}
Hai Shalom81f62d82019-07-22 12:10:00 -07005749
5750
5751int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len)
5752{
5753 size_t len;
5754 int reused;
5755
5756 reused = SSL_session_reused(conn->ssl);
5757 if ((conn->server && !reused) || (!conn->server && reused))
5758 len = SSL_get_peer_finished(conn->ssl, buf, max_len);
5759 else
5760 len = SSL_get_finished(conn->ssl, buf, max_len);
5761
5762 if (len == 0 || len > max_len)
5763 return -1;
5764
5765 return len;
5766}
5767
5768
5769u16 tls_connection_get_cipher_suite(struct tls_connection *conn)
5770{
5771 const SSL_CIPHER *cipher;
5772
5773 cipher = SSL_get_current_cipher(conn->ssl);
5774 if (!cipher)
5775 return 0;
5776#if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER)
5777 return SSL_CIPHER_get_protocol_id(cipher);
5778#else
5779 return SSL_CIPHER_get_id(cipher) & 0xFFFF;
5780#endif
5781}
Hai Shalom899fcc72020-10-19 14:38:18 -07005782
5783
5784const char * tls_connection_get_peer_subject(struct tls_connection *conn)
5785{
5786 if (conn)
5787 return conn->peer_subject;
5788 return NULL;
5789}
5790
5791
5792bool tls_connection_get_own_cert_used(struct tls_connection *conn)
5793{
5794 if (conn)
5795 return SSL_get_certificate(conn->ssl) != NULL;
5796 return false;
5797}