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:
@ -56,6 +56,7 @@ set(src_crypto
|
||||
padlock.c
|
||||
pem.c
|
||||
pk.c
|
||||
pk_ecc.c
|
||||
pk_wrap.c
|
||||
pkcs12.c
|
||||
pkcs5.c
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
188
library/pk.c
188
library/pk.c
@ -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
255
library/pk_ecc.c
Normal 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 */
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
|
Reference in New Issue
Block a user