2008-02-28 02:34:43 +01:00
|
|
|
/*
|
2009-12-20 17:17:55 +01:00
|
|
|
* TLS interface functions and an internal TLS implementation
|
2011-07-05 10:29:42 +02:00
|
|
|
* Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
|
2008-02-28 02:34:43 +01:00
|
|
|
*
|
2012-02-11 15:46:35 +01:00
|
|
|
* This software may be distributed under the terms of the BSD license.
|
|
|
|
* See README for more details.
|
2008-02-28 02:34:43 +01:00
|
|
|
*
|
|
|
|
* This file interface functions for hostapd/wpa_supplicant to use the
|
|
|
|
* integrated TLSv1 implementation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "includes.h"
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "tls.h"
|
|
|
|
#include "tls/tlsv1_client.h"
|
|
|
|
#include "tls/tlsv1_server.h"
|
|
|
|
|
|
|
|
|
|
|
|
static int tls_ref_count = 0;
|
|
|
|
|
|
|
|
struct tls_global {
|
|
|
|
int server;
|
|
|
|
struct tlsv1_credentials *server_cred;
|
|
|
|
int check_crl;
|
2015-11-29 17:59:27 +01:00
|
|
|
|
|
|
|
void (*event_cb)(void *ctx, enum tls_event ev,
|
|
|
|
union tls_event_data *data);
|
|
|
|
void *cb_ctx;
|
|
|
|
int cert_in_cb;
|
2008-02-28 02:34:43 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct tls_connection {
|
|
|
|
struct tlsv1_client *client;
|
|
|
|
struct tlsv1_server *server;
|
2014-03-01 23:07:50 +01:00
|
|
|
struct tls_global *global;
|
2008-02-28 02:34:43 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void * tls_init(const struct tls_config *conf)
|
|
|
|
{
|
|
|
|
struct tls_global *global;
|
|
|
|
|
|
|
|
if (tls_ref_count == 0) {
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (tlsv1_client_global_init())
|
|
|
|
return NULL;
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (tlsv1_server_global_init())
|
|
|
|
return NULL;
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
}
|
|
|
|
tls_ref_count++;
|
|
|
|
|
|
|
|
global = os_zalloc(sizeof(*global));
|
|
|
|
if (global == NULL)
|
|
|
|
return NULL;
|
2015-11-29 17:59:27 +01:00
|
|
|
if (conf) {
|
|
|
|
global->event_cb = conf->event_cb;
|
|
|
|
global->cb_ctx = conf->cb_ctx;
|
|
|
|
global->cert_in_cb = conf->cert_in_cb;
|
|
|
|
}
|
2008-02-28 02:34:43 +01:00
|
|
|
|
|
|
|
return global;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tls_deinit(void *ssl_ctx)
|
|
|
|
{
|
|
|
|
struct tls_global *global = ssl_ctx;
|
|
|
|
tls_ref_count--;
|
|
|
|
if (tls_ref_count == 0) {
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
tlsv1_client_global_deinit();
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
tlsv1_server_global_deinit();
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
}
|
2015-10-31 17:15:22 +01:00
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
tlsv1_cred_free(global->server_cred);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
2008-02-28 02:34:43 +01:00
|
|
|
os_free(global);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_get_errors(void *tls_ctx)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct tls_connection * tls_connection_init(void *tls_ctx)
|
|
|
|
{
|
|
|
|
struct tls_connection *conn;
|
|
|
|
struct tls_global *global = tls_ctx;
|
|
|
|
|
|
|
|
conn = os_zalloc(sizeof(*conn));
|
|
|
|
if (conn == NULL)
|
|
|
|
return NULL;
|
2014-03-01 23:07:50 +01:00
|
|
|
conn->global = global;
|
2008-02-28 02:34:43 +01:00
|
|
|
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (!global->server) {
|
|
|
|
conn->client = tlsv1_client_init();
|
|
|
|
if (conn->client == NULL) {
|
|
|
|
os_free(conn);
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-11-29 17:59:27 +01:00
|
|
|
tlsv1_client_set_cb(conn->client, global->event_cb,
|
|
|
|
global->cb_ctx, global->cert_in_cb);
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (global->server) {
|
|
|
|
conn->server = tlsv1_server_init(global->server_cred);
|
|
|
|
if (conn->server == NULL) {
|
|
|
|
os_free(conn);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
|
|
|
|
return conn;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-03-01 23:43:59 +01:00
|
|
|
#ifdef CONFIG_TESTING_OPTIONS
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
void tls_connection_set_test_flags(struct tls_connection *conn, u32 flags)
|
|
|
|
{
|
|
|
|
if (conn->server)
|
|
|
|
tlsv1_server_set_test_flags(conn->server, flags);
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
#endif /* CONFIG_TESTING_OPTIONS */
|
|
|
|
|
|
|
|
|
2014-03-01 23:07:50 +01:00
|
|
|
void tls_connection_set_log_cb(struct tls_connection *conn,
|
|
|
|
void (*log_cb)(void *ctx, const char *msg),
|
|
|
|
void *ctx)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
tlsv1_server_set_log_cb(conn->server, log_cb, ctx);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
if (conn == NULL)
|
|
|
|
return;
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
|
|
|
tlsv1_client_deinit(conn->client);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
tlsv1_server_deinit(conn->server);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
os_free(conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
|
|
|
return tlsv1_client_established(conn->client);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
return tlsv1_server_established(conn->server);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
|
|
|
return tlsv1_client_shutdown(conn->client);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
return tlsv1_server_shutdown(conn->server);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
|
|
|
const struct tls_connection_params *params)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
struct tlsv1_credentials *cred;
|
|
|
|
|
|
|
|
if (conn->client == NULL)
|
|
|
|
return -1;
|
|
|
|
|
EAP peer: External server certificate chain validation
This adds support for optional functionality to validate server
certificate chain in TLS-based EAP methods in an external program.
wpa_supplicant control interface is used to indicate when such
validation is needed and what the result of the external validation is.
This external validation can extend or replace the internal validation.
When ca_cert or ca_path parameter is set, the internal validation is
used. If these parameters are omitted, only the external validation is
used. It needs to be understood that leaving those parameters out will
disable most of the validation steps done with the TLS library and that
configuration is not really recommend.
By default, the external validation is not used. It can be enabled by
addingtls_ext_cert_check=1 into the network profile phase1 parameter.
When enabled, external validation is required through the CTRL-REQ/RSP
mechanism similarly to other EAP authentication parameters through the
control interface.
The request to perform external validation is indicated by the following
event:
CTRL-REQ-EXT_CERT_CHECK-<id>:External server certificate validation needed for SSID <ssid>
Before that event, the server certificate chain is provided with the
CTRL-EVENT-EAP-PEER-CERT events that include the cert=<hexdump>
parameter. depth=# indicates which certificate is in question (0 for the
server certificate, 1 for its issues, and so on).
The result of the external validation is provided with the following
command:
CTRL-RSP-EXT_CERT_CHECK-<id>:<good|bad>
It should be noted that this is currently enabled only for OpenSSL (and
BoringSSL/LibreSSL). Due to the constraints in the library API, the
validation result from external processing cannot be reported cleanly
with TLS alert. In other words, if the external validation reject the
server certificate chain, the pending TLS handshake is terminated
without sending more messages to the server.
Signed-off-by: Jouni Malinen <j@w1.fi>
2015-12-12 17:16:54 +01:00
|
|
|
if (params->flags & TLS_CONN_EXT_CERT_CHECK) {
|
|
|
|
wpa_printf(MSG_INFO,
|
|
|
|
"TLS: tls_ext_cert_check=1 not supported");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
cred = tlsv1_cred_alloc();
|
|
|
|
if (cred == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2015-01-10 23:37:21 +01:00
|
|
|
if (params->subject_match) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: subject_match not supported");
|
2015-03-31 15:17:48 +02:00
|
|
|
tlsv1_cred_free(cred);
|
2015-01-10 23:37:21 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (params->altsubject_match) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: altsubject_match not supported");
|
2015-03-31 15:17:48 +02:00
|
|
|
tlsv1_cred_free(cred);
|
2015-01-10 23:37:21 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (params->suffix_match) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: suffix_match not supported");
|
2015-03-31 15:17:48 +02:00
|
|
|
tlsv1_cred_free(cred);
|
2015-01-10 23:37:21 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-01-14 14:31:28 +01:00
|
|
|
if (params->domain_match) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: domain_match not supported");
|
2015-03-31 15:17:48 +02:00
|
|
|
tlsv1_cred_free(cred);
|
2015-01-14 14:31:28 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-01-11 00:35:54 +01:00
|
|
|
if (params->openssl_ciphers) {
|
2015-03-31 15:17:48 +02:00
|
|
|
wpa_printf(MSG_INFO, "TLS: openssl_ciphers not supported");
|
|
|
|
tlsv1_cred_free(cred);
|
2015-01-11 00:35:54 +01:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
if (tlsv1_set_ca_cert(cred, params->ca_cert,
|
|
|
|
params->ca_cert_blob, params->ca_cert_blob_len,
|
|
|
|
params->ca_path)) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
|
|
|
|
"certificates");
|
|
|
|
tlsv1_cred_free(cred);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsv1_set_cert(cred, params->client_cert,
|
|
|
|
params->client_cert_blob,
|
|
|
|
params->client_cert_blob_len)) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: Failed to configure client "
|
|
|
|
"certificate");
|
|
|
|
tlsv1_cred_free(cred);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsv1_set_private_key(cred, params->private_key,
|
|
|
|
params->private_key_passwd,
|
|
|
|
params->private_key_blob,
|
|
|
|
params->private_key_blob_len)) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: Failed to load private key");
|
|
|
|
tlsv1_cred_free(cred);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
|
|
|
|
params->dh_blob_len)) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
|
|
|
|
tlsv1_cred_free(cred);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsv1_client_set_cred(conn->client, cred) < 0) {
|
|
|
|
tlsv1_cred_free(cred);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-11-29 18:48:17 +01:00
|
|
|
tlsv1_client_set_flags(conn->client, params->flags);
|
2011-07-05 10:29:42 +02:00
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
return 0;
|
|
|
|
#else /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
return -1;
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_global_set_params(void *tls_ctx,
|
|
|
|
const struct tls_connection_params *params)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
struct tls_global *global = tls_ctx;
|
|
|
|
struct tlsv1_credentials *cred;
|
|
|
|
|
|
|
|
/* Currently, global parameters are only set when running in server
|
|
|
|
* mode. */
|
|
|
|
global->server = 1;
|
|
|
|
tlsv1_cred_free(global->server_cred);
|
|
|
|
global->server_cred = cred = tlsv1_cred_alloc();
|
|
|
|
if (cred == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob,
|
|
|
|
params->ca_cert_blob_len, params->ca_path)) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA "
|
|
|
|
"certificates");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob,
|
|
|
|
params->client_cert_blob_len)) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: Failed to configure server "
|
|
|
|
"certificate");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsv1_set_private_key(cred, params->private_key,
|
|
|
|
params->private_key_passwd,
|
|
|
|
params->private_key_blob,
|
|
|
|
params->private_key_blob_len)) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: Failed to load private key");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob,
|
|
|
|
params->dh_blob_len)) {
|
|
|
|
wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
#else /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_global_set_verify(void *tls_ctx, int check_crl)
|
|
|
|
{
|
|
|
|
struct tls_global *global = tls_ctx;
|
|
|
|
global->check_crl = check_crl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
2015-08-23 20:11:01 +02:00
|
|
|
int verify_peer, unsigned int flags,
|
|
|
|
const u8 *session_ctx, size_t session_ctx_len)
|
2008-02-28 02:34:43 +01:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
return tlsv1_server_set_verify(conn->server, verify_peer);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-01 17:17:14 +02:00
|
|
|
int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn,
|
|
|
|
struct tls_random *data)
|
2008-02-28 02:34:43 +01:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
2015-08-01 17:17:14 +02:00
|
|
|
return tlsv1_client_get_random(conn->client, data);
|
2008-02-28 02:34:43 +01:00
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
2015-08-01 17:17:14 +02:00
|
|
|
return tlsv1_server_get_random(conn->server, data);
|
2008-02-28 02:34:43 +01:00
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-31 15:15:39 +02:00
|
|
|
static int tls_get_keyblock_size(struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
|
|
|
return tlsv1_client_get_keyblock_size(conn->client);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
return tlsv1_server_get_keyblock_size(conn->server);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
|
|
|
|
const char *label, int server_random_first,
|
2015-03-31 15:15:39 +02:00
|
|
|
int skip_keyblock, u8 *out, size_t out_len)
|
|
|
|
{
|
|
|
|
int ret = -1, skip = 0;
|
|
|
|
u8 *tmp_out = NULL;
|
|
|
|
u8 *_out = out;
|
|
|
|
|
|
|
|
if (skip_keyblock) {
|
|
|
|
skip = tls_get_keyblock_size(conn);
|
|
|
|
if (skip < 0)
|
|
|
|
return -1;
|
|
|
|
tmp_out = os_malloc(skip + out_len);
|
|
|
|
if (!tmp_out)
|
|
|
|
return -1;
|
|
|
|
_out = tmp_out;
|
|
|
|
}
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client) {
|
2015-03-31 15:15:39 +02:00
|
|
|
ret = tlsv1_client_prf(conn->client, label,
|
|
|
|
server_random_first,
|
2015-11-29 22:40:54 +01:00
|
|
|
_out, skip + out_len);
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server) {
|
2015-03-31 15:15:39 +02:00
|
|
|
ret = tlsv1_server_prf(conn->server, label,
|
|
|
|
server_random_first,
|
2015-11-29 22:40:54 +01:00
|
|
|
_out, skip + out_len);
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
2015-03-31 15:15:39 +02:00
|
|
|
if (ret == 0 && skip_keyblock)
|
|
|
|
os_memcpy(out, _out + skip, out_len);
|
|
|
|
bin_clear_free(tmp_out, skip);
|
|
|
|
|
|
|
|
return ret;
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 17:17:55 +01:00
|
|
|
struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
|
|
|
struct tls_connection *conn,
|
|
|
|
const struct wpabuf *in_data,
|
|
|
|
struct wpabuf **appl_data)
|
2011-11-13 09:47:04 +01:00
|
|
|
{
|
|
|
|
return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct wpabuf * tls_connection_handshake2(void *tls_ctx,
|
|
|
|
struct tls_connection *conn,
|
|
|
|
const struct wpabuf *in_data,
|
|
|
|
struct wpabuf **appl_data,
|
|
|
|
int *need_more_data)
|
2008-02-28 02:34:43 +01:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
2009-12-20 17:17:55 +01:00
|
|
|
u8 *res, *ad;
|
|
|
|
size_t res_len, ad_len;
|
|
|
|
struct wpabuf *out;
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
if (conn->client == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2009-12-20 17:17:55 +01:00
|
|
|
ad = NULL;
|
|
|
|
res = tlsv1_client_handshake(conn->client,
|
|
|
|
in_data ? wpabuf_head(in_data) : NULL,
|
|
|
|
in_data ? wpabuf_len(in_data) : 0,
|
2011-11-13 09:47:04 +01:00
|
|
|
&res_len, &ad, &ad_len, need_more_data);
|
2009-12-20 17:17:55 +01:00
|
|
|
if (res == NULL)
|
|
|
|
return NULL;
|
|
|
|
out = wpabuf_alloc_ext_data(res, res_len);
|
|
|
|
if (out == NULL) {
|
|
|
|
os_free(res);
|
|
|
|
os_free(ad);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (appl_data) {
|
|
|
|
if (ad) {
|
|
|
|
*appl_data = wpabuf_alloc_ext_data(ad, ad_len);
|
|
|
|
if (*appl_data == NULL)
|
|
|
|
os_free(ad);
|
|
|
|
} else
|
|
|
|
*appl_data = NULL;
|
|
|
|
} else
|
|
|
|
os_free(ad);
|
2008-02-28 02:34:43 +01:00
|
|
|
|
2009-12-20 17:17:55 +01:00
|
|
|
return out;
|
2008-02-28 02:34:43 +01:00
|
|
|
#else /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
return NULL;
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 17:17:55 +01:00
|
|
|
struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
|
|
|
struct tls_connection *conn,
|
|
|
|
const struct wpabuf *in_data,
|
|
|
|
struct wpabuf **appl_data)
|
2008-02-28 02:34:43 +01:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
2009-12-20 17:17:55 +01:00
|
|
|
u8 *res;
|
|
|
|
size_t res_len;
|
|
|
|
struct wpabuf *out;
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
if (conn->server == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2009-12-20 17:17:55 +01:00
|
|
|
if (appl_data)
|
|
|
|
*appl_data = NULL;
|
|
|
|
|
|
|
|
res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data),
|
|
|
|
wpabuf_len(in_data), &res_len);
|
|
|
|
if (res == NULL && tlsv1_server_established(conn->server))
|
|
|
|
return wpabuf_alloc(0);
|
|
|
|
if (res == NULL)
|
|
|
|
return NULL;
|
|
|
|
out = wpabuf_alloc_ext_data(res, res_len);
|
|
|
|
if (out == NULL) {
|
|
|
|
os_free(res);
|
|
|
|
return NULL;
|
2008-08-24 12:08:15 +02:00
|
|
|
}
|
2009-12-20 17:17:55 +01:00
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
return out;
|
|
|
|
#else /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return NULL;
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 17:17:55 +01:00
|
|
|
struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
|
|
|
struct tls_connection *conn,
|
|
|
|
const struct wpabuf *in_data)
|
2008-02-28 02:34:43 +01:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client) {
|
2009-12-20 17:17:55 +01:00
|
|
|
struct wpabuf *buf;
|
|
|
|
int res;
|
|
|
|
buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
|
|
|
|
if (buf == NULL)
|
|
|
|
return NULL;
|
|
|
|
res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data),
|
|
|
|
wpabuf_len(in_data),
|
|
|
|
wpabuf_mhead(buf),
|
|
|
|
wpabuf_size(buf));
|
|
|
|
if (res < 0) {
|
|
|
|
wpabuf_free(buf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
wpabuf_put(buf, res);
|
|
|
|
return buf;
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server) {
|
2009-12-20 17:17:55 +01:00
|
|
|
struct wpabuf *buf;
|
|
|
|
int res;
|
|
|
|
buf = wpabuf_alloc(wpabuf_len(in_data) + 300);
|
|
|
|
if (buf == NULL)
|
|
|
|
return NULL;
|
|
|
|
res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data),
|
|
|
|
wpabuf_len(in_data),
|
|
|
|
wpabuf_mhead(buf),
|
|
|
|
wpabuf_size(buf));
|
|
|
|
if (res < 0) {
|
|
|
|
wpabuf_free(buf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
wpabuf_put(buf, res);
|
|
|
|
return buf;
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
2009-12-20 17:17:55 +01:00
|
|
|
return NULL;
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-12-20 17:17:55 +01:00
|
|
|
struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
|
|
|
struct tls_connection *conn,
|
|
|
|
const struct wpabuf *in_data)
|
2008-02-28 02:34:43 +01:00
|
|
|
{
|
2011-11-13 09:47:04 +01:00
|
|
|
return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct wpabuf * tls_connection_decrypt2(void *tls_ctx,
|
|
|
|
struct tls_connection *conn,
|
|
|
|
const struct wpabuf *in_data,
|
|
|
|
int *need_more_data)
|
|
|
|
{
|
|
|
|
if (need_more_data)
|
|
|
|
*need_more_data = 0;
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client) {
|
2011-11-13 09:47:04 +01:00
|
|
|
return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data),
|
|
|
|
wpabuf_len(in_data),
|
|
|
|
need_more_data);
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server) {
|
2009-12-20 17:17:55 +01:00
|
|
|
struct wpabuf *buf;
|
|
|
|
int res;
|
|
|
|
buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
|
|
|
|
if (buf == NULL)
|
|
|
|
return NULL;
|
|
|
|
res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data),
|
|
|
|
wpabuf_len(in_data),
|
|
|
|
wpabuf_mhead(buf),
|
|
|
|
wpabuf_size(buf));
|
|
|
|
if (res < 0) {
|
|
|
|
wpabuf_free(buf);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
wpabuf_put(buf, res);
|
|
|
|
return buf;
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
2009-12-20 17:17:55 +01:00
|
|
|
return NULL;
|
2008-02-28 02:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
|
|
|
return tlsv1_client_resumed(conn->client);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
return tlsv1_server_resumed(conn->server);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
|
|
|
u8 *ciphers)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
|
|
|
return tlsv1_client_set_cipher_list(conn->client, ciphers);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
return tlsv1_server_set_cipher_list(conn->server, ciphers);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-08 18:51:03 +02:00
|
|
|
int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
|
|
|
|
char *buf, size_t buflen)
|
|
|
|
{
|
2015-11-29 18:41:37 +01:00
|
|
|
if (conn == NULL)
|
|
|
|
return -1;
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
|
|
|
return tlsv1_client_get_version(conn->client, buf, buflen);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
2015-07-08 18:51:03 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-28 02:34:43 +01:00
|
|
|
int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
|
|
|
|
char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
if (conn == NULL)
|
|
|
|
return -1;
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client)
|
|
|
|
return tlsv1_client_get_cipher(conn->client, buf, buflen);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server)
|
|
|
|
return tlsv1_server_get_cipher(conn->server, buf, buflen);
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_enable_workaround(void *tls_ctx,
|
|
|
|
struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
|
|
|
|
int ext_type, const u8 *data,
|
|
|
|
size_t data_len)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client) {
|
|
|
|
return tlsv1_client_hello_ext(conn->client, ext_type,
|
|
|
|
data, data_len);
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_get_write_alerts(void *tls_ctx,
|
|
|
|
struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int tls_connection_set_session_ticket_cb(void *tls_ctx,
|
|
|
|
struct tls_connection *conn,
|
|
|
|
tls_session_ticket_cb cb,
|
|
|
|
void *ctx)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_CLIENT
|
|
|
|
if (conn->client) {
|
|
|
|
tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_CLIENT */
|
|
|
|
#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
|
|
if (conn->server) {
|
|
|
|
tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_TLS_INTERNAL_SERVER */
|
|
|
|
return -1;
|
|
|
|
}
|
2015-01-11 14:37:38 +01:00
|
|
|
|
|
|
|
|
|
|
|
int tls_get_library_version(char *buf, size_t buf_len)
|
|
|
|
{
|
|
|
|
return os_snprintf(buf, buf_len, "internal");
|
|
|
|
}
|
2015-08-23 21:01:37 +02:00
|
|
|
|
|
|
|
|
|
|
|
void tls_connection_set_success_data(struct tls_connection *conn,
|
|
|
|
struct wpabuf *data)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void tls_connection_set_success_data_resumed(struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const struct wpabuf *
|
|
|
|
tls_connection_get_success_data(struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void tls_connection_remove_session(struct tls_connection *conn)
|
|
|
|
{
|
|
|
|
}
|