Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS session tickets #1430

Merged
merged 13 commits into from
Aug 7, 2020
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions etc/tempesta_fw.conf
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,41 @@
# Specifies a file with the secret key in the PEM format.
#

# TAG: tls_tickets
#
# Enable TLS session tickets generation and processing for faster TLS
# connection establishing as defined in RFC 5077. Enabled by default, allowed
# in vhost scope.
#
# Syntax:
# tls_tickets [disable|enable] [secret=SECRET] [lifetime=N]
#
# The option provides performance improvement without security degradation,
# thus enabled by default. If this is not the desired behaviour, Session
# Tickets can be switched off by 'disable' argument.
#
# In default configuration a random built key is used to generate TLS Sessions
# Ticket keys, so every vhost has its own unique keys and keys are different
# on different TempestaFW installations. If 'secret' is provided, it's used
# as master key to generate Session Ticket keys equally on different TempestaFW
# nodes running the same configuration. In this case TLS session established
# on one TempestaFW node can be resumed on the others. Note that local time is
# mixed into the generated keys, so all TempestaFW nodes should use the same
# time settings. Even if multiple vhosts share the same secret, generated
# tickets keys will differ for them.
#
# Session Ticket keys are constantly rotated, to reduce number of tickets
# encrypted with the same key. Default rotation period is set to 1 hour.
# The rotation period can be exteded by 'lifetime' option.
#
# Example:
# tls_tickets disable;
# tls_tickets secret="f00)9eR59*_/22" lifetime=7200;
#
# Default:
# tls_tickets;
#

