1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-30 22:43:08 +03:00

Merge branch 'development' into 'development-restricted'

Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
This commit is contained in:
Minos Galanakis
2024-03-19 22:24:00 +00:00
87 changed files with 5816 additions and 2224 deletions

View File

@ -56,6 +56,7 @@ set(src_crypto
padlock.c
pem.c
pk.c
pk_ecc.c
pk_wrap.c
pkcs12.c
pkcs5.c

View File

@ -1,3 +1,26 @@
ifndef MBEDTLS_PATH
MBEDTLS_PATH := ..
endif
GENERATED_FILES := \
error.c version_features.c \
ssl_debug_helpers_generated.c \
psa_crypto_driver_wrappers.h \
psa_crypto_driver_wrappers_no_static.c
ifneq ($(GENERATED_FILES),$(wildcard $(GENERATED_FILES)))
ifeq (,$(wildcard $(MBEDTLS_PATH)/framework/exported.make))
# Use the define keyword to get a multi-line message.
# GNU make appends ". Stop.", so tweak the ending of our message accordingly.
define error_message
$(MBEDTLS_PATH)/framework/exported.make not found.
Run `git submodule update --init` to fetch the submodule contents.
This is a fatal error
endef
$(error $(error_message))
endif
include $(MBEDTLS_PATH)/framework/exported.make
endif
# Also see "include/mbedtls/mbedtls_config.h"
@ -125,6 +148,7 @@ OBJS_CRYPTO= \
padlock.o \
pem.o \
pk.o \
pk_ecc.o \
pk_wrap.o \
pkcs12.o \
pkcs5.o \
@ -314,11 +338,6 @@ libmbedcrypto.dll: $(OBJS_CRYPTO)
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
.PHONY: generated_files
GENERATED_FILES = \
error.c version_features.c \
ssl_debug_helpers_generated.c \
psa_crypto_driver_wrappers.h \
psa_crypto_driver_wrappers_no_static.c
generated_files: $(GENERATED_FILES)
# See root Makefile

View File

@ -57,22 +57,29 @@ static int cmac_multiply_by_u(unsigned char *output,
size_t blocksize)
{
const unsigned char R_128 = 0x87;
const unsigned char R_64 = 0x1B;
unsigned char R_n;
unsigned char overflow = 0x00;
uint32_t overflow = 0x00;
int i;
if (blocksize == MBEDTLS_AES_BLOCK_SIZE) {
R_n = R_128;
} else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
}
#if defined(MBEDTLS_DES_C)
else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
const unsigned char R_64 = 0x1B;
R_n = R_64;
} else {
}
#endif
else {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
for (i = (int) blocksize - 1; i >= 0; i--) {
output[i] = input[i] << 1 | overflow;
overflow = input[i] >> 7;
for (i = (int) blocksize - 4; i >= 0; i -= 4) {
uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);
uint32_t new_overflow = i32 >> 31;
i32 = (i32 << 1) | overflow;
MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);
overflow = new_overflow;
}
R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n);
@ -205,6 +212,10 @@ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
state = ctx->cmac_ctx->state;
/* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form
* error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */
MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE);
/* Is there data still to process from the last call, that's greater in
* size than a block? */
if (cmac_ctx->unprocessed_len > 0 &&
@ -272,6 +283,7 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
cmac_ctx = ctx->cmac_ctx;
block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning
state = cmac_ctx->state;
mbedtls_platform_zeroize(K1, sizeof(K1));

View File

@ -412,8 +412,17 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
while (iv_len > 0) {
use_len = (iv_len < 16) ? iv_len : 16;
#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wstringop-overflow=0"
#endif
mbedtls_xor(ctx->y, ctx->y, p, use_len);
#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
#pragma GCC diagnostic pop
#endif
gcm_mult(ctx, ctx->y, ctx->y);
iv_len -= use_len;

View File

@ -35,6 +35,10 @@
#include <limits.h>
#include <stdint.h>
#define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \
(PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \
PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
/*
* Initialise a mbedtls_pk_context
*/
@ -320,14 +324,14 @@ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
}
psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes);
/* Key's enrollment is available only when MBEDTLS_PSA_CRYPTO_CLIENT is
* defined, i.e. when the Mbed TLS implementation of PSA Crypto is being used.
/* Key's enrollment is available only when an Mbed TLS implementation of PSA
* Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
* Even though we don't officially support using other implementations of PSA
* Crypto with TLS and X.509 (yet), we're still trying to simplify the life of
* people who would like to try it before it's officially supported. */
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
* Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
* separated. */
#if defined(MBEDTLS_PSA_CRYPTO_C)
psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
#endif /* MBEDTLS_PSA_CRYPTO_C */
key_usage = psa_get_key_usage_flags(&attributes);
psa_reset_key_attributes(&attributes);
@ -345,11 +349,11 @@ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
if (alg == key_alg) {
return 1;
}
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#if defined(MBEDTLS_PSA_CRYPTO_C)
if (alg == key_alg2) {
return 1;
}
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
#endif /* MBEDTLS_PSA_CRYPTO_C */
/*
* If key_alg [or key_alg2] is a hash-and-sign with a wildcard for the hash,
@ -357,26 +361,25 @@ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
* then alg is compliant with this key alg
*/
if (PSA_ALG_IS_SIGN_HASH(alg)) {
if (PSA_ALG_IS_SIGN_HASH(key_alg) &&
PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH &&
(alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) {
return 1;
}
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#if defined(MBEDTLS_PSA_CRYPTO_C)
if (PSA_ALG_IS_SIGN_HASH(key_alg2) &&
PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH &&
(alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) {
return 1;
}
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
#endif /* MBEDTLS_PSA_CRYPTO_C */
}
return 0;
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PSA_CRYPTO_C)
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#if defined(MBEDTLS_RSA_C)
static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,
int want_crypt)
@ -573,7 +576,14 @@ int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,
}
psa_set_key_usage_flags(attributes, more_usage);
/* Key's enrollment is available only when an Mbed TLS implementation of PSA
* Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
* Even though we don't officially support using other implementations of PSA
* Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
* separated. */
#if defined(MBEDTLS_PSA_CRYPTO_C)
psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE);
#endif
return 0;
}
@ -850,7 +860,136 @@ int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
return import_pair_into_psa(pk, attributes, key_id);
}
}
#endif /* MBEDTLS_PSA_CRYPTO_C */
static int copy_from_psa(mbedtls_svc_key_id_t key_id,
mbedtls_pk_context *pk,
int public_only)
{
psa_status_t status;
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type;
psa_algorithm_t alg_type;
size_t key_bits;
/* Use a buffer size large enough to contain either a key pair or public key. */
unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE];
size_t exp_key_len;
int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
if (pk == NULL) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
status = psa_get_key_attributes(key_id, &key_attr);
if (status != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
if (public_only) {
status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
} else {
status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
}
if (status != PSA_SUCCESS) {
ret = PSA_PK_TO_MBEDTLS_ERR(status);
goto exit;
}
key_type = psa_get_key_type(&key_attr);
if (public_only) {
key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);
}
key_bits = psa_get_key_bits(&key_attr);
alg_type = psa_get_key_algorithm(&key_attr);
#if defined(MBEDTLS_RSA_C)
if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) ||
(key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) {
ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
if (ret != 0) {
goto exit;
}
if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
} else {
ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
}
if (ret != 0) {
goto exit;
}
mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) {
md_type = mbedtls_md_type_from_psa_alg(alg_type);
}
if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) {
ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type);
} else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) ||
alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) {
ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type);
}
if (ret != 0) {
goto exit;
}
} else
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ||
PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) {
mbedtls_ecp_group_id grp_id;
ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
if (ret != 0) {
goto exit;
}
grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits);
ret = mbedtls_pk_ecc_set_group(pk, grp_id);
if (ret != 0) {
goto exit;
}
if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len);
if (ret != 0) {
goto exit;
}
ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE);
} else {
ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len);
}
if (ret != 0) {
goto exit;
}
} else
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
{
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
exit:
psa_reset_key_attributes(&key_attr);
mbedtls_platform_zeroize(exp_key, sizeof(exp_key));
return ret;
}
int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id,
mbedtls_pk_context *pk)
{
return copy_from_psa(key_id, pk, 0);
}
int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id,
mbedtls_pk_context *pk)
{
return copy_from_psa(key_id, pk, 1);
}
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
/*
* Helper for mbedtls_pk_sign and mbedtls_pk_verify
@ -987,6 +1126,12 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len);
}
/* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa()
* below would return a NULL pointer. */
if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) {
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
}
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_pk_rsassa_pss_options *pss_opts;
@ -1017,7 +1162,7 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg);
p = buf + sizeof(buf);
key_len = mbedtls_pk_write_pubkey(&p, buf, ctx);
key_len = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*ctx), buf, &p);
if (key_len < 0) {
return key_len;
@ -1183,7 +1328,10 @@ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t psa_alg, psa_enrollment_alg, sign_alg;
psa_algorithm_t psa_alg, sign_alg;
#if defined(MBEDTLS_PSA_CRYPTO_C)
psa_algorithm_t psa_enrollment_alg;
#endif /* MBEDTLS_PSA_CRYPTO_C */
psa_status_t status;
status = psa_get_key_attributes(ctx->priv_id, &key_attr);
@ -1191,16 +1339,22 @@ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
}
psa_alg = psa_get_key_algorithm(&key_attr);
#if defined(MBEDTLS_PSA_CRYPTO_C)
psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr);
#endif /* MBEDTLS_PSA_CRYPTO_C */
psa_reset_key_attributes(&key_attr);
/* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between
* alg and enrollment alg should be of type RSA_PSS. */
if (PSA_ALG_IS_RSA_PSS(psa_alg)) {
sign_alg = psa_alg;
} else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) {
}
#if defined(MBEDTLS_PSA_CRYPTO_C)
else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) {
sign_alg = psa_enrollment_alg;
} else {
}
#endif /* MBEDTLS_PSA_CRYPTO_C */
else {
/* The opaque key has no RSA PSS algorithm associated. */
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}

