Merge branch 'tls13'

This adds support for TLS 1.3 to libtls and adds several new features to
existing TLS versions (e.g. support for x25519/x448, EdDSA or RSA-PSS).

Unfortunately, TLS 1.3 is not really usable for TLS-based EAP methods in
practice because, in particular, key derivation is not yet standardized.
While it works between two strongSwan instances and even FreeRADIUS 3.0.21,
there will be compatibility issues in the future when implementations move
to a standardized scheme.  There are currently two Internet-Drafts in
development to specify that (see 121ac4b9e3 for details).  Until they are
more stable, the default maximum version is set to 1.2.

The default minimum version has also been increased to 1.2 and several
older/weaker cipher suites have been removed (e.g. with 3DES and MD5).
This commit is contained in:
Tobias Brunner 2021-02-12 15:14:37 +01:00
commit c7a0f2698d
38 changed files with 6661 additions and 1284 deletions

View File

@ -473,6 +473,24 @@ charon.tls.mac
charon.tls.suites
List of TLS cipher suites.
charon.tls.ke_group
List of TLS key exchange groups.
charon.tls.signature
List of TLS signature schemes.
charon.tls.send_certreq_authorities = yes
Whether to include CAs in a server's CertificateRequest message.
Whether to include CAs in a server's CertificateRequest message. May be
disabled if clients can't handle a long list of CAs.
charon.tls.version_min = 1.2
Minimum TLS version to negotiate.
charon.tls.version_max = 1.2
Maximum TLS version to negotiate.
charon.user
Name of the user the daemon changes to after startup.

View File