# TAG: cache
#
# Web content caching mode:
Expand Down
22 changes: 11 additions & 11 deletions tempesta_fw/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Transport Layer Security (TLS) interfaces to Tempesta TLS.
*
* Copyright (C) 2015-2019 Tempesta Technologies, Inc.
* Copyright (C) 2015-2020 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -115,8 +115,8 @@ tfw_tls_msg_process(void *conn, TfwFsmData *data)
r = ss_skb_process(skb, ttls_recv, tls, &tls->io_in.chunks, &parsed);
switch (r) {
default:
T_WARN("Unrecognized TLS receive return code %d, drop packet\n",
r);
T_WARN("Unrecognized TLS receive return code -0x%X, drop packet\n",
-r);
/* Fall through. */
case T_DROP:
spin_unlock(&tls->lock);
Expand Down Expand Up @@ -692,10 +692,10 @@ static TfwConnHooks tls_conn_hooks = {
.conn_send = tfw_tls_conn_send,
};

static const TlsPeerCfg *
static TlsPeerCfg *
tfw_tls_get_if_configured(TfwVhost *vhost)
{
const TlsPeerCfg *cfg;
TlsPeerCfg *cfg;

if (unlikely(!vhost))
return false;
Expand Down Expand Up @@ -736,26 +736,26 @@ tfw_tls_sni(TlsCtx *ctx, const unsigned char *data, size_t len)
{
const TfwStr srv_name = {.data = (unsigned char *)data, .len = len};
TfwVhost *vhost = NULL;
const TlsPeerCfg *peer_cfg;
TlsPeerCfg *peer_cfg;
TfwCliConn *cli_conn = &container_of(ctx, TfwTlsConn, tls)->cli_conn;

T_DBG2("%s: server name '%.*s'\n", __func__, (int)len, data);

if (WARN_ON_ONCE(ctx->peer_conf))
return -TTLS_ERR_BAD_HS_CLIENT_HELLO;
return TTLS_ERR_BAD_HS_CLIENT_HELLO;

if (data && len) {
vhost = tfw_vhost_lookup(&srv_name);
if (unlikely(vhost && !vhost->vhost_dflt)) {
SNI_WARN(" '%s' vhost by name, reject connection.\n",
TFW_VH_DFT_NAME);
tfw_vhost_put(vhost);
return -TTLS_ERR_BAD_HS_CLIENT_HELLO;
return TTLS_ERR_BAD_HS_CLIENT_HELLO;
}
if (unlikely(!vhost && !tfw_tls.allow_any_sni)) {
SNI_WARN(" unknown server name '%.*s', reject connection.\n",
(int)len, data);
return -TTLS_ERR_BAD_HS_CLIENT_HELLO;
return TTLS_ERR_BAD_HS_CLIENT_HELLO;
}
}
/*
Expand All @@ -765,7 +765,7 @@ tfw_tls_sni(TlsCtx *ctx, const unsigned char *data, size_t len)
if (!vhost)
vhost = tfw_vhost_lookup_default();
if (unlikely(!vhost))
return -TTLS_ERR_CERTIFICATE_REQUIRED;
return TTLS_ERR_CERTIFICATE_REQUIRED;

peer_cfg = tfw_tls_get_if_configured(vhost);
ctx->peer_conf = peer_cfg;
Expand All @@ -776,7 +776,7 @@ tfw_tls_sni(TlsCtx *ctx, const unsigned char *data, size_t len)
PR_TFW_STR(&vhost->name));
}

return peer_cfg ? 0 : -TTLS_ERR_CERTIFICATE_REQUIRED;
return peer_cfg ? 0 : TTLS_ERR_CERTIFICATE_REQUIRED;
}

/*
Expand Down
60 changes: 60 additions & 0 deletions tempesta_fw/tls_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,63 @@ tfw_tls_cert_clean(TfwVhost *vhost)
}
ttls_config_peer_free(&vhost->tls_cfg);
}

int
tfw_tls_set_tickets(TfwVhost *vhost, TfwCfgSpec *cs, TfwCfgEntry *ce)
{
bool enabled = true;
const char *secret = NULL;
size_t secret_len = 0;
unsigned long lifetime = 0;
TfwCfgEntry ce_tmp;
const char *key, *val;
int i, r;

if ((r = tfw_tls_peer_tls_init(vhost)))
return r;

if (ce->have_children) {
T_ERR_NL("%s: nested settings not allowed!\n", cs->name);
return -EINVAL;
}
/*
* Tickets are by default enabled, unless user has switched them off,
* parse enable/disable value first and ignore all attributes.
*/
ce_tmp = *ce;
ce_tmp.attr_n = 0;
cs->dest = &enabled;
if (tfw_cfg_set_bool(cs, ce)) {
T_ERR_NL("%s: can't parse positional values!\n", cs->name);
cs->dest = NULL;
return -EINVAL;
}
cs->dest = NULL;
if (enabled) {
TFW_CFG_ENTRY_FOR_EACH_ATTR(ce, i, key, val) {
if (!strcasecmp(key, "secret")) {
secret = val;
secret_len = strlen(val);
} else if (!strcasecmp(key, "lifetime")) {
if ((r = tfw_cfg_parse_long(val, &lifetime))) {
T_ERR_NL("%s: can't parse '%s' argument!"
"\n", cs->name, key);
return r;
}
if (lifetime > 5 * TTLS_DEFAULT_TICKET_LIFETIME)
T_WARN_NL("%s: setting too long ticket"
"lifetime can be insecure, "
"recommended value is %d\n",
cs->name,
TTLS_DEFAULT_TICKET_LIFETIME);
} else {
T_ERR_NL("%s: unsupported argument: '%s=%s'.\n",
cs->name, key, val);
return -EINVAL;
}
}
}

return ttls_conf_tickets(&vhost->tls_cfg, enabled, lifetime, secret,
secret_len, vhost->name.data, vhost->name.len);
}
3 changes: 2 additions & 1 deletion tempesta_fw/tls_conf.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Tempesta FW
*
* Copyright (C) 2019 Tempesta Technologies, Inc.
* Copyright (C) 2019-2020 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -26,6 +26,7 @@

int tfw_tls_set_cert(TfwVhost *vhost, TfwCfgSpec *cs, TfwCfgEntry *ce);
int tfw_tls_set_cert_key(TfwVhost *vhost, TfwCfgSpec *cs, TfwCfgEntry *ce);
int tfw_tls_set_tickets(TfwVhost *vhost, TfwCfgSpec *cs, TfwCfgEntry *ce);

int tfw_tls_cert_cfg_finish(TfwVhost *vhost);
void tfw_tls_cert_clean(TfwVhost *vhost);
Expand Down
36 changes: 35 additions & 1 deletion tempesta_fw/vhost.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Tempesta FW
*
* Copyright (C) 2016-2019 Tempesta Technologies, Inc.
* Copyright (C) 2016-2020 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -2077,6 +2077,24 @@ tfw_cfgop_in_tls_certificate_key(TfwCfgSpec *cs, TfwCfgEntry *ce)
return tfw_tls_set_cert_key(tfw_vhost_entry, cs, ce);
}

static int
tfw_cfgop_out_tls_tickets(TfwCfgSpec *cs, TfwCfgEntry *ce)
{
if (tfw_vhosts_reconfig->expl_dflt) {
T_ERR_NL("%s: global tls tickets are to be configured "
"outside of explicit '%s' vhost.\n",
cs->name, TFW_VH_DFT_NAME);
return -EINVAL;
}
return tfw_tls_set_tickets(tfw_vhosts_reconfig->vhost_dflt, cs, ce);
}

static int
tfw_cfgop_in_tls_tickets(TfwCfgSpec *cs, TfwCfgEntry *ce)
{
return tfw_tls_set_tickets(tfw_vhost_entry, cs, ce);
}

static int
tfw_cfgop_tls_any_sni(TfwCfgSpec *cs, TfwCfgEntry *ce)
{
Expand Down Expand Up @@ -2823,6 +2841,14 @@ static TfwCfgSpec tfw_vhost_internal_specs[] = {
.allow_repeat = true,
.allow_reconfig = true,
},
{
.name = "tls_tickets",
.deflt = "",
.handler = tfw_cfgop_in_tls_tickets,
.allow_none = true,
.allow_repeat = true,
.allow_reconfig = true,
},
{
.name = "tls_match_any_server_name",
.deflt = "false",
Expand Down Expand Up @@ -2973,6 +2999,14 @@ static TfwCfgSpec tfw_vhost_specs[] = {
.allow_repeat = true,
.allow_reconfig = true,
},
{
.name = "tls_tickets",
.deflt = "",
.handler = tfw_cfgop_out_tls_tickets,
.allow_none = true,
.allow_repeat = true,
.allow_reconfig = true,
},
{
.name = "tls_match_any_server_name",
.deflt = "false",
Expand Down
8 changes: 7 additions & 1 deletion tls/tls_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Based on mbed TLS, https://tls.mbed.org.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Copyright (C) 2015-2019 Tempesta Technologies, Inc.
* Copyright (C) 2015-2020 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -45,6 +45,9 @@
#include "ttls.h"
#include "x509_crt.h"

struct aead_request *ttls_aead_req_alloc(struct crypto_aead *tfm);
void ttls_aead_req_free(struct crypto_aead *tfm, struct aead_request *req);

/* Determine minimum supported version */
#define TTLS_MIN_MAJOR_VERSION TTLS_MAJOR_VERSION_3
#define TTLS_MIN_MINOR_VERSION TTLS_MINOR_VERSION_3
Expand Down Expand Up @@ -139,6 +142,7 @@ typedef struct {
* @tmp - buffer to store temporary data between data chunks;
* @ecdh_ctx - ECDH key exchange;
* @dhm_ctx - DHM key exchange;
* @ticket_ctx - tls session ticket context.
*/
struct tls_handshake_t {
TlsSigHashSet hash_algs;
Expand Down Expand Up @@ -202,6 +206,8 @@ struct tls_handshake_t {
TlsECDHCtx *ecdh_ctx;
TlsDHMCtx *dhm_ctx;
};

TlSTicketCtx ticket_ctx;
};

extern int ttls_preset_hashes[];
Expand Down
Loading