255
library/pk_ecc.c Normal file
View File

@ -0,0 +1,255 @@
/*
* ECC setters for PK.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#include "mbedtls/pk.h"
#include "mbedtls/error.h"
#include "mbedtls/ecp.h"
#include "pk_internal.h"
#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS)
int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
size_t ec_bits;
psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);
/* group may already be initialized; if so, make sure IDs match */
if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||
(pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
}
/* set group */
pk->ec_family = ec_family;
pk->ec_bits = ec_bits;
return 0;
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
/* grp may already be initialized; if so, make sure IDs match */
if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
}
/* set group */
return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_usage_t flags;
psa_status_t status;
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));
if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) {
/* Do not set algorithm here because Montgomery keys cannot do ECDSA and
* the PK module cannot do ECDH. When the key will be used in TLS for
* ECDH, it will be exported and then re-imported with proper flags
* and algorithm. */
flags = PSA_KEY_USAGE_EXPORT;
} else {
psa_set_key_algorithm(&attributes,
MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));
flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE |
PSA_KEY_USAGE_EXPORT;
}
psa_set_key_usage_flags(&attributes, flags);
status = psa_import_key(&attributes, key, key_len, &pk->priv_id);
return psa_pk_status_to_mbedtls(status);
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
}
return 0;
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
const unsigned char *prv, size_t prv_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
(void) f_rng;
(void) p_rng;
(void) prv;
(void) prv_len;
psa_status_t status;
status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
&pk->pub_raw_len);
return psa_pk_status_to_mbedtls(status);
#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */
(void) f_rng;
(void) p_rng;
psa_status_t status;
mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
size_t curve_bits;
psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
/* Import private key into PSA, from serialized input */
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
status = psa_import_key(&key_attr, prv, prv_len, &key_id);
if (status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(status);
}
/* Export public key from PSA */
unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
size_t pub_len;
status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len);
psa_status_t destruction_status = psa_destroy_key(key_id);
if (status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(status);
} else if (destruction_status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(destruction_status);
}
/* Load serialized public key into ecp_keypair structure */
return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len);
#else /* MBEDTLS_USE_PSA_CRYPTO */
(void) prv;
(void) prv_len;
mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
#endif /* MBEDTLS_USE_PSA_CRYPTO */
}
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
/*
* Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case.
*
* Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA
* functions to handle keys. However, currently psa_import_key() does not
* support compressed points. In case that support was explicitly requested,
* this fallback uses ECP functions to get the job done. This is the reason
* why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT.
*
* [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group().
* out: will have the public key set.
* [in] pub, pub_len: the public key as an ECPoint,
* in any format supported by ECP.
*
* Return:
* - 0 on success;
* - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
* but not supported;
* - another error code otherwise.
*/
static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk,
const unsigned char *pub,
size_t pub_len)
{
#if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
(void) pk;
(void) pub;
(void) pub_len;
return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
mbedtls_ecp_keypair ecp_key;
mbedtls_ecp_group_id ecp_group_id;
int ret;
ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
mbedtls_ecp_keypair_init(&ecp_key);
ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);
if (ret != 0) {
goto exit;
}
ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,
pub, pub_len);
if (ret != 0) {
goto exit;
}
ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
&pk->pub_raw_len, pk->pub_raw,
sizeof(pk->pub_raw));
exit:
mbedtls_ecp_keypair_free(&ecp_key);
return ret;
#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
}
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
/* Load the key */
if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) {
/* Format directly supported by PSA:
* - non-Weierstrass curves that only have one format;
* - uncompressed format for Weierstrass curves. */
if (pub_len > sizeof(pk->pub_raw)) {
return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
}
memcpy(pk->pub_raw, pub, pub_len);
pk->pub_raw_len = pub_len;
} else {
/* Other format, try the fallback */
int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len);
if (ret != 0) {
return ret;
}
}
/* Validate the key by trying to import it */
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&key_attrs, 0);
psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));
psa_set_key_bits(&key_attrs, pk->ec_bits);
if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,
&key_id) != PSA_SUCCESS) ||
(psa_destroy_key(key_id) != PSA_SUCCESS)) {
return MBEDTLS_ERR_PK_INVALID_PUBKEY;
}
return 0;
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
int ret;
mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);
if (ret != 0) {
return ret;
}
return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
#endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */

