2010-01-25 11:21:57 +00:00
|
|
|
/*
|
2020-08-25 11:14:05 +00:00
|
|
|
* Copyright (C) 2020 Tobias Brunner
|
2021-01-18 17:11:55 +00:00
|
|
|
* Copyright (C) 2020-2021 Pascal Knecht
|
2020-08-25 11:14:05 +00:00
|
|
|
* Copyright (C) 2020 Méline Sieber
|
|
|
|
* HSR Hochschule fuer Technik Rapperswil
|
|
|
|
*
|
2014-01-15 14:51:03 +00:00
|
|
|
* Copyright (C) 2010-2014 Martin Willi
|
|
|
|
* Copyright (C) 2010-2014 revosec AG
|
2010-01-25 11:21:57 +00:00
|
|
|
*
|
|
|
|
* 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_crypto.h"
|
2020-05-21 07:37:38 +00:00
|
|
|
#include "tls_hkdf.h"
|
2010-01-25 11:21:57 +00:00
|
|
|
|
2012-10-16 14:03:21 +00:00
|
|
|
#include <utils/debug.h>
|
2014-01-15 14:51:03 +00:00
|
|
|
#include <plugins/plugin_feature.h>
|
2020-10-12 16:58:53 +00:00
|
|
|
#include <collections/hashtable.h>
|
2020-11-10 09:22:12 +00:00
|
|
|
#include <collections/array.h>
|
2010-02-04 10:17:48 +00:00
|
|
|
|
2010-08-04 23:21:59 +00:00
|
|
|
ENUM_BEGIN(tls_cipher_suite_names, TLS_NULL_WITH_NULL_NULL,
|
|
|
|
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
|
|
|
|
"TLS_NULL_WITH_NULL_NULL",
|
|
|
|
"TLS_RSA_WITH_NULL_MD5",
|
|
|
|
"TLS_RSA_WITH_NULL_SHA",
|
|
|
|
"TLS_RSA_EXPORT_WITH_RC4_40_MD5",
|
|
|
|
"TLS_RSA_WITH_RC4_128_MD5",
|
|
|
|
"TLS_RSA_WITH_RC4_128_SHA",
|
|
|
|
"TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5",
|
|
|
|
"TLS_RSA_WITH_IDEA_CBC_SHA",
|
|
|
|
"TLS_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_DES_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
|
|
|
"TLS_DH_DSS_WITH_DES_CBC_SHA",
|
|
|
|
"TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
|
|
|
"TLS_DH_RSA_WITH_DES_CBC_SHA",
|
|
|
|
"TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
|
2010-08-05 11:58:49 +00:00
|
|
|
"TLS_DHE_DSS_WITH_DES_CBC_SHA",
|
2010-08-04 23:21:59 +00:00
|
|
|
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
|
|
|
|
"TLS_DHE_RSA_WITH_DES_CBC_SHA",
|
|
|
|
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_DH_anon_EXPORT_WITH_RC4_40_MD5",
|
|
|
|
"TLS_DH_anon_WITH_RC4_128_MD5",
|
|
|
|
"TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
|
|
|
|
"TLS_DH_anon_WITH_DES_CBC_SHA",
|
|
|
|
"TLS_DH_anon_WITH_3DES_EDE_CBC_SHA");
|
|
|
|
ENUM_NEXT(tls_cipher_suite_names, TLS_KRB5_WITH_DES_CBC_SHA,
|
|
|
|
TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
|
|
|
|
TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
|
|
|
|
"TLS_KRB5_WITH_DES_CBC_SHA",
|
|
|
|
"TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_KRB5_WITH_RC4_128_SHA",
|
|
|
|
"TLS_KRB5_WITH_IDEA_CBC_SHA",
|
|
|
|
"TLS_KRB5_WITH_DES_CBC_MD5",
|
|
|
|
"TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
|
|
|
|
"TLS_KRB5_WITH_RC4_128_MD5",
|
|
|
|
"TLS_KRB5_WITH_IDEA_CBC_MD5",
|
|
|
|
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
|
2010-08-05 11:58:49 +00:00
|
|
|
"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA",
|
2010-08-04 23:21:59 +00:00
|
|
|
"TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
|
|
|
|
"TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
|
|
|
|
"TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5",
|
|
|
|
"TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
|
|
|
|
"TLS_PSK_WITH_NULL_SHA",
|
|
|
|
"TLS_DHE_PSK_WITH_NULL_SHA",
|
|
|
|
"TLS_RSA_PSK_WITH_NULL_SHA",
|
|
|
|
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_DH_DSS_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_DH_RSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_DH_anon_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_DH_DSS_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_DH_RSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_DH_anon_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_NULL_SHA256",
|
2014-03-25 08:20:15 +00:00
|
|
|
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
2010-08-04 23:21:59 +00:00
|
|
|
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
|
|
|
"TLS_DH_DSS_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_DH_RSA_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
|
|
|
|
"TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA",
|
|
|
|
"TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA",
|
|
|
|
"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",
|
2010-08-05 11:58:49 +00:00
|
|
|
"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
|
2010-08-04 23:21:59 +00:00
|
|
|
"TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA");
|
|
|
|
ENUM_NEXT(tls_cipher_suite_names, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
|
|
|
TLS_DH_anon_WITH_AES_256_CBC_SHA256,
|
|
|
|
TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
|
|
|
|
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_DH_DSS_WITH_AES_256_CBC_SHA256",
|
|
|
|
"TLS_DH_RSA_WITH_AES_256_CBC_SHA256",
|
|
|
|
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
|
|
|
|
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
|
|
|
|
"TLS_DH_anon_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_DH_anon_WITH_AES_256_CBC_SHA256");
|
|
|
|
ENUM_NEXT(tls_cipher_suite_names, TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
2010-08-05 11:58:49 +00:00
|
|
|
TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
|
2010-08-04 23:21:59 +00:00
|
|
|
TLS_DH_anon_WITH_AES_256_CBC_SHA256,
|
|
|
|
"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
|
|
|
"TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA",
|
|
|
|
"TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
|
|
|
"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",
|
|
|
|
"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
|
|
|
"TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA",
|
|
|
|
"TLS_PSK_WITH_RC4_128_SHA",
|
2014-03-25 08:20:15 +00:00
|
|
|
"TLS_PSK_WITH_3DES_EDE_CBC_SHA",
|
2010-08-04 23:21:59 +00:00
|
|
|
"TLS_PSK_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_PSK_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_DHE_PSK_WITH_RC4_128_SHA",
|
|
|
|
"TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_DHE_PSK_WITH_AES_128_CBC_SHA",
|
2014-03-25 08:20:15 +00:00
|
|
|
"TLS_DHE_PSK_WITH_AES_256_CBC_SHA",
|
2010-08-04 23:21:59 +00:00
|
|
|
"TLS_RSA_PSK_WITH_RC4_128_SHA",
|
|
|
|
"TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_RSA_PSK_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_RSA_PSK_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_SEED_CBC_SHA",
|
|
|
|
"TLS_DH_DSS_WITH_SEED_CBC_SHA",
|
|
|
|
"TLS_DH_RSA_WITH_SEED_CBC_SHA",
|
|
|
|
"TLS_DHE_DSS_WITH_SEED_CBC_SHA",
|
|
|
|
"TLS_DHE_RSA_WITH_SEED_CBC_SHA",
|
|
|
|
"TLS_DH_anon_WITH_SEED_CBC_SHA",
|
|
|
|
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_DH_RSA_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_DH_RSA_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_DH_DSS_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_DH_DSS_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_DH_anon_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_DH_anon_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_PSK_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_PSK_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_RSA_PSK_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_RSA_PSK_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_PSK_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_PSK_WITH_AES_256_CBC_SHA384",
|
|
|
|
"TLS_PSK_WITH_NULL_SHA256",
|
|
|
|
"TLS_PSK_WITH_NULL_SHA384",
|
|
|
|
"TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",
|
|
|
|
"TLS_DHE_PSK_WITH_NULL_SHA256",
|
|
|
|
"TLS_DHE_PSK_WITH_NULL_SHA384",
|
|
|
|
"TLS_RSA_PSK_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_RSA_PSK_WITH_AES_256_CBC_SHA384",
|
|
|
|
"TLS_RSA_PSK_WITH_NULL_SHA256",
|
|
|
|
"TLS_RSA_PSK_WITH_NULL_SHA384",
|
|
|
|
"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
|
|
|
"TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256",
|
|
|
|
"TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
|
|
|
"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",
|
|
|
|
"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
|
|
|
"TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256",
|
|
|
|
"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
|
|
|
|
"TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256",
|
|
|
|
"TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256",
|
|
|
|
"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",
|
|
|
|
"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
|
|
|
|
"TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256");
|
|
|
|
ENUM_NEXT(tls_cipher_suite_names, TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
2010-08-05 11:58:49 +00:00
|
|
|
TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
2010-08-04 23:21:59 +00:00
|
|
|
TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
|
|
|
|
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
|
2020-05-21 07:37:38 +00:00
|
|
|
ENUM_NEXT(tls_cipher_suite_names, TLS_AES_128_GCM_SHA256,
|
|
|
|
TLS_AES_128_CCM_8_SHA256,
|
|
|
|
TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
|
|
|
|
"TLS_AES_128_GCM_SHA256",
|
|
|
|
"TLS_AES_256_GCM_SHA384",
|
|
|
|
"TLS_CHACHA20_POLY1305_SHA256",
|
|
|
|
"TLS_AES_128_CCM_SHA256",
|
|
|
|
"TLS_AES_128_CCM_8_SHA256");
|
2010-08-04 23:21:59 +00:00
|
|
|
ENUM_NEXT(tls_cipher_suite_names, TLS_ECDH_ECDSA_WITH_NULL_SHA,
|
2010-08-05 11:58:49 +00:00
|
|
|
TLS_ECDHE_PSK_WITH_NULL_SHA384,
|
2020-05-21 07:37:38 +00:00
|
|
|
TLS_AES_128_CCM_8_SHA256,
|
2010-08-04 23:21:59 +00:00
|
|
|
"TLS_ECDH_ECDSA_WITH_NULL_SHA",
|
|
|
|
"TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
|
|
|
|
"TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_NULL_SHA",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_ECDH_RSA_WITH_NULL_SHA",
|
|
|
|
"TLS_ECDH_RSA_WITH_RC4_128_SHA",
|
|
|
|
"TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_ECDHE_RSA_WITH_NULL_SHA",
|
|
|
|
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
|
|
|
|
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_ECDH_anon_WITH_NULL_SHA",
|
|
|
|
"TLS_ECDH_anon_WITH_RC4_128_SHA",
|
|
|
|
"TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
|
|
|
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
|
|
|
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
|
|
|
"TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
|
|
|
|
"TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
|
|
|
|
"TLS_ECDHE_PSK_WITH_RC4_128_SHA",
|
|
|
|
"TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA",
|
|
|
|
"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
|
|
|
|
"TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
|
|
|
|
"TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",
|
|
|
|
"TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384",
|
|
|
|
"TLS_ECDHE_PSK_WITH_NULL_SHA",
|
|
|
|
"TLS_ECDHE_PSK_WITH_NULL_SHA256",
|
|
|
|
"TLS_ECDHE_PSK_WITH_NULL_SHA384");
|
2020-09-15 14:08:08 +00:00
|
|
|
ENUM_NEXT(tls_cipher_suite_names, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
|
|
|
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
|
|
|
TLS_ECDHE_PSK_WITH_NULL_SHA384,
|
|
|
|
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
|
|
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
|
|
|
|
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256");
|
|
|
|
ENUM_END(tls_cipher_suite_names, TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
|
|
|
|
|
2010-08-04 23:21:59 +00:00
|
|
|
|
2010-09-02 07:21:45 +00:00
|
|
|
ENUM(tls_hash_algorithm_names, TLS_HASH_NONE, TLS_HASH_SHA512,
|
|
|
|
"NONE",
|
|
|
|
"MD5",
|
|
|
|
"SHA1",
|
|
|
|
"SHA224",
|
|
|
|
"SHA256",
|
|
|
|
"SHA384",
|
|
|
|
"SHA512",
|
|
|
|
);
|
|
|
|
|
2020-08-28 06:59:37 +00:00
|
|
|
ENUM_BEGIN(tls_signature_scheme_names,
|
|
|
|
TLS_SIG_RSA_PKCS1_SHA1, TLS_SIG_RSA_PKCS1_SHA1,
|
|
|
|
"RSA_PKCS1_SHA1");
|
|
|
|
ENUM_NEXT(tls_signature_scheme_names,
|
|
|
|
TLS_SIG_ECDSA_SHA1, TLS_SIG_ECDSA_SHA1, TLS_SIG_RSA_PKCS1_SHA1,
|
|
|
|
"ECDSA_SHA1");
|
|
|
|
ENUM_NEXT(tls_signature_scheme_names,
|
2020-10-10 15:10:37 +00:00
|
|
|
TLS_SIG_RSA_PKCS1_SHA224, TLS_SIG_ECDSA_SHA224, TLS_SIG_ECDSA_SHA1,
|
|
|
|
"RSA_PKCS1_SHA224",
|
|
|
|
"DSA_SHA224",
|
|
|
|
"ECDSA_SHA224");
|
2020-08-28 06:59:37 +00:00
|
|
|
ENUM_NEXT(tls_signature_scheme_names,
|
2020-10-10 15:10:37 +00:00
|
|
|
TLS_SIG_RSA_PKCS1_SHA256, TLS_SIG_ECDSA_SHA256, TLS_SIG_ECDSA_SHA224,
|
|
|
|
"RSA_PKCS1_SHA256",
|
|
|
|
"DSA_SHA256",
|
2020-08-28 06:59:37 +00:00
|
|
|
"ECDSA_SHA256");
|
|
|
|
ENUM_NEXT(tls_signature_scheme_names,
|
2020-10-10 15:10:37 +00:00
|
|
|
TLS_SIG_RSA_PKCS1_SHA384, TLS_SIG_ECDSA_SHA384, TLS_SIG_ECDSA_SHA256,
|
|
|
|
"RSA_PKCS1_SHA384",
|
|
|
|
"DSA_SHA384",
|
2020-08-28 06:59:37 +00:00
|
|
|
"ECDSA_SHA384");
|
|
|
|
ENUM_NEXT(tls_signature_scheme_names,
|
2020-10-10 15:10:37 +00:00
|
|
|
TLS_SIG_RSA_PKCS1_SHA512, TLS_SIG_ECDSA_SHA512, TLS_SIG_ECDSA_SHA384,
|
|
|
|
"RSA_PKCS1_SHA512",
|
|
|
|
"DSA_SHA512",
|
2020-08-28 06:59:37 +00:00
|
|
|
"ECDSA_SHA512");
|
|
|
|
ENUM_NEXT(tls_signature_scheme_names,
|
|
|
|
TLS_SIG_RSA_PSS_RSAE_SHA256, TLS_SIG_RSA_PSS_PSS_SHA512, TLS_SIG_ECDSA_SHA512,
|
|
|
|
"RSA_PSS_RSAE_SHA256",
|
|
|
|
"RSA_PSS_RSAE_SHA384",
|
|
|
|
"RSA_PSS_RSAE_SHA512",
|
|
|
|
"ED25519",
|
|
|
|
"ED448",
|
|
|
|
"RSA_PSS_PSS_SHA256",
|
|
|
|
"RSA_PSS_PSS_SHA384",
|
|
|
|
"RSA_PSS_PSS_SHA512",
|
2010-09-02 07:21:45 +00:00
|
|
|
);
|
2020-08-28 06:59:37 +00:00
|
|
|
ENUM_END(tls_signature_scheme_names, TLS_SIG_RSA_PSS_PSS_SHA512);
|
2010-09-02 07:21:45 +00:00
|
|
|
|
2010-09-02 08:05:11 +00:00
|
|
|
ENUM_BEGIN(tls_client_certificate_type_names,
|
|
|
|
TLS_RSA_SIGN, TLS_DSS_EPHEMERAL_DH,
|
|
|
|
"RSA_SIGN",
|
|
|
|
"DSA_SIGN",
|
|
|
|
"RSA_FIXED_DH",
|
|
|
|
"DSS_FIXED_DH",
|
|
|
|
"RSA_EPHEMERAL_DH",
|
|
|
|
"DSS_EPHEMERAL_DH");
|
|
|
|
ENUM_NEXT(tls_client_certificate_type_names,
|
|
|
|
TLS_FORTEZZA_DMS, TLS_FORTEZZA_DMS, TLS_DSS_EPHEMERAL_DH,
|
|
|
|
"FORTEZZA_DMS");
|
|
|
|
ENUM_NEXT(tls_client_certificate_type_names,
|
|
|
|
TLS_ECDSA_SIGN, TLS_ECDSA_FIXED_ECDH, TLS_FORTEZZA_DMS,
|
|
|
|
"ECDSA_SIGN",
|
|
|
|
"RSA_FIXED_ECDH",
|
|
|
|
"ECDSA_FIXED_ECDH");
|
|
|
|
ENUM_END(tls_client_certificate_type_names, TLS_ECDSA_FIXED_ECDH);
|
|
|
|
|
2010-09-03 08:59:01 +00:00
|
|
|
ENUM(tls_ecc_curve_type_names, TLS_ECC_EXPLICIT_PRIME, TLS_ECC_NAMED_CURVE,
|
|
|
|
"EXPLICIT_PRIME",
|
|
|
|
"EXPLICIT_CHAR2",
|
|
|
|
"NAMED_CURVE",
|
|
|
|
);
|
|
|
|
|
2020-05-21 07:37:38 +00:00
|
|
|
ENUM_BEGIN(tls_named_group_names, TLS_SECT163K1, TLS_SECP521R1,
|
2010-09-03 08:59:01 +00:00
|
|
|
"SECT163K1",
|
|
|
|
"SECT163R1",
|
|
|
|
"SECT163R2",
|
|
|
|
"SECT193R1",
|
|
|
|
"SECT193R2",
|
|
|
|
"SECT233K1",
|
|
|
|
"SECT233R1",
|
|
|
|
"SECT239K1",
|
|
|
|
"SECT283K1",
|
|
|
|
"SECT283R1",
|
|
|
|
"SECT409K1",
|
|
|
|
"SECT409R1",
|
|
|
|
"SECT571K1",
|
|
|
|
"SECT571R1",
|
|
|
|
"SECP160K1",
|
|
|
|
"SECP160R1",
|
|
|
|
"SECP160R2",
|
|
|
|
"SECP192K1",
|
|
|
|
"SECP192R1",
|
|
|
|
"SECP224K1",
|
|
|
|
"SECP224R1",
|
|
|
|
"SECP256K1",
|
|
|
|
"SECP256R1",
|
|
|
|
"SECP384R1",
|
|
|
|
"SECP521R1",
|
|
|
|
);
|
2020-08-25 11:16:52 +00:00
|
|
|
ENUM_NEXT(tls_named_group_names, TLS_CURVE25519, TLS_CURVE448, TLS_SECP521R1,
|
2020-05-21 07:37:38 +00:00
|
|
|
"CURVE25519",
|
|
|
|
"CURVE448",
|
|
|
|
);
|
2020-08-25 11:16:52 +00:00
|
|
|
ENUM_NEXT(tls_named_group_names, TLS_FFDHE2048, TLS_FFDHE8192, TLS_CURVE448,
|
2020-05-21 07:37:38 +00:00
|
|
|
"FFDHE2048",
|
|
|
|
"FFDHE3072",
|
|
|
|
"FFDHE4096",
|
|
|
|
"FFDHE6144",
|
|
|
|
"FFDHE8192",
|
|
|
|
);
|
|
|
|
ENUM_END(tls_named_group_names, TLS_FFDHE8192);
|
2010-09-03 08:59:01 +00:00
|
|
|
|
2010-09-06 16:36:27 +00:00
|
|
|
ENUM(tls_ansi_point_format_names, TLS_ANSI_COMPRESSED, TLS_ANSI_HYBRID_Y,
|
2010-09-06 13:31:32 +00:00
|
|
|
"compressed",
|
|
|
|
"compressed y",
|
|
|
|
"uncompressed",
|
|
|
|
"uncompressed y",
|
|
|
|
"hybrid",
|
|
|
|
"hybrid y",
|
|
|
|
);
|
2010-09-02 08:05:11 +00:00
|
|
|
|
2010-09-06 16:42:43 +00:00
|
|
|
ENUM(tls_ec_point_format_names,
|
|
|
|
TLS_EC_POINT_UNCOMPRESSED, TLS_EC_POINT_ANSIX962_COMPRESSED_CHAR2,
|
|
|
|
"uncompressed",
|
|
|
|
"ansiX962 compressed prime",
|
|
|
|
"ansiX962 compressed char2",
|
|
|
|
);
|
|
|
|
|
2010-01-25 11:21:57 +00:00
|
|
|
typedef struct private_tls_crypto_t private_tls_crypto_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Private data of an tls_crypto_t object.
|
|
|
|
*/
|
|
|
|
struct private_tls_crypto_t {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Public tls_crypto_t interface.
|
|
|
|
*/
|
|
|
|
tls_crypto_t public;
|
2010-02-04 10:17:48 +00:00
|
|
|
|
2010-02-05 13:39:19 +00:00
|
|
|
/**
|
|
|
|
* Protection layer
|
|
|
|
*/
|
|
|
|
tls_protection_t *protection;
|
|
|
|
|
2010-02-04 10:17:48 +00:00
|
|
|
/**
|
|
|
|
* List of supported/acceptable cipher suites
|
|
|
|
*/
|
|
|
|
tls_cipher_suite_t *suites;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Number of supported suites
|
|
|
|
*/
|
|
|
|
int suite_count;
|
|
|
|
|
2020-05-21 07:37:38 +00:00
|
|
|
/**
|
|
|
|
* HKDF for TLS 1.3
|
|
|
|
*/
|
|
|
|
tls_hkdf_t *hkdf;
|
|
|
|
|
2010-02-04 10:17:48 +00:00
|
|
|
/**
|
|
|
|
* Selected cipher suite
|
|
|
|
*/
|
|
|
|
tls_cipher_suite_t suite;
|
|
|
|
|
2010-09-03 16:11:03 +00:00
|
|
|
/**
|
|
|
|
* RSA supported?
|
|
|
|
*/
|
|
|
|
bool rsa;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ECDSA supported?
|
|
|
|
*/
|
|
|
|
bool ecdsa;
|
|
|
|
|
2010-02-04 10:17:48 +00:00
|
|
|
/**
|
|
|
|
* TLS context
|
|
|
|
*/
|
|
|
|
tls_t *tls;
|
|
|
|
|
2011-12-31 00:41:56 +00:00
|
|
|
/**
|
|
|
|
* TLS session cache
|
|
|
|
*/
|
|
|
|
tls_cache_t *cache;
|
|
|
|
|
2010-02-05 13:25:38 +00:00
|
|
|
/**
|
2018-02-13 11:04:12 +00:00
|
|
|
* All handshake data concatenated
|
2010-02-05 13:25:38 +00:00
|
|
|
*/
|
|
|
|
chunk_t handshake;
|
|
|
|
|
2010-02-04 10:17:48 +00:00
|
|
|
/**
|
|
|
|
* Connection state TLS PRF
|
|
|
|
*/
|
|
|
|
tls_prf_t *prf;
|
2010-02-04 17:18:10 +00:00
|
|
|
|
|
|
|
/**
|
2014-02-03 12:20:46 +00:00
|
|
|
* AEAD transform for inbound traffic
|
2010-02-04 17:18:10 +00:00
|
|
|
*/
|
2014-02-03 12:20:46 +00:00
|
|
|
tls_aead_t *aead_in;
|
2010-02-04 17:18:10 +00:00
|
|
|
|
|
|
|
/**
|
2014-02-03 12:20:46 +00:00
|
|
|
* AEAD transform for outbound traffic
|
2010-02-04 17:18:10 +00:00
|
|
|
*/
|
2014-02-03 12:20:46 +00:00
|
|
|
tls_aead_t *aead_out;
|
2010-02-05 11:28:48 +00:00
|
|
|
|
|
|
|
/**
|
2010-08-06 15:33:46 +00:00
|
|
|
* EAP-[T]TLS MSK
|
2010-02-05 11:28:48 +00:00
|
|
|
*/
|
|
|
|
chunk_t msk;
|
2010-08-06 15:33:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* ASCII string constant used as seed for EAP-[T]TLS MSK PRF
|
|
|
|
*/
|
|
|
|
char *msk_label;
|
2010-01-25 11:21:57 +00:00
|
|
|
};
|
|
|
|
|
2010-02-04 17:18:10 +00:00
|
|
|
typedef struct {
|
|
|
|
tls_cipher_suite_t suite;
|
2010-09-03 10:50:18 +00:00
|
|
|
key_type_t key;
|
|
|
|
diffie_hellman_group_t dh;
|
2010-02-04 17:18:10 +00:00
|
|
|
hash_algorithm_t hash;
|
|
|
|
pseudo_random_function_t prf;
|
|
|
|
integrity_algorithm_t mac;
|
|
|
|
encryption_algorithm_t encr;
|
|
|
|
size_t encr_size;
|
2020-08-25 11:54:08 +00:00
|
|
|
tls_version_t min_version;
|
|
|
|
tls_version_t max_version;
|
2010-02-04 17:18:10 +00:00
|
|
|
} suite_algs_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Mapping suites to a set of algorithms
|
2020-09-04 17:36:40 +00:00
|
|
|
*
|
|
|
|
* The order represents the descending preference of cipher suites and follows
|
|
|
|
* this rule set:
|
|
|
|
*
|
|
|
|
* 1. TLS 1.3 > Legacy TLS
|
|
|
|
* 2. AES > CAMELLIA > NULL
|
|
|
|
* 3. AES256 > AES128
|
|
|
|
* 4. GCM > CBC
|
|
|
|
* 5. ECDHE > DHE > NULL
|
|
|
|
* 6. ECDSA > RSA
|
|
|
|
* 7. SHA384 > SHA256 > SHA1
|
|
|
|
*
|
2010-02-04 17:18:10 +00:00
|
|
|
*/
|
|
|
|
static suite_algs_t suite_algs[] = {
|
2020-05-21 07:37:38 +00:00
|
|
|
/* Cipher suites of TLS 1.3: key exchange and authentication
|
|
|
|
* delegated to extensions, therefore KEY_ANY, MODP_NONE, PRF_UNDEFINED */
|
|
|
|
{ TLS_AES_256_GCM_SHA384,
|
|
|
|
KEY_ANY, MODP_NONE,
|
|
|
|
HASH_SHA384, PRF_UNDEFINED,
|
|
|
|
AUTH_HMAC_SHA2_384_384, ENCR_AES_GCM_ICV16, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_3, TLS_1_3,
|
2020-05-21 07:37:38 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_AES_128_GCM_SHA256,
|
|
|
|
KEY_ANY, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_UNDEFINED,
|
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_GCM_ICV16, 16,
|
|
|
|
TLS_1_3, TLS_1_3,
|
|
|
|
},
|
2020-05-21 07:37:38 +00:00
|
|
|
{ TLS_CHACHA20_POLY1305_SHA256,
|
|
|
|
KEY_ANY, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_UNDEFINED,
|
2020-08-26 10:18:06 +00:00
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_CHACHA20_POLY1305, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_3, TLS_1_3,
|
2020-05-21 07:37:38 +00:00
|
|
|
},
|
|
|
|
{ TLS_AES_128_CCM_SHA256,
|
2020-08-25 11:54:08 +00:00
|
|
|
KEY_ANY, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_UNDEFINED,
|
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_CCM_ICV16, 16,
|
|
|
|
TLS_1_3, TLS_1_3,
|
2020-05-21 07:37:38 +00:00
|
|
|
},
|
|
|
|
{ TLS_AES_128_CCM_8_SHA256,
|
2020-08-25 11:54:08 +00:00
|
|
|
KEY_ANY, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_UNDEFINED,
|
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_CCM_ICV8, 16,
|
|
|
|
TLS_1_3, TLS_1_3,
|
2020-05-21 07:37:38 +00:00
|
|
|
},
|
|
|
|
/* Legacy TLS cipher suites */
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
|
|
KEY_ECDSA, ECP_384_BIT,
|
|
|
|
HASH_SHA384, PRF_HMAC_SHA2_384,
|
|
|
|
AUTH_UNDEFINED, ENCR_AES_GCM_ICV16, 32,
|
|
|
|
TLS_1_2, TLS_1_2,
|
2010-09-03 10:54:40 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
|
|
|
KEY_ECDSA, ECP_384_BIT,
|
|
|
|
HASH_SHA384, PRF_HMAC_SHA2_384,
|
|
|
|
AUTH_HMAC_SHA2_384_384, ENCR_AES_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-09-03 10:54:40 +00:00
|
|
|
},
|
|
|
|
{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
|
|
KEY_ECDSA, ECP_384_BIT,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_AES_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_0, TLS_1_2,
|
2010-09-03 10:54:40 +00:00
|
|
|
},
|
2014-02-03 17:08:11 +00:00
|
|
|
{ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
|
|
KEY_ECDSA, ECP_256_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_UNDEFINED, ENCR_AES_GCM_ICV16, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2014-02-03 17:08:11 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
|
|
|
KEY_ECDSA, ECP_256_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2014-02-03 17:08:11 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
|
|
KEY_ECDSA, ECP_256_BIT,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_AES_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_0, TLS_1_2,
|
2010-09-03 10:54:40 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
2010-09-03 15:24:39 +00:00
|
|
|
KEY_RSA, ECP_384_BIT,
|
2020-09-04 17:36:40 +00:00
|
|
|
HASH_SHA384, PRF_HMAC_SHA2_384,
|
|
|
|
AUTH_UNDEFINED, ENCR_AES_GCM_ICV16, 32,
|
|
|
|
TLS_1_2, TLS_1_2,
|
2010-09-03 10:54:40 +00:00
|
|
|
},
|
|
|
|
{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
2010-09-03 15:24:39 +00:00
|
|
|
KEY_RSA, ECP_384_BIT,
|
2010-09-03 10:54:40 +00:00
|
|
|
HASH_SHA384, PRF_HMAC_SHA2_384,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA2_384_384, ENCR_AES_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-09-03 10:54:40 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
|
|
KEY_RSA, ECP_384_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
|
|
|
AUTH_HMAC_SHA1_160, ENCR_AES_CBC, 32,
|
|
|
|
TLS_1_0, TLS_1_2,
|
|
|
|
},
|
2014-02-03 17:08:11 +00:00
|
|
|
{ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
|
|
KEY_RSA, ECP_256_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_UNDEFINED, ENCR_AES_GCM_ICV16, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2014-02-03 17:08:11 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
|
|
|
KEY_RSA, ECP_256_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2014-02-03 17:08:11 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
|
|
KEY_RSA, ECP_256_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_AES_CBC, 16,
|
2020-09-04 17:36:40 +00:00
|
|
|
TLS_1_0, TLS_1_2,
|
2010-09-02 17:27:37 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
|
|
KEY_RSA, MODP_4096_BIT,
|
|
|
|
HASH_SHA384, PRF_HMAC_SHA2_384,
|
|
|
|
AUTH_UNDEFINED, ENCR_AES_GCM_ICV16, 32,
|
|
|
|
TLS_1_2, TLS_1_2,
|
|
|
|
},
|
|
|
|
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
|
|
|
KEY_RSA, MODP_4096_BIT,
|
2010-09-03 10:50:18 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-09-02 17:27:37 +00:00
|
|
|
},
|
|
|
|
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_3072_BIT,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_AES_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
SSL_3_0, TLS_1_2,
|
2010-09-02 17:27:37 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_4096_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_CAMELLIA_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-09-02 17:27:37 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
|
|
|
KEY_RSA, MODP_3072_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
|
|
|
AUTH_HMAC_SHA1_160, ENCR_CAMELLIA_CBC, 32,
|
|
|
|
SSL_3_0, TLS_1_2,
|
|
|
|
},
|
2014-02-03 17:08:11 +00:00
|
|
|
{ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
|
|
KEY_RSA, MODP_3072_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_UNDEFINED, ENCR_AES_GCM_ICV16, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2014-02-03 17:08:11 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
|
|
|
KEY_RSA, MODP_3072_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2014-02-03 17:08:11 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_2048_BIT,
|
2020-09-04 17:36:40 +00:00
|
|
|
HASH_SHA256,PRF_HMAC_SHA2_256,
|
|
|
|
AUTH_HMAC_SHA1_160, ENCR_AES_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
SSL_3_0, TLS_1_2,
|
2010-09-02 17:27:37 +00:00
|
|
|
},
|
|
|
|
{ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_3072_BIT,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_CAMELLIA_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-09-02 17:27:37 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_2048_BIT,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_CAMELLIA_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
SSL_3_0, TLS_1_2,
|
2010-09-02 17:27:37 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_RSA_WITH_AES_256_GCM_SHA384,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
2020-09-04 17:36:40 +00:00
|
|
|
HASH_SHA384, PRF_HMAC_SHA2_384,
|
|
|
|
AUTH_UNDEFINED, ENCR_AES_GCM_ICV16, 32,
|
|
|
|
TLS_1_2, TLS_1_2,
|
2010-08-20 09:01:57 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_RSA_WITH_AES_256_CBC_SHA256,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-02-04 17:18:10 +00:00
|
|
|
},
|
|
|
|
{ TLS_RSA_WITH_AES_256_CBC_SHA,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_AES_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
SSL_3_0, TLS_1_2,
|
2010-02-04 17:18:10 +00:00
|
|
|
},
|
2014-02-03 17:08:11 +00:00
|
|
|
{ TLS_RSA_WITH_AES_128_GCM_SHA256,
|
|
|
|
KEY_RSA, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_UNDEFINED, ENCR_AES_GCM_ICV16, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2014-02-03 17:08:11 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_RSA_WITH_AES_128_CBC_SHA256,
|
2014-02-03 17:08:11 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
2020-09-04 17:36:40 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_AES_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2014-02-03 17:08:11 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_RSA_WITH_AES_128_CBC_SHA,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_AES_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
SSL_3_0, TLS_1_2,
|
2010-08-20 09:01:57 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_CAMELLIA_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-08-20 09:01:57 +00:00
|
|
|
},
|
|
|
|
{ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_CAMELLIA_CBC, 32,
|
2020-08-25 11:54:08 +00:00
|
|
|
SSL_3_0, TLS_1_2,
|
2010-08-20 09:01:57 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_CAMELLIA_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-02-04 17:18:10 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_CAMELLIA_CBC, 16,
|
2020-08-25 11:54:08 +00:00
|
|
|
SSL_3_0, TLS_1_2,
|
2010-08-25 16:30:09 +00:00
|
|
|
},
|
2010-09-03 10:54:40 +00:00
|
|
|
{ TLS_ECDHE_ECDSA_WITH_NULL_SHA,
|
|
|
|
KEY_ECDSA, ECP_256_BIT,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_NULL, 0,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_0, TLS_1_2,
|
2010-09-03 10:54:40 +00:00
|
|
|
},
|
|
|
|
{ TLS_ECDHE_RSA_WITH_NULL_SHA,
|
|
|
|
KEY_ECDSA, ECP_256_BIT,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_NULL, 0,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_0, TLS_1_2,
|
2010-09-03 10:54:40 +00:00
|
|
|
},
|
2010-08-25 16:30:09 +00:00
|
|
|
{ TLS_RSA_WITH_NULL_SHA256,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-05-21 07:37:38 +00:00
|
|
|
AUTH_HMAC_SHA2_256_256, ENCR_NULL, 0,
|
2020-08-25 11:54:08 +00:00
|
|
|
TLS_1_2, TLS_1_2,
|
2010-08-25 16:30:09 +00:00
|
|
|
},
|
2020-09-04 17:36:40 +00:00
|
|
|
{ TLS_RSA_WITH_NULL_SHA,
|
2010-09-03 10:50:18 +00:00
|
|
|
KEY_RSA, MODP_NONE,
|
2011-12-24 11:35:28 +00:00
|
|
|
HASH_SHA256, PRF_HMAC_SHA2_256,
|
2020-09-04 17:36:40 +00:00
|
|
|
AUTH_HMAC_SHA1_160, ENCR_NULL, 0,
|
|
|
|
SSL_3_0, TLS_1_2,
|
2010-08-25 16:30:09 +00:00
|
|
|
},
|
2010-02-04 17:18:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2011-07-20 13:57:53 +00:00
|
|
|
* Look up algorithms by a suite
|
2010-02-04 17:18:10 +00:00
|
|
|
*/
|
|
|
|
static suite_algs_t *find_suite(tls_cipher_suite_t suite)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < countof(suite_algs); i++)
|
|
|
|
{
|
|
|
|
if (suite_algs[i].suite == suite)
|
|
|
|
{
|
|
|
|
return &suite_algs[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-04 10:17:48 +00:00
|
|
|
/**
|
2010-08-20 10:10:21 +00:00
|
|
|
* Filter a suite list using a transform enumerator
|
2010-02-04 10:17:48 +00:00
|
|
|
*/
|
2014-03-24 13:28:50 +00:00
|
|
|
static void filter_suite(suite_algs_t suites[], int *count, int offset,
|
2010-08-20 10:10:21 +00:00
|
|
|
enumerator_t*(*create_enumerator)(crypto_factory_t*))
|
2010-01-25 11:21:57 +00:00
|
|
|
{
|
2010-12-18 15:31:01 +00:00
|
|
|
const char *plugin_name;
|
2010-08-20 10:10:21 +00:00
|
|
|
suite_algs_t current;
|
2010-12-18 19:24:53 +00:00
|
|
|
int *current_alg, i, remaining = 0;
|
2010-08-20 10:10:21 +00:00
|
|
|
enumerator_t *enumerator;
|
2010-01-25 11:21:57 +00:00
|
|
|
|
2010-08-20 10:10:21 +00:00
|
|
|
memset(¤t, 0, sizeof(current));
|
2010-12-18 19:24:53 +00:00
|
|
|
current_alg = (int*)((char*)¤t + offset);
|
|
|
|
|
2010-08-20 10:10:21 +00:00
|
|
|
for (i = 0; i < *count; i++)
|
2010-01-25 11:21:57 +00:00
|
|
|
{
|
2014-03-11 09:57:18 +00:00
|
|
|
if (create_enumerator == lib->crypto->create_crypter_enumerator &&
|
|
|
|
encryption_algorithm_is_aead(suites[i].encr))
|
|
|
|
{ /* filtering crypters, but current suite uses an AEAD, apply */
|
|
|
|
suites[remaining] = suites[i];
|
|
|
|
remaining++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (create_enumerator == lib->crypto->create_aead_enumerator &&
|
|
|
|
!encryption_algorithm_is_aead(suites[i].encr))
|
|
|
|
{ /* filtering AEADs, but current suite doesn't use one, apply */
|
|
|
|
suites[remaining] = suites[i];
|
|
|
|
remaining++;
|
|
|
|
continue;
|
|
|
|
}
|
2010-08-20 10:10:21 +00:00
|
|
|
enumerator = create_enumerator(lib->crypto);
|
2010-12-18 19:24:53 +00:00
|
|
|
while (enumerator->enumerate(enumerator, current_alg, &plugin_name))
|
2010-01-25 11:21:57 +00:00
|
|
|
{
|
2014-03-11 09:57:18 +00:00
|
|
|
if (current.encr && current.encr != suites[i].encr)
|
2010-01-25 11:21:57 +00:00
|
|
|
{
|
2014-03-11 09:57:18 +00:00
|
|
|
if (suites[i].encr != ENCR_NULL)
|
|
|
|
{ /* skip, ENCR does not match nor is NULL */
|
|
|
|
continue;
|
|
|
|
}
|
2010-01-25 11:21:57 +00:00
|
|
|
}
|
2014-03-11 09:57:18 +00:00
|
|
|
if (current.mac && current.mac != suites[i].mac)
|
|
|
|
{
|
|
|
|
if (suites[i].mac != AUTH_UNDEFINED)
|
|
|
|
{ /* skip, MAC does not match nor is it undefined */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (current.prf && current.prf != suites[i].prf)
|
2020-08-25 11:47:00 +00:00
|
|
|
{
|
|
|
|
if (suites[i].prf != PRF_UNDEFINED)
|
|
|
|
{
|
|
|
|
/* skip, PRF does not match nor is it undefined */
|
|
|
|
continue;
|
|
|
|
}
|
2014-03-11 09:57:18 +00:00
|
|
|
}
|
|
|
|
if (current.hash && current.hash != suites[i].hash)
|
|
|
|
{ /* skip, hash does not match */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (current.dh && current.dh != suites[i].dh)
|
|
|
|
{
|
|
|
|
if (suites[i].dh != MODP_NONE)
|
|
|
|
{ /* skip DH group, does not match nor NONE */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* suite supported, apply */
|
|
|
|
suites[remaining] = suites[i];
|
|
|
|
remaining++;
|
|
|
|
break;
|
2010-01-25 11:21:57 +00:00
|
|
|
}
|
2010-08-20 10:10:21 +00:00
|
|
|
enumerator->destroy(enumerator);
|
2010-01-25 11:21:57 +00:00
|
|
|
}
|
2010-08-20 10:10:21 +00:00
|
|
|
*count = remaining;
|
|
|
|
}
|
|
|
|
|
2010-08-20 13:02:25 +00:00
|
|
|
/**
|
|
|
|
* Purge NULL encryption cipher suites from list
|
|
|
|
*/
|
2014-03-24 13:28:50 +00:00
|
|
|
static void filter_null_suites(suite_algs_t suites[], int *count)
|
2010-08-20 13:02:25 +00:00
|
|
|
{
|
|
|
|
int i, remaining = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < *count; i++)
|
|
|
|
{
|
|
|
|
if (suites[i].encr != ENCR_NULL)
|
|
|
|
{
|
|
|
|
suites[remaining] = suites[i];
|
|
|
|
remaining++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*count = remaining;
|
|
|
|
}
|
|
|
|
|
2010-09-03 16:11:03 +00:00
|
|
|
/**
|
|
|
|
* Purge suites using a given key type
|
|
|
|
*/
|
|
|
|
static void filter_key_suites(private_tls_crypto_t *this,
|
|
|
|
suite_algs_t suites[], int *count, key_type_t key)
|
|
|
|
{
|
|
|
|
int i, remaining = 0;
|
|
|
|
|
|
|
|
DBG2(DBG_TLS, "disabling %N suites, no backend found", key_type_names, key);
|
|
|
|
for (i = 0; i < *count; i++)
|
|
|
|
{
|
|
|
|
if (suites[i].key != key)
|
|
|
|
{
|
|
|
|
suites[remaining] = suites[i];
|
|
|
|
remaining++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*count = remaining;
|
|
|
|
}
|
|
|
|
|
2010-09-06 14:37:45 +00:00
|
|
|
/**
|
|
|
|
* Filter suites by key exchange user config
|
|
|
|
*/
|
|
|
|
static void filter_key_exchange_config_suites(private_tls_crypto_t *this,
|
|
|
|
suite_algs_t suites[], int *count)
|
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
int i, remaining = 0;
|
|
|
|
char *token, *config;
|
|
|
|
|
2014-01-28 16:26:50 +00:00
|
|
|
config = lib->settings->get_str(lib->settings, "%s.tls.key_exchange", NULL,
|
|
|
|
lib->ns);
|
2010-09-06 14:37:45 +00:00
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
for (i = 0; i < *count; i++)
|
|
|
|
{
|
|
|
|
enumerator = enumerator_create_token(config, ",", " ");
|
|
|
|
while (enumerator->enumerate(enumerator, &token))
|
|
|
|
{
|
|
|
|
if (strcaseeq(token, "ecdhe-ecdsa") &&
|
|
|
|
diffie_hellman_group_is_ec(suites[i].dh) &&
|
|
|
|
suites[i].key == KEY_ECDSA)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "ecdhe-rsa") &&
|
|
|
|
diffie_hellman_group_is_ec(suites[i].dh) &&
|
|
|
|
suites[i].key == KEY_RSA)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "dhe-rsa") &&
|
|
|
|
!diffie_hellman_group_is_ec(suites[i].dh) &&
|
|
|
|
suites[i].dh != MODP_NONE &&
|
|
|
|
suites[i].key == KEY_RSA)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "rsa") &&
|
|
|
|
suites[i].dh == MODP_NONE &&
|
|
|
|
suites[i].key == KEY_RSA)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
}
|
|
|
|
*count = remaining;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Filter suites by cipher user config
|
|
|
|
*/
|
|
|
|
static void filter_cipher_config_suites(private_tls_crypto_t *this,
|
|
|
|
suite_algs_t suites[], int *count)
|
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
int i, remaining = 0;
|
|
|
|
char *token, *config;
|
|
|
|
|
2014-01-28 16:26:50 +00:00
|
|
|
config = lib->settings->get_str(lib->settings, "%s.tls.cipher", NULL,
|
|
|
|
lib->ns);
|
2010-09-06 14:37:45 +00:00
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
for (i = 0; i < *count; i++)
|
|
|
|
{
|
|
|
|
enumerator = enumerator_create_token(config, ",", " ");
|
|
|
|
while (enumerator->enumerate(enumerator, &token))
|
|
|
|
{
|
|
|
|
if (strcaseeq(token, "aes128") &&
|
|
|
|
suites[i].encr == ENCR_AES_CBC &&
|
|
|
|
suites[i].encr_size == 16)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "aes256") &&
|
|
|
|
suites[i].encr == ENCR_AES_CBC &&
|
|
|
|
suites[i].encr_size == 32)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
2014-02-03 17:08:11 +00:00
|
|
|
if (strcaseeq(token, "aes128gcm") &&
|
|
|
|
suites[i].encr == ENCR_AES_GCM_ICV16 &&
|
|
|
|
suites[i].encr_size == 16)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "aes256gcm") &&
|
|
|
|
suites[i].encr == ENCR_AES_GCM_ICV16 &&
|
|
|
|
suites[i].encr_size == 32)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
2010-09-06 14:37:45 +00:00
|
|
|
if (strcaseeq(token, "camellia128") &&
|
|
|
|
suites[i].encr == ENCR_CAMELLIA_CBC &&
|
|
|
|
suites[i].encr_size == 16)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "camellia256") &&
|
|
|
|
suites[i].encr == ENCR_CAMELLIA_CBC &&
|
|
|
|
suites[i].encr_size == 32)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "null") &&
|
|
|
|
suites[i].encr == ENCR_NULL)
|
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
}
|
|
|
|
*count = remaining;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Filter suites by mac user config
|
|
|
|
*/
|
|
|
|
static void filter_mac_config_suites(private_tls_crypto_t *this,
|
|
|
|
suite_algs_t suites[], int *count)
|
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
int i, remaining = 0;
|
|
|
|
char *token, *config;
|
|
|
|
|
2014-01-28 16:26:50 +00:00
|
|
|
config = lib->settings->get_str(lib->settings, "%s.tls.mac", NULL,
|
|
|
|
lib->ns);
|
2010-09-06 14:37:45 +00:00
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
for (i = 0; i < *count; i++)
|
|
|
|
{
|
|
|
|
enumerator = enumerator_create_token(config, ",", " ");
|
|
|
|
while (enumerator->enumerate(enumerator, &token))
|
|
|
|
{
|
|
|
|
if (strcaseeq(token, "sha1") &&
|
2012-02-07 08:37:51 +00:00
|
|
|
suites[i].mac == AUTH_HMAC_SHA1_160)
|
2010-09-06 14:37:45 +00:00
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "sha256") &&
|
2012-02-07 08:37:51 +00:00
|
|
|
suites[i].mac == AUTH_HMAC_SHA2_256_256)
|
2010-09-06 14:37:45 +00:00
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strcaseeq(token, "sha384") &&
|
2012-02-07 08:37:51 +00:00
|
|
|
suites[i].mac == AUTH_HMAC_SHA2_384_384)
|
2010-09-06 14:37:45 +00:00
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
}
|
|
|
|
*count = remaining;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-06 14:44:47 +00:00
|
|
|
/**
|
|
|
|
* Filter for specific suites specified in strongswan.conf
|
|
|
|
*/
|
|
|
|
static void filter_specific_config_suites(private_tls_crypto_t *this,
|
|
|
|
suite_algs_t suites[], int *count)
|
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
int i, remaining = 0, suite;
|
|
|
|
char *token, *config;
|
|
|
|
|
2014-01-28 16:26:50 +00:00
|
|
|
config = lib->settings->get_str(lib->settings, "%s.tls.suites", NULL,
|
|
|
|
lib->ns);
|
2010-09-06 14:44:47 +00:00
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
for (i = 0; i < *count; i++)
|
|
|
|
{
|
|
|
|
enumerator = enumerator_create_token(config, ",", " ");
|
|
|
|
while (enumerator->enumerate(enumerator, &token))
|
|
|
|
{
|
2014-05-16 09:57:54 +00:00
|
|
|
if (enum_from_name(tls_cipher_suite_names, token, &suite) &&
|
|
|
|
suite == suites[i].suite)
|
2010-09-06 14:44:47 +00:00
|
|
|
{
|
|
|
|
suites[remaining++] = suites[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
}
|
|
|
|
*count = remaining;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-26 20:19:16 +00:00
|
|
|
/**
|
|
|
|
* Filter key exchange curves by curve user config
|
|
|
|
*/
|
|
|
|
static bool filter_curve_config(tls_named_group_t curve)
|
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
char *token, *config;
|
|
|
|
|
2021-01-18 17:11:55 +00:00
|
|
|
config = lib->settings->get_str(lib->settings, "%s.tls.ke_group", NULL,
|
|
|
|
lib->ns);
|
2020-09-26 20:19:16 +00:00
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
enumerator = enumerator_create_token(config, ",", " ");
|
|
|
|
while (enumerator->enumerate(enumerator, &token))
|
|
|
|
{
|
|
|
|
const proposal_token_t *tok;
|
|
|
|
|
|
|
|
tok = lib->proposal->get_token(lib->proposal, token);
|
|
|
|
if (tok != NULL && tok->type == DIFFIE_HELLMAN_GROUP &&
|
|
|
|
curve == tls_ec_group_to_curve(tok->algorithm))
|
|
|
|
{
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
}
|
|
|
|
return !config;
|
|
|
|
}
|
|
|
|
|
2014-03-24 13:28:50 +00:00
|
|
|
/**
|
|
|
|
* Filter out unsupported suites on given suite array
|
|
|
|
*/
|
|
|
|
static void filter_unsupported_suites(suite_algs_t suites[], int *count)
|
|
|
|
{
|
|
|
|
/* filter suite list by each algorithm */
|
2020-08-25 11:47:00 +00:00
|
|
|
filter_suite(suites, count, offsetof(suite_algs_t, encr),
|
|
|
|
lib->crypto->create_aead_enumerator);
|
|
|
|
filter_suite(suites, count, offsetof(suite_algs_t, prf),
|
|
|
|
lib->crypto->create_prf_enumerator);
|
2014-03-24 13:28:50 +00:00
|
|
|
filter_suite(suites, count, offsetof(suite_algs_t, encr),
|
|
|
|
lib->crypto->create_crypter_enumerator);
|
|
|
|
filter_suite(suites, count, offsetof(suite_algs_t, mac),
|
|
|
|
lib->crypto->create_signer_enumerator);
|
|
|
|
filter_suite(suites, count, offsetof(suite_algs_t, hash),
|
|
|
|
lib->crypto->create_hasher_enumerator);
|
|
|
|
filter_suite(suites, count, offsetof(suite_algs_t, dh),
|
|
|
|
lib->crypto->create_dh_enumerator);
|
|
|
|
}
|
|
|
|
|
2010-08-20 10:10:21 +00:00
|
|
|
/**
|
|
|
|
* Initialize the cipher suite list
|
|
|
|
*/
|
2020-08-25 13:46:29 +00:00
|
|
|
static void build_cipher_suite_list(private_tls_crypto_t *this)
|
2010-08-20 10:10:21 +00:00
|
|
|
{
|
|
|
|
suite_algs_t suites[countof(suite_algs)];
|
2020-09-04 16:29:43 +00:00
|
|
|
tls_version_t min_version, max_version, new_min_version, new_max_version;
|
2020-08-25 13:46:29 +00:00
|
|
|
bool require_encryption;
|
2020-08-25 11:54:08 +00:00
|
|
|
int count = 0, i;
|
2010-01-25 11:21:57 +00:00
|
|
|
|
2020-08-25 13:46:29 +00:00
|
|
|
switch (this->tls->get_purpose(this->tls))
|
|
|
|
{
|
|
|
|
case TLS_PURPOSE_EAP_TLS:
|
|
|
|
case TLS_PURPOSE_GENERIC_NULLOK:
|
|
|
|
require_encryption = FALSE;
|
|
|
|
break;
|
|
|
|
case TLS_PURPOSE_EAP_PEAP:
|
|
|
|
case TLS_PURPOSE_EAP_TTLS:
|
|
|
|
case TLS_PURPOSE_GENERIC:
|
|
|
|
require_encryption = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-08-25 11:54:08 +00:00
|
|
|
min_version = this->tls->get_version_min(this->tls);
|
|
|
|
max_version = this->tls->get_version_max(this->tls);
|
|
|
|
|
|
|
|
/* copy all suites appropriate for the current min/max versions */
|
|
|
|
for (i = 0; i < countof(suite_algs); i++)
|
2010-01-25 11:21:57 +00:00
|
|
|
{
|
2020-08-25 11:54:08 +00:00
|
|
|
if (suite_algs[i].min_version <= max_version &&
|
|
|
|
suite_algs[i].max_version >= min_version)
|
|
|
|
{
|
|
|
|
suites[count++] = suite_algs[i];
|
|
|
|
}
|
2010-02-04 10:17:48 +00:00
|
|
|
}
|
2014-03-24 13:28:50 +00:00
|
|
|
|
2010-08-20 13:02:25 +00:00
|
|
|
if (require_encryption)
|
|
|
|
{
|
2014-03-24 13:28:50 +00:00
|
|
|
filter_null_suites(suites, &count);
|
2010-08-20 13:02:25 +00:00
|
|
|
}
|
2010-09-03 16:11:03 +00:00
|
|
|
if (!this->rsa)
|
|
|
|
{
|
|
|
|
filter_key_suites(this, suites, &count, KEY_RSA);
|
|
|
|
}
|
|
|
|
if (!this->ecdsa)
|
|
|
|
{
|
|
|
|
filter_key_suites(this, suites, &count, KEY_ECDSA);
|
|
|
|
}
|
|
|
|
|
2014-03-24 13:28:50 +00:00
|
|
|
filter_unsupported_suites(suites, &count);
|
2010-08-20 10:10:21 +00:00
|
|
|
|
2010-09-06 14:37:45 +00:00
|
|
|
/* filter suites with strongswan.conf options */
|
|
|
|
filter_key_exchange_config_suites(this, suites, &count);
|
|
|
|
filter_cipher_config_suites(this, suites, &count);
|
|
|
|
filter_mac_config_suites(this, suites, &count);
|
2010-09-06 14:44:47 +00:00
|
|
|
filter_specific_config_suites(this, suites, &count);
|
2010-09-06 14:37:45 +00:00
|
|
|
|
2010-08-21 10:51:54 +00:00
|
|
|
free(this->suites);
|
|
|
|
this->suite_count = count;
|
|
|
|
this->suites = malloc(sizeof(tls_cipher_suite_t) * count);
|
|
|
|
|
2010-08-20 13:57:47 +00:00
|
|
|
DBG2(DBG_TLS, "%d supported TLS cipher suites:", count);
|
2020-09-04 16:29:43 +00:00
|
|
|
new_min_version = max_version;
|
|
|
|
new_max_version = min_version;
|
2010-08-20 10:10:21 +00:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2010-08-20 13:57:47 +00:00
|
|
|
DBG2(DBG_TLS, " %N", tls_cipher_suite_names, suites[i].suite);
|
2010-08-21 10:51:54 +00:00
|
|
|
this->suites[i] = suites[i].suite;
|
2020-09-04 16:29:43 +00:00
|
|
|
|
|
|
|
/* set TLS min/max versions appropriate to the final cipher suites */
|
|
|
|
new_max_version = max(new_max_version, suites[i].max_version);
|
|
|
|
new_min_version = min(new_min_version, suites[i].min_version);
|
|
|
|
}
|
|
|
|
new_max_version = min(new_max_version, max_version);
|
|
|
|
new_min_version = max(new_min_version, min_version);
|
|
|
|
|
2021-01-14 14:11:13 +00:00
|
|
|
if ((min_version != new_min_version || max_version != new_max_version) &&
|
|
|
|
this->tls->set_version(this->tls, new_min_version, new_max_version))
|
2020-09-04 16:29:43 +00:00
|
|
|
{
|
|
|
|
DBG2(DBG_TLS, "TLS min/max %N/%N according to the cipher suites",
|
2021-01-14 14:11:13 +00:00
|
|
|
tls_numeric_version_names, new_min_version,
|
|
|
|
tls_numeric_version_names, new_max_version);
|
2010-08-20 10:10:21 +00:00
|
|
|
}
|
2010-02-04 10:17:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
METHOD(tls_crypto_t, get_cipher_suites, int,
|
|
|
|
private_tls_crypto_t *this, tls_cipher_suite_t **suites)
|
|
|
|
{
|
2020-08-25 13:46:29 +00:00
|
|
|
if (!this->suites)
|
|
|
|
{
|
|
|
|
build_cipher_suite_list(this);
|
|
|
|
}
|
2020-11-19 13:40:30 +00:00
|
|
|
if (suites)
|
|
|
|
{
|
|
|
|
*suites = this->suites;
|
|
|
|
}
|
2010-02-04 10:17:48 +00:00
|
|
|
return this->suite_count;
|
|
|
|
}
|
|
|
|
|
2014-02-03 12:20:46 +00:00
|
|
|
/**
|
|
|
|
* Create NULL encryption transforms
|
|
|
|
*/
|
|
|
|
static bool create_null(private_tls_crypto_t *this, suite_algs_t *algs)
|
|
|
|
{
|
|
|
|
this->aead_in = tls_aead_create_null(algs->mac);
|
|
|
|
this->aead_out = tls_aead_create_null(algs->mac);
|
|
|
|
if (!this->aead_in || !this->aead_out)
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "selected TLS MAC %N not supported",
|
|
|
|
integrity_algorithm_names, algs->mac);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create traditional transforms
|
|
|
|
*/
|
|
|
|
static bool create_traditional(private_tls_crypto_t *this, suite_algs_t *algs)
|
|
|
|
{
|
2020-05-21 07:37:38 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) < TLS_1_1)
|
2014-02-03 12:20:46 +00:00
|
|
|
{
|
|
|
|
this->aead_in = tls_aead_create_implicit(algs->mac,
|
|
|
|
algs->encr, algs->encr_size);
|
|
|
|
this->aead_out = tls_aead_create_implicit(algs->mac,
|
|
|
|
algs->encr, algs->encr_size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->aead_in = tls_aead_create_explicit(algs->mac,
|
|
|
|
algs->encr, algs->encr_size);
|
|
|
|
this->aead_out = tls_aead_create_explicit(algs->mac,
|
|
|
|
algs->encr, algs->encr_size);
|
|
|
|
}
|
|
|
|
if (!this->aead_in || !this->aead_out)
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "selected TLS transforms %N-%u-%N not supported",
|
|
|
|
encryption_algorithm_names, algs->encr, algs->encr_size * 8,
|
|
|
|
integrity_algorithm_names, algs->mac);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2014-02-03 17:03:41 +00:00
|
|
|
/**
|
|
|
|
* Create AEAD transforms
|
|
|
|
*/
|
|
|
|
static bool create_aead(private_tls_crypto_t *this, suite_algs_t *algs)
|
|
|
|
{
|
2020-05-21 07:37:38 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) < TLS_1_3)
|
|
|
|
{
|
|
|
|
this->aead_in = tls_aead_create_aead(algs->encr, algs->encr_size);
|
|
|
|
this->aead_out = tls_aead_create_aead(algs->encr, algs->encr_size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->aead_in = tls_aead_create_seq(algs->encr, algs->encr_size);
|
|
|
|
this->aead_out = tls_aead_create_seq(algs->encr, algs->encr_size);
|
|
|
|
}
|
2014-02-03 17:03:41 +00:00
|
|
|
if (!this->aead_in || !this->aead_out)
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "selected TLS transforms %N-%u not supported",
|
|
|
|
encryption_algorithm_names, algs->encr, algs->encr_size * 8);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2014-02-03 12:20:46 +00:00
|
|
|
/**
|
|
|
|
* Clean up and unset AEAD transforms
|
|
|
|
*/
|
|
|
|
static void destroy_aeads(private_tls_crypto_t *this)
|
|
|
|
{
|
|
|
|
DESTROY_IF(this->aead_in);
|
|
|
|
DESTROY_IF(this->aead_out);
|
|
|
|
this->aead_in = this->aead_out = NULL;
|
|
|
|
}
|
|
|
|
|
2010-02-04 17:18:10 +00:00
|
|
|
/**
|
|
|
|
* Create crypto primitives
|
|
|
|
*/
|
2010-09-03 10:50:18 +00:00
|
|
|
static bool create_ciphers(private_tls_crypto_t *this, suite_algs_t *algs)
|
2010-02-04 17:18:10 +00:00
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
destroy_aeads(this);
|
2020-08-25 15:13:17 +00:00
|
|
|
DESTROY_IF(this->hkdf);
|
2010-02-04 17:18:10 +00:00
|
|
|
DESTROY_IF(this->prf);
|
2020-05-21 07:37:38 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) < TLS_1_3)
|
2010-02-04 17:18:10 +00:00
|
|
|
{
|
2020-05-21 07:37:38 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) < TLS_1_2)
|
|
|
|
{
|
|
|
|
this->prf = tls_prf_create_10();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->prf = tls_prf_create_12(algs->prf);
|
|
|
|
}
|
|
|
|
if (!this->prf)
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "selected TLS PRF not supported");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-05-21 07:37:38 +00:00
|
|
|
this->hkdf = tls_hkdf_create(algs->hash, chunk_empty);
|
|
|
|
if (!this->hkdf)
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "TLS HKDF creation unsuccessful");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
|
|
|
if (algs->encr == ENCR_NULL)
|
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
if (create_null(this, algs))
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
2014-02-03 17:03:41 +00:00
|
|
|
else if (encryption_algorithm_is_aead(algs->encr))
|
|
|
|
{
|
|
|
|
if (create_aead(this, algs))
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
2010-02-04 17:18:10 +00:00
|
|
|
else
|
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
if (create_traditional(this, algs))
|
2010-02-04 17:18:10 +00:00
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
return TRUE;
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
2014-02-03 12:20:46 +00:00
|
|
|
destroy_aeads(this);
|
|
|
|
return FALSE;
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
|
|
|
|
2010-02-04 10:17:48 +00:00
|
|
|
METHOD(tls_crypto_t, select_cipher_suite, tls_cipher_suite_t,
|
2010-09-03 10:50:18 +00:00
|
|
|
private_tls_crypto_t *this, tls_cipher_suite_t *suites, int count,
|
|
|
|
key_type_t key)
|
2010-02-04 10:17:48 +00:00
|
|
|
{
|
2010-09-03 10:50:18 +00:00
|
|
|
suite_algs_t *algs;
|
2010-02-04 10:17:48 +00:00
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i = 0; i < this->suite_count; i++)
|
|
|
|
{
|
|
|
|
for (j = 0; j < count; j++)
|
|
|
|
{
|
|
|
|
if (this->suites[i] == suites[j])
|
|
|
|
{
|
2010-09-03 10:50:18 +00:00
|
|
|
algs = find_suite(this->suites[i]);
|
|
|
|
if (algs)
|
2010-02-04 17:18:10 +00:00
|
|
|
{
|
2020-10-23 14:17:16 +00:00
|
|
|
if (key == KEY_ANY || key == algs->key ||
|
|
|
|
(algs->key == KEY_ECDSA && key == KEY_ED25519) ||
|
|
|
|
(algs->key == KEY_ECDSA && key == KEY_ED448))
|
2010-09-03 10:50:18 +00:00
|
|
|
{
|
|
|
|
if (create_ciphers(this, algs))
|
|
|
|
{
|
|
|
|
this->suite = this->suites[i];
|
|
|
|
return this->suite;
|
|
|
|
}
|
|
|
|
}
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
2010-02-04 10:17:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-09-02 17:24:56 +00:00
|
|
|
METHOD(tls_crypto_t, get_dh_group, diffie_hellman_group_t,
|
|
|
|
private_tls_crypto_t *this)
|
|
|
|
{
|
|
|
|
suite_algs_t *algs;
|
|
|
|
|
|
|
|
algs = find_suite(this->suite);
|
|
|
|
if (algs)
|
|
|
|
{
|
|
|
|
return algs->dh;
|
|
|
|
}
|
|
|
|
return MODP_NONE;
|
|
|
|
}
|
|
|
|
|
2014-01-15 14:51:03 +00:00
|
|
|
/**
|
2020-08-28 06:59:37 +00:00
|
|
|
* Parameters for RSA/PSS signature schemes
|
|
|
|
*/
|
|
|
|
#define PSS_PARAMS(bits) static rsa_pss_params_t pss_params_sha##bits = { \
|
|
|
|
.hash = HASH_SHA##bits, \
|
|
|
|
.mgf1_hash = HASH_SHA##bits, \
|
|
|
|
.salt_len = HASH_SIZE_SHA##bits, \
|
|
|
|
}
|
|
|
|
|
|
|
|
PSS_PARAMS(256);
|
|
|
|
PSS_PARAMS(384);
|
|
|
|
PSS_PARAMS(512);
|
|
|
|
|
2021-02-01 20:41:56 +00:00
|
|
|
typedef struct {
|
2020-08-28 06:59:37 +00:00
|
|
|
tls_signature_scheme_t sig;
|
|
|
|
signature_params_t params;
|
|
|
|
/* min/max versions for use in CertificateVerify */
|
|
|
|
tls_version_t min_version;
|
|
|
|
tls_version_t max_version;
|
2021-02-01 20:41:56 +00:00
|
|
|
} scheme_algs_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Map TLS signature schemes, ordered by preference
|
|
|
|
*/
|
|
|
|
static scheme_algs_t schemes[] = {
|
2020-08-28 06:59:37 +00:00
|
|
|
{ TLS_SIG_ECDSA_SHA256, { .scheme = SIGN_ECDSA_WITH_SHA256_DER },
|
|
|
|
TLS_1_0, TLS_1_3 },
|
|
|
|
{ TLS_SIG_ECDSA_SHA384, { .scheme = SIGN_ECDSA_WITH_SHA384_DER },
|
|
|
|
TLS_1_0, TLS_1_3 },
|
|
|
|
{ TLS_SIG_ECDSA_SHA512, { .scheme = SIGN_ECDSA_WITH_SHA512_DER },
|
|
|
|
TLS_1_0, TLS_1_3 },
|
|
|
|
{ TLS_SIG_ED25519, { .scheme = SIGN_ED25519 },
|
2020-10-23 14:17:16 +00:00
|
|
|
TLS_1_0, TLS_1_3 },
|
2020-08-28 06:59:37 +00:00
|
|
|
{ TLS_SIG_ED448, { .scheme = SIGN_ED448 },
|
2020-10-23 14:17:16 +00:00
|
|
|
TLS_1_0, TLS_1_3 },
|
2020-08-28 06:59:37 +00:00
|
|
|
{ TLS_SIG_RSA_PSS_RSAE_SHA256, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha256, },
|
|
|
|
TLS_1_2, TLS_1_3 },
|
|
|
|
{ TLS_SIG_RSA_PSS_RSAE_SHA384, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha384, },
|
|
|
|
TLS_1_2, TLS_1_3 },
|
|
|
|
{ TLS_SIG_RSA_PSS_RSAE_SHA512, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha512, },
|
|
|
|
TLS_1_2, TLS_1_3 },
|
|
|
|
/* the parameters for the next three should actually be taken from the
|
|
|
|
* public key, we currently don't have an API for that, so assume defaults */
|
|
|
|
{ TLS_SIG_RSA_PSS_PSS_SHA256, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha256, },
|
|
|
|
TLS_1_2, TLS_1_3 },
|
|
|
|
{ TLS_SIG_RSA_PSS_PSS_SHA384, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha384, },
|
|
|
|
TLS_1_2, TLS_1_3 },
|
|
|
|
{ TLS_SIG_RSA_PSS_PSS_SHA512, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha512, },
|
|
|
|
TLS_1_2, TLS_1_3 },
|
|
|
|
{ TLS_SIG_RSA_PKCS1_SHA256, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256 },
|
|
|
|
TLS_1_0, TLS_1_2 },
|
|
|
|
{ TLS_SIG_RSA_PKCS1_SHA384, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_384 },
|
|
|
|
TLS_1_0, TLS_1_2 },
|
|
|
|
{ TLS_SIG_RSA_PKCS1_SHA512, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_512 },
|
|
|
|
TLS_1_0, TLS_1_2 },
|
2014-01-15 14:51:03 +00:00
|
|
|
};
|
|
|
|
|
2021-02-01 20:41:56 +00:00
|
|
|
/**
|
|
|
|
* Filter signature scheme config
|
|
|
|
*/
|
|
|
|
static bool filter_signature_scheme_config(tls_signature_scheme_t signature)
|
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
char *token, *config;
|
|
|
|
|
|
|
|
config = lib->settings->get_str(lib->settings, "%s.tls.signature", NULL,
|
|
|
|
lib->ns);
|
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
enumerator = enumerator_create_token(config, ",", " ");
|
|
|
|
while (enumerator->enumerate(enumerator, &token))
|
|
|
|
{
|
|
|
|
tls_signature_scheme_t sig;
|
|
|
|
|
|
|
|
if (enum_from_name(tls_signature_scheme_names, token, &sig) &&
|
|
|
|
sig == signature)
|
|
|
|
{
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
}
|
|
|
|
return !config;
|
|
|
|
}
|
|
|
|
|
2010-09-02 17:15:16 +00:00
|
|
|
METHOD(tls_crypto_t, get_signature_algorithms, void,
|
2020-08-28 06:59:37 +00:00
|
|
|
private_tls_crypto_t *this, bio_writer_t *writer, bool cert)
|
2010-09-02 17:15:16 +00:00
|
|
|
{
|
2011-05-31 13:46:30 +00:00
|
|
|
bio_writer_t *supported;
|
2020-08-28 06:59:37 +00:00
|
|
|
tls_version_t min_version, max_version;
|
2014-01-15 14:51:03 +00:00
|
|
|
int i;
|
2010-09-02 17:15:16 +00:00
|
|
|
|
2011-05-31 13:46:30 +00:00
|
|
|
supported = bio_writer_create(32);
|
2020-08-28 06:59:37 +00:00
|
|
|
|
|
|
|
if (!cert)
|
|
|
|
{
|
|
|
|
min_version = this->tls->get_version_min(this->tls);
|
|
|
|
max_version = this->tls->get_version_max(this->tls);
|
|
|
|
}
|
2014-01-15 14:51:03 +00:00
|
|
|
|
|
|
|
for (i = 0; i < countof(schemes); i++)
|
2010-09-02 17:15:16 +00:00
|
|
|
{
|
2020-08-28 06:59:37 +00:00
|
|
|
if ((cert || (schemes[i].min_version <= max_version &&
|
|
|
|
schemes[i].max_version >= min_version)) &&
|
|
|
|
lib->plugins->has_feature(lib->plugins,
|
2021-02-01 20:41:56 +00:00
|
|
|
PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[i].params.scheme)) &&
|
|
|
|
filter_signature_scheme_config(schemes[i].sig))
|
2010-09-02 17:15:16 +00:00
|
|
|
{
|
2020-08-28 06:59:37 +00:00
|
|
|
supported->write_uint16(supported, schemes[i].sig);
|
2020-05-21 07:37:38 +00:00
|
|
|
}
|
2010-09-02 17:15:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
writer->write_data16(writer, supported->get_buf(supported));
|
|
|
|
supported->destroy(supported);
|
|
|
|
}
|
|
|
|
|
2014-01-15 14:51:03 +00:00
|
|
|
/**
|
2020-08-28 06:59:37 +00:00
|
|
|
* Get the signature parameters from a TLS signature scheme
|
2014-01-15 14:51:03 +00:00
|
|
|
*/
|
2020-10-13 11:54:38 +00:00
|
|
|
static signature_params_t *params_for_scheme(tls_signature_scheme_t sig,
|
|
|
|
bool sign)
|
2014-01-15 14:51:03 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2020-08-28 06:59:37 +00:00
|
|
|
for (i = 0; i < countof(schemes); i++)
|
2014-01-15 14:51:03 +00:00
|
|
|
{
|
2020-09-08 13:58:14 +00:00
|
|
|
/* strongSwan supports only RSA_PSS_RSAE schemes for signing but can
|
2020-10-13 11:54:38 +00:00
|
|
|
* verify public keys in rsaEncryption as well as rsassaPss encoding. */
|
|
|
|
if (sign && (sig == TLS_SIG_RSA_PSS_PSS_SHA256 ||
|
|
|
|
sig == TLS_SIG_RSA_PSS_PSS_SHA384 ||
|
|
|
|
sig == TLS_SIG_RSA_PSS_PSS_SHA512))
|
2020-09-08 13:58:14 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2020-08-28 06:59:37 +00:00
|
|
|
if (schemes[i].sig == sig)
|
2014-01-15 14:51:03 +00:00
|
|
|
{
|
2020-08-28 06:59:37 +00:00
|
|
|
return &schemes[i].params;
|
2014-01-15 14:51:03 +00:00
|
|
|
}
|
|
|
|
}
|
2020-08-28 06:59:37 +00:00
|
|
|
return NULL;
|
2014-01-15 14:51:03 +00:00
|
|
|
}
|
|
|
|
|
2010-09-03 15:05:39 +00:00
|
|
|
/**
|
|
|
|
* Mapping groups to TLS named curves
|
|
|
|
*/
|
|
|
|
static struct {
|
|
|
|
diffie_hellman_group_t group;
|
2020-05-21 07:37:38 +00:00
|
|
|
tls_named_group_t curve;
|
2010-09-03 15:05:39 +00:00
|
|
|
} curves[] = {
|
|
|
|
{ ECP_256_BIT, TLS_SECP256R1},
|
|
|
|
{ ECP_384_BIT, TLS_SECP384R1},
|
|
|
|
{ ECP_521_BIT, TLS_SECP521R1},
|
|
|
|
{ ECP_224_BIT, TLS_SECP224R1},
|
|
|
|
{ ECP_192_BIT, TLS_SECP192R1},
|
2020-08-25 11:16:52 +00:00
|
|
|
{ CURVE_25519, TLS_CURVE25519},
|
|
|
|
{ CURVE_448, TLS_CURVE448},
|
2010-09-03 15:05:39 +00:00
|
|
|
};
|
|
|
|
|
2017-05-12 10:10:27 +00:00
|
|
|
CALLBACK(group_filter, bool,
|
|
|
|
void *null, enumerator_t *orig, va_list args)
|
2010-09-03 15:05:39 +00:00
|
|
|
{
|
2020-09-26 20:19:16 +00:00
|
|
|
diffie_hellman_group_t group, *group_out;
|
|
|
|
tls_named_group_t curve, *curve_out;
|
2017-05-12 10:10:27 +00:00
|
|
|
char *plugin;
|
2010-09-03 15:05:39 +00:00
|
|
|
|
2020-09-26 20:19:16 +00:00
|
|
|
VA_ARGS_VGET(args, group_out, curve_out);
|
2017-05-12 10:10:27 +00:00
|
|
|
|
|
|
|
while (orig->enumerate(orig, &group, &plugin))
|
2010-09-03 15:05:39 +00:00
|
|
|
{
|
2020-09-26 20:19:16 +00:00
|
|
|
curve = tls_ec_group_to_curve(group);
|
|
|
|
if (curve)
|
2010-09-03 15:05:39 +00:00
|
|
|
{
|
2020-09-26 20:19:16 +00:00
|
|
|
if (group_out)
|
2010-09-03 15:05:39 +00:00
|
|
|
{
|
2020-09-26 20:19:16 +00:00
|
|
|
*group_out = group;
|
|
|
|
}
|
|
|
|
if (curve_out)
|
|
|
|
{
|
|
|
|
*curve_out = curve;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CALLBACK(config_filter, bool,
|
|
|
|
void *null, enumerator_t *orig, va_list args)
|
|
|
|
{
|
|
|
|
diffie_hellman_group_t group, *group_out;
|
|
|
|
tls_named_group_t curve, *curve_out;
|
|
|
|
|
|
|
|
VA_ARGS_VGET(args, group_out, curve_out);
|
|
|
|
|
|
|
|
while (orig->enumerate(orig, &group, &curve))
|
|
|
|
{
|
|
|
|
if (filter_curve_config(curve))
|
|
|
|
{
|
|
|
|
if (group_out)
|
|
|
|
{
|
|
|
|
*group_out = group;
|
2010-09-03 15:05:39 +00:00
|
|
|
}
|
2020-09-26 20:19:16 +00:00
|
|
|
if (curve_out)
|
|
|
|
{
|
|
|
|
*curve_out = curve;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2010-09-03 15:05:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
METHOD(tls_crypto_t, create_ec_enumerator, enumerator_t*,
|
|
|
|
private_tls_crypto_t *this)
|
2010-09-03 09:45:55 +00:00
|
|
|
{
|
2010-09-03 15:05:39 +00:00
|
|
|
return enumerator_create_filter(
|
2020-09-26 20:19:16 +00:00
|
|
|
enumerator_create_filter(
|
|
|
|
lib->crypto->create_dh_enumerator(lib->crypto),
|
|
|
|
group_filter, NULL, NULL),
|
|
|
|
config_filter, NULL, NULL);
|
2010-09-03 09:45:55 +00:00
|
|
|
}
|
|
|
|
|
2010-02-05 13:39:19 +00:00
|
|
|
METHOD(tls_crypto_t, set_protection, void,
|
|
|
|
private_tls_crypto_t *this, tls_protection_t *protection)
|
|
|
|
{
|
|
|
|
this->protection = protection;
|
|
|
|
}
|
|
|
|
|
2010-02-05 13:25:38 +00:00
|
|
|
METHOD(tls_crypto_t, append_handshake, void,
|
|
|
|
private_tls_crypto_t *this, tls_handshake_type_t type, chunk_t data)
|
|
|
|
{
|
2016-03-22 12:22:01 +00:00
|
|
|
uint32_t header;
|
2010-02-05 13:25:38 +00:00
|
|
|
|
|
|
|
/* reconstruct handshake header */
|
|
|
|
header = htonl(data.len | (type << 24));
|
|
|
|
this->handshake = chunk_cat("mcc", this->handshake,
|
|
|
|
chunk_from_thing(header), data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-09-02 17:15:16 +00:00
|
|
|
* Create a hash using the suites HASH algorithm
|
2010-02-05 13:25:38 +00:00
|
|
|
*/
|
2010-09-02 17:15:16 +00:00
|
|
|
static bool hash_data(private_tls_crypto_t *this, chunk_t data, chunk_t *hash)
|
2010-02-05 13:25:38 +00:00
|
|
|
{
|
2020-05-21 07:37:38 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) >= TLS_1_2)
|
2010-02-05 13:25:38 +00:00
|
|
|
{
|
|
|
|
hasher_t *hasher;
|
|
|
|
suite_algs_t *alg;
|
|
|
|
|
|
|
|
alg = find_suite(this->suite);
|
|
|
|
if (!alg)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
hasher = lib->crypto->create_hasher(lib->crypto, alg->hash);
|
2012-07-09 15:15:52 +00:00
|
|
|
if (!hasher || !hasher->allocate_hash(hasher, data, hash))
|
2010-02-05 13:25:38 +00:00
|
|
|
{
|
2010-08-20 13:57:47 +00:00
|
|
|
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, alg->hash);
|
2012-07-09 15:15:52 +00:00
|
|
|
DESTROY_IF(hasher);
|
2010-02-05 13:25:38 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
hasher->destroy(hasher);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hasher_t *md5, *sha1;
|
|
|
|
char buf[HASH_SIZE_MD5 + HASH_SIZE_SHA1];
|
|
|
|
|
|
|
|
md5 = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
|
2012-07-09 13:33:41 +00:00
|
|
|
if (!md5 || !md5->get_hash(md5, data, buf))
|
2010-02-05 13:25:38 +00:00
|
|
|
{
|
2010-08-20 13:57:47 +00:00
|
|
|
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, HASH_MD5);
|
2012-07-09 13:33:41 +00:00
|
|
|
DESTROY_IF(md5);
|
2010-02-05 13:25:38 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
md5->destroy(md5);
|
|
|
|
sha1 = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
|
2012-07-09 13:33:41 +00:00
|
|
|
if (!sha1 || !sha1->get_hash(sha1, data, buf + HASH_SIZE_MD5))
|
2010-02-05 13:25:38 +00:00
|
|
|
{
|
2010-08-20 13:57:47 +00:00
|
|
|
DBG1(DBG_TLS, "%N not supported", hash_algorithm_names, HASH_SHA1);
|
2012-07-09 13:33:41 +00:00
|
|
|
DESTROY_IF(sha1);
|
2010-02-05 13:25:38 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
sha1->destroy(sha1);
|
|
|
|
|
|
|
|
*hash = chunk_clone(chunk_from_thing(buf));
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-08-25 15:17:55 +00:00
|
|
|
METHOD(tls_crypto_t, hash_handshake, bool,
|
|
|
|
private_tls_crypto_t *this, chunk_t *out)
|
|
|
|
{
|
|
|
|
chunk_t hash;
|
|
|
|
|
|
|
|
if (!hash_data(this, this->handshake, &hash))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
chunk_free(&this->handshake);
|
|
|
|
append_handshake(this, TLS_MESSAGE_HASH, hash);
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
{
|
|
|
|
*out = hash;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
free(hash.ptr);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-08-25 13:58:46 +00:00
|
|
|
/**
|
|
|
|
* TLS 1.3 static part of the data the server signs (64 spaces followed by the
|
|
|
|
* context string "TLS 1.3, server CertificateVerify" and a 0 byte).
|
|
|
|
*/
|
|
|
|
static chunk_t tls13_sig_data_server = chunk_from_chars(
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, 0x2c,
|
|
|
|
0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20,
|
|
|
|
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
|
|
|
0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66,
|
|
|
|
0x79, 0x00,
|
|
|
|
);
|
|
|
|
|
2020-10-30 14:15:30 +00:00
|
|
|
/**
|
|
|
|
* TLS 1.3 static part of the data the peer signs (64 spaces followed by the
|
|
|
|
* context string "TLS 1.3, client CertificateVerify" and a 0 byte).
|
|
|
|
*/
|
|
|
|
static chunk_t tls13_sig_data_client = chunk_from_chars(
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
|
|
|
0x54, 0x4c, 0x53, 0x20, 0x31, 0x2e, 0x33, 0x2c,
|
|
|
|
0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20,
|
|
|
|
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
|
|
|
0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x69, 0x66,
|
|
|
|
0x79, 0x00,
|
|
|
|
);
|
|
|
|
|
2010-09-02 17:15:16 +00:00
|
|
|
METHOD(tls_crypto_t, sign, bool,
|
2011-05-31 13:46:30 +00:00
|
|
|
private_tls_crypto_t *this, private_key_t *key, bio_writer_t *writer,
|
2010-09-02 17:15:16 +00:00
|
|
|
chunk_t data, chunk_t hashsig)
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
2020-05-21 07:37:38 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) >= TLS_1_2)
|
2010-02-05 13:25:38 +00:00
|
|
|
{
|
2020-08-28 06:59:37 +00:00
|
|
|
/* fallback to SHA1/RSA and SHA1/ECDSA */
|
|
|
|
const chunk_t hashsig_def = chunk_from_chars(0x02, 0x01, 0x02, 0x03);
|
|
|
|
signature_params_t *params;
|
|
|
|
key_type_t type;
|
|
|
|
uint16_t scheme;
|
2011-05-31 13:46:30 +00:00
|
|
|
bio_reader_t *reader;
|
2010-09-02 08:29:32 +00:00
|
|
|
chunk_t sig;
|
|
|
|
bool done = FALSE;
|
|
|
|
|
2020-09-08 13:58:14 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) >= TLS_1_3)
|
|
|
|
{
|
|
|
|
chunk_t transcript_hash;
|
|
|
|
|
|
|
|
if (!hash_data(this, data, &transcript_hash))
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "unable to create transcript hash");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-11-10 13:50:59 +00:00
|
|
|
if (this->tls->is_server(this->tls))
|
|
|
|
{
|
|
|
|
data = chunk_cata("cm", tls13_sig_data_server, transcript_hash);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data = chunk_cata("cm", tls13_sig_data_client, transcript_hash);
|
|
|
|
}
|
2020-09-08 13:58:14 +00:00
|
|
|
}
|
|
|
|
|
2010-09-02 17:15:16 +00:00
|
|
|
if (!hashsig.len)
|
|
|
|
{ /* fallback if none given */
|
2020-01-29 09:02:38 +00:00
|
|
|
hashsig = hashsig_def;
|
2010-09-02 17:15:16 +00:00
|
|
|
}
|
2020-08-28 06:59:37 +00:00
|
|
|
type = key->get_type(key);
|
2011-05-31 13:46:30 +00:00
|
|
|
reader = bio_reader_create(hashsig);
|
2010-09-02 08:29:32 +00:00
|
|
|
while (reader->remaining(reader) >= 2)
|
2010-02-09 17:19:25 +00:00
|
|
|
{
|
2020-08-28 06:59:37 +00:00
|
|
|
if (reader->read_uint16(reader, &scheme))
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
2020-10-13 11:54:38 +00:00
|
|
|
params = params_for_scheme(scheme, TRUE);
|
2020-08-28 06:59:37 +00:00
|
|
|
if (params &&
|
|
|
|
type == key_type_from_signature_scheme(params->scheme) &&
|
|
|
|
key->sign(key, params->scheme, params->params, data, &sig))
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
|
|
|
done = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
reader->destroy(reader);
|
|
|
|
if (!done)
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "none of the proposed hash/sig algorithms supported");
|
2010-02-09 17:19:25 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2020-08-28 06:59:37 +00:00
|
|
|
DBG2(DBG_TLS, "created signature with %N", tls_signature_scheme_names,
|
|
|
|
scheme);
|
|
|
|
writer->write_uint16(writer, scheme);
|
2010-02-09 17:19:25 +00:00
|
|
|
writer->write_data16(writer, sig);
|
|
|
|
free(sig.ptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-09-02 08:29:32 +00:00
|
|
|
chunk_t sig, hash;
|
2010-09-02 17:15:16 +00:00
|
|
|
bool done;
|
2010-09-02 08:29:32 +00:00
|
|
|
|
|
|
|
switch (key->get_type(key))
|
2010-02-09 17:19:25 +00:00
|
|
|
{
|
2010-09-02 08:29:32 +00:00
|
|
|
case KEY_RSA:
|
2010-09-02 17:15:16 +00:00
|
|
|
if (!hash_data(this, data, &hash))
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2017-09-19 15:26:58 +00:00
|
|
|
done = key->sign(key, SIGN_RSA_EMSA_PKCS1_NULL, NULL, hash,
|
|
|
|
&sig);
|
2010-09-02 17:15:16 +00:00
|
|
|
free(hash.ptr);
|
|
|
|
if (!done)
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-09-02 17:15:16 +00:00
|
|
|
DBG2(DBG_TLS, "created signature with MD5+SHA1/RSA");
|
2010-09-02 08:29:32 +00:00
|
|
|
break;
|
|
|
|
case KEY_ECDSA:
|
2017-09-19 15:26:58 +00:00
|
|
|
if (!key->sign(key, SIGN_ECDSA_WITH_SHA1_DER, NULL, data, &sig))
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-09-02 17:15:16 +00:00
|
|
|
DBG2(DBG_TLS, "created signature with SHA1/ECDSA");
|
2010-09-02 08:29:32 +00:00
|
|
|
break;
|
2020-10-23 14:17:16 +00:00
|
|
|
case KEY_ED25519:
|
|
|
|
if (!key->sign(key, SIGN_ED25519, NULL, data, &sig))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
DBG2(DBG_TLS, "created signature with Ed25519");
|
|
|
|
break;
|
|
|
|
case KEY_ED448:
|
|
|
|
if (!key->sign(key, SIGN_ED448, NULL, data, &sig))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
DBG2(DBG_TLS, "created signature with Ed448");
|
|
|
|
break;
|
2010-09-02 08:29:32 +00:00
|
|
|
default:
|
|
|
|
return FALSE;
|
2010-02-09 17:19:25 +00:00
|
|
|
}
|
|
|
|
writer->write_data16(writer, sig);
|
|
|
|
free(sig.ptr);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-09-02 17:15:16 +00:00
|
|
|
METHOD(tls_crypto_t, verify, bool,
|
2011-05-31 13:46:30 +00:00
|
|
|
private_tls_crypto_t *this, public_key_t *key, bio_reader_t *reader,
|
2010-09-02 17:15:16 +00:00
|
|
|
chunk_t data)
|
2010-02-09 17:19:25 +00:00
|
|
|
{
|
2020-08-25 13:58:46 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) >= TLS_1_2)
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-28 06:59:37 +00:00
|
|
|
signature_params_t *params;
|
|
|
|
uint16_t scheme;
|
2020-08-25 13:58:46 +00:00
|
|
|
chunk_t sig;
|
2020-05-21 07:37:38 +00:00
|
|
|
|
2020-08-28 06:59:37 +00:00
|
|
|
if (!reader->read_uint16(reader, &scheme) ||
|
2020-05-21 07:37:38 +00:00
|
|
|
!reader->read_data16(reader, &sig))
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "received invalid signature");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-10-13 11:54:38 +00:00
|
|
|
params = params_for_scheme(scheme, FALSE);
|
2020-08-28 06:59:37 +00:00
|
|
|
if (!params)
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-28 06:59:37 +00:00
|
|
|
DBG1(DBG_TLS, "signature algorithms %N not supported",
|
|
|
|
tls_signature_scheme_names, scheme);
|
2020-05-21 07:37:38 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2020-11-10 13:50:59 +00:00
|
|
|
if (this->tls->get_version_max(this->tls) >= TLS_1_3)
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-25 13:58:46 +00:00
|
|
|
chunk_t transcript_hash;
|
2010-02-05 13:25:38 +00:00
|
|
|
|
2020-08-25 13:58:46 +00:00
|
|
|
if (!hash_data(this, data, &transcript_hash))
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "Unable to create transcript hash");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2020-10-30 14:15:30 +00:00
|
|
|
if (this->tls->is_server(this->tls))
|
|
|
|
{
|
|
|
|
data = chunk_cata("cm", tls13_sig_data_client, transcript_hash);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
data = chunk_cata("cm", tls13_sig_data_server, transcript_hash);
|
|
|
|
}
|
2010-02-05 13:25:38 +00:00
|
|
|
}
|
2020-08-28 06:59:37 +00:00
|
|
|
if (!key->verify(key, params->scheme, params->params, data, sig))
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
2020-08-28 06:59:37 +00:00
|
|
|
DBG1(DBG_TLS, "signature verification with %N failed",
|
|
|
|
tls_signature_scheme_names, scheme);
|
2010-09-02 08:29:32 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2020-08-28 06:59:37 +00:00
|
|
|
DBG2(DBG_TLS, "verified signature with %N",
|
|
|
|
tls_signature_scheme_names, scheme);
|
2010-02-05 13:25:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-02-09 17:19:25 +00:00
|
|
|
chunk_t sig, hash;
|
2010-09-02 17:15:16 +00:00
|
|
|
bool done;
|
2010-02-05 13:25:38 +00:00
|
|
|
|
2010-02-09 17:19:25 +00:00
|
|
|
if (!reader->read_data16(reader, &sig))
|
|
|
|
{
|
2010-09-02 17:15:16 +00:00
|
|
|
DBG1(DBG_TLS, "received invalid signature");
|
2010-02-09 17:19:25 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2010-09-02 08:29:32 +00:00
|
|
|
switch (key->get_type(key))
|
2010-02-05 13:25:38 +00:00
|
|
|
{
|
2010-09-02 08:29:32 +00:00
|
|
|
case KEY_RSA:
|
2010-09-02 17:15:16 +00:00
|
|
|
if (!hash_data(this, data, &hash))
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2017-09-19 15:15:18 +00:00
|
|
|
done = key->verify(key, SIGN_RSA_EMSA_PKCS1_NULL, NULL, hash,
|
|
|
|
sig);
|
2010-09-02 17:15:16 +00:00
|
|
|
free(hash.ptr);
|
|
|
|
if (!done)
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-09-02 17:15:16 +00:00
|
|
|
DBG2(DBG_TLS, "verified signature data with MD5+SHA1/RSA");
|
2010-09-02 08:29:32 +00:00
|
|
|
break;
|
|
|
|
case KEY_ECDSA:
|
2017-09-19 15:15:18 +00:00
|
|
|
if (!key->verify(key, SIGN_ECDSA_WITH_SHA1_DER, NULL, data,
|
|
|
|
sig))
|
2010-09-02 08:29:32 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-09-02 17:15:16 +00:00
|
|
|
DBG2(DBG_TLS, "verified signature with SHA1/ECDSA");
|
2010-09-02 08:29:32 +00:00
|
|
|
break;
|
2020-10-23 14:17:16 +00:00
|
|
|
case KEY_ED25519:
|
|
|
|
if (!key->verify(key, SIGN_ED25519, NULL, data, sig))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
DBG2(DBG_TLS, "verified signature with Ed25519");
|
|
|
|
break;
|
|
|
|
case KEY_ED448:
|
|
|
|
if (!key->verify(key, SIGN_ED448, NULL, data, sig))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
DBG2(DBG_TLS, "verified signature with Ed448");
|
|
|
|
break;
|
2010-09-02 08:29:32 +00:00
|
|
|
default:
|
|
|
|
return FALSE;
|
2010-02-05 13:25:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2010-09-02 17:15:16 +00:00
|
|
|
METHOD(tls_crypto_t, sign_handshake, bool,
|
2011-05-31 13:46:30 +00:00
|
|
|
private_tls_crypto_t *this, private_key_t *key, bio_writer_t *writer,
|
2010-09-02 17:15:16 +00:00
|
|
|
chunk_t hashsig)
|
|
|
|
{
|
|
|
|
return sign(this, key, writer, this->handshake, hashsig);
|
|
|
|
}
|
|
|
|
|
|
|
|
METHOD(tls_crypto_t, verify_handshake, bool,
|
2011-05-31 13:46:30 +00:00
|
|
|
private_tls_crypto_t *this, public_key_t *key, bio_reader_t *reader)
|
2010-09-02 17:15:16 +00:00
|
|
|
{
|
|
|
|
return verify(this, key, reader, this->handshake);
|
|
|
|
}
|
|
|
|
|
2020-08-25 14:52:20 +00:00
|
|
|
METHOD(tls_crypto_t, calculate_finished_legacy, bool,
|
2010-02-05 13:25:38 +00:00
|
|
|
private_tls_crypto_t *this, char *label, char out[12])
|
|
|
|
{
|
|
|
|
chunk_t seed;
|
|
|
|
|
|
|
|
if (!this->prf)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-09-02 17:15:16 +00:00
|
|
|
if (!hash_data(this, this->handshake, &seed))
|
2010-02-05 13:25:38 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2012-07-06 07:49:16 +00:00
|
|
|
if (!this->prf->get_bytes(this->prf, label, seed, 12, out))
|
|
|
|
{
|
|
|
|
free(seed.ptr);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-02-05 13:25:38 +00:00
|
|
|
free(seed.ptr);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-08-25 14:52:20 +00:00
|
|
|
METHOD(tls_crypto_t, calculate_finished, bool,
|
2020-09-16 12:10:57 +00:00
|
|
|
private_tls_crypto_t *this, bool server, chunk_t *out)
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
|
|
|
chunk_t finished_key, finished_hash;
|
|
|
|
|
2020-08-25 14:49:52 +00:00
|
|
|
if (!this->hkdf)
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-25 14:49:52 +00:00
|
|
|
return FALSE;
|
2020-05-21 07:37:38 +00:00
|
|
|
}
|
2020-08-25 14:49:52 +00:00
|
|
|
if (!hash_data(this, this->handshake, &finished_hash))
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-25 14:49:52 +00:00
|
|
|
DBG1(DBG_TLS, "creating hash of handshake failed");
|
|
|
|
return FALSE;
|
2020-05-21 07:37:38 +00:00
|
|
|
}
|
2020-09-16 12:10:57 +00:00
|
|
|
if (!this->hkdf->derive_finished(this->hkdf, server, &finished_key))
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-25 14:49:52 +00:00
|
|
|
DBG1(DBG_TLS, "generating finished key failed");
|
|
|
|
chunk_clear(&finished_hash);
|
|
|
|
return FALSE;
|
2020-05-21 07:37:38 +00:00
|
|
|
}
|
2020-08-25 14:49:52 +00:00
|
|
|
if (!this->hkdf->allocate_bytes(this->hkdf, finished_key, finished_hash, out))
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-25 14:49:52 +00:00
|
|
|
DBG1(DBG_TLS, "generating finished HMAC failed");
|
2020-05-21 07:37:38 +00:00
|
|
|
chunk_clear(&finished_key);
|
|
|
|
chunk_clear(&finished_hash);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
chunk_clear(&finished_key);
|
|
|
|
chunk_clear(&finished_hash);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2011-12-31 00:41:56 +00:00
|
|
|
/**
|
|
|
|
* Derive master secret from premaster, optionally save session
|
|
|
|
*/
|
2012-07-06 07:49:16 +00:00
|
|
|
static bool derive_master(private_tls_crypto_t *this, chunk_t premaster,
|
2011-12-31 00:41:56 +00:00
|
|
|
chunk_t session, identification_t *id,
|
|
|
|
chunk_t client_random, chunk_t server_random)
|
2010-02-04 10:17:48 +00:00
|
|
|
{
|
2010-02-04 17:18:10 +00:00
|
|
|
char master[48];
|
2011-12-31 00:41:56 +00:00
|
|
|
chunk_t seed;
|
2010-02-04 17:18:10 +00:00
|
|
|
|
|
|
|
/* derive master secret */
|
|
|
|
seed = chunk_cata("cc", client_random, server_random);
|
2012-07-06 07:49:25 +00:00
|
|
|
|
|
|
|
if (!this->prf->set_key(this->prf, premaster) ||
|
|
|
|
!this->prf->get_bytes(this->prf, "master secret", seed,
|
|
|
|
sizeof(master), master) ||
|
|
|
|
!this->prf->set_key(this->prf, chunk_from_thing(master)))
|
2012-07-06 07:49:16 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-12-31 00:41:56 +00:00
|
|
|
if (this->cache && session.len)
|
|
|
|
{
|
|
|
|
this->cache->create(this->cache, session, id, chunk_from_thing(master),
|
|
|
|
this->suite);
|
|
|
|
}
|
|
|
|
memwipe(master, sizeof(master));
|
2012-07-06 07:49:16 +00:00
|
|
|
return TRUE;
|
2011-12-31 00:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Expand key material from master secret
|
|
|
|
*/
|
2012-07-06 07:28:25 +00:00
|
|
|
static bool expand_keys(private_tls_crypto_t *this,
|
2011-12-31 00:41:56 +00:00
|
|
|
chunk_t client_random, chunk_t server_random)
|
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
chunk_t seed, block;
|
|
|
|
chunk_t cw_mac, cw, cw_iv;
|
|
|
|
chunk_t sw_mac, sw, sw_iv;
|
|
|
|
int mklen, eklen, ivlen;
|
2010-02-04 17:18:10 +00:00
|
|
|
|
2014-02-03 12:20:46 +00:00
|
|
|
if (!this->aead_in || !this->aead_out)
|
2010-02-04 10:17:48 +00:00
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
return FALSE;
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
2014-02-03 12:20:46 +00:00
|
|
|
|
|
|
|
/* derive key block for key expansion */
|
|
|
|
mklen = this->aead_in->get_mac_key_size(this->aead_in);
|
|
|
|
eklen = this->aead_in->get_encr_key_size(this->aead_in);
|
|
|
|
ivlen = this->aead_in->get_iv_size(this->aead_in);
|
2010-02-04 17:18:10 +00:00
|
|
|
seed = chunk_cata("cc", server_random, client_random);
|
2014-02-03 12:20:46 +00:00
|
|
|
block = chunk_alloca((mklen + eklen + ivlen) * 2);
|
2012-07-06 07:49:16 +00:00
|
|
|
if (!this->prf->get_bytes(this->prf, "key expansion", seed,
|
|
|
|
block.len, block.ptr))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-02-04 17:18:10 +00:00
|
|
|
|
2014-02-03 12:20:46 +00:00
|
|
|
/* client/server write signer keys */
|
|
|
|
cw_mac = chunk_create(block.ptr, mklen);
|
|
|
|
block = chunk_skip(block, mklen);
|
|
|
|
sw_mac = chunk_create(block.ptr, mklen);
|
|
|
|
block = chunk_skip(block, mklen);
|
|
|
|
|
|
|
|
/* client/server write encryption keys */
|
|
|
|
cw = chunk_create(block.ptr, eklen);
|
|
|
|
block = chunk_skip(block, eklen);
|
|
|
|
sw = chunk_create(block.ptr, eklen);
|
|
|
|
block = chunk_skip(block, eklen);
|
|
|
|
|
|
|
|
/* client/server write IV; TLS 1.0 implicit IVs or AEAD salt, if any */
|
|
|
|
cw_iv = chunk_create(block.ptr, ivlen);
|
|
|
|
block = chunk_skip(block, ivlen);
|
|
|
|
sw_iv = chunk_create(block.ptr, ivlen);
|
|
|
|
block = chunk_skip(block, ivlen);
|
|
|
|
|
2010-02-04 17:18:10 +00:00
|
|
|
if (this->tls->is_server(this->tls))
|
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
if (!this->aead_in->set_keys(this->aead_in, cw_mac, cw, cw_iv) ||
|
|
|
|
!this->aead_out->set_keys(this->aead_out, sw_mac, sw, sw_iv))
|
2012-07-06 07:33:10 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
if (!this->aead_out->set_keys(this->aead_out, cw_mac, cw, cw_iv) ||
|
|
|
|
!this->aead_in->set_keys(this->aead_in, sw_mac, sw, sw_iv))
|
2012-07-06 07:33:10 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
|
|
|
|
2011-12-31 00:41:56 +00:00
|
|
|
/* EAP-MSK */
|
|
|
|
if (this->msk_label)
|
|
|
|
{
|
2012-02-07 09:50:02 +00:00
|
|
|
seed = chunk_cata("cc", client_random, server_random);
|
2011-12-31 00:41:56 +00:00
|
|
|
this->msk = chunk_alloc(64);
|
2012-07-06 07:49:16 +00:00
|
|
|
if (!this->prf->get_bytes(this->prf, this->msk_label, seed,
|
|
|
|
this->msk.len, this->msk.ptr))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-12-31 00:41:56 +00:00
|
|
|
}
|
2012-07-06 07:28:25 +00:00
|
|
|
return TRUE;
|
2011-12-31 00:41:56 +00:00
|
|
|
}
|
|
|
|
|
2012-07-06 07:28:25 +00:00
|
|
|
METHOD(tls_crypto_t, derive_secrets, bool,
|
2011-12-31 00:41:56 +00:00
|
|
|
private_tls_crypto_t *this, chunk_t premaster, chunk_t session,
|
|
|
|
identification_t *id, chunk_t client_random, chunk_t server_random)
|
|
|
|
{
|
2012-07-06 07:49:16 +00:00
|
|
|
return derive_master(this, premaster, session, id,
|
|
|
|
client_random, server_random) &&
|
|
|
|
expand_keys(this, client_random, server_random);
|
2011-12-31 00:41:56 +00:00
|
|
|
}
|
|
|
|
|
2020-08-25 11:22:04 +00:00
|
|
|
/**
|
2020-08-27 09:51:00 +00:00
|
|
|
* Derive and configure the client/server key/IV on an AEAD using a given label.
|
2020-08-25 11:22:04 +00:00
|
|
|
*/
|
2020-08-27 09:51:00 +00:00
|
|
|
static bool derive_labeled_key(private_tls_crypto_t *this, bool server,
|
|
|
|
tls_hkdf_label_t label, tls_aead_t *aead)
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-27 09:51:00 +00:00
|
|
|
chunk_t key = chunk_empty, iv = chunk_empty;
|
2020-08-25 11:22:04 +00:00
|
|
|
bool success = FALSE;
|
2020-05-21 07:37:38 +00:00
|
|
|
|
2020-08-27 09:51:00 +00:00
|
|
|
if (!this->hkdf->generate_secret(this->hkdf, label, this->handshake,
|
2020-08-25 11:22:04 +00:00
|
|
|
NULL) ||
|
2020-08-27 09:51:00 +00:00
|
|
|
!this->hkdf->derive_key(this->hkdf, server,
|
|
|
|
aead->get_encr_key_size(aead), &key) ||
|
|
|
|
!this->hkdf->derive_iv(this->hkdf, server,
|
|
|
|
aead->get_iv_size(aead), &iv))
|
|
|
|
{
|
|
|
|
DBG1(DBG_TLS, "deriving key material failed");
|
2020-08-25 11:22:04 +00:00
|
|
|
goto out;
|
2020-05-21 07:37:38 +00:00
|
|
|
}
|
|
|
|
|
2020-08-27 09:51:00 +00:00
|
|
|
if (!aead->set_keys(aead, chunk_empty, key, iv))
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-25 11:22:04 +00:00
|
|
|
DBG1(DBG_TLS, "setting AEAD key material failed");
|
|
|
|
goto out;
|
2020-05-21 07:37:38 +00:00
|
|
|
}
|
2020-08-25 11:22:04 +00:00
|
|
|
success = TRUE;
|
2020-05-21 07:37:38 +00:00
|
|
|
|
2020-08-25 11:22:04 +00:00
|
|
|
out:
|
2020-08-27 09:51:00 +00:00
|
|
|
chunk_clear(&key);
|
|
|
|
chunk_clear(&iv);
|
2020-08-25 11:22:04 +00:00
|
|
|
return success;
|
2020-05-21 07:37:38 +00:00
|
|
|
}
|
|
|
|
|
2020-08-27 09:51:00 +00:00
|
|
|
/**
|
|
|
|
* Derive and configure the keys/IVs using the given labels.
|
|
|
|
*/
|
|
|
|
static bool derive_labeled_keys(private_tls_crypto_t *this,
|
|
|
|
tls_hkdf_label_t client_label,
|
|
|
|
tls_hkdf_label_t server_label)
|
|
|
|
{
|
2020-10-28 20:54:09 +00:00
|
|
|
tls_aead_t *aead_c, *aead_s;
|
|
|
|
suite_algs_t *algs;
|
2020-08-27 09:51:00 +00:00
|
|
|
|
2020-10-28 20:54:09 +00:00
|
|
|
algs = find_suite(this->suite);
|
|
|
|
destroy_aeads(this);
|
|
|
|
if (!create_aead(this, algs))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
aead_c = this->aead_out;
|
|
|
|
aead_s = this->aead_in;
|
2020-08-27 09:51:00 +00:00
|
|
|
if (this->tls->is_server(this->tls))
|
|
|
|
{
|
|
|
|
aead_c = this->aead_in;
|
|
|
|
aead_s = this->aead_out;
|
|
|
|
}
|
|
|
|
return derive_labeled_key(this, FALSE, client_label, aead_c) &&
|
|
|
|
derive_labeled_key(this, TRUE, server_label, aead_s);
|
|
|
|
}
|
|
|
|
|
2020-08-25 11:22:04 +00:00
|
|
|
METHOD(tls_crypto_t, derive_handshake_keys, bool,
|
|
|
|
private_tls_crypto_t *this, chunk_t shared_secret)
|
2020-05-21 07:37:38 +00:00
|
|
|
{
|
2020-08-25 11:22:04 +00:00
|
|
|
this->hkdf->set_shared_secret(this->hkdf, shared_secret);
|
|
|
|
return derive_labeled_keys(this, TLS_HKDF_C_HS_TRAFFIC,
|
|
|
|
TLS_HKDF_S_HS_TRAFFIC);
|
|
|
|
}
|
2020-05-21 07:37:38 +00:00
|
|
|
|
2020-08-25 11:22:04 +00:00
|
|
|
METHOD(tls_crypto_t, derive_app_keys, bool,
|
|
|
|
private_tls_crypto_t *this)
|
|
|
|
{
|
tls-crypto: Generate MSK for TLS 1.3
We generate material for both MSK and EMSK even though we only need the
former. Because HKDF-Expand-Label(), on which the export functionality
is based, encodes the requested key length, we have to allocate the same
number of bytes as e.g. FreeRADIUS does (i.e. if we only request 64
bytes, those won't be the same as the first 64 bytes after requesting
128 bytes).
Unfortunately, key derivation for TLS-based methods is currently not
standardized for TLS 1.3. There is a draft [1], which defines a scheme
that's different from previous versions (instead of individual label
strings it uses a single one and passes the EAP type/code as context
value to TLS-Export()). The current code is compatible to FreeRADIUS
3.0.x, which doesn't implement it according to that draft yet (there are
unreleased changes for EAP-TLS, not for the other methods, but these only
switch the label, no context value is passed). In a separate draft
for EAP-TLS [2] there is an altogether different scheme defined in the
latest version (label combined with EAP method, no context and separate
derivation for MSK and EMSK).
So this is a mess and we will have to change this later with the inevitable
compatibility issues (we should definitely disable TLS 1.3 by default).
[1] https://tools.ietf.org/html/draft-ietf-emu-tls-eap-types
[2] https://tools.ietf.org/html/draft-ietf-emu-eap-tls13
2020-09-01 16:51:32 +00:00
|
|
|
if (!derive_labeled_keys(this, TLS_HKDF_C_AP_TRAFFIC,
|
|
|
|
TLS_HKDF_S_AP_TRAFFIC))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* EAP-MSK */
|
|
|
|
if (this->msk_label)
|
|
|
|
{
|
|
|
|
/* because the length is encoded when expanding key material, we
|
|
|
|
* request the same number of bytes as FreeRADIUS (the first 64 for
|
|
|
|
* the MSK, the next for the EMSK, which we just ignore) */
|
|
|
|
if (!this->hkdf->export(this->hkdf, this->msk_label, chunk_empty,
|
|
|
|
this->handshake, 128, &this->msk))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
this->msk.len = 64;
|
|
|
|
}
|
|
|
|
return TRUE;
|
2020-05-21 07:37:38 +00:00
|
|
|
}
|
|
|
|
|
2020-08-27 09:51:00 +00:00
|
|
|
METHOD(tls_crypto_t, update_app_keys, bool,
|
|
|
|
private_tls_crypto_t *this, bool inbound)
|
|
|
|
{
|
2020-10-28 20:54:09 +00:00
|
|
|
suite_algs_t *algs;
|
2020-08-27 09:51:00 +00:00
|
|
|
tls_hkdf_label_t label = TLS_HKDF_UPD_C_TRAFFIC;
|
|
|
|
|
2020-10-28 20:54:09 +00:00
|
|
|
algs = find_suite(this->suite);
|
|
|
|
destroy_aeads(this);
|
|
|
|
if (!create_aead(this, algs))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-08-27 09:51:00 +00:00
|
|
|
if (this->tls->is_server(this->tls) != inbound)
|
|
|
|
{
|
|
|
|
label = TLS_HKDF_UPD_S_TRAFFIC;
|
|
|
|
}
|
|
|
|
return derive_labeled_key(this, label == TLS_HKDF_UPD_S_TRAFFIC, label,
|
|
|
|
inbound ? this->aead_in : this->aead_out);
|
|
|
|
}
|
|
|
|
|
2011-12-31 00:41:56 +00:00
|
|
|
METHOD(tls_crypto_t, resume_session, tls_cipher_suite_t,
|
|
|
|
private_tls_crypto_t *this, chunk_t session, identification_t *id,
|
|
|
|
chunk_t client_random, chunk_t server_random)
|
|
|
|
{
|
|
|
|
chunk_t master;
|
|
|
|
|
|
|
|
if (this->cache && session.len)
|
|
|
|
{
|
|
|
|
this->suite = this->cache->lookup(this->cache, session, id, &master);
|
|
|
|
if (this->suite)
|
|
|
|
{
|
2012-02-07 10:41:56 +00:00
|
|
|
this->suite = select_cipher_suite(this, &this->suite, 1, KEY_ANY);
|
2011-12-31 00:41:56 +00:00
|
|
|
if (this->suite)
|
|
|
|
{
|
2012-07-06 07:49:25 +00:00
|
|
|
if (!this->prf->set_key(this->prf, master) ||
|
|
|
|
!expand_keys(this, client_random, server_random))
|
2012-07-06 07:28:25 +00:00
|
|
|
{
|
|
|
|
this->suite = 0;
|
|
|
|
}
|
2011-12-31 00:41:56 +00:00
|
|
|
}
|
|
|
|
chunk_clear(&master);
|
|
|
|
}
|
2012-02-07 10:41:56 +00:00
|
|
|
return this->suite;
|
2011-12-31 00:41:56 +00:00
|
|
|
}
|
2012-02-07 10:41:56 +00:00
|
|
|
return 0;
|
2011-12-31 00:41:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
METHOD(tls_crypto_t, get_session, chunk_t,
|
|
|
|
private_tls_crypto_t *this, identification_t *server)
|
|
|
|
{
|
|
|
|
if (this->cache)
|
|
|
|
{
|
|
|
|
return this->cache->check(this->cache, server);
|
|
|
|
}
|
|
|
|
return chunk_empty;
|
2010-02-04 17:18:10 +00:00
|
|
|
}
|
2010-02-04 10:17:48 +00:00
|
|
|
|
2010-02-04 17:18:10 +00:00
|
|
|
METHOD(tls_crypto_t, change_cipher, void,
|
|
|
|
private_tls_crypto_t *this, bool inbound)
|
|
|
|
{
|
2010-02-05 13:39:19 +00:00
|
|
|
if (this->protection)
|
2010-02-04 17:18:10 +00:00
|
|
|
{
|
2010-02-05 13:39:19 +00:00
|
|
|
if (inbound)
|
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
this->protection->set_cipher(this->protection, TRUE, this->aead_in);
|
2020-10-28 20:54:09 +00:00
|
|
|
this->aead_in = NULL;
|
2010-02-05 13:39:19 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
this->protection->set_cipher(this->protection, FALSE, this->aead_out);
|
2020-10-28 20:54:09 +00:00
|
|
|
this->aead_out = NULL;
|
2010-02-05 13:39:19 +00:00
|
|
|
}
|
2010-02-04 10:17:48 +00:00
|
|
|
}
|
2010-01-25 11:21:57 +00:00
|
|
|
}
|
|
|
|
|
2010-02-05 11:28:48 +00:00
|
|
|
METHOD(tls_crypto_t, get_eap_msk, chunk_t,
|
|
|
|
private_tls_crypto_t *this)
|
|
|
|
{
|
|
|
|
return this->msk;
|
|
|
|
}
|
|
|
|
|
2010-01-25 11:21:57 +00:00
|
|
|
METHOD(tls_crypto_t, destroy, void,
|
|
|
|
private_tls_crypto_t *this)
|
|
|
|
{
|
2014-02-03 12:20:46 +00:00
|
|
|
destroy_aeads(this);
|
2010-02-05 13:25:38 +00:00
|
|
|
free(this->handshake.ptr);
|
2010-02-05 11:28:48 +00:00
|
|
|
free(this->msk.ptr);
|
2010-02-04 10:17:48 +00:00
|
|
|
DESTROY_IF(this->prf);
|
2020-05-21 07:37:38 +00:00
|
|
|
DESTROY_IF(this->hkdf);
|
2010-02-04 17:18:10 +00:00
|
|
|
free(this->suites);
|
2010-01-25 11:21:57 +00:00
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* See header
|
|
|
|
*/
|
2011-12-31 00:41:56 +00:00
|
|
|
tls_crypto_t *tls_crypto_create(tls_t *tls, tls_cache_t *cache)
|
2010-01-25 11:21:57 +00:00
|
|
|
{
|
|
|
|
private_tls_crypto_t *this;
|
2010-09-03 16:11:03 +00:00
|
|
|
enumerator_t *enumerator;
|
|
|
|
credential_type_t type;
|
|
|
|
int subtype;
|
2010-01-25 11:21:57 +00:00
|
|
|
|
|
|
|
INIT(this,
|
|
|
|
.public = {
|
|
|
|
.get_cipher_suites = _get_cipher_suites,
|
2010-02-04 10:17:48 +00:00
|
|
|
.select_cipher_suite = _select_cipher_suite,
|
2010-09-02 17:24:56 +00:00
|
|
|
.get_dh_group = _get_dh_group,
|
2010-09-02 17:15:16 +00:00
|
|
|
.get_signature_algorithms = _get_signature_algorithms,
|
2010-09-03 15:05:39 +00:00
|
|
|
.create_ec_enumerator = _create_ec_enumerator,
|
2010-02-05 13:39:19 +00:00
|
|
|
.set_protection = _set_protection,
|
2010-02-05 13:25:38 +00:00
|
|
|
.append_handshake = _append_handshake,
|
2020-08-25 15:17:55 +00:00
|
|
|
.hash_handshake = _hash_handshake,
|
2010-09-02 17:15:16 +00:00
|
|
|
.sign = _sign,
|
|
|
|
.verify = _verify,
|
2010-02-05 13:25:38 +00:00
|
|
|
.sign_handshake = _sign_handshake,
|
2010-02-09 17:19:25 +00:00
|
|
|
.verify_handshake = _verify_handshake,
|
2020-08-25 14:52:20 +00:00
|
|
|
.calculate_finished_legacy = _calculate_finished_legacy,
|
2010-02-05 13:25:38 +00:00
|
|
|
.calculate_finished = _calculate_finished,
|
|
|
|
.derive_secrets = _derive_secrets,
|
2020-08-25 11:22:04 +00:00
|
|
|
.derive_handshake_keys = _derive_handshake_keys,
|
|
|
|
.derive_app_keys = _derive_app_keys,
|
2020-08-27 09:51:00 +00:00
|
|
|
.update_app_keys = _update_app_keys,
|
2011-12-31 00:41:56 +00:00
|
|
|
.resume_session = _resume_session,
|
|
|
|
.get_session = _get_session,
|
2010-02-04 17:18:10 +00:00
|
|
|
.change_cipher = _change_cipher,
|
2010-02-05 11:28:48 +00:00
|
|
|
.get_eap_msk = _get_eap_msk,
|
2010-01-25 11:21:57 +00:00
|
|
|
.destroy = _destroy,
|
|
|
|
},
|
2010-02-04 10:17:48 +00:00
|
|
|
.tls = tls,
|
2011-12-31 00:41:56 +00:00
|
|
|
.cache = cache,
|
2010-01-25 11:21:57 +00:00
|
|
|
);
|
|
|
|
|
2020-10-23 14:17:16 +00:00
|
|
|
/* FIXME: EDDSA keys are currently treated like ECDSA keys. A cleaner
|
|
|
|
* separation would be welcome. */
|
2010-09-03 16:11:03 +00:00
|
|
|
enumerator = lib->creds->create_builder_enumerator(lib->creds);
|
|
|
|
while (enumerator->enumerate(enumerator, &type, &subtype))
|
|
|
|
{
|
|
|
|
if (type == CRED_PUBLIC_KEY)
|
|
|
|
{
|
|
|
|
switch (subtype)
|
|
|
|
{
|
|
|
|
case KEY_RSA:
|
|
|
|
this->rsa = TRUE;
|
|
|
|
break;
|
|
|
|
case KEY_ECDSA:
|
2020-10-23 14:17:16 +00:00
|
|
|
case KEY_ED25519:
|
|
|
|
case KEY_ED448:
|
2010-09-03 16:11:03 +00:00
|
|
|
this->ecdsa = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
|
2010-08-20 13:02:25 +00:00
|
|
|
switch (tls->get_purpose(tls))
|
|
|
|
{
|
|
|
|
case TLS_PURPOSE_EAP_TLS:
|
|
|
|
/* MSK PRF ASCII constant label according to EAP-TLS RFC 5216 */
|
|
|
|
this->msk_label = "client EAP encryption";
|
2012-09-28 16:55:40 +00:00
|
|
|
break;
|
2012-08-30 09:13:02 +00:00
|
|
|
case TLS_PURPOSE_EAP_PEAP:
|
|
|
|
this->msk_label = "client EAP encryption";
|
2010-08-20 13:02:25 +00:00
|
|
|
break;
|
|
|
|
case TLS_PURPOSE_EAP_TTLS:
|
|
|
|
/* MSK PRF ASCII constant label according to EAP-TTLS RFC 5281 */
|
|
|
|
this->msk_label = "ttls keying material";
|
2014-03-25 08:49:04 +00:00
|
|
|
break;
|
2010-09-08 10:11:44 +00:00
|
|
|
default:
|
|
|
|
break;
|
2010-08-20 13:02:25 +00:00
|
|
|
}
|
2010-01-25 11:21:57 +00:00
|
|
|
return &this->public;
|
|
|
|
}
|
2014-03-24 13:28:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* See header.
|
|
|
|
*/
|
2020-08-25 11:54:08 +00:00
|
|
|
int tls_crypto_get_supported_suites(bool null, tls_version_t version,
|
|
|
|
tls_cipher_suite_t **out)
|
2014-03-24 13:28:50 +00:00
|
|
|
{
|
|
|
|
suite_algs_t suites[countof(suite_algs)];
|
2020-08-25 11:54:08 +00:00
|
|
|
int count = 0, i;
|
2014-03-24 13:28:50 +00:00
|
|
|
|
|
|
|
/* initialize copy of suite list */
|
2020-08-25 11:54:08 +00:00
|
|
|
for (i = 0; i < countof(suite_algs); i++)
|
2014-03-24 13:28:50 +00:00
|
|
|
{
|
2020-08-25 11:54:08 +00:00
|
|
|
if (suite_algs[i].min_version <= version &&
|
|
|
|
suite_algs[i].max_version >= version)
|
|
|
|
{
|
|
|
|
suites[count++] = suite_algs[i];
|
|
|
|
}
|
2014-03-24 13:28:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
filter_unsupported_suites(suites, &count);
|
|
|
|
|
|
|
|
if (!null)
|
|
|
|
{
|
|
|
|
filter_null_suites(suites, &count);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
{
|
|
|
|
*out = calloc(count, sizeof(tls_cipher_suite_t));
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
(*out)[i] = suites[i].suite;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
2020-09-30 12:57:14 +00:00
|
|
|
|
2020-09-26 20:19:16 +00:00
|
|
|
/**
|
|
|
|
* See header.
|
|
|
|
*/
|
|
|
|
int tls_crypto_get_supported_groups(diffie_hellman_group_t **out)
|
|
|
|
{
|
|
|
|
enumerator_t *enumerator;
|
|
|
|
diffie_hellman_group_t groups[countof(curves)];
|
|
|
|
diffie_hellman_group_t group;
|
|
|
|
tls_named_group_t curve;
|
|
|
|
int count = 0, i;
|
|
|
|
|
|
|
|
enumerator = enumerator_create_filter(
|
|
|
|
lib->crypto->create_dh_enumerator(lib->crypto),
|
|
|
|
group_filter, NULL, NULL);
|
|
|
|
|
|
|
|
while (enumerator->enumerate(enumerator, &group, &curve))
|
|
|
|
{
|
|
|
|
groups[count++] = group;
|
|
|
|
}
|
|
|
|
enumerator->destroy(enumerator);
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
{
|
|
|
|
*out = calloc(count, sizeof(diffie_hellman_group_t));
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
(*out)[i] = groups[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:41:56 +00:00
|
|
|
/**
|
|
|
|
* See header.
|
|
|
|
*/
|
|
|
|
int tls_crypto_get_supported_signatures(tls_version_t version,
|
|
|
|
tls_signature_scheme_t **out)
|
|
|
|
{
|
|
|
|
scheme_algs_t sigs[countof(schemes)];
|
|
|
|
int count = 0, i;
|
|
|
|
|
|
|
|
/* initialize copy of signature scheme list */
|
|
|
|
for (i = 0; i < countof(schemes); i++)
|
|
|
|
{
|
|
|
|
/* only RSA_PSS_RSAE schemes supported for signing and verifying */
|
|
|
|
if (schemes[i].sig == TLS_SIG_RSA_PSS_PSS_SHA256 ||
|
|
|
|
schemes[i].sig == TLS_SIG_RSA_PSS_PSS_SHA384 ||
|
|
|
|
schemes[i].sig == TLS_SIG_RSA_PSS_PSS_SHA512)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (schemes[i].min_version <= version &&
|
|
|
|
schemes[i].max_version >= version &&
|
|
|
|
lib->plugins->has_feature(lib->plugins,
|
|
|
|
PLUGIN_PROVIDE(PUBKEY_VERIFY, schemes[i].params.scheme)))
|
|
|
|
{
|
|
|
|
sigs[count++] = schemes[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (out)
|
|
|
|
{
|
|
|
|
*out = calloc(count, sizeof(tls_signature_scheme_t));
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
(*out)[i] = sigs[i].sig;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2020-09-30 12:57:14 +00:00
|
|
|
/**
|
|
|
|
* See header.
|
|
|
|
*/
|
|
|
|
tls_named_group_t tls_ec_group_to_curve(diffie_hellman_group_t group)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < countof(curves); i++)
|
|
|
|
{
|
|
|
|
if (curves[i].group == group)
|
|
|
|
{
|
|
|
|
return curves[i].curve;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2020-10-12 16:58:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* See header.
|
|
|
|
*/
|
|
|
|
key_type_t tls_signature_scheme_to_key_type(tls_signature_scheme_t sig)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < countof(schemes); i++)
|
|
|
|
{
|
|
|
|
if (schemes[i].sig == sig)
|
|
|
|
{
|
|
|
|
return key_type_from_signature_scheme(schemes[i].params.scheme);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hashtable hash function
|
|
|
|
*/
|
|
|
|
static u_int hash_key_type(key_type_t *type)
|
|
|
|
{
|
|
|
|
return chunk_hash(chunk_from_thing(*type));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hashtable equals function
|
|
|
|
*/
|
|
|
|
static bool equals_key_type(key_type_t *key1, key_type_t *key2)
|
|
|
|
{
|
|
|
|
return *key1 == *key2;
|
|
|
|
}
|
|
|
|
|
|
|
|
CALLBACK(filter_key_types, bool,
|
|
|
|
void *data, enumerator_t *orig, va_list args)
|
|
|
|
{
|
|
|
|
key_type_t *key_type, *out;
|
|
|
|
|
|
|
|
VA_ARGS_VGET(args, out);
|
|
|
|
|
|
|
|
if (orig->enumerate(orig, NULL, &key_type))
|
|
|
|
{
|
|
|
|
*out = *key_type;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CALLBACK(destroy_key_types, void,
|
|
|
|
hashtable_t *ht)
|
|
|
|
{
|
|
|
|
ht->destroy_function(ht, (void*)free);
|
|
|
|
}
|
|
|
|
|
2020-11-10 09:22:12 +00:00
|
|
|
/**
|
|
|
|
* Create an enumerator over supported key types within a specific TLS range
|
2020-10-12 16:58:53 +00:00
|
|
|
*/
|
2020-11-10 09:22:12 +00:00
|
|
|
static enumerator_t *get_supported_key_types(tls_version_t min_version,
|
2020-10-12 16:58:53 +00:00
|
|
|
tls_version_t max_version)
|
|
|
|
{
|
|
|
|
hashtable_t *ht;
|
|
|
|
key_type_t *type, lookup;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
ht = hashtable_create((hashtable_hash_t)hash_key_type,
|
|
|
|
(hashtable_equals_t)equals_key_type, 4);
|
|
|
|
for (i = 0; i < countof(schemes); i++)
|
|
|
|
{
|
|
|
|
if (schemes[i].min_version <= max_version &&
|
|
|
|
schemes[i].max_version >= min_version)
|
|
|
|
{
|
|
|
|
lookup = key_type_from_signature_scheme(schemes[i].params.scheme);
|
|
|
|
if (!ht->get(ht, &lookup))
|
|
|
|
{
|
|
|
|
type = malloc_thing(key_type_t);
|
|
|
|
*type = lookup;
|
|
|
|
ht->put(ht, type, type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return enumerator_create_filter(ht->create_enumerator(ht),
|
|
|
|
filter_key_types, ht, destroy_key_types);
|
|
|
|
}
|
2020-11-10 09:22:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create an array of an intersection of server and peer supported key types
|
|
|
|
*/
|
|
|
|
static array_t *create_common_key_types(enumerator_t *enumerator, chunk_t hashsig)
|
|
|
|
{
|
|
|
|
array_t *key_types;
|
|
|
|
key_type_t v, lookup;
|
|
|
|
uint16_t sig_scheme;
|
|
|
|
|
|
|
|
key_types = array_create(sizeof(key_type_t), 8);
|
|
|
|
while (enumerator->enumerate(enumerator, &v))
|
|
|
|
{
|
|
|
|
bio_reader_t *reader;
|
|
|
|
|
|
|
|
reader = bio_reader_create(hashsig);
|
|
|
|
while (reader->remaining(reader) &&
|
|
|
|
reader->read_uint16(reader, &sig_scheme))
|
|
|
|
{
|
|
|
|
lookup = tls_signature_scheme_to_key_type(sig_scheme);
|
|
|
|
if (v == lookup)
|
|
|
|
{
|
|
|
|
array_insert(key_types, ARRAY_TAIL, &lookup);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
reader->destroy(reader);
|
|
|
|
}
|
|
|
|
return key_types;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
enumerator_t public;
|
|
|
|
array_t *key_types;
|
|
|
|
identification_t *peer;
|
|
|
|
private_key_t *key;
|
|
|
|
auth_cfg_t *auth;
|
|
|
|
} private_key_enumerator_t;
|
|
|
|
|
|
|
|
METHOD(enumerator_t, private_key_enumerate, bool,
|
|
|
|
private_key_enumerator_t *this, va_list args)
|
|
|
|
{
|
|
|
|
key_type_t type;
|
|
|
|
auth_cfg_t **auth_out;
|
|
|
|
private_key_t **key_out;
|
|
|
|
|
|
|
|
VA_ARGS_VGET(args, key_out, auth_out);
|
|
|
|
|
|
|
|
DESTROY_IF(this->key);
|
|
|
|
DESTROY_IF(this->auth);
|
|
|
|
this->auth = auth_cfg_create();
|
|
|
|
|
|
|
|
while (array_remove(this->key_types, ARRAY_HEAD, &type))
|
|
|
|
{
|
|
|
|
this->key = lib->credmgr->get_private(lib->credmgr, type, this->peer,
|
|
|
|
this->auth);
|
|
|
|
if (this->key)
|
|
|
|
{
|
|
|
|
*key_out = this->key;
|
|
|
|
if (auth_out)
|
|
|
|
{
|
|
|
|
*auth_out = this->auth;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
METHOD(enumerator_t, private_key_destroy, void,
|
|
|
|
private_key_enumerator_t *this)
|
|
|
|
{
|
|
|
|
DESTROY_IF(this->key);
|
|
|
|
DESTROY_IF(this->auth);
|
|
|
|
array_destroy(this->key_types);
|
|
|
|
free(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* See header.
|
|
|
|
*/
|
|
|
|
enumerator_t *tls_create_private_key_enumerator(tls_version_t min_version,
|
|
|
|
tls_version_t max_version,
|
|
|
|
chunk_t hashsig,
|
|
|
|
identification_t *peer)
|
|
|
|
{
|
|
|
|
private_key_enumerator_t *enumerator;
|
|
|
|
enumerator_t *key_types;
|
|
|
|
|
|
|
|
key_types = get_supported_key_types(min_version, max_version);
|
|
|
|
|
|
|
|
INIT(enumerator,
|
|
|
|
.public = {
|
|
|
|
.enumerate = enumerator_enumerate_default,
|
|
|
|
.venumerate = _private_key_enumerate,
|
|
|
|
.destroy = _private_key_destroy,
|
|
|
|
},
|
|
|
|
.key_types = create_common_key_types(key_types, hashsig),
|
|
|
|
.peer = peer,
|
|
|
|
);
|
|
|
|
key_types->destroy(key_types);
|
|
|
|
|
|
|
|
if (!array_count(enumerator->key_types))
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return &enumerator->public;
|
|
|
|
}
|