/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdlib.h>
#include "ssl_local.h"
#include "internal/ktls.h"
#include "record/record_local.h"
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/core_names.h>
#define TLS13_MAX_LABEL_LEN 249
/* ASCII: "tls13 ", in hex for EBCDIC compatibility */
static const unsigned char label_prefix[] = "\x74\x6C\x73\x31\x33\x20";
/*
* Given a |secret|; a |label| of length |labellen|; and |data| of length
* |datalen| (e.g. typically a hash of the handshake messages), derive a new
* secret |outlen| bytes long and store it in the location pointed to be |out|.
* The |data| value may be zero length. Any errors will be treated as fatal if
* |fatal| is set. Returns 1 on success 0 on failure.
* If |raise_error| is set, ERR_raise is called on failure.
*/
int tls13_hkdf_expand_ex(OSSL_LIB_CTX *libctx, const char *propq,
const EVP_MD *md,
const unsigned char *secret,
const unsigned char *label, size_t labellen,
const unsigned char *data, size_t datalen,
unsigned char *out, size_t outlen, int raise_error)
{
EVP_KDF *kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_TLS1_3_KDF, propq);
EVP_KDF_CTX *kctx;
OSSL_PARAM params[7], *p = params;
int mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
const char *mdname = EVP_MD_get0_name(md);
int ret;
size_t hashlen;
kctx = EVP_KDF_CTX_new(kdf);
EVP_KDF_free(kdf);
if (kctx == NULL)
return 0;
if (labellen > TLS13_MAX_LABEL_LEN) {
if (raise_error)
/*
* Probably we have been called from SSL_export_keying_material(),
* or SSL_export_keying_material_early().
*/
ERR_raise(ERR_LIB_SSL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
EVP_KDF_CTX_free(kctx);
return 0;
}
if ((ret = EVP_MD_get_size(md)) <= 0) {
EVP_KDF_CTX_free(kctx);
if (raise_error)
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
hashlen = (size_t)ret;
*p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
(char *)mdname, 0);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
(unsigned char *)secret, hashlen);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PREFIX,
(unsigned char *)label_prefix,
sizeof(label_prefix) - 1);
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_LABEL,
(unsigned char *)label, labellen);
if (data != NULL)
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_DATA,
(unsigned char *)data,
datalen);
*p++ = OSSL_PARAM_construct_end();
ret = EVP_KDF_derive(kctx, out, outlen, params) <= 0;
EVP_KDF_CTX_free(kctx);
if (ret != 0) {
if (raise_error)
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
}
return ret == 0;
}
int tls13_hkdf_expand(SSL_CONNECTION *s, const EVP_MD *md,
const unsigned char *secret,
const unsigned char *label, size_t labellen,
const unsigned char *data, size_t datalen,
unsigned char *out, size_t outlen, int fatal)
{
int ret;
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
ret = tls13_hkdf_expand_ex(sctx->libctx, sctx->propq, md,
secret, label, labellen, data, datalen,
out, outlen, !fatal);
if (ret == 0 && fatal)
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return ret;
}
/*
* Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on
* success 0 on failure.
*/
int tls13_derive_key(SSL_CONNECTION *s, const EVP_MD *md,
const unsigned char *