View File

@ -127,6 +127,62 @@ static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk)
return MBEDTLS_PK_IS_RFC8410_GROUP_ID(id);
}
/*
* Set the group used by this key.
*
* [in/out] pk: in: must have been pk_setup() to an ECC type
* out: will have group (curve) information set
* [in] grp_in: a supported group ID (not NONE)
*/
int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id);
/*
* Set the private key material
*
* [in/out] pk: in: must have the group set already, see mbedtls_pk_ecc_set_group().
* out: will have the private key set.
* [in] key, key_len: the raw private key (no ASN.1 wrapping).
*/
int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len);
/*
* Set the public key.
*
* [in/out] pk: in: must have its group set, see mbedtls_pk_ecc_set_group().
* out: will have the public key set.
* [in] pub, pub_len: the raw public key (an ECPoint).
*
* Return:
* - 0 on success;
* - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
* but not supported;
* - another error code otherwise.
*/
int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len);
/*
* Derive a public key from its private counterpart.
* Computationally intensive, only use when public key is not available.
*
* [in/out] pk: in: must have the private key set, see mbedtls_pk_ecc_set_key().
* out: will have the public key set.
* [in] prv, prv_len: the raw private key (see note below).
* [in] f_rng, p_rng: RNG function and context.
*
* Note: the private key information is always available from pk,
* however for convenience the serialized version is also passed,
* as it's available at each calling site, and useful in some configs
* (as otherwise we would have to re-serialize it from the pk context).
*
* There are three implementations of this function:
* 1. MBEDTLS_PK_USE_PSA_EC_DATA,
* 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA,
* 3. not MBEDTLS_USE_PSA_CRYPTO.
*/
int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
const unsigned char *prv, size_t prv_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
/* Helper for (deterministic) ECDSA */

View File

