-# $OpenBSD: Makefile,v 1.69 2021/04/25 13:15:22 jsing Exp $
+# $OpenBSD: Makefile,v 1.70 2021/05/05 10:05:27 jsing Exp $
.include <bsd.own.mk>
.ifndef NOMAN
ssl_versions.c \
t1_enc.c \
t1_lib.c \
+ tls12_key_schedule.c \
tls12_lib.c \
tls12_record_layer.c \
tls13_buffer.c \
-/* $OpenBSD: ssl_locl.h,v 1.341 2021/05/02 17:46:58 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.342 2021/05/05 10:05:27 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
int cert_request;
STACK_OF(X509_NAME) *ca_names;
- /* Size of the MAC secret. */
- int mac_secret_size;
-
/* Record-layer key block for TLS 1.2 and earlier. */
- unsigned char *key_block;
- size_t key_block_len;
+ struct tls12_key_block *key_block;
/* Transcript hash prior to sending certificate verify message. */
uint8_t cert_verify[EVP_MAX_MD_SIZE];
SSL_HANDSHAKE_TLS13 tls13;
} SSL_HANDSHAKE;
+struct tls12_key_block;
+
+struct tls12_key_block *tls12_key_block_new(void);
+void tls12_key_block_free(struct tls12_key_block *kb);
+void tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key,
+ CBS *key, CBS *iv);
+void tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key,
+ CBS *key, CBS *iv);
+int tls12_key_block_generate(struct tls12_key_block *kb, SSL *s,
+ const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash);
+
struct tls12_record_layer;
struct tls12_record_layer *tls12_record_layer_new(void);
size_t *overhead);
int tls12_record_layer_read_protected(struct tls12_record_layer *rl);
int tls12_record_layer_write_protected(struct tls12_record_layer *rl);
-const EVP_AEAD *tls12_record_layer_aead(struct tls12_record_layer *rl);
-const EVP_CIPHER *tls12_record_layer_cipher(struct tls12_record_layer *rl);
void tls12_record_layer_set_aead(struct tls12_record_layer *rl,
const EVP_AEAD *aead);
void tls12_record_layer_set_cipher_hash(struct tls12_record_layer *rl,
void tls12_record_layer_read_cipher_hash(struct tls12_record_layer *rl,
EVP_CIPHER_CTX **cipher, EVP_MD_CTX **hash);
int tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl,
- const uint8_t *mac_key, size_t mac_key_len, const uint8_t *key,
- size_t key_len, const uint8_t *iv, size_t iv_len);
+ CBS *mac_key, CBS *key, CBS *iv);
int tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl,
- const uint8_t *mac_key, size_t mac_key_len, const uint8_t *key,
- size_t key_len, const uint8_t *iv, size_t iv_len);
+ CBS *mac_key, CBS *key, CBS *iv);
int tls12_record_layer_open_record(struct tls12_record_layer *rl,
uint8_t *buf, size_t buf_len, uint8_t **out, size_t *out_len);
int tls12_record_layer_seal_record(struct tls12_record_layer *rl,
int tls1_change_read_cipher_state(SSL *s);
int tls1_change_write_cipher_state(SSL *s);
int tls1_setup_key_block(SSL *s);
+int tls1_generate_key_block(SSL *s, uint8_t *key_block, size_t key_block_len);
int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen, const unsigned char *p, size_t plen,
int use_context);
-/* $OpenBSD: t1_enc.c,v 1.142 2021/05/02 17:46:58 jsing Exp $ */
+/* $OpenBSD: t1_enc.c,v 1.143 2021/05/05 10:05:27 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
void
tls1_cleanup_key_block(SSL *s)
{
- freezero(S3I(s)->hs.tls12.key_block, S3I(s)->hs.tls12.key_block_len);
+ tls12_key_block_free(S3I(s)->hs.tls12.key_block);
S3I(s)->hs.tls12.key_block = NULL;
- S3I(s)->hs.tls12.key_block_len = 0;
}
/*
return (1);
}
-static int
+int
tls1_generate_key_block(SSL *s, uint8_t *key_block, size_t key_block_len)
{
return tls1_PRF(s,
static int
tls1_change_cipher_state(SSL *s, int is_write)
{
- const unsigned char *client_write_mac_secret, *server_write_mac_secret;
- const unsigned char *client_write_key, *server_write_key;
- const unsigned char *client_write_iv, *server_write_iv;
- const unsigned char *mac_secret, *key, *iv;
- int mac_secret_size, key_len, iv_len;
- unsigned char *key_block;
- const EVP_CIPHER *cipher;
- const EVP_AEAD *aead;
-
- aead = tls12_record_layer_aead(s->internal->rl);
- cipher = tls12_record_layer_cipher(s->internal->rl);
-
- if (aead != NULL) {
- key_len = EVP_AEAD_key_length(aead);
- iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(S3I(s)->hs.cipher);
- } else {
- key_len = EVP_CIPHER_key_length(cipher);
- iv_len = EVP_CIPHER_iv_length(cipher);
- }
-
- mac_secret_size = S3I(s)->hs.tls12.mac_secret_size;
-
- key_block = S3I(s)->hs.tls12.key_block;
- client_write_mac_secret = key_block;
- key_block += mac_secret_size;
- server_write_mac_secret = key_block;
- key_block += mac_secret_size;
- client_write_key = key_block;
- key_block += key_len;
- server_write_key = key_block;
- key_block += key_len;
- client_write_iv = key_block;
- key_block += iv_len;
- server_write_iv = key_block;
- key_block += iv_len;
+ CBS mac_key, key, iv;
/* Use client write keys on client write and server read. */
if ((!s->server && is_write) || (s->server && !is_write)) {
- mac_secret = client_write_mac_secret;
- key = client_write_key;
- iv = client_write_iv;
+ tls12_key_block_client_write(S3I(s)->hs.tls12.key_block,
+ &mac_key, &key, &iv);
} else {
- mac_secret = server_write_mac_secret;
- key = server_write_key;
- iv = server_write_iv;
- }
-
- if (key_block - S3I(s)->hs.tls12.key_block !=
- S3I(s)->hs.tls12.key_block_len) {
- SSLerror(s, ERR_R_INTERNAL_ERROR);
- goto err;
+ tls12_key_block_server_write(S3I(s)->hs.tls12.key_block,
+ &mac_key, &key, &iv);
}
if (!is_write) {
if (!tls12_record_layer_change_read_cipher_state(s->internal->rl,
- mac_secret, mac_secret_size, key, key_len, iv, iv_len))
+ &mac_key, &key, &iv))
goto err;
if (SSL_is_dtls(s))
dtls1_reset_read_seq_numbers(s);
&s->enc_read_ctx, &s->read_hash);
} else {
if (!tls12_record_layer_change_write_cipher_state(s->internal->rl,
- mac_secret, mac_secret_size, key, key_len, iv, iv_len))
+ &mac_key, &key, &iv))
goto err;
if (SSL_is_dtls(s))
dtls1_reset_write_seq_numbers(s);
int
tls1_setup_key_block(SSL *s)
{
- unsigned char *key_block;
+ struct tls12_key_block *key_block;
int mac_type = NID_undef, mac_secret_size = 0;
- size_t key_block_len;
- int key_len, iv_len;
const EVP_CIPHER *cipher = NULL;
const EVP_AEAD *aead = NULL;
const EVP_MD *handshake_hash = NULL;
const EVP_MD *mac_hash = NULL;
int ret = 0;
- if (S3I(s)->hs.tls12.key_block_len != 0)
+ /*
+ * XXX - callers should be changed so that they only call this
+ * function once.
+ */
+ if (S3I(s)->hs.tls12.key_block != NULL)
return (1);
if (s->session->cipher &&
SSLerror(s, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
return (0);
}
- key_len = EVP_AEAD_key_length(aead);
- iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
} else {
+ /* XXX - mac_type and mac_secret_size are now unused. */
if (!ssl_cipher_get_evp(s->session, &cipher, &mac_hash,
&mac_type, &mac_secret_size)) {
SSLerror(s, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
return (0);
}
- key_len = EVP_CIPHER_key_length(cipher);
- iv_len = EVP_CIPHER_iv_length(cipher);
}
if (!ssl_get_handshake_evp_md(s, &handshake_hash))
return (0);
- S3I(s)->hs.tls12.mac_secret_size = mac_secret_size;
-
tls12_record_layer_set_aead(s->internal->rl, aead);
tls12_record_layer_set_cipher_hash(s->internal->rl, cipher,
handshake_hash, mac_hash);
- tls1_cleanup_key_block(s);
-
- if ((key_block = reallocarray(NULL, mac_secret_size + key_len + iv_len,
- 2)) == NULL) {
- SSLerror(s, ERR_R_MALLOC_FAILURE);
+ if ((key_block = tls12_key_block_new()) == NULL)
+ goto err;
+ if (!tls12_key_block_generate(key_block, s, aead, cipher, mac_hash))
goto err;
- }
- key_block_len = (mac_secret_size + key_len + iv_len) * 2;
- S3I(s)->hs.tls12.key_block_len = key_block_len;
S3I(s)->hs.tls12.key_block = key_block;
-
- if (!tls1_generate_key_block(s, key_block, key_block_len))
- goto err;
+ key_block = NULL;
if (!(s->internal->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) &&
s->method->internal->version <= TLS1_VERSION) {
ret = 1;
err:
+ tls12_key_block_free(key_block);
+
return (ret);
}
--- /dev/null
+/* $OpenBSD: tls12_key_schedule.c,v 1.1 2021/05/05 10:05:27 jsing Exp $ */
+/*
+ * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+
+#include <openssl/evp.h>
+
+#include "bytestring.h"
+#include "ssl_locl.h"
+
+struct tls12_key_block {
+ CBS client_write_mac_key;
+ CBS server_write_mac_key;
+ CBS client_write_key;
+ CBS server_write_key;
+ CBS client_write_iv;
+ CBS server_write_iv;
+
+ uint8_t *key_block;
+ size_t key_block_len;
+};
+
+struct tls12_key_block *
+tls12_key_block_new(void)
+{
+ return calloc(1, sizeof(struct tls12_key_block));
+}
+
+static void
+tls12_key_block_clear(struct tls12_key_block *kb)
+{
+ CBS_init(&kb->client_write_mac_key, NULL, 0);
+ CBS_init(&kb->server_write_mac_key, NULL, 0);
+ CBS_init(&kb->client_write_key, NULL, 0);
+ CBS_init(&kb->server_write_key, NULL, 0);
+ CBS_init(&kb->client_write_iv, NULL, 0);
+ CBS_init(&kb->server_write_iv, NULL, 0);
+
+ freezero(kb->key_block, kb->key_block_len);
+ kb->key_block = NULL;
+ kb->key_block_len = 0;
+}
+
+void
+tls12_key_block_free(struct tls12_key_block *kb)
+{
+ if (kb == NULL)
+ return;
+
+ tls12_key_block_clear(kb);
+
+ freezero(kb, sizeof(struct tls12_key_block));
+}
+
+void
+tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key,
+ CBS *key, CBS *iv)
+{
+ CBS_dup(&kb->client_write_mac_key, mac_key);
+ CBS_dup(&kb->client_write_key, key);
+ CBS_dup(&kb->client_write_iv, iv);
+}
+
+void
+tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key,
+ CBS *key, CBS *iv)
+{
+ CBS_dup(&kb->server_write_mac_key, mac_key);
+ CBS_dup(&kb->server_write_key, key);
+ CBS_dup(&kb->server_write_iv, iv);
+}
+
+int
+tls12_key_block_generate(struct tls12_key_block *kb, SSL *s,
+ const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash)
+{
+ size_t mac_key_len = 0, key_len = 0, iv_len = 0;
+ uint8_t *key_block = NULL;
+ size_t key_block_len = 0;
+ CBS cbs;
+
+ /*
+ * Generate a TLSv1.2 key block and partition into individual secrets,
+ * as per RFC 5246 section 6.3.
+ */
+
+ tls12_key_block_clear(kb);
+
+ /* Must have AEAD or cipher/MAC pair. */
+ if (aead == NULL && (cipher == NULL || mac_hash == NULL))
+ goto err;
+
+ if (aead != NULL) {
+ key_len = EVP_AEAD_key_length(aead);
+
+ /* AEAD fixed nonce length. */
+ if (aead == EVP_aead_aes_128_gcm() ||
+ aead == EVP_aead_aes_256_gcm())
+ iv_len = 4;
+ else if (aead == EVP_aead_chacha20_poly1305())
+ iv_len = 12;
+ else
+ goto err;
+ } else if (cipher != NULL && mac_hash != NULL) {
+ /*
+ * A negative integer return value will be detected via the
+ * EVP_MAX_* checks against the size_t variables below.
+ */
+ mac_key_len = EVP_MD_size(mac_hash);
+ key_len = EVP_CIPHER_key_length(cipher);
+ iv_len = EVP_CIPHER_iv_length(cipher);
+
+ /* Special handling for GOST... */
+ if (EVP_MD_type(mac_hash) == NID_id_Gost28147_89_MAC)
+ mac_key_len = 32;
+ }
+
+ if (mac_key_len > EVP_MAX_MD_SIZE)
+ goto err;
+ if (key_len > EVP_MAX_KEY_LENGTH)
+ goto err;
+ if (iv_len > EVP_MAX_IV_LENGTH)
+ goto err;
+
+ key_block_len = 2 * mac_key_len + 2 * key_len + 2 * iv_len;
+ if ((key_block = calloc(1, key_block_len)) == NULL)
+ goto err;
+
+ if (!tls1_generate_key_block(s, key_block, key_block_len))
+ goto err;
+
+ kb->key_block = key_block;
+ kb->key_block_len = key_block_len;
+ key_block = NULL;
+ key_block_len = 0;
+
+ /* Partition key block into individual secrets. */
+ CBS_init(&cbs, kb->key_block, kb->key_block_len);
+ if (!CBS_get_bytes(&cbs, &kb->client_write_mac_key, mac_key_len))
+ goto err;
+ if (!CBS_get_bytes(&cbs, &kb->server_write_mac_key, mac_key_len))
+ goto err;
+ if (!CBS_get_bytes(&cbs, &kb->client_write_key, key_len))
+ goto err;
+ if (!CBS_get_bytes(&cbs, &kb->server_write_key, key_len))
+ goto err;
+ if (!CBS_get_bytes(&cbs, &kb->client_write_iv, iv_len))
+ goto err;
+ if (!CBS_get_bytes(&cbs, &kb->server_write_iv, iv_len))
+ goto err;
+ if (CBS_len(&cbs) != 0)
+ goto err;
+
+ return 1;
+
+ err:
+ tls12_key_block_clear(kb);
+ freezero(key_block, key_block_len);
+
+ return 0;
+}
-/* $OpenBSD: tls12_record_layer.c,v 1.26 2021/04/19 17:26:39 jsing Exp $ */
+/* $OpenBSD: tls12_record_layer.c,v 1.27 2021/05/05 10:05:27 jsing Exp $ */
/*
* Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
*
return tls12_record_protection_engaged(rl->write);
}
-const EVP_AEAD *
-tls12_record_layer_aead(struct tls12_record_layer *rl)
-{
- return rl->aead;
-}
-
-const EVP_CIPHER *
-tls12_record_layer_cipher(struct tls12_record_layer *rl)
-{
- return rl->cipher;
-}
-
void
tls12_record_layer_set_aead(struct tls12_record_layer *rl, const EVP_AEAD *aead)
{
static int
tls12_record_layer_ccs_aead(struct tls12_record_layer *rl,
- struct tls12_record_protection *rp, int is_write, const uint8_t *mac_key,
- size_t mac_key_len, const uint8_t *key, size_t key_len, const uint8_t *iv,
- size_t iv_len)
+ struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key,
+ CBS *iv)
{
- size_t aead_nonce_len;
+ size_t aead_nonce_len, fixed_nonce_len;
if (!tls12_record_protection_unused(rp))
return 0;
if (rl->aead == EVP_aead_chacha20_poly1305())
rp->aead_ctx->xor_fixed_nonce = 1;
- if (iv_len > sizeof(rp->aead_ctx->fixed_nonce))
+ if (!CBS_write_bytes(iv, rp->aead_ctx->fixed_nonce,
+ sizeof(rp->aead_ctx->fixed_nonce), &fixed_nonce_len))
return 0;
- memcpy(rp->aead_ctx->fixed_nonce, iv, iv_len);
- rp->aead_ctx->fixed_nonce_len = iv_len;
+ rp->aead_ctx->fixed_nonce_len = fixed_nonce_len;
rp->aead_ctx->tag_len = EVP_AEAD_max_overhead(rl->aead);
rp->aead_ctx->variable_nonce_len = 8;
return 0;
}
- if (!EVP_AEAD_CTX_init(&rp->aead_ctx->ctx, rl->aead, key, key_len,
- EVP_AEAD_DEFAULT_TAG_LENGTH, NULL))
+ if (!EVP_AEAD_CTX_init(&rp->aead_ctx->ctx, rl->aead, CBS_data(key),
+ CBS_len(key), EVP_AEAD_DEFAULT_TAG_LENGTH, NULL))
return 0;
return 1;
static int
tls12_record_layer_ccs_cipher(struct tls12_record_layer *rl,
- struct tls12_record_protection *rp, int is_write, const uint8_t *mac_key,
- size_t mac_key_len, const uint8_t *key, size_t key_len, const uint8_t *iv,
- size_t iv_len)
+ struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key,
+ CBS *iv)
{
EVP_PKEY *mac_pkey = NULL;
int gost_param_nid;
mac_type = EVP_PKEY_HMAC;
rp->stream_mac = 0;
- if (iv_len > INT_MAX || key_len > INT_MAX)
+ if (CBS_len(iv) > INT_MAX || CBS_len(key) > INT_MAX)
goto err;
- if (EVP_CIPHER_iv_length(rl->cipher) != iv_len)
+ if (EVP_CIPHER_iv_length(rl->cipher) != CBS_len(iv))
goto err;
- if (EVP_CIPHER_key_length(rl->cipher) != key_len)
+ if (EVP_CIPHER_key_length(rl->cipher) != CBS_len(key))
goto err;
/* Special handling for GOST... */
if (EVP_MD_type(rl->mac_hash) == NID_id_Gost28147_89_MAC) {
- if (mac_key_len != 32)
+ if (CBS_len(mac_key) != 32)
goto err;
mac_type = EVP_PKEY_GOSTIMIT;
rp->stream_mac = 1;
} else {
- if (mac_key_len > INT_MAX)
+ if (CBS_len(mac_key) > INT_MAX)
goto err;
- if (EVP_MD_size(rl->mac_hash) != mac_key_len)
+ if (EVP_MD_size(rl->mac_hash) != CBS_len(mac_key))
goto err;
}
if ((rp->hash_ctx = EVP_MD_CTX_new()) == NULL)
goto err;
- if (!tls12_record_layer_set_mac_key(rp, mac_key, mac_key_len))
+ if (!tls12_record_layer_set_mac_key(rp, CBS_data(mac_key),
+ CBS_len(mac_key)))
goto err;
- if ((mac_pkey = EVP_PKEY_new_mac_key(mac_type, NULL, mac_key,
- mac_key_len)) == NULL)
+ if ((mac_pkey = EVP_PKEY_new_mac_key(mac_type, NULL, CBS_data(mac_key),
+ CBS_len(mac_key))) == NULL)
goto err;
- if (!EVP_CipherInit_ex(rp->cipher_ctx, rl->cipher, NULL, key, iv,
- is_write))
+ if (!EVP_CipherInit_ex(rp->cipher_ctx, rl->cipher, NULL, CBS_data(key),
+ CBS_data(iv), is_write))
goto err;
if (EVP_DigestSignInit(rp->hash_ctx, NULL, rl->mac_hash, NULL,
static int
tls12_record_layer_change_cipher_state(struct tls12_record_layer *rl,
- struct tls12_record_protection *rp, int is_write, const uint8_t *mac_key,
- size_t mac_key_len, const uint8_t *key, size_t key_len, const uint8_t *iv,
- size_t iv_len)
+ struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key,
+ CBS *iv)
{
if (rl->aead != NULL)
return tls12_record_layer_ccs_aead(rl, rp, is_write, mac_key,
- mac_key_len, key, key_len, iv, iv_len);
+ key, iv);
return tls12_record_layer_ccs_cipher(rl, rp, is_write, mac_key,
- mac_key_len, key, key_len, iv, iv_len);
+ key, iv);
}
int
tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl,
- const uint8_t *mac_key, size_t mac_key_len, const uint8_t *key,
- size_t key_len, const uint8_t *iv, size_t iv_len)
+ CBS *mac_key, CBS *key, CBS *iv)
{
struct tls12_record_protection *read_new = NULL;
int ret = 0;
/* Read sequence number gets reset to zero. */
if (!tls12_record_layer_change_cipher_state(rl, read_new, 0,
- mac_key, mac_key_len, key, key_len, iv, iv_len))
+ mac_key, key, iv))
goto err;
tls12_record_protection_free(rl->read_current);
int
tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl,
- const uint8_t *mac_key, size_t mac_key_len, const uint8_t *key,
- size_t key_len, const uint8_t *iv, size_t iv_len)
+ CBS *mac_key, CBS *key, CBS *iv)
{
struct tls12_record_protection *write_new;
int ret = 0;
/* Write sequence number gets reset to zero. */
if (!tls12_record_layer_change_cipher_state(rl, write_new, 1,
- mac_key, mac_key_len, key, key_len, iv, iv_len))
+ mac_key, key, iv))
goto err;
if (rl->dtls) {