-/* $OpenBSD: ssl_lib.c,v 1.306 2022/10/02 16:36:41 jsing Exp $ */
+/* $OpenBSD: ssl_lib.c,v 1.307 2022/11/07 11:58:45 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
#include "ssl_locl.h"
#include "ssl_sigalgs.h"
#include "ssl_tlsext.h"
+#include "tls12_internal.h"
const char *SSL_version_str = OPENSSL_VERSION_TEXT;
}
int
-SSL_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)
+SSL_export_keying_material(SSL *s, unsigned char *out, size_t out_len,
+ const char *label, size_t label_len, const unsigned char *context,
+ size_t context_len, int use_context)
{
if (s->tls13 != NULL && s->version == TLS1_3_VERSION) {
if (!use_context) {
- p = NULL;
- plen = 0;
+ context = NULL;
+ context_len = 0;
}
- return tls13_exporter(s->tls13, label, llen, p, plen,
- out, olen);
+ return tls13_exporter(s->tls13, label, label_len, context,
+ context_len, out, out_len);
}
- return (tls1_export_keying_material(s, out, olen, label, llen, p, plen,
- use_context));
+ return tls12_exporter(s, label, label_len, context, context_len,
+ use_context, out, out_len);
}
static unsigned long
-/* $OpenBSD: ssl_locl.h,v 1.429 2022/10/20 15:22:51 tb Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.430 2022/11/07 11:58:45 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
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);
int ssl_ok(SSL *s);
int tls12_derive_finished(SSL *s);
-/* $OpenBSD: t1_enc.c,v 1.155 2022/10/02 16:36:41 jsing Exp $ */
+/* $OpenBSD: t1_enc.c,v 1.156 2022/11/07 11:58:45 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
return (ret);
}
-
-int
-tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
- const char *label, size_t llen, const unsigned char *context,
- size_t contextlen, int use_context)
-{
- unsigned char *val = NULL;
- size_t vallen, currentvalpos;
- int rv;
-
- if (!SSL_is_init_finished(s)) {
- SSLerror(s, SSL_R_BAD_STATE);
- return 0;
- }
-
- /* construct PRF arguments
- * we construct the PRF argument ourself rather than passing separate
- * values into the TLS PRF to ensure that the concatenation of values
- * does not create a prohibited label.
- */
- vallen = llen + SSL3_RANDOM_SIZE * 2;
- if (use_context) {
- vallen += 2 + contextlen;
- }
-
- val = malloc(vallen);
- if (val == NULL)
- goto err2;
- currentvalpos = 0;
- memcpy(val + currentvalpos, (unsigned char *) label, llen);
- currentvalpos += llen;
- memcpy(val + currentvalpos, s->s3->client_random, SSL3_RANDOM_SIZE);
- currentvalpos += SSL3_RANDOM_SIZE;
- memcpy(val + currentvalpos, s->s3->server_random, SSL3_RANDOM_SIZE);
- currentvalpos += SSL3_RANDOM_SIZE;
-
- if (use_context) {
- val[currentvalpos] = (contextlen >> 8) & 0xff;
- currentvalpos++;
- val[currentvalpos] = contextlen & 0xff;
- currentvalpos++;
- if ((contextlen > 0) || (context != NULL)) {
- memcpy(val + currentvalpos, context, contextlen);
- }
- }
-
- /* disallow prohibited labels
- * note that SSL3_RANDOM_SIZE > max(prohibited label len) =
- * 15, so size of val > max(prohibited label len) = 15 and the
- * comparisons won't have buffer overflow
- */
- if (memcmp(val, TLS_MD_CLIENT_FINISH_CONST,
- TLS_MD_CLIENT_FINISH_CONST_SIZE) == 0)
- goto err1;
- if (memcmp(val, TLS_MD_SERVER_FINISH_CONST,
- TLS_MD_SERVER_FINISH_CONST_SIZE) == 0)
- goto err1;
- if (memcmp(val, TLS_MD_MASTER_SECRET_CONST,
- TLS_MD_MASTER_SECRET_CONST_SIZE) == 0)
- goto err1;
- if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
- TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0)
- goto err1;
-
- rv = tls1_PRF(s, s->session->master_key, s->session->master_key_length,
- val, vallen, NULL, 0, NULL, 0, NULL, 0, NULL, 0, out, olen);
-
- goto ret;
- err1:
- SSLerror(s, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
- rv = 0;
- goto ret;
- err2:
- SSLerror(s, ERR_R_MALLOC_FAILURE);
- rv = 0;
- ret:
- free(val);
-
- return (rv);
-}
--- /dev/null
+/* $OpenBSD: tls12_internal.h,v 1.1 2022/11/07 11:58:45 jsing Exp $ */
+/*
+ * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and/or 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.
+ */
+
+#ifndef HEADER_TLS12_INTERNAL_H
+#define HEADER_TLS12_INTERNAL_H
+
+__BEGIN_HIDDEN_DECLS
+
+int tls12_exporter(SSL *s, const uint8_t *label, size_t label_len,
+ const uint8_t *context_value, size_t context_value_len, int use_context,
+ uint8_t *out, size_t out_len);
+
+__END_HIDDEN_DECLS
+
+#endif
-/* $OpenBSD: tls12_key_schedule.c,v 1.1 2021/05/05 10:05:27 jsing Exp $ */
+/* $OpenBSD: tls12_key_schedule.c,v 1.2 2022/11/07 11:58:45 jsing Exp $ */
/*
* Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
*
#include "bytestring.h"
#include "ssl_locl.h"
+#include "tls12_internal.h"
struct tls12_key_block {
CBS client_write_mac_key;
return 0;
}
+
+struct tls12_reserved_label {
+ const char *label;
+ size_t label_len;
+};
+
+/*
+ * RFC 5705 section 6.
+ */
+static const struct tls12_reserved_label tls12_reserved_labels[] = {
+ {
+ .label = TLS_MD_CLIENT_FINISH_CONST,
+ .label_len = TLS_MD_CLIENT_FINISH_CONST_SIZE,
+ },
+ {
+ .label = TLS_MD_SERVER_FINISH_CONST,
+ .label_len = TLS_MD_SERVER_FINISH_CONST_SIZE,
+ },
+ {
+ .label = TLS_MD_MASTER_SECRET_CONST,
+ .label_len = TLS_MD_MASTER_SECRET_CONST_SIZE,
+ },
+ {
+ .label = TLS_MD_KEY_EXPANSION_CONST,
+ .label_len = TLS_MD_KEY_EXPANSION_CONST_SIZE,
+ },
+ {
+ .label = NULL,
+ .label_len = 0,
+ },
+};
+
+int
+tls12_exporter(SSL *s, const uint8_t *label, size_t label_len,
+ const uint8_t *context_value, size_t context_value_len, int use_context,
+ uint8_t *out, size_t out_len)
+{
+ uint8_t *data = NULL;
+ size_t data_len = 0;
+ CBB cbb, context;
+ CBS seed;
+ size_t i;
+ int ret = 0;
+
+ /*
+ * RFC 5705 - Key Material Exporters for TLS.
+ */
+
+ memset(&cbb, 0, sizeof(cbb));
+
+ if (!SSL_is_init_finished(s)) {
+ SSLerror(s, SSL_R_BAD_STATE);
+ goto err;
+ }
+
+ if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION)
+ goto err;
+
+ /*
+ * Due to exceptional design choices, we need to build a concatenation
+ * of the label and the seed value, before checking for reserved
+ * labels. This prevents a reserved label from being split across the
+ * label and the seed (that includes the client random), which are
+ * concatenated by the PRF.
+ */
+ if (!CBB_init(&cbb, 0))
+ goto err;
+ if (!CBB_add_bytes(&cbb, label, label_len))
+ goto err;
+ if (!CBB_add_bytes(&cbb, s->s3->client_random, SSL3_RANDOM_SIZE))
+ goto err;
+ if (!CBB_add_bytes(&cbb, s->s3->server_random, SSL3_RANDOM_SIZE))
+ goto err;
+ if (use_context) {
+ if (!CBB_add_u16_length_prefixed(&cbb, &context))
+ goto err;
+ if (context_value_len > 0) {
+ if (!CBB_add_bytes(&context, context_value,
+ context_value_len))
+ goto err;
+ }
+ }
+ if (!CBB_finish(&cbb, &data, &data_len))
+ goto err;
+
+ /*
+ * Ensure that the block (label + seed) does not start with a reserved
+ * label - in an ideal world we would ensure that the label has an
+ * explicitly permitted prefix instead, but of course this also got
+ * messed up by the standards.
+ */
+ for (i = 0; tls12_reserved_labels[i].label != NULL; i++) {
+ /* XXX - consider adding/using CBS_has_prefix(). */
+ if (tls12_reserved_labels[i].label_len > data_len)
+ goto err;
+ if (memcmp(data, tls12_reserved_labels[i].label,
+ tls12_reserved_labels[i].label_len) == 0) {
+ SSLerror(s, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
+ goto err;
+ }
+ }
+
+ CBS_init(&seed, data, data_len);
+ if (!CBS_skip(&seed, label_len))
+ goto err;
+
+ if (!tls1_PRF(s, s->session->master_key, s->session->master_key_length,
+ label, label_len, CBS_data(&seed), CBS_len(&seed), NULL, 0, NULL, 0,
+ NULL, 0, out, out_len))
+ goto err;
+
+ ret = 1;
+
+ err:
+ freezero(data, data_len);
+ CBB_cleanup(&cbb);
+
+ return ret;
+}