@ -368,7 +368,7 @@ static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t psa_md_alg;
psa_algorithm_t psa_md_alg, psa_encrypt_alg;
psa_status_t status;
int key_len;
unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
@ -389,10 +389,11 @@ static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_OAEP(psa_md_alg));
psa_encrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);
} else {
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
psa_encrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
}
psa_set_key_algorithm(&attributes, psa_encrypt_alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
status = psa_import_key(&attributes,
@ -403,7 +404,7 @@ static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
goto cleanup;
}
status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
status = psa_asymmetric_encrypt(key_id, psa_encrypt_alg,
input, ilen,
NULL, 0,
output, osize, olen);

View File

@ -44,302 +44,6 @@
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
/***********************************************************************
*
* ECC setters
*
* 1. This is an abstraction layer around MBEDTLS_PK_USE_PSA_EC_DATA:
* this macro will not appear outside this section.
* 2. All inputs are raw: no metadata, no ASN.1 until the next section.
*
**********************************************************************/
/*
* Set the group used by this key.
*
* [in/out] pk: in: must have been pk_setup() to an ECC type
* out: will have group (curve) information set
* [in] grp_in: a supported group ID (not NONE)
*/
static int pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
size_t ec_bits;
psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);
/* group may already be initialized; if so, make sure IDs match */
if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||
(pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
}
/* set group */
pk->ec_family = ec_family;
pk->ec_bits = ec_bits;
return 0;
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
/* grp may already be initialized; if so, make sure IDs match */
if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
}
/* set group */
return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
/*
* Set the private key material
*
* [in/out] pk: in: must have the group set already, see pk_ecc_set_group().
* out: will have the private key set.
* [in] key, key_len: the raw private key (no ASN.1 wrapping).
*/
static int pk_ecc_set_key(mbedtls_pk_context *pk,
unsigned char *key, size_t key_len)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_usage_t flags;
psa_status_t status;
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));
if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) {
/* Do not set algorithm here because Montgomery keys cannot do ECDSA and
* the PK module cannot do ECDH. When the key will be used in TLS for
* ECDH, it will be exported and then re-imported with proper flags
* and algorithm. */
flags = PSA_KEY_USAGE_EXPORT;
} else {
psa_set_key_algorithm(&attributes,
MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));
flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE |
PSA_KEY_USAGE_EXPORT;
}
psa_set_key_usage_flags(&attributes, flags);
status = psa_import_key(&attributes, key, key_len, &pk->priv_id);
return psa_pk_status_to_mbedtls(status);
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
}
return 0;
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
/*
* Derive a public key from its private counterpart.
* Computationally intensive, only use when public key is not available.
*
* [in/out] pk: in: must have the private key set, see pk_ecc_set_key().
* out: will have the public key set.
* [in] prv, prv_len: the raw private key (see note below).
* [in] f_rng, p_rng: RNG function and context.
*
* Note: the private key information is always available from pk,
* however for convenience the serialized version is also passed,
* as it's available at each calling site, and useful in some configs
* (as otherwise we would have to re-serialize it from the pk context).
*
* There are three implementations of this function:
* 1. MBEDTLS_PK_USE_PSA_EC_DATA,
* 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA,
* 3. not MBEDTLS_USE_PSA_CRYPTO.
*/
static int pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
const unsigned char *prv, size_t prv_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
(void) f_rng;
(void) p_rng;
(void) prv;
(void) prv_len;
psa_status_t status;
status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
&pk->pub_raw_len);
return psa_pk_status_to_mbedtls(status);
#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */
(void) f_rng;
(void) p_rng;
psa_status_t status;
mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
size_t curve_bits;
psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
/* Import private key into PSA, from serialized input */
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
status = psa_import_key(&key_attr, prv, prv_len, &key_id);
if (status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(status);
}
/* Export public key from PSA */
unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
size_t pub_len;
status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len);
psa_status_t destruction_status = psa_destroy_key(key_id);
if (status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(status);
} else if (destruction_status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(destruction_status);
}
/* Load serialized public key into ecp_keypair structure */
return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len);
#else /* MBEDTLS_USE_PSA_CRYPTO */
(void) prv;
(void) prv_len;
mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
#endif /* MBEDTLS_USE_PSA_CRYPTO */
}
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
/*
* Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case.
*
* Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA
* functions to handle keys. However, currently psa_import_key() does not
* support compressed points. In case that support was explicitly requested,
* this fallback uses ECP functions to get the job done. This is the reason
* why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT.
*
* [in/out] pk: in: must have the group set, see pk_ecc_set_group().
* out: will have the public key set.
* [in] pub, pub_len: the public key as an ECPoint,
* in any format supported by ECP.
*
* Return:
* - 0 on success;
* - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
* but not supported;
* - another error code otherwise.
*/
static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk,
const unsigned char *pub,
size_t pub_len)
{
#if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
(void) pk;
(void) pub;
(void) pub_len;
return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
mbedtls_ecp_keypair ecp_key;
mbedtls_ecp_group_id ecp_group_id;
int ret;
ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
mbedtls_ecp_keypair_init(&ecp_key);
ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);
if (ret != 0) {
goto exit;
}
ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,
pub, pub_len);
if (ret != 0) {
goto exit;
}
ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
&pk->pub_raw_len, pk->pub_raw,
sizeof(pk->pub_raw));
exit:
mbedtls_ecp_keypair_free(&ecp_key);
return ret;
#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
}
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
/*
* Set the public key.
*
* [in/out] pk: in: must have its group set, see pk_ecc_set_group().
* out: will have the public key set.
* [in] pub, pub_len: the raw public key (an ECPoint).
*
* Return:
* - 0 on success;
* - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
* but not supported;
* - another error code otherwise.
*/
static int pk_ecc_set_pubkey(mbedtls_pk_context *pk,
const unsigned char *pub, size_t pub_len)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
/* Load the key */
if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) {
/* Format directly supported by PSA:
* - non-Weierstrass curves that only have one format;
* - uncompressed format for Weierstrass curves. */
if (pub_len > sizeof(pk->pub_raw)) {
return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
}
memcpy(pk->pub_raw, pub, pub_len);
pk->pub_raw_len = pub_len;
} else {
/* Other format, try the fallback */
int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len);
if (ret != 0) {
return ret;
}
}
/* Validate the key by trying to import it */
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&key_attrs, 0);
psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));
psa_set_key_bits(&key_attrs, pk->ec_bits);
if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,
&key_id) != PSA_SUCCESS) ||
(psa_destroy_key(key_id) != PSA_SUCCESS)) {
return MBEDTLS_ERR_PK_INVALID_PUBKEY;
}
return 0;
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
int ret;
mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);
if (ret != 0) {
return ret;
}
return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
/***********************************************************************
*
* Low-level ECC parsing: optional support for SpecifiedECDomain
@ -698,7 +402,7 @@ static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *p
}
}
return pk_ecc_set_group(pk, grp_id);
return mbedtls_pk_ecc_set_group(pk, grp_id);
}
#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
@ -714,7 +418,7 @@ static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params,
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
}
return pk_ecc_set_group(pk, grp_id);
return mbedtls_pk_ecc_set_group(pk, grp_id);
}
/*
@ -740,7 +444,7 @@ static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
/*
* Load the private key
*/
ret = pk_ecc_set_key(pk, key, len);
ret = mbedtls_pk_ecc_set_key(pk, key, len);
if (ret != 0) {
return ret;
}
@ -748,7 +452,7 @@ static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
/* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,
* which never contain a public key. As such, derive the public key
* unconditionally. */
if ((ret = pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
return ret;
}
@ -874,7 +578,7 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
ret = pk_use_ecparams(&alg_params, pk);
}
if (ret == 0) {
ret = pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
*p += end - *p;
}
} else
@ -966,7 +670,7 @@ static int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
/*
* Load the private key
*/
ret = pk_ecc_set_key(pk, d, d_len);
ret = mbedtls_pk_ecc_set_key(pk, d, d_len);
if (ret != 0) {
return ret;
}
@ -990,11 +694,11 @@ static int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
}
if ((ret = pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
pubkey_done = 1;
} else {
/*
* The only acceptable failure mode of pk_ecc_set_pubkey() above
* The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above
* is if the point format is not recognized.
*/
if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
@ -1007,7 +711,7 @@ static int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
}
if (!pubkey_done) {
if ((ret = pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
return ret;
}
}

View File

@ -71,6 +71,7 @@
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "mbedtls/psa_util.h"
#include "mbedtls/threading.h"
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \
@ -92,17 +93,80 @@ static int key_type_is_raw_bytes(psa_key_type_t type)
#define RNG_INITIALIZED 1
#define RNG_SEEDED 2
/* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized
* variables as arguments. */
typedef enum {
PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1,
PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS,
PSA_CRYPTO_SUBSYSTEM_RNG,
PSA_CRYPTO_SUBSYSTEM_TRANSACTION,
} mbedtls_psa_crypto_subsystem;
/* Initialization flags for global_data::initialized */
#define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED 0x01
#define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED 0x02
#define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED 0x04
#define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED ( \
PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \
PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \
PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)
typedef struct {
uint8_t initialized;
uint8_t rng_state;
uint8_t drivers_initialized;
mbedtls_psa_random_context_t rng;
} psa_global_data_t;
static psa_global_data_t global_data;
static uint8_t psa_get_initialized(void)
{
uint8_t initialized;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
initialized = global_data.rng_state == RNG_SEEDED;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
initialized =
(initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED));
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
return initialized;
}
static uint8_t psa_get_drivers_initialized(void)
{
uint8_t initialized;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
return initialized;
}
#define GUARD_MODULE_INITIALIZED \
if (global_data.initialized == 0) \
if (psa_get_initialized() == 0) \
return PSA_ERROR_BAD_STATE;
#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
@ -220,14 +284,14 @@ static psa_global_data_t global_data;
int psa_can_do_hash(psa_algorithm_t hash_alg)
{
(void) hash_alg;
return global_data.drivers_initialized;
return psa_get_drivers_initialized();
}
int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg)
{
(void) key_type;
(void) cipher_alg;
return global_data.drivers_initialized;
return psa_get_drivers_initialized();
}
@ -7630,6 +7694,9 @@ exit:
#endif
/** Initialize the PSA random generator.
*
* Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling
* this function if mutexes are enabled.
*/
static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng)
{
@ -7662,6 +7729,9 @@ static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng)
}
/** Deinitialize the PSA random generator.
*
* Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling
* this function if mutexes are enabled.
*/
static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng)
{
@ -7710,7 +7780,7 @@ exit:
psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
size_t seed_size)
{
if (global_data.initialized) {
if (psa_get_initialized()) {
return PSA_ERROR_NOT_PERMITTED;
}
@ -7952,28 +8022,77 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
void (* entropy_init)(mbedtls_entropy_context *ctx),
void (* entropy_free)(mbedtls_entropy_context *ctx))
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
if (global_data.rng_state != RNG_NOT_INITIALIZED) {
return PSA_ERROR_BAD_STATE;
status = PSA_ERROR_BAD_STATE;
} else {
global_data.rng.entropy_init = entropy_init;
global_data.rng.entropy_free = entropy_free;
status = PSA_SUCCESS;
}
global_data.rng.entropy_init = entropy_init;
global_data.rng.entropy_free = entropy_free;
return PSA_SUCCESS;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
return status;
}
#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
void mbedtls_psa_crypto_free(void)
{
psa_wipe_all_key_slots();
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
/* Nothing to do to free transaction. */
if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) {
global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
}
if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) {
psa_wipe_all_key_slots();
global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
}
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
if (global_data.rng_state != RNG_NOT_INITIALIZED) {
mbedtls_psa_random_free(&global_data.rng);
}
/* Wipe all remaining data, including configuration.
* In particular, this sets all state indicator to the value
* indicating "uninitialized". */
mbedtls_platform_zeroize(&global_data, sizeof(global_data));
global_data.rng_state = RNG_NOT_INITIALIZED;
mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng));
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
/* Terminate drivers */
psa_driver_wrapper_free();
if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) {
psa_driver_wrapper_free();
global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
}
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
}
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
@ -8001,57 +8120,171 @@ static psa_status_t psa_crypto_recover_transaction(
}
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem)
{
psa_status_t status = PSA_SUCCESS;
uint8_t driver_wrappers_initialized = 0;
switch (subsystem) {
case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS:
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) {
/* Init drivers */
status = psa_driver_wrapper_init();
/* Drivers need shutdown regardless of startup errors. */
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
&mbedtls_threading_psa_globaldata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
break;
case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS:
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) {
status = psa_initialize_key_slots();
/* Need to wipe keys even if initialization fails. */
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
&mbedtls_threading_psa_globaldata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
break;
case PSA_CRYPTO_SUBSYSTEM_RNG:
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
driver_wrappers_initialized =
(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED);
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
&mbedtls_threading_psa_globaldata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
/* Need to use separate mutex here, as initialisation can require
* testing of init flags, which requires locking the global data
* mutex. */
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
/* Initialize and seed the random generator. */
if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) {
mbedtls_psa_random_init(&global_data.rng);
global_data.rng_state = RNG_INITIALIZED;
status = mbedtls_psa_random_seed(&global_data.rng);
if (status == PSA_SUCCESS) {
global_data.rng_state = RNG_SEEDED;
}
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
&mbedtls_threading_psa_rngdata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
break;
case PSA_CRYPTO_SUBSYSTEM_TRANSACTION:
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) {
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
status = psa_crypto_load_transaction();
if (status == PSA_SUCCESS) {
status = psa_crypto_recover_transaction(&psa_crypto_transaction);
if (status == PSA_SUCCESS) {
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
}
status = psa_crypto_stop_transaction();
} else if (status == PSA_ERROR_DOES_NOT_EXIST) {
/* There's no transaction to complete. It's all good. */
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
status = PSA_SUCCESS;
}
#else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
status = PSA_SUCCESS;
#endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
&mbedtls_threading_psa_globaldata_mutex));
#endif /* defined(MBEDTLS_THREADING_C) */
break;
default:
status = PSA_ERROR_CORRUPTION_DETECTED;
}
/* Exit label only required when using threading macros. */
#if defined(MBEDTLS_THREADING_C)
exit:
#endif /* defined(MBEDTLS_THREADING_C) */
return status;
}
psa_status_t psa_crypto_init(void)
{
psa_status_t status;
/* Double initialization is explicitly allowed. */
if (global_data.initialized != 0) {
/* Double initialization is explicitly allowed. Early out if everything is
* done. */
if (psa_get_initialized()) {
return PSA_SUCCESS;
}
/* Init drivers */
status = psa_driver_wrapper_init();
if (status != PSA_SUCCESS) {
goto exit;
}
global_data.drivers_initialized = 1;
status = psa_initialize_key_slots();
status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS);
if (status != PSA_SUCCESS) {
goto exit;
}
/* Initialize and seed the random generator. */
mbedtls_psa_random_init(&global_data.rng);
global_data.rng_state = RNG_INITIALIZED;
status = mbedtls_psa_random_seed(&global_data.rng);
status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS);
if (status != PSA_SUCCESS) {
goto exit;
}
global_data.rng_state = RNG_SEEDED;
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
status = psa_crypto_load_transaction();
if (status == PSA_SUCCESS) {
status = psa_crypto_recover_transaction(&psa_crypto_transaction);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_crypto_stop_transaction();
} else if (status == PSA_ERROR_DOES_NOT_EXIST) {
/* There's no transaction to complete. It's all good. */
status = PSA_SUCCESS;
status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG);
if (status != PSA_SUCCESS) {
goto exit;
}
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
/* All done. */
global_data.initialized = 1;
status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION);
exit:
if (status != PSA_SUCCESS) {
mbedtls_psa_crypto_free();
}
return status;
}

