|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2001-2012 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
* Copyright (C) 2017 Red Hat, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Functions that are supposed to run after the handshake procedure is
|
|
Packit Service |
4684c1 |
* finished. These functions activate the established security parameters.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include <constate.h>
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include <kx.h>
|
|
Packit Service |
4684c1 |
#include <algorithms.h>
|
|
Packit Service |
4684c1 |
#include <num.h>
|
|
Packit Service |
4684c1 |
#include <datum.h>
|
|
Packit Service |
4684c1 |
#include <state.h>
|
|
Packit Service |
4684c1 |
#include <hello_ext.h>
|
|
Packit Service |
4684c1 |
#include <buffers.h>
|
|
Packit Service |
4684c1 |
#include "dtls.h"
|
|
Packit Service |
4684c1 |
#include "secrets.h"
|
|
Packit Service |
4684c1 |
#include "handshake.h"
|
|
Packit Service |
4684c1 |
#include "crypto-api.h"
|
|
Packit Service |
4684c1 |
#include "locks.h"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static const char keyexp[] = "key expansion";
|
|
Packit Service |
4684c1 |
static const int keyexp_length = sizeof(keyexp) - 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_tls13_init_record_state(gnutls_cipher_algorithm_t algo, record_state_st *state);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* This function is to be called after handshake, when master_secret,
|
|
Packit Service |
4684c1 |
* client_random and server_random have been initialized.
|
|
Packit Service |
4684c1 |
* This function creates the keys and stores them into pending session.
|
|
Packit Service |
4684c1 |
* (session->cipher_specs)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_gnutls_set_keys(gnutls_session_t session, record_parameters_st * params,
|
|
Packit Service |
4684c1 |
unsigned hash_size, unsigned IV_size, unsigned key_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t rnd[2 * GNUTLS_RANDOM_SIZE];
|
|
Packit Service |
4684c1 |
int pos, ret;
|
|
Packit Service |
4684c1 |
int block_size;
|
|
Packit Service |
4684c1 |
char buf[4 * MAX_HASH_SIZE + 4 * MAX_CIPHER_KEY_SIZE +
|
|
Packit Service |
4684c1 |
4 * MAX_CIPHER_BLOCK_SIZE];
|
|
Packit Service |
4684c1 |
/* avoid using malloc */
|
|
Packit Service |
4684c1 |
uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
|
|
Packit Service |
4684c1 |
2 * MAX_CIPHER_BLOCK_SIZE];
|
|
Packit Service |
4684c1 |
record_state_st *client_write, *server_write;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
client_write = ¶ms->write;
|
|
Packit Service |
4684c1 |
server_write = ¶ms->read;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
client_write = ¶ms->read;
|
|
Packit Service |
4684c1 |
server_write = ¶ms->write;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
block_size = 2 * hash_size + 2 * key_size;
|
|
Packit Service |
4684c1 |
block_size += 2 * IV_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy(rnd, session->security_parameters.server_random,
|
|
Packit Service |
4684c1 |
GNUTLS_RANDOM_SIZE);
|
|
Packit Service |
4684c1 |
memcpy(&rnd[GNUTLS_RANDOM_SIZE],
|
|
Packit Service |
4684c1 |
session->security_parameters.client_random,
|
|
Packit Service |
4684c1 |
GNUTLS_RANDOM_SIZE);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_SSL3
|
|
Packit Service |
4684c1 |
if (get_num_version(session) == GNUTLS_SSL3) { /* SSL 3 */
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_ssl3_generate_random
|
|
Packit Service |
4684c1 |
(session->security_parameters.master_secret,
|
|
Packit Service |
4684c1 |
GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE,
|
|
Packit Service |
4684c1 |
block_size, key_block);
|
|
Packit Service |
4684c1 |
} else /* TLS 1.0+ */
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_PRF(session,
|
|
Packit Service |
4684c1 |
session->security_parameters.master_secret,
|
|
Packit Service |
4684c1 |
GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
|
|
Packit Service |
4684c1 |
rnd, 2 * GNUTLS_RANDOM_SIZE, block_size,
|
|
Packit Service |
4684c1 |
key_block);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: KEY BLOCK[%d]: %s\n", block_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(key_block, block_size, buf,
|
|
Packit Service |
4684c1 |
sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pos = 0;
|
|
Packit Service |
4684c1 |
if (hash_size > 0) {
|
|
Packit Service |
4684c1 |
assert(hash_size<=sizeof(client_write->mac_key));
|
|
Packit Service |
4684c1 |
client_write->mac_key_size = hash_size;
|
|
Packit Service |
4684c1 |
memcpy(client_write->mac_key, &key_block[pos], hash_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pos += hash_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
server_write->mac_key_size = hash_size;
|
|
Packit Service |
4684c1 |
memcpy(server_write->mac_key, &key_block[pos], hash_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pos += hash_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: CLIENT MAC KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(client_write->mac_key,
|
|
Packit Service |
4684c1 |
hash_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: SERVER MAC KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(server_write->mac_key,
|
|
Packit Service |
4684c1 |
hash_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (key_size > 0) {
|
|
Packit Service |
4684c1 |
assert(key_size <=sizeof(client_write->key));
|
|
Packit Service |
4684c1 |
client_write->key_size = key_size;
|
|
Packit Service |
4684c1 |
memcpy(client_write->key, &key_block[pos], key_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pos += key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
server_write->key_size = key_size;
|
|
Packit Service |
4684c1 |
memcpy(server_write->key, &key_block[pos], key_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pos += key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: CLIENT WRITE KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(client_write->key,
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: SERVER WRITE KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(server_write->key,
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* IV generation in export and non export ciphers.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (IV_size > 0) {
|
|
Packit Service |
4684c1 |
assert(IV_size <= sizeof(client_write->iv));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
client_write->iv_size = IV_size;
|
|
Packit Service |
4684c1 |
memcpy(client_write->iv, &key_block[pos], IV_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pos += IV_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
server_write->iv_size = IV_size;
|
|
Packit Service |
4684c1 |
memcpy(server_write->iv, &key_block[pos], IV_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: CLIENT WRITE IV [%d]: %s\n",
|
|
Packit Service |
4684c1 |
client_write->iv_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(client_write->iv,
|
|
Packit Service |
4684c1 |
client_write->iv_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: SERVER WRITE IV [%d]: %s\n",
|
|
Packit Service |
4684c1 |
server_write->iv_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(server_write->iv,
|
|
Packit Service |
4684c1 |
server_write->iv_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_tls13_update_keys(gnutls_session_t session, hs_stage_t stage,
|
|
Packit Service |
4684c1 |
record_parameters_st *params,
|
|
Packit Service |
4684c1 |
unsigned iv_size, unsigned key_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t key_block[MAX_CIPHER_KEY_SIZE];
|
|
Packit Service |
4684c1 |
uint8_t iv_block[MAX_CIPHER_IV_SIZE];
|
|
Packit Service |
4684c1 |
char buf[65];
|
|
Packit Service |
4684c1 |
record_state_st *upd_state;
|
|
Packit Service |
4684c1 |
record_parameters_st *prev = NULL;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* generate new keys for direction needed and copy old from previous epoch */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (stage == STAGE_UPD_OURS) {
|
|
Packit Service |
4684c1 |
upd_state = ¶ms->write;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_get(session, EPOCH_READ_CURRENT, &prev;;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
assert(prev != NULL);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
params->read.sequence_number = prev->read.sequence_number;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
params->read.key_size = prev->read.key_size;
|
|
Packit Service |
4684c1 |
memcpy(params->read.key, prev->read.key, prev->read.key_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: READ KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
params->read.key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(params->read.key, params->read.key_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
params->read.iv_size = prev->read.iv_size;
|
|
Packit Service |
4684c1 |
memcpy(params->read.iv, prev->read.iv, prev->read.key_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: READ IV [%d]: %s\n",
|
|
Packit Service |
4684c1 |
params->read.iv_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(params->read.iv, params->read.iv_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
upd_state = ¶ms->read;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_get(session, EPOCH_WRITE_CURRENT, &prev;;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
assert(prev != NULL);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
params->write.sequence_number = prev->write.sequence_number;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
params->write.key_size = prev->write.key_size;
|
|
Packit Service |
4684c1 |
memcpy(params->write.key, prev->write.key, prev->write.key_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: WRITE KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
params->write.key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(params->write.key, params->write.key_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
params->write.iv_size = prev->write.iv_size;
|
|
Packit Service |
4684c1 |
memcpy(params->write.iv, prev->write.iv, prev->write.iv_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: WRITE IV [%d]: %s\n",
|
|
Packit Service |
4684c1 |
params->write.iv_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(params->write.iv, params->write.iv_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((session->security_parameters.entity == GNUTLS_CLIENT && stage == STAGE_UPD_OURS) ||
|
|
Packit Service |
4684c1 |
(session->security_parameters.entity == GNUTLS_SERVER && stage == STAGE_UPD_PEERS)) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* client keys */
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, APPLICATION_TRAFFIC_UPDATE,
|
|
Packit Service |
4684c1 |
sizeof(APPLICATION_TRAFFIC_UPDATE)-1,
|
|
Packit Service |
4684c1 |
NULL, 0,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_ckey,
|
|
Packit Service |
4684c1 |
session->security_parameters.prf->output_size,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_ckey);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "key", 3, NULL, 0, session->key.proto.tls13.ap_ckey, key_size, key_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, session->key.proto.tls13.ap_ckey, iv_size, iv_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, APPLICATION_TRAFFIC_UPDATE,
|
|
Packit Service |
4684c1 |
sizeof(APPLICATION_TRAFFIC_UPDATE)-1,
|
|
Packit Service |
4684c1 |
NULL, 0,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_skey,
|
|
Packit Service |
4684c1 |
session->security_parameters.prf->output_size,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.ap_skey);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "key", 3, NULL, 0, session->key.proto.tls13.ap_skey, key_size, key_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, session->key.proto.tls13.ap_skey, iv_size, iv_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
upd_state->mac_key_size = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(key_size <= sizeof(upd_state->key));
|
|
Packit Service |
4684c1 |
memcpy(upd_state->key, key_block, key_size);
|
|
Packit Service |
4684c1 |
upd_state->key_size = key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: NEW %s KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
(upd_state == ¶ms->read)?"READ":"WRITE",
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(key_block, key_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (iv_size > 0) {
|
|
Packit Service |
4684c1 |
assert(iv_size <= sizeof(upd_state->iv));
|
|
Packit Service |
4684c1 |
memcpy(upd_state->iv, iv_block, iv_size);
|
|
Packit Service |
4684c1 |
upd_state->iv_size = iv_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: NEW %s IV [%d]: %s\n",
|
|
Packit Service |
4684c1 |
(upd_state == ¶ms->read)?"READ":"WRITE",
|
|
Packit Service |
4684c1 |
iv_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(iv_block, iv_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_tls13_set_early_keys(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
record_parameters_st * params,
|
|
Packit Service |
4684c1 |
unsigned iv_size, unsigned key_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t key_block[MAX_CIPHER_KEY_SIZE];
|
|
Packit Service |
4684c1 |
uint8_t iv_block[MAX_CIPHER_IV_SIZE];
|
|
Packit Service |
4684c1 |
char buf[65];
|
|
Packit Service |
4684c1 |
record_state_st *early_state;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_CLIENT &&
|
|
Packit Service |
4684c1 |
!(session->internals.hsk_flags & HSK_TLS13_TICKET_SENT)) {
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "key", 3, NULL, 0, session->key.proto.tls13.e_ckey, key_size, key_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, session->key.proto.tls13.e_ckey, iv_size, iv_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
early_state = ¶ms->write;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
early_state = ¶ms->read;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
early_state->mac_key_size = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(key_size <= sizeof(early_state->key));
|
|
Packit Service |
4684c1 |
memcpy(early_state->key, key_block, key_size);
|
|
Packit Service |
4684c1 |
early_state->key_size = key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: EARLY KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(key_block, key_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (iv_size > 0) {
|
|
Packit Service |
4684c1 |
assert(iv_size <= sizeof(early_state->iv));
|
|
Packit Service |
4684c1 |
memcpy(early_state->iv, iv_block, iv_size);
|
|
Packit Service |
4684c1 |
early_state->iv_size = iv_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: EARLY IV [%d]: %s\n",
|
|
Packit Service |
4684c1 |
iv_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(iv_block, iv_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_tls13_set_keys(gnutls_session_t session, hs_stage_t stage,
|
|
Packit Service |
4684c1 |
record_parameters_st * params,
|
|
Packit Service |
4684c1 |
unsigned iv_size, unsigned key_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t ckey_block[MAX_CIPHER_KEY_SIZE];
|
|
Packit Service |
4684c1 |
uint8_t civ_block[MAX_CIPHER_IV_SIZE];
|
|
Packit Service |
4684c1 |
uint8_t skey_block[MAX_CIPHER_KEY_SIZE];
|
|
Packit Service |
4684c1 |
uint8_t siv_block[MAX_CIPHER_IV_SIZE];
|
|
Packit Service |
4684c1 |
char buf[65];
|
|
Packit Service |
4684c1 |
record_state_st *client_write, *server_write;
|
|
Packit Service |
4684c1 |
const char *label;
|
|
Packit Service |
4684c1 |
unsigned label_size, hsk_len;
|
|
Packit Service |
4684c1 |
const char *keylog_label;
|
|
Packit Service |
4684c1 |
void *ckey, *skey;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (stage == STAGE_UPD_OURS || stage == STAGE_UPD_PEERS)
|
|
Packit Service |
4684c1 |
return _tls13_update_keys(session, stage,
|
|
Packit Service |
4684c1 |
params, iv_size, key_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
else if (stage == STAGE_EARLY)
|
|
Packit Service |
4684c1 |
return _tls13_set_early_keys(session,
|
|
Packit Service |
4684c1 |
params, iv_size, key_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
else if (stage == STAGE_HS) {
|
|
Packit Service |
4684c1 |
label = HANDSHAKE_CLIENT_TRAFFIC_LABEL;
|
|
Packit Service |
4684c1 |
label_size = sizeof(HANDSHAKE_CLIENT_TRAFFIC_LABEL)-1;
|
|
Packit Service |
4684c1 |
hsk_len = session->internals.handshake_hash_buffer.length;
|
|
Packit Service |
4684c1 |
keylog_label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
|
|
Packit Service |
4684c1 |
ckey = session->key.proto.tls13.hs_ckey;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
label = APPLICATION_CLIENT_TRAFFIC_LABEL;
|
|
Packit Service |
4684c1 |
label_size = sizeof(APPLICATION_CLIENT_TRAFFIC_LABEL)-1;
|
|
Packit Service |
4684c1 |
hsk_len = session->internals.handshake_hash_buffer_server_finished_len;
|
|
Packit Service |
4684c1 |
keylog_label = "CLIENT_TRAFFIC_SECRET_0";
|
|
Packit Service |
4684c1 |
ckey = session->key.proto.tls13.ap_ckey;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_derive_secret(session, label, label_size,
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer.data,
|
|
Packit Service |
4684c1 |
hsk_len,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.temp_secret,
|
|
Packit Service |
4684c1 |
ckey);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_call_keylog_func(session, keylog_label,
|
|
Packit Service |
4684c1 |
ckey,
|
|
Packit Service |
4684c1 |
session->security_parameters.prf->output_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* client keys */
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "key", 3, NULL, 0, ckey, key_size, ckey_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, ckey, iv_size, civ_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* server keys */
|
|
Packit Service |
4684c1 |
if (stage == STAGE_HS) {
|
|
Packit Service |
4684c1 |
label = HANDSHAKE_SERVER_TRAFFIC_LABEL;
|
|
Packit Service |
4684c1 |
label_size = sizeof(HANDSHAKE_SERVER_TRAFFIC_LABEL)-1;
|
|
Packit Service |
4684c1 |
keylog_label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
|
|
Packit Service |
4684c1 |
skey = session->key.proto.tls13.hs_skey;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
label = APPLICATION_SERVER_TRAFFIC_LABEL;
|
|
Packit Service |
4684c1 |
label_size = sizeof(APPLICATION_SERVER_TRAFFIC_LABEL)-1;
|
|
Packit Service |
4684c1 |
keylog_label = "SERVER_TRAFFIC_SECRET_0";
|
|
Packit Service |
4684c1 |
skey = session->key.proto.tls13.ap_skey;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_derive_secret(session, label, label_size,
|
|
Packit Service |
4684c1 |
session->internals.handshake_hash_buffer.data,
|
|
Packit Service |
4684c1 |
hsk_len,
|
|
Packit Service |
4684c1 |
session->key.proto.tls13.temp_secret,
|
|
Packit Service |
4684c1 |
skey);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_call_keylog_func(session, keylog_label,
|
|
Packit Service |
4684c1 |
skey,
|
|
Packit Service |
4684c1 |
session->security_parameters.prf->output_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "key", 3, NULL, 0, skey, key_size, skey_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, skey, iv_size, siv_block);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
client_write = ¶ms->write;
|
|
Packit Service |
4684c1 |
server_write = ¶ms->read;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
client_write = ¶ms->read;
|
|
Packit Service |
4684c1 |
server_write = ¶ms->write;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
client_write->mac_key_size = 0;
|
|
Packit Service |
4684c1 |
server_write->mac_key_size = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(key_size <= sizeof(client_write->key));
|
|
Packit Service |
4684c1 |
memcpy(client_write->key, ckey_block, key_size);
|
|
Packit Service |
4684c1 |
client_write->key_size = key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: CLIENT WRITE KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(ckey_block, key_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy(server_write->key, skey_block, key_size);
|
|
Packit Service |
4684c1 |
server_write->key_size = key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: SERVER WRITE KEY [%d]: %s\n",
|
|
Packit Service |
4684c1 |
key_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(skey_block, key_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (iv_size > 0) {
|
|
Packit Service |
4684c1 |
assert(iv_size <= sizeof(client_write->iv));
|
|
Packit Service |
4684c1 |
memcpy(client_write->iv, civ_block, iv_size);
|
|
Packit Service |
4684c1 |
client_write->iv_size = iv_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: CLIENT WRITE IV [%d]: %s\n",
|
|
Packit Service |
4684c1 |
iv_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(civ_block, iv_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy(server_write->iv, siv_block, iv_size);
|
|
Packit Service |
4684c1 |
server_write->iv_size = iv_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hard_log("INT: SERVER WRITE IV [%d]: %s\n",
|
|
Packit Service |
4684c1 |
iv_size,
|
|
Packit Service |
4684c1 |
_gnutls_bin2hex(siv_block, iv_size,
|
|
Packit Service |
4684c1 |
buf, sizeof(buf), NULL));
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_gnutls_init_record_state(record_parameters_st * params,
|
|
Packit Service |
4684c1 |
const version_entry_st * ver, int read,
|
|
Packit Service |
4684c1 |
record_state_st * state)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t *iv = NULL, _iv;
|
|
Packit Service |
4684c1 |
gnutls_datum_t key;
|
|
Packit Service |
4684c1 |
gnutls_datum_t mac;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_iv.data = state->iv;
|
|
Packit Service |
4684c1 |
_iv.size = state->iv_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
key.data = state->key;
|
|
Packit Service |
4684c1 |
key.size = state->key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mac.data = state->mac_key;
|
|
Packit Service |
4684c1 |
mac.size = state->mac_key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (_gnutls_cipher_type(params->cipher) == CIPHER_BLOCK) {
|
|
Packit Service |
4684c1 |
if (!_gnutls_version_has_explicit_iv(ver))
|
|
Packit Service |
4684c1 |
iv = &_iv;
|
|
Packit Service |
4684c1 |
} else if (_gnutls_cipher_type(params->cipher) == CIPHER_STREAM) {
|
|
Packit Service |
4684c1 |
/* To handle GOST ciphersuites */
|
|
Packit Service |
4684c1 |
if (_gnutls_cipher_get_implicit_iv_size(params->cipher))
|
|
Packit Service |
4684c1 |
iv = &_iv;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_auth_cipher_init(&state->ctx.tls12,
|
|
Packit Service |
4684c1 |
params->cipher, &key, iv,
|
|
Packit Service |
4684c1 |
params->mac, &mac,
|
|
Packit Service |
4684c1 |
params->etm,
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_SSL3
|
|
Packit Service |
4684c1 |
(ver->id == GNUTLS_SSL3) ? 1 : 0,
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
1 - read /*1==encrypt */ );
|
|
Packit Service |
4684c1 |
if (ret < 0 && params->cipher->id != GNUTLS_CIPHER_NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_set_cipher_suite2(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
const gnutls_cipher_suite_entry_st *cs)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const cipher_entry_st *cipher_algo;
|
|
Packit Service |
4684c1 |
const mac_entry_st *mac_algo;
|
|
Packit Service |
4684c1 |
record_parameters_st *params;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
const version_entry_st *ver = get_version(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_get(session, EPOCH_NEXT, ¶ms);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cipher_algo = cipher_to_entry(cs->block_algorithm);
|
|
Packit Service |
4684c1 |
mac_algo = mac_to_entry(cs->mac_algorithm);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ver->tls13_sem && (session->internals.hsk_flags & HSK_HRR_SENT)) {
|
|
Packit Service |
4684c1 |
if (params->initialized && (params->cipher != cipher_algo ||
|
|
Packit Service |
4684c1 |
params->mac != mac_algo || cs != session->security_parameters.cs))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
if (params->initialized
|
|
Packit Service |
4684c1 |
|| params->cipher != NULL || params->mac != NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (_gnutls_cipher_is_ok(cipher_algo) == 0
|
|
Packit Service |
4684c1 |
|| _gnutls_mac_is_ok(mac_algo) == 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (_gnutls_version_has_selectable_prf(get_version(session))) {
|
|
Packit Service |
4684c1 |
if (cs->prf == GNUTLS_MAC_UNKNOWN ||
|
|
Packit Service |
4684c1 |
_gnutls_mac_is_ok(mac_to_entry(cs->prf)) == 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
|
|
Packit Service |
4684c1 |
session->security_parameters.prf = mac_to_entry(cs->prf);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
session->security_parameters.prf = mac_to_entry(GNUTLS_MAC_MD5_SHA1);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->security_parameters.cs = cs;
|
|
Packit Service |
4684c1 |
params->cipher = cipher_algo;
|
|
Packit Service |
4684c1 |
params->mac = mac_algo;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Sets the next epoch to be a clone of the current one.
|
|
Packit Service |
4684c1 |
* The keys are not cloned, only the cipher and MAC.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls_epoch_dup(gnutls_session_t session, unsigned int epoch_rel)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
record_parameters_st *prev;
|
|
Packit Service |
4684c1 |
record_parameters_st *next;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_get(session, epoch_rel, &prev;;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_get(session, EPOCH_NEXT, &next;;
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_setup_next(session, 0, &next;;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (next->initialized
|
|
Packit Service |
4684c1 |
|| next->cipher != NULL || next->mac != NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
next->cipher = prev->cipher;
|
|
Packit Service |
4684c1 |
next->mac = prev->mac;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch, hs_stage_t stage)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int hash_size;
|
|
Packit Service |
4684c1 |
int IV_size;
|
|
Packit Service |
4684c1 |
int key_size;
|
|
Packit Service |
4684c1 |
record_parameters_st *params;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
const version_entry_st *ver = get_version(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(ver == NULL))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_get(session, epoch, ¶ms);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (params->initialized)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_record_log
|
|
Packit Service |
4684c1 |
("REC[%p]: Initializing epoch #%u\n", session, params->epoch);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (_gnutls_cipher_is_ok(params->cipher) == 0 ||
|
|
Packit Service |
4684c1 |
_gnutls_mac_is_ok(params->mac) == 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (_gnutls_version_has_explicit_iv(ver) &&
|
|
Packit Service |
4684c1 |
(_gnutls_cipher_type(params->cipher) != CIPHER_BLOCK)) {
|
|
Packit Service |
4684c1 |
IV_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
IV_size = _gnutls_cipher_get_iv_size(params->cipher);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
key_size = _gnutls_cipher_get_key_size(params->cipher);
|
|
Packit Service |
4684c1 |
hash_size = _gnutls_mac_get_key_size(params->mac);
|
|
Packit Service |
4684c1 |
params->etm = session->security_parameters.etm;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ver->tls13_sem) {
|
|
Packit Service |
4684c1 |
ret = _tls13_set_keys
|
|
Packit Service |
4684c1 |
(session, stage, params, IV_size, key_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (stage != STAGE_EARLY ||
|
|
Packit Service |
4684c1 |
session->security_parameters.entity == GNUTLS_SERVER) {
|
|
Packit Service |
4684c1 |
ret = _tls13_init_record_state(params->cipher->id, ¶ms->read);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (stage != STAGE_EARLY ||
|
|
Packit Service |
4684c1 |
session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
ret = _tls13_init_record_state(params->cipher->id, ¶ms->write);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
ret = _gnutls_set_keys
|
|
Packit Service |
4684c1 |
(session, params, hash_size, IV_size, key_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_init_record_state(params, ver, 1, ¶ms->read);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_init_record_state(params, ver, 0, ¶ms->write);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* The TLS1.3 limit of 256 additional bytes is also enforced under CBC
|
|
Packit Service |
4684c1 |
* ciphers to ensure we interoperate with gnutls 2.12.x which could add padding
|
|
Packit Service |
4684c1 |
* data exceeding the maximum. */
|
|
Packit Service |
4684c1 |
if (ver->tls13_sem || _gnutls_cipher_type(params->cipher) == CIPHER_BLOCK) {
|
|
Packit Service |
4684c1 |
session->internals.max_recv_size = 256;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
session->internals.max_recv_size = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!ver->tls13_sem) {
|
|
Packit Service |
4684c1 |
session->internals.max_recv_size += _gnutls_record_overhead(ver, params->cipher, params->mac, 1);
|
|
Packit Service |
4684c1 |
if (session->internals.allow_large_records != 0)
|
|
Packit Service |
4684c1 |
session->internals.max_recv_size += EXTRA_COMP_SIZE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.max_recv_size += session->security_parameters.max_record_recv_size + RECORD_HEADER_SIZE(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_dtls_reset_window(params);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_record_log("REC[%p]: Epoch #%u ready\n", session,
|
|
Packit Service |
4684c1 |
params->epoch);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
params->initialized = 1;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* This copies the session values which apply to subsequent/resumed
|
|
Packit Service |
4684c1 |
* sessions. Under TLS 1.3, these values are items which are not
|
|
Packit Service |
4684c1 |
* negotiated on the subsequent session. */
|
|
Packit Service |
4684c1 |
#define CPY_COMMON(tls13_sem) \
|
|
Packit Service |
4684c1 |
if (!tls13_sem) { \
|
|
Packit Service |
4684c1 |
dst->cs = src->cs; \
|
|
Packit Service |
4684c1 |
memcpy(dst->master_secret, src->master_secret, GNUTLS_MASTER_SIZE); \
|
|
Packit Service |
4684c1 |
memcpy(dst->client_random, src->client_random, GNUTLS_RANDOM_SIZE); \
|
|
Packit Service |
4684c1 |
memcpy(dst->server_random, src->server_random, GNUTLS_RANDOM_SIZE); \
|
|
Packit Service |
4684c1 |
dst->ext_master_secret = src->ext_master_secret; \
|
|
Packit Service |
4684c1 |
dst->etm = src->etm; \
|
|
Packit Service |
4684c1 |
dst->prf = src->prf; \
|
|
Packit Service |
4684c1 |
dst->grp = src->grp; \
|
|
Packit Service |
4684c1 |
dst->pversion = src->pversion; \
|
|
Packit Service |
4684c1 |
} \
|
|
Packit Service |
4684c1 |
memcpy(dst->session_id, src->session_id, GNUTLS_MAX_SESSION_ID_SIZE); \
|
|
Packit Service |
4684c1 |
dst->session_id_size = src->session_id_size; \
|
|
Packit Service |
4684c1 |
dst->timestamp = src->timestamp; \
|
|
Packit Service |
4684c1 |
dst->client_ctype = src->client_ctype; \
|
|
Packit Service |
4684c1 |
dst->server_ctype = src->server_ctype; \
|
|
Packit Service |
4684c1 |
dst->client_auth_type = src->client_auth_type; \
|
|
Packit Service |
4684c1 |
dst->server_auth_type = src->server_auth_type
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void _gnutls_set_resumed_parameters(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
security_parameters_st *src =
|
|
Packit Service |
4684c1 |
&session->internals.resumed_security_parameters;
|
|
Packit Service |
4684c1 |
security_parameters_st *dst = &session->security_parameters;
|
|
Packit Service |
4684c1 |
const version_entry_st *ver = get_version(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
CPY_COMMON(ver->tls13_sem);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!ver->tls13_sem &&
|
|
Packit Service |
4684c1 |
!(session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED)) {
|
|
Packit Service |
4684c1 |
dst->max_record_recv_size = src->max_record_recv_size;
|
|
Packit Service |
4684c1 |
dst->max_record_send_size = src->max_record_send_size;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Sets the current connection session to conform with the
|
|
Packit Service |
4684c1 |
* Security parameters(pending session), and initializes encryption.
|
|
Packit Service |
4684c1 |
* Actually it initializes and starts encryption ( so it needs
|
|
Packit Service |
4684c1 |
* secrets and random numbers to have been negotiated)
|
|
Packit Service |
4684c1 |
* This is to be called after sending the Change Cipher Spec packet.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls_connection_state_init(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Setup the master secret
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if ((ret = _gnutls_generate_master(session, 0)) < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Initializes the read connection session
|
|
Packit Service |
4684c1 |
* (read encrypted data)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls_read_connection_state_init(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const uint16_t epoch_next =
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_next;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Update internals from CipherSuite selected.
|
|
Packit Service |
4684c1 |
* If we are resuming just copy the connection session
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (session->internals.resumed != RESUME_FALSE &&
|
|
Packit Service |
4684c1 |
session->security_parameters.entity == GNUTLS_CLIENT)
|
|
Packit Service |
4684c1 |
_gnutls_set_resumed_parameters(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_set_keys(session, epoch_next, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("HSK[%p]: Cipher Suite: %s\n",
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
session->security_parameters.cs->name);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_read = epoch_next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Initializes the write connection session
|
|
Packit Service |
4684c1 |
* (write encrypted data)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int _gnutls_write_connection_state_init(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const uint16_t epoch_next =
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_next;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* reset max_record_send_size if it was negotiated in the
|
|
Packit Service |
4684c1 |
* previous handshake using the record_size_limit extension */
|
|
Packit Service |
4684c1 |
if (!(session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED) &&
|
|
Packit Service |
4684c1 |
session->security_parameters.entity == GNUTLS_SERVER)
|
|
Packit Service |
4684c1 |
session->security_parameters.max_record_send_size =
|
|
Packit Service |
4684c1 |
session->security_parameters.max_user_record_send_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Update internals from CipherSuite selected.
|
|
Packit Service |
4684c1 |
* If we are resuming just copy the connection session
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if (session->internals.resumed != RESUME_FALSE &&
|
|
Packit Service |
4684c1 |
session->security_parameters.entity == GNUTLS_SERVER)
|
|
Packit Service |
4684c1 |
_gnutls_set_resumed_parameters(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_set_keys(session, epoch_next, 0);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("HSK[%p]: Cipher Suite: %s\n", session,
|
|
Packit Service |
4684c1 |
session->security_parameters.cs->name);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("HSK[%p]: Initializing internal [write] cipher sessions\n",
|
|
Packit Service |
4684c1 |
session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_write = epoch_next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static inline int
|
|
Packit Service |
4684c1 |
epoch_resolve(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
unsigned int epoch_rel, uint16_t * epoch_out)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
switch (epoch_rel) {
|
|
Packit Service |
4684c1 |
case EPOCH_READ_CURRENT:
|
|
Packit Service |
4684c1 |
*epoch_out = session->security_parameters.epoch_read;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
case EPOCH_WRITE_CURRENT:
|
|
Packit Service |
4684c1 |
*epoch_out = session->security_parameters.epoch_write;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
case EPOCH_NEXT:
|
|
Packit Service |
4684c1 |
*epoch_out = session->security_parameters.epoch_next;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
default:
|
|
Packit Service |
4684c1 |
if (epoch_rel > 0xffffu)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*epoch_out = epoch_rel;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static inline record_parameters_st **epoch_get_slot(gnutls_session_t
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
uint16_t epoch)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint16_t epoch_index =
|
|
Packit Service |
4684c1 |
epoch - session->security_parameters.epoch_min;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (epoch_index >= MAX_EPOCH_INDEX) {
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("Epoch %d out of range (idx: %d, max: %d)\n",
|
|
Packit Service |
4684c1 |
(int) epoch, (int) epoch_index, MAX_EPOCH_INDEX);
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
/* The slot may still be empty (NULL) */
|
|
Packit Service |
4684c1 |
return &session->record_parameters[epoch_index];
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_epoch_get(gnutls_session_t session, unsigned int epoch_rel,
|
|
Packit Service |
4684c1 |
record_parameters_st ** params_out)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint16_t epoch;
|
|
Packit Service |
4684c1 |
record_parameters_st **params;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_mutex_lock(&session->internals.epoch_lock);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = epoch_resolve(session, epoch_rel, &epoch);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
params = epoch_get_slot(session, epoch);
|
|
Packit Service |
4684c1 |
if (params == NULL || *params == NULL) {
|
|
Packit Service |
4684c1 |
ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
goto cleanup;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (params_out)
|
|
Packit Service |
4684c1 |
*params_out = *params;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cleanup:
|
|
Packit Service |
4684c1 |
gnutls_mutex_unlock(&session->internals.epoch_lock);
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Ensures that the next epoch is setup. When an epoch will null ciphers
|
|
Packit Service |
4684c1 |
* is to be setup, call with @null_epoch set to true. In that case
|
|
Packit Service |
4684c1 |
* the epoch is fully initialized after call.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_epoch_setup_next(gnutls_session_t session, unsigned null_epoch, record_parameters_st **newp)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
record_parameters_st **slot;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
slot = epoch_get_slot(session, session->security_parameters.epoch_next);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* If slot out of range or not empty. */
|
|
Packit Service |
4684c1 |
if (slot == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (*slot != NULL) { /* already initialized */
|
|
Packit Service |
4684c1 |
if (unlikely(null_epoch && !(*slot)->initialized))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely((*slot)->epoch != session->security_parameters.epoch_next))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
goto finish;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_record_log("REC[%p]: Allocating epoch #%u\n", session,
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_next);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
*slot = gnutls_calloc(1, sizeof(record_parameters_st));
|
|
Packit Service |
4684c1 |
if (*slot == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
(*slot)->epoch = session->security_parameters.epoch_next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (null_epoch) {
|
|
Packit Service |
4684c1 |
(*slot)->cipher = cipher_to_entry(GNUTLS_CIPHER_NULL);
|
|
Packit Service |
4684c1 |
(*slot)->mac = mac_to_entry(GNUTLS_MAC_NULL);
|
|
Packit Service |
4684c1 |
(*slot)->initialized = 1;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
(*slot)->cipher = NULL;
|
|
Packit Service |
4684c1 |
(*slot)->mac = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (IS_DTLS(session)) {
|
|
Packit Service |
4684c1 |
uint64_t seq = (*slot)->write.sequence_number;
|
|
Packit Service |
4684c1 |
seq &= UINT64_C(0xffffffffffff);
|
|
Packit Service |
4684c1 |
seq |= ((uint64_t)session->security_parameters.epoch_next) << 48;
|
|
Packit Service |
4684c1 |
(*slot)->write.sequence_number = seq;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
finish:
|
|
Packit Service |
4684c1 |
if (newp != NULL)
|
|
Packit Service |
4684c1 |
*newp = *slot;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static inline int
|
|
Packit Service |
4684c1 |
epoch_is_active(gnutls_session_t session, record_parameters_st * params)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const security_parameters_st *sp = &session->security_parameters;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (params->epoch == sp->epoch_read)
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (params->epoch == sp->epoch_write)
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (params->epoch == sp->epoch_next)
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static inline int
|
|
Packit Service |
4684c1 |
epoch_alive(gnutls_session_t session, record_parameters_st * params)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (params->usage_cnt > 0)
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return epoch_is_active(session, params);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void _gnutls_epoch_gc(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int i, j;
|
|
Packit Service |
4684c1 |
unsigned int min_index = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_record_log("REC[%p]: Start of epoch cleanup\n", session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_mutex_lock(&session->internals.epoch_lock);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Free all dead cipher state */
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_EPOCH_INDEX; i++) {
|
|
Packit Service |
4684c1 |
if (session->record_parameters[i] != NULL) {
|
|
Packit Service |
4684c1 |
if (!epoch_is_active
|
|
Packit Service |
4684c1 |
(session, session->record_parameters[i])
|
|
Packit Service |
4684c1 |
&& session->record_parameters[i]->usage_cnt)
|
|
Packit Service |
4684c1 |
_gnutls_record_log
|
|
Packit Service |
4684c1 |
("REC[%p]: Note inactive epoch %d has %d users\n",
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
session->record_parameters[i]->epoch,
|
|
Packit Service |
4684c1 |
session->record_parameters[i]->
|
|
Packit Service |
4684c1 |
usage_cnt);
|
|
Packit Service |
4684c1 |
if (!epoch_alive
|
|
Packit Service |
4684c1 |
(session, session->record_parameters[i])) {
|
|
Packit Service |
4684c1 |
_gnutls_epoch_free(session,
|
|
Packit Service |
4684c1 |
session->
|
|
Packit Service |
4684c1 |
record_parameters[i]);
|
|
Packit Service |
4684c1 |
session->record_parameters[i] = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Look for contiguous NULLs at the start of the array */
|
|
Packit Service |
4684c1 |
for (i = 0;
|
|
Packit Service |
4684c1 |
i < MAX_EPOCH_INDEX && session->record_parameters[i] == NULL;
|
|
Packit Service |
4684c1 |
i++);
|
|
Packit Service |
4684c1 |
min_index = i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Pick up the slack in the epoch window. */
|
|
Packit Service |
4684c1 |
if (min_index != 0) {
|
|
Packit Service |
4684c1 |
for (i = 0, j = min_index; j < MAX_EPOCH_INDEX; i++, j++) {
|
|
Packit Service |
4684c1 |
session->record_parameters[i] =
|
|
Packit Service |
4684c1 |
session->record_parameters[j];
|
|
Packit Service |
4684c1 |
session->record_parameters[j] = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Set the new epoch_min */
|
|
Packit Service |
4684c1 |
if (session->record_parameters[0] != NULL)
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_min =
|
|
Packit Service |
4684c1 |
session->record_parameters[0]->epoch;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_mutex_unlock(&session->internals.epoch_lock);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_record_log("REC[%p]: End of epoch cleanup\n", session);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static inline void free_record_state(record_state_st * state)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
zeroize_temp_key(state->mac_key, state->mac_key_size);
|
|
Packit Service |
4684c1 |
zeroize_temp_key(state->iv, state->iv_size);
|
|
Packit Service |
4684c1 |
zeroize_temp_key(state->key, state->key_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (state->is_aead)
|
|
Packit Service |
4684c1 |
_gnutls_aead_cipher_deinit(&state->ctx.aead);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
_gnutls_auth_cipher_deinit(&state->ctx.tls12);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
_gnutls_epoch_free(gnutls_session_t session, record_parameters_st * params)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
_gnutls_record_log("REC[%p]: Epoch #%u freed\n", session,
|
|
Packit Service |
4684c1 |
params->epoch);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
free_record_state(¶ms->read);
|
|
Packit Service |
4684c1 |
free_record_state(¶ms->write);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(params);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _tls13_connection_state_init(gnutls_session_t session, hs_stage_t stage)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const uint16_t epoch_next =
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_next;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_set_keys(session, epoch_next, stage);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("HSK[%p]: TLS 1.3 re-key with cipher suite: %s\n",
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
session->security_parameters.cs->name);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_read = epoch_next;
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_write = epoch_next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _tls13_read_connection_state_init(gnutls_session_t session, hs_stage_t stage)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const uint16_t epoch_next =
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_next;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_set_keys(session, epoch_next, stage);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("HSK[%p]: TLS 1.3 set read key with cipher suite: %s\n",
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
session->security_parameters.cs->name);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_read = epoch_next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _tls13_write_connection_state_init(gnutls_session_t session, hs_stage_t stage)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const uint16_t epoch_next =
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_next;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_epoch_set_keys(session, epoch_next, stage);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("HSK[%p]: TLS 1.3 set write key with cipher suite: %s\n",
|
|
Packit Service |
4684c1 |
session,
|
|
Packit Service |
4684c1 |
session->security_parameters.cs->name);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->security_parameters.epoch_write = epoch_next;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_tls13_init_record_state(gnutls_cipher_algorithm_t algo, record_state_st *state)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t key;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
key.data = state->key;
|
|
Packit Service |
4684c1 |
key.size = state->key_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_aead_cipher_init(&state->ctx.aead,
|
|
Packit Service |
4684c1 |
algo, &key);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
state->aead_tag_size = gnutls_cipher_get_tag_size(algo);
|
|
Packit Service |
4684c1 |
state->is_aead = 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|