blob: 935add5aa72d9e187cff425bf51a04c7079dda36 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * SSL/TLS interface functions for OpenSSL
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003 * Copyright (c) 2004-2013, 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>
21#include <openssl/pkcs12.h>
22#include <openssl/x509v3.h>
23#ifndef OPENSSL_NO_ENGINE
24#include <openssl/engine.h>
25#endif /* OPENSSL_NO_ENGINE */
26
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070027#include "common.h"
28#include "crypto.h"
Dmitry Shmidtaf9da312015-04-03 10:03:11 -070029#include "sha1.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "tls.h"
31
Dmitry Shmidtea69e842013-05-13 14:52:28 -070032#if defined(SSL_CTX_get_app_data) && defined(SSL_CTX_set_app_data)
33#define OPENSSL_SUPPORTS_CTX_APP_DATA
34#endif
35
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -070036#if OPENSSL_VERSION_NUMBER < 0x10000000L
37/* ERR_remove_thread_state replaces ERR_remove_state and the latter is
38 * deprecated. However, OpenSSL 0.9.8 doesn't include
39 * ERR_remove_thread_state. */
40#define ERR_remove_thread_state(tid) ERR_remove_state(0)
41#endif
42
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -070043#if defined(OPENSSL_IS_BORINGSSL)
44/* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */
45typedef size_t stack_index_t;
46#else
47typedef int stack_index_t;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#endif
49
Dmitry Shmidt34af3062013-07-11 10:46:32 -070050#ifdef SSL_set_tlsext_status_type
51#ifndef OPENSSL_NO_TLSEXT
52#define HAVE_OCSP
53#include <openssl/ocsp.h>
54#endif /* OPENSSL_NO_TLSEXT */
55#endif /* SSL_set_tlsext_status_type */
56
Dmitry Shmidtff079172013-11-08 14:10:30 -080057#ifdef ANDROID
58#include <openssl/pem.h>
59#include <keystore/keystore_get.h>
60
61static BIO * BIO_from_keystore(const char *key)
62{
63 BIO *bio = NULL;
64 uint8_t *value = NULL;
65 int length = keystore_get(key, strlen(key), &value);
66 if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL)
67 BIO_write(bio, value, length);
68 free(value);
69 return bio;
70}
71#endif /* ANDROID */
72
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070073static int tls_openssl_ref_count = 0;
74
Dmitry Shmidtea69e842013-05-13 14:52:28 -070075struct tls_context {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070076 void (*event_cb)(void *ctx, enum tls_event ev,
77 union tls_event_data *data);
78 void *cb_ctx;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080079 int cert_in_cb;
Dmitry Shmidt34af3062013-07-11 10:46:32 -070080 char *ocsp_stapling_response;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070081};
82
Dmitry Shmidtea69e842013-05-13 14:52:28 -070083static struct tls_context *tls_global = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070084
85
86struct tls_connection {
Dmitry Shmidtea69e842013-05-13 14:52:28 -070087 struct tls_context *context;
Dmitry Shmidt216983b2015-02-06 10:50:36 -080088 SSL_CTX *ssl_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070089 SSL *ssl;
90 BIO *ssl_in, *ssl_out;
91#ifndef OPENSSL_NO_ENGINE
92 ENGINE *engine; /* functional reference to the engine */
93 EVP_PKEY *private_key; /* the private key if using engine */
94#endif /* OPENSSL_NO_ENGINE */
Dmitry Shmidt2f74e362015-01-21 13:19:05 -080095 char *subject_match, *altsubject_match, *suffix_match, *domain_match;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096 int read_alerts, write_alerts, failed;
97
98 tls_session_ticket_cb session_ticket_cb;
99 void *session_ticket_cb_ctx;
100
101 /* SessionTicket received from OpenSSL hello_extension_cb (server) */
102 u8 *session_ticket;
103 size_t session_ticket_len;
104
105 unsigned int ca_cert_verify:1;
106 unsigned int cert_probe:1;
107 unsigned int server_cert_only:1;
Jouni Malinen26af48b2014-04-09 13:02:53 +0300108 unsigned int invalid_hb_used:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700109
110 u8 srv_cert_hash[32];
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700111
112 unsigned int flags;
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700113
114 X509 *peer_cert;
115 X509 *peer_issuer;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800116 X509 *peer_issuer_issuer;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700117};
118
119
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700120static struct tls_context * tls_context_new(const struct tls_config *conf)
121{
122 struct tls_context *context = os_zalloc(sizeof(*context));
123 if (context == NULL)
124 return NULL;
125 if (conf) {
126 context->event_cb = conf->event_cb;
127 context->cb_ctx = conf->cb_ctx;
128 context->cert_in_cb = conf->cert_in_cb;
129 }
130 return context;
131}
132
133
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700134#ifdef CONFIG_NO_STDOUT_DEBUG
135
136static void _tls_show_errors(void)
137{
138 unsigned long err;
139
140 while ((err = ERR_get_error())) {
141 /* Just ignore the errors, since stdout is disabled */
142 }
143}
144#define tls_show_errors(l, f, t) _tls_show_errors()
145
146#else /* CONFIG_NO_STDOUT_DEBUG */
147
148static void tls_show_errors(int level, const char *func, const char *txt)
149{
150 unsigned long err;
151
152 wpa_printf(level, "OpenSSL: %s - %s %s",
153 func, txt, ERR_error_string(ERR_get_error(), NULL));
154
155 while ((err = ERR_get_error())) {
156 wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",
157 ERR_error_string(err, NULL));
158 }
159}
160
161#endif /* CONFIG_NO_STDOUT_DEBUG */
162
163
164#ifdef CONFIG_NATIVE_WINDOWS
165
166/* Windows CryptoAPI and access to certificate stores */
167#include <wincrypt.h>
168
169#ifdef __MINGW32_VERSION
170/*
171 * MinGW does not yet include all the needed definitions for CryptoAPI, so
172 * define here whatever extra is needed.
173 */
174#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16)
175#define CERT_STORE_READONLY_FLAG 0x00008000
176#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000
177
178#endif /* __MINGW32_VERSION */
179
180
181struct cryptoapi_rsa_data {
182 const CERT_CONTEXT *cert;
183 HCRYPTPROV crypt_prov;
184 DWORD key_spec;
185 BOOL free_crypt_prov;
186};
187
188
189static void cryptoapi_error(const char *msg)
190{
191 wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u",
192 msg, (unsigned int) GetLastError());
193}
194
195
196static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from,
197 unsigned char *to, RSA *rsa, int padding)
198{
199 wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
200 return 0;
201}
202
203
204static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from,
205 unsigned char *to, RSA *rsa, int padding)
206{
207 wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
208 return 0;
209}
210
211
212static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from,
213 unsigned char *to, RSA *rsa, int padding)
214{
215 struct cryptoapi_rsa_data *priv =
216 (struct cryptoapi_rsa_data *) rsa->meth->app_data;
217 HCRYPTHASH hash;
218 DWORD hash_size, len, i;
219 unsigned char *buf = NULL;
220 int ret = 0;
221
222 if (priv == NULL) {
223 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
224 ERR_R_PASSED_NULL_PARAMETER);
225 return 0;
226 }
227
228 if (padding != RSA_PKCS1_PADDING) {
229 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
230 RSA_R_UNKNOWN_PADDING_TYPE);
231 return 0;
232 }
233
234 if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) {
235 wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported",
236 __func__);
237 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
238 RSA_R_INVALID_MESSAGE_LENGTH);
239 return 0;
240 }
241
242 if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
243 {
244 cryptoapi_error("CryptCreateHash failed");
245 return 0;
246 }
247
248 len = sizeof(hash_size);
249 if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len,
250 0)) {
251 cryptoapi_error("CryptGetHashParam failed");
252 goto err;
253 }
254
255 if ((int) hash_size != flen) {
256 wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)",
257 (unsigned) hash_size, flen);
258 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,
259 RSA_R_INVALID_MESSAGE_LENGTH);
260 goto err;
261 }
262 if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {
263 cryptoapi_error("CryptSetHashParam failed");
264 goto err;
265 }
266
267 len = RSA_size(rsa);
268 buf = os_malloc(len);
269 if (buf == NULL) {
270 RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
271 goto err;
272 }
273
274 if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) {
275 cryptoapi_error("CryptSignHash failed");
276 goto err;
277 }
278
279 for (i = 0; i < len; i++)
280 to[i] = buf[len - i - 1];
281 ret = len;
282
283err:
284 os_free(buf);
285 CryptDestroyHash(hash);
286
287 return ret;
288}
289
290
291static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from,
292 unsigned char *to, RSA *rsa, int padding)
293{
294 wpa_printf(MSG_DEBUG, "%s - not implemented", __func__);
295 return 0;
296}
297
298
299static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv)
300{
301 if (priv == NULL)
302 return;
303 if (priv->crypt_prov && priv->free_crypt_prov)
304 CryptReleaseContext(priv->crypt_prov, 0);
305 if (priv->cert)
306 CertFreeCertificateContext(priv->cert);
307 os_free(priv);
308}
309
310
311static int cryptoapi_finish(RSA *rsa)
312{
313 cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data);
314 os_free((void *) rsa->meth);
315 rsa->meth = NULL;
316 return 1;
317}
318
319
320static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store)
321{
322 HCERTSTORE cs;
323 const CERT_CONTEXT *ret = NULL;
324
325 cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0,
326 store | CERT_STORE_OPEN_EXISTING_FLAG |
327 CERT_STORE_READONLY_FLAG, L"MY");
328 if (cs == NULL) {
329 cryptoapi_error("Failed to open 'My system store'");
330 return NULL;
331 }
332
333 if (strncmp(name, "cert://", 7) == 0) {
334 unsigned short wbuf[255];
335 MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255);
336 ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING |
337 PKCS_7_ASN_ENCODING,
338 0, CERT_FIND_SUBJECT_STR,
339 wbuf, NULL);
340 } else if (strncmp(name, "hash://", 7) == 0) {
341 CRYPT_HASH_BLOB blob;
342 int len;
343 const char *hash = name + 7;
344 unsigned char *buf;
345
346 len = os_strlen(hash) / 2;
347 buf = os_malloc(len);
348 if (buf && hexstr2bin(hash, buf, len) == 0) {
349 blob.cbData = len;
350 blob.pbData = buf;
351 ret = CertFindCertificateInStore(cs,
352 X509_ASN_ENCODING |
353 PKCS_7_ASN_ENCODING,
354 0, CERT_FIND_HASH,
355 &blob, NULL);
356 }
357 os_free(buf);
358 }
359
360 CertCloseStore(cs, 0);
361
362 return ret;
363}
364
365
366static int tls_cryptoapi_cert(SSL *ssl, const char *name)
367{
368 X509 *cert = NULL;
369 RSA *rsa = NULL, *pub_rsa;
370 struct cryptoapi_rsa_data *priv;
371 RSA_METHOD *rsa_meth;
372
373 if (name == NULL ||
374 (strncmp(name, "cert://", 7) != 0 &&
375 strncmp(name, "hash://", 7) != 0))
376 return -1;
377
378 priv = os_zalloc(sizeof(*priv));
379 rsa_meth = os_zalloc(sizeof(*rsa_meth));
380 if (priv == NULL || rsa_meth == NULL) {
381 wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory "
382 "for CryptoAPI RSA method");
383 os_free(priv);
384 os_free(rsa_meth);
385 return -1;
386 }
387
388 priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER);
389 if (priv->cert == NULL) {
390 priv->cert = cryptoapi_find_cert(
391 name, CERT_SYSTEM_STORE_LOCAL_MACHINE);
392 }
393 if (priv->cert == NULL) {
394 wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate "
395 "'%s'", name);
396 goto err;
397 }
398
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800399 cert = d2i_X509(NULL,
400 (const unsigned char **) &priv->cert->pbCertEncoded,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700401 priv->cert->cbCertEncoded);
402 if (cert == NULL) {
403 wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER "
404 "encoding");
405 goto err;
406 }
407
408 if (!CryptAcquireCertificatePrivateKey(priv->cert,
409 CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
410 NULL, &priv->crypt_prov,
411 &priv->key_spec,
412 &priv->free_crypt_prov)) {
413 cryptoapi_error("Failed to acquire a private key for the "
414 "certificate");
415 goto err;
416 }
417
418 rsa_meth->name = "Microsoft CryptoAPI RSA Method";
419 rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc;
420 rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec;
421 rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc;
422 rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec;
423 rsa_meth->finish = cryptoapi_finish;
424 rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;
425 rsa_meth->app_data = (char *) priv;
426
427 rsa = RSA_new();
428 if (rsa == NULL) {
429 SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE,
430 ERR_R_MALLOC_FAILURE);
431 goto err;
432 }
433
434 if (!SSL_use_certificate(ssl, cert)) {
435 RSA_free(rsa);
436 rsa = NULL;
437 goto err;
438 }
439 pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
440 X509_free(cert);
441 cert = NULL;
442
443 rsa->n = BN_dup(pub_rsa->n);
444 rsa->e = BN_dup(pub_rsa->e);
445 if (!RSA_set_method(rsa, rsa_meth))
446 goto err;
447
448 if (!SSL_use_RSAPrivateKey(ssl, rsa))
449 goto err;
450 RSA_free(rsa);
451
452 return 0;
453
454err:
455 if (cert)
456 X509_free(cert);
457 if (rsa)
458 RSA_free(rsa);
459 else {
460 os_free(rsa_meth);
461 cryptoapi_free_data(priv);
462 }
463 return -1;
464}
465
466
467static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name)
468{
469 HCERTSTORE cs;
470 PCCERT_CONTEXT ctx = NULL;
471 X509 *cert;
472 char buf[128];
473 const char *store;
474#ifdef UNICODE
475 WCHAR *wstore;
476#endif /* UNICODE */
477
478 if (name == NULL || strncmp(name, "cert_store://", 13) != 0)
479 return -1;
480
481 store = name + 13;
482#ifdef UNICODE
483 wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR));
484 if (wstore == NULL)
485 return -1;
486 wsprintf(wstore, L"%S", store);
487 cs = CertOpenSystemStore(0, wstore);
488 os_free(wstore);
489#else /* UNICODE */
490 cs = CertOpenSystemStore(0, store);
491#endif /* UNICODE */
492 if (cs == NULL) {
493 wpa_printf(MSG_DEBUG, "%s: failed to open system cert store "
494 "'%s': error=%d", __func__, store,
495 (int) GetLastError());
496 return -1;
497 }
498
499 while ((ctx = CertEnumCertificatesInStore(cs, ctx))) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800500 cert = d2i_X509(NULL,
501 (const unsigned char **) &ctx->pbCertEncoded,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502 ctx->cbCertEncoded);
503 if (cert == NULL) {
504 wpa_printf(MSG_INFO, "CryptoAPI: Could not process "
505 "X509 DER encoding for CA cert");
506 continue;
507 }
508
509 X509_NAME_oneline(X509_get_subject_name(cert), buf,
510 sizeof(buf));
511 wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for "
512 "system certificate store: subject='%s'", buf);
513
514 if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) {
515 tls_show_errors(MSG_WARNING, __func__,
516 "Failed to add ca_cert to OpenSSL "
517 "certificate store");
518 }
519
520 X509_free(cert);
521 }
522
523 if (!CertCloseStore(cs, 0)) {
524 wpa_printf(MSG_DEBUG, "%s: failed to close system cert store "
525 "'%s': error=%d", __func__, name + 13,
526 (int) GetLastError());
527 }
528
529 return 0;
530}
531
532
533#else /* CONFIG_NATIVE_WINDOWS */
534
535static int tls_cryptoapi_cert(SSL *ssl, const char *name)
536{
537 return -1;
538}
539
540#endif /* CONFIG_NATIVE_WINDOWS */
541
542
543static void ssl_info_cb(const SSL *ssl, int where, int ret)
544{
545 const char *str;
546 int w;
547
548 wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret);
549 w = where & ~SSL_ST_MASK;
550 if (w & SSL_ST_CONNECT)
551 str = "SSL_connect";
552 else if (w & SSL_ST_ACCEPT)
553 str = "SSL_accept";
554 else
555 str = "undefined";
556
557 if (where & SSL_CB_LOOP) {
558 wpa_printf(MSG_DEBUG, "SSL: %s:%s",
559 str, SSL_state_string_long(ssl));
560 } else if (where & SSL_CB_ALERT) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700561 struct tls_connection *conn = SSL_get_app_data((SSL *) ssl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700562 wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s",
563 where & SSL_CB_READ ?
564 "read (remote end reported an error)" :
565 "write (local SSL3 detected an error)",
566 SSL_alert_type_string_long(ret),
567 SSL_alert_desc_string_long(ret));
568 if ((ret >> 8) == SSL3_AL_FATAL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700569 if (where & SSL_CB_READ)
570 conn->read_alerts++;
571 else
572 conn->write_alerts++;
573 }
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700574 if (conn->context->event_cb != NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700575 union tls_event_data ev;
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700576 struct tls_context *context = conn->context;
Dmitry Shmidt04949592012-07-19 12:16:46 -0700577 os_memset(&ev, 0, sizeof(ev));
578 ev.alert.is_local = !(where & SSL_CB_READ);
579 ev.alert.type = SSL_alert_type_string_long(ret);
580 ev.alert.description = SSL_alert_desc_string_long(ret);
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700581 context->event_cb(context->cb_ctx, TLS_ALERT, &ev);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700582 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583 } else if (where & SSL_CB_EXIT && ret <= 0) {
584 wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s",
585 str, ret == 0 ? "failed" : "error",
586 SSL_state_string_long(ssl));
587 }
588}
589
590
591#ifndef OPENSSL_NO_ENGINE
592/**
593 * tls_engine_load_dynamic_generic - load any openssl engine
594 * @pre: an array of commands and values that load an engine initialized
595 * in the engine specific function
596 * @post: an array of commands and values that initialize an already loaded
597 * engine (or %NULL if not required)
598 * @id: the engine id of the engine to load (only required if post is not %NULL
599 *
600 * This function is a generic function that loads any openssl engine.
601 *
602 * Returns: 0 on success, -1 on failure
603 */
604static int tls_engine_load_dynamic_generic(const char *pre[],
605 const char *post[], const char *id)
606{
607 ENGINE *engine;
608 const char *dynamic_id = "dynamic";
609
610 engine = ENGINE_by_id(id);
611 if (engine) {
612 ENGINE_free(engine);
613 wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already "
614 "available", id);
615 return 0;
616 }
617 ERR_clear_error();
618
619 engine = ENGINE_by_id(dynamic_id);
620 if (engine == NULL) {
621 wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
622 dynamic_id,
623 ERR_error_string(ERR_get_error(), NULL));
624 return -1;
625 }
626
627 /* Perform the pre commands. This will load the engine. */
628 while (pre && pre[0]) {
629 wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]);
630 if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) {
631 wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: "
632 "%s %s [%s]", pre[0], pre[1],
633 ERR_error_string(ERR_get_error(), NULL));
634 ENGINE_free(engine);
635 return -1;
636 }
637 pre += 2;
638 }
639
640 /*
641 * Free the reference to the "dynamic" engine. The loaded engine can
642 * now be looked up using ENGINE_by_id().
643 */
644 ENGINE_free(engine);
645
646 engine = ENGINE_by_id(id);
647 if (engine == NULL) {
648 wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]",
649 id, ERR_error_string(ERR_get_error(), NULL));
650 return -1;
651 }
652
653 while (post && post[0]) {
654 wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]);
655 if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) {
656 wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:"
657 " %s %s [%s]", post[0], post[1],
658 ERR_error_string(ERR_get_error(), NULL));
659 ENGINE_remove(engine);
660 ENGINE_free(engine);
661 return -1;
662 }
663 post += 2;
664 }
665 ENGINE_free(engine);
666
667 return 0;
668}
669
670
671/**
672 * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc
673 * @pkcs11_so_path: pksc11_so_path from the configuration
674 * @pcks11_module_path: pkcs11_module_path from the configuration
675 */
676static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path,
677 const char *pkcs11_module_path)
678{
679 char *engine_id = "pkcs11";
680 const char *pre_cmd[] = {
681 "SO_PATH", NULL /* pkcs11_so_path */,
682 "ID", NULL /* engine_id */,
683 "LIST_ADD", "1",
684 /* "NO_VCHECK", "1", */
685 "LOAD", NULL,
686 NULL, NULL
687 };
688 const char *post_cmd[] = {
689 "MODULE_PATH", NULL /* pkcs11_module_path */,
690 NULL, NULL
691 };
692
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800693 if (!pkcs11_so_path)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700694 return 0;
695
696 pre_cmd[1] = pkcs11_so_path;
697 pre_cmd[3] = engine_id;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800698 if (pkcs11_module_path)
699 post_cmd[1] = pkcs11_module_path;
700 else
701 post_cmd[0] = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702
703 wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s",
704 pkcs11_so_path);
705
706 return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id);
707}
708
709
710/**
711 * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc
712 * @opensc_so_path: opensc_so_path from the configuration
713 */
714static int tls_engine_load_dynamic_opensc(const char *opensc_so_path)
715{
716 char *engine_id = "opensc";
717 const char *pre_cmd[] = {
718 "SO_PATH", NULL /* opensc_so_path */,
719 "ID", NULL /* engine_id */,
720 "LIST_ADD", "1",
721 "LOAD", NULL,
722 NULL, NULL
723 };
724
725 if (!opensc_so_path)
726 return 0;
727
728 pre_cmd[1] = opensc_so_path;
729 pre_cmd[3] = engine_id;
730
731 wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s",
732 opensc_so_path);
733
734 return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id);
735}
736#endif /* OPENSSL_NO_ENGINE */
737
738
739void * tls_init(const struct tls_config *conf)
740{
741 SSL_CTX *ssl;
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700742 struct tls_context *context;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800743 const char *ciphers;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744
745 if (tls_openssl_ref_count == 0) {
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700746 tls_global = context = tls_context_new(conf);
747 if (context == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700748 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749#ifdef CONFIG_FIPS
750#ifdef OPENSSL_FIPS
751 if (conf && conf->fips_mode) {
752 if (!FIPS_mode_set(1)) {
753 wpa_printf(MSG_ERROR, "Failed to enable FIPS "
754 "mode");
755 ERR_load_crypto_strings();
756 ERR_print_errors_fp(stderr);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700757 os_free(tls_global);
758 tls_global = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759 return NULL;
760 } else
761 wpa_printf(MSG_INFO, "Running in FIPS mode");
762 }
763#else /* OPENSSL_FIPS */
764 if (conf && conf->fips_mode) {
765 wpa_printf(MSG_ERROR, "FIPS mode requested, but not "
766 "supported");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700767 os_free(tls_global);
768 tls_global = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700769 return NULL;
770 }
771#endif /* OPENSSL_FIPS */
772#endif /* CONFIG_FIPS */
773 SSL_load_error_strings();
774 SSL_library_init();
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800775#ifndef OPENSSL_NO_SHA256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700776 EVP_add_digest(EVP_sha256());
777#endif /* OPENSSL_NO_SHA256 */
778 /* TODO: if /dev/urandom is available, PRNG is seeded
779 * automatically. If this is not the case, random data should
780 * be added here. */
781
782#ifdef PKCS12_FUNCS
783#ifndef OPENSSL_NO_RC2
784 /*
785 * 40-bit RC2 is commonly used in PKCS#12 files, so enable it.
786 * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8
787 * versions, but it looks like OpenSSL 1.0.0 does not do that
788 * anymore.
789 */
790 EVP_add_cipher(EVP_rc2_40_cbc());
791#endif /* OPENSSL_NO_RC2 */
792 PKCS12_PBE_add();
793#endif /* PKCS12_FUNCS */
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700794 } else {
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700795#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
796 /* Newer OpenSSL can store app-data per-SSL */
797 context = tls_context_new(conf);
798 if (context == NULL)
799 return NULL;
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -0800800#else /* OPENSSL_SUPPORTS_CTX_APP_DATA */
801 context = tls_global;
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700802#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700803 }
804 tls_openssl_ref_count++;
805
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800806 ssl = SSL_CTX_new(SSLv23_method());
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700807 if (ssl == NULL) {
808 tls_openssl_ref_count--;
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700809#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
810 if (context != tls_global)
811 os_free(context);
812#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700813 if (tls_openssl_ref_count == 0) {
814 os_free(tls_global);
815 tls_global = NULL;
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700816 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700817 return NULL;
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700818 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800820 SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2);
821 SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3);
822
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823 SSL_CTX_set_info_callback(ssl, ssl_info_cb);
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700824#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
825 SSL_CTX_set_app_data(ssl, context);
826#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700827
828#ifndef OPENSSL_NO_ENGINE
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800829 wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine");
830 ERR_load_ENGINE_strings();
831 ENGINE_load_dynamic();
832
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700833 if (conf &&
834 (conf->opensc_engine_path || conf->pkcs11_engine_path ||
835 conf->pkcs11_module_path)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700836 if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) ||
837 tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path,
838 conf->pkcs11_module_path)) {
839 tls_deinit(ssl);
840 return NULL;
841 }
842 }
843#endif /* OPENSSL_NO_ENGINE */
844
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800845 if (conf && conf->openssl_ciphers)
846 ciphers = conf->openssl_ciphers;
847 else
848 ciphers = "DEFAULT:!EXP:!LOW";
849 if (SSL_CTX_set_cipher_list(ssl, ciphers) != 1) {
850 wpa_printf(MSG_ERROR,
851 "OpenSSL: Failed to set cipher string '%s'",
852 ciphers);
853 tls_deinit(ssl);
854 return NULL;
855 }
856
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700857 return ssl;
858}
859
860
861void tls_deinit(void *ssl_ctx)
862{
863 SSL_CTX *ssl = ssl_ctx;
Dmitry Shmidtea69e842013-05-13 14:52:28 -0700864#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
865 struct tls_context *context = SSL_CTX_get_app_data(ssl);
866 if (context != tls_global)
867 os_free(context);
868#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700869 SSL_CTX_free(ssl);
870
871 tls_openssl_ref_count--;
872 if (tls_openssl_ref_count == 0) {
873#ifndef OPENSSL_NO_ENGINE
874 ENGINE_cleanup();
875#endif /* OPENSSL_NO_ENGINE */
876 CRYPTO_cleanup_all_ex_data();
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700877 ERR_remove_thread_state(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700878 ERR_free_strings();
879 EVP_cleanup();
Dmitry Shmidt34af3062013-07-11 10:46:32 -0700880 os_free(tls_global->ocsp_stapling_response);
881 tls_global->ocsp_stapling_response = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700882 os_free(tls_global);
883 tls_global = NULL;
884 }
885}
886
887
888static int tls_engine_init(struct tls_connection *conn, const char *engine_id,
889 const char *pin, const char *key_id,
890 const char *cert_id, const char *ca_cert_id)
891{
892#ifndef OPENSSL_NO_ENGINE
893 int ret = -1;
894 if (engine_id == NULL) {
895 wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set");
896 return -1;
897 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700898
899 ERR_clear_error();
Kenny Rootdb3c5a42012-03-20 17:00:47 -0700900#ifdef ANDROID
901 ENGINE_load_dynamic();
902#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700903 conn->engine = ENGINE_by_id(engine_id);
904 if (!conn->engine) {
905 wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]",
906 engine_id, ERR_error_string(ERR_get_error(), NULL));
907 goto err;
908 }
909 if (ENGINE_init(conn->engine) != 1) {
910 wpa_printf(MSG_ERROR, "ENGINE: engine init failed "
911 "(engine: %s) [%s]", engine_id,
912 ERR_error_string(ERR_get_error(), NULL));
913 goto err;
914 }
915 wpa_printf(MSG_DEBUG, "ENGINE: engine initialized");
916
Kenny Rootdb3c5a42012-03-20 17:00:47 -0700917#ifndef ANDROID
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800918 if (pin && ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919 wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]",
920 ERR_error_string(ERR_get_error(), NULL));
921 goto err;
922 }
Kenny Rootdb3c5a42012-03-20 17:00:47 -0700923#endif
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800924 if (key_id) {
925 /*
926 * Ensure that the ENGINE does not attempt to use the OpenSSL
927 * UI system to obtain a PIN, if we didn't provide one.
928 */
929 struct {
930 const void *password;
931 const char *prompt_info;
932 } key_cb = { "", NULL };
933
934 /* load private key first in-case PIN is required for cert */
935 conn->private_key = ENGINE_load_private_key(conn->engine,
936 key_id, NULL,
937 &key_cb);
938 if (!conn->private_key) {
939 wpa_printf(MSG_ERROR,
940 "ENGINE: cannot load private key with id '%s' [%s]",
941 key_id,
942 ERR_error_string(ERR_get_error(), NULL));
943 ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
944 goto err;
945 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700946 }
947
948 /* handle a certificate and/or CA certificate */
949 if (cert_id || ca_cert_id) {
950 const char *cmd_name = "LOAD_CERT_CTRL";
951
952 /* test if the engine supports a LOAD_CERT_CTRL */
953 if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME,
954 0, (void *)cmd_name, NULL)) {
955 wpa_printf(MSG_ERROR, "ENGINE: engine does not support"
956 " loading certificates");
957 ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
958 goto err;
959 }
960 }
961
962 return 0;
963
964err:
965 if (conn->engine) {
966 ENGINE_free(conn->engine);
967 conn->engine = NULL;
968 }
969
970 if (conn->private_key) {
971 EVP_PKEY_free(conn->private_key);
972 conn->private_key = NULL;
973 }
974
975 return ret;
976#else /* OPENSSL_NO_ENGINE */
977 return 0;
978#endif /* OPENSSL_NO_ENGINE */
979}
980
981
982static void tls_engine_deinit(struct tls_connection *conn)
983{
984#ifndef OPENSSL_NO_ENGINE
985 wpa_printf(MSG_DEBUG, "ENGINE: engine deinit");
986 if (conn->private_key) {
987 EVP_PKEY_free(conn->private_key);
988 conn->private_key = NULL;
989 }
990 if (conn->engine) {
991 ENGINE_finish(conn->engine);
992 conn->engine = NULL;
993 }
994#endif /* OPENSSL_NO_ENGINE */
995}
996
997
998int tls_get_errors(void *ssl_ctx)
999{
1000 int count = 0;
1001 unsigned long err;
1002
1003 while ((err = ERR_get_error())) {
1004 wpa_printf(MSG_INFO, "TLS - SSL error: %s",
1005 ERR_error_string(err, NULL));
1006 count++;
1007 }
1008
1009 return count;
1010}
1011
Jouni Malinen26af48b2014-04-09 13:02:53 +03001012
1013static void tls_msg_cb(int write_p, int version, int content_type,
1014 const void *buf, size_t len, SSL *ssl, void *arg)
1015{
1016 struct tls_connection *conn = arg;
1017 const u8 *pos = buf;
1018
1019 wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d",
1020 write_p ? "TX" : "RX", version, content_type);
1021 wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len);
1022 if (content_type == 24 && len >= 3 && pos[0] == 1) {
1023 size_t payload_len = WPA_GET_BE16(pos + 1);
1024 if (payload_len + 3 > len) {
1025 wpa_printf(MSG_ERROR, "OpenSSL: Heartbeat attack detected");
1026 conn->invalid_hb_used = 1;
1027 }
1028 }
1029}
1030
1031
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001032struct tls_connection * tls_connection_init(void *ssl_ctx)
1033{
1034 SSL_CTX *ssl = ssl_ctx;
1035 struct tls_connection *conn;
1036 long options;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001037#ifdef OPENSSL_SUPPORTS_CTX_APP_DATA
Dmitry Shmidt7d5c8f22014-03-03 13:53:28 -08001038 struct tls_context *context = SSL_CTX_get_app_data(ssl);
1039#else /* OPENSSL_SUPPORTS_CTX_APP_DATA */
1040 struct tls_context *context = tls_global;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001041#endif /* OPENSSL_SUPPORTS_CTX_APP_DATA */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001042
1043 conn = os_zalloc(sizeof(*conn));
1044 if (conn == NULL)
1045 return NULL;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001046 conn->ssl_ctx = ssl_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001047 conn->ssl = SSL_new(ssl);
1048 if (conn->ssl == NULL) {
1049 tls_show_errors(MSG_INFO, __func__,
1050 "Failed to initialize new SSL connection");
1051 os_free(conn);
1052 return NULL;
1053 }
1054
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001055 conn->context = context;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001056 SSL_set_app_data(conn->ssl, conn);
Jouni Malinen26af48b2014-04-09 13:02:53 +03001057 SSL_set_msg_callback(conn->ssl, tls_msg_cb);
1058 SSL_set_msg_callback_arg(conn->ssl, conn);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001059 options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
1060 SSL_OP_SINGLE_DH_USE;
1061#ifdef SSL_OP_NO_COMPRESSION
1062 options |= SSL_OP_NO_COMPRESSION;
1063#endif /* SSL_OP_NO_COMPRESSION */
1064 SSL_set_options(conn->ssl, options);
1065
1066 conn->ssl_in = BIO_new(BIO_s_mem());
1067 if (!conn->ssl_in) {
1068 tls_show_errors(MSG_INFO, __func__,
1069 "Failed to create a new BIO for ssl_in");
1070 SSL_free(conn->ssl);
1071 os_free(conn);
1072 return NULL;
1073 }
1074
1075 conn->ssl_out = BIO_new(BIO_s_mem());
1076 if (!conn->ssl_out) {
1077 tls_show_errors(MSG_INFO, __func__,
1078 "Failed to create a new BIO for ssl_out");
1079 SSL_free(conn->ssl);
1080 BIO_free(conn->ssl_in);
1081 os_free(conn);
1082 return NULL;
1083 }
1084
1085 SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out);
1086
1087 return conn;
1088}
1089
1090
1091void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn)
1092{
1093 if (conn == NULL)
1094 return;
1095 SSL_free(conn->ssl);
1096 tls_engine_deinit(conn);
1097 os_free(conn->subject_match);
1098 os_free(conn->altsubject_match);
Dmitry Shmidt051af732013-10-22 13:52:46 -07001099 os_free(conn->suffix_match);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001100 os_free(conn->domain_match);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001101 os_free(conn->session_ticket);
1102 os_free(conn);
1103}
1104
1105
1106int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
1107{
1108 return conn ? SSL_is_init_finished(conn->ssl) : 0;
1109}
1110
1111
1112int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
1113{
1114 if (conn == NULL)
1115 return -1;
1116
1117 /* Shutdown previous TLS connection without notifying the peer
1118 * because the connection was already terminated in practice
1119 * and "close notify" shutdown alert would confuse AS. */
1120 SSL_set_quiet_shutdown(conn->ssl, 1);
1121 SSL_shutdown(conn->ssl);
1122 return 0;
1123}
1124
1125
1126static int tls_match_altsubject_component(X509 *cert, int type,
1127 const char *value, size_t len)
1128{
1129 GENERAL_NAME *gen;
1130 void *ext;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001131 int found = 0;
1132 stack_index_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133
1134 ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1135
1136 for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
1137 gen = sk_GENERAL_NAME_value(ext, i);
1138 if (gen->type != type)
1139 continue;
1140 if (os_strlen((char *) gen->d.ia5->data) == len &&
1141 os_memcmp(value, gen->d.ia5->data, len) == 0)
1142 found++;
1143 }
1144
1145 return found;
1146}
1147
1148
1149static int tls_match_altsubject(X509 *cert, const char *match)
1150{
1151 int type;
1152 const char *pos, *end;
1153 size_t len;
1154
1155 pos = match;
1156 do {
1157 if (os_strncmp(pos, "EMAIL:", 6) == 0) {
1158 type = GEN_EMAIL;
1159 pos += 6;
1160 } else if (os_strncmp(pos, "DNS:", 4) == 0) {
1161 type = GEN_DNS;
1162 pos += 4;
1163 } else if (os_strncmp(pos, "URI:", 4) == 0) {
1164 type = GEN_URI;
1165 pos += 4;
1166 } else {
1167 wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName "
1168 "match '%s'", pos);
1169 return 0;
1170 }
1171 end = os_strchr(pos, ';');
1172 while (end) {
1173 if (os_strncmp(end + 1, "EMAIL:", 6) == 0 ||
1174 os_strncmp(end + 1, "DNS:", 4) == 0 ||
1175 os_strncmp(end + 1, "URI:", 4) == 0)
1176 break;
1177 end = os_strchr(end + 1, ';');
1178 }
1179 if (end)
1180 len = end - pos;
1181 else
1182 len = os_strlen(pos);
1183 if (tls_match_altsubject_component(cert, type, pos, len) > 0)
1184 return 1;
1185 pos = end + 1;
1186 } while (end);
1187
1188 return 0;
1189}
1190
1191
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08001192#ifndef CONFIG_NATIVE_WINDOWS
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001193static int domain_suffix_match(const u8 *val, size_t len, const char *match,
1194 int full)
Dmitry Shmidt051af732013-10-22 13:52:46 -07001195{
1196 size_t i, match_len;
1197
1198 /* Check for embedded nuls that could mess up suffix matching */
1199 for (i = 0; i < len; i++) {
1200 if (val[i] == '\0') {
1201 wpa_printf(MSG_DEBUG, "TLS: Embedded null in a string - reject");
1202 return 0;
1203 }
1204 }
1205
1206 match_len = os_strlen(match);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001207 if (match_len > len || (full && match_len != len))
Dmitry Shmidt051af732013-10-22 13:52:46 -07001208 return 0;
1209
1210 if (os_strncasecmp((const char *) val + len - match_len, match,
1211 match_len) != 0)
1212 return 0; /* no match */
1213
1214 if (match_len == len)
1215 return 1; /* exact match */
1216
1217 if (val[len - match_len - 1] == '.')
1218 return 1; /* full label match completes suffix match */
1219
1220 wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match");
1221 return 0;
1222}
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08001223#endif /* CONFIG_NATIVE_WINDOWS */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001224
1225
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001226static int tls_match_suffix(X509 *cert, const char *match, int full)
Dmitry Shmidt051af732013-10-22 13:52:46 -07001227{
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08001228#ifdef CONFIG_NATIVE_WINDOWS
1229 /* wincrypt.h has conflicting X509_NAME definition */
1230 return -1;
1231#else /* CONFIG_NATIVE_WINDOWS */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001232 GENERAL_NAME *gen;
1233 void *ext;
1234 int i;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001235 stack_index_t j;
Dmitry Shmidt051af732013-10-22 13:52:46 -07001236 int dns_name = 0;
1237 X509_NAME *name;
1238
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001239 wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s",
1240 full ? "": "suffix ", match);
Dmitry Shmidt051af732013-10-22 13:52:46 -07001241
1242 ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
1243
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001244 for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) {
1245 gen = sk_GENERAL_NAME_value(ext, j);
Dmitry Shmidt051af732013-10-22 13:52:46 -07001246 if (gen->type != GEN_DNS)
1247 continue;
1248 dns_name++;
1249 wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName",
1250 gen->d.dNSName->data,
1251 gen->d.dNSName->length);
1252 if (domain_suffix_match(gen->d.dNSName->data,
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001253 gen->d.dNSName->length, match, full) ==
1254 1) {
1255 wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found",
1256 full ? "Match" : "Suffix match");
Dmitry Shmidt051af732013-10-22 13:52:46 -07001257 return 1;
1258 }
1259 }
1260
1261 if (dns_name) {
1262 wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched");
1263 return 0;
1264 }
1265
1266 name = X509_get_subject_name(cert);
1267 i = -1;
1268 for (;;) {
1269 X509_NAME_ENTRY *e;
1270 ASN1_STRING *cn;
1271
1272 i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
1273 if (i == -1)
1274 break;
1275 e = X509_NAME_get_entry(name, i);
1276 if (e == NULL)
1277 continue;
1278 cn = X509_NAME_ENTRY_get_data(e);
1279 if (cn == NULL)
1280 continue;
1281 wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName",
1282 cn->data, cn->length);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001283 if (domain_suffix_match(cn->data, cn->length, match, full) == 1)
1284 {
1285 wpa_printf(MSG_DEBUG, "TLS: %s in commonName found",
1286 full ? "Match" : "Suffix match");
Dmitry Shmidt051af732013-10-22 13:52:46 -07001287 return 1;
1288 }
1289 }
1290
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001291 wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found",
1292 full ? "": "suffix ");
Dmitry Shmidt051af732013-10-22 13:52:46 -07001293 return 0;
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08001294#endif /* CONFIG_NATIVE_WINDOWS */
Dmitry Shmidt051af732013-10-22 13:52:46 -07001295}
1296
1297
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298static enum tls_fail_reason openssl_tls_fail_reason(int err)
1299{
1300 switch (err) {
1301 case X509_V_ERR_CERT_REVOKED:
1302 return TLS_FAIL_REVOKED;
1303 case X509_V_ERR_CERT_NOT_YET_VALID:
1304 case X509_V_ERR_CRL_NOT_YET_VALID:
1305 return TLS_FAIL_NOT_YET_VALID;
1306 case X509_V_ERR_CERT_HAS_EXPIRED:
1307 case X509_V_ERR_CRL_HAS_EXPIRED:
1308 return TLS_FAIL_EXPIRED;
1309 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
1310 case X509_V_ERR_UNABLE_TO_GET_CRL:
1311 case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
1312 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
1313 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1314 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1315 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
1316 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
1317 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
1318 case X509_V_ERR_INVALID_CA:
1319 return TLS_FAIL_UNTRUSTED;
1320 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
1321 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
1322 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
1323 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
1324 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
1325 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
1326 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
1327 case X509_V_ERR_CERT_UNTRUSTED:
1328 case X509_V_ERR_CERT_REJECTED:
1329 return TLS_FAIL_BAD_CERTIFICATE;
1330 default:
1331 return TLS_FAIL_UNSPECIFIED;
1332 }
1333}
1334
1335
1336static struct wpabuf * get_x509_cert(X509 *cert)
1337{
1338 struct wpabuf *buf;
1339 u8 *tmp;
1340
1341 int cert_len = i2d_X509(cert, NULL);
1342 if (cert_len <= 0)
1343 return NULL;
1344
1345 buf = wpabuf_alloc(cert_len);
1346 if (buf == NULL)
1347 return NULL;
1348
1349 tmp = wpabuf_put(buf, cert_len);
1350 i2d_X509(cert, &tmp);
1351 return buf;
1352}
1353
1354
1355static void openssl_tls_fail_event(struct tls_connection *conn,
1356 X509 *err_cert, int err, int depth,
1357 const char *subject, const char *err_str,
1358 enum tls_fail_reason reason)
1359{
1360 union tls_event_data ev;
1361 struct wpabuf *cert = NULL;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001362 struct tls_context *context = conn->context;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001364 if (context->event_cb == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001365 return;
1366
1367 cert = get_x509_cert(err_cert);
1368 os_memset(&ev, 0, sizeof(ev));
1369 ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ?
1370 reason : openssl_tls_fail_reason(err);
1371 ev.cert_fail.depth = depth;
1372 ev.cert_fail.subject = subject;
1373 ev.cert_fail.reason_txt = err_str;
1374 ev.cert_fail.cert = cert;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001375 context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001376 wpabuf_free(cert);
1377}
1378
1379
1380static void openssl_tls_cert_event(struct tls_connection *conn,
1381 X509 *err_cert, int depth,
1382 const char *subject)
1383{
1384 struct wpabuf *cert = NULL;
1385 union tls_event_data ev;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001386 struct tls_context *context = conn->context;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001387 char *altsubject[TLS_MAX_ALT_SUBJECT];
1388 int alt, num_altsubject = 0;
1389 GENERAL_NAME *gen;
1390 void *ext;
1391 stack_index_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392#ifdef CONFIG_SHA256
1393 u8 hash[32];
1394#endif /* CONFIG_SHA256 */
1395
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001396 if (context->event_cb == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001397 return;
1398
1399 os_memset(&ev, 0, sizeof(ev));
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001400 if (conn->cert_probe || context->cert_in_cb) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001401 cert = get_x509_cert(err_cert);
1402 ev.peer_cert.cert = cert;
1403 }
1404#ifdef CONFIG_SHA256
1405 if (cert) {
1406 const u8 *addr[1];
1407 size_t len[1];
1408 addr[0] = wpabuf_head(cert);
1409 len[0] = wpabuf_len(cert);
1410 if (sha256_vector(1, addr, len, hash) == 0) {
1411 ev.peer_cert.hash = hash;
1412 ev.peer_cert.hash_len = sizeof(hash);
1413 }
1414 }
1415#endif /* CONFIG_SHA256 */
1416 ev.peer_cert.depth = depth;
1417 ev.peer_cert.subject = subject;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001418
1419 ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
1420 for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
1421 char *pos;
1422
1423 if (num_altsubject == TLS_MAX_ALT_SUBJECT)
1424 break;
1425 gen = sk_GENERAL_NAME_value(ext, i);
1426 if (gen->type != GEN_EMAIL &&
1427 gen->type != GEN_DNS &&
1428 gen->type != GEN_URI)
1429 continue;
1430
1431 pos = os_malloc(10 + gen->d.ia5->length + 1);
1432 if (pos == NULL)
1433 break;
1434 altsubject[num_altsubject++] = pos;
1435
1436 switch (gen->type) {
1437 case GEN_EMAIL:
1438 os_memcpy(pos, "EMAIL:", 6);
1439 pos += 6;
1440 break;
1441 case GEN_DNS:
1442 os_memcpy(pos, "DNS:", 4);
1443 pos += 4;
1444 break;
1445 case GEN_URI:
1446 os_memcpy(pos, "URI:", 4);
1447 pos += 4;
1448 break;
1449 }
1450
1451 os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length);
1452 pos += gen->d.ia5->length;
1453 *pos = '\0';
1454 }
1455
1456 for (alt = 0; alt < num_altsubject; alt++)
1457 ev.peer_cert.altsubject[alt] = altsubject[alt];
1458 ev.peer_cert.num_altsubject = num_altsubject;
1459
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001460 context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001461 wpabuf_free(cert);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001462 for (alt = 0; alt < num_altsubject; alt++)
1463 os_free(altsubject[alt]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001464}
1465
1466
1467static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
1468{
1469 char buf[256];
1470 X509 *err_cert;
1471 int err, depth;
1472 SSL *ssl;
1473 struct tls_connection *conn;
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001474 struct tls_context *context;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001475 char *match, *altmatch, *suffix_match, *domain_match;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001476 const char *err_str;
1477
1478 err_cert = X509_STORE_CTX_get_current_cert(x509_ctx);
Dmitry Shmidt96be6222014-02-13 10:16:51 -08001479 if (!err_cert)
1480 return 0;
1481
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001482 err = X509_STORE_CTX_get_error(x509_ctx);
1483 depth = X509_STORE_CTX_get_error_depth(x509_ctx);
1484 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
1485 SSL_get_ex_data_X509_STORE_CTX_idx());
1486 X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
1487
1488 conn = SSL_get_app_data(ssl);
1489 if (conn == NULL)
1490 return 0;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001491
1492 if (depth == 0)
1493 conn->peer_cert = err_cert;
1494 else if (depth == 1)
1495 conn->peer_issuer = err_cert;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001496 else if (depth == 2)
1497 conn->peer_issuer_issuer = err_cert;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001498
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001499 context = conn->context;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500 match = conn->subject_match;
1501 altmatch = conn->altsubject_match;
Dmitry Shmidt051af732013-10-22 13:52:46 -07001502 suffix_match = conn->suffix_match;
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001503 domain_match = conn->domain_match;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001504
1505 if (!preverify_ok && !conn->ca_cert_verify)
1506 preverify_ok = 1;
1507 if (!preverify_ok && depth > 0 && conn->server_cert_only)
1508 preverify_ok = 1;
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07001509 if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) &&
1510 (err == X509_V_ERR_CERT_HAS_EXPIRED ||
1511 err == X509_V_ERR_CERT_NOT_YET_VALID)) {
1512 wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity "
1513 "time mismatch");
1514 preverify_ok = 1;
1515 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516
1517 err_str = X509_verify_cert_error_string(err);
1518
1519#ifdef CONFIG_SHA256
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07001520 /*
1521 * Do not require preverify_ok so we can explicity allow otherwise
1522 * invalid pinned server certificates.
1523 */
1524 if (depth == 0 && conn->server_cert_only) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001525 struct wpabuf *cert;
1526 cert = get_x509_cert(err_cert);
1527 if (!cert) {
1528 wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch "
1529 "server certificate data");
1530 preverify_ok = 0;
1531 } else {
1532 u8 hash[32];
1533 const u8 *addr[1];
1534 size_t len[1];
1535 addr[0] = wpabuf_head(cert);
1536 len[0] = wpabuf_len(cert);
1537 if (sha256_vector(1, addr, len, hash) < 0 ||
1538 os_memcmp(conn->srv_cert_hash, hash, 32) != 0) {
1539 err_str = "Server certificate mismatch";
1540 err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
1541 preverify_ok = 0;
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07001542 } else if (!preverify_ok) {
1543 /*
1544 * Certificate matches pinned certificate, allow
1545 * regardless of other problems.
1546 */
1547 wpa_printf(MSG_DEBUG,
1548 "OpenSSL: Ignore validation issues for a pinned server certificate");
1549 preverify_ok = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001550 }
1551 wpabuf_free(cert);
1552 }
1553 }
1554#endif /* CONFIG_SHA256 */
1555
1556 if (!preverify_ok) {
1557 wpa_printf(MSG_WARNING, "TLS: Certificate verification failed,"
1558 " error %d (%s) depth %d for '%s'", err, err_str,
1559 depth, buf);
1560 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
1561 err_str, TLS_FAIL_UNSPECIFIED);
1562 return preverify_ok;
1563 }
1564
1565 wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d "
1566 "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'",
1567 preverify_ok, err, err_str,
1568 conn->ca_cert_verify, depth, buf);
1569 if (depth == 0 && match && os_strstr(buf, match) == NULL) {
1570 wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not "
1571 "match with '%s'", buf, match);
1572 preverify_ok = 0;
1573 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
1574 "Subject mismatch",
1575 TLS_FAIL_SUBJECT_MISMATCH);
1576 } else if (depth == 0 && altmatch &&
1577 !tls_match_altsubject(err_cert, altmatch)) {
1578 wpa_printf(MSG_WARNING, "TLS: altSubjectName match "
1579 "'%s' not found", altmatch);
1580 preverify_ok = 0;
1581 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
1582 "AltSubject mismatch",
1583 TLS_FAIL_ALTSUBJECT_MISMATCH);
Dmitry Shmidt051af732013-10-22 13:52:46 -07001584 } else if (depth == 0 && suffix_match &&
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001585 !tls_match_suffix(err_cert, suffix_match, 0)) {
Dmitry Shmidt051af732013-10-22 13:52:46 -07001586 wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found",
1587 suffix_match);
1588 preverify_ok = 0;
1589 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
1590 "Domain suffix mismatch",
1591 TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001592 } else if (depth == 0 && domain_match &&
1593 !tls_match_suffix(err_cert, domain_match, 1)) {
1594 wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found",
1595 domain_match);
1596 preverify_ok = 0;
1597 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
1598 "Domain mismatch",
1599 TLS_FAIL_DOMAIN_MISMATCH);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001600 } else
1601 openssl_tls_cert_event(conn, err_cert, depth, buf);
1602
1603 if (conn->cert_probe && preverify_ok && depth == 0) {
1604 wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate "
1605 "on probe-only run");
1606 preverify_ok = 0;
1607 openssl_tls_fail_event(conn, err_cert, err, depth, buf,
1608 "Server certificate chain probe",
1609 TLS_FAIL_SERVER_CHAIN_PROBE);
1610 }
1611
Dmitry Shmidtea69e842013-05-13 14:52:28 -07001612 if (preverify_ok && context->event_cb != NULL)
1613 context->event_cb(context->cb_ctx,
1614 TLS_CERT_CHAIN_SUCCESS, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001615
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001616 return preverify_ok;
1617}
1618
1619
1620#ifndef OPENSSL_NO_STDIO
1621static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert)
1622{
1623 SSL_CTX *ssl_ctx = _ssl_ctx;
1624 X509_LOOKUP *lookup;
1625 int ret = 0;
1626
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001627 lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(ssl_ctx),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001628 X509_LOOKUP_file());
1629 if (lookup == NULL) {
1630 tls_show_errors(MSG_WARNING, __func__,
1631 "Failed add lookup for X509 store");
1632 return -1;
1633 }
1634
1635 if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) {
1636 unsigned long err = ERR_peek_error();
1637 tls_show_errors(MSG_WARNING, __func__,
1638 "Failed load CA in DER format");
1639 if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
1640 ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1641 wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
1642 "cert already in hash table error",
1643 __func__);
1644 } else
1645 ret = -1;
1646 }
1647
1648 return ret;
1649}
1650#endif /* OPENSSL_NO_STDIO */
1651
1652
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001653static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn,
1654 const char *ca_cert, const u8 *ca_cert_blob,
1655 size_t ca_cert_blob_len, const char *ca_path)
1656{
1657 SSL_CTX *ssl_ctx = _ssl_ctx;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001658 X509_STORE *store;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001659
1660 /*
1661 * Remove previously configured trusted CA certificates before adding
1662 * new ones.
1663 */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001664 store = X509_STORE_new();
1665 if (store == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001666 wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
1667 "certificate store", __func__);
1668 return -1;
1669 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001670 SSL_CTX_set_cert_store(ssl_ctx, store);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671
1672 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
1673 conn->ca_cert_verify = 1;
1674
1675 if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) {
1676 wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate "
1677 "chain");
1678 conn->cert_probe = 1;
1679 conn->ca_cert_verify = 0;
1680 return 0;
1681 }
1682
1683 if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) {
1684#ifdef CONFIG_SHA256
1685 const char *pos = ca_cert + 7;
1686 if (os_strncmp(pos, "server/sha256/", 14) != 0) {
1687 wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert "
1688 "hash value '%s'", ca_cert);
1689 return -1;
1690 }
1691 pos += 14;
1692 if (os_strlen(pos) != 32 * 2) {
1693 wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 "
1694 "hash length in ca_cert '%s'", ca_cert);
1695 return -1;
1696 }
1697 if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) {
1698 wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash "
1699 "value in ca_cert '%s'", ca_cert);
1700 return -1;
1701 }
1702 conn->server_cert_only = 1;
1703 wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server "
1704 "certificate match");
1705 return 0;
1706#else /* CONFIG_SHA256 */
1707 wpa_printf(MSG_INFO, "No SHA256 included in the build - "
1708 "cannot validate server certificate hash");
1709 return -1;
1710#endif /* CONFIG_SHA256 */
1711 }
1712
1713 if (ca_cert_blob) {
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001714 X509 *cert = d2i_X509(NULL,
1715 (const unsigned char **) &ca_cert_blob,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716 ca_cert_blob_len);
1717 if (cert == NULL) {
1718 tls_show_errors(MSG_WARNING, __func__,
1719 "Failed to parse ca_cert_blob");
1720 return -1;
1721 }
1722
Dmitry Shmidt216983b2015-02-06 10:50:36 -08001723 if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx),
1724 cert)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725 unsigned long err = ERR_peek_error();
1726 tls_show_errors(MSG_WARNING, __func__,
1727 "Failed to add ca_cert_blob to "
1728 "certificate store");
1729 if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
1730 ERR_GET_REASON(err) ==
1731 X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1732 wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring "
1733 "cert already in hash table error",
1734 __func__);
1735 } else {
1736 X509_free(cert);
1737 return -1;
1738 }
1739 }
1740 X509_free(cert);
1741 wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob "
1742 "to certificate store", __func__);
1743 return 0;
1744 }
1745
1746#ifdef ANDROID
1747 if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) {
1748 BIO *bio = BIO_from_keystore(&ca_cert[11]);
1749 STACK_OF(X509_INFO) *stack = NULL;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001750 stack_index_t i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751
1752 if (bio) {
1753 stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
1754 BIO_free(bio);
1755 }
1756 if (!stack)
1757 return -1;
1758
1759 for (i = 0; i < sk_X509_INFO_num(stack); ++i) {
1760 X509_INFO *info = sk_X509_INFO_value(stack, i);
1761 if (info->x509) {
1762 X509_STORE_add_cert(ssl_ctx->cert_store,
1763 info->x509);
1764 }
1765 if (info->crl) {
1766 X509_STORE_add_crl(ssl_ctx->cert_store,
1767 info->crl);
1768 }
1769 }
1770 sk_X509_INFO_pop_free(stack, X509_INFO_free);
1771 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
1772 return 0;
1773 }
1774#endif /* ANDROID */
1775
1776#ifdef CONFIG_NATIVE_WINDOWS
1777 if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) ==
1778 0) {
1779 wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from "
1780 "system certificate store");
1781 return 0;
1782 }
1783#endif /* CONFIG_NATIVE_WINDOWS */
1784
1785 if (ca_cert || ca_path) {
1786#ifndef OPENSSL_NO_STDIO
1787 if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) !=
1788 1) {
1789 tls_show_errors(MSG_WARNING, __func__,
1790 "Failed to load root certificates");
1791 if (ca_cert &&
1792 tls_load_ca_der(ssl_ctx, ca_cert) == 0) {
1793 wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded "
1794 "DER format CA certificate",
1795 __func__);
1796 } else
1797 return -1;
1798 } else {
1799 wpa_printf(MSG_DEBUG, "TLS: Trusted root "
1800 "certificate(s) loaded");
1801 tls_get_errors(ssl_ctx);
1802 }
1803#else /* OPENSSL_NO_STDIO */
1804 wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
1805 __func__);
1806 return -1;
1807#endif /* OPENSSL_NO_STDIO */
1808 } else {
1809 /* No ca_cert configured - do not try to verify server
1810 * certificate */
1811 conn->ca_cert_verify = 0;
1812 }
1813
1814 return 0;
1815}
1816
1817
1818static int tls_global_ca_cert(SSL_CTX *ssl_ctx, const char *ca_cert)
1819{
1820 if (ca_cert) {
1821 if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1)
1822 {
1823 tls_show_errors(MSG_WARNING, __func__,
1824 "Failed to load root certificates");
1825 return -1;
1826 }
1827
1828 wpa_printf(MSG_DEBUG, "TLS: Trusted root "
1829 "certificate(s) loaded");
1830
1831#ifndef OPENSSL_NO_STDIO
1832 /* Add the same CAs to the client certificate requests */
1833 SSL_CTX_set_client_CA_list(ssl_ctx,
1834 SSL_load_client_CA_file(ca_cert));
1835#endif /* OPENSSL_NO_STDIO */
1836 }
1837
1838 return 0;
1839}
1840
1841
1842int tls_global_set_verify(void *ssl_ctx, int check_crl)
1843{
1844 int flags;
1845
1846 if (check_crl) {
1847 X509_STORE *cs = SSL_CTX_get_cert_store(ssl_ctx);
1848 if (cs == NULL) {
1849 tls_show_errors(MSG_INFO, __func__, "Failed to get "
1850 "certificate store when enabling "
1851 "check_crl");
1852 return -1;
1853 }
1854 flags = X509_V_FLAG_CRL_CHECK;
1855 if (check_crl == 2)
1856 flags |= X509_V_FLAG_CRL_CHECK_ALL;
1857 X509_STORE_set_flags(cs, flags);
1858 }
1859 return 0;
1860}
1861
1862
1863static int tls_connection_set_subject_match(struct tls_connection *conn,
1864 const char *subject_match,
Dmitry Shmidt051af732013-10-22 13:52:46 -07001865 const char *altsubject_match,
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001866 const char *suffix_match,
1867 const char *domain_match)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001868{
1869 os_free(conn->subject_match);
1870 conn->subject_match = NULL;
1871 if (subject_match) {
1872 conn->subject_match = os_strdup(subject_match);
1873 if (conn->subject_match == NULL)
1874 return -1;
1875 }
1876
1877 os_free(conn->altsubject_match);
1878 conn->altsubject_match = NULL;
1879 if (altsubject_match) {
1880 conn->altsubject_match = os_strdup(altsubject_match);
1881 if (conn->altsubject_match == NULL)
1882 return -1;
1883 }
1884
Dmitry Shmidt051af732013-10-22 13:52:46 -07001885 os_free(conn->suffix_match);
1886 conn->suffix_match = NULL;
1887 if (suffix_match) {
1888 conn->suffix_match = os_strdup(suffix_match);
1889 if (conn->suffix_match == NULL)
1890 return -1;
1891 }
1892
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001893 os_free(conn->domain_match);
1894 conn->domain_match = NULL;
1895 if (domain_match) {
1896 conn->domain_match = os_strdup(domain_match);
1897 if (conn->domain_match == NULL)
1898 return -1;
1899 }
1900
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001901 return 0;
1902}
1903
1904
1905int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn,
1906 int verify_peer)
1907{
1908 static int counter = 0;
1909
1910 if (conn == NULL)
1911 return -1;
1912
1913 if (verify_peer) {
1914 conn->ca_cert_verify = 1;
1915 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER |
1916 SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
1917 SSL_VERIFY_CLIENT_ONCE, tls_verify_cb);
1918 } else {
1919 conn->ca_cert_verify = 0;
1920 SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
1921 }
1922
1923 SSL_set_accept_state(conn->ssl);
1924
1925 /*
1926 * Set session id context in order to avoid fatal errors when client
1927 * tries to resume a session. However, set the context to a unique
1928 * value in order to effectively disable session resumption for now
1929 * since not all areas of the server code are ready for it (e.g.,
1930 * EAP-TTLS needs special handling for Phase 2 after abbreviated TLS
1931 * handshake).
1932 */
1933 counter++;
1934 SSL_set_session_id_context(conn->ssl,
1935 (const unsigned char *) &counter,
1936 sizeof(counter));
1937
1938 return 0;
1939}
1940
1941
1942static int tls_connection_client_cert(struct tls_connection *conn,
1943 const char *client_cert,
1944 const u8 *client_cert_blob,
1945 size_t client_cert_blob_len)
1946{
1947 if (client_cert == NULL && client_cert_blob == NULL)
1948 return 0;
1949
1950 if (client_cert_blob &&
1951 SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob,
1952 client_cert_blob_len) == 1) {
1953 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> "
1954 "OK");
1955 return 0;
1956 } else if (client_cert_blob) {
1957 tls_show_errors(MSG_DEBUG, __func__,
1958 "SSL_use_certificate_ASN1 failed");
1959 }
1960
1961 if (client_cert == NULL)
1962 return -1;
1963
1964#ifdef ANDROID
1965 if (os_strncmp("keystore://", client_cert, 11) == 0) {
1966 BIO *bio = BIO_from_keystore(&client_cert[11]);
1967 X509 *x509 = NULL;
1968 int ret = -1;
1969 if (bio) {
1970 x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
1971 BIO_free(bio);
1972 }
1973 if (x509) {
1974 if (SSL_use_certificate(conn->ssl, x509) == 1)
1975 ret = 0;
1976 X509_free(x509);
1977 }
1978 return ret;
1979 }
1980#endif /* ANDROID */
1981
1982#ifndef OPENSSL_NO_STDIO
1983 if (SSL_use_certificate_file(conn->ssl, client_cert,
1984 SSL_FILETYPE_ASN1) == 1) {
1985 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)"
1986 " --> OK");
1987 return 0;
1988 }
1989
1990 if (SSL_use_certificate_file(conn->ssl, client_cert,
1991 SSL_FILETYPE_PEM) == 1) {
1992 ERR_clear_error();
1993 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)"
1994 " --> OK");
1995 return 0;
1996 }
1997
1998 tls_show_errors(MSG_DEBUG, __func__,
1999 "SSL_use_certificate_file failed");
2000#else /* OPENSSL_NO_STDIO */
2001 wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
2002#endif /* OPENSSL_NO_STDIO */
2003
2004 return -1;
2005}
2006
2007
2008static int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert)
2009{
2010#ifndef OPENSSL_NO_STDIO
2011 if (client_cert == NULL)
2012 return 0;
2013
2014 if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
2015 SSL_FILETYPE_ASN1) != 1 &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002016 SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017 SSL_CTX_use_certificate_file(ssl_ctx, client_cert,
2018 SSL_FILETYPE_PEM) != 1) {
2019 tls_show_errors(MSG_INFO, __func__,
2020 "Failed to load client certificate");
2021 return -1;
2022 }
2023 return 0;
2024#else /* OPENSSL_NO_STDIO */
2025 if (client_cert == NULL)
2026 return 0;
2027 wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__);
2028 return -1;
2029#endif /* OPENSSL_NO_STDIO */
2030}
2031
2032
2033static int tls_passwd_cb(char *buf, int size, int rwflag, void *password)
2034{
2035 if (password == NULL) {
2036 return 0;
2037 }
2038 os_strlcpy(buf, (char *) password, size);
2039 return os_strlen(buf);
2040}
2041
2042
2043#ifdef PKCS12_FUNCS
2044static int tls_parse_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, PKCS12 *p12,
2045 const char *passwd)
2046{
2047 EVP_PKEY *pkey;
2048 X509 *cert;
2049 STACK_OF(X509) *certs;
2050 int res = 0;
2051 char buf[256];
2052
2053 pkey = NULL;
2054 cert = NULL;
2055 certs = NULL;
2056 if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) {
2057 tls_show_errors(MSG_DEBUG, __func__,
2058 "Failed to parse PKCS12 file");
2059 PKCS12_free(p12);
2060 return -1;
2061 }
2062 wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data");
2063
2064 if (cert) {
2065 X509_NAME_oneline(X509_get_subject_name(cert), buf,
2066 sizeof(buf));
2067 wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: "
2068 "subject='%s'", buf);
2069 if (ssl) {
2070 if (SSL_use_certificate(ssl, cert) != 1)
2071 res = -1;
2072 } else {
2073 if (SSL_CTX_use_certificate(ssl_ctx, cert) != 1)
2074 res = -1;
2075 }
2076 X509_free(cert);
2077 }
2078
2079 if (pkey) {
2080 wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12");
2081 if (ssl) {
2082 if (SSL_use_PrivateKey(ssl, pkey) != 1)
2083 res = -1;
2084 } else {
2085 if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1)
2086 res = -1;
2087 }
2088 EVP_PKEY_free(pkey);
2089 }
2090
2091 if (certs) {
2092 while ((cert = sk_X509_pop(certs)) != NULL) {
2093 X509_NAME_oneline(X509_get_subject_name(cert), buf,
2094 sizeof(buf));
2095 wpa_printf(MSG_DEBUG, "TLS: additional certificate"
2096 " from PKCS12: subject='%s'", buf);
2097 /*
2098 * There is no SSL equivalent for the chain cert - so
2099 * always add it to the context...
2100 */
2101 if (SSL_CTX_add_extra_chain_cert(ssl_ctx, cert) != 1) {
2102 res = -1;
2103 break;
2104 }
2105 }
2106 sk_X509_free(certs);
2107 }
2108
2109 PKCS12_free(p12);
2110
2111 if (res < 0)
2112 tls_get_errors(ssl_ctx);
2113
2114 return res;
2115}
2116#endif /* PKCS12_FUNCS */
2117
2118
2119static int tls_read_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, const char *private_key,
2120 const char *passwd)
2121{
2122#ifdef PKCS12_FUNCS
2123 FILE *f;
2124 PKCS12 *p12;
2125
2126 f = fopen(private_key, "rb");
2127 if (f == NULL)
2128 return -1;
2129
2130 p12 = d2i_PKCS12_fp(f, NULL);
2131 fclose(f);
2132
2133 if (p12 == NULL) {
2134 tls_show_errors(MSG_INFO, __func__,
2135 "Failed to use PKCS#12 file");
2136 return -1;
2137 }
2138
2139 return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd);
2140
2141#else /* PKCS12_FUNCS */
2142 wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read "
2143 "p12/pfx files");
2144 return -1;
2145#endif /* PKCS12_FUNCS */
2146}
2147
2148
2149static int tls_read_pkcs12_blob(SSL_CTX *ssl_ctx, SSL *ssl,
2150 const u8 *blob, size_t len, const char *passwd)
2151{
2152#ifdef PKCS12_FUNCS
2153 PKCS12 *p12;
2154
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002155 p12 = d2i_PKCS12(NULL, (const unsigned char **) &blob, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002156 if (p12 == NULL) {
2157 tls_show_errors(MSG_INFO, __func__,
2158 "Failed to use PKCS#12 blob");
2159 return -1;
2160 }
2161
2162 return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd);
2163
2164#else /* PKCS12_FUNCS */
2165 wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse "
2166 "p12/pfx blobs");
2167 return -1;
2168#endif /* PKCS12_FUNCS */
2169}
2170
2171
2172#ifndef OPENSSL_NO_ENGINE
2173static int tls_engine_get_cert(struct tls_connection *conn,
2174 const char *cert_id,
2175 X509 **cert)
2176{
2177 /* this runs after the private key is loaded so no PIN is required */
2178 struct {
2179 const char *cert_id;
2180 X509 *cert;
2181 } params;
2182 params.cert_id = cert_id;
2183 params.cert = NULL;
2184
2185 if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL",
2186 0, &params, NULL, 1)) {
2187 wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id"
2188 " '%s' [%s]", cert_id,
2189 ERR_error_string(ERR_get_error(), NULL));
2190 return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
2191 }
2192 if (!params.cert) {
2193 wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id"
2194 " '%s'", cert_id);
2195 return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED;
2196 }
2197 *cert = params.cert;
2198 return 0;
2199}
2200#endif /* OPENSSL_NO_ENGINE */
2201
2202
2203static int tls_connection_engine_client_cert(struct tls_connection *conn,
2204 const char *cert_id)
2205{
2206#ifndef OPENSSL_NO_ENGINE
2207 X509 *cert;
2208
2209 if (tls_engine_get_cert(conn, cert_id, &cert))
2210 return -1;
2211
2212 if (!SSL_use_certificate(conn->ssl, cert)) {
2213 tls_show_errors(MSG_ERROR, __func__,
2214 "SSL_use_certificate failed");
2215 X509_free(cert);
2216 return -1;
2217 }
2218 X509_free(cert);
2219 wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> "
2220 "OK");
2221 return 0;
2222
2223#else /* OPENSSL_NO_ENGINE */
2224 return -1;
2225#endif /* OPENSSL_NO_ENGINE */
2226}
2227
2228
2229static int tls_connection_engine_ca_cert(void *_ssl_ctx,
2230 struct tls_connection *conn,
2231 const char *ca_cert_id)
2232{
2233#ifndef OPENSSL_NO_ENGINE
2234 X509 *cert;
2235 SSL_CTX *ssl_ctx = _ssl_ctx;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002236 X509_STORE *store;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237
2238 if (tls_engine_get_cert(conn, ca_cert_id, &cert))
2239 return -1;
2240
2241 /* start off the same as tls_connection_ca_cert */
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002242 store = X509_STORE_new();
2243 if (store == NULL) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002244 wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new "
2245 "certificate store", __func__);
2246 X509_free(cert);
2247 return -1;
2248 }
Dmitry Shmidt216983b2015-02-06 10:50:36 -08002249 SSL_CTX_set_cert_store(ssl_ctx, store);
2250 if (!X509_STORE_add_cert(store, cert)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002251 unsigned long err = ERR_peek_error();
2252 tls_show_errors(MSG_WARNING, __func__,
2253 "Failed to add CA certificate from engine "
2254 "to certificate store");
2255 if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
2256 ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
2257 wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert"
2258 " already in hash table error",
2259 __func__);
2260 } else {
2261 X509_free(cert);
2262 return -1;
2263 }
2264 }
2265 X509_free(cert);
2266 wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine "
2267 "to certificate store", __func__);
2268 SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002269 conn->ca_cert_verify = 1;
2270
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002271 return 0;
2272
2273#else /* OPENSSL_NO_ENGINE */
2274 return -1;
2275#endif /* OPENSSL_NO_ENGINE */
2276}
2277
2278
2279static int tls_connection_engine_private_key(struct tls_connection *conn)
2280{
2281#ifndef OPENSSL_NO_ENGINE
2282 if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) {
2283 tls_show_errors(MSG_ERROR, __func__,
2284 "ENGINE: cannot use private key for TLS");
2285 return -1;
2286 }
2287 if (!SSL_check_private_key(conn->ssl)) {
2288 tls_show_errors(MSG_INFO, __func__,
2289 "Private key failed verification");
2290 return -1;
2291 }
2292 return 0;
2293#else /* OPENSSL_NO_ENGINE */
2294 wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but "
2295 "engine support was not compiled in");
2296 return -1;
2297#endif /* OPENSSL_NO_ENGINE */
2298}
2299
2300
2301static int tls_connection_private_key(void *_ssl_ctx,
2302 struct tls_connection *conn,
2303 const char *private_key,
2304 const char *private_key_passwd,
2305 const u8 *private_key_blob,
2306 size_t private_key_blob_len)
2307{
2308 SSL_CTX *ssl_ctx = _ssl_ctx;
2309 char *passwd;
2310 int ok;
2311
2312 if (private_key == NULL && private_key_blob == NULL)
2313 return 0;
2314
2315 if (private_key_passwd) {
2316 passwd = os_strdup(private_key_passwd);
2317 if (passwd == NULL)
2318 return -1;
2319 } else
2320 passwd = NULL;
2321
2322 SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
2323 SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd);
2324
2325 ok = 0;
2326 while (private_key_blob) {
2327 if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl,
2328 (u8 *) private_key_blob,
2329 private_key_blob_len) == 1) {
2330 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
2331 "ASN1(EVP_PKEY_RSA) --> OK");
2332 ok = 1;
2333 break;
2334 }
2335
2336 if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl,
2337 (u8 *) private_key_blob,
2338 private_key_blob_len) == 1) {
2339 wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_"
2340 "ASN1(EVP_PKEY_DSA) --> OK");
2341 ok = 1;
2342 break;
2343 }
2344
2345 if (SSL_use_RSAPrivateKey_ASN1(conn->ssl,
2346 (u8 *) private_key_blob,
2347 private_key_blob_len) == 1) {
2348 wpa_printf(MSG_DEBUG, "OpenSSL: "
2349 "SSL_use_RSAPrivateKey_ASN1 --> OK");
2350 ok = 1;
2351 break;
2352 }
2353
2354 if (tls_read_pkcs12_blob(ssl_ctx, conn->ssl, private_key_blob,
2355 private_key_blob_len, passwd) == 0) {
2356 wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> "
2357 "OK");
2358 ok = 1;
2359 break;
2360 }
2361
2362 break;
2363 }
2364
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002365 while (!ok && private_key) {
2366#ifndef OPENSSL_NO_STDIO
2367 if (SSL_use_PrivateKey_file(conn->ssl, private_key,
2368 SSL_FILETYPE_ASN1) == 1) {
2369 wpa_printf(MSG_DEBUG, "OpenSSL: "
2370 "SSL_use_PrivateKey_File (DER) --> OK");
2371 ok = 1;
2372 break;
2373 }
2374
2375 if (SSL_use_PrivateKey_file(conn->ssl, private_key,
2376 SSL_FILETYPE_PEM) == 1) {
2377 wpa_printf(MSG_DEBUG, "OpenSSL: "
2378 "SSL_use_PrivateKey_File (PEM) --> OK");
2379 ok = 1;
2380 break;
2381 }
2382#else /* OPENSSL_NO_STDIO */
2383 wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO",
2384 __func__);
2385#endif /* OPENSSL_NO_STDIO */
2386
2387 if (tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd)
2388 == 0) {
2389 wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file "
2390 "--> OK");
2391 ok = 1;
2392 break;
2393 }
2394
2395 if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) {
2396 wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to "
2397 "access certificate store --> OK");
2398 ok = 1;
2399 break;
2400 }
2401
2402 break;
2403 }
2404
2405 if (!ok) {
2406 tls_show_errors(MSG_INFO, __func__,
2407 "Failed to load private key");
2408 os_free(passwd);
2409 return -1;
2410 }
2411 ERR_clear_error();
2412 SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
2413 os_free(passwd);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002414
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002415 if (!SSL_check_private_key(conn->ssl)) {
2416 tls_show_errors(MSG_INFO, __func__, "Private key failed "
2417 "verification");
2418 return -1;
2419 }
2420
2421 wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully");
2422 return 0;
2423}
2424
2425
2426static int tls_global_private_key(SSL_CTX *ssl_ctx, const char *private_key,
2427 const char *private_key_passwd)
2428{
2429 char *passwd;
2430
2431 if (private_key == NULL)
2432 return 0;
2433
2434 if (private_key_passwd) {
2435 passwd = os_strdup(private_key_passwd);
2436 if (passwd == NULL)
2437 return -1;
2438 } else
2439 passwd = NULL;
2440
2441 SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
2442 SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd);
2443 if (
2444#ifndef OPENSSL_NO_STDIO
2445 SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key,
2446 SSL_FILETYPE_ASN1) != 1 &&
2447 SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key,
2448 SSL_FILETYPE_PEM) != 1 &&
2449#endif /* OPENSSL_NO_STDIO */
2450 tls_read_pkcs12(ssl_ctx, NULL, private_key, passwd)) {
2451 tls_show_errors(MSG_INFO, __func__,
2452 "Failed to load private key");
2453 os_free(passwd);
2454 ERR_clear_error();
2455 return -1;
2456 }
2457 os_free(passwd);
2458 ERR_clear_error();
2459 SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002460
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 if (!SSL_CTX_check_private_key(ssl_ctx)) {
2462 tls_show_errors(MSG_INFO, __func__,
2463 "Private key failed verification");
2464 return -1;
2465 }
2466
2467 return 0;
2468}
2469
2470
2471static int tls_connection_dh(struct tls_connection *conn, const char *dh_file)
2472{
2473#ifdef OPENSSL_NO_DH
2474 if (dh_file == NULL)
2475 return 0;
2476 wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
2477 "dh_file specified");
2478 return -1;
2479#else /* OPENSSL_NO_DH */
2480 DH *dh;
2481 BIO *bio;
2482
2483 /* TODO: add support for dh_blob */
2484 if (dh_file == NULL)
2485 return 0;
2486 if (conn == NULL)
2487 return -1;
2488
2489 bio = BIO_new_file(dh_file, "r");
2490 if (bio == NULL) {
2491 wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
2492 dh_file, ERR_error_string(ERR_get_error(), NULL));
2493 return -1;
2494 }
2495 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2496 BIO_free(bio);
2497#ifndef OPENSSL_NO_DSA
2498 while (dh == NULL) {
2499 DSA *dsa;
2500 wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
2501 " trying to parse as DSA params", dh_file,
2502 ERR_error_string(ERR_get_error(), NULL));
2503 bio = BIO_new_file(dh_file, "r");
2504 if (bio == NULL)
2505 break;
2506 dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
2507 BIO_free(bio);
2508 if (!dsa) {
2509 wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
2510 "'%s': %s", dh_file,
2511 ERR_error_string(ERR_get_error(), NULL));
2512 break;
2513 }
2514
2515 wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
2516 dh = DSA_dup_DH(dsa);
2517 DSA_free(dsa);
2518 if (dh == NULL) {
2519 wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
2520 "params into DH params");
2521 break;
2522 }
2523 break;
2524 }
2525#endif /* !OPENSSL_NO_DSA */
2526 if (dh == NULL) {
2527 wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
2528 "'%s'", dh_file);
2529 return -1;
2530 }
2531
2532 if (SSL_set_tmp_dh(conn->ssl, dh) != 1) {
2533 wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
2534 "%s", dh_file,
2535 ERR_error_string(ERR_get_error(), NULL));
2536 DH_free(dh);
2537 return -1;
2538 }
2539 DH_free(dh);
2540 return 0;
2541#endif /* OPENSSL_NO_DH */
2542}
2543
2544
2545static int tls_global_dh(SSL_CTX *ssl_ctx, const char *dh_file)
2546{
2547#ifdef OPENSSL_NO_DH
2548 if (dh_file == NULL)
2549 return 0;
2550 wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
2551 "dh_file specified");
2552 return -1;
2553#else /* OPENSSL_NO_DH */
2554 DH *dh;
2555 BIO *bio;
2556
2557 /* TODO: add support for dh_blob */
2558 if (dh_file == NULL)
2559 return 0;
2560 if (ssl_ctx == NULL)
2561 return -1;
2562
2563 bio = BIO_new_file(dh_file, "r");
2564 if (bio == NULL) {
2565 wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
2566 dh_file, ERR_error_string(ERR_get_error(), NULL));
2567 return -1;
2568 }
2569 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2570 BIO_free(bio);
2571#ifndef OPENSSL_NO_DSA
2572 while (dh == NULL) {
2573 DSA *dsa;
2574 wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
2575 " trying to parse as DSA params", dh_file,
2576 ERR_error_string(ERR_get_error(), NULL));
2577 bio = BIO_new_file(dh_file, "r");
2578 if (bio == NULL)
2579 break;
2580 dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
2581 BIO_free(bio);
2582 if (!dsa) {
2583 wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
2584 "'%s': %s", dh_file,
2585 ERR_error_string(ERR_get_error(), NULL));
2586 break;
2587 }
2588
2589 wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
2590 dh = DSA_dup_DH(dsa);
2591 DSA_free(dsa);
2592 if (dh == NULL) {
2593 wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
2594 "params into DH params");
2595 break;
2596 }
2597 break;
2598 }
2599#endif /* !OPENSSL_NO_DSA */
2600 if (dh == NULL) {
2601 wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
2602 "'%s'", dh_file);
2603 return -1;
2604 }
2605
2606 if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) {
2607 wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
2608 "%s", dh_file,
2609 ERR_error_string(ERR_get_error(), NULL));
2610 DH_free(dh);
2611 return -1;
2612 }
2613 DH_free(dh);
2614 return 0;
2615#endif /* OPENSSL_NO_DH */
2616}
2617
2618
2619int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn,
2620 struct tls_keys *keys)
2621{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002622#ifdef CONFIG_FIPS
2623 wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS "
2624 "mode");
2625 return -1;
2626#else /* CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627 SSL *ssl;
2628
2629 if (conn == NULL || keys == NULL)
2630 return -1;
2631 ssl = conn->ssl;
2632 if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL)
2633 return -1;
2634
2635 os_memset(keys, 0, sizeof(*keys));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636 keys->client_random = ssl->s3->client_random;
2637 keys->client_random_len = SSL3_RANDOM_SIZE;
2638 keys->server_random = ssl->s3->server_random;
2639 keys->server_random_len = SSL3_RANDOM_SIZE;
2640
2641 return 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002642#endif /* CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643}
2644
2645
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07002646static int openssl_get_keyblock_size(SSL *ssl)
2647{
2648 const EVP_CIPHER *c;
2649 const EVP_MD *h;
2650 int md_size;
2651
2652 if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL ||
2653 ssl->read_hash == NULL)
2654 return -1;
2655
2656 c = ssl->enc_read_ctx->cipher;
2657#if OPENSSL_VERSION_NUMBER >= 0x00909000L
2658 h = EVP_MD_CTX_md(ssl->read_hash);
2659#else
2660 h = conn->ssl->read_hash;
2661#endif
2662 if (h)
2663 md_size = EVP_MD_size(h);
2664#if OPENSSL_VERSION_NUMBER >= 0x10000000L
2665 else if (ssl->s3)
2666 md_size = ssl->s3->tmp.new_mac_secret_size;
2667#endif
2668 else
2669 return -1;
2670
2671 wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d "
2672 "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
2673 EVP_CIPHER_iv_length(c));
2674 return 2 * (EVP_CIPHER_key_length(c) +
2675 md_size +
2676 EVP_CIPHER_iv_length(c));
2677}
2678
2679
2680static int openssl_tls_prf(void *tls_ctx, struct tls_connection *conn,
2681 const char *label, int server_random_first,
2682 int skip_keyblock, u8 *out, size_t out_len)
2683{
2684#ifdef CONFIG_FIPS
2685 wpa_printf(MSG_ERROR, "OpenSSL: TLS keys cannot be exported in FIPS "
2686 "mode");
2687 return -1;
2688#else /* CONFIG_FIPS */
2689 SSL *ssl;
2690 u8 *rnd;
2691 int ret = -1;
2692 int skip = 0;
2693 u8 *tmp_out = NULL;
2694 u8 *_out = out;
2695
2696 /*
2697 * TLS library did not support key generation, so get the needed TLS
2698 * session parameters and use an internal implementation of TLS PRF to
2699 * derive the key.
2700 */
2701
2702 if (conn == NULL)
2703 return -1;
2704 ssl = conn->ssl;
2705 if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL ||
2706 ssl->s3->client_random == NULL || ssl->s3->server_random == NULL ||
2707 ssl->session->master_key == NULL)
2708 return -1;
2709
2710 if (skip_keyblock) {
2711 skip = openssl_get_keyblock_size(ssl);
2712 if (skip < 0)
2713 return -1;
2714 tmp_out = os_malloc(skip + out_len);
2715 if (!tmp_out)
2716 return -1;
2717 _out = tmp_out;
2718 }
2719
2720 rnd = os_malloc(2 * SSL3_RANDOM_SIZE);
2721 if (rnd == NULL)
2722 return -1;
2723 if (server_random_first) {
2724 os_memcpy(rnd, ssl->s3->server_random, SSL3_RANDOM_SIZE);
2725 os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->client_random,
2726 SSL3_RANDOM_SIZE);
2727 } else {
2728 os_memcpy(rnd, ssl->s3->client_random, SSL3_RANDOM_SIZE);
2729 os_memcpy(rnd + SSL3_RANDOM_SIZE, ssl->s3->server_random,
2730 SSL3_RANDOM_SIZE);
2731 }
2732
2733 /* TODO: TLSv1.2 may need another PRF. This could use something closer
2734 * to SSL_export_keying_material() design. */
2735 if (tls_prf_sha1_md5(ssl->session->master_key,
2736 ssl->session->master_key_length,
2737 label, rnd, 2 * SSL3_RANDOM_SIZE,
2738 _out, skip + out_len) == 0)
2739 ret = 0;
2740 os_free(rnd);
2741 if (ret == 0 && skip_keyblock)
2742 os_memcpy(out, _out + skip, out_len);
2743 bin_clear_free(tmp_out, skip);
2744
2745 return ret;
2746#endif /* CONFIG_FIPS */
2747}
2748
2749
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
2751 const char *label, int server_random_first,
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07002752 int skip_keyblock, u8 *out, size_t out_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002753{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754#if OPENSSL_VERSION_NUMBER >= 0x10001000L
2755 SSL *ssl;
2756 if (conn == NULL)
2757 return -1;
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07002758 if (server_random_first || skip_keyblock)
2759 return openssl_tls_prf(tls_ctx, conn, label,
2760 server_random_first, skip_keyblock,
2761 out, out_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002762 ssl = conn->ssl;
2763 if (SSL_export_keying_material(ssl, out, out_len, label,
2764 os_strlen(label), NULL, 0, 0) == 1) {
2765 wpa_printf(MSG_DEBUG, "OpenSSL: Using internal PRF");
2766 return 0;
2767 }
2768#endif
Dmitry Shmidtaf9da312015-04-03 10:03:11 -07002769 return openssl_tls_prf(tls_ctx, conn, label, server_random_first,
2770 skip_keyblock, out, out_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771}
2772
2773
2774static struct wpabuf *
2775openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data,
2776 int server)
2777{
2778 int res;
2779 struct wpabuf *out_data;
2780
2781 /*
2782 * Give TLS handshake data from the server (if available) to OpenSSL
2783 * for processing.
2784 */
2785 if (in_data &&
2786 BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data))
2787 < 0) {
2788 tls_show_errors(MSG_INFO, __func__,
2789 "Handshake failed - BIO_write");
2790 return NULL;
2791 }
2792
2793 /* Initiate TLS handshake or continue the existing handshake */
2794 if (server)
2795 res = SSL_accept(conn->ssl);
2796 else
2797 res = SSL_connect(conn->ssl);
2798 if (res != 1) {
2799 int err = SSL_get_error(conn->ssl, res);
2800 if (err == SSL_ERROR_WANT_READ)
2801 wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want "
2802 "more data");
2803 else if (err == SSL_ERROR_WANT_WRITE)
2804 wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to "
2805 "write");
2806 else {
2807 tls_show_errors(MSG_INFO, __func__, "SSL_connect");
2808 conn->failed++;
2809 }
2810 }
2811
2812 /* Get the TLS handshake data to be sent to the server */
2813 res = BIO_ctrl_pending(conn->ssl_out);
2814 wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res);
2815 out_data = wpabuf_alloc(res);
2816 if (out_data == NULL) {
2817 wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for "
2818 "handshake output (%d bytes)", res);
2819 if (BIO_reset(conn->ssl_out) < 0) {
2820 tls_show_errors(MSG_INFO, __func__,
2821 "BIO_reset failed");
2822 }
2823 return NULL;
2824 }
2825 res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data),
2826 res);
2827 if (res < 0) {
2828 tls_show_errors(MSG_INFO, __func__,
2829 "Handshake failed - BIO_read");
2830 if (BIO_reset(conn->ssl_out) < 0) {
2831 tls_show_errors(MSG_INFO, __func__,
2832 "BIO_reset failed");
2833 }
2834 wpabuf_free(out_data);
2835 return NULL;
2836 }
2837 wpabuf_put(out_data, res);
2838
2839 return out_data;
2840}
2841
2842
2843static struct wpabuf *
2844openssl_get_appl_data(struct tls_connection *conn, size_t max_len)
2845{
2846 struct wpabuf *appl_data;
2847 int res;
2848
2849 appl_data = wpabuf_alloc(max_len + 100);
2850 if (appl_data == NULL)
2851 return NULL;
2852
2853 res = SSL_read(conn->ssl, wpabuf_mhead(appl_data),
2854 wpabuf_size(appl_data));
2855 if (res < 0) {
2856 int err = SSL_get_error(conn->ssl, res);
2857 if (err == SSL_ERROR_WANT_READ ||
2858 err == SSL_ERROR_WANT_WRITE) {
2859 wpa_printf(MSG_DEBUG, "SSL: No Application Data "
2860 "included");
2861 } else {
2862 tls_show_errors(MSG_INFO, __func__,
2863 "Failed to read possible "
2864 "Application Data");
2865 }
2866 wpabuf_free(appl_data);
2867 return NULL;
2868 }
2869
2870 wpabuf_put(appl_data, res);
2871 wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished "
2872 "message", appl_data);
2873
2874 return appl_data;
2875}
2876
2877
2878static struct wpabuf *
2879openssl_connection_handshake(struct tls_connection *conn,
2880 const struct wpabuf *in_data,
2881 struct wpabuf **appl_data, int server)
2882{
2883 struct wpabuf *out_data;
2884
2885 if (appl_data)
2886 *appl_data = NULL;
2887
2888 out_data = openssl_handshake(conn, in_data, server);
2889 if (out_data == NULL)
2890 return NULL;
Jouni Malinen26af48b2014-04-09 13:02:53 +03002891 if (conn->invalid_hb_used) {
2892 wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
2893 wpabuf_free(out_data);
2894 return NULL;
2895 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002896
2897 if (SSL_is_init_finished(conn->ssl) && appl_data && in_data)
2898 *appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data));
2899
Jouni Malinen26af48b2014-04-09 13:02:53 +03002900 if (conn->invalid_hb_used) {
2901 wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
2902 if (appl_data) {
2903 wpabuf_free(*appl_data);
2904 *appl_data = NULL;
2905 }
2906 wpabuf_free(out_data);
2907 return NULL;
2908 }
2909
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002910 return out_data;
2911}
2912
2913
2914struct wpabuf *
2915tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn,
2916 const struct wpabuf *in_data,
2917 struct wpabuf **appl_data)
2918{
2919 return openssl_connection_handshake(conn, in_data, appl_data, 0);
2920}
2921
2922
2923struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
2924 struct tls_connection *conn,
2925 const struct wpabuf *in_data,
2926 struct wpabuf **appl_data)
2927{
2928 return openssl_connection_handshake(conn, in_data, appl_data, 1);
2929}
2930
2931
2932struct wpabuf * tls_connection_encrypt(void *tls_ctx,
2933 struct tls_connection *conn,
2934 const struct wpabuf *in_data)
2935{
2936 int res;
2937 struct wpabuf *buf;
2938
2939 if (conn == NULL)
2940 return NULL;
2941
2942 /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */
2943 if ((res = BIO_reset(conn->ssl_in)) < 0 ||
2944 (res = BIO_reset(conn->ssl_out)) < 0) {
2945 tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
2946 return NULL;
2947 }
2948 res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data));
2949 if (res < 0) {
2950 tls_show_errors(MSG_INFO, __func__,
2951 "Encryption failed - SSL_write");
2952 return NULL;
2953 }
2954
2955 /* Read encrypted data to be sent to the server */
2956 buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
2957 if (buf == NULL)
2958 return NULL;
2959 res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf));
2960 if (res < 0) {
2961 tls_show_errors(MSG_INFO, __func__,
2962 "Encryption failed - BIO_read");
2963 wpabuf_free(buf);
2964 return NULL;
2965 }
2966 wpabuf_put(buf, res);
2967
2968 return buf;
2969}
2970
2971
2972struct wpabuf * tls_connection_decrypt(void *tls_ctx,
2973 struct tls_connection *conn,
2974 const struct wpabuf *in_data)
2975{
2976 int res;
2977 struct wpabuf *buf;
2978
2979 /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */
2980 res = BIO_write(conn->ssl_in, wpabuf_head(in_data),
2981 wpabuf_len(in_data));
2982 if (res < 0) {
2983 tls_show_errors(MSG_INFO, __func__,
2984 "Decryption failed - BIO_write");
2985 return NULL;
2986 }
2987 if (BIO_reset(conn->ssl_out) < 0) {
2988 tls_show_errors(MSG_INFO, __func__, "BIO_reset failed");
2989 return NULL;
2990 }
2991
2992 /* Read decrypted data for further processing */
2993 /*
2994 * Even though we try to disable TLS compression, it is possible that
2995 * this cannot be done with all TLS libraries. Add extra buffer space
2996 * to handle the possibility of the decrypted data being longer than
2997 * input data.
2998 */
2999 buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
3000 if (buf == NULL)
3001 return NULL;
3002 res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf));
3003 if (res < 0) {
3004 tls_show_errors(MSG_INFO, __func__,
3005 "Decryption failed - SSL_read");
3006 wpabuf_free(buf);
3007 return NULL;
3008 }
3009 wpabuf_put(buf, res);
3010
Jouni Malinen26af48b2014-04-09 13:02:53 +03003011 if (conn->invalid_hb_used) {
3012 wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response");
3013 wpabuf_free(buf);
3014 return NULL;
3015 }
3016
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003017 return buf;
3018}
3019
3020
3021int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn)
3022{
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003023#if OPENSSL_VERSION_NUMBER >= 0x10001000L
3024 return conn ? SSL_cache_hit(conn->ssl) : 0;
3025#else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003026 return conn ? conn->ssl->hit : 0;
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003027#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003028}
3029
3030
3031int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
3032 u8 *ciphers)
3033{
3034 char buf[100], *pos, *end;
3035 u8 *c;
3036 int ret;
3037
3038 if (conn == NULL || conn->ssl == NULL || ciphers == NULL)
3039 return -1;
3040
3041 buf[0] = '\0';
3042 pos = buf;
3043 end = pos + sizeof(buf);
3044
3045 c = ciphers;
3046 while (*c != TLS_CIPHER_NONE) {
3047 const char *suite;
3048
3049 switch (*c) {
3050 case TLS_CIPHER_RC4_SHA:
3051 suite = "RC4-SHA";
3052 break;
3053 case TLS_CIPHER_AES128_SHA:
3054 suite = "AES128-SHA";
3055 break;
3056 case TLS_CIPHER_RSA_DHE_AES128_SHA:
3057 suite = "DHE-RSA-AES128-SHA";
3058 break;
3059 case TLS_CIPHER_ANON_DH_AES128_SHA:
3060 suite = "ADH-AES128-SHA";
3061 break;
3062 default:
3063 wpa_printf(MSG_DEBUG, "TLS: Unsupported "
3064 "cipher selection: %d", *c);
3065 return -1;
3066 }
3067 ret = os_snprintf(pos, end - pos, ":%s", suite);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003068 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003069 break;
3070 pos += ret;
3071
3072 c++;
3073 }
3074
3075 wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
3076
3077 if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) {
3078 tls_show_errors(MSG_INFO, __func__,
3079 "Cipher suite configuration failed");
3080 return -1;
3081 }
3082
3083 return 0;
3084}
3085
3086
3087int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn,
3088 char *buf, size_t buflen)
3089{
3090 const char *name;
3091 if (conn == NULL || conn->ssl == NULL)
3092 return -1;
3093
3094 name = SSL_get_cipher(conn->ssl);
3095 if (name == NULL)
3096 return -1;
3097
3098 os_strlcpy(buf, name, buflen);
3099 return 0;
3100}
3101
3102
3103int tls_connection_enable_workaround(void *ssl_ctx,
3104 struct tls_connection *conn)
3105{
3106 SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
3107
3108 return 0;
3109}
3110
3111
3112#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
3113/* ClientHello TLS extensions require a patch to openssl, so this function is
3114 * commented out unless explicitly needed for EAP-FAST in order to be able to
3115 * build this file with unmodified openssl. */
3116int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn,
3117 int ext_type, const u8 *data,
3118 size_t data_len)
3119{
3120 if (conn == NULL || conn->ssl == NULL || ext_type != 35)
3121 return -1;
3122
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003123 if (SSL_set_session_ticket_ext(conn->ssl, (void *) data,
3124 data_len) != 1)
3125 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003126
3127 return 0;
3128}
3129#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
3130
3131
3132int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn)
3133{
3134 if (conn == NULL)
3135 return -1;
3136 return conn->failed;
3137}
3138
3139
3140int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn)
3141{
3142 if (conn == NULL)
3143 return -1;
3144 return conn->read_alerts;
3145}
3146
3147
3148int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn)
3149{
3150 if (conn == NULL)
3151 return -1;
3152 return conn->write_alerts;
3153}
3154
3155
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003156#ifdef HAVE_OCSP
3157
3158static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp)
3159{
3160#ifndef CONFIG_NO_STDOUT_DEBUG
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003161 BIO *out;
3162 size_t rlen;
3163 char *txt;
3164 int res;
3165
3166 if (wpa_debug_level > MSG_DEBUG)
3167 return;
3168
3169 out = BIO_new(BIO_s_mem());
3170 if (!out)
3171 return;
3172
3173 OCSP_RESPONSE_print(out, rsp, 0);
3174 rlen = BIO_ctrl_pending(out);
3175 txt = os_malloc(rlen + 1);
3176 if (!txt) {
3177 BIO_free(out);
3178 return;
3179 }
3180
3181 res = BIO_read(out, txt, rlen);
3182 if (res > 0) {
3183 txt[res] = '\0';
3184 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt);
3185 }
3186 os_free(txt);
3187 BIO_free(out);
3188#endif /* CONFIG_NO_STDOUT_DEBUG */
3189}
3190
3191
Dmitry Shmidt71757432014-06-02 13:50:35 -07003192static void debug_print_cert(X509 *cert, const char *title)
3193{
3194#ifndef CONFIG_NO_STDOUT_DEBUG
3195 BIO *out;
3196 size_t rlen;
3197 char *txt;
3198 int res;
3199
3200 if (wpa_debug_level > MSG_DEBUG)
3201 return;
3202
3203 out = BIO_new(BIO_s_mem());
3204 if (!out)
3205 return;
3206
3207 X509_print(out, cert);
3208 rlen = BIO_ctrl_pending(out);
3209 txt = os_malloc(rlen + 1);
3210 if (!txt) {
3211 BIO_free(out);
3212 return;
3213 }
3214
3215 res = BIO_read(out, txt, rlen);
3216 if (res > 0) {
3217 txt[res] = '\0';
3218 wpa_printf(MSG_DEBUG, "OpenSSL: %s\n%s", title, txt);
3219 }
3220 os_free(txt);
3221
3222 BIO_free(out);
3223#endif /* CONFIG_NO_STDOUT_DEBUG */
3224}
3225
3226
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003227static int ocsp_resp_cb(SSL *s, void *arg)
3228{
3229 struct tls_connection *conn = arg;
3230 const unsigned char *p;
3231 int len, status, reason;
3232 OCSP_RESPONSE *rsp;
3233 OCSP_BASICRESP *basic;
3234 OCSP_CERTID *id;
3235 ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003236 X509_STORE *store;
3237 STACK_OF(X509) *certs = NULL;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003238
3239 len = SSL_get_tlsext_status_ocsp_resp(s, &p);
3240 if (!p) {
3241 wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
3242 return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
3243 }
3244
3245 wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len);
3246
3247 rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
3248 if (!rsp) {
3249 wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response");
3250 return 0;
3251 }
3252
3253 ocsp_debug_print_resp(rsp);
3254
3255 status = OCSP_response_status(rsp);
3256 if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
3257 wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)",
3258 status, OCSP_response_status_str(status));
3259 return 0;
3260 }
3261
3262 basic = OCSP_response_get1_basic(rsp);
3263 if (!basic) {
3264 wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse");
3265 return 0;
3266 }
3267
Dmitry Shmidt216983b2015-02-06 10:50:36 -08003268 store = SSL_CTX_get_cert_store(conn->ssl_ctx);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003269 if (conn->peer_issuer) {
Dmitry Shmidt71757432014-06-02 13:50:35 -07003270 debug_print_cert(conn->peer_issuer, "Add OCSP issuer");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003271
3272 if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) {
3273 tls_show_errors(MSG_INFO, __func__,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003274 "OpenSSL: Could not add issuer to certificate store");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003275 }
3276 certs = sk_X509_new_null();
3277 if (certs) {
3278 X509 *cert;
3279 cert = X509_dup(conn->peer_issuer);
3280 if (cert && !sk_X509_push(certs, cert)) {
3281 tls_show_errors(
3282 MSG_INFO, __func__,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003283 "OpenSSL: Could not add issuer to OCSP responder trust store");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003284 X509_free(cert);
3285 sk_X509_free(certs);
3286 certs = NULL;
3287 }
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003288 if (certs && conn->peer_issuer_issuer) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003289 cert = X509_dup(conn->peer_issuer_issuer);
3290 if (cert && !sk_X509_push(certs, cert)) {
3291 tls_show_errors(
3292 MSG_INFO, __func__,
Dmitry Shmidt7f656022015-02-25 14:36:37 -08003293 "OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003294 X509_free(cert);
3295 }
3296 }
3297 }
3298 }
3299
3300 status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER);
3301 sk_X509_pop_free(certs, X509_free);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003302 if (status <= 0) {
3303 tls_show_errors(MSG_INFO, __func__,
3304 "OpenSSL: OCSP response failed verification");
3305 OCSP_BASICRESP_free(basic);
3306 OCSP_RESPONSE_free(rsp);
3307 return 0;
3308 }
3309
3310 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded");
3311
Dmitry Shmidt56052862013-10-04 10:23:25 -07003312 if (!conn->peer_cert) {
3313 wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check");
3314 OCSP_BASICRESP_free(basic);
3315 OCSP_RESPONSE_free(rsp);
3316 return 0;
3317 }
3318
3319 if (!conn->peer_issuer) {
3320 wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check");
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003321 OCSP_BASICRESP_free(basic);
3322 OCSP_RESPONSE_free(rsp);
3323 return 0;
3324 }
3325
3326 id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer);
3327 if (!id) {
3328 wpa_printf(MSG_DEBUG, "OpenSSL: Could not create OCSP certificate identifier");
3329 OCSP_BASICRESP_free(basic);
3330 OCSP_RESPONSE_free(rsp);
3331 return 0;
3332 }
3333
3334 if (!OCSP_resp_find_status(basic, id, &status, &reason, &produced_at,
3335 &this_update, &next_update)) {
3336 wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s",
3337 (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" :
3338 " (OCSP not required)");
3339 OCSP_BASICRESP_free(basic);
3340 OCSP_RESPONSE_free(rsp);
3341 return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1;
3342 }
3343
3344 if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) {
3345 tls_show_errors(MSG_INFO, __func__,
3346 "OpenSSL: OCSP status times invalid");
3347 OCSP_BASICRESP_free(basic);
3348 OCSP_RESPONSE_free(rsp);
3349 return 0;
3350 }
3351
3352 OCSP_BASICRESP_free(basic);
3353 OCSP_RESPONSE_free(rsp);
3354
3355 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s",
3356 OCSP_cert_status_str(status));
3357
3358 if (status == V_OCSP_CERTSTATUS_GOOD)
3359 return 1;
3360 if (status == V_OCSP_CERTSTATUS_REVOKED)
3361 return 0;
3362 if (conn->flags & TLS_CONN_REQUIRE_OCSP) {
3363 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required");
3364 return 0;
3365 }
Dmitry Shmidt051af732013-10-22 13:52:46 -07003366 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 -07003367 return 1;
3368}
3369
3370
3371static int ocsp_status_cb(SSL *s, void *arg)
3372{
3373 char *tmp;
3374 char *resp;
3375 size_t len;
3376
3377 if (tls_global->ocsp_stapling_response == NULL) {
3378 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured");
3379 return SSL_TLSEXT_ERR_OK;
3380 }
3381
3382 resp = os_readfile(tls_global->ocsp_stapling_response, &len);
3383 if (resp == NULL) {
3384 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file");
3385 /* TODO: Build OCSPResponse with responseStatus = internalError
3386 */
3387 return SSL_TLSEXT_ERR_OK;
3388 }
3389 wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response");
3390 tmp = OPENSSL_malloc(len);
3391 if (tmp == NULL) {
3392 os_free(resp);
3393 return SSL_TLSEXT_ERR_ALERT_FATAL;
3394 }
3395
3396 os_memcpy(tmp, resp, len);
3397 os_free(resp);
3398 SSL_set_tlsext_status_ocsp_resp(s, tmp, len);
3399
3400 return SSL_TLSEXT_ERR_OK;
3401}
3402
3403#endif /* HAVE_OCSP */
3404
3405
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003406int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
3407 const struct tls_connection_params *params)
3408{
3409 int ret;
3410 unsigned long err;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003411 int can_pkcs11 = 0;
3412 const char *key_id = params->key_id;
3413 const char *cert_id = params->cert_id;
3414 const char *ca_cert_id = params->ca_cert_id;
3415 const char *engine_id = params->engine ? params->engine_id : NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003416
3417 if (conn == NULL)
3418 return -1;
3419
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003420 /*
3421 * If the engine isn't explicitly configured, and any of the
3422 * cert/key fields are actually PKCS#11 URIs, then automatically
3423 * use the PKCS#11 ENGINE.
3424 */
3425 if (!engine_id || os_strcmp(engine_id, "pkcs11") == 0)
3426 can_pkcs11 = 1;
3427
3428 if (!key_id && params->private_key && can_pkcs11 &&
3429 os_strncmp(params->private_key, "pkcs11:", 7) == 0) {
3430 can_pkcs11 = 2;
3431 key_id = params->private_key;
3432 }
3433
3434 if (!cert_id && params->client_cert && can_pkcs11 &&
3435 os_strncmp(params->client_cert, "pkcs11:", 7) == 0) {
3436 can_pkcs11 = 2;
3437 cert_id = params->client_cert;
3438 }
3439
3440 if (!ca_cert_id && params->ca_cert && can_pkcs11 &&
3441 os_strncmp(params->ca_cert, "pkcs11:", 7) == 0) {
3442 can_pkcs11 = 2;
3443 ca_cert_id = params->ca_cert;
3444 }
3445
3446 /* If we need to automatically enable the PKCS#11 ENGINE, do so. */
3447 if (can_pkcs11 == 2 && !engine_id)
3448 engine_id = "pkcs11";
3449
3450 if (params->flags & TLS_CONN_EAP_FAST) {
3451 wpa_printf(MSG_DEBUG,
3452 "OpenSSL: Use TLSv1_method() for EAP-FAST");
3453 if (SSL_set_ssl_method(conn->ssl, TLSv1_method()) != 1) {
3454 tls_show_errors(MSG_INFO, __func__,
3455 "Failed to set TLSv1_method() for EAP-FAST");
3456 return -1;
3457 }
3458 }
3459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003460 while ((err = ERR_get_error())) {
3461 wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
3462 __func__, ERR_error_string(err, NULL));
3463 }
3464
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003465 if (engine_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466 wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003467 ret = tls_engine_init(conn, engine_id, params->pin,
3468 key_id, cert_id, ca_cert_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003469 if (ret)
3470 return ret;
3471 }
3472 if (tls_connection_set_subject_match(conn,
3473 params->subject_match,
Dmitry Shmidt051af732013-10-22 13:52:46 -07003474 params->altsubject_match,
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003475 params->suffix_match,
3476 params->domain_match))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 return -1;
3478
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003479 if (engine_id && ca_cert_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003480 if (tls_connection_engine_ca_cert(tls_ctx, conn,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003481 ca_cert_id))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003482 return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
3483 } else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert,
3484 params->ca_cert_blob,
3485 params->ca_cert_blob_len,
3486 params->ca_path))
3487 return -1;
3488
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003489 if (engine_id && cert_id) {
3490 if (tls_connection_engine_client_cert(conn, cert_id))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003491 return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
3492 } else if (tls_connection_client_cert(conn, params->client_cert,
3493 params->client_cert_blob,
3494 params->client_cert_blob_len))
3495 return -1;
3496
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003497 if (engine_id && key_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003498 wpa_printf(MSG_DEBUG, "TLS: Using private key from engine");
3499 if (tls_connection_engine_private_key(conn))
3500 return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED;
3501 } else if (tls_connection_private_key(tls_ctx, conn,
3502 params->private_key,
3503 params->private_key_passwd,
3504 params->private_key_blob,
3505 params->private_key_blob_len)) {
3506 wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'",
3507 params->private_key);
3508 return -1;
3509 }
3510
3511 if (tls_connection_dh(conn, params->dh_file)) {
3512 wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
3513 params->dh_file);
3514 return -1;
3515 }
3516
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003517 if (params->openssl_ciphers &&
3518 SSL_set_cipher_list(conn->ssl, params->openssl_ciphers) != 1) {
3519 wpa_printf(MSG_INFO,
3520 "OpenSSL: Failed to set cipher string '%s'",
3521 params->openssl_ciphers);
3522 return -1;
3523 }
3524
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003525#ifdef SSL_OP_NO_TICKET
3526 if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
3527 SSL_set_options(conn->ssl, SSL_OP_NO_TICKET);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003528#ifdef SSL_clear_options
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003529 else
3530 SSL_clear_options(conn->ssl, SSL_OP_NO_TICKET);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003531#endif /* SSL_clear_options */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003532#endif /* SSL_OP_NO_TICKET */
3533
Dmitry Shmidt13ca8d82014-02-20 10:18:40 -08003534#ifdef SSL_OP_NO_TLSv1_1
3535 if (params->flags & TLS_CONN_DISABLE_TLSv1_1)
3536 SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_1);
3537 else
3538 SSL_clear_options(conn->ssl, SSL_OP_NO_TLSv1_1);
3539#endif /* SSL_OP_NO_TLSv1_1 */
3540#ifdef SSL_OP_NO_TLSv1_2
3541 if (params->flags & TLS_CONN_DISABLE_TLSv1_2)
3542 SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_2);
3543 else
3544 SSL_clear_options(conn->ssl, SSL_OP_NO_TLSv1_2);
3545#endif /* SSL_OP_NO_TLSv1_2 */
3546
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003547#ifdef HAVE_OCSP
3548 if (params->flags & TLS_CONN_REQUEST_OCSP) {
Dmitry Shmidtfa3fc4a2013-11-21 13:34:38 -08003549 SSL_CTX *ssl_ctx = tls_ctx;
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003550 SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp);
3551 SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb);
3552 SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn);
3553 }
3554#endif /* HAVE_OCSP */
3555
Dmitry Shmidtc55524a2011-07-07 11:18:38 -07003556 conn->flags = params->flags;
3557
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003558 tls_get_errors(tls_ctx);
3559
3560 return 0;
3561}
3562
3563
3564int tls_global_set_params(void *tls_ctx,
3565 const struct tls_connection_params *params)
3566{
3567 SSL_CTX *ssl_ctx = tls_ctx;
3568 unsigned long err;
3569
3570 while ((err = ERR_get_error())) {
3571 wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s",
3572 __func__, ERR_error_string(err, NULL));
3573 }
3574
3575 if (tls_global_ca_cert(ssl_ctx, params->ca_cert))
3576 return -1;
3577
3578 if (tls_global_client_cert(ssl_ctx, params->client_cert))
3579 return -1;
3580
3581 if (tls_global_private_key(ssl_ctx, params->private_key,
3582 params->private_key_passwd))
3583 return -1;
3584
3585 if (tls_global_dh(ssl_ctx, params->dh_file)) {
3586 wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'",
3587 params->dh_file);
3588 return -1;
3589 }
3590
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003591 if (params->openssl_ciphers &&
3592 SSL_CTX_set_cipher_list(ssl_ctx, params->openssl_ciphers) != 1) {
3593 wpa_printf(MSG_INFO,
3594 "OpenSSL: Failed to set cipher string '%s'",
3595 params->openssl_ciphers);
3596 return -1;
3597 }
3598
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003599#ifdef SSL_OP_NO_TICKET
3600 if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET)
3601 SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003602#ifdef SSL_CTX_clear_options
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003603 else
3604 SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET);
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003605#endif /* SSL_clear_options */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003606#endif /* SSL_OP_NO_TICKET */
3607
Dmitry Shmidt34af3062013-07-11 10:46:32 -07003608#ifdef HAVE_OCSP
3609 SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb);
3610 SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx);
3611 os_free(tls_global->ocsp_stapling_response);
3612 if (params->ocsp_stapling_response)
3613 tls_global->ocsp_stapling_response =
3614 os_strdup(params->ocsp_stapling_response);
3615 else
3616 tls_global->ocsp_stapling_response = NULL;
3617#endif /* HAVE_OCSP */
3618
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003619 return 0;
3620}
3621
3622
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003623unsigned int tls_capabilities(void *tls_ctx)
3624{
3625 return 0;
3626}
3627
3628
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
3630/* Pre-shared secred requires a patch to openssl, so this function is
3631 * commented out unless explicitly needed for EAP-FAST in order to be able to
3632 * build this file with unmodified openssl. */
3633
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003634#ifdef OPENSSL_IS_BORINGSSL
3635static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
3636 STACK_OF(SSL_CIPHER) *peer_ciphers,
3637 const SSL_CIPHER **cipher, void *arg)
3638#else /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003639static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len,
3640 STACK_OF(SSL_CIPHER) *peer_ciphers,
3641 SSL_CIPHER **cipher, void *arg)
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07003642#endif /* OPENSSL_IS_BORINGSSL */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003643{
3644 struct tls_connection *conn = arg;
3645 int ret;
3646
3647 if (conn == NULL || conn->session_ticket_cb == NULL)
3648 return 0;
3649
3650 ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx,
3651 conn->session_ticket,
3652 conn->session_ticket_len,
3653 s->s3->client_random,
3654 s->s3->server_random, secret);
3655 os_free(conn->session_ticket);
3656 conn->session_ticket = NULL;
3657
3658 if (ret <= 0)
3659 return 0;
3660
3661 *secret_len = SSL_MAX_MASTER_KEY_LENGTH;
3662 return 1;
3663}
3664
3665
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data,
3667 int len, void *arg)
3668{
3669 struct tls_connection *conn = arg;
3670
3671 if (conn == NULL || conn->session_ticket_cb == NULL)
3672 return 0;
3673
3674 wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len);
3675
3676 os_free(conn->session_ticket);
3677 conn->session_ticket = NULL;
3678
3679 wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket "
3680 "extension", data, len);
3681
3682 conn->session_ticket = os_malloc(len);
3683 if (conn->session_ticket == NULL)
3684 return 0;
3685
3686 os_memcpy(conn->session_ticket, data, len);
3687 conn->session_ticket_len = len;
3688
3689 return 1;
3690}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003691#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
3692
3693
3694int tls_connection_set_session_ticket_cb(void *tls_ctx,
3695 struct tls_connection *conn,
3696 tls_session_ticket_cb cb,
3697 void *ctx)
3698{
3699#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
3700 conn->session_ticket_cb = cb;
3701 conn->session_ticket_cb_ctx = ctx;
3702
3703 if (cb) {
3704 if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb,
3705 conn) != 1)
3706 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003707 SSL_set_session_ticket_ext_cb(conn->ssl,
3708 tls_session_ticket_ext_cb, conn);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003709 } else {
3710 if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1)
3711 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003712 SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003713 }
3714
3715 return 0;
3716#else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
3717 return -1;
3718#endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */
3719}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08003720
3721
3722int tls_get_library_version(char *buf, size_t buf_len)
3723{
3724 return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s",
3725 OPENSSL_VERSION_TEXT,
3726 SSLeay_version(SSLEAY_VERSION));
3727}