View File

@ -34,6 +34,23 @@ typedef struct {
static psa_global_data_t global_data;
static uint8_t psa_get_key_slots_initialized(void)
{
uint8_t initialized;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
initialized = global_data.key_slots_initialized;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
#endif /* defined(MBEDTLS_THREADING_C) */
return initialized;
}
int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok)
{
psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
@ -136,7 +153,9 @@ psa_status_t psa_initialize_key_slots(void)
{
/* Nothing to do: program startup and psa_wipe_all_key_slots() both
* guarantee that the key slots are initialized to all-zero, which
* means that all the key slots are in a valid, empty state. */
* means that all the key slots are in a valid, empty state. The global
* data mutex is already held when calling this function, so no need to
* lock it here, to set the flag. */
global_data.key_slots_initialized = 1;
return PSA_SUCCESS;
}
@ -151,6 +170,7 @@ void psa_wipe_all_key_slots(void)
slot->state = PSA_SLOT_PENDING_DELETION;
(void) psa_wipe_key_slot(slot);
}
/* The global data mutex is already held when calling this function. */
global_data.key_slots_initialized = 0;
}
@ -161,7 +181,7 @@ psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
size_t slot_idx;
psa_key_slot_t *selected_slot, *unused_persistent_key_slot;
if (!global_data.key_slots_initialized) {
if (!psa_get_key_slots_initialized()) {
status = PSA_ERROR_BAD_STATE;
goto error;
}
@ -344,7 +364,7 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
*p_slot = NULL;
if (!global_data.key_slots_initialized) {
if (!psa_get_key_slots_initialized()) {
return PSA_ERROR_BAD_STATE;
}

View File

@ -231,8 +231,9 @@ typedef uint16_t psa_crypto_transaction_type_t;
* This type is designed to be serialized by writing the memory representation
* and reading it back on the same device.
*
* \note The transaction mechanism is designed for a single active transaction
* at a time. The transaction object is #psa_crypto_transaction.
* \note The transaction mechanism is not thread-safe. There can only be one
* single active transaction at a time.
* The transaction object is #psa_crypto_transaction.
*
* \note If an API call starts a transaction, it must complete this transaction
* before returning to the application.

View File

@ -2231,7 +2231,7 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
}
if (ctx->hash_id == MBEDTLS_MD_NONE) {
if ((ctx->hash_id == MBEDTLS_MD_NONE) && (md_alg == MBEDTLS_MD_NONE)) {
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
}
return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen,

View File

@ -792,10 +792,15 @@ static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl)
(ssl->handshake->cookie == NULL))
#endif
{
ret = ssl_generate_random(ssl);
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret);
return ret;
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
if (!ssl->handshake->hello_retry_request_flag)
#endif
{
ret = ssl_generate_random(ssl);
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret);
return ret;
}
}
}