@ -1,4 +1,8 @@
/*
* Copyright (C) 2020 Pascal Knecht
* Copyright (C) 2020 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@ -33,8 +37,27 @@
static void usage(FILE *out, char *cmd)
{
fprintf(out, "usage:\n");
fprintf(out, " %s --connect <address> --port <port> [--key <key] [--cert <file>]+ [--times <n>]\n", cmd);
fprintf(out, " %s --listen <address> --port <port> --key <key> [--cert <file>]+ [--times <n>]\n", cmd);
fprintf(out, " %s --connect <address> --port <port> [--key <key] [--cert <file>] [--cacert <file>]+ [--times <n>]\n", cmd);
fprintf(out, " %s --listen <address> --port <port> --key <key> --cert <file> [--cacert <file>]+ [--times <n>]\n", cmd);
fprintf(out, "\n");
fprintf(out, "options:\n");
fprintf(out, " --help print help and exit\n");
fprintf(out, " --connect <address> connect to a server on dns name or ip address\n");
fprintf(out, " --listen <address> listen on dns name or ip address\n");
fprintf(out, " --port <port> specify the port to use\n");
fprintf(out, " --cert <file> certificate to authenticate itself\n");
fprintf(out, " --key <file> private key to authenticate itself\n");
fprintf(out, " --cacert <file> certificate to verify other peer\n");
fprintf(out, " --times <n> specify the amount of repeated connection establishments\n");
fprintf(out, " --ipv4 use IPv4\n");
fprintf(out, " --ipv6 use IPv6\n");
fprintf(out, " --min-version <version> specify the minimum TLS version, supported versions:\n");
fprintf(out, " 1.0 (default), 1.1, 1.2 and 1.3\n");
fprintf(out, " --max-version <version> specify the maximum TLS version, supported versions:\n");
fprintf(out, " 1.0, 1.1, 1.2 and 1.3 (default)\n");
fprintf(out, " --version <version> set one specific TLS version to use, supported versions:\n");
fprintf(out, " 1.0, 1.1, 1.2 and 1.3\n");
fprintf(out, " --debug <debug level> set debug level, default is 1\n");
}
/**
@ -85,14 +108,16 @@ static identification_t *find_client_id()
* Client routine
*/
static int run_client(host_t *host, identification_t *server,
identification_t *client, int times, tls_cache_t *cache)
identification_t *client, int times, tls_cache_t *cache,
tls_version_t min_version, tls_version_t max_version)
{
tls_socket_t *tls;
int fd, res;
while (times == -1 || times-- > 0)
{
fd = socket(AF_INET, SOCK_STREAM, 0);
DBG2(DBG_TLS, "connecting to %#H", host);
fd = socket(host->get_family(host), SOCK_STREAM, 0);
if (fd == -1)
{
DBG1(DBG_TLS, "opening socket failed: %s", strerror(errno));
@ -105,7 +130,8 @@ static int run_client(host_t *host, identification_t *server,
close(fd);
return 1;
}
tls = tls_socket_create(FALSE, server, client, fd, cache, TLS_1_2, TRUE);
tls = tls_socket_create(FALSE, server, client, fd, cache, min_version,
max_version, TRUE);
if (!tls)
{
close(fd);
@ -125,8 +151,9 @@ static int run_client(host_t *host, identification_t *server,
/**
* Server routine
*/
static int serve(host_t *host, identification_t *server,
int times, tls_cache_t *cache)
static int serve(host_t *host, identification_t *server, identification_t *client,
int times, tls_cache_t *cache, tls_version_t min_version,
tls_version_t max_version)
{
tls_socket_t *tls;
int fd, cfd;
@ -162,7 +189,8 @@ static int serve(host_t *host, identification_t *server,
}
DBG1(DBG_TLS, "%#H connected", host);
tls = tls_socket_create(TRUE, server, NULL, cfd, cache, TLS_1_2, TRUE);
tls = tls_socket_create(TRUE, server, client, cfd, cache, min_version,
max_version, TRUE);
if (!tls)
{
close(fd);
@ -207,8 +235,8 @@ static bool load_key(char *filename)
{
private_key_t *key;
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
BUILD_FROM_FILE, filename, BUILD_END);
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
BUILD_FROM_FILE, filename, BUILD_END);
if (!key)
{
DBG1(DBG_TLS, "loading key from '%s' failed", filename);
@ -251,11 +279,14 @@ static void cleanup()
*/
static void init()
{
char *plugins;
library_init(NULL, "tls_test");
dbg = dbg_tls;
lib->plugins->load(lib->plugins, PLUGINS);
plugins = getenv("PLUGINS") ?: PLUGINS;
lib->plugins->load(lib->plugins, plugins);
creds = mem_cred_create();
lib->credmgr->add_set(lib->credmgr, &creds->set);
@ -267,8 +298,9 @@ int main(int argc, char *argv[])
{
char *address = NULL;
bool listen = FALSE;
int port = 0, times = -1, res;
identification_t *server, *client;
int port = 0, times = -1, res, family = AF_UNSPEC;
identification_t *server, *client = NULL;
tls_version_t min_version = TLS_SUPPORTED_MIN, max_version = TLS_SUPPORTED_MAX;
tls_cache_t *cache;
host_t *host;
@ -283,7 +315,13 @@ int main(int argc, char *argv[])
{"port", required_argument, NULL, 'p' },
{"cert", required_argument, NULL, 'x' },
{"key", required_argument, NULL, 'k' },
{"cacert", required_argument, NULL, 'f' },
{"times", required_argument, NULL, 't' },
{"ipv4", no_argument, NULL, '4' },
{"ipv6", no_argument, NULL, '6' },
{"min-version", required_argument, NULL, 'm' },
{"max-version", required_argument, NULL, 'M' },
{"version", required_argument, NULL, 'v' },
{"debug", required_argument, NULL, 'd' },
{0,0,0,0 }
};
@ -306,6 +344,13 @@ int main(int argc, char *argv[])
return 1;
}
continue;
case 'f':
if (!load_certificate(optarg))
{
return 1;
}
client = identification_create_from_encoding(ID_ANY, chunk_empty);
continue;
case 'l':
listen = TRUE;
/* fall */
@ -326,6 +371,37 @@ int main(int argc, char *argv[])
case 'd':
tls_level = atoi(optarg);
continue;
case '4':
family = AF_INET;
continue;
case '6':
family = AF_INET6;
continue;
case 'm':
if (!enum_from_name(tls_numeric_version_names, optarg,
&min_version))
{
fprintf(stderr, "unknown minimum TLS version: %s\n", optarg);
return 1;
}
continue;
case 'M':
if (!enum_from_name(tls_numeric_version_names, optarg,
&max_version))
{
fprintf(stderr, "unknown maximum TLS version: %s\n", optarg);
return 1;
}
continue;
case 'v':
if (!enum_from_name(tls_numeric_version_names, optarg,
&min_version))
{
fprintf(stderr, "unknown TLS version: %s\n", optarg);
return 1;
}
max_version = min_version;
continue;
default:
usage(stderr, argv[0]);
return 1;
@ -337,7 +413,7 @@ int main(int argc, char *argv[])
usage(stderr, argv[0]);
return 1;
}
host = host_create_from_dns(address, 0, port);
host = host_create_from_dns(address, family, port);
if (!host)
{
DBG1(DBG_TLS, "resolving hostname %s failed", address);
@ -347,12 +423,14 @@ int main(int argc, char *argv[])
cache = tls_cache_create(100, 30);
if (listen)
{
res = serve(host, server, times, cache);
res = serve(host, server, client, times, cache, min_version, max_version);
}
else
{
DESTROY_IF(client);
client = find_client_id();
res = run_client(host, server, client, times, cache);
res = run_client(host, server, client, times, cache, min_version,
max_version);
DESTROY_IF(client);
}
cache->destroy(cache);

View File

@ -220,10 +220,10 @@ ifneq ($(or $(call plugin_enabled, eap-tls), $(call plugin_enabled, eap-ttls), \
$(call plugin_enabled, eap-peap), $(call plugin_enabled, eap-tnc)),)
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libtls/
LOCAL_SRC_FILES += $(addprefix ../libtls/, \
tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
tls_crypto.c tls_prf.c tls_socket.c tls_eap.c tls_cache.c tls_peer.c \
tls_aead_expl.c tls_aead_impl.c tls_aead_null.c tls_aead.c \
tls_server.c tls.c \
tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
tls_crypto.c tls_prf.c tls_hkdf.c tls_socket.c tls_eap.c tls_cache.c \
tls_aead_expl.c tls_aead_impl.c tls_aead_null.c tls_aead_seq.c tls_aead.c \
tls_peer.c tls_server.c tls.c \
)
endif

View File

@ -877,7 +877,7 @@ static bool soap_init(private_tnc_ifmap_soap_t *this)
/* open TLS socket */
this->tls = tls_socket_create(FALSE, server_id, client_id, this->fd,
NULL, TLS_1_2, FALSE);
NULL, TLS_UNSPEC, TLS_UNSPEC, FALSE);
if (!this->tls)
{
DBG1(DBG_TNC, "creating TLS socket failed");

View File

@ -85,7 +85,7 @@ static bool make_connection(private_pt_tls_client_t *this)
}
this->tls = tls_socket_create(FALSE, this->server, this->client, fd,
NULL, TLS_1_2, FALSE);
NULL, TLS_UNSPEC, TLS_UNSPEC, FALSE);
if (!this->tls)
{
close(fd);

View File

@ -532,7 +532,8 @@ pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd,
.destroy = _destroy,
},
.state = PT_TLS_SERVER_VERSION,
.tls = tls_socket_create(TRUE, server, NULL, fd, NULL, TLS_1_2, FALSE),
.tls = tls_socket_create(TRUE, server, NULL, fd, NULL, TLS_UNSPEC,
TLS_UNSPEC, FALSE),
.tnccs = (tls_t*)tnccs,
.auth = auth,
);

View File

@ -57,6 +57,45 @@ ENUM_NEXT(diffie_hellman_group_names, MODP_CUSTOM, MODP_CUSTOM, NH_128_BIT,
"MODP_CUSTOM");
ENUM_END(diffie_hellman_group_names, MODP_CUSTOM);
ENUM_BEGIN(diffie_hellman_group_names_short, MODP_NONE, MODP_1024_BIT,
"modpnone",
"modp768",
"modp1024");
ENUM_NEXT(diffie_hellman_group_names_short, MODP_1536_BIT, MODP_1536_BIT, MODP_1024_BIT,
"modp1536");
ENUM_NEXT(diffie_hellman_group_names_short, MODP_2048_BIT, ECP_521_BIT, MODP_1536_BIT,
"modp2048",
"modp3072",
"modp4096",
"modp6144",
"modp8192",
"ecp256",
"ecp384",
"ecp521");
ENUM_NEXT(diffie_hellman_group_names_short, MODP_1024_160, CURVE_448, ECP_521_BIT,
"modp1024s160",
"modp2048s224",
"modp2048s256",
"ecp192",
"ecp224",
"ecp224bp",
"ecp256bp",
"ecp384bp",
"ecp512bp",
"curve25519",
"curve448");
ENUM_NEXT(diffie_hellman_group_names_short, MODP_NULL, MODP_NULL, CURVE_448,
"modpnull");
ENUM_NEXT(diffie_hellman_group_names_short, NTRU_112_BIT, NTRU_256_BIT, MODP_NULL,
"ntru112",
"ntru128",
"ntru192",
"ntru256");
ENUM_NEXT(diffie_hellman_group_names_short, NH_128_BIT, NH_128_BIT, NTRU_256_BIT,
"newhope128");
ENUM_NEXT(diffie_hellman_group_names_short, MODP_CUSTOM, MODP_CUSTOM, NH_128_BIT,
"modpcustom");
ENUM_END(diffie_hellman_group_names_short, MODP_CUSTOM);
/**
* List of known diffie hellman group parameters.
@ -493,6 +532,8 @@ bool diffie_hellman_group_is_ec(diffie_hellman_group_t group)
case ECP_256_BP:
case ECP_384_BP:
case ECP_512_BP:
case CURVE_25519:
case CURVE_448:
return TRUE;
default:
return FALSE;

View File

@ -82,6 +82,11 @@ enum diffie_hellman_group_t {
*/
extern enum_name_t *diffie_hellman_group_names;
/**
* enum names for diffie_hellman_group_t (matching proposal keywords).
*/
extern enum_name_t *diffie_hellman_group_names_short;
/**
* Implementation of the Diffie-Hellman algorithm, as in RFC2631.
*/

View File

@ -45,36 +45,42 @@ aes128ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128
aes128ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128
aes128ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
aes128ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
aes128ccm, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128
aes192ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192
aes192ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192
aes192ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192
aes192ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192
aes192ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
aes192ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
aes192ccm, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192
aes256ccm8, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256
aes256ccm64, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256
aes256ccm12, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256
aes256ccm96, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256
aes256ccm16, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
aes256ccm128, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
aes256ccm, ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256
aes128gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128
aes128gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128
aes128gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128
aes128gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128
aes128gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
aes128gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
aes128gcm, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128
aes192gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192
aes192gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192
aes192gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192
aes192gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192
aes192gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
aes192gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
aes192gcm, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192
aes256gcm8, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256
aes256gcm64, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256
aes256gcm12, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256
aes256gcm96, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256
aes256gcm16, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
aes256gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
aes256gcm, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
aes128gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 128
aes192gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 192
aes256gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256

View File

@ -17,6 +17,32 @@
#include <crypto/proposal/proposal.h>
START_TEST(test_dh_group_mapping)
{
enum_name_t *e = diffie_hellman_group_names_short;
diffie_hellman_group_t group;
const proposal_token_t *token;
char *name;
do
{
for (group = e->first; group <= e->last; group++)
{
if (group == MODP_CUSTOM)
{ /* can't be configured */
continue;
}
name = e->names[group - e->first];
token = lib->proposal->get_token(lib->proposal, name);
ck_assert_msg(token, "%s can't be mapped", name);
ck_assert_int_eq(token->type, DIFFIE_HELLMAN_GROUP);
ck_assert_int_eq(token->algorithm, group);
}
}
while ((e = e->next));
}
END_TEST
static struct {
protocol_id_t proto;
char *proposal;
@ -456,6 +482,10 @@ Suite *proposal_suite_create()
s = suite_create("proposal");
tc = tcase_create("proposal keywords");
tcase_add_test(tc, test_dh_group_mapping);
suite_add_tcase(s, tc);
tc = tcase_create("create_from_string");
tcase_add_loop_test(tc, test_create_from_string, 0, countof(create_data));
suite_add_tcase(s, tc);

View File

@ -10,9 +10,9 @@ AM_LDFLAGS = \
ipseclib_LTLIBRARIES = libtls.la
libtls_la_SOURCES = \
tls_protection.c tls_compression.c tls_fragmentation.c tls_alert.c \
tls_crypto.c tls_prf.c tls_socket.c tls_eap.c tls_cache.c tls_peer.c \
tls_aead_expl.c tls_aead_impl.c tls_aead_null.c tls_aead.c \
tls_server.c tls.c
tls_crypto.c tls_prf.c tls_hkdf.c tls_socket.c tls_eap.c tls_cache.c \
tls_aead_expl.c tls_aead_impl.c tls_aead_null.c tls_aead_seq.c tls_aead.c \
tls_peer.c tls_server.c tls.c
libtls_la_LIBADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la
@ -25,8 +25,8 @@ if USE_DEV_HEADERS
tls_includedir = ${dev_headers}/tls
nobase_tls_include_HEADERS = \
tls_protection.h tls_compression.h tls_fragmentation.h tls_alert.h \
tls_crypto.h tls_prf.h tls_socket.h tls_eap.h tls_cache.h tls_peer.h \
tls_server.h tls_handshake.h tls_application.h tls_aead.h tls.h
tls_crypto.h tls_prf.h tls_hkdf.h tls_socket.h tls_eap.h tls_cache.h \
tls_peer.h tls_server.h tls_handshake.h tls_application.h tls_aead.h tls.h
endif
SUBDIRS = . tests

View File

@ -3,6 +3,7 @@ TESTS = tls_tests
check_PROGRAMS = $(TESTS)
tls_tests_SOURCES = \
suites/test_hkdf.c \
suites/test_socket.c \
suites/test_suites.c \
tls_tests.h tls_tests.c

View File

@ -0,0 +1,727 @@
/*
* Copyright (C) 2020 Pascal Knecht
* Copyright (C) 2020 Méline Sieber
* HSR Hochschule fuer Technik Rapperswil
*
* 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 the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <test_suite.h>
#include "tls_hkdf.h"
static chunk_t ulfheim_ecdhe = chunk_from_chars(
0xdf,0x4a,0x29,0x1b,0xaa,0x1e,0xb7,0xcf,0xa6,0x93,0x4b,0x29,0xb4,0x74,0xba,0xad,
0x26,0x97,0xe2,0x9f,0x1f,0x92,0x0d,0xcc,0x77,0xc8,0xa0,0xa0,0x88,0x44,0x76,0x24,
);
static chunk_t ulfheim_client_server_hello = chunk_from_chars(
/* Client Hello */
0x01,0x00,0x00,0xc6,0x03,0x03,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,
0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,
0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,0x00,0x06,0x13,0x01,0x13,0x02,0x13,0x03,0x01,
0x00,0x00,0x77,0x00,0x00,0x00,0x18,0x00,0x16,0x00,0x00,0x13,0x65,0x78,0x61,0x6d,
0x70,0x6c,0x65,0x2e,0x75,0x6c,0x66,0x68,0x65,0x69,0x6d,0x2e,0x6e,0x65,0x74,0x00,
0x0a,0x00,0x08,0x00,0x06,0x00,0x1d,0x00,0x17,0x00,0x18,0x00,0x0d,0x00,0x14,0x00,
0x12,0x04,0x03,0x08,0x04,0x04,0x01,0x05,0x03,0x08,0x05,0x05,0x01,0x08,0x06,0x06,
0x01,0x02,0x01,0x00,0x33,0x00,0x26,0x00,0x24,0x00,0x1d,0x00,0x20,0x35,0x80,0x72,
0xd6,0x36,0x58,0x80,0xd1,0xae,0xea,0x32,0x9a,0xdf,0x91,0x21,0x38,0x38,0x51,0xed,
0x21,0xa2,0x8e,0x3b,0x75,0xe9,0x65,0xd0,0xd2,0xcd,0x16,0x62,0x54,0x00,0x2d,0x00,
0x02,0x01,0x01,0x00,0x2b,0x00,0x03,0x02,0x03,0x04,
/* Server Hello */
0x02,0x00,0x00,0x76,0x03,0x03,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,0x20,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,
0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,0x13,0x01,0x00,0x00,0x2e,0x00,0x33,0x00,0x24,
0x00,0x1d,0x00,0x20,0x9f,0xd7,0xad,0x6d,0xcf,0xf4,0x29,0x8d,0xd3,0xf9,0x6d,0x5b,
0x1b,0x2a,0xf9,0x10,0xa0,0x53,0x5b,0x14,0x88,0xd7,0xf8,0xfa,0xbb,0x34,0x9a,0x98,
0x28,0x80,0xb6,0x15,0x00,0x2b,0x00,0x02,0x03,0x04,
);
static chunk_t ulfheim_server_data = chunk_from_chars(
/* Server Encrypted Extension */
0x08,0x00,0x00,0x02,0x00,0x00,
/* Server Certificate */
0x0b,0x00,0x03,0x2e,0x00,0x00,0x03,0x2a,0x00,0x03,0x25,0x30,0x82,0x03,0x21,0x30,
0x82,0x02,0x09,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x15,0x5a,0x92,0xad,0xc2,0x04,
0x8f,0x90,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,
0x00,0x30,0x22,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,
0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x13,0x0a,0x45,0x78,0x61,0x6d,0x70,
0x6c,0x65,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x31,0x38,0x31,0x30,0x30,0x35,0x30,
0x31,0x33,0x38,0x31,0x37,0x5a,0x17,0x0d,0x31,0x39,0x31,0x30,0x30,0x35,0x30,0x31,
0x33,0x38,0x31,0x37,0x5a,0x30,0x2b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
0x13,0x02,0x55,0x53,0x31,0x1c,0x30,0x1a,0x06,0x03,0x55,0x04,0x03,0x13,0x13,0x65,
0x78,0x61,0x6d,0x70,0x6c,0x65,0x2e,0x75,0x6c,0x66,0x68,0x65,0x69,0x6d,0x2e,0x6e,
0x65,0x74,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,
0x01,0x01,0x00,0xc4,0x80,0x36,0x06,0xba,0xe7,0x47,0x6b,0x08,0x94,0x04,0xec,0xa7,
0xb6,0x91,0x04,0x3f,0xf7,0x92,0xbc,0x19,0xee,0xfb,0x7d,0x74,0xd7,0xa8,0x0d,0x00,
0x1e,0x7b,0x4b,0x3a,0x4a,0xe6,0x0f,0xe8,0xc0,0x71,0xfc,0x73,0xe7,0x02,0x4c,0x0d,
0xbc,0xf4,0xbd,0xd1,0x1d,0x39,0x6b,0xba,0x70,0x46,0x4a,0x13,0xe9,0x4a,0xf8,0x3d,
0xf3,0xe1,0x09,0x59,0x54,0x7b,0xc9,0x55,0xfb,0x41,0x2d,0xa3,0x76,0x52,0x11,0xe1,
0xf3,0xdc,0x77,0x6c,0xaa,0x53,0x37,0x6e,0xca,0x3a,0xec,0xbe,0xc3,0xaa,0xb7,0x3b,
0x31,0xd5,0x6c,0xb6,0x52,0x9c,0x80,0x98,0xbc,0xc9,0xe0,0x28,0x18,0xe2,0x0b,0xf7,
0xf8,0xa0,0x3a,0xfd,0x17,0x04,0x50,0x9e,0xce,0x79,0xbd,0x9f,0x39,0xf1,0xea,0x69,
0xec,0x47,0x97,0x2e,0x83,0x0f,0xb5,0xca,0x95,0xde,0x95,0xa1,0xe6,0x04,0x22,0xd5,
0xee,0xbe,0x52,0x79,0x54,0xa1,0xe7,0xbf,0x8a,0x86,0xf6,0x46,0x6d,0x0d,0x9f,0x16,
0x95,0x1a,0x4c,0xf7,0xa0,0x46,0x92,0x59,0x5c,0x13,0x52,0xf2,0x54,0x9e,0x5a,0xfb,
0x4e,0xbf,0xd7,0x7a,0x37,0x95,0x01,0x44,0xe4,0xc0,0x26,0x87,0x4c,0x65,0x3e,0x40,
0x7d,0x7d,0x23,0x07,0x44,0x01,0xf4,0x84,0xff,0xd0,0x8f,0x7a,0x1f,0xa0,0x52,0x10,
0xd1,0xf4,0xf0,0xd5,0xce,0x79,0x70,0x29,0x32,0xe2,0xca,0xbe,0x70,0x1f,0xdf,0xad,
0x6b,0x4b,0xb7,0x11,0x01,0xf4,0x4b,0xad,0x66,0x6a,0x11,0x13,0x0f,0xe2,0xee,0x82,
0x9e,0x4d,0x02,0x9d,0xc9,0x1c,0xdd,0x67,0x16,0xdb,0xb9,0x06,0x18,0x86,0xed,0xc1,
0xba,0x94,0x21,0x02,0x03,0x01,0x00,0x01,0xa3,0x52,0x30,0x50,0x30,0x0e,0x06,0x03,
0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x05,0xa0,0x30,0x1d,0x06,0x03,
0x55,0x1d,0x25,0x04,0x16,0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,
0x02,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x01,0x30,0x1f,0x06,0x03,0x55,
0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,0x89,0x4f,0xde,0x5b,0xcc,0x69,0xe2,0x52,
0xcf,0x3e,0xa3,0x00,0xdf,0xb1,0x97,0xb8,0x1d,0xe1,0xc1,0x46,0x30,0x0d,0x06,0x09,
0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x82,0x01,0x01,0x00,
0x59,0x16,0x45,0xa6,0x9a,0x2e,0x37,0x79,0xe4,0xf6,0xdd,0x27,0x1a,0xba,0x1c,0x0b,
0xfd,0x6c,0xd7,0x55,0x99,0xb5,0xe7,0xc3,0x6e,0x53,0x3e,0xff,0x36,0x59,0x08,0x43,
0x24,0xc9,0xe7,0xa5,0x04,0x07,0x9d,0x39,0xe0,0xd4,0x29,0x87,0xff,0xe3,0xeb,0xdd,
0x09,0xc1,0xcf,0x1d,0x91,0x44,0x55,0x87,0x0b,0x57,0x1d,0xd1,0x9b,0xdf,0x1d,0x24,
0xf8,0xbb,0x9a,0x11,0xfe,0x80,0xfd,0x59,0x2b,0xa0,0x39,0x8c,0xde,0x11,0xe2,0x65,
0x1e,0x61,0x8c,0xe5,0x98,0xfa,0x96,0xe5,0x37,0x2e,0xef,0x3d,0x24,0x8a,0xfd,0xe1,
0x74,0x63,0xeb,0xbf,0xab,0xb8,0xe4,0xd1,0xab,0x50,0x2a,0x54,0xec,0x00,0x64,0xe9,
0x2f,0x78,0x19,0x66,0x0d,0x3f,0x27,0xcf,0x20,0x9e,0x66,0x7f,0xce,0x5a,0xe2,0xe4,
0xac,0x99,0xc7,0xc9,0x38,0x18,0xf8,0xb2,0x51,0x07,0x22,0xdf,0xed,0x97,0xf3,0x2e,
0x3e,0x93,0x49,0xd4,0xc6,0x6c,0x9e,0xa6,0x39,0x6d,0x74,0x44,0x62,0xa0,0x6b,0x42,
0xc6,0xd5,0xba,0x68,0x8e,0xac,0x3a,0x01,0x7b,0xdd,0xfc,0x8e,0x2c,0xfc,0xad,0x27,
0xcb,0x69,0xd3,0xcc,0xdc,0xa2,0x80,0x41,0x44,0x65,0xd3,0xae,0x34,0x8c,0xe0,0xf3,
0x4a,0xb2,0xfb,0x9c,0x61,0x83,0x71,0x31,0x2b,0x19,0x10,0x41,0x64,0x1c,0x23,0x7f,
0x11,0xa5,0xd6,0x5c,0x84,0x4f,0x04,0x04,0x84,0x99,0x38,0x71,0x2b,0x95,0x9e,0xd6,
0x85,0xbc,0x5c,0x5d,0xd6,0x45,0xed,0x19,0x90,0x94,0x73,0x40,0x29,0x26,0xdc,0xb4,
0x0e,0x34,0x69,0xa1,0x59,0x41,0xe8,0xe2,0xcc,0xa8,0x4b,0xb6,0x08,0x46,0x36,0xa0,
0x00,0x00,
/* Server Certificate Verify */
0x0f,0x00,0x01,0x04,0x08,0x04,0x01,0x00,0x17,0xfe,0xb5,0x33,0xca,0x6d,0x00,0x7d,
0x00,0x58,0x25,0x79,0x68,0x42,0x4b,0xbc,0x3a,0xa6,0x90,0x9e,0x9d,0x49,0x55,0x75,
0x76,0xa5,0x20,0xe0,0x4a,0x5e,0xf0,0x5f,0x0e,0x86,0xd2,0x4f,0xf4,0x3f,0x8e,0xb8,
0x61,0xee,0xf5,0x95,0x22,0x8d,0x70,0x32,0xaa,0x36,0x0f,0x71,0x4e,0x66,0x74,0x13,
0x92,0x6e,0xf4,0xf8,0xb5,0x80,0x3b,0x69,0xe3,0x55,0x19,0xe3,0xb2,0x3f,0x43,0x73,
0xdf,0xac,0x67,0x87,0x06,0x6d,0xcb,0x47,0x56,0xb5,0x45,0x60,0xe0,0x88,0x6e,0x9b,
0x96,0x2c,0x4a,0xd2,0x8d,0xab,0x26,0xba,0xd1,0xab,0xc2,0x59,0x16,0xb0,0x9a,0xf2,
0x86,0x53,0x7f,0x68,0x4f,0x80,0x8a,0xef,0xee,0x73,0x04,0x6c,0xb7,0xdf,0x0a,0x84,
0xfb,0xb5,0x96,0x7a,0xca,0x13,0x1f,0x4b,0x1c,0xf3,0x89,0x79,0x94,0x03,0xa3,0x0c,
0x02,0xd2,0x9c,0xbd,0xad,0xb7,0x25,0x12,0xdb,0x9c,0xec,0x2e,0x5e,0x1d,0x00,0xe5,
0x0c,0xaf,0xcf,0x6f,0x21,0x09,0x1e,0xbc,0x4f,0x25,0x3c,0x5e,0xab,0x01,0xa6,0x79,
0xba,0xea,0xbe,0xed,0xb9,0xc9,0x61,0x8f,0x66,0x00,0x6b,0x82,0x44,0xd6,0x62,0x2a,
0xaa,0x56,0x88,0x7c,0xcf,0xc6,0x6a,0x0f,0x38,0x51,0xdf,0xa1,0x3a,0x78,0xcf,0xf7,
0x99,0x1e,0x03,0xcb,0x2c,0x3a,0x0e,0xd8,0x7d,0x73,0x67,0x36,0x2e,0xb7,0x80,0x5b,
0x00,0xb2,0x52,0x4f,0xf2,0x98,0xa4,0xda,0x48,0x7c,0xac,0xde,0xaf,0x8a,0x23,0x36,
0xc5,0x63,0x1b,0x3e,0xfa,0x93,0x5b,0xb4,0x11,0xe7,0x53,0xca,0x13,0xb0,0x15,0xfe,
0xc7,0xe4,0xa7,0x30,0xf1,0x36,0x9f,0x9e,
/* Server Handshake Finish */
0x14,0x00,0x00,0x20,0xea,0x6e,0xe1,0x76,0xdc,0xcc,0x4a,0xf1,0x85,0x9e,0x9e,0x4e,
0x93,0xf7,0x97,0xea,0xc9,0xa7,0x8c,0xe4,0x39,0x30,0x1e,0x35,0x27,0x5a,0xd4,0x3f,
0x3c,0xdd,0xbd,0xe3,
);
static void check_secret(tls_hkdf_t *hkdf, tls_hkdf_label_t label, chunk_t data, chunk_t exp_secret)
{
chunk_t secret;
ck_assert(hkdf->generate_secret(hkdf, label, data, &secret));
ck_assert_chunk_eq(exp_secret, secret);
chunk_free(&secret);
}
static void check_secret_key_iv(tls_hkdf_t *hkdf, tls_hkdf_label_t label,
chunk_t data, bool is_server, chunk_t exp_secret,
int key_length, int iv_length, chunk_t exp_key,
chunk_t exp_iv)
{
chunk_t key, iv;
check_secret(hkdf, label, data, exp_secret);
ck_assert(hkdf->derive_key(hkdf, is_server, key_length, &key));
ck_assert_chunk_eq(exp_key, key);
ck_assert(hkdf->derive_iv(hkdf, is_server, iv_length, &iv));
ck_assert_chunk_eq(exp_iv, iv);
chunk_free(&key);
chunk_free(&iv);
}
static void check_finished(tls_hkdf_t *hkdf, bool is_server, chunk_t exp_finished)
{
chunk_t finished;
ck_assert(hkdf->derive_finished(hkdf, is_server, &finished));
ck_assert_chunk_eq(exp_finished, finished);
chunk_free(&finished);
}
static void check_resumption(tls_hkdf_t *hkdf, chunk_t data, chunk_t exp_resume)
{
chunk_t nonce, resume;
nonce = chunk_from_chars(0x00,0x00);
ck_assert(hkdf->resume(hkdf, data, nonce, &resume));
ck_assert_chunk_eq(exp_resume, resume);
chunk_free(&resume);
}
START_TEST(test_ulfheim_handshake)
{
chunk_t exp_client_handshake_traffic_secret = chunk_from_chars(
0xff,0x0e,0x5b,0x96,0x52,0x91,0xc6,0x08,0xc1,0xe8,0xcd,0x26,0x7e,0xef,0xc0,0xaf,
0xcc,0x5e,0x98,0xa2,0x78,0x63,0x73,0xf0,0xdb,0x47,0xb0,0x47,0x86,0xd7,0x2a,0xea,
);
chunk_t exp_client_handshake_key = chunk_from_chars(
0x71,0x54,0xf3,0x14,0xe6,0xbe,0x7d,0xc0,0x08,0xdf,0x2c,0x83,0x2b,0xaa,0x1d,0x39,
);
chunk_t exp_client_handshake_iv = chunk_from_chars(
0x71,0xab,0xc2,0xca,0xe4,0xc6,0x99,0xd4,0x7c,0x60,0x02,0x68,
);
chunk_t exp_server_handshake_traffic_secret = chunk_from_chars(
0xa2,0x06,0x72,0x65,0xe7,0xf0,0x65,0x2a,0x92,0x3d,0x5d,0x72,0xab,0x04,0x67,0xc4,
0x61,0x32,0xee,0xb9,0x68,0xb6,0xa3,0x2d,0x31,0x1c,0x80,0x58,0x68,0x54,0x88,0x14,
);
chunk_t exp_server_handshake_key = chunk_from_chars(
0x84,0x47,0x80,0xa7,0xac,0xad,0x9f,0x98,0x0f,0xa2,0x5c,0x11,0x4e,0x43,0x40,0x2a,
);
chunk_t exp_server_handshake_iv = chunk_from_chars(
0x4c,0x04,0x2d,0xdc,0x12,0x0a,0x38,0xd1,0x41,0x7f,0xc8,0x15,
);
chunk_t exp_client_finished_key = chunk_from_chars(
0x7c,0x60,0xf8,0xd6,0x34,0x6f,0x4a,0x96,0x91,0xd2,0xae,0x64,0x5a,0x78,0x85,0xe0,
0x10,0x4a,0xdf,0xf9,0x8e,0xba,0x98,0x1c,0xa2,0xf9,0x9e,0xf6,0x2b,0xdd,0x8f,0xaa,
);
chunk_t exp_server_finished_key = chunk_from_chars(
0xea,0x84,0xab,0xd2,0xad,0xa0,0xb5,0xc6,0x4c,0x08,0x07,0xa3,0x26,0xb6,0xfd,0x94,
0xa9,0x59,0x7e,0x39,0xca,0x62,0x10,0x60,0x7c,0x0d,0x3c,0x8c,0x76,0x68,0x65,0x71,
);
tls_hkdf_t *hkdf = tls_hkdf_create(HASH_SHA256, chunk_empty);
ck_assert(hkdf);
hkdf->set_shared_secret(hkdf, ulfheim_ecdhe);
/* Generate client handshake traffic secret */
check_secret_key_iv(hkdf, TLS_HKDF_C_HS_TRAFFIC, ulfheim_client_server_hello,
FALSE, exp_client_handshake_traffic_secret, 16, 12,
exp_client_handshake_key, exp_client_handshake_iv);
check_finished(hkdf, FALSE, exp_client_finished_key);
/* Generate server handshake traffic secret */
check_secret_key_iv(hkdf, TLS_HKDF_S_HS_TRAFFIC, ulfheim_client_server_hello,
TRUE, exp_server_handshake_traffic_secret, 16, 12,
exp_server_handshake_key, exp_server_handshake_iv);
check_finished(hkdf, TRUE, exp_server_finished_key);
hkdf->destroy(hkdf);
}
END_TEST
START_TEST(test_ulfheim_traffic)
{
chunk_t exp_client_application_traffic_secret = chunk_from_chars(
0xb8,0x82,0x22,0x31,0xc1,0xd6,0x76,0xec,0xca,0x1c,0x11,0xff,0xf6,0x59,0x42,0x80,
0x31,0x4d,0x03,0xa4,0xe9,0x1c,0xf1,0xaf,0x7f,0xe7,0x3f,0x8f,0x7b,0xe2,0xc1,0x1b,
);
chunk_t exp_client_application_key = chunk_from_chars(
0x49,0x13,0x4b,0x95,0x32,0x8f,0x27,0x9f,0x01,0x83,0x86,0x05,0x89,0xac,0x67,0x07,
);
chunk_t exp_client_application_iv = chunk_from_chars(
0xbc,0x4d,0xd5,0xf7,0xb9,0x8a,0xcf,0xf8,0x54,0x66,0x26,0x1d,
);
chunk_t exp_server_application_traffic_secret = chunk_from_chars(
0x3f,0xc3,0x5e,0xa7,0x06,0x93,0x06,0x9a,0x27,0x79,0x56,0xaf,0xa2,0x3b,0x8f,0x45,
0x43,0xce,0x68,0xac,0x59,0x5f,0x2a,0xac,0xe0,0x5c,0xd7,0xa1,0xc9,0x20,0x23,0xd5,
);
chunk_t exp_server_application_key = chunk_from_chars(
0x0b,0x6d,0x22,0xc8,0xff,0x68,0x09,0x7e,0xa8,0x71,0xc6,0x72,0x07,0x37,0x73,0xbf,
);
chunk_t exp_server_application_iv = chunk_from_chars(
0x1b,0x13,0xdd,0x9f,0x8d,0x8f,0x17,0x09,0x1d,0x34,0xb3,0x49,
);
chunk_t hs_data;
tls_hkdf_t *hkdf = tls_hkdf_create(HASH_SHA256, chunk_empty);
ck_assert(hkdf);
hkdf->set_shared_secret(hkdf, ulfheim_ecdhe);
/* Generate client application traffic secret */
hs_data = chunk_cata("cc", ulfheim_client_server_hello, ulfheim_server_data);
check_secret_key_iv(hkdf, TLS_HKDF_C_AP_TRAFFIC, hs_data, FALSE,
exp_client_application_traffic_secret, 16, 12,
exp_client_application_key, exp_client_application_iv);
/* Generate server application traffic secret */
check_secret_key_iv(hkdf, TLS_HKDF_S_AP_TRAFFIC, hs_data, TRUE,
exp_server_application_traffic_secret, 16, 12,
exp_server_application_key, exp_server_application_iv);
hkdf->destroy(hkdf);
}
END_TEST
START_TEST(test_rfc8448_simple_1_rtt_handshake)
{
chunk_t client_hello = chunk_from_chars(
0x01,0x00,0x00,0xc0,0x03,0x03,0xcb,0x34,0xec,0xb1,0xe7,0x81,0x63,0xba,0x1c,0x38,
0xc6,0xda,0xcb,0x19,0x6a,0x6d,0xff,0xa2,0x1a,0x8d,0x99,0x12,0xec,0x18,0xa2,0xef,
0x62,0x83,0x02,0x4d,0xec,0xe7,0x00,0x00,0x06,0x13,0x01,0x13,0x03,0x13,0x02,0x01,
0x00,0x00,0x91,0x00,0x00,0x00,0x0b,0x00,0x09,0x00,0x00,0x06,0x73,0x65,0x72,0x76,
0x65,0x72,0xff,0x01,0x00,0x01,0x00,0x00,0x0a,0x00,0x14,0x00,0x12,0x00,0x1d,0x00,
0x17,0x00,0x18,0x00,0x19,0x01,0x00,0x01,0x01,0x01,0x02,0x01,0x03,0x01,0x04,0x00,
0x23,0x00,0x00,0x00,0x33,0x00,0x26,0x00,0x24,0x00,0x1d,0x00,0x20,0x99,0x38,0x1d,
0xe5,0x60,0xe4,0xbd,0x43,0xd2,0x3d,0x8e,0x43,0x5a,0x7d,0xba,0xfe,0xb3,0xc0,0x6e,
0x51,0xc1,0x3c,0xae,0x4d,0x54,0x13,0x69,0x1e,0x52,0x9a,0xaf,0x2c,0x00,0x2b,0x00,
0x03,0x02,0x03,0x04,0x00,0x0d,0x00,0x20,0x00,0x1e,0x04,0x03,0x05,0x03,0x06,0x03,
0x02,0x03,0x08,0x04,0x08,0x05,0x08,0x06,0x04,0x01,0x05,0x01,0x06,0x01,0x02,0x01,
0x04,0x02,0x05,0x02,0x06,0x02,0x02,0x02,0x00,0x2d,0x00,0x02,0x01,0x01,0x00,0x1c,
0x00,0x02,0x40,0x01,
);
chunk_t server_hello = chunk_from_chars(
0x02,0x00,0x00,0x56,0x03,0x03,0xa6,0xaf,0x06,0xa4,0x12,0x18,0x60,0xdc,0x5e,0x6e,
0x60,0x24,0x9c,0xd3,0x4c,0x95,0x93,0x0c,0x8a,0xc5,0xcb,0x14,0x34,0xda,0xc1,0x55,
0x77,0x2e,0xd3,0xe2,0x69,0x28,0x00,0x13,0x01,0x00,0x00,0x2e,0x00,0x33,0x00,0x24,
0x00,0x1d,0x00,0x20,0xc9,0x82,0x88,0x76,0x11,0x20,0x95,0xfe,0x66,0x76,0x2b,0xdb,
0xf7,0xc6,0x72,0xe1,0x56,0xd6,0xcc,0x25,0x3b,0x83,0x3d,0xf1,0xdd,0x69,0xb1,0xb0,
0x4e,0x75,0x1f,0x0f,0x00,0x2b,0x00,0x02,0x03,0x04,
);
chunk_t server_data = chunk_from_chars(
/* Server Encrypted Extension */
0x08,0x00,0x00,0x24,0x00,0x22,0x00,0x0a,0x00,0x14,0x00,0x12,0x00,0x1d,0x00,0x17,
0x00,0x18,0x00,0x19,0x01,0x00,0x01,0x01,0x01,0x02,0x01,0x03,0x01,0x04,0x00,0x1c,
0x00,0x02,0x40,0x01,0x00,0x00,0x00,0x00,
/* Server Certificate */
0x0b,0x00,0x01,0xb9,0x00,0x00,0x01,0xb5,0x00,0x01,0xb0,0x30,0x82,0x01,0xac,0x30,
0x82,0x01,0x15,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x02,0x30,0x0d,0x06,0x09,0x2a,
0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x30,0x0e,0x31,0x0c,0x30,0x0a,
0x06,0x03,0x55,0x04,0x03,0x13,0x03,0x72,0x73,0x61,0x30,0x1e,0x17,0x0d,0x31,0x36,
0x30,0x37,0x33,0x30,0x30,0x31,0x32,0x33,0x35,0x39,0x5a,0x17,0x0d,0x32,0x36,0x30,
0x37,0x33,0x30,0x30,0x31,0x32,0x33,0x35,0x39,0x5a,0x30,0x0e,0x31,0x0c,0x30,0x0a,
0x06,0x03,0x55,0x04,0x03,0x13,0x03,0x72,0x73,0x61,0x30,0x81,0x9f,0x30,0x0d,0x06,
0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb4,0xbb,0x49,0x8f,0x82,0x79,0x30,0x3d,0x98,
0x08,0x36,0x39,0x9b,0x36,0xc6,0x98,0x8c,0x0c,0x68,0xde,0x55,0xe1,0xbd,0xb8,0x26,
0xd3,0x90,0x1a,0x24,0x61,0xea,0xfd,0x2d,0xe4,0x9a,0x91,0xd0,0x15,0xab,0xbc,0x9a,
0x95,0x13,0x7a,0xce,0x6c,0x1a,0xf1,0x9e,0xaa,0x6a,0xf9,0x8c,0x7c,0xed,0x43,0x12,
0x09,0x98,0xe1,0x87,0xa8,0x0e,0xe0,0xcc,0xb0,0x52,0x4b,0x1b,0x01,0x8c,0x3e,0x0b,
0x63,0x26,0x4d,0x44,0x9a,0x6d,0x38,0xe2,0x2a,0x5f,0xda,0x43,0x08,0x46,0x74,0x80,
0x30,0x53,0x0e,0xf0,0x46,0x1c,0x8c,0xa9,0xd9,0xef,0xbf,0xae,0x8e,0xa6,0xd1,0xd0,
0x3e,0x2b,0xd1,0x93,0xef,0xf0,0xab,0x9a,0x80,0x02,0xc4,0x74,0x28,0xa6,0xd3,0x5a,
0x8d,0x88,0xd7,0x9f,0x7f,0x1e,0x3f,0x02,0x03,0x01,0x00,0x01,0xa3,0x1a,0x30,0x18,
0x30,0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0b,0x06,0x03,0x55,
0x1d,0x0f,0x04,0x04,0x03,0x02,0x05,0xa0,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x81,0x81,0x00,0x85,0xaa,0xd2,0xa0,0xe5,
0xb9,0x27,0x6b,0x90,0x8c,0x65,0xf7,0x3a,0x72,0x67,0x17,0x06,0x18,0xa5,0x4c,0x5f,
0x8a,0x7b,0x33,0x7d,0x2d,0xf7,0xa5,0x94,0x36,0x54,0x17,0xf2,0xea,0xe8,0xf8,0xa5,
0x8c,0x8f,0x81,0x72,0xf9,0x31,0x9c,0xf3,0x6b,0x7f,0xd6,0xc5,0x5b,0x80,0xf2,0x1a,
0x03,0x01,0x51,0x56,0x72,0x60,0x96,0xfd,0x33,0x5e,0x5e,0x67,0xf2,0xdb,0xf1,0x02,
0x70,0x2e,0x60,0x8c,0xca,0xe6,0xbe,0xc1,0xfc,0x63,0xa4,0x2a,0x99,0xbe,0x5c,0x3e,
0xb7,0x10,0x7c,0x3c,0x54,0xe9,0xb9,0xeb,0x2b,0xd5,0x20,0x3b,0x1c,0x3b,0x84,0xe0,
0xa8,0xb2,0xf7,0x59,0x40,0x9b,0xa3,0xea,0xc9,0xd9,0x1d,0x40,0x2d,0xcc,0x0c,0xc8,
0xf8,0x96,0x12,0x29,0xac,0x91,0x87,0xb4,0x2b,0x4d,0xe1,0x00,0x00,
/* Server Certificate Verify */
0x0f,0x00,0x00,0x84,0x08,0x04,0x00,0x80,0x5a,0x74,0x7c,0x5d,0x88,0xfa,0x9b,0xd2,
0xe5,0x5a,0xb0,0x85,0xa6,0x10,0x15,0xb7,0x21,0x1f,0x82,0x4c,0xd4,0x84,0x14,0x5a,
0xb3,0xff,0x52,0xf1,0xfd,0xa8,0x47,0x7b,0x0b,0x7a,0xbc,0x90,0xdb,0x78,0xe2,0xd3,
0x3a,0x5c,0x14,0x1a,0x07,0x86,0x53,0xfa,0x6b,0xef,0x78,0x0c,0x5e,0xa2,0x48,0xee,
0xaa,0xa7,0x85,0xc4,0xf3,0x94,0xca,0xb6,0xd3,0x0b,0xbe,0x8d,0x48,0x59,0xee,0x51,
0x1f,0x60,0x29,0x57,0xb1,0x54,0x11,0xac,0x02,0x76,0x71,0x45,0x9e,0x46,0x44,0x5c,
0x9e,0xa5,0x8c,0x18,0x1e,0x81,0x8e,0x95,0xb8,0xc3,0xfb,0x0b,0xf3,0x27,0x84,0x09,
0xd3,0xbe,0x15,0x2a,0x3d,0xa5,0x04,0x3e,0x06,0x3d,0xda,0x65,0xcd,0xf5,0xae,0xa2,
0x0d,0x53,0xdf,0xac,0xd4,0x2f,0x74,0xf3,
/* Server Handshake Finish */
0x14,0x00,0x00,0x20,0x9b,0x9b,0x14,0x1d,0x90,0x63,0x37,0xfb,0xd2,0xcb,0xdc,0xe7,
0x1d,0xf4,0xde,0xda,0x4a,0xb4,0x2c,0x30,0x95,0x72,0xcb,0x7f,0xff,0xee,0x54,0x54,
0xb7,0x8f,0x07,0x18,
);
chunk_t client_finished = chunk_from_chars(
0x14,0x00,0x00,0x20,0xa8,0xec,0x43,0x6d,0x67,0x76,0x34,0xae,0x52,0x5a,0xc1,0xfc,
0xeb,0xe1,0x1a,0x03,0x9e,0xc1,0x76,0x94,0xfa,0xc6,0xe9,0x85,0x27,0xb6,0x42,0xf2,
0xed,0xd5,0xce,0x61,
);
chunk_t ecdhe = chunk_from_chars(
0x8b,0xd4,0x05,0x4f,0xb5,0x5b,0x9d,0x63,0xfd,0xfb,0xac,0xf9,0xf0,0x4b,0x9f,0x0d,
0x35,0xe6,0xd6,0x3f,0x53,0x75,0x63,0xef,0xd4,0x62,0x72,0x90,0x0f,0x89,0x49,0x2d,
);
chunk_t exp_client_handshake_traffic_secret = chunk_from_chars(
0xb3,0xed,0xdb,0x12,0x6e,0x06,0x7f,0x35,0xa7,0x80,0xb3,0xab,0xf4,0x5e,0x2d,0x8f,
0x3b,0x1a,0x95,0x07,0x38,0xf5,0x2e,0x96,0x00,0x74,0x6a,0x0e,0x27,0xa5,0x5a,0x21,
);
chunk_t exp_client_handshake_key = chunk_from_chars(
0xdb,0xfa,0xa6,0x93,0xd1,0x76,0x2c,0x5b,0x66,0x6a,0xf5,0xd9,0x50,0x25,0x8d,0x01,
);
chunk_t exp_client_handshake_iv = chunk_from_chars(
0x5b,0xd3,0xc7,0x1b,0x83,0x6e,0x0b,0x76,0xbb,0x73,0x26,0x5f,
);
chunk_t exp_server_handshake_traffic_secret = chunk_from_chars(
0xb6,0x7b,0x7d,0x69,0x0c,0xc1,0x6c,0x4e,0x75,0xe5,0x42,0x13,0xcb,0x2d,0x37,0xb4,
0xe9,0xc9,0x12,0xbc,0xde,0xd9,0x10,0x5d,0x42,0xbe,0xfd,0x59,0xd3,0x91,0xad,0x38,
);
chunk_t exp_server_handshake_key = chunk_from_chars(
0x3f,0xce,0x51,0x60,0x09,0xc2,0x17,0x27,0xd0,0xf2,0xe4,0xe8,0x6e,0xe4,0x03,0xbc,
);
chunk_t exp_server_handshake_iv = chunk_from_chars(
0x5d,0x31,0x3e,0xb2,0x67,0x12,0x76,0xee,0x13,0x00,0x0b,0x30,
);
chunk_t exp_client_finished_key = chunk_from_chars(
0xb8,0x0a,0xd0,0x10,0x15,0xfb,0x2f,0x0b,0xd6,0x5f,0xf7,0xd4,0xda,0x5d,0x6b,0xf8,
0x3f,0x84,0x82,0x1d,0x1f,0x87,0xfd,0xc7,0xd3,0xc7,0x5b,0x5a,0x7b,0x42,0xd9,0xc4,
);
chunk_t exp_server_finished_key = chunk_from_chars(
0x00,0x8d,0x3b,0x66,0xf8,0x16,0xea,0x55,0x9f,0x96,0xb5,0x37,0xe8,0x85,0xc3,0x1f,
0xc0,0x68,0xbf,0x49,0x2c,0x65,0x2f,0x01,0xf2,0x88,0xa1,0xd8,0xcd,0xc1,0x9f,0xc8,
);
chunk_t exp_client_application_traffic_secret = chunk_from_chars(
0x9e,0x40,0x64,0x6c,0xe7,0x9a,0x7f,0x9d,0xc0,0x5a,0xf8,0x88,0x9b,0xce,0x65,0x52,
0x87,0x5a,0xfa,0x0b,0x06,0xdf,0x00,0x87,0xf7,0x92,0xeb,0xb7,0xc1,0x75,0x04,0xa5,
);
chunk_t exp_client_application_key = chunk_from_chars(
0x17,0x42,0x2d,0xda,0x59,0x6e,0xd5,0xd9,0xac,0xd8,0x90,0xe3,0xc6,0x3f,0x50,0x51,
);
chunk_t exp_client_application_iv = chunk_from_chars(
0x5b,0x78,0x92,0x3d,0xee,0x08,0x57,0x90,0x33,0xe5,0x23,0xd9,
);
chunk_t exp_server_application_traffic_secret = chunk_from_chars(
0xa1,0x1a,0xf9,0xf0,0x55,0x31,0xf8,0x56,0xad,0x47,0x11,0x6b,0x45,0xa9,0x50,0x32,
0x82,0x04,0xb4,0xf4,0x4b,0xfb,0x6b,0x3a,0x4b,0x4f,0x1f,0x3f,0xcb,0x63,0x16,0x43,
);
chunk_t exp_server_application_key = chunk_from_chars(
0x9f,0x02,0x28,0x3b,0x6c,0x9c,0x07,0xef,0xc2,0x6b,0xb9,0xf2,0xac,0x92,0xe3,0x56,
);
chunk_t exp_server_application_iv = chunk_from_chars(
0xcf,0x78,0x2b,0x88,0xdd,0x83,0x54,0x9a,0xad,0xf1,0xe9,0x84,
);
chunk_t exp_generated_resumption_secret = chunk_from_chars(
0x4e,0xcd,0x0e,0xb6,0xec,0x3b,0x4d,0x87,0xf5,0xd6,0x02,0x8f,0x92,0x2c,0xa4,0xc5,
0x85,0x1a,0x27,0x7f,0xd4,0x13,0x11,0xc9,0xe6,0x2d,0x2c,0x94,0x92,0xe1,0xc4,0xf3,
);
chunk_t hs_data;
tls_hkdf_t *hkdf = tls_hkdf_create(HASH_SHA256, chunk_empty);
ck_assert(hkdf);
hkdf->set_shared_secret(hkdf, ecdhe);
/* Generate client handshake traffic secret */
hs_data = chunk_cata("cc", client_hello, server_hello);
check_secret_key_iv(hkdf, TLS_HKDF_C_HS_TRAFFIC, hs_data, FALSE,
exp_client_handshake_traffic_secret, 16, 12,
exp_client_handshake_key,
exp_client_handshake_iv);
check_finished(hkdf, FALSE, exp_client_finished_key);
/* Generate server handshake traffic secret */
check_secret_key_iv(hkdf, TLS_HKDF_S_HS_TRAFFIC, hs_data, TRUE,
exp_server_handshake_traffic_secret, 16, 12,
exp_server_handshake_key,
exp_server_handshake_iv);
check_finished(hkdf, TRUE, exp_server_finished_key);
/* Generate client application traffic secret */
hs_data = chunk_cata("cc", hs_data, server_data);
check_secret_key_iv(hkdf, TLS_HKDF_C_AP_TRAFFIC, hs_data, FALSE,
exp_client_application_traffic_secret, 16, 12,
exp_client_application_key,
exp_client_application_iv);
/* Generate server application traffic secret */
check_secret_key_iv(hkdf, TLS_HKDF_S_AP_TRAFFIC, hs_data, TRUE,
exp_server_application_traffic_secret, 16, 12,
exp_server_application_key,
exp_server_application_iv);
/* Generating resumption master secret */
hs_data = chunk_cata("cc", hs_data, client_finished);
check_resumption(hkdf, hs_data, exp_generated_resumption_secret);
hkdf->destroy(hkdf);
}
END_TEST
START_TEST(test_rfc8448_resumed_0_rtt_handshake)
{
chunk_t client_hello = chunk_from_chars(
0x01,0x00,0x01,0xfc,0x03,0x03,0x1b,0xc3,0xce,0xb6,0xbb,0xe3,0x9c,0xff,0x93,0x83,
0x55,0xb5,0xa5,0x0a,0xdb,0x6d,0xb2,0x1b,0x7a,0x6a,0xf6,0x49,0xd7,0xb4,0xbc,0x41,
0x9d,0x78,0x76,0x48,0x7d,0x95,0x00,0x00,0x06,0x13,0x01,0x13,0x03,0x13,0x02,0x01,
0x00,0x01,0xcd,0x00,0x00,0x00,0x0b,0x00,0x09,0x00,0x00,0x06,0x73,0x65,0x72,0x76,
0x65,0x72,0xff,0x01,0x00,0x01,0x00,0x00,0x0a,0x00,0x14,0x00,0x12,0x00,0x1d,0x00,
0x17,0x00,0x18,0x00,0x19,0x01,0x00,0x01,0x01,0x01,0x02,0x01,0x03,0x01,0x04,0x00,
0x33,0x00,0x26,0x00,0x24,0x00,0x1d,0x00,0x20,0xe4,0xff,0xb6,0x8a,0xc0,0x5f,0x8d,
0x96,0xc9,0x9d,0xa2,0x66,0x98,0x34,0x6c,0x6b,0xe1,0x64,0x82,0xba,0xdd,0xda,0xfe,
0x05,0x1a,0x66,0xb4,0xf1,0x8d,0x66,0x8f,0x0b,0x00,0x2a,0x00,0x00,0x00,0x2b,0x00,
0x03,0x02,0x03,0x04,0x00,0x0d,0x00,0x20,0x00,0x1e,0x04,0x03,0x05,0x03,0x06,0x03,
0x02,0x03,0x08,0x04,0x08,0x05,0x08,0x06,0x04,0x01,0x05,0x01,0x06,0x01,0x02,0x01,
0x04,0x02,0x05,0x02,0x06,0x02,0x02,0x02,0x00,0x2d,0x00,0x02,0x01,0x01,0x00,0x1c,
0x00,0x02,0x40,0x01,0x00,0x15,0x00,0x57,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x29,0x00,0xdd,0x00,0xb8,0x00,0xb2,0x2c,0x03,0x5d,0x82,0x93,0x59,0xee,0x5f,0xf7,
0xaf,0x4e,0xc9,0x00,0x00,0x00,0x00,0x26,0x2a,0x64,0x94,0xdc,0x48,0x6d,0x2c,0x8a,
0x34,0xcb,0x33,0xfa,0x90,0xbf,0x1b,0x00,0x70,0xad,0x3c,0x49,0x88,0x83,0xc9,0x36,
0x7c,0x09,0xa2,0xbe,0x78,0x5a,0xbc,0x55,0xcd,0x22,0x60,0x97,0xa3,0xa9,0x82,0x11,
0x72,0x83,0xf8,0x2a,0x03,0xa1,0x43,0xef,0xd3,0xff,0x5d,0xd3,0x6d,0x64,0xe8,0x61,
0xbe,0x7f,0xd6,0x1d,0x28,0x27,0xdb,0x27,0x9c,0xce,0x14,0x50,0x77,0xd4,0x54,0xa3,
0x66,0x4d,0x4e,0x6d,0xa4,0xd2,0x9e,0xe0,0x37,0x25,0xa6,0xa4,0xda,0xfc,0xd0,0xfc,
0x67,0xd2,0xae,0xa7,0x05,0x29,0x51,0x3e,0x3d,0xa2,0x67,0x7f,0xa5,0x90,0x6c,0x5b,
0x3f,0x7d,0x8f,0x92,0xf2,0x28,0xbd,0xa4,0x0d,0xda,0x72,0x14,0x70,0xf9,0xfb,0xf2,
0x97,0xb5,0xae,0xa6,0x17,0x64,0x6f,0xac,0x5c,0x03,0x27,0x2e,0x97,0x07,0x27,0xc6,
0x21,0xa7,0x91,0x41,0xef,0x5f,0x7d,0xe6,0x50,0x5e,0x5b,0xfb,0xc3,0x88,0xe9,0x33,
0x43,0x69,0x40,0x93,0x93,0x4a,0xe4,0xd3,0x57,0xfa,0xd6,0xaa,0xcb,
);
chunk_t client_hello_hash = chunk_from_chars(
0x63,0x22,0x4b,0x2e,0x45,0x73,0xf2,0xd3,0x45,0x4c,0xa8,0x4b,0x9d,0x00,0x9a,0x04,
0xf6,0xbe,0x9e,0x05,0x71,0x1a,0x83,0x96,0x47,0x3a,0xef,0xa0,0x1e,0x92,0x4a,0x14,
);
chunk_t server_hello = chunk_from_chars(
0x02,0x00,0x00,0x5c,0x03,0x03,0x3c,0xcf,0xd2,0xde,0xc8,0x90,0x22,0x27,0x63,0x47,
0x2a,0xe8,0x13,0x67,0x77,0xc9,0xd7,0x35,0x87,0x77,0xbb,0x66,0xe9,0x1e,0xa5,0x12,
0x24,0x95,0xf5,0x59,0xea,0x2d,0x00,0x13,0x01,0x00,0x00,0x34,0x00,0x29,0x00,0x02,
0x00,0x00,0x00,0x33,0x00,0x24,0x00,0x1d,0x00,0x20,0x12,0x17,0x61,0xee,0x42,0xc3,
0x33,0xe1,0xb9,0xe7,0x7b,0x60,0xdd,0x57,0xc2,0x05,0x3c,0xd9,0x45,0x12,0xab,0x47,
0xf1,0x15,0xe8,0x6e,0xff,0x50,0x94,0x2c,0xea,0x31,0x00,0x2b,0x00,0x02,0x03,0x04,
);
chunk_t encrypted_extension = chunk_from_chars(
0x08,0x00,0x00,0x28,0x00,0x26,0x00,0x0a,0x00,0x14,0x00,0x12,0x00,0x1d,0x00,0x17,
0x00,0x18,0x00,0x19,0x01,0x00,0x01,0x01,0x01,0x02,0x01,0x03,0x01,0x04,0x00,0x1c,
0x00,0x02,0x40,0x01,0x00,0x00,0x00,0x00,0x00,0x2a,0x00,0x00,
);
chunk_t server_finished = chunk_from_chars(
0x14,0x00,0x00,0x20,0x48,0xd3,0xe0,0xe1,0xb3,0xd9,0x07,0xc6,0xac,0xff,0x14,0x5e,
0x16,0x09,0x03,0x88,0xc7,0x7b,0x05,0xc0,0x50,0xb6,0x34,0xab,0x1a,0x88,0xbb,0xd0,
0xdd,0x1a,0x34,0xb2,
);
chunk_t end_of_early_data = chunk_from_chars(
0x05,0x00,0x00,0x00,
);
chunk_t client_finished = chunk_from_chars(
0x14,0x00,0x00,0x20,0x72,0x30,0xa9,0xc9,0x52,0xc2,0x5c,0xd6,0x13,0x8f,0xc5,0xe6,
0x62,0x83,0x08,0xc4,0x1c,0x53,0x35,0xdd,0x81,0xb9,0xf9,0x6b,0xce,0xa5,0x0f,0xd3,
0x2b,0xda,0x41,0x6d,
);
chunk_t psk = chunk_from_chars(
0x4e,0xcd,0x0e,0xb6,0xec,0x3b,0x4d,0x87,0xf5,0xd6,0x02,0x8f,0x92,0x2c,0xa4,0xc5,
0x85,0x1a,0x27,0x7f,0xd4,0x13,0x11,0xc9,0xe6,0x2d,0x2c,0x94,0x92,0xe1,0xc4,0xf3,
);
chunk_t ecdhe = chunk_from_chars(
0xf4,0x41,0x94,0x75,0x6f,0xf9,0xec,0x9d,0x25,0x18,0x06,0x35,0xd6,0x6e,0xa6,0x82,
0x4c,0x6a,0xb3,0xbf,0x17,0x99,0x77,0xbe,0x37,0xf7,0x23,0x57,0x0e,0x7c,0xcb,0x2e,
);
chunk_t exp_psk_binder = chunk_from_chars(
0x3a,0xdd,0x4f,0xb2,0xd8,0xfd,0xf8,0x22,0xa0,0xca,0x3c,0xf7,0x67,0x8e,0xf5,0xe8,
0x8d,0xae,0x99,0x01,0x41,0xc5,0x92,0x4d,0x57,0xbb,0x6f,0xa3,0x1b,0x9e,0x5f,0x9d,
);
chunk_t exp_early_exporter_master_secret = chunk_from_chars(
0xb2,0x02,0x68,0x66,0x61,0x09,0x37,0xd7,0x42,0x3e,0x5b,0xe9,0x08,0x62,0xcc,0xf2,
0x4c,0x0e,0x60,0x91,0x18,0x6d,0x34,0xf8,0x12,0x08,0x9f,0xf5,0xbe,0x2e,0xf7,0xdf,
);
chunk_t exp_client_handshake_traffic_secret = chunk_from_chars(
0x2f,0xaa,0xc0,0x8f,0x85,0x1d,0x35,0xfe,0xa3,0x60,0x4f,0xcb,0x4d,0xe8,0x2d,0xc6,
0x2c,0x9b,0x16,0x4a,0x70,0x97,0x4d,0x04,0x62,0xe2,0x7f,0x1a,0xb2,0x78,0x70,0x0f,
);
chunk_t exp_client_handshake_key = chunk_from_chars(
0xb1,0x53,0x08,0x06,0xf4,0xad,0xfe,0xac,0x83,0xf1,0x41,0x30,0x32,0xbb,0xfa,0x82,
);
chunk_t exp_client_handshake_iv = chunk_from_chars(
0xeb,0x50,0xc1,0x6b,0xe7,0x65,0x4a,0xbf,0x99,0xdd,0x06,0xd9,
);
chunk_t exp_server_handshake_traffic_secret = chunk_from_chars(
0xfe,0x92,0x7a,0xe2,0x71,0x31,0x2e,0x8b,0xf0,0x27,0x5b,0x58,0x1c,0x54,0xee,0xf0,
0x20,0x45,0x0d,0xc4,0xec,0xff,0xaa,0x05,0xa1,0xa3,0x5d,0x27,0x51,0x8e,0x78,0x03,
);
chunk_t exp_server_handshake_key = chunk_from_chars(
0x27,0xc6,0xbd,0xc0,0xa3,0xdc,0xea,0x39,0xa4,0x73,0x26,0xd7,0x9b,0xc9,0xe4,0xee,
);
chunk_t exp_server_handshake_iv = chunk_from_chars(
0x95,0x69,0xec,0xdd,0x4d,0x05,0x36,0x70,0x5e,0x9e,0xf7,0x25,
);
chunk_t exp_server_finished = chunk_from_chars(
0x4b,0xb7,0x4c,0xae,0x7a,0x5d,0xc8,0x91,0x46,0x04,0xc0,0xbf,0xbe,0x2f,0x0c,0x06,
0x23,0x96,0x88,0x39,0x22,0xbe,0xc8,0xa1,0x5e,0x2a,0x9b,0x53,0x2a,0x5d,0x39,0x2c,
);
chunk_t exp_client_finished = chunk_from_chars(
0x5a,0xce,0x39,0x4c,0x26,0x98,0x0d,0x58,0x12,0x43,0xf6,0x27,0xd1,0x15,0x0a,0xe2,
0x7e,0x37,0xfa,0x52,0x36,0x4e,0x0a,0x7f,0x20,0xac,0x68,0x6d,0x09,0xcd,0x0e,0x8e,
);
chunk_t exp_client_application_traffic_secret = chunk_from_chars(
0x2a,0xbb,0xf2,0xb8,0xe3,0x81,0xd2,0x3d,0xbe,0xbe,0x1d,0xd2,0xa7,0xd1,0x6a,0x8b,
0xf4,0x84,0xcb,0x49,0x50,0xd2,0x3f,0xb7,0xfb,0x7f,0xa8,0x54,0x70,0x62,0xd9,0xa1,
);
chunk_t exp_client_application_key = chunk_from_chars(
0x3c,0xf1,0x22,0xf3,0x01,0xc6,0x35,0x8c,0xa7,0x98,0x95,0x53,0x25,0x0e,0xfd,0x72,
);
chunk_t exp_client_application_iv = chunk_from_chars(
0xab,0x1a,0xec,0x26,0xaa,0x78,0xb8,0xfc,0x11,0x76,0xb9,0xac,
);
chunk_t exp_server_application_traffic_secret = chunk_from_chars(
0xcc,0x21,0xf1,0xbf,0x8f,0xeb,0x7d,0xd5,0xfa,0x50,0x5b,0xd9,0xc4,0xb4,0x68,0xa9,
0x98,0x4d,0x55,0x4a,0x99,0x3d,0xc4,0x9e,0x6d,0x28,0x55,0x98,0xfb,0x67,0x26,0x91,
);
chunk_t exp_server_application_key = chunk_from_chars(
0xe8,0x57,0xc6,0x90,0xa3,0x4c,0x5a,0x91,0x29,0xd8,0x33,0x61,0x96,0x84,0xf9,0x5e
);
chunk_t exp_server_application_iv = chunk_from_chars(
0x06,0x85,0xd6,0xb5,0x61,0xaa,0xb9,0xef,0x10,0x13,0xfa,0xf9,
);
chunk_t exp_exporter_master_secret = chunk_from_chars(
0x3f,0xd9,0x3d,0x4f,0xfd,0xdc,0x98,0xe6,0x4b,0x14,0xdd,0x10,0x7a,0xed,0xf8,0xee,
0x4a,0xdd,0x23,0xf4,0x51,0x0f,0x58,0xa4,0x59,0x2d,0x0b,0x20,0x1b,0xee,0x56,0xb4,
);
chunk_t exp_resumption_master_secret = chunk_from_chars(
0x5e,0x95,0xbd,0xf1,0xf8,0x90,0x05,0xea,0x2e,0x9a,0xa0,0xba,0x85,0xe7,0x28,0xe3,
0xc1,0x9c,0x5f,0xe0,0xc6,0x99,0xe3,0xf5,0xbe,0xe5,0x9f,0xae,0xbd,0x0b,0x54,0x06,
);
chunk_t hs_data, psk_binder;
tls_hkdf_t *hkdf = tls_hkdf_create(HASH_SHA256, psk);
ck_assert(hkdf);
ck_assert(hkdf->binder(hkdf, client_hello_hash, &psk_binder));
ck_assert_chunk_eq(exp_psk_binder, psk_binder);
/* PSK binder is wrapped first with 0x20 and then with 0x00,0x21 length bytes*/
hs_data = chunk_cata("ccc", client_hello, chunk_from_chars(0x00,0x21,0x20),
psk_binder);
check_secret(hkdf, TLS_HKDF_E_EXP_MASTER, hs_data, exp_early_exporter_master_secret);
hkdf->set_shared_secret(hkdf, ecdhe);
/* Generate client handshake traffic secret */
hs_data = chunk_cata("cc", hs_data, server_hello);
check_secret_key_iv(hkdf, TLS_HKDF_C_HS_TRAFFIC, hs_data, FALSE,
exp_client_handshake_traffic_secret, 16, 12,
exp_client_handshake_key,
exp_client_handshake_iv);
/* Generate sever handshake traffic secret */
check_secret_key_iv(hkdf, TLS_HKDF_S_HS_TRAFFIC, hs_data, TRUE,
exp_server_handshake_traffic_secret, 16, 12,
exp_server_handshake_key,
exp_server_handshake_iv);
check_finished(hkdf, TRUE, exp_server_finished);
check_finished(hkdf, FALSE, exp_client_finished);
/* Generate client application traffic secret */
hs_data = chunk_cata("ccc", hs_data, encrypted_extension, server_finished);
check_secret_key_iv(hkdf, TLS_HKDF_C_AP_TRAFFIC, hs_data, FALSE,
exp_client_application_traffic_secret, 16, 12,
exp_client_application_key,
exp_client_application_iv);
/* Generate server application traffic secret */
check_secret_key_iv(hkdf, TLS_HKDF_S_AP_TRAFFIC, hs_data, TRUE,
exp_server_application_traffic_secret, 16, 12,
exp_server_application_key,
exp_server_application_iv);
check_secret(hkdf, TLS_HKDF_EXP_MASTER, hs_data, exp_exporter_master_secret);
hs_data = chunk_cata("ccc", hs_data, end_of_early_data, client_finished);
check_secret(hkdf, TLS_HKDF_RES_MASTER, hs_data, exp_resumption_master_secret);
hkdf->destroy(hkdf);
chunk_free(&psk_binder);
}
END_TEST
Suite *hkdf_suite_create()
{
Suite *s;
TCase *tc;
s = suite_create("HKDF TLS 1.3");
tc = tcase_create("Ulfheim Keys");
tcase_add_test(tc, test_ulfheim_handshake);
tcase_add_test(tc, test_ulfheim_traffic);
suite_add_tcase(s, tc);
tc = tcase_create("RFC 8448");
tcase_add_test(tc, test_rfc8448_simple_1_rtt_handshake);
tcase_add_test(tc, test_rfc8448_resumed_0_rtt_handshake);
suite_add_tcase(s, tc);
return s;
}

View File

@ -1,4 +1,7 @@
/*
* Copyright (C) 2020-2021 Pascal Knecht
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@ -126,6 +129,28 @@ static char ecdsa[] = {
0xb1,0x47,0xc8,0xf6,0x18,0xbb,0x97,
};
/**
* Ed25519 private key
* pki --gen --type ed25519
*/
static char ed25519[] = {
0x30,0x2e,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x70,0x04,0x22,0x04,0x20,
0x70,0x4b,0xca,0x70,0x1c,0xb1,0x75,0xf1,0xed,0xde,0xf1,0x99,0x8e,0x11,0x32,0x2d,
0x76,0x41,0x01,0x6c,0xd7,0xbc,0x79,0xa2,0x06,0x15,0x7e,0x44,0x28,0xf2,0x49,0x61,
};
/**
* Ed448 private key
* pki --gen --type ed448
*/
static char ed448[] = {
0x30,0x47,0x02,0x01,0x00,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x04,0x3b,0x04,0x39,
0xcf,0xb9,0xbe,0x75,0xdf,0x76,0x8b,0x9a,0xdf,0x56,0x52,0x5d,0x37,0x7d,0xb0,0xa8,
0x1f,0x19,0x44,0x30,0xbd,0x9d,0x0e,0xff,0x5f,0xc8,0xc3,0xec,0x60,0xd5,0xf6,0xa4,
0x3d,0x1f,0x0e,0xb5,0x65,0x6e,0xe6,0x62,0x4d,0xb7,0xe7,0x5c,0x88,0x7b,0xe8,0xdd,
0x02,0xd9,0x0f,0xaa,0xe7,0xfb,0x05,0x14,0x41,
};
/**
* TLS certificate for RSA key
* pki --self --in rsa.key --dn "C=CH, O=strongSwan, CN=tls-rsa" --san 127.0.0.1
@ -217,12 +242,77 @@ static char ecdsa_crt[] = {
0xac,0x36,0x08,0x14,0x29,
};
START_SETUP(setup_creds)
/**
* TLS certificate for Ed25519 key
* pki --self --in ed25519.key --dn "C=CH, O=strongSwan, CN=tls-ed25519" \
* --san 127.0.0.1
*/
static char ed25519_crt[] = {
0x30,0x82,0x01,0x38,0x30,0x81,0xeb,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x46,0x41,
0x12,0x0d,0xa4,0xbd,0x00,0x11,0x30,0x05,0x06,0x03,0x2b,0x65,0x70,0x30,0x38,0x31,
0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,
0x06,0x03,0x55,0x04,0x0a,0x13,0x0a,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,
0x6e,0x31,0x14,0x30,0x12,0x06,0x03,0x55,0x04,0x03,0x13,0x0b,0x74,0x6c,0x73,0x2d,
0x65,0x64,0x32,0x35,0x35,0x31,0x39,0x30,0x1e,0x17,0x0d,0x32,0x30,0x31,0x30,0x32,
0x32,0x31,0x34,0x30,0x31,0x30,0x30,0x5a,0x17,0x0d,0x32,0x33,0x31,0x30,0x32,0x32,
0x31,0x34,0x30,0x31,0x30,0x30,0x5a,0x30,0x38,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x13,
0x0a,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x14,0x30,0x12,0x06,
0x03,0x55,0x04,0x03,0x13,0x0b,0x74,0x6c,0x73,0x2d,0x65,0x64,0x32,0x35,0x35,0x31,
0x39,0x30,0x2a,0x30,0x05,0x06,0x03,0x2b,0x65,0x70,0x03,0x21,0x00,0xbd,0xbd,0xd2,
0x9d,0x90,0x2c,0x4f,0xb0,0x0d,0x88,0xe9,0x92,0xba,0x59,0x91,0x6c,0x0a,0x30,0xc3,
0x8e,0x7d,0x0d,0x55,0x67,0xf7,0xb0,0x37,0x39,0xfa,0x05,0x61,0xc3,0xa3,0x13,0x30,
0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x11,0x04,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,
0x00,0x01,0x30,0x05,0x06,0x03,0x2b,0x65,0x70,0x03,0x41,0x00,0x04,0xc6,0x12,0x57,
0xfa,0x69,0x74,0xd2,0x3a,0x7d,0x1b,0x23,0xde,0x64,0x08,0xa8,0x05,0x75,0xd3,0x15,
0xfb,0xd4,0x46,0xe0,0x4a,0x59,0x48,0x8e,0xee,0x4e,0x4d,0x72,0xbf,0xbc,0xdb,0x36,
0xda,0x39,0x23,0x9a,0x06,0x88,0xee,0x63,0xe5,0xb4,0x23,0xf9,0xa9,0x80,0x41,0x99,
0x3d,0x3f,0xb5,0x39,0x72,0x4b,0x62,0x86,0x4e,0x85,0x61,0x0b,
};
/**
* TLS certificate for Ed448 key
* pki --self --in ed448.key --dn "C=CH, O=strongSwan, CN=tls-ed448" \
* --san 127.0.0.1
*/
static char ed448_crt[] = {
0x30,0x82,0x01,0x80,0x30,0x82,0x01,0x00,0xa0,0x03,0x02,0x01,0x02,0x02,0x08,0x71,
0xa9,0xa0,0xdd,0x5b,0xee,0xa0,0x5c,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x30,0x36,
0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,
0x11,0x06,0x03,0x55,0x04,0x0a,0x13,0x0a,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,
0x61,0x6e,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x74,0x6c,0x73,
0x2d,0x65,0x64,0x34,0x34,0x38,0x30,0x1e,0x17,0x0d,0x32,0x30,0x31,0x30,0x32,0x33,
0x32,0x30,0x34,0x34,0x30,0x35,0x5a,0x17,0x0d,0x32,0x33,0x31,0x30,0x32,0x33,0x32,
0x30,0x34,0x34,0x30,0x35,0x5a,0x30,0x36,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,
0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x13,0x0a,
0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x12,0x30,0x10,0x06,0x03,
0x55,0x04,0x03,0x13,0x09,0x74,0x6c,0x73,0x2d,0x65,0x64,0x34,0x34,0x38,0x30,0x43,
0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,0x3a,0x00,0xdd,0x5e,0x19,0xc8,0x67,0xa9,
0x93,0x53,0x5f,0x26,0xca,0x6f,0x2f,0xdf,0x9e,0x0f,0x48,0xb6,0x60,0x3e,0x56,0xa5,
0xaf,0xe8,0xf9,0x3f,0xe5,0x1c,0xeb,0xf2,0xf4,0x84,0xd1,0x48,0xa9,0xb1,0x92,0x6b,
0xa1,0x4d,0x47,0x86,0x8e,0xf9,0xcc,0xd2,0x58,0xd4,0x6f,0x8c,0x76,0x59,0xf4,0x77,
0x59,0xc8,0x00,0xa3,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x11,0x04,0x08,
0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01,0x30,0x05,0x06,0x03,0x2b,0x65,0x71,0x03,
0x73,0x00,0xc6,0xf0,0x4e,0xf2,0x41,0xe0,0xb4,0xa0,0x0a,0x9f,0x73,0x67,0xcb,0x89,
0x97,0xf0,0x3a,0xfe,0x53,0xb2,0x1b,0x6c,0x37,0x24,0xbe,0x9e,0x2b,0x50,0x0c,0x98,
0xb3,0x15,0x65,0x79,0x37,0xd6,0xc2,0x92,0x89,0x96,0xf3,0x5f,0x2d,0x70,0xa5,0x49,
0xdd,0x7d,0x12,0x3d,0x17,0x28,0xd2,0x56,0x25,0xab,0x80,0x89,0x4d,0x6a,0xfa,0x32,
0x6a,0x16,0x7f,0xd2,0x12,0xb3,0x73,0xf5,0xe7,0x1f,0x89,0x0b,0x5e,0x05,0xbe,0x69,
0xb8,0x11,0x59,0xf9,0xdc,0x9c,0xca,0x68,0xe3,0x1f,0x7a,0x43,0x1a,0x72,0xfa,0x1f,
0x07,0xe0,0x58,0xc2,0x3a,0x18,0xb3,0x01,0x68,0x90,0x40,0x05,0x7d,0x35,0x1a,0x3f,
0xdc,0xc8,0x00,0x00
};
static void setup_credentials(chunk_t key_data, chunk_t cert_data)
{
private_key_t *key;
certificate_t *cert;
creds = mem_cred_create();
if (!creds)
{
creds = mem_cred_create();
lib->credmgr->add_set(lib->credmgr, &creds->set);
}
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
BUILD_BLOB, chunk_from_thing(rsa), BUILD_END);
@ -230,8 +320,8 @@ START_SETUP(setup_creds)
{
creds->add_key(creds, key);
}
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
BUILD_BLOB, chunk_from_thing(ecdsa), BUILD_END);
key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
BUILD_BLOB, key_data, BUILD_END);
if (key)
{
creds->add_key(creds, key);
@ -243,13 +333,36 @@ START_SETUP(setup_creds)
creds->add_cert(creds, TRUE, cert);
}
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB, chunk_from_thing(ecdsa_crt), BUILD_END);
BUILD_BLOB, cert_data, BUILD_END);
if (cert)
{
creds->add_cert(creds, TRUE, cert);
}
}
lib->credmgr->add_set(lib->credmgr, &creds->set);
START_SETUP(setup_creds)
{
setup_credentials(chunk_from_thing(ecdsa), chunk_from_thing(ecdsa_crt));
}
END_SETUP
START_SETUP(setup_ed25519_creds)
{
setup_credentials(chunk_from_thing(ed25519), chunk_from_thing(ed25519_crt));
}
END_SETUP
START_SETUP(setup_ed448_creds)
{
setup_credentials(chunk_from_thing(ed448), chunk_from_thing(ed448_crt));
}
END_SETUP
START_SETUP(setup_all_creds)
{
setup_credentials(chunk_from_thing(ecdsa), chunk_from_thing(ecdsa_crt));
setup_credentials(chunk_from_thing(ed25519), chunk_from_thing(ed25519_crt));
setup_credentials(chunk_from_thing(ed448), chunk_from_thing(ed448_crt));
}
END_SETUP
@ -257,6 +370,7 @@ START_TEARDOWN(teardown_creds)
{
lib->credmgr->remove_set(lib->credmgr, &creds->set);
creds->destroy(creds);
creds = NULL;
}
END_TEARDOWN
@ -298,7 +412,7 @@ static job_requeue_t serve_echo(echo_server_config_t *config)
}
tls = tls_socket_create(TRUE, server, client, cfd, NULL,
config->version, TRUE);
TLS_SUPPORTED_MIN, config->version, TRUE);
ck_assert(tls != NULL);
while (TRUE)
@ -374,7 +488,7 @@ static void run_echo_client(echo_server_config_t *config)
ck_assert(connect(fd, host->get_sockaddr(host),
*host->get_sockaddr_len(host)) != -1);
tls = tls_socket_create(FALSE, server, client, fd, NULL,
config->version, TRUE);
TLS_SUPPORTED_MIN, config->version, TRUE);
ck_assert(tls != NULL);
wr = rd = 0;
@ -406,6 +520,24 @@ static void run_echo_client(echo_server_config_t *config)
server->destroy(server);
}
/**
* Create server/peer configuration
*/
static echo_server_config_t *create_config(tls_version_t version, uint16_t port,
bool cauth)
{
echo_server_config_t *config;
INIT(config,
.version = version,
.addr = "127.0.0.1",
.port = port,
.cauth = cauth,
.data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08),
);
return config;
}
/**
* Common test wrapper function for different test variants
*/
@ -416,18 +548,11 @@ static void test_tls(tls_version_t version, uint16_t port, bool cauth, u_int i)
char suite[128];
int count;
INIT(config,
.version = version,
.addr = "127.0.0.1",
.port = port,
.cauth = cauth,
.data = chunk_from_chars(0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08),
);
config = create_config(version, port, cauth);
start_echo_server(config);
count = tls_crypto_get_supported_suites(TRUE, &suites);
count = tls_crypto_get_supported_suites(TRUE, version, &suites);
ck_assert(i < count);
snprintf(suite, sizeof(suite), "%N", tls_cipher_suite_names, suites[i]);
lib->settings->set_str(lib->settings, "%s.tls.suites", suite, lib->ns);
@ -442,6 +567,176 @@ static void test_tls(tls_version_t version, uint16_t port, bool cauth, u_int i)
free(config);
}
/**
* TLS curve test wrapper function
*/
static void test_tls_ke_groups(tls_version_t version, uint16_t port, bool cauth,
u_int i)
{
echo_server_config_t *config;
diffie_hellman_group_t *groups;
char curve[128];
int count;
config = create_config(version, port, cauth);
start_echo_server(config);
count = tls_crypto_get_supported_groups(&groups);
ck_assert(i < count);
snprintf(curve, sizeof(curve), "%N", diffie_hellman_group_names_short,
groups[i]);
lib->settings->set_str(lib->settings, "%s.tls.ke_group", curve, lib->ns);
run_echo_client(config);
free(groups);
shutdown(config->fd, SHUT_RDWR);
close(config->fd);
free(config);
}
/**
* TLS signature test wrapper function
*/
static void test_tls_signature_schemes(tls_version_t version, uint16_t port,
bool cauth, u_int i)
{
echo_server_config_t *config;
tls_signature_scheme_t *schemes;
char signature[128];
int count;
config = create_config(version, port, cauth);
start_echo_server(config);
count = tls_crypto_get_supported_signatures(version, &schemes);
ck_assert(i < count);
snprintf(signature, sizeof(signature), "%N", tls_signature_scheme_names,
schemes[i]);
lib->settings->set_str(lib->settings, "%s.tls.signature", signature, lib->ns);
run_echo_client(config);
free(schemes);
shutdown(config->fd, SHUT_RDWR);
close(config->fd);
free(config);
}
/**
* TLS server version test wrapper function
*/
static void test_tls_server(tls_version_t version, uint16_t port, bool cauth,
u_int i)
{
echo_server_config_t *client, *server;
client = create_config(i, port, cauth);
server = create_config(version, port, cauth);
start_echo_server(server);
run_echo_client(client);
shutdown(client->fd, SHUT_RDWR);
close(client->fd);
shutdown(server->fd, SHUT_RDWR);
close(server->fd);
free(client);
free(server);
}
/**
* TLS client version test wrapper function
*/
static void test_tls_client(tls_version_t version, uint16_t port, bool cauth,
u_int i)
{
echo_server_config_t *client, *server;
client = create_config(version, port, cauth);
server = create_config(i, port, cauth);
start_echo_server(server);
run_echo_client(client);
shutdown(client->fd, SHUT_RDWR);
close(client->fd);
shutdown(server->fd, SHUT_RDWR);
close(server->fd);
free(client);
free(server);
}
START_TEST(test_tls_12_server)
{
test_tls_server(TLS_1_2, 5661, FALSE, _i);
}
END_TEST
START_TEST(test_tls_13_server)
{
test_tls_server(TLS_1_3, 5662, FALSE, _i);
}
END_TEST
START_TEST(test_tls_13_client)
{
test_tls_client(TLS_1_3, 5663, FALSE, _i);
}
END_TEST
START_TEST(test_tls13_ke_groups)
{
test_tls_ke_groups(TLS_1_3, 5664, FALSE, _i);
}
END_TEST
START_TEST(test_tls13_signature_schemes)
{
test_tls_signature_schemes(TLS_1_3, 5665, FALSE, _i);
}
END_TEST
START_TEST(test_tls12_signature_schemes)
{
test_tls_signature_schemes(TLS_1_2, 5666, FALSE, _i);
}
END_TEST
START_TEST(test_tls11_signature_schemes)
{
test_tls_signature_schemes(TLS_1_1, 5667, FALSE, _i);
}
END_TEST
START_TEST(test_tls10_signature_schemes)
{
test_tls_signature_schemes(TLS_1_0, 5668, FALSE, _i);
}
END_TEST
START_TEST(test_tls13)
{
test_tls(TLS_1_3, 5669, FALSE, _i);
}
END_TEST
START_TEST(test_tls13_mutual)
{
test_tls(TLS_1_3, 5670, TRUE, _i);
}
END_TEST
START_TEST(test_tls12)
{
test_tls(TLS_1_2, 5671, FALSE, _i);
@ -478,44 +773,163 @@ START_TEST(test_tls10_mutual)
}
END_TEST
#define add_tls_test(func, version) \
tcase_add_loop_test(tc, func, 0, \
tls_crypto_get_supported_suites(TRUE, version, NULL));
#define add_tls_versions_test(func, from, to) \
tcase_add_loop_test(tc, func, from, to+1);
Suite *socket_suite_create()
{
Suite *s;
TCase *tc;
int count;
count = tls_crypto_get_supported_suites(TRUE, NULL);
s = suite_create("socket");
tc = tcase_create("TLS [1.0..1.3] client to TLS 1.3 server");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
add_tls_versions_test(test_tls_13_server, TLS_1_0, TLS_1_3);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.3 client to TLS [1.0..1.3] server");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
add_tls_versions_test(test_tls_13_client, TLS_1_0, TLS_1_3);
suite_add_tcase(s, tc);
tc = tcase_create("TLS [1.0..1.3] client to TLS 1.2 server");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
add_tls_versions_test(test_tls_12_server, TLS_1_0, TLS_1_3);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.3/key exchange groups");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls13_ke_groups, 0,
tls_crypto_get_supported_groups(NULL));
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.3/signature schemes");
tcase_add_checked_fixture(tc, setup_all_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls13_signature_schemes, 0,
tls_crypto_get_supported_signatures(TLS_1_3, NULL));
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.2/signature schemes");
tcase_add_checked_fixture(tc, setup_all_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls12_signature_schemes, 0,
tls_crypto_get_supported_signatures(TLS_1_2, NULL));
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.1/signature schemes");
tcase_add_checked_fixture(tc, setup_all_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls11_signature_schemes, 0,
tls_crypto_get_supported_signatures(TLS_1_1, NULL));
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.0/signature schemes");
tcase_add_checked_fixture(tc, setup_all_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls10_signature_schemes, 0,
tls_crypto_get_supported_signatures(TLS_1_0, NULL));
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.3/anon");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
add_tls_test(test_tls13, TLS_1_3);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.3/mutl");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
add_tls_test(test_tls13_mutual, TLS_1_3);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.2/anon");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls12, 0, count);
add_tls_test(test_tls12, TLS_1_2);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.2/mutl");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls12_mutual, 0, count);
add_tls_test(test_tls12_mutual, TLS_1_2);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.1/anon");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls11, 0, count);
add_tls_test(test_tls11, TLS_1_1);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.1/mutl");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls11_mutual, 0, count);
add_tls_test(test_tls11_mutual, TLS_1_1);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.0/anon");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls10, 0, count);
add_tls_test(test_tls10, TLS_1_0);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.0/mutl");
tcase_add_checked_fixture(tc, setup_creds, teardown_creds);
tcase_add_loop_test(tc, test_tls10_mutual, 0, count);
add_tls_test(test_tls10_mutual, TLS_1_0);
suite_add_tcase(s, tc);
return s;
}
Suite *socket_suite_ed25519_create()
{
Suite *s;
TCase *tc;
s = suite_create("socket ed25519");
tc = tcase_create("TLS 1.3/ed25519");
tcase_add_checked_fixture(tc, setup_ed25519_creds, teardown_creds);
add_tls_test(test_tls13, TLS_1_3);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.2/ed25519");
tcase_add_checked_fixture(tc, setup_ed25519_creds, teardown_creds);
add_tls_test(test_tls12, TLS_1_2);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.1/ed25519");
tcase_add_checked_fixture(tc, setup_ed25519_creds, teardown_creds);
add_tls_test(test_tls11, TLS_1_1);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.0/ed25519");
tcase_add_checked_fixture(tc, setup_ed25519_creds, teardown_creds);
add_tls_test(test_tls10, TLS_1_0);
suite_add_tcase(s, tc);
return s;
}
Suite *socket_suite_ed448_create()
{
Suite *s;
TCase *tc;
s = suite_create("socket ed448");
tc = tcase_create("TLS 1.3/ed448");
tcase_add_checked_fixture(tc, setup_ed448_creds, teardown_creds);
add_tls_test(test_tls13, TLS_1_3);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.2/ed448");
tcase_add_checked_fixture(tc, setup_ed448_creds, teardown_creds);
add_tls_test(test_tls12, TLS_1_2);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.1/ed448");
tcase_add_checked_fixture(tc, setup_ed448_creds, teardown_creds);
add_tls_test(test_tls11, TLS_1_1);
suite_add_tcase(s, tc);
tc = tcase_create("TLS 1.0/ed448");
tcase_add_checked_fixture(tc, setup_ed448_creds, teardown_creds);
add_tls_test(test_tls10, TLS_1_0);
suite_add_tcase(s, tc);
return s;

View File

@ -1,4 +1,7 @@
/*
* Copyright (C) 2020 Pascal Knecht
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@ -170,6 +173,11 @@ START_TEST(test_cipher_names)
CHECK_NAME(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256);
CHECK_NAME(TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256);
CHECK_NAME(TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
CHECK_NAME(TLS_AES_128_GCM_SHA256);
CHECK_NAME(TLS_AES_256_GCM_SHA384);
CHECK_NAME(TLS_CHACHA20_POLY1305_SHA256);
CHECK_NAME(TLS_AES_128_CCM_SHA256);
CHECK_NAME(TLS_AES_128_CCM_8_SHA256);
CHECK_NAME(TLS_ECDH_ECDSA_WITH_NULL_SHA);
CHECK_NAME(TLS_ECDH_ECDSA_WITH_RC4_128_SHA);
CHECK_NAME(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA);
@ -229,6 +237,9 @@ START_TEST(test_cipher_names)
CHECK_NAME(TLS_ECDHE_PSK_WITH_NULL_SHA);
CHECK_NAME(TLS_ECDHE_PSK_WITH_NULL_SHA256);
CHECK_NAME(TLS_ECDHE_PSK_WITH_NULL_SHA384);
CHECK_NAME(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
CHECK_NAME(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
CHECK_NAME(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
}
END_TEST

View File

@ -35,8 +35,13 @@ static bool test_runner_init(bool init)
{
if (init)
{
plugin_loader_add_plugindirs(PLUGINDIR, PLUGINS);
if (!lib->plugins->load(lib->plugins, PLUGINS))
char *plugins;
plugins = getenv("TESTS_PLUGINS") ?:
lib->settings->get_str(lib->settings,
"tests.load", PLUGINS);
plugin_loader_add_plugindirs(PLUGINDIR, plugins);
if (!lib->plugins->load(lib->plugins, plugins))
{
return FALSE;
}

View File

@ -13,5 +13,8 @@
* for more details.
*/
TEST_SUITE(hkdf_suite_create)
TEST_SUITE(socket_suite_create)
TEST_SUITE_DEPEND(socket_suite_ed25519_create, PRIVKEY_GEN, KEY_ED25519)
TEST_SUITE_DEPEND(socket_suite_ed448_create, PRIVKEY_GEN, KEY_ED448)
TEST_SUITE(suites_suite_create)

View File

@ -1,4 +1,8 @@
/*
* Copyright (C) 2021 Tobias Brunner
* Copyright (C) 2020-2021 Pascal Knecht
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@ -24,14 +28,26 @@
#include "tls_server.h"
#include "tls_peer.h"
ENUM_BEGIN(tls_version_names, SSL_2_0, SSL_2_0,
ENUM_BEGIN(tls_version_names, TLS_UNSPEC, TLS_UNSPEC,
"TLS UNSPEC");
ENUM_NEXT(tls_version_names, SSL_2_0, SSL_2_0, TLS_UNSPEC,
"SSLv2");
ENUM_NEXT(tls_version_names, SSL_3_0, TLS_1_2, SSL_2_0,
ENUM_NEXT(tls_version_names, SSL_3_0, TLS_1_3, SSL_2_0,
"SSLv3",
"TLS 1.0",
"TLS 1.1",
"TLS 1.2");
ENUM_END(tls_version_names, TLS_1_2);
"TLS 1.2",
"TLS 1.3");
ENUM_END(tls_version_names, TLS_1_3);
/**
* Only supported versions are mapped
*/
ENUM(tls_numeric_version_names, TLS_SUPPORTED_MIN, TLS_SUPPORTED_MAX,
"1.0",
"1.1",
"1.2",
"1.3");
ENUM(tls_content_type_names, TLS_CHANGE_CIPHER_SPEC, TLS_APPLICATION_DATA,
"ChangeCipherSpec",
@ -40,12 +56,22 @@ ENUM(tls_content_type_names, TLS_CHANGE_CIPHER_SPEC, TLS_APPLICATION_DATA,
"ApplicationData",
);
ENUM_BEGIN(tls_handshake_type_names, TLS_HELLO_REQUEST, TLS_SERVER_HELLO,
"HelloRequest",
"ClientHello",
"ServerHello");
ENUM_BEGIN(tls_handshake_type_names, TLS_HELLO_REQUEST, TLS_HELLO_REQUEST,
"HelloRequest");
ENUM_NEXT(tls_handshake_type_names,
TLS_CERTIFICATE, TLS_CLIENT_KEY_EXCHANGE, TLS_SERVER_HELLO,
TLS_CLIENT_HELLO, TLS_HELLO_RETRY_REQUEST, TLS_HELLO_REQUEST,
"ClientHello",
"ServerHello",
"HelloVerifyRequest",
"NewSessionTicket",
"EndOfEarlyData",
"HelloRetryRequest");
ENUM_NEXT(tls_handshake_type_names,
TLS_ENCRYPTED_EXTENSIONS, TLS_ENCRYPTED_EXTENSIONS,
TLS_HELLO_RETRY_REQUEST,
"EncryptedExtensions");
ENUM_NEXT(tls_handshake_type_names,
TLS_CERTIFICATE, TLS_CLIENT_KEY_EXCHANGE, TLS_ENCRYPTED_EXTENSIONS,
"Certificate",
"ServerKeyExchange",
"CertificateRequest",
@ -53,9 +79,16 @@ ENUM_NEXT(tls_handshake_type_names,
"CertificateVerify",
"ClientKeyExchange");
ENUM_NEXT(tls_handshake_type_names,
TLS_FINISHED, TLS_FINISHED, TLS_CLIENT_KEY_EXCHANGE,
"Finished");
ENUM_END(tls_handshake_type_names, TLS_FINISHED);
TLS_FINISHED, TLS_KEY_UPDATE, TLS_CLIENT_KEY_EXCHANGE,
"Finished",
"CertificateUrl",
"CertificateStatus",
"SupplementalData",
"KeyUpdate");
ENUM_NEXT(tls_handshake_type_names,
TLS_MESSAGE_HASH, TLS_MESSAGE_HASH, TLS_KEY_UPDATE,
"MessageHash");
ENUM_END(tls_handshake_type_names, TLS_MESSAGE_HASH);
ENUM_BEGIN(tls_extension_names, TLS_EXT_SERVER_NAME, TLS_EXT_STATUS_REQUEST,
"server name",
@ -65,20 +98,68 @@ ENUM_BEGIN(tls_extension_names, TLS_EXT_SERVER_NAME, TLS_EXT_STATUS_REQUEST,
"truncated hmac",
"status request");
ENUM_NEXT(tls_extension_names,
TLS_EXT_ELLIPTIC_CURVES, TLS_EXT_EC_POINT_FORMATS,
TLS_EXT_SUPPORTED_GROUPS, TLS_EXT_EC_POINT_FORMATS,
TLS_EXT_STATUS_REQUEST,
"elliptic curves",
"supported groups",
"ec point formats");
ENUM_NEXT(tls_extension_names,
TLS_EXT_SIGNATURE_ALGORITHMS, TLS_EXT_SIGNATURE_ALGORITHMS,
TLS_EXT_SIGNATURE_ALGORITHMS,
TLS_EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION,
TLS_EXT_EC_POINT_FORMATS,
"signature algorithms");
"signature algorithms",
"use rtp",
"heartbeat",
"application layer protocol negotiation");
ENUM_NEXT(tls_extension_names,
TLS_CLIENT_CERTIFICATE_TYPE, TLS_SERVER_CERTIFICATE_TYPE,
TLS_EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION,
"client certificate type",
"server certificate type");
ENUM_NEXT(tls_extension_names,
TLS_EXT_ENCRYPT_THEN_MAC, TLS_EXT_EXTENDED_MASTER_SECRET,
TLS_SERVER_CERTIFICATE_TYPE,
"encrypt-then-mac",
"extended master secret");
ENUM_NEXT(tls_extension_names,
TLS_EXT_SESSION_TICKET, TLS_EXT_SESSION_TICKET,
TLS_EXT_EXTENDED_MASTER_SECRET,
"session ticket");
ENUM_NEXT(tls_extension_names,
TLS_EXT_PRE_SHARED_KEY, TLS_EXT_PSK_KEY_EXCHANGE_MODES,
TLS_EXT_SESSION_TICKET,
"pre-shared key",
"early data",
"supported versions",
"cookie",
"psk key exchange modes");
ENUM_NEXT(tls_extension_names,
TLS_EXT_CERTIFICATE_AUTHORITIES, TLS_EXT_KEY_SHARE,
TLS_EXT_PSK_KEY_EXCHANGE_MODES,
"certificate authorities",
"oid filters",
"post-handshake auth",
"signature algorithms cert",
"key-share");
ENUM_NEXT(tls_extension_names,
TLS_EXT_RENEGOTIATION_INFO, TLS_EXT_RENEGOTIATION_INFO,
TLS_EXT_SIGNATURE_ALGORITHMS,
TLS_EXT_KEY_SHARE,
"renegotiation info");
ENUM_END(tls_extension_names, TLS_EXT_RENEGOTIATION_INFO);
chunk_t tls_hello_retry_request_magic = chunk_from_chars(
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C,
);
chunk_t tls_downgrade_protection_tls11 = chunk_from_chars(
0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x00,
);
chunk_t tls_downgrade_protection_tls12 = chunk_from_chars(
0x44, 0x4F, 0x57, 0x4E, 0x47, 0x52, 0x44, 0x01,
);
/**
* TLS record
*/
@ -107,9 +188,14 @@ struct private_tls_t {
bool is_server;
/**
* Negotiated TLS version
* Negotiated TLS version and maximum supported TLS version
*/
tls_version_t version;
tls_version_t version_max;
/**
* Minimal supported TLS version
*/
tls_version_t version_min;
/**
* TLS stack purpose, as given to constructor
@ -300,7 +386,14 @@ METHOD(tls_t, build, status_t,
{
case NEED_MORE:
record.type = type;
htoun16(&record.version, this->version);
if (this->version_max < TLS_1_3)
{
htoun16(&record.version, this->version_max);
}
else
{
htoun16(&record.version, TLS_1_2);
}
htoun16(&record.length, data.len);
this->output = chunk_cat("mcm", this->output,
chunk_from_thing(record), data);
@ -361,32 +454,86 @@ METHOD(tls_t, get_peer_id, identification_t*,
return this->handshake->get_peer_id(this->handshake);
}
METHOD(tls_t, get_version, tls_version_t,
/**
* Determine the min/max versions
*/
static void determine_versions(private_tls_t *this)
{
tls_version_t version;
char *version_str;
if (this->version_min == TLS_UNSPEC)
{ /* default to TLS 1.2 as older versions are considered deprecated */
this->version_min = TLS_1_2;
version_str = lib->settings->get_str(lib->settings, "%s.tls.version_min",
NULL, lib->ns);
if (version_str &&
enum_from_name(tls_numeric_version_names, version_str, &version))
{
this->version_min = version;
}
}
if (this->version_max == TLS_UNSPEC)
{ /* default to TLS 1.2 until 1.3 is stable for use in EAP */
this->version_max = TLS_1_2;
version_str = lib->settings->get_str(lib->settings, "%s.tls.version_max",
NULL, lib->ns);
if (version_str &&
enum_from_name(tls_numeric_version_names, version_str, &version))
{
this->version_max = version;
}
}
if (this->version_max < this->version_min)
{
this->version_min = this->version_max;
}
}
METHOD(tls_t, get_version_max, tls_version_t,
private_tls_t *this)
{
return this->version;
determine_versions(this);
return this->version_max;
}
METHOD(tls_t, get_version_min, tls_version_t,
private_tls_t *this)
{
determine_versions(this);
return this->version_min;
}
METHOD(tls_t, set_version, bool,
private_tls_t *this, tls_version_t version)
private_tls_t *this, tls_version_t min_version, tls_version_t max_version)
{
if (version > this->version)
if (min_version == TLS_UNSPEC)
{
min_version = this->version_min;
}
if (max_version == TLS_UNSPEC)
{
max_version = this->version_max;
}
if ((this->version_min != TLS_UNSPEC && min_version < this->version_min) ||
(this->version_max != TLS_UNSPEC && max_version > this->version_max) ||
(min_version != TLS_UNSPEC && min_version < TLS_SUPPORTED_MIN) ||
(max_version != TLS_UNSPEC && max_version > TLS_SUPPORTED_MAX) ||
min_version > max_version)
{
return FALSE;
}
switch (version)
this->version_min = min_version;
this->version_max = max_version;
if (min_version != TLS_UNSPEC && min_version == max_version)
{
case TLS_1_0:
case TLS_1_1:
case TLS_1_2:
this->version = version;
this->protection->set_version(this->protection, version);
return TRUE;
case SSL_2_0:
case SSL_3_0:
default:
return FALSE;
this->protection->set_version(this->protection, max_version);
}
return TRUE;
}
METHOD(tls_t, get_purpose, tls_purpose_t,
@ -466,7 +613,8 @@ tls_t *tls_create(bool is_server, identification_t *server,
.is_server = _is_server,
.get_server_id = _get_server_id,
.get_peer_id = _get_peer_id,
.get_version = _get_version,
.get_version_max = _get_version_max,
.get_version_min = _get_version_min,
.set_version = _set_version,
.get_purpose = _get_purpose,
.is_complete = _is_complete,
@ -475,7 +623,6 @@ tls_t *tls_create(bool is_server, identification_t *server,
.destroy = _destroy,
},
.is_server = is_server,
.version = TLS_1_2,
.application = application,
.purpose = purpose,
);

View File

@ -1,4 +1,8 @@
/*
* Copyright (C) 2021 Tobias Brunner
* Copyright (C) 2020-2021 Pascal Knecht
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@ -47,11 +51,15 @@ typedef struct tls_t tls_t;
* TLS/SSL version numbers
*/
enum tls_version_t {
TLS_UNSPEC = 0,
SSL_2_0 = 0x0200,
SSL_3_0 = 0x0300,
TLS_1_0 = 0x0301,
TLS_SUPPORTED_MIN = TLS_1_0,
TLS_1_1 = 0x0302,
TLS_1_2 = 0x0303,
TLS_1_3 = 0x0304,
TLS_SUPPORTED_MAX = TLS_1_3,
};
/**
@ -59,6 +67,11 @@ enum tls_version_t {
*/
extern enum_name_t *tls_version_names;
/**
* Simple, numeric enum names for tls_version_t (only supported versions)
*/
extern enum_name_t *tls_numeric_version_names;
/**
* TLS higher level content type
*/
@ -81,6 +94,11 @@ enum tls_handshake_type_t {
TLS_HELLO_REQUEST = 0,
TLS_CLIENT_HELLO = 1,
TLS_SERVER_HELLO = 2,
TLS_HELLO_VERIFY_REQUEST = 3,
TLS_NEW_SESSION_TICKET = 4,
TLS_END_OF_EARLY_DATA = 5,
TLS_HELLO_RETRY_REQUEST = 6,
TLS_ENCRYPTED_EXTENSIONS = 8,
TLS_CERTIFICATE = 11,
TLS_SERVER_KEY_EXCHANGE = 12,
TLS_CERTIFICATE_REQUEST = 13,
@ -88,6 +106,11 @@ enum tls_handshake_type_t {
TLS_CERTIFICATE_VERIFY = 15,
TLS_CLIENT_KEY_EXCHANGE = 16,
TLS_FINISHED = 20,
TLS_CERTIFICATE_URL = 21,
TLS_CERTIFICATE_STATUS = 22,
TLS_SUPPLEMENTAL_DATA = 23,
TLS_KEY_UPDATE = 24,
TLS_MESSAGE_HASH = 254,
};
/**
@ -114,7 +137,7 @@ enum tls_purpose_t {
};
/**
* TLS Hello extension types.
* TLS Handshake extension types.
*/
enum tls_extension_t {
/** Server name the client wants to talk to */
@ -129,12 +152,48 @@ enum tls_extension_t {
TLS_EXT_TRUNCATED_HMAC = 4,
/** list of OCSP responders the client trusts */
TLS_EXT_STATUS_REQUEST = 5,
/** list of supported elliptic curves */
TLS_EXT_ELLIPTIC_CURVES = 10,
/** list of supported groups, in legacy tls: elliptic curves */
TLS_EXT_SUPPORTED_GROUPS = 10,
/** supported point formats */
TLS_EXT_EC_POINT_FORMATS = 11,
/** list supported signature algorithms */
TLS_EXT_SIGNATURE_ALGORITHMS = 13,
/** indicate usage of Datagram Transport Layer Security (DTLS) */
TLS_EXT_USE_SRTP = 14,
/** indicate usage of heartbeat */
TLS_EXT_HEARTBEAT = 15,
/** indicate usage of application-layer protocol negotiation */
TLS_EXT_APPLICATION_LAYER_PROTOCOL_NEGOTIATION = 16,
/** exchange raw public key, client side*/
TLS_CLIENT_CERTIFICATE_TYPE = 19,
/** exchange raw public key, server side*/
TLS_SERVER_CERTIFICATE_TYPE = 20,
/** use encrypt-then-MAC security mechanism RFC 7366 */
TLS_EXT_ENCRYPT_THEN_MAC = 22,
/** bind master secret to handshake data RFC 7627 */
TLS_EXT_EXTENDED_MASTER_SECRET = 23,
/** session resumption without server-side state RFC 5077 */
TLS_EXT_SESSION_TICKET = 35,
/** negotiate identity of the psk **/
TLS_EXT_PRE_SHARED_KEY = 41,
/** send data in 0-RTT when psk is used and early data is allowed **/
TLS_EXT_EARLY_DATA = 42,
/** negotiate supported tls versions **/
TLS_EXT_SUPPORTED_VERSIONS = 43,
/** identify client **/
TLS_EXT_COOKIE = 44,
/** psk modes supported by the client **/
TLS_EXT_PSK_KEY_EXCHANGE_MODES = 45,
/** indicate supported ca's by endpoint **/
TLS_EXT_CERTIFICATE_AUTHORITIES = 47,
/** provide oid/value pairs to match client's certificate **/
TLS_EXT_OID_FILTERS = 48,
/** willing to perform post-handshake authentication **/
TLS_EXT_POST_HANDSHAKE_AUTH = 49,
/** list supported signature algorithms to verify certificates **/
TLS_EXT_SIGNATURE_ALGORITHMS_CERT = 50,
/** list endpoint's cryptographic parameters **/
TLS_EXT_KEY_SHARE = 51,
/** cryptographic binding for RFC 5746 renegotiation indication */
TLS_EXT_RENEGOTIATION_INFO = 65281,
};
@ -148,6 +207,18 @@ enum tls_name_type_t {
*/
extern enum_name_t *tls_extension_names;
/**
* Magic value (SHA-256 of "HelloRetryRequest") for Random to differentiate
* ServerHello from HelloRetryRequest.
*/
extern chunk_t tls_hello_retry_request_magic;
/**
* Magic values for downgrade protection (see RFC 8446, section 4.1.3)
*/
extern chunk_t tls_downgrade_protection_tls11;
extern chunk_t tls_downgrade_protection_tls12;
/**
* A bottom-up driven TLS stack, suitable for EAP implementations.
*/
@ -216,19 +287,29 @@ struct tls_t {
identification_t* (*get_peer_id)(tls_t *this);
/**
* Get the negotiated TLS/SSL version.
* Get the maximum and negotiated TLS version.
*
* @return negotiated TLS version
* @return max and negotiated TLS version
*/
tls_version_t (*get_version)(tls_t *this);
tls_version_t (*get_version_max)(tls_t *this);
/**
* Set the negotiated TLS/SSL version.
* Get the minimum TLS version.
*
* @return min TLS version
*/
tls_version_t (*get_version_min)(tls_t *this);
/**
* Set the initial minimum/maximum TLS version, or set both to the same
* value once negotiated.
*
* @param version negotiated TLS version
* @return TRUE if version acceptable
* @param min_version minimum (or negotiated) TLS version
* @param max_version maximum (or negotiated) TLS version
* @return TRUE if version(s) acceptable
*/
bool (*set_version)(tls_t *this, tls_version_t version);
bool (*set_version)(tls_t *this, tls_version_t min_version,
tls_version_t max_version);
/**
* Get the purpose of this TLS stack instance.

View File

@ -51,7 +51,7 @@ typedef struct __attribute__((__packed__)) {
} sigheader_t;
METHOD(tls_aead_t, encrypt, bool,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t type,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
uint64_t seq, chunk_t *data)
{
chunk_t assoc, encrypted, iv, plain;
@ -74,7 +74,7 @@ METHOD(tls_aead_t, encrypt, bool,
plain = chunk_skip(encrypted, iv.len);
plain.len -= icvlen;
hdr.type = type;
hdr.type = *type;
htoun64(&hdr.seq, seq);
htoun16(&hdr.version, version);
htoun16(&hdr.length, plain.len);
@ -91,7 +91,7 @@ METHOD(tls_aead_t, encrypt, bool,
}
METHOD(tls_aead_t, decrypt, bool,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t type,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
uint64_t seq, chunk_t *data)
{
chunk_t assoc, iv;
@ -111,7 +111,7 @@ METHOD(tls_aead_t, decrypt, bool,
return FALSE;
}
hdr.type = type;
hdr.type = *type;
htoun64(&hdr.seq, seq);
htoun16(&hdr.version, version);
htoun16(&hdr.length, data->len - icvlen);

View File

@ -1,4 +1,7 @@
/*
* Copyright (C) 2020 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@ -44,13 +47,13 @@ struct tls_aead_t {
* gets updated to the IV for the next record.
*
* @param version TLS version
* @param type TLS content type
* @param type TLS content type (may be changed)
* @param seq record sequence number
* @param data data to encrypt, encryption result
* @return TRUE if successfully encrypted
*/
bool (*encrypt)(tls_aead_t *this, tls_version_t version,
tls_content_type_t type, uint64_t seq, chunk_t *data);
tls_content_type_t *type, uint64_t seq, chunk_t *data);
/**
* Decrypt and verify a TLS record.
@ -59,13 +62,13 @@ struct tls_aead_t {
* length, decryption is done inline.
*
* @param version TLS version
* @param type TLS content type
* @param type TLS content type (may be changed)
* @param seq record sequence number
* @param data data to decrypt, decrypted result
* @return TRUE if successfully decrypted
*/
bool (*decrypt)(tls_aead_t *this, tls_version_t version,
tls_content_type_t type, uint64_t seq, chunk_t *data);
tls_content_type_t *type, uint64_t seq, chunk_t *data);
/**
* Get the authentication key size.
@ -147,10 +150,27 @@ tls_aead_t *tls_aead_create_null(integrity_algorithm_t mac);
/**
* Create a tls_aead instance using real a AEAD cipher.
*
* The sequence number is used as IV directly. The internally used nonce
* is derived from the key material. Used for TLS 1.2.
*
* @param encr AEAD encryption algorithm
* @param encr_size encryption key size, in bytes
* @return TLS AEAD transform
*/
tls_aead_t *tls_aead_create_aead(encryption_algorithm_t encr, size_t encr_size);
/**
* Create a tls_aead instance using real a AEAD cipher and sequence number
* as IV.
*
* The sequence number XORed with a static value of at least the same length
* that is derived from the key material is used as IV. This is what TLS 1.3
* and newer uses.
*
* @param encr AEAD encryption algorithm
* @param encr_size encryption key size, in bytes
* @return TLS AEAD transform
*/
tls_aead_t *tls_aead_create_seq(encryption_algorithm_t encr, size_t encr_size);
#endif /** TLS_AEAD_H_ @}*/

View File

@ -56,14 +56,14 @@ typedef struct __attribute__((__packed__)) {
} sigheader_t;
METHOD(tls_aead_t, encrypt, bool,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t type,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
uint64_t seq, chunk_t *data)
{
chunk_t assoc, mac, padding, iv;
uint8_t bs, padlen;
sigheader_t hdr;
hdr.type = type;
hdr.type = *type;
htoun64(&hdr.seq, seq);
htoun16(&hdr.version, version);
htoun16(&hdr.length, data->len);
@ -99,7 +99,7 @@ METHOD(tls_aead_t, encrypt, bool,
}
METHOD(tls_aead_t, decrypt, bool,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t type,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
uint64_t seq, chunk_t *data)
{
chunk_t assoc, mac, iv;
@ -144,7 +144,7 @@ METHOD(tls_aead_t, decrypt, bool,
mac = chunk_skip(*data, data->len - bs);
data->len -= bs;
hdr.type = type;
hdr.type = *type;
htoun64(&hdr.seq, seq);
htoun16(&hdr.version, version);
htoun16(&hdr.length, data->len);

View File

@ -55,13 +55,13 @@ typedef struct __attribute__((__packed__)) {
METHOD(tls_aead_t, encrypt, bool,
private_tls_aead_t *this, tls_version_t version,
tls_content_type_t type, uint64_t seq, chunk_t *data)
tls_content_type_t *type, uint64_t seq, chunk_t *data)
{
chunk_t assoc, mac, padding;
uint8_t bs, padlen;
sigheader_t hdr;
hdr.type = type;
hdr.type = *type;
htoun64(&hdr.seq, seq);
htoun16(&hdr.version, version);
htoun16(&hdr.length, data->len);
@ -95,7 +95,7 @@ METHOD(tls_aead_t, encrypt, bool,
METHOD(tls_aead_t, decrypt, bool,
private_tls_aead_t *this, tls_version_t version,
tls_content_type_t type, uint64_t seq, chunk_t *data)
tls_content_type_t *type, uint64_t seq, chunk_t *data)
{
chunk_t assoc, mac, iv;
uint8_t bs, padlen;
@ -135,7 +135,7 @@ METHOD(tls_aead_t, decrypt, bool,
mac = chunk_skip(*data, data->len - bs);
data->len -= bs;
hdr.type = type;
hdr.type = *type;
htoun64(&hdr.seq, seq);
htoun16(&hdr.version, version);
htoun16(&hdr.length, data->len);

View File

@ -45,12 +45,12 @@ typedef struct __attribute__((__packed__)) {
METHOD(tls_aead_t, encrypt, bool,
private_tls_aead_t *this, tls_version_t version,
tls_content_type_t type, uint64_t seq, chunk_t *data)
tls_content_type_t *type, uint64_t seq, chunk_t *data)
{
chunk_t assoc, mac;
sigheader_t hdr;
hdr.type = type;
hdr.type = *type;
htoun64(&hdr.seq, seq);
htoun16(&hdr.version, version);
htoun16(&hdr.length, data->len);
@ -67,7 +67,7 @@ METHOD(tls_aead_t, encrypt, bool,
METHOD(tls_aead_t, decrypt, bool,
private_tls_aead_t *this, tls_version_t version,
tls_content_type_t type, uint64_t seq, chunk_t *data)
tls_content_type_t *type, uint64_t seq, chunk_t *data)
{
chunk_t assoc, mac;
sigheader_t hdr;
@ -80,7 +80,7 @@ METHOD(tls_aead_t, decrypt, bool,
mac = chunk_skip(*data, data->len - mac.len);
data->len -= mac.len;
hdr.type = type;
hdr.type = *type;
htoun64(&hdr.seq, seq);
htoun16(&hdr.version, version);
htoun16(&hdr.length, data->len);

264
src/libtls/tls_aead_seq.c Normal file
View File

@ -0,0 +1,264 @@
/*
* Copyright (C) 2020 Tobias Brunner
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
* 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 the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "tls_aead.h"
#include <bio/bio_writer.h>
typedef struct private_tls_aead_t private_tls_aead_t;
/**
* Private data of an tls_aead_t object.
*/
struct private_tls_aead_t {
/**
* Public tls_aead_t interface.
*/
tls_aead_t public;
/**
* AEAD transform.
*/
aead_t *aead;
/**
* IV derived from key material.
*/
chunk_t iv;
/**
* Size of the salt that's internally used by the AEAD implementation.
*/
size_t salt;
};
/**
* Additional data for AEAD (record header)
*/
typedef struct __attribute__((__packed__)) {
uint8_t type;
uint16_t version;
uint16_t length;
} sigheader_t;
/**
* Generate the IV from the given sequence number.
*/
static bool generate_iv(private_tls_aead_t *this, uint64_t seq, chunk_t iv)
{
if (iv.len < sizeof(uint64_t) ||
iv.len < this->iv.len)
{
return FALSE;
}
memset(iv.ptr, 0, iv.len);
htoun64(iv.ptr + iv.len - sizeof(uint64_t), seq);
memxor(iv.ptr + iv.len - this->iv.len, this->iv.ptr, this->iv.len);
return TRUE;
}
METHOD(tls_aead_t, encrypt, bool,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
uint64_t seq, chunk_t *data)
{
bio_writer_t *writer;
chunk_t assoc, encrypted, iv, padding, plain;
uint8_t icvlen;
sigheader_t hdr;
iv = chunk_alloca(this->aead->get_iv_size(this->aead));
if (!generate_iv(this, seq, iv))
{
return FALSE;
}
/* no padding for now */
padding = chunk_empty;
icvlen = this->aead->get_icv_size(this->aead);
writer = bio_writer_create(data->len + 1 + padding.len + icvlen);
writer->write_data(writer, *data);
writer->write_uint8(writer, *type);
writer->write_data(writer, padding);
writer->skip(writer, icvlen);
encrypted = writer->extract_buf(writer);
writer->destroy(writer);
plain = encrypted;
plain.len -= icvlen;
hdr.type = TLS_APPLICATION_DATA;
htoun16(&hdr.version, TLS_1_2);
htoun16(&hdr.length, encrypted.len);
assoc = chunk_from_thing(hdr);
if (!this->aead->encrypt(this->aead, plain, assoc, iv, NULL))
{
chunk_free(&encrypted);
return FALSE;
}
chunk_free(data);
*type = TLS_APPLICATION_DATA;
*data = encrypted;
return TRUE;
}
METHOD(tls_aead_t, decrypt, bool,
private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
uint64_t seq, chunk_t *data)
{
chunk_t assoc, iv;
uint8_t icvlen;
sigheader_t hdr;
iv = chunk_alloca(this->aead->get_iv_size(this->aead));
if (!generate_iv(this, seq, iv))
{
return FALSE;
}
icvlen = this->aead->get_icv_size(this->aead);
if (data->len < icvlen)
{
return FALSE;
}
hdr.type = TLS_APPLICATION_DATA;
htoun16(&hdr.version, TLS_1_2);
htoun16(&hdr.length, data->len);
assoc = chunk_from_thing(hdr);
if (!this->aead->decrypt(this->aead, *data, assoc, iv, NULL))
{
return FALSE;
}
data->len -= icvlen;
while (data->len && !data->ptr[data->len-1])
{ /* ignore any padding */
data->len--;
}
if (data->len < 1)
{
return FALSE;
}
*type = data->ptr[data->len-1];
data->len--;
return TRUE;
}
METHOD(tls_aead_t, get_mac_key_size, size_t,
private_tls_aead_t *this)
{
return 0;
}
METHOD(tls_aead_t, get_encr_key_size, size_t,
private_tls_aead_t *this)
{
/* our AEAD implementations add the salt length here, so subtract it */
return this->aead->get_key_size(this->aead) - this->salt;
}
METHOD(tls_aead_t, get_iv_size, size_t,
private_tls_aead_t *this)
{
/* analogous to the change above, we add the salt length here */
return this->aead->get_iv_size(this->aead) + this->salt;
}
METHOD(tls_aead_t, set_keys, bool,
private_tls_aead_t *this, chunk_t mac, chunk_t encr, chunk_t iv)
{
chunk_t key, salt;
bool success;
if (mac.len || iv.len < this->salt)
{
return FALSE;
}
/* we have to recombine the keys as our AEAD implementations expect the
* salt as part of the key */
chunk_clear(&this->iv);
chunk_split(iv, "ma", this->salt, &salt, iv.len - this->salt, &this->iv);
key = chunk_cata("cc", encr, salt);
success = this->aead->set_key(this->aead, key);
memwipe(key.ptr, key.len);
return success;
}
METHOD(tls_aead_t, destroy, void,
private_tls_aead_t *this)
{
this->aead->destroy(this->aead);
chunk_clear(&this->iv);
free(this);
}
/*
* Described in header
*/
tls_aead_t *tls_aead_create_seq(encryption_algorithm_t encr, size_t encr_size)
{
private_tls_aead_t *this;
size_t salt;
switch (encr)
{
case ENCR_AES_GCM_ICV16:
case ENCR_CHACHA20_POLY1305:
salt = 4;
break;
case ENCR_AES_CCM_ICV8:
case ENCR_AES_CCM_ICV16:
salt = 3;
break;
default:
return NULL;
}
INIT(this,
.public = {
.encrypt = _encrypt,
.decrypt = _decrypt,
.get_mac_key_size = _get_mac_key_size,
.get_encr_key_size = _get_encr_key_size,
.get_iv_size = _get_iv_size,
.set_keys = _set_keys,
.destroy = _destroy,
},
.aead = lib->crypto->create_aead(lib->crypto, encr, encr_size, salt),
.salt = salt,
);
if (!this->aead)
{
free(this);
return NULL;
}
if (this->aead->get_block_size(this->aead) != 1)
{ /* TLS does not define any padding scheme for AEAD */
destroy(this);
return NULL;
}
return &this->public;
}

View File

@ -63,19 +63,34 @@ ENUM_NEXT(tls_alert_desc_names, TLS_INTERNAL_ERROR, TLS_INTERNAL_ERROR,
TLS_INSUFFICIENT_SECURITY,
"internal error",
);
ENUM_NEXT(tls_alert_desc_names, TLS_INAPPROPRIATE_FALLBACK,
TLS_INAPPROPRIATE_FALLBACK, TLS_INTERNAL_ERROR,
"inappropriate fallback",
);
ENUM_NEXT(tls_alert_desc_names, TLS_USER_CANCELED, TLS_USER_CANCELED,
TLS_INTERNAL_ERROR,
TLS_INAPPROPRIATE_FALLBACK,
"user canceled",
);
ENUM_NEXT(tls_alert_desc_names, TLS_NO_RENEGOTIATION, TLS_NO_RENEGOTIATION,
TLS_USER_CANCELED,
"no renegotiation",
);
ENUM_NEXT(tls_alert_desc_names, TLS_UNSUPPORTED_EXTENSION, TLS_UNSUPPORTED_EXTENSION,
ENUM_NEXT(tls_alert_desc_names, TLS_MISSING_EXTENSION, TLS_CERTIFICATE_REQUIRED,
TLS_NO_RENEGOTIATION,
"missing extensions",
"unsupported extension",
"certificate unobtainable",
"recognized name",
"bad certificate status response",
"bad certificate hash value",
"unknown psk identity",
"certificate required",
);
ENUM_END(tls_alert_desc_names, TLS_UNSUPPORTED_EXTENSION);
ENUM_NEXT(tls_alert_desc_names, TLS_NO_APPLICATION_PROTOCOL,
TLS_NO_APPLICATION_PROTOCOL, TLS_CERTIFICATE_REQUIRED,
"no application protocol"
);
ENUM_END(tls_alert_desc_names, TLS_NO_APPLICATION_PROTOCOL);
typedef struct private_tls_alert_t private_tls_alert_t;

View File

@ -61,9 +61,18 @@ enum tls_alert_desc_t {
TLS_PROTOCOL_VERSION = 70,
TLS_INSUFFICIENT_SECURITY = 71,
TLS_INTERNAL_ERROR = 80,
TLS_INAPPROPRIATE_FALLBACK = 86,
TLS_USER_CANCELED = 90,
TLS_NO_RENEGOTIATION = 100,
TLS_MISSING_EXTENSION = 109,
TLS_UNSUPPORTED_EXTENSION = 110,
TLS_CERTIFICATE_UNOBTAINABLE = 111,
TLS_RECOGNIZED_NAME = 112,
TLS_BAD_CERTIFICATE_STATUS_RESPONSE = 113,
TLS_BAD_CERTIFICATE_HASH_VALUE = 114,
TLS_UNKNOWN_PSK_IDENTITY = 115,
TLS_CERTIFICATE_REQUIRED = 116,
TLS_NO_APPLICATION_PROTOCOL = 120,
};
/**

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,9 @@
/*
* Copyright (C) 2020 Tobias Brunner
* Copyright (C) 2020-2021 Pascal Knecht
* Copyright (C) 2020 Méline Sieber
* HSR Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
*
@ -24,10 +29,10 @@
typedef struct tls_crypto_t tls_crypto_t;
typedef enum tls_cipher_suite_t tls_cipher_suite_t;
typedef enum tls_hash_algorithm_t tls_hash_algorithm_t;
typedef enum tls_signature_algorithm_t tls_signature_algorithm_t;
typedef enum tls_signature_scheme_t tls_signature_scheme_t;
typedef enum tls_client_certificate_type_t tls_client_certificate_type_t;
typedef enum tls_ecc_curve_type_t tls_ecc_curve_type_t;
typedef enum tls_named_curve_t tls_named_curve_t;
typedef enum tls_named_group_t tls_named_group_t;
typedef enum tls_ansi_point_format_t tls_ansi_point_format_t;
typedef enum tls_ec_point_format_t tls_ec_point_format_t;
@ -43,213 +48,222 @@ typedef enum tls_ec_point_format_t tls_ec_point_format_t;
* TLS cipher suites
*/
enum tls_cipher_suite_t {
TLS_NULL_WITH_NULL_NULL = 0x0000,
TLS_RSA_WITH_NULL_MD5 = 0x0001,
TLS_RSA_WITH_NULL_SHA = 0x0002,
TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003,
TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
TLS_RSA_WITH_RC4_128_SHA = 0x0005,
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006,
TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007,
TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008,
TLS_RSA_WITH_DES_CBC_SHA = 0x0009,
TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A,
TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B,
TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C,
TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E,
TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F,
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011,
TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012,
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014,
TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017,
TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019,
TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A,
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
TLS_NULL_WITH_NULL_NULL = 0x0000,
TLS_RSA_WITH_NULL_MD5 = 0x0001,
TLS_RSA_WITH_NULL_SHA = 0x0002,
TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003,
TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
TLS_RSA_WITH_RC4_128_SHA = 0x0005,
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006,
TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007,
TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008,
TLS_RSA_WITH_DES_CBC_SHA = 0x0009,
TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A,
TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B,
TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C,
TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E,
TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F,
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011,
TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012,
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014,
TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017,
TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019,
TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A,
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
TLS_KRB5_WITH_DES_CBC_SHA = 0x001E,
TLS_KRB5_WITH_3DES_EDE_CBC_SHA = 0x001F,
TLS_KRB5_WITH_RC4_128_SHA = 0x0020,
TLS_KRB5_WITH_IDEA_CBC_SHA = 0x0021,
TLS_KRB5_WITH_DES_CBC_MD5 = 0x0022,
TLS_KRB5_WITH_3DES_EDE_CBC_MD5 = 0x0023,
TLS_KRB5_WITH_RC4_128_MD5 = 0x0024,
TLS_KRB5_WITH_IDEA_CBC_MD5 = 0x0025,
TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA = 0x0026,
TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA = 0x0027,
TLS_KRB5_EXPORT_WITH_RC4_40_SHA = 0x0028,
TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 = 0x0029,
TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 = 0x002A,
TLS_KRB5_EXPORT_WITH_RC4_40_MD5 = 0x002B,
TLS_PSK_WITH_NULL_SHA = 0x002C,
TLS_DHE_PSK_WITH_NULL_SHA = 0x002D,
TLS_RSA_PSK_WITH_NULL_SHA = 0x002E,
TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F,
TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030,
TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033,
TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034,
TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035,
TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036,
TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039,
TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A,
TLS_RSA_WITH_NULL_SHA256 = 0x003B,
TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C,
TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D,
TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E,
TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041,
TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042,
TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043,
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044,
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045,
TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046,
TLS_KRB5_WITH_DES_CBC_SHA = 0x001E,
TLS_KRB5_WITH_3DES_EDE_CBC_SHA = 0x001F,
TLS_KRB5_WITH_RC4_128_SHA = 0x0020,
TLS_KRB5_WITH_IDEA_CBC_SHA = 0x0021,
TLS_KRB5_WITH_DES_CBC_MD5 = 0x0022,
TLS_KRB5_WITH_3DES_EDE_CBC_MD5 = 0x0023,
TLS_KRB5_WITH_RC4_128_MD5 = 0x0024,
TLS_KRB5_WITH_IDEA_CBC_MD5 = 0x0025,
TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA = 0x0026,
TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA = 0x0027,
TLS_KRB5_EXPORT_WITH_RC4_40_SHA = 0x0028,
TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 = 0x0029,
TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 = 0x002A,
TLS_KRB5_EXPORT_WITH_RC4_40_MD5 = 0x002B,
TLS_PSK_WITH_NULL_SHA = 0x002C,
TLS_DHE_PSK_WITH_NULL_SHA = 0x002D,
TLS_RSA_PSK_WITH_NULL_SHA = 0x002E,
TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F,
TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030,
TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033,
TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034,
TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035,
TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036,
TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039,
TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A,
TLS_RSA_WITH_NULL_SHA256 = 0x003B,
TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C,
TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D,
TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E,
TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041,
TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042,
TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043,
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044,
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045,
TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068,
TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C,
TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068,
TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C,
TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D,
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084,
TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085,
TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086,
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088,
TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089,
TLS_PSK_WITH_RC4_128_SHA = 0x008A,
TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B,
TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C,
TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D,
TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E,
TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090,
TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091,
TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092,
TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093,
TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094,
TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095,
TLS_RSA_WITH_SEED_CBC_SHA = 0x0096,
TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097,
TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098,
TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099,
TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A,
TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B,
TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C,
TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E,
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F,
TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0,
TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1,
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2,
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3,
TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4,
TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5,
TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6,
TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7,
TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8,
TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9,
TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA,
TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB,
TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC,
TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD,
TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE,
TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF,
TLS_PSK_WITH_NULL_SHA256 = 0x00B0,
TLS_PSK_WITH_NULL_SHA384 = 0x00B1,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2,
TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3,
TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4,
TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5,
TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6,
TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7,
TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8,
TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9,
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BA,
TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BB,
TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BC,
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BD,
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BE,
TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BF,
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C0,
TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C1,
TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C2,
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4,
TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5,
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084,
TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085,
TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086,
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088,
TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089,
TLS_PSK_WITH_RC4_128_SHA = 0x008A,
TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B,
TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C,
TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D,
TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E,
TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090,
TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091,
TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092,
TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093,
TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094,
TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095,
TLS_RSA_WITH_SEED_CBC_SHA = 0x0096,
TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097,
TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098,
TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099,
TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A,
TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B,
TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C,
TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E,
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F,
TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0,
TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1,
TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2,
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3,
TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4,
TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5,
TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6,
TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7,
TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8,
TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9,
TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA,
TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB,
TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC,
TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD,
TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE,
TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF,
TLS_PSK_WITH_NULL_SHA256 = 0x00B0,
TLS_PSK_WITH_NULL_SHA384 = 0x00B1,
TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2,
TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3,
TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4,
TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5,
TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6,
TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7,
TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8,
TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9,
TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BA,
TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BB,
TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BC,
TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BD,
TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BE,
TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BF,
TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C0,
TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C1,
TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C2,
TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3,
TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4,
TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5,
TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001,
TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002,
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005,
TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A,
TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B,
TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C,
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F,
TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010,
TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
TLS_ECDH_anon_WITH_NULL_SHA = 0xC015,
TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016,
TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017,
TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018,
TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019,
TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A,
TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B,
TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C,
TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D,
TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E,
TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F,
TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020,
TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021,
TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C,
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D,
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030,
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031,
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032,
TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033,
TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034,
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035,
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036,
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037,
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038,
TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039,
TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A,
TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B
TLS_AES_128_GCM_SHA256 = 0x1301,
TLS_AES_256_GCM_SHA384 = 0x1302,
TLS_CHACHA20_POLY1305_SHA256 = 0x1303,
TLS_AES_128_CCM_SHA256 = 0x1304,
TLS_AES_128_CCM_8_SHA256 = 0x1305,
TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001,
TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002,
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005,
TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006,
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A,
TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B,
TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C,
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F,
TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010,
TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
TLS_ECDH_anon_WITH_NULL_SHA = 0xC015,
TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016,
TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017,
TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018,
TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019,
TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A,
TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B,
TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C,
TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D,
TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E,
TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F,
TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020,
TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021,
TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B,
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C,
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D,
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030,
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031,
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032,
TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033,
TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034,
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035,
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036,
TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037,
TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038,
TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039,
TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A,
TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B,
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8,
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9,
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA,
};
/**
@ -276,18 +290,42 @@ enum tls_hash_algorithm_t {
extern enum_name_t *tls_hash_algorithm_names;
/**
* TLS SignatureAlgorithm identifiers
* TLS SignatureScheme identifiers
*/
enum tls_signature_algorithm_t {
TLS_SIG_RSA = 1,
TLS_SIG_DSA = 2,
TLS_SIG_ECDSA = 3,
enum tls_signature_scheme_t {
/* legacy schemes compatible with TLS 1.2 (first byte is the hash algorithm,
* second the key type) */
TLS_SIG_RSA_PKCS1_SHA1 = 0x0201,
TLS_SIG_ECDSA_SHA1 = 0x0203,
TLS_SIG_RSA_PKCS1_SHA224 = 0x0301,
TLS_SIG_DSA_SHA224 = 0x0302,
TLS_SIG_ECDSA_SHA224 = 0x0303,
TLS_SIG_RSA_PKCS1_SHA256 = 0x0401,
TLS_SIG_DSA_SHA256 = 0x0402,
TLS_SIG_ECDSA_SHA256 = 0x0403,
TLS_SIG_RSA_PKCS1_SHA384 = 0x0501,
TLS_SIG_DSA_SHA384 = 0x0502,
TLS_SIG_ECDSA_SHA384 = 0x0503,
TLS_SIG_RSA_PKCS1_SHA512 = 0x0601,
TLS_SIG_DSA_SHA512 = 0x0602,
TLS_SIG_ECDSA_SHA512 = 0x0603,
/* RSASSA-PSS for public keys with OID rsaEncryption */
TLS_SIG_RSA_PSS_RSAE_SHA256 = 0x0804,
TLS_SIG_RSA_PSS_RSAE_SHA384 = 0x0805,
TLS_SIG_RSA_PSS_RSAE_SHA512 = 0x0806,
/* EdDSA */
TLS_SIG_ED25519 = 0x0807,
TLS_SIG_ED448 = 0x0808,
/* RSASSA-PSS for public keys with OID RSASSA-PSS */
TLS_SIG_RSA_PSS_PSS_SHA256 = 0x0809,
TLS_SIG_RSA_PSS_PSS_SHA384 = 0x080a,
TLS_SIG_RSA_PSS_PSS_SHA512 = 0x080b,
};
/**
* Enum names for tls_signature_algorithm_t
* Enum names for tls_signature_scheme_t
*/
extern enum_name_t *tls_signature_algorithm_names;
extern enum_name_t *tls_signature_scheme_names;
/**
* TLS ClientCertificateType
@ -327,7 +365,7 @@ extern enum_name_t *tls_ecc_curve_type_names;
/**
* TLS Named Curve identifiers
*/
enum tls_named_curve_t {
enum tls_named_group_t {
TLS_SECT163K1 = 1,
TLS_SECT163R1 = 2,
TLS_SECT163R2 = 3,
@ -353,12 +391,21 @@ enum tls_named_curve_t {
TLS_SECP256R1 = 23,
TLS_SECP384R1 = 24,
TLS_SECP521R1 = 25,
/* TLS 1.3: new ecdhe, dhe groups */
TLS_CURVE25519 = 29,
TLS_CURVE448 = 30,
TLS_FFDHE2048 = 256,
TLS_FFDHE3072 = 257,
TLS_FFDHE4096 = 258,
TLS_FFDHE6144 = 259,
TLS_FFDHE8192 = 260,
};
/**
* Enum names for tls_named_curve_t
* Enum names for tls_named_group_t
*/
extern enum_name_t *tls_named_curve_names;
extern enum_name_t *tls_named_group_names;
/**
* EC Point format, ANSI X9.62.
@ -398,7 +445,7 @@ struct tls_crypto_t {
/**
* Get a list of supported TLS cipher suites.
*
* @param suites list of suites, points to internal data
* @param suites optional list of suites, points to internal data
* @return number of suites returned
*/
int (*get_cipher_suites)(tls_crypto_t *this, tls_cipher_suite_t **suites);
@ -423,16 +470,19 @@ struct tls_crypto_t {
diffie_hellman_group_t (*get_dh_group)(tls_crypto_t *this);
/**
* Write the list of supported hash/sig algorithms to writer.
* Write the list of supported signature schemes, either for certificates
* or for CertificateVerify messages, to writer.
*
* @param writer writer to write supported hash/sig algorithms
* @param writer writer to write supported signature schemes
* @param cert TRUE to return signature schemes supported in certs
*/
void (*get_signature_algorithms)(tls_crypto_t *this, bio_writer_t *writer);
void (*get_signature_algorithms)(tls_crypto_t *this, bio_writer_t *writer,
bool cert);
/**
* Create an enumerator over supported ECDH groups.
*
* Enumerates over (diffie_hellman_group_t, tls_named_curve_t)
* Enumerates over (diffie_hellman_group_t, tls_named_group_t)
*
* @return enumerator
*/
@ -454,6 +504,14 @@ struct tls_crypto_t {
void (*append_handshake)(tls_crypto_t *this,
tls_handshake_type_t type, chunk_t data);
/**
* Hash the stored handshake data and store it. It is optionally returned
* so it could be sent in a cookie extension.
*
* @param hash optionally returned hash (allocated)
*/
bool (*hash_handshake)(tls_crypto_t *this, chunk_t *hash);
/**
* Sign a blob of data, append signature to writer.
*
@ -499,13 +557,24 @@ struct tls_crypto_t {
bio_reader_t *reader);
/**
* Calculate the data of a TLS finished message.
* Calculate the data of a legacy TLS finished message.
*
* @param label ASCII label to use for calculation
* @param out buffer to write finished data to
* @return TRUE if calculation successful
*/
bool (*calculate_finished)(tls_crypto_t *this, char *label, char out[12]);
bool (*calculate_finished_legacy)(tls_crypto_t *this, char *label,
char out[12]);
/**
* Calculate the data of a TLS finished message.
*
* @param server Whether the server or client finish message is calculated
* @param out buffer to write finished data to
* @return TRUE if calculation successful
*/
bool (*calculate_finished)(tls_crypto_t *this, bool server,
chunk_t *out);
/**
* Derive the master secret, MAC and encryption keys.
@ -521,6 +590,29 @@ struct tls_crypto_t {
chunk_t session, identification_t *id,
chunk_t client_random, chunk_t server_random);
/**
* Derive the handshake keys.
*
* @param shared_secret input key material
* @return TRUE if secret derived successfully
*/
bool (*derive_handshake_keys)(tls_crypto_t *this, chunk_t shared_secret);
/**
* Derive the application keys.
*
* @return TRUE if secret derived successfully
*/
bool (*derive_app_keys)(tls_crypto_t *this);
/**
* Update the application keys.
*
* @param inbound whether to update the in- or outbound keys
* @return TRUE if secret derived successfully
*/
bool (*update_app_keys)(tls_crypto_t *this, bool inbound);
/**
* Try to resume a TLS session, derive key material.
*
@ -576,9 +668,60 @@ tls_crypto_t *tls_crypto_create(tls_t *tls, tls_cache_t *cache);
* Get a list of all supported TLS cipher suites.
*
* @param null include supported NULL encryption suites
* @param version TLS version
* @param suites pointer to allocated suites array, to free(), or NULL
* @return number of suites supported
*/
int tls_crypto_get_supported_suites(bool null, tls_cipher_suite_t **suites);
int tls_crypto_get_supported_suites(bool null, tls_version_t version,
tls_cipher_suite_t **suites);
/**
* Get a list of all supported TLS DH groups.
*
* @param groups pointer to allocated DH group array, to free(), or NULL
* @return number of curves supported
*/
int tls_crypto_get_supported_groups(diffie_hellman_group_t **groups);
/**
* Get a list of all supported TLS signature schemes.
*
* @param version TLS version
* @param schemes pointer to allocated signature array, to free(), or NULL
* @return number of signature schemes supported
*/
int tls_crypto_get_supported_signatures(tls_version_t version,
tls_signature_scheme_t **schemes);
/**
* Get the TLS curve of a given EC DH group
*
* @param group diffie hellman group indicator
* @return TLS group indicator
*/
tls_named_group_t tls_ec_group_to_curve(diffie_hellman_group_t group);
/**
* Get the key type from a TLS signature scheme
*
* @param sig TLS signature algorithm scheme
* @return type of a key
*/
key_type_t tls_signature_scheme_to_key_type(tls_signature_scheme_t sig);
/**
* Find a private key to encrypt/verify key exchange data
*
* @param min_version minimum negotiated TLS version
* @param max_version maximum negotiated TLS version
* @param hashsig hash and signature algorithms supported by other peer
* @param peer this peer identification
* @return enumerator over private keys,
* NULL in case no common signature scheme
*/
enumerator_t *tls_create_private_key_enumerator(tls_version_t min_version,
tls_version_t max_version,
chunk_t hashsig,
identification_t *peer);
#endif /** TLS_CRYPTO_H_ @}*/

View File

@ -394,6 +394,10 @@ METHOD(tls_eap_t, process, status_t,
switch (status)
{
case INVALID_STATE:
if (this->tls->is_complete(this->tls))
{
return SUCCESS;
}
*out = create_ack(this);
return NEED_MORE;
case FAILED:

View File

@ -292,7 +292,11 @@ METHOD(tls_fragmentation_t, process, status_t,
break;
case TLS_HANDSHAKE:
status = process_handshake(this, reader);
break;
if (!this->handshake->finished(this->handshake))
{
break;
}
/* fall-through */
case TLS_APPLICATION_DATA:
status = process_application(this, reader);
break;
@ -353,7 +357,9 @@ static status_t build_handshake(private_tls_fragmentation_t *this)
msg->write_data24(msg, hs->get_buf(hs));
DBG2(DBG_TLS, "sending TLS %N handshake (%u bytes)",
tls_handshake_type_names, type, hs->get_buf(hs).len);
if (!this->handshake->cipherspec_changed(this->handshake, FALSE))
if (type != TLS_FINISHED &&
type != TLS_KEY_UPDATE &&
!this->handshake->cipherspec_changed(this->handshake, FALSE))
{
hs->destroy(hs);
continue;

743
src/libtls/tls_hkdf.c Normal file
View File

@ -0,0 +1,743 @@
/*
* Copyright (C) 2020 Tobias Brunner
* Copyright (C) 2020 Pascal Knecht
* Copyright (C) 2020 Méline Sieber
* HSR Hochschule fuer Technik Rapperswil
*
* 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 the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "tls_hkdf.h"
#include <bio/bio_writer.h>
#include <crypto/prf_plus.h>
typedef struct private_tls_hkdf_t private_tls_hkdf_t;
typedef struct cached_secrets_t {
chunk_t client;
chunk_t server;
} cached_secrets_t;
typedef enum hkdf_phase {
HKDF_PHASE_0,
HKDF_PHASE_1,
HKDF_PHASE_2,
HKDF_PHASE_3,
} hkdf_phase;
struct private_tls_hkdf_t {
/**
* Public tls_hkdf_t interface.
*/
struct tls_hkdf_t public;
/**
* Phase we are in.
*/
hkdf_phase phase;
/**
* Pseudorandom function used.
*/
prf_t *prf;
/**
* Hasher used.
*/
hasher_t *hasher;
/**
* (EC)DHE as IKM to switch from phase 1 to phase 2
*/
chunk_t shared_secret;
/**
* PSK used.
*/
chunk_t psk;
/**
* PRK used.
*/
chunk_t prk;
/**
* Handshake traffic secrets.
*/
cached_secrets_t handshake_traffic_secrets;
/**
* Current traffic secrets.
*/
cached_secrets_t traffic_secrets;
};
static char *hkdf_labels[] = {
"ext binder",
"res binder",
"c e traffic",
"e exp master",
"c hs traffic",
"s hs traffic",
"c ap traffic",
"s ap traffic",
"exp master",
"res master",
};
/**
* Step 1: Extract, as defined in RFC 5869, section 2.2:
* HKDF-Extract(salt, IKM) -> PRK
*/
static bool extract(private_tls_hkdf_t *this, chunk_t salt, chunk_t ikm,
chunk_t *prk)
{
if (!this->prf->set_key(this->prf, salt))
{
DBG1(DBG_TLS, "unable to set PRF secret to salt");
return FALSE;
}
chunk_clear(prk);
if(!this->prf->allocate_bytes(this->prf, ikm, prk))
{
DBG1(DBG_TLS, "unable to allocate PRF result");
return FALSE;
}
DBG4(DBG_TLS, "PRK: %B", prk);
return TRUE;
}
/**
* Step 2: Expand as defined in RFC 5869, section 2.3:
* HKDF-Expand(PRK, info, L) -> OKM
*/
static bool expand(private_tls_hkdf_t *this, chunk_t prk, chunk_t info,
size_t length, chunk_t *okm)
{
prf_plus_t *prf_plus;
if (!this->prf->set_key(this->prf, prk))
{
DBG1(DBG_TLS, "unable to set PRF secret to PRK");
return FALSE;
}
prf_plus = prf_plus_create(this->prf, TRUE, info);
if (!prf_plus || !prf_plus->allocate_bytes(prf_plus, length, okm))
{
DBG1(DBG_TLS, "unable to allocate PRF+ result");
DESTROY_IF(prf_plus);
return FALSE;
}
prf_plus->destroy(prf_plus);
DBG4(DBG_TLS, "OKM: %B", okm);
return TRUE;
}
/**
* Expand-Label as defined in RFC 8446, section 7.1:
* HKDF-Expand-Label(Secret, Label, Context, Length) -> OKM
*/
static bool expand_label(private_tls_hkdf_t *this, chunk_t secret,
chunk_t label, chunk_t context, uint16_t length,
chunk_t *key)
{
bool success;
if (!label.len || label.len > 249 || context.len > 255)
{
return FALSE;
}
/* HKDFLabel as defined in RFC 8446, section 7.1 */
bio_writer_t *writer = bio_writer_create(0);
writer->write_uint16(writer, length);
label = chunk_cata("cc", chunk_from_str("tls13 "), label);
writer->write_data8(writer, label);
writer->write_data8(writer, context);
success = expand(this, secret, writer->get_buf(writer), length, key);
writer->destroy(writer);
return success;
}
/**
* Derive-Secret as defined in RFC 8446, section 7.1:
* Derive-Secret(Secret, Label, Message) -> OKM
*/
static bool derive_secret(private_tls_hkdf_t *this, chunk_t secret,
chunk_t label, chunk_t messages, chunk_t *okm)
{
chunk_t context;
bool success;
if (!this->hasher->allocate_hash(this->hasher, messages, &context))
{
return FALSE;
}
success = expand_label(this, secret, label, context,
this->hasher->get_hash_size(this->hasher), okm);
chunk_free(&context);
return success;
}
/**
* Move to phase 1 (Early Secret)
*
* 0
* |
* v
* PSK -> HKDF-Extract = Early Secret
* |
* +-----> Derive-Secret(., "ext binder" | "res binder", "")
* | = binder_key
* |
* +-----> Derive-Secret(., "c e traffic", ClientHello)
* | = client_early_traffic_secret
* |
* +-----> Derive-Secret(., "e exp master", ClientHello)
* | = early_exporter_master_secret
* v
*/
static bool move_to_phase_1(private_tls_hkdf_t *this)
{
chunk_t salt_zero, psk = this->psk;
switch (this->phase)
{
case HKDF_PHASE_0:
salt_zero = chunk_alloca(this->hasher->get_hash_size(this->hasher));
chunk_copy_pad(salt_zero, chunk_empty, 0);
if (!psk.ptr)
{
psk = salt_zero;
}
if (!extract(this, salt_zero, psk, &this->prk))
{
DBG1(DBG_TLS, "unable to extract PRK");
return FALSE;
}
this->phase = HKDF_PHASE_1;
return TRUE;
case HKDF_PHASE_1:
return TRUE;
default:
DBG1(DBG_TLS, "invalid HKDF phase");
return FALSE;
}
}
/**
* Move to phase 2 (Handshake Secret)
*
* Derive-Secret(., "derived", "")
* |
* v
* (EC)DHE -> HKDF-Extract = Handshake Secret
* |
* +-----> Derive-Secret(., "c hs traffic",
* | ClientHello...ServerHello)
* | = client_handshake_traffic_secret
* |
* +-----> Derive-Secret(., "s hs traffic",
* | ClientHello...ServerHello)
* | = server_handshake_traffic_secret
* v
*/
static bool move_to_phase_2(private_tls_hkdf_t *this)
{
chunk_t okm;
switch (this->phase)
{
case HKDF_PHASE_0:
if (!move_to_phase_1(this))
{
DBG1(DBG_TLS, "unable to move to phase 1");
return FALSE;
}
/* fall-through */
case HKDF_PHASE_1:
if (!derive_secret(this, this->prk, chunk_from_str("derived"),
chunk_empty, &okm))
{
DBG1(DBG_TLS, "unable to derive secret");
return FALSE;
}
if (!this->shared_secret.ptr)
{
DBG1(DBG_TLS, "no shared secret set");
chunk_clear(&okm);
return FALSE;
}
if (!extract(this, okm, this->shared_secret, &this->prk))
{
DBG1(DBG_TLS, "unable extract PRK");
chunk_clear(&okm);
return FALSE;
}
chunk_clear(&okm);
this->phase = HKDF_PHASE_2;
return TRUE;
case HKDF_PHASE_2:
return TRUE;
default:
DBG1(DBG_TLS, "invalid HKDF phase");
return FALSE;
}
}
/**
* Move to phase 3 (Master Secret)
*
* Derive-Secret(., "derived", "")
* |
* v
* 0 -> HKDF-Extract = Master Secret
* |
* +-----> Derive-Secret(., "c ap traffic",
* | ClientHello...server Finished)
* | = client_application_traffic_secret_0
* |
* +-----> Derive-Secret(., "s ap traffic",
* | ClientHello...server Finished)
* | = server_application_traffic_secret_0
* |
* +-----> Derive-Secret(., "exp master",
* | ClientHello...server Finished)
* | = exporter_master_secret
* |
* +-----> Derive-Secret(., "res master",
* ClientHello...client Finished)
* = resumption_master_secret
*/
static bool move_to_phase_3(private_tls_hkdf_t *this)
{
chunk_t okm, ikm_zero;
switch (this->phase)
{
case HKDF_PHASE_0:
case HKDF_PHASE_1:
if (!move_to_phase_2(this))
{
DBG1(DBG_TLS, "unable to move to phase 2");
return FALSE;
}
/* fall-through */
case HKDF_PHASE_2:
/* prepare okm for next extract */
if (!derive_secret(this, this->prk, chunk_from_str("derived"),
chunk_empty, &okm))
{
DBG1(DBG_TLS, "unable to derive secret");
return FALSE;
}
ikm_zero = chunk_alloca(this->hasher->get_hash_size(this->hasher));
chunk_copy_pad(ikm_zero, chunk_empty, 0);
if (!extract(this, okm, ikm_zero, &this->prk))
{
DBG1(DBG_TLS, "unable extract PRK");
chunk_clear(&okm);
return FALSE;
}
chunk_clear(&okm);
this->phase = HKDF_PHASE_3;
return TRUE;
case HKDF_PHASE_3:
return TRUE;
default:
DBG1(DBG_TLS, "invalid HKDF phase");
return FALSE;
}
}
METHOD(tls_hkdf_t, set_shared_secret, void,
private_tls_hkdf_t *this, chunk_t shared_secret)
{
this->shared_secret = chunk_clone(shared_secret);
}
METHOD(tls_hkdf_t, generate_secret, bool,
private_tls_hkdf_t *this, tls_hkdf_label_t label, chunk_t messages,
chunk_t *secret)
{
chunk_t okm;
switch (label)
{
case TLS_HKDF_EXT_BINDER:
case TLS_HKDF_RES_BINDER:
case TLS_HKDF_C_E_TRAFFIC:
case TLS_HKDF_E_EXP_MASTER:
if (!move_to_phase_1(this))
{
DBG1(DBG_TLS, "unable to move to phase 1");
return FALSE;
}
break;
case TLS_HKDF_C_HS_TRAFFIC:
case TLS_HKDF_S_HS_TRAFFIC:
if (!move_to_phase_2(this))
{
DBG1(DBG_TLS, "unable to move to phase 2");
return FALSE;
}
break;
case TLS_HKDF_C_AP_TRAFFIC:
case TLS_HKDF_S_AP_TRAFFIC:
case TLS_HKDF_EXP_MASTER:
case TLS_HKDF_RES_MASTER:
if (!move_to_phase_3(this))
{
DBG1(DBG_TLS, "unable to move to phase 3");
return FALSE;
}
break;
case TLS_HKDF_UPD_C_TRAFFIC:
case TLS_HKDF_UPD_S_TRAFFIC:
if (this->phase != HKDF_PHASE_3)
{
DBG1(DBG_TLS, "unable to update traffic keys");
return FALSE;
}
break;
default:
DBG1(DBG_TLS, "invalid HKDF label");
return FALSE;
}
if (label == TLS_HKDF_UPD_C_TRAFFIC || label == TLS_HKDF_UPD_S_TRAFFIC)
{
chunk_t previous = this->traffic_secrets.client;
if (label == TLS_HKDF_UPD_S_TRAFFIC)
{
previous = this->traffic_secrets.server;
}
if (!expand_label(this, previous, chunk_from_str("traffic upd"),
chunk_empty, this->hasher->get_hash_size(this->hasher),
&okm))
{
DBG1(DBG_TLS, "unable to update secret");
return FALSE;
}
}
else
{
if (!derive_secret(this, this->prk, chunk_from_str(hkdf_labels[label]),
messages, &okm))
{
DBG1(DBG_TLS, "unable to derive secret");
return FALSE;
}
}
switch (label)
{
case TLS_HKDF_C_HS_TRAFFIC:
chunk_clear(&this->handshake_traffic_secrets.client);
this->handshake_traffic_secrets.client = chunk_clone(okm);
/* fall-through */
case TLS_HKDF_C_AP_TRAFFIC:
case TLS_HKDF_UPD_C_TRAFFIC:
chunk_clear(&this->traffic_secrets.client);
this->traffic_secrets.client = chunk_clone(okm);
break;
case TLS_HKDF_S_HS_TRAFFIC:
chunk_clear(&this->handshake_traffic_secrets.server);
this->handshake_traffic_secrets.server = chunk_clone(okm);
/* fall-through */
case TLS_HKDF_S_AP_TRAFFIC:
case TLS_HKDF_UPD_S_TRAFFIC:
chunk_clear(&this->traffic_secrets.server);
this->traffic_secrets.server = chunk_clone(okm);
break;
default:
break;
}
if (secret)
{
*secret = okm;
}
else
{
chunk_clear(&okm);
}
return TRUE;
}
/**
* Derive keys/IVs from the current traffic secrets.
*/
static bool get_shared_label_keys(private_tls_hkdf_t *this, chunk_t label,
cached_secrets_t *secrets,
bool server, size_t length, chunk_t *key)
{
chunk_t result = chunk_empty, secret;
secret = server ? secrets->server : secrets->client;
if (!expand_label(this, secret, label, chunk_empty, length, &result))
{
DBG1(DBG_TLS, "unable to derive labeled secret");
chunk_clear(&result);
return FALSE;
}
if (key)
{
*key = result;
}
else
{
chunk_clear(&result);
}
return TRUE;
}
METHOD(tls_hkdf_t, derive_key, bool,
private_tls_hkdf_t *this, bool is_server, size_t length, chunk_t *key)
{
return get_shared_label_keys(this, chunk_from_str("key"),
&this->traffic_secrets, is_server, length, key);
}
METHOD(tls_hkdf_t, derive_iv, bool,
private_tls_hkdf_t *this, bool is_server, size_t length, chunk_t *iv)
{
return get_shared_label_keys(this, chunk_from_str("iv"),
&this->traffic_secrets, is_server, length, iv);
}
METHOD(tls_hkdf_t, derive_finished, bool,
private_tls_hkdf_t *this, bool server, chunk_t *finished)
{
return get_shared_label_keys(this, chunk_from_str("finished"),
&this->handshake_traffic_secrets, server,
this->hasher->get_hash_size(this->hasher),
finished);
}
METHOD(tls_hkdf_t, export, bool,
private_tls_hkdf_t *this, char *label, chunk_t context,
chunk_t messages, size_t length, chunk_t *key)
{
chunk_t exporter_master, exporter, hash = chunk_empty;
if (this->phase != HKDF_PHASE_3)
{
DBG1(DBG_TLS, "unable to export key material");
return FALSE;
}
/**
* Export key material according to RFC 8446, section 7.5:
*
* TLS-Exporter(label, context_value, key_length) =
* HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
* "exporter", Hash(context_value), key_length)
*/
if (!generate_secret(this, TLS_HKDF_EXP_MASTER, messages, &exporter_master))
{
DBG1(DBG_TLS, "unable to derive exporter master secret");
return FALSE;
}
if (!derive_secret(this, exporter_master, chunk_from_str(label),
chunk_empty, &exporter))
{
DBG1(DBG_TLS, "unable to derive exporter secret");
chunk_clear(&exporter_master);
return FALSE;
}
chunk_clear(&exporter_master);
if (!this->hasher->allocate_hash(this->hasher, context, &hash) ||
!expand_label(this, exporter, chunk_from_str("exporter"), hash,
length, key))
{
DBG1(DBG_TLS, "unable to expand key material");
chunk_clear(&exporter);
chunk_free(&hash);
return FALSE;
}
chunk_clear(&exporter);
chunk_free(&hash);
return TRUE;
}
METHOD(tls_hkdf_t, resume, bool,
private_tls_hkdf_t *this, chunk_t messages, chunk_t nonce, chunk_t *key)
{
chunk_t resumption_master;
if (this->phase != HKDF_PHASE_3)
{
DBG1(DBG_TLS, "unable to generate resumption key material");
return FALSE;
}
if (!nonce.len)
{
DBG1(DBG_TLS, "no nonce provided");
return FALSE;
}
/**
* PSK associated with the ticket according to RFC 8446, section 4.6.1
*
* HKDF-Expand-Label(resumption_master_secret,
* "resumption", ticket_nonce, Hash.length)
*/
if (!generate_secret(this, TLS_HKDF_RES_MASTER, messages,
&resumption_master))
{
DBG1(DBG_TLS, "unable to derive resumption master secret");
return FALSE;
}
if (!expand_label(this, resumption_master, chunk_from_str("resumption"),
nonce, this->hasher->get_hash_size(this->hasher), key))
{
chunk_clear(&resumption_master);
DBG1(DBG_TLS, "unable to expand key material");
return FALSE;
}
chunk_clear(&resumption_master);
return TRUE;
}
METHOD(tls_hkdf_t, binder, bool,
private_tls_hkdf_t *this, chunk_t seed, chunk_t *out)
{
chunk_t binder_key, finished_key;
if (!generate_secret(this, TLS_HKDF_RES_BINDER, chunk_empty, &binder_key))
{
DBG1(DBG_TLS, "unable to derive binder key");
return FALSE;
}
if (!expand_label(this, binder_key, chunk_from_str("finished"), chunk_empty,
this->hasher->get_hash_size(this->hasher), &finished_key))
{
chunk_clear(&binder_key);
return FALSE;
}
chunk_clear(&binder_key);
if (!this->prf->set_key(this->prf, finished_key) ||
!this->prf->allocate_bytes(this->prf, seed, out))
{
chunk_clear(&finished_key);
return FALSE;
}
chunk_clear(&finished_key);
return TRUE;
}
METHOD(tls_hkdf_t, allocate_bytes, bool,
private_tls_hkdf_t *this, chunk_t key, chunk_t seed,
chunk_t *out)
{
return this->prf->set_key(this->prf, key) &&
this->prf->allocate_bytes(this->prf, seed, out);
}
/**
* Clean up secrets
*/
static void destroy_secrets(cached_secrets_t *secrets)
{
chunk_clear(&secrets->client);
chunk_clear(&secrets->server);
}
METHOD(tls_hkdf_t, destroy, void,
private_tls_hkdf_t *this)
{
chunk_clear(&this->psk);
chunk_clear(&this->prk);
chunk_clear(&this->shared_secret);
destroy_secrets(&this->handshake_traffic_secrets);
destroy_secrets(&this->traffic_secrets);
DESTROY_IF(this->prf);
DESTROY_IF(this->hasher);
free(this);
}
tls_hkdf_t *tls_hkdf_create(hash_algorithm_t hash_algorithm, chunk_t psk)
{
private_tls_hkdf_t *this;
pseudo_random_function_t prf_algorithm;
switch (hash_algorithm)
{
case HASH_SHA256:
prf_algorithm = PRF_HMAC_SHA2_256;
break;
case HASH_SHA384:
prf_algorithm = PRF_HMAC_SHA2_384;
break;
default:
DBG1(DBG_TLS, "unsupported hash algorithm %N", hash_algorithm_names,
hash_algorithm);
return NULL;
}
INIT(this,
.public = {
.set_shared_secret = _set_shared_secret,
.generate_secret = _generate_secret,
.derive_key = _derive_key,
.derive_iv = _derive_iv,
.derive_finished = _derive_finished,
.export = _export,
.resume = _resume,
.binder = _binder,
.allocate_bytes = _allocate_bytes,
.destroy = _destroy,
},
.phase = HKDF_PHASE_0,
.psk = psk.ptr ? chunk_clone(psk) : chunk_empty,
.prf = lib->crypto->create_prf(lib->crypto, prf_algorithm),
.hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm),
);
if (!this->prf || !this->hasher)
{
if (!this->prf)
{
DBG1(DBG_TLS, "%N not supported", pseudo_random_function_names,
prf_algorithm);
}
if (!this->hasher)
{
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names,
hash_algorithm);
}
DBG1(DBG_TLS, "unable to initialise HKDF");
destroy(this);
return NULL;
}
return &this->public;
}

182
src/libtls/tls_hkdf.h Normal file
View File

@ -0,0 +1,182 @@
/*
* Copyright (C) 2020 Pascal Knecht
* Copyright (C) 2020 Méline Sieber
* HSR Hochschule fuer Technik Rapperswil
*
* 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 the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup tls_hkdf tls_hkdf
* @{ @ingroup libtls
*/
#ifndef TLS_HKDF_H_
#define TLS_HKDF_H_
#include <library.h>
#include <crypto/hashers/hasher.h>
typedef enum tls_hkdf_label_t tls_hkdf_label_t;
typedef struct tls_hkdf_t tls_hkdf_t;
/**
* TLS HKDF labels
*/
enum tls_hkdf_label_t {
TLS_HKDF_EXT_BINDER,
TLS_HKDF_RES_BINDER,
TLS_HKDF_C_E_TRAFFIC,
TLS_HKDF_E_EXP_MASTER,
TLS_HKDF_C_HS_TRAFFIC,
TLS_HKDF_S_HS_TRAFFIC,
TLS_HKDF_C_AP_TRAFFIC,
TLS_HKDF_S_AP_TRAFFIC,
TLS_HKDF_EXP_MASTER,
TLS_HKDF_RES_MASTER,
TLS_HKDF_UPD_C_TRAFFIC,
TLS_HKDF_UPD_S_TRAFFIC,
};
/**
* TLS HKDF helper functions.
*/
struct tls_hkdf_t {
/**
* Set the (EC)DHE shared secret of this connection.
*
* @param shared_secret input key material to use
*/
void (*set_shared_secret)(tls_hkdf_t *this, chunk_t shared_secret);
/**
* Allocate secret of the requested label.
*
* Space for returned secret is allocated and must be freed by the caller.
*
* @param label HKDF label of requested secret
* @param messages handshake messages
* @param secret secret will be written into this chunk, if used
* @return TRUE if secrets derived successfully
*/
bool (*generate_secret)(tls_hkdf_t *this, tls_hkdf_label_t label,
chunk_t messages, chunk_t *secret);
/**
* Allocate traffic encryption key bytes.
*
* Key used to encrypt traffic data as defined in RFC 8446, section 7.3.
* Space for returned secret is allocated and must be freed by the caller.
*
* @param is_server TRUE if server, FALSE if client derives secret
* @param length key length, in bytes
* @param key key will be written into this chunk
* @return TRUE if secrets derived successfully
*/
bool (*derive_key)(tls_hkdf_t *this, bool is_server, size_t length,
chunk_t *key);
/**
* Allocate traffic IV bytes.
*
* IV used to encrypt traffic data as defined in RFC 8446, section 7.3.
* Space for returned secret is allocated and must be freed by the caller.
*
* @param is_server TRUE if server, FALSE if client derives secret
* @param length key length, in bytes
* @param iv IV will be written into this chunk
* @return TRUE if secrets derived successfully
*/
bool (*derive_iv)(tls_hkdf_t *this, bool is_server, size_t length,
chunk_t *iv);
/**
* Allocate finished key bytes.
*
* Key used to compute Finished messages as defined in RFC 8446,
* section 4.4.4. Space for returned secret is allocated and must be freed
* by the caller.
*
* @param server Whether the client or server finish key is derived
* @param finished key will be written into this chunk
* @return TRUE if secrets derived successfully
*/
bool (*derive_finished)(tls_hkdf_t *this, bool server,
chunk_t *finished);
/**
* Export key material.
*
* @param label exporter label
* @param context optional context
* @param messages handshake messages
* @param length key length, in bytes
* @param key exported key material
* @return TRUE if key material successfully exported
*/
bool (*export)(tls_hkdf_t *this, char *label, chunk_t context,
chunk_t messages, size_t length, chunk_t *key);
/**
* Generate resumption PSKs.
*
* @param messages handshake messages
* @param nonce nonce to use for this PSK
* @param psk generated PSK
* @return TRUE if PSK successfully generated
*/
bool (*resume)(tls_hkdf_t *this, chunk_t messages, chunk_t nonce,
chunk_t *psk);
/**
* Generate a PSK binder.
*
* @note The transcript hash is built of the partial ClientHello message up
* to and including the PreSharedKey extension's identities field, excluding
* the actual binders (their length is included in that of the extension(s)
* and message, though), as per RFC 8446, section 4.2.11.2.
*
* @param seed transcript-hash of client_hello to seed the PRF
* @param psk_binder generated psk binder
* @return TRUE if output was generated
*/
bool (*binder)(tls_hkdf_t *this, chunk_t seed, chunk_t *psk_binder);
/**
* Use the internal PRF to allocate data (mainly for the finished message
* where the key is from derive_finished() and the seed is the transcript
* hash).
*
* @param key key to use with the PRF
* @param seed seed to use with the PRF
* @param out output from the PRF (allocated)
* @return TRUE if output was generated
*/
bool (*allocate_bytes)(tls_hkdf_t *this, chunk_t key, chunk_t seed,
chunk_t *out);
/**
* Destroy a tls_hkdf_t
*/
void (*destroy)(tls_hkdf_t *this);
};
/**
* Create a tls_hkdf instance.
*
* @param hash_algorithm hash algorithm to use
* @param psk Pre shared key if available otherwise NULL
* @return TLS HKDF helper
*/
tls_hkdf_t *tls_hkdf_create(hash_algorithm_t hash_algorithm, chunk_t psk);
#endif /** TLS_HKDF_H_ @}*/

File diff suppressed because it is too large Load Diff

View File

@ -73,23 +73,19 @@ METHOD(tls_protection_t, process, status_t,
return NEED_MORE;
}
if (this->aead_in)
if (this->version < TLS_1_3 ||
type == TLS_APPLICATION_DATA)
{
if (!this->aead_in->decrypt(this->aead_in, this->version,
type, this->seq_in, &data))
if (this->aead_in)
{
DBG1(DBG_TLS, "TLS record decryption failed");
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
return NEED_MORE;
if (!this->aead_in->decrypt(this->aead_in, this->version,
&type, this->seq_in, &data))
{
DBG1(DBG_TLS, "TLS record decryption failed");
this->alert->add(this->alert, TLS_FATAL, TLS_BAD_RECORD_MAC);
return NEED_MORE;
}
}
}
if (type == TLS_CHANGE_CIPHER_SPEC)
{
this->seq_in = 0;
}
else
{
this->seq_in++;
}
return this->compression->process(this->compression, type, data);
@ -103,15 +99,14 @@ METHOD(tls_protection_t, build, status_t,
status = this->compression->build(this->compression, type, data);
if (status == NEED_MORE)
{
if (*type == TLS_CHANGE_CIPHER_SPEC)
if (*type == TLS_CHANGE_CIPHER_SPEC && this->version < TLS_1_3)
{
this->seq_out = 0;
return status;
}
if (this->aead_out)
{
if (!this->aead_out->encrypt(this->aead_out, this->version,
*type, this->seq_out, data))
type, this->seq_out, data))
{
DBG1(DBG_TLS, "TLS record encryption failed");
chunk_free(data);
@ -128,11 +123,15 @@ METHOD(tls_protection_t, set_cipher, void,
{
if (inbound)
{
DESTROY_IF(this->aead_in);
this->aead_in = aead;
this->seq_in = 0;
}
else
{
DESTROY_IF(this->aead_out);
this->aead_out = aead;
this->seq_out = 0;
}
}
@ -145,6 +144,8 @@ METHOD(tls_protection_t, set_version, void,
METHOD(tls_protection_t, destroy, void,
private_tls_protection_t *this)
{
DESTROY_IF(this->aead_in);
DESTROY_IF(this->aead_out);
free(this);
}

File diff suppressed because it is too large Load Diff

View File

@ -101,6 +101,11 @@ struct private_tls_socket_t {
* Underlying OS socket
*/
int fd;
/**
* Whether the socket returned EOF
*/
bool eof;
};
METHOD(tls_application_t, process, status_t,
@ -188,7 +193,11 @@ static bool exchange(private_tls_socket_t *this, bool wr, bool block)
case SUCCESS:
return TRUE;
default:
return FALSE;
if (wr)
{
return FALSE;
}
break;
}
break;
}
@ -232,6 +241,7 @@ static bool exchange(private_tls_socket_t *this, bool wr, bool block)
}
if (in == 0)
{ /* EOF */
this->eof = TRUE;
return TRUE;
}
switch (this->tls->process(this->tls, buf, in))
@ -264,11 +274,20 @@ METHOD(tls_socket_t, read_, ssize_t,
}
return cache;
}
if (this->eof)
{
return 0;
}
this->app.in.ptr = buf;
this->app.in.len = len;
this->app.in_done = 0;
if (exchange(this, FALSE, block))
{
if (!this->app.in_done && !this->eof)
{
errno = EWOULDBLOCK;
return -1;
}
return this->app.in_done;
}
return -1;
@ -292,13 +311,13 @@ METHOD(tls_socket_t, splice, bool,
{
char buf[PLAIN_BUF_SIZE], *pos;
ssize_t in, out;
bool old, plain_eof = FALSE, crypto_eof = FALSE;
bool old, crypto_eof = FALSE;
struct pollfd pfd[] = {
{ .fd = this->fd, .events = POLLIN, },
{ .fd = rfd, .events = POLLIN, },
};
while (!plain_eof && !crypto_eof)
while (!this->eof && !crypto_eof)
{
old = thread_cancelability(TRUE);
in = poll(pfd, countof(pfd), -1);
@ -308,14 +327,11 @@ METHOD(tls_socket_t, splice, bool,
DBG1(DBG_TLS, "TLS select error: %s", strerror(errno));
return FALSE;
}
while (!plain_eof && pfd[0].revents & (POLLIN | POLLHUP | POLLNVAL))
while (!this->eof && pfd[0].revents & (POLLIN | POLLHUP | POLLNVAL))
{
in = read_(this, buf, sizeof(buf), FALSE);
switch (in)
{
case 0:
plain_eof = TRUE;
break;
case -1:
if (errno != EWOULDBLOCK)
{
@ -405,8 +421,9 @@ METHOD(tls_socket_t, destroy, void,
* See header
*/
tls_socket_t *tls_socket_create(bool is_server, identification_t *server,
identification_t *peer, int fd, tls_cache_t *cache,
tls_version_t max_version, bool nullok)
identification_t *peer, int fd,
tls_cache_t *cache, tls_version_t min_version,
tls_version_t max_version, bool nullok)
{
private_tls_socket_t *this;
tls_purpose_t purpose;
@ -442,12 +459,11 @@ tls_socket_t *tls_socket_create(bool is_server, identification_t *server,
this->tls = tls_create(is_server, server, peer, purpose,
&this->app.application, cache);
if (!this->tls)
if (!this->tls ||
!this->tls->set_version(this->tls, min_version, max_version))
{
free(this);
return NULL;
}
this->tls->set_version(this->tls, max_version);
return &this->public;
}

View File

@ -99,17 +99,21 @@ struct tls_socket_t {
/**
* Create a tls_socket instance.
*
* Use TLS_UNSPEC to default to the configured min/max version.
*
* @param is_server TRUE to act as TLS server
* @param server server identity
* @param peer client identity, NULL for no client authentication
* @param fd socket to read/write from
* @param cache session cache to use, or NULL
* @param max_version maximum TLS version to negotiate
* @param min_version minimum TLS version to negotiate or TLS_UNSPEC
* @param max_version maximum TLS version to negotiate or TLS_UNSPEC
* @param nullok accept NULL encryption ciphers
* @return TLS socket wrapper
*/
tls_socket_t *tls_socket_create(bool is_server, identification_t *server,
identification_t *peer, int fd, tls_cache_t *cache,
tls_version_t max_version, bool nullok);
identification_t *peer, int fd,
tls_cache_t *cache, tls_version_t min_version,
tls_version_t max_version, bool nullok);
#endif /** TLS_SOCKET_H_ @}*/