blob: 1c1ca078b3d83b60cea0b98df74950ecec474dd4 [file] [log] [blame]
/*
* Embedded Linux library
*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define _GNU_SOURCE
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include "util.h"
#include "tls.h"
#include "cipher.h"
#include "checksum.h"
#include "cert.h"
#include "tls-private.h"
#include "key.h"
#include "random.h"
#include "ecc.h"
#include "ecdh.h"
#include "missing.h"
static bool tls_rsa_validate_cert_key(struct l_cert *cert)
{
return l_cert_get_pubkey_type(cert) == L_CERT_KEY_RSA;
}
static ssize_t tls_rsa_sign(struct l_tls *tls, uint8_t *out, size_t out_len,
tls_get_hash_t get_hash,
const uint8_t *data, size_t data_len)
{
ssize_t result = -EMSGSIZE;
enum l_checksum_type sign_checksum_type;
uint8_t sign_input[HANDSHAKE_HASH_MAX_SIZE + 36];
size_t sign_input_len;
uint8_t *ptr = out;
if (!tls->priv_key || !tls->priv_key_size) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, TLS_ALERT_BAD_CERT,
"No private key loaded");
return -ENOKEY;
}
if (tls->negotiated_version >= L_TLS_V12) {
const struct tls_hash_algorithm *hash_type =
&tls_handshake_hash_data[tls->signature_hash];
/* Build the DigitallySigned struct */
if (out_len < 2) /* Is there space for the algorithm IDs */
goto error;
get_hash(tls, tls->signature_hash, data, data_len,
sign_input, &sign_input_len);
sign_checksum_type = hash_type->l_id;
*ptr++ = hash_type->tls_id;
*ptr++ = 1; /* RSA_sign */
out_len -= 2;
} else {
get_hash(tls, HANDSHAKE_HASH_MD5, data, data_len,
sign_input + 0, NULL);
get_hash(tls, HANDSHAKE_HASH_SHA1, data, data_len,
sign_input + 16, NULL);
sign_checksum_type = L_CHECKSUM_NONE;
sign_input_len = 36;
}
if (out_len < tls->priv_key_size + 2)
goto error;
l_put_be16(tls->priv_key_size, ptr);
result = l_key_sign(tls->priv_key, L_KEY_RSA_PKCS1_V1_5,
sign_checksum_type, sign_input, ptr + 2,
sign_input_len, tls->priv_key_size);
ptr += tls->priv_key_size + 2;
if (result == (ssize_t) tls->priv_key_size)
return ptr - out; /* Success */
error:
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Signing the hash failed: %s",
strerror(-result));
return result;
}
static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t in_len,
tls_get_hash_t get_hash,
const uint8_t *data, size_t data_len)
{
enum l_checksum_type sign_checksum_type;
uint8_t expected[HANDSHAKE_HASH_MAX_SIZE + 36];
size_t expected_len;
unsigned int offset;
bool success;
/* 2 bytes for SignatureAndHashAlgorithm if version >= 1.2 */
offset = 2;
if (tls->negotiated_version < L_TLS_V12)
offset = 0;
if (in_len < offset + 2 ||
(size_t) l_get_be16(in + offset) + offset + 2 !=
in_len) {
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0, "Signature msg too "
"short (%zi) or signature length doesn't match",
in_len);
return false;
}
/* Only the default hash type supported */
if (in_len != offset + 2 + tls->peer_pubkey_size) {
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"Signature length %zi not equal %zi", in_len,
offset + 2 + tls->peer_pubkey_size);
return false;
}
if (tls->negotiated_version >= L_TLS_V12) {
enum handshake_hash_type hash;
/* Only RSA supported */
if (in[1] != 1 /* RSA_sign */) {
TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
"Unknown signature algorithm %i",
in[1]);
return false;
}
for (hash = 0; hash < __HANDSHAKE_HASH_COUNT; hash++)
if (tls_handshake_hash_data[hash].tls_id == in[0])
break;
if (hash == __HANDSHAKE_HASH_COUNT) {
TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
"Unknown hash type %i", in[0]);
return false;
}
get_hash(tls, hash, data, data_len, expected, &expected_len);
sign_checksum_type = tls_handshake_hash_data[hash].l_id;
/*
* Note: Next we let the l_key_verify's underlying kernel
* operation prepend the OID to the hash to build the
* DigestInfo struct. However according to 4.7 we need to
* support at least two forms of the signed content in the
* verification:
* - DigestInfo with NULL AlgorithmIdentifier.parameters,
* - DigestInfo with empty AlgorithmIdentifier.parameters,
*
* while the kernel only understands the former encoding.
* Note PKCS#1 versions 2.0 and later section A.2.4 do
* mandate NULL AlgorithmIdentifier.parameters.
*
* Additionally PKCS#1 v1.5 said BER is used in place of DER
* for DigestInfo encoding which adds more ambiguity in the
* encoding.
*/
} else {
get_hash(tls, HANDSHAKE_HASH_MD5, data, data_len,
expected + 0, NULL);
get_hash(tls, HANDSHAKE_HASH_SHA1, data, data_len,
expected + 16, NULL);
expected_len = 36;
sign_checksum_type = L_CHECKSUM_NONE;
/*
* Note: Within the RSA padding for signatures PKCS#1 1.5
* allows the block format to be either 0 or 1, while PKCS#1
* v2.0+ mandates block type 1 making the signatures
* unambiguous. TLS 1.0 doesn't additionally specify which
* block type is to be used (TLS 1.2 does) meaning that both
* PKCS#1 v1.5 types are allowed. The l_key_verify's
* underlying kernel implementation only accepts block type
* 1. If this ever becomes an issue we'd need to go back to
* using L_KEY_RSA_RAW and our own PKCS#1 v1.5 verify logic.
*/
}
success = l_key_verify(tls->peer_pubkey, L_KEY_RSA_PKCS1_V1_5,
sign_checksum_type, expected, in + offset + 2,
expected_len, tls->peer_pubkey_size);
if (!success)
TLS_DISCONNECT(TLS_ALERT_DECRYPT_ERROR, 0,
"Peer signature verification failed");
else
TLS_DEBUG("Peer signature verified");
return success;
}
static struct tls_signature_algorithm tls_rsa_signature = {
.id = 1, /* SignatureAlgorithm.rsa */
.validate_cert_key_type = tls_rsa_validate_cert_key,
.sign = tls_rsa_sign,
.verify = tls_rsa_verify,
};
static bool tls_send_rsa_client_key_xchg(struct l_tls *tls)
{
uint8_t buf[1024 + 32];
uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
uint8_t pre_master_secret[48];
ssize_t bytes_encrypted;
if (!tls->peer_pubkey) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Peer public key not received");
return false;
}
/* Must match the version in tls_send_client_hello */
pre_master_secret[0] = (uint8_t) (tls->max_version >> 8);
pre_master_secret[1] = (uint8_t) (tls->max_version >> 0);
l_getrandom(pre_master_secret + 2, 46);
if (tls->peer_pubkey_size + 32 > (int) sizeof(buf)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Peer public key too big: %zi",
tls->peer_pubkey_size);
return false;
}
l_put_be16(tls->peer_pubkey_size, ptr);
bytes_encrypted = l_key_encrypt(tls->peer_pubkey,
L_KEY_RSA_PKCS1_V1_5, L_CHECKSUM_NONE,
pre_master_secret, ptr + 2, 48,
tls->peer_pubkey_size);
ptr += tls->peer_pubkey_size + 2;
if (bytes_encrypted != (ssize_t) tls->peer_pubkey_size) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Encrypting PreMasterSecret failed: %s",
strerror(-bytes_encrypted));
return false;
}
tls_tx_handshake(tls, TLS_CLIENT_KEY_EXCHANGE, buf, ptr - buf);
tls_generate_master_secret(tls, pre_master_secret, 48);
explicit_bzero(pre_master_secret, 48);
return true;
}
static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
const uint8_t *buf, size_t len)
{
uint8_t pre_master_secret[48], random_secret[46];
ssize_t bytes_decrypted;
if (!tls->priv_key || !tls->priv_key_size) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, TLS_ALERT_BAD_CERT,
"No private key");
return;
}
if (len != tls->priv_key_size + 2) {
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"ClientKeyExchange len %zi not %zi", len,
tls->priv_key_size + 2);
return;
}
len = l_get_be16(buf);
if (len != tls->priv_key_size) {
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"EncryptedPreMasterSecret len %zi not %zi",
len, tls->priv_key_size);
return;
}
bytes_decrypted = l_key_decrypt(tls->priv_key, L_KEY_RSA_PKCS1_V1_5,
L_CHECKSUM_NONE, buf + 2,
pre_master_secret, tls->priv_key_size,
48);
/*
* Assume correct premaster secret client version which according
* to the TLS1.2 spec is unlikely in client implementations SSLv3
* and prior. Spec suggests either not supporting them or adding
* a configurable override for <= SSLv3 clients. For now we have
* no need to support them.
*
* On any decode error randomise the Pre Master Secret as per the
* countermeasures in 7.4.7.1 and don't generate any alerts.
*/
l_getrandom(random_secret, 46);
pre_master_secret[0] = tls->client_version >> 8;
pre_master_secret[1] = tls->client_version >> 0;
if (bytes_decrypted != 48) {
memcpy(pre_master_secret + 2, random_secret, 46);
TLS_DEBUG("Error decrypting PreMasterSecret: %s",
strerror(-bytes_decrypted));
}
tls_generate_master_secret(tls, pre_master_secret, 48);
explicit_bzero(pre_master_secret, 48);
explicit_bzero(random_secret, 46);
}
static struct tls_key_exchange_algorithm tls_rsa_key_xchg = {
.send_client_key_exchange = tls_send_rsa_client_key_xchg,
.handle_client_key_exchange = tls_handle_rsa_client_key_xchg,
};
/* Used by both DHE and ECDHE */
static bool tls_get_dh_params_hash(struct l_tls *tls,
enum handshake_hash_type type,
const uint8_t *data, size_t data_len,
uint8_t *out, size_t *out_len)
{
struct l_checksum *checksum;
ssize_t ret;
/*
* The ServerKeyExchange signature hash input format for RSA_sign is
* not really specified in either RFC 8422 or RFC 5246 explicitly
* but we use this format by analogy to DHE_RSA which uses RSA_sign
* as well. Also matches ecdsa, ed25519 and ed448 formats.
*/
struct iovec iov[] = {
{ .iov_base = tls->pending.client_random, .iov_len = 32 },
{ .iov_base = tls->pending.server_random, .iov_len = 32 },
{ .iov_base = (void *) data, .iov_len = data_len },
};
checksum = l_checksum_new(tls_handshake_hash_data[type].l_id);
if (!checksum)
return false;
l_checksum_updatev(checksum, iov, L_ARRAY_SIZE(iov));
ret = l_checksum_get_digest(checksum, out, HANDSHAKE_HASH_MAX_SIZE);
l_checksum_free(checksum);
if (ret < 0)
return false;
if (out_len)
*out_len = ret;
return true;
}
struct tls_ecdhe_params {
const struct l_ecc_curve *curve;
struct l_ecc_scalar *private;
struct l_ecc_point *public;
};
static void tls_free_ecdhe_params(struct l_tls *tls)
{
struct tls_ecdhe_params *params = tls->pending.key_xchg_params;
if (!params)
return;
tls->pending.key_xchg_params = NULL;
l_ecc_scalar_free(params->private);
l_ecc_point_free(params->public);
l_free(params);
}
static size_t tls_write_ecpoint(uint8_t *buf, size_t len,
const struct tls_named_group *curve,
const struct l_ecc_point *point)
{
size_t point_bytes;
/* RFC 8422, Section 5.4.1 */
point_bytes = l_ecc_point_get_data(point, buf + 2, len - 2);
buf[0] = 1 + point_bytes; /* length */
buf[1] = 4; /* form: uncompressed */
return 2 + point_bytes;
}
static size_t tls_write_server_ecdh_params(struct l_tls *tls, uint8_t *buf, size_t len)
{
struct tls_ecdhe_params *params = tls->pending.key_xchg_params;
/* RFC 8422, Section 5.4 */
buf[0] = 3; /* curve_type: named_curve */
l_put_be16(tls->negotiated_curve->id, buf + 1);
return 3 + tls_write_ecpoint(buf + 3, len - 3, tls->negotiated_curve,
params->public);
}
static bool tls_send_ecdhe_server_key_xchg(struct l_tls *tls)
{
uint8_t buf[1024];
uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
struct tls_ecdhe_params *params;
ssize_t sign_len;
const uint8_t *server_ecdh_params_ptr;
/*
* RFC 8422, Section 5.4
*
* If we're getting here we can assume that tls->pending.key_xchg_params
* is NULL, tls->priv_key is our signing key and tls->negotiated_curve
* is non-NULL.
*/
params = l_new(struct tls_ecdhe_params, 1);
params->curve = l_ecc_curve_from_tls_group(tls->negotiated_curve->id);
tls->pending.key_xchg_params = params;
if (!l_ecdh_generate_key_pair(params->curve,
&params->private, &params->public)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Generating ECDH key pair failed");
return false;
}
server_ecdh_params_ptr = ptr;
ptr += tls_write_server_ecdh_params(tls, ptr, buf + sizeof(buf) - ptr);
if (tls->pending.cipher_suite->signature) {
sign_len = tls->pending.cipher_suite->signature->sign(tls, ptr,
buf + sizeof(buf) - ptr,
tls_get_dh_params_hash,
server_ecdh_params_ptr,
ptr - server_ecdh_params_ptr);
if (sign_len < 0)
return false;
ptr += sign_len;
}
tls_tx_handshake(tls, TLS_SERVER_KEY_EXCHANGE, buf, ptr - buf);
return true;
}
static void tls_handle_ecdhe_server_key_xchg(struct l_tls *tls,
const uint8_t *buf, size_t len)
{
struct tls_ecdhe_params *params;
uint16_t namedcurve;
const uint8_t *server_ecdh_params_ptr = buf;
size_t point_bytes;
/* RFC 8422, Section 5.4 */
if (len < 5)
goto decode_error;
if (*buf != 3) {
TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
"Unsupported (deprecated?) ECCurveType %u",
*buf);
return;
}
namedcurve = l_get_be16(buf + 1);
buf += 3;
len -= 3;
tls->negotiated_curve = tls_find_group(namedcurve);
if (!tls->negotiated_curve ||
tls->negotiated_curve->type != TLS_GROUP_TYPE_EC) {
TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
"Unsupported NamedCurve %u", namedcurve);
return;
}
TLS_DEBUG("Negotiated %s", tls->negotiated_curve->name);
if (*buf < 1)
goto decode_error;
point_bytes = *buf++ - 1;
if (*buf != 4) { /* uncompressed */
TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
"Unsupported (deprecated?) PointConversionForm "
"%u", *buf);
return;
}
buf++;
len -= 2;
if (len < point_bytes)
goto decode_error;
/*
* RFC 8422, Section 5.11: "A receiving party MUST check that the
* x and y parameters from the peer's public value satisfy the
* curve equation, y^2 = x^3 + ax + b mod p."
* This happens in l_ecc_point_from_data when the L_ECC_POINT_TYPE_FULL
* format is used.
*/
params = l_new(struct tls_ecdhe_params, 1);
params->curve = l_ecc_curve_from_tls_group(tls->negotiated_curve->id);
params->public = l_ecc_point_from_data(params->curve,
L_ECC_POINT_TYPE_FULL,
buf, point_bytes);
tls->pending.key_xchg_params = params;
buf += point_bytes;
len -= point_bytes;
if (!params->public || point_bytes !=
2 * l_ecc_curve_get_scalar_bytes(params->curve)) {
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"ServerKeyExchange.params.public decode error");
return;
}
if (tls->pending.cipher_suite->signature) {
if (!tls->pending.cipher_suite->signature->verify(tls, buf, len,
tls_get_dh_params_hash,
server_ecdh_params_ptr,
buf - server_ecdh_params_ptr))
return;
} else {
if (len)
goto decode_error;
}
TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO_DONE);
return;
decode_error:
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"ServerKeyExchange decode error");
}
static bool tls_send_ecdhe_client_key_xchg(struct l_tls *tls)
{
uint8_t buf[1024];
uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
uint8_t pre_master_secret[128];
ssize_t pre_master_secret_len;
struct tls_ecdhe_params *params = tls->pending.key_xchg_params;
struct l_ecc_point *our_public;
struct l_ecc_scalar *secret;
/* RFC 8422, Section 5.7 */
if (!l_ecdh_generate_key_pair(params->curve,
&params->private, &our_public)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Generating ECDH key pair failed");
return false;
}
ptr += tls_write_ecpoint(ptr, buf + sizeof(buf) - ptr,
tls->negotiated_curve, our_public);
l_ecc_point_free(our_public);
/*
* Neither 5.4 or 5.7 "Actions" paragraphs say when the ECDH shared
* secret is calculated but we can either do this in
* tls_handle_ecdhe_server_key_xchg or here. In both cases we only
* need to store the public key in the client's key_xchg_params and
* can free all of the params after sending the ClientKeyExchange.
* By doing this calculation here we're aligned with RSA and also
* with the server mode where the shared secret can only be
* calculated after the ClientKeyExchange is received.
*/
if (!l_ecdh_generate_shared_secret(params->private, params->public,
&secret)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Generating ECDH shared-secret failed");
return false;
}
tls_free_ecdhe_params(tls);
pre_master_secret_len = l_ecc_scalar_get_data(secret,
pre_master_secret,
sizeof(pre_master_secret));
l_ecc_scalar_free(secret);
if (pre_master_secret_len < 0) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"l_ecc_scalar_get_data(secret) failed");
return false;
}
tls_tx_handshake(tls, TLS_CLIENT_KEY_EXCHANGE, buf, ptr - buf);
tls_generate_master_secret(tls, pre_master_secret,
pre_master_secret_len);
explicit_bzero(pre_master_secret, pre_master_secret_len);
return true;
}
static void tls_handle_ecdhe_client_key_xchg(struct l_tls *tls,
const uint8_t *buf, size_t len)
{
struct tls_ecdhe_params *params = tls->pending.key_xchg_params;
uint8_t pre_master_secret[128];
ssize_t pre_master_secret_len;
struct l_ecc_point *other_public;
struct l_ecc_scalar *secret;
size_t point_bytes = 2 * l_ecc_curve_get_scalar_bytes(params->curve);
/* RFC 8422, Section 5.7 */
if (len < 2)
goto decode_error;
if (*buf++ != 1 + point_bytes)
goto decode_error;
if (*buf != 4) { /* uncompressed */
TLS_DISCONNECT(TLS_ALERT_ILLEGAL_PARAM, 0,
"Unsupported (deprecated?) PointConversionForm "
"%u", *buf);
return;
}
buf++;
len -= 2;
if (len != point_bytes)
goto decode_error;
/*
* RFC 8422, Section 5.11: "A receiving party MUST check that the
* x and y parameters from the peer's public value satisfy the
* curve equation, y^2 = x^3 + ax + b mod p."
* This happens in l_ecc_point_from_data when the L_ECC_POINT_TYPE_FULL
* format is used.
*/
other_public = l_ecc_point_from_data(params->curve,
L_ECC_POINT_TYPE_FULL,
buf, len);
if (!other_public) {
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"ClientKeyExchange.exchange_keys.ecdh_Yc "
"decode error");
return;
}
if (!l_ecdh_generate_shared_secret(params->private, other_public,
&secret)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Generating ECDH shared-secret failed");
return;
}
tls_free_ecdhe_params(tls);
l_ecc_point_free(other_public);
pre_master_secret_len = l_ecc_scalar_get_data(secret,
pre_master_secret,
sizeof(pre_master_secret));
l_ecc_scalar_free(secret);
if (pre_master_secret_len < 0) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"l_ecc_scalar_get_data(secret) failed");
return;
}
tls_generate_master_secret(tls, pre_master_secret,
pre_master_secret_len);
explicit_bzero(pre_master_secret, pre_master_secret_len);
return;
decode_error:
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"ClientKeyExchange decode error");
}
static struct tls_key_exchange_algorithm tls_ecdhe = {
.need_ecc = true,
.send_server_key_exchange = tls_send_ecdhe_server_key_xchg,
.handle_server_key_exchange = tls_handle_ecdhe_server_key_xchg,
.send_client_key_exchange = tls_send_ecdhe_client_key_xchg,
.handle_client_key_exchange = tls_handle_ecdhe_client_key_xchg,
.free_params = tls_free_ecdhe_params,
};
/* Maximum FF DH prime modulus size in bytes */
#define TLS_DHE_MAX_SIZE 1024
struct tls_dhe_params {
size_t prime_len;
struct l_key *prime;
struct l_key *generator;
struct l_key *private;
struct l_key *public;
};
static void tls_free_dhe_params(struct l_tls *tls)
{
struct tls_dhe_params *params = tls->pending.key_xchg_params;
if (!params)
return;
tls->pending.key_xchg_params = NULL;
l_key_free(params->prime);
l_key_free(params->generator);
l_key_free(params->private);
l_key_free(params->public);
l_free(params);
}
static bool tls_send_dhe_server_key_xchg(struct l_tls *tls)
{
uint8_t buf[1024 + TLS_DHE_MAX_SIZE * 3];
uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
struct tls_dhe_params *params;
const uint8_t *prime_buf;
uint8_t generator_buf = tls->negotiated_ff_group->ff.generator;
uint8_t public_buf[TLS_DHE_MAX_SIZE];
size_t public_len;
unsigned int zeros = 0;
ssize_t sign_len;
const uint8_t *server_dh_params_ptr;
params = l_new(struct tls_dhe_params, 1);
prime_buf = tls->negotiated_ff_group->ff.prime;
params->prime_len = tls->negotiated_ff_group->ff.prime_len;
params->prime = l_key_new(L_KEY_RAW, prime_buf, params->prime_len);
params->generator = l_key_new(L_KEY_RAW, &generator_buf, 1);
if (!params->prime || !params->generator) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, "l_key_new failed");
goto free_params;
}
params->private = l_key_generate_dh_private(prime_buf, params->prime_len);
if (!params->private) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"l_key_generate_dh_private failed");
goto free_params;
}
memset(public_buf, 0, sizeof(public_buf));
public_len = params->prime_len;
if (!l_key_compute_dh_public(params->generator, params->private,
params->prime, public_buf,
&public_len)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"l_key_compute_dh_public failed");
goto free_params;
}
while (zeros < public_len && public_buf[zeros] == 0x00)
zeros++;
server_dh_params_ptr = ptr;
/* RFC 5246, Section 7.4.3 */
l_put_be16(params->prime_len, ptr);
memcpy(ptr + 2, prime_buf, params->prime_len);
ptr += 2 + params->prime_len;
l_put_be16(1, ptr);
memcpy(ptr + 2, &generator_buf, 1);
ptr += 2 + 1;
l_put_be16(public_len - zeros, ptr);
memcpy(ptr + 2, public_buf + zeros, public_len - zeros);
ptr += 2 + public_len - zeros;
if (tls->pending.cipher_suite->signature) {
sign_len = tls->pending.cipher_suite->signature->sign(tls, ptr,
buf + sizeof(buf) - ptr,
tls_get_dh_params_hash,
server_dh_params_ptr,
ptr - server_dh_params_ptr);
if (sign_len < 0)
goto free_params;
ptr += sign_len;
}
tls->pending.key_xchg_params = params;
tls_tx_handshake(tls, TLS_SERVER_KEY_EXCHANGE, buf, ptr - buf);
return true;
free_params:
l_key_free(params->prime);
l_key_free(params->generator);
l_key_free(params->private);
l_free(params);
return false;
}
static void tls_handle_dhe_server_key_xchg(struct l_tls *tls,
const uint8_t *buf, size_t len)
{
struct tls_dhe_params *params = NULL;
const uint8_t *prime_buf;
const uint8_t *generator_buf;
size_t generator_len;
const uint8_t *public_buf;
size_t public_len;
const uint8_t *server_dh_params_ptr = buf;
if (len < 2)
goto decode_error;
params = l_new(struct tls_dhe_params, 1);
params->prime_len = l_get_be16(buf);
if (len < 2 + params->prime_len + 2)
goto decode_error;
prime_buf = buf + 2;
buf += 2 + params->prime_len;
len -= 2 + params->prime_len;
/* Strip leading zeros for the length checks later */
while (params->prime_len && prime_buf[0] == 0x00) {
prime_buf++;
params->prime_len--;
}
generator_len = l_get_be16(buf);
if (len < 2 + generator_len + 2)
goto decode_error;
generator_buf = buf + 2;
buf += 2 + generator_len;
len -= 2 + generator_len;
public_len = l_get_be16(buf);
if (len < 2 + public_len)
goto decode_error;
public_buf = buf + 2;
buf += 2 + public_len;
len -= 2 + public_len;
/*
* Validate the values received. Without requiring RFC 7919 from
* the server, and there are many servers that don't implement it
* yet, we basically have to blindly accept the provided prime value.
* We have no way to confirm that it's actually prime or that it's a
* "safe prime" or that it forms a group without small sub-groups.
* There's also no way to whitelist all valid values. But we do a
* basic sanity check and require it to be 1536-bit or longer, the
* minimum length required by the Linux kernel for keyctl_dh_compute().
* The generator must also be at least within the min & max interval
* for the private/public values.
*/
if (params->prime_len > TLS_DHE_MAX_SIZE || params->prime_len < 192 ||
!(prime_buf[params->prime_len - 1] & 1)) {
TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
"Server DH prime modulus invalid");
goto free_params;
}
if (!l_key_validate_dh_payload(generator_buf, generator_len,
prime_buf, params->prime_len)) {
TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
"Server DH generator value invalid");
goto free_params;
}
/*
* Just output a warning if the server sent group parameters not
* offered in our RFC 7919 Supported Groups extension.
*/
if (!tls_find_ff_group(prime_buf, params->prime_len,
generator_buf, generator_len))
TLS_DEBUG("Warning: using server's custom %i-bit FF DH group",
(int) (params->prime_len * 8));
/*
* RFC 7919 Section 3.0:
* "the client MUST verify that dh_Ys is in the range
* 1 < dh_Ys < dh_p - 1. If dh_Ys is not in this range, the client
* MUST terminate the connection with a fatal handshake_failure(40)
* alert."
*/
if (!l_key_validate_dh_payload(public_buf, public_len,
prime_buf, params->prime_len)) {
TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
"Server DH public value invalid");
goto free_params;
}
params->prime = l_key_new(L_KEY_RAW, prime_buf, params->prime_len);
params->generator = l_key_new(L_KEY_RAW, generator_buf, generator_len);
params->public = l_key_new(L_KEY_RAW, public_buf, public_len);
if (!params->prime || !params->generator || !params->public) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, "l_key_new failed");
goto free_params;
}
/* Do this now so we don't need prime_buf in send_client_key_xchg */
params->private = l_key_generate_dh_private(prime_buf, params->prime_len);
if (!params->private) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"l_key_generate_dh_private failed");
goto free_params;
}
tls->pending.key_xchg_params = params;
if (tls->pending.cipher_suite->signature) {
if (!tls->pending.cipher_suite->signature->verify(tls, buf, len,
tls_get_dh_params_hash,
server_dh_params_ptr,
buf - server_dh_params_ptr))
return;
} else {
if (len)
goto decode_error;
}
TLS_SET_STATE(TLS_HANDSHAKE_WAIT_HELLO_DONE);
return;
decode_error:
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"ServerKeyExchange decode error");
free_params:
if (params) {
l_key_free(params->prime);
l_key_free(params->generator);
l_key_free(params->public);
l_free(params);
}
}
static bool tls_send_dhe_client_key_xchg(struct l_tls *tls)
{
struct tls_dhe_params *params = tls->pending.key_xchg_params;
uint8_t buf[128 + params->prime_len];
uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
uint8_t public_buf[params->prime_len];
size_t public_len;
unsigned int zeros = 0;
uint8_t pre_master_secret[params->prime_len];
size_t pre_master_secret_len;
public_len = params->prime_len;
memset(public_buf, 0, sizeof(public_buf));
if (!l_key_compute_dh_public(params->generator, params->private,
params->prime, public_buf,
&public_len)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"l_key_compute_dh_public failed");
return false;
}
while (zeros < public_len && public_buf[zeros] == 0x00)
zeros++;
l_put_be16(public_len - zeros, ptr);
memcpy(ptr + 2, public_buf + zeros, public_len - zeros);
ptr += 2 + public_len - zeros;
pre_master_secret_len = params->prime_len;
zeros = 0;
if (!l_key_compute_dh_secret(params->public, params->private,
params->prime, pre_master_secret,
&pre_master_secret_len)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Generating DH shared-secret failed");
return false;
}
while (zeros < pre_master_secret_len &&
pre_master_secret[zeros] == 0x00)
zeros++;
tls_tx_handshake(tls, TLS_CLIENT_KEY_EXCHANGE, buf, ptr - buf);
tls_free_dhe_params(tls);
tls_generate_master_secret(tls, pre_master_secret + zeros,
pre_master_secret_len - zeros);
explicit_bzero(pre_master_secret, pre_master_secret_len);
return true;
}
static void tls_handle_dhe_client_key_xchg(struct l_tls *tls,
const uint8_t *buf, size_t len)
{
struct tls_dhe_params *params = tls->pending.key_xchg_params;
uint8_t pre_master_secret[params->prime_len];
size_t pre_master_secret_len;
size_t public_len;
unsigned int zeros = 0;
if (len < 2)
goto decode_error;
public_len = l_get_be16(buf);
buf += 2;
len -= 2;
if (public_len != len)
goto decode_error;
/*
* RFC 7919 Section 4:
* "the server MUST verify that 1 < dh_Yc < dh_p - 1. If dh_Yc is
* out of range, the server MUST terminate the connection with
* a fatal handshake_failure(40) alert."
*/
if (!l_key_validate_dh_payload(buf, public_len,
tls->negotiated_ff_group->ff.prime,
params->prime_len)) {
TLS_DISCONNECT(TLS_ALERT_HANDSHAKE_FAIL, 0,
"Client DH public value invalid");
return;
}
params->public = l_key_new(L_KEY_RAW, buf, public_len);
if (!params->public) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0, "l_key_new failed");
return;
}
pre_master_secret_len = params->prime_len;
if (!l_key_compute_dh_secret(params->public, params->private,
params->prime, pre_master_secret,
&pre_master_secret_len)) {
TLS_DISCONNECT(TLS_ALERT_INTERNAL_ERROR, 0,
"Generating DH shared-secret failed");
return;
}
while (zeros < pre_master_secret_len &&
pre_master_secret[zeros] == 0x00)
zeros++;
tls_free_dhe_params(tls);
tls_generate_master_secret(tls, pre_master_secret + zeros,
pre_master_secret_len - zeros);
explicit_bzero(pre_master_secret, pre_master_secret_len);
return;
decode_error:
TLS_DISCONNECT(TLS_ALERT_DECODE_ERROR, 0,
"ClientKeyExchange decode error");
}
static struct tls_key_exchange_algorithm tls_dhe = {
.need_ecc = true,
.send_server_key_exchange = tls_send_dhe_server_key_xchg,
.handle_server_key_exchange = tls_handle_dhe_server_key_xchg,
.send_client_key_exchange = tls_send_dhe_client_key_xchg,
.handle_client_key_exchange = tls_handle_dhe_client_key_xchg,
.free_params = tls_free_dhe_params,
};
static struct tls_bulk_encryption_algorithm tls_aes128 = {
.cipher_type = TLS_CIPHER_BLOCK,
.l_id = L_CIPHER_AES_CBC,
.key_length = 16,
.iv_length = 16,
.block_length = 16,
}, tls_aes256 = {
.cipher_type = TLS_CIPHER_BLOCK,
.l_id = L_CIPHER_AES_CBC,
.key_length = 32,
.iv_length = 16,
.block_length = 16,
}, tls_3des_ede = {
.cipher_type = TLS_CIPHER_BLOCK,
.l_id = L_CIPHER_DES3_EDE_CBC,
.key_length = 24,
.iv_length = 8,
.block_length = 8,
}, tls_aes128_gcm = {
.cipher_type = TLS_CIPHER_AEAD,
.l_aead_id = L_AEAD_CIPHER_AES_GCM,
.key_length = 16,
.iv_length = 12,
.fixed_iv_length = 4,
.auth_tag_length = 16,
}, tls_aes256_gcm = {
.cipher_type = TLS_CIPHER_AEAD,
.l_aead_id = L_AEAD_CIPHER_AES_GCM,
.key_length = 32,
.iv_length = 12,
.fixed_iv_length = 4,
.auth_tag_length = 16,
};
static struct tls_mac_algorithm tls_sha = {
.id = 2,
.hmac_type = L_CHECKSUM_SHA1,
.mac_length = 20,
}, tls_sha256 = {
.id = 4,
.hmac_type = L_CHECKSUM_SHA256,
.mac_length = 32,
}, tls_sha384 = {
.id = 5,
.hmac_type = L_CHECKSUM_SHA384,
.mac_length = 48,
};
static struct tls_cipher_suite tls_rsa_with_3des_ede_cbc_sha = {
.id = { 0x00, 0x0a },
.name = "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_3des_ede,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_rsa_key_xchg,
}, tls_dhe_rsa_with_3des_ede_cbc_sha = {
.id = { 0x00, 0x16 },
.name = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_3des_ede,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_dhe,
}, tls_rsa_with_aes_128_cbc_sha = {
.id = { 0x00, 0x2f },
.name = "TLS_RSA_WITH_AES_128_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_aes128,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_rsa_key_xchg,
}, tls_dhe_rsa_with_aes_128_cbc_sha = {
.id = { 0x00, 0x33 },
.name = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_aes128,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_dhe,
}, tls_rsa_with_aes_256_cbc_sha = {
.id = { 0x00, 0x35 },
.name = "TLS_RSA_WITH_AES_256_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_aes256,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_rsa_key_xchg,
}, tls_dhe_rsa_with_aes_256_cbc_sha = {
.id = { 0x00, 0x39 },
.name = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_aes256,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_dhe,
}, tls_rsa_with_aes_128_cbc_sha256 = {
.id = { 0x00, 0x3c },
.name = "TLS_RSA_WITH_AES_128_CBC_SHA256",
.verify_data_length = 12,
.encryption = &tls_aes128,
.mac = &tls_sha256,
.signature = &tls_rsa_signature,
.key_xchg = &tls_rsa_key_xchg,
}, tls_rsa_with_aes_256_cbc_sha256 = {
.id = { 0x00, 0x3d },
.name = "TLS_RSA_WITH_AES_256_CBC_SHA256",
.verify_data_length = 12,
.encryption = &tls_aes256,
.mac = &tls_sha256,
.signature = &tls_rsa_signature,
.key_xchg = &tls_rsa_key_xchg,
}, tls_dhe_rsa_with_aes_128_cbc_sha256 = {
.id = { 0x00, 0x67 },
.name = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
.verify_data_length = 12,
.encryption = &tls_aes128,
.mac = &tls_sha256,
.signature = &tls_rsa_signature,
.key_xchg = &tls_dhe,
}, tls_dhe_rsa_with_aes_256_cbc_sha256 = {
.id = { 0x00, 0x6b },
.name = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
.verify_data_length = 12,
.encryption = &tls_aes256,
.mac = &tls_sha256,
.signature = &tls_rsa_signature,
.key_xchg = &tls_dhe,
}, tls_rsa_with_aes_128_gcm_sha256 = {
.id = { 0x00, 0x9c },
.name = "TLS_RSA_WITH_AES_128_GCM_SHA256",
.verify_data_length = 12,
.encryption = &tls_aes128_gcm,
.signature = &tls_rsa_signature,
.key_xchg = &tls_rsa_key_xchg,
}, tls_rsa_with_aes_256_gcm_sha384 = {
.id = { 0x00, 0x9d },
.name = "TLS_RSA_WITH_AES_256_GCM_SHA384",
.verify_data_length = 12,
.encryption = &tls_aes256_gcm,
.prf_hmac = L_CHECKSUM_SHA384,
.signature = &tls_rsa_signature,
.key_xchg = &tls_rsa_key_xchg,
}, tls_dhe_rsa_with_aes_128_gcm_sha256 = {
.id = { 0x00, 0x9e },
.name = "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
.verify_data_length = 12,
.encryption = &tls_aes128_gcm,
.signature = &tls_rsa_signature,
.key_xchg = &tls_dhe,
}, tls_dhe_rsa_with_aes_256_gcm_sha384 = {
.id = { 0x00, 0x9f },
.name = "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
.verify_data_length = 12,
.encryption = &tls_aes256_gcm,
.prf_hmac = L_CHECKSUM_SHA384,
.signature = &tls_rsa_signature,
.key_xchg = &tls_dhe,
}, tls_ecdhe_rsa_with_3des_ede_cbc_sha = {
.id = { 0xc0, 0x12 },
.name = "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_3des_ede,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_ecdhe,
}, tls_ecdhe_rsa_with_aes_128_cbc_sha = {
.id = { 0xc0, 0x13 },
.name = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_aes128,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_ecdhe,
}, tls_ecdhe_rsa_with_aes_256_cbc_sha = {
.id = { 0xc0, 0x14 },
.name = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
.verify_data_length = 12,
.encryption = &tls_aes256,
.mac = &tls_sha,
.signature = &tls_rsa_signature,
.key_xchg = &tls_ecdhe,
}, tls_ecdhe_rsa_with_aes_128_cbc_sha256 = {
.id = { 0xc0, 0x27 },
.name = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
.verify_data_length = 12,
.encryption = &tls_aes128,
.mac = &tls_sha256,
.signature = &tls_rsa_signature,
.key_xchg = &tls_ecdhe,
}, tls_ecdhe_rsa_with_aes_256_cbc_sha384 = {
.id = { 0xc0, 0x28 },
.name = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
.verify_data_length = 12,
.encryption = &tls_aes256,
.mac = &tls_sha384,
.prf_hmac = L_CHECKSUM_SHA384,
.signature = &tls_rsa_signature,
.key_xchg = &tls_ecdhe,
}, tls_ecdhe_rsa_with_aes_128_gcm_sha256 = {
.id = { 0xc0, 0x2f },
.name = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
.verify_data_length = 12,
.encryption = &tls_aes128_gcm,
.signature = &tls_rsa_signature,
.key_xchg = &tls_ecdhe,
}, tls_ecdhe_rsa_with_aes_256_gcm_sha384 = {
.id = { 0xc0, 0x30 },
.name = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
.verify_data_length = 12,
.encryption = &tls_aes256_gcm,
.prf_hmac = L_CHECKSUM_SHA384,
.signature = &tls_rsa_signature,
.key_xchg = &tls_ecdhe,
};
struct tls_cipher_suite *tls_cipher_suite_pref[] = {
&tls_ecdhe_rsa_with_aes_256_cbc_sha,
&tls_ecdhe_rsa_with_aes_128_cbc_sha,
&tls_dhe_rsa_with_aes_256_cbc_sha,
&tls_dhe_rsa_with_aes_128_cbc_sha,
&tls_rsa_with_aes_256_cbc_sha,
&tls_rsa_with_aes_128_cbc_sha,
&tls_ecdhe_rsa_with_aes_256_cbc_sha384,
&tls_ecdhe_rsa_with_aes_128_cbc_sha256,
&tls_dhe_rsa_with_aes_256_cbc_sha256,
&tls_dhe_rsa_with_aes_128_cbc_sha256,
&tls_rsa_with_aes_256_cbc_sha256,
&tls_rsa_with_aes_128_cbc_sha256,
&tls_ecdhe_rsa_with_aes_256_gcm_sha384,
&tls_ecdhe_rsa_with_aes_128_gcm_sha256,
&tls_dhe_rsa_with_aes_256_gcm_sha384,
&tls_dhe_rsa_with_aes_128_gcm_sha256,
&tls_rsa_with_aes_256_gcm_sha384,
&tls_rsa_with_aes_128_gcm_sha256,
&tls_ecdhe_rsa_with_3des_ede_cbc_sha,
&tls_dhe_rsa_with_3des_ede_cbc_sha,
&tls_rsa_with_3des_ede_cbc_sha,
NULL,
};