View File

@ -23,6 +23,7 @@ const char *mbedtls_ssl_states_str(mbedtls_ssl_states in);
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in);
const char *mbedtls_ssl_early_data_state_str(mbedtls_ssl_early_data_state in);
#endif
const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in);

View File

@ -2153,6 +2153,57 @@ int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,
size_t early_data_len);
typedef enum {
/*
* The client has not sent the first ClientHello yet, the negotiation of early
* data has not started yet.
*/
MBEDTLS_SSL_EARLY_DATA_STATE_IDLE,
/*
* In its ClientHello, the client has not included an early data indication
* extension.
*/
MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT,
/*
* The client has sent an early data indication extension in its first
* ClientHello, it has not received the response (ServerHello or
* HelloRetryRequest) from the server yet. The transform to protect early data
* is not set either as for middlebox compatibility a dummy CCS may have to be
* sent in clear. Early data cannot be sent to the server yet.
*/
MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT,
/*
* The client has sent an early data indication extension in its first
* ClientHello, it has not received the response (ServerHello or
* HelloRetryRequest) from the server yet. The transform to protect early data
* has been set and early data can be written now.
*/
MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE,
/*
* The client has indicated the use of early data and the server has accepted
* it.
*/
MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED,
/*
* The client has indicated the use of early data but the server has rejected
* it.
*/
MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED,
/*
* The client has sent an early data indication extension in its first
* ClientHello, the server has accepted them and the client has received the
* server Finished message. It cannot send early data to the server anymore.
*/
MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED,
} mbedtls_ssl_early_data_state;
#endif /* MBEDTLS_SSL_EARLY_DATA */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
@ -2801,6 +2852,13 @@ int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,
const char *hostname);
#endif
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \
defined(MBEDTLS_SSL_ALPN)
MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,
const char *alpn);
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
#define MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME (604800)

View File

@ -6074,7 +6074,7 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const struct mbedtls_ssl_config *conf;
int written_data_len = 0;
uint32_t remaining;
MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data"));
@ -6097,21 +6097,21 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
}
/*
* If we are at the beginning of the handshake, the early data status being
* equal to MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN or
* MBEDTLS_SSL_EARLY_DATA_STATUS_SENT advance the handshake just
* If we are at the beginning of the handshake, the early data state being
* equal to MBEDTLS_SSL_EARLY_DATA_STATE_IDLE or
* MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT advance the handshake just
* enough to be able to send early data if possible. That way, we can
* guarantee that when starting the handshake with this function we will
* send at least one record of early data. Note that when the status is
* MBEDTLS_SSL_EARLY_DATA_STATUS_SENT and not yet
* MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE, we cannot send early data yet
* send at least one record of early data. Note that when the state is
* MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT and not yet
* MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, we cannot send early data
* as the early data outbound transform has not been set as we may have to
* first send a dummy CCS in clear.
*/
if ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) ||
(ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) {
while ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) ||
(ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) {
if ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||
(ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {
while ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||
(ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {
ret = mbedtls_ssl_handshake_step(ssl);
if (ret != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret);
@ -6124,15 +6124,24 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
return ret;
}
}
remaining = ssl->session_negotiate->max_early_data_size;
} else {
/*
* If we are past the point where we can send early data, return
* immediatly. Otherwise, progress the handshake as much as possible to
* not delay it too much. If we reach a point where we can still send
* early data, then we will send some.
* If we are past the point where we can send early data or we have
* already reached the maximum early data size, return immediatly.
* Otherwise, progress the handshake as much as possible to not delay
* it too much. If we reach a point where we can still send early data,
* then we will send some.
*/
if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) &&
(ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) {
if ((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&
(ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) {
return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
}
remaining = ssl->session_negotiate->max_early_data_size -
ssl->total_early_data_size;
if (remaining == 0) {
return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
}
@ -6143,16 +6152,24 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
}
}
if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) &&
(ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) {
if (((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&
(ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED))
|| (remaining == 0)) {
return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
}
written_data_len = ssl_write_real(ssl, buf, len);
if (len > remaining) {
len = remaining;
}
MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, len=%d", written_data_len));
ret = ssl_write_real(ssl, buf, len);
if (ret >= 0) {
ssl->total_early_data_size += ret;
}
return written_data_len;
MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, ret=%d", ret));
return ret;
}
#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */

View File

@ -504,7 +504,7 @@ int mbedtls_ssl_ticket_parse(void *p_ticket,
#if defined(MBEDTLS_HAVE_TIME)
mbedtls_ms_time_t ticket_creation_time, ticket_age;
mbedtls_ms_time_t ticket_lifetime =
(mbedtls_ms_time_t) ctx->ticket_lifetime * 1000;
(mbedtls_ms_time_t) key->lifetime * 1000;
ret = mbedtls_ssl_session_get_ticket_creation_time(session,
&ticket_creation_time);

View File

@ -238,6 +238,11 @@ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst,
#endif
#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \
defined(MBEDTLS_SSL_EARLY_DATA)
dst->ticket_alpn = NULL;
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C)
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
@ -275,6 +280,16 @@ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst,
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \
defined(MBEDTLS_SSL_EARLY_DATA)
{
int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn);
if (ret != 0) {
return ret;
}
}
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN && MBEDTLS_SSL_EARLY_DATA */
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
if (src->ticket != NULL) {
dst->ticket = mbedtls_calloc(1, src->ticket_len);
@ -1096,7 +1111,7 @@ static int ssl_handshake_init(mbedtls_ssl_context *ssl)
#if defined(MBEDTLS_SSL_EARLY_DATA)
#if defined(MBEDTLS_SSL_CLI_C)
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN;
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IDLE;
#endif
#if defined(MBEDTLS_SSL_SRV_C)
ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
@ -3751,9 +3766,16 @@ static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
size_t hostname_len = (session->hostname == NULL) ?
0 : strlen(session->hostname) + 1;
#endif
#if defined(MBEDTLS_SSL_SRV_C) && \
defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
const size_t alpn_len = (session->ticket_alpn == NULL) ?
0 : strlen(session->ticket_alpn) + 1;
#endif
size_t needed = 4 /* ticket_age_add */
+ 1 /* ticket_flags */
+ 1; /* resumption_key length */
*olen = 0;
if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {
@ -3772,6 +3794,15 @@ static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
needed += 8; /* ticket_creation_time or ticket_reception_time */
#endif
#if defined(MBEDTLS_SSL_SRV_C)
if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
needed += 2 /* alpn_len */
+ alpn_len; /* alpn */
#endif
}
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_CLI_C)
if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@ -3814,13 +3845,26 @@ static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
p += 2;
#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
#if defined(MBEDTLS_SSL_SRV_C)
if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
#if defined(MBEDTLS_HAVE_TIME)
MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);
p += 8;
}
#endif /* MBEDTLS_HAVE_TIME */
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
MBEDTLS_PUT_UINT16_BE(alpn_len, p, 0);
p += 2;
if (alpn_len > 0) {
/* save chosen alpn */
memcpy(p, session->ticket_alpn, alpn_len);
p += alpn_len;
}
#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
}
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_CLI_C)
if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@ -3895,16 +3939,41 @@ static int ssl_tls13_session_load(mbedtls_ssl_session *session,
p += 2;
#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
#if defined(MBEDTLS_SSL_SRV_C)
if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
#if defined(MBEDTLS_HAVE_TIME)
if (end - p < 8) {
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);
p += 8;
}
#endif /* MBEDTLS_HAVE_TIME */
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
size_t alpn_len;
if (end - p < 2) {
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
alpn_len = MBEDTLS_GET_UINT16_BE(p, 0);
p += 2;
if (end - p < (long int) alpn_len) {
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
if (alpn_len > 0) {
int ret = mbedtls_ssl_session_set_ticket_alpn(session, (char *) p);
if (ret != 0) {
return ret;
}
p += alpn_len;
}
#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
}
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_CLI_C)
if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@ -4061,6 +4130,13 @@ static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 0
#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) && \
defined(MBEDTLS_SSL_EARLY_DATA)
#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 1
#else
#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 0
#endif /* MBEDTLS_SSL_ALPN */
#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0
#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1
#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2
@ -4071,6 +4147,7 @@ static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
#define SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT 7
#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT 8
#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT 9
#define SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT 10
#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \
((uint16_t) ( \
@ -4087,7 +4164,9 @@ static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
(SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA << \
SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT) | \
(SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE << \
SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT)))
SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT) | \
(SSL_SERIALIZED_SESSION_CONFIG_ALPN << \
SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT)))
static const unsigned char ssl_serialized_session_header[] = {
MBEDTLS_VERSION_MAJOR,
@ -4162,8 +4241,12 @@ static const unsigned char ssl_serialized_session_header[] = {
* #endif
* select ( endpoint ) {
* case client: ClientOnlyData;
* case server:
* #if defined(MBEDTLS_HAVE_TIME)
* case server: uint64 ticket_creation_time;
* uint64 ticket_creation_time;
* #endif
* #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
* opaque ticket_alpn<0..256>;
* #endif
* };
* } serialized_session_tls13;
@ -4853,6 +4936,11 @@ void mbedtls_ssl_session_free(mbedtls_ssl_session *session)
mbedtls_free(session->ticket);
#endif
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && \
defined(MBEDTLS_SSL_SRV_C)
mbedtls_free(session->ticket_alpn);
#endif
mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session));
}
@ -5351,7 +5439,7 @@ static int ssl_context_load(mbedtls_ssl_context *ssl,
/* alpn_chosen should point to an item in the configured list */
for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) {
if (strlen(*cur) == alpn_len &&
memcmp(p, cur, alpn_len) == 0) {
memcmp(p, *cur, alpn_len) == 0) {
ssl->alpn_chosen = *cur;
break;
}
@ -9799,4 +9887,36 @@ int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,
MBEDTLS_SSL_SERVER_NAME_INDICATION &&
MBEDTLS_SSL_CLI_C */
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \
defined(MBEDTLS_SSL_ALPN)
int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,
const char *alpn)
{
size_t alpn_len = 0;
if (alpn != NULL) {
alpn_len = strlen(alpn);
if (alpn_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) {
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
}
if (session->ticket_alpn != NULL) {
mbedtls_zeroize_and_free(session->ticket_alpn,
strlen(session->ticket_alpn));
session->ticket_alpn = NULL;
}
if (alpn != NULL) {
session->ticket_alpn = mbedtls_calloc(alpn_len + 1, 1);
if (session->ticket_alpn == NULL) {
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
}
memcpy(session->ticket_alpn, alpn, alpn_len);
}
return 0;
}
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
#endif /* MBEDTLS_SSL_TLS_C */

View File

@ -1181,12 +1181,12 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_EARLY_DATA)
/* In the first ClientHello, write the early data indication extension if
* necessary and update the early data status.
* necessary and update the early data state.
* If an HRR has been received and thus we are currently writing the
* second ClientHello, the second ClientHello must not contain an early
* data extension and the early data status must stay as it is:
* MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT or
* MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED.
* data extension and the early data state must stay as it is:
* MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT or
* MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED.
*/
if (!ssl->handshake->hello_retry_request_flag) {
if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&
@ -1199,9 +1199,9 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
}
p += ext_len;
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SENT;
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT;
} else {
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT;
}
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@ -1239,7 +1239,7 @@ int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl)
size_t psk_len;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT) {
if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT) {
MBEDTLS_SSL_DEBUG_MSG(
1, ("Set hs psk for early data when writing the first psk"));
@ -1302,7 +1302,7 @@ int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl)
1, ("Switch to early data keys for outbound traffic"));
mbedtls_ssl_set_outbound_transform(
ssl, ssl->handshake->transform_earlydata);
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE;
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE;
#endif
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@ -1919,7 +1919,7 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
* cases we compute it here.
*/
#if defined(MBEDTLS_SSL_EARLY_DATA)
if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT ||
if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT ||
handshake->key_exchange_mode ==
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL)
#endif
@ -1975,8 +1975,8 @@ static int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl)
ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id;
#if defined(MBEDTLS_SSL_EARLY_DATA)
if (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) {
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED;
}
#endif
@ -2238,9 +2238,10 @@ static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl)
return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
}
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
} else if (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) {
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED;
} else if (ssl->early_data_state !=
MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED;
}
#endif
@ -2324,16 +2325,16 @@ int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl)
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
switch (ssl->early_data_status) {
case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT:
return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
switch (ssl->early_data_state) {
case MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT:
return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED;
break;
case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED:
case MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED:
return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
break;
case MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED:
case MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED:
return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
break;
@ -2604,8 +2605,8 @@ static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl)
}
#if defined(MBEDTLS_SSL_EARLY_DATA)
if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED;
if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED) {
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED;
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);
} else
#endif /* MBEDTLS_SSL_EARLY_DATA */
@ -2916,12 +2917,17 @@ static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl,
return ret;
}
/* session has been updated, allow export */
session->exported = 0;
return 0;
}
/* Non negative return values for ssl_tls13_postprocess_new_session_ticket().
* - POSTPROCESS_NEW_SESSION_TICKET_SIGNAL, all good, we have to signal the
* application that a valid ticket has been received.
* - POSTPROCESS_NEW_SESSION_TICKET_DISCARD, no fatal error, we keep the
* connection alive but we do not signal the ticket to the application.
*/
#define POSTPROCESS_NEW_SESSION_TICKET_SIGNAL 0
#define POSTPROCESS_NEW_SESSION_TICKET_DISCARD 1
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
unsigned char *ticket_nonce,
@ -2933,6 +2939,10 @@ static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
psa_algorithm_t psa_hash_alg;
int hash_length;
if (session->ticket_lifetime == 0) {
return POSTPROCESS_NEW_SESSION_TICKET_DISCARD;
}
#if defined(MBEDTLS_HAVE_TIME)
/* Store ticket creation time */
session->ticket_reception_time = mbedtls_ms_time();
@ -2989,7 +2999,7 @@ static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
session, ssl->conf->tls13_kex_modes);
MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
return 0;
return POSTPROCESS_NEW_SESSION_TICKET_SIGNAL;
}
/*
@ -3010,12 +3020,37 @@ static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl)
ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
&buf, &buf_len));
/*
* We are about to update (maybe only partially) ticket data thus block
* any session export for the time being.
*/
ssl->session->exported = 1;
MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket(
ssl, buf, buf + buf_len,
&ticket_nonce, &ticket_nonce_len));
MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_new_session_ticket(
ssl, ticket_nonce, ticket_nonce_len));
MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_postprocess_new_session_ticket(
ssl, ticket_nonce, ticket_nonce_len));
switch (ret) {
case POSTPROCESS_NEW_SESSION_TICKET_SIGNAL:
/*
* All good, we have received a new valid ticket, session data can
* be exported now and we signal the ticket to the application.
*/
ssl->session->exported = 0;
ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;
break;
case POSTPROCESS_NEW_SESSION_TICKET_DISCARD:
ret = 0;
MBEDTLS_SSL_DEBUG_MSG(2, ("Discard new session ticket"));
break;
default:
ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
@ -3123,7 +3158,7 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)
1, ("Switch to early data keys for outbound traffic"));
mbedtls_ssl_set_outbound_transform(
ssl, ssl->handshake->transform_earlydata);
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE;
ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE;
}
break;
#endif /* MBEDTLS_SSL_EARLY_DATA */
@ -3132,10 +3167,6 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:
ret = ssl_tls13_process_new_session_ticket(ssl);
if (ret != 0) {
break;
}
ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;
break;
#endif /* MBEDTLS_SSL_SESSION_TICKETS */

View File

@ -473,7 +473,14 @@ static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst,
#if defined(MBEDTLS_SSL_EARLY_DATA)
dst->max_early_data_size = src->max_early_data_size;
#endif
#if defined(MBEDTLS_SSL_ALPN)
int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn);
if (ret != 0) {
return ret;
}
#endif /* MBEDTLS_SSL_ALPN */
#endif /* MBEDTLS_SSL_EARLY_DATA*/
return 0;
}
@ -1818,7 +1825,6 @@ static int ssl_tls13_check_early_data_requirements(mbedtls_ssl_context *ssl)
* NOTE:
* - The TLS version number is checked in
* ssl_tls13_offered_psks_check_identity_match_ticket().
* - ALPN is not checked for the time being (TODO).
*/
if (handshake->selected_identity != 0) {
@ -1845,6 +1851,28 @@ static int ssl_tls13_check_early_data_requirements(mbedtls_ssl_context *ssl)
return -1;
}
#if defined(MBEDTLS_SSL_ALPN)
const char *alpn = mbedtls_ssl_get_alpn_protocol(ssl);
size_t alpn_len;
if (alpn == NULL && ssl->session_negotiate->ticket_alpn == NULL) {
return 0;
}
if (alpn != NULL) {
alpn_len = strlen(alpn);
}
if (alpn == NULL ||
ssl->session_negotiate->ticket_alpn == NULL ||
alpn_len != strlen(ssl->session_negotiate->ticket_alpn) ||
(memcmp(alpn, ssl->session_negotiate->ticket_alpn, alpn_len) != 0)) {
MBEDTLS_SSL_DEBUG_MSG(1, ("EarlyData: rejected, the selected ALPN is different "
"from the one associated with the pre-shared key."));
return -1;
}
#endif
return 0;
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@ -3143,6 +3171,15 @@ static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,
MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
if (session->ticket_alpn == NULL) {
ret = mbedtls_ssl_session_set_ticket_alpn(session, ssl->alpn_chosen);
if (ret != 0) {
return ret;
}
}
#endif
/* Generate ticket_age_add */
if ((ret = ssl->conf->f_rng(ssl->conf->p_rng,
(unsigned char *) &session->ticket_age_add,
@ -3272,20 +3309,21 @@ static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_RET(1, "write_ticket", ret);
return ret;
}
/* RFC 8446 4.6.1
/* RFC 8446 section 4.6.1
*
* ticket_lifetime: Indicates the lifetime in seconds as a 32-bit
* unsigned integer in network byte order from the time of ticket
* issuance. Servers MUST NOT use any value greater than
* 604800 seconds (7 days). The value of zero indicates that the
* ticket should be discarded immediately. Clients MUST NOT cache
* tickets for longer than 7 days, regardless of the ticket_lifetime,
* and MAY delete tickets earlier based on local policy. A server
* MAY treat a ticket as valid for a shorter period of time than what
* is stated in the ticket_lifetime.
* unsigned integer in network byte order from the time of ticket
* issuance. Servers MUST NOT use any value greater than
* 604800 seconds (7 days) ...
*/
if (ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) {
ticket_lifetime = MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME;
MBEDTLS_SSL_DEBUG_MSG(
1, ("Ticket lifetime (%u) is greater than 7 days.",
(unsigned int) ticket_lifetime));
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0);
MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u",
(unsigned int) ticket_lifetime));

View File

@ -150,6 +150,8 @@ void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *),
#endif
#if defined(MBEDTLS_PSA_CRYPTO_C)
mbedtls_mutex_init(&mbedtls_threading_key_slot_mutex);
mbedtls_mutex_init(&mbedtls_threading_psa_globaldata_mutex);
mbedtls_mutex_init(&mbedtls_threading_psa_rngdata_mutex);
#endif
}
@ -166,6 +168,8 @@ void mbedtls_threading_free_alt(void)
#endif
#if defined(MBEDTLS_PSA_CRYPTO_C)
mbedtls_mutex_free(&mbedtls_threading_key_slot_mutex);
mbedtls_mutex_free(&mbedtls_threading_psa_globaldata_mutex);
mbedtls_mutex_free(&mbedtls_threading_psa_rngdata_mutex);
#endif
}
#endif /* MBEDTLS_THREADING_ALT */
@ -184,6 +188,8 @@ mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
#endif
#if defined(MBEDTLS_PSA_CRYPTO_C)
mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex MUTEX_INIT;
mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex MUTEX_INIT;
mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex MUTEX_INIT;
#endif
#endif /* MBEDTLS_THREADING_C */