aboutsummaryrefslogtreecommitdiff
path: root/library
diff options
context:
space:
mode:
Diffstat (limited to 'library')
-rw-r--r--library/CMakeLists.txt1
-rw-r--r--library/Makefile29
-rw-r--r--library/cmac.c26
-rw-r--r--library/gcm.c9
-rw-r--r--library/pk.c182
-rw-r--r--library/pk_ecc.c255
-rw-r--r--library/pk_internal.h56
-rw-r--r--library/pk_wrap.c9
-rw-r--r--library/pkparse.c314
-rw-r--r--library/psa_crypto_storage.h5
-rw-r--r--library/rsa.c2
-rw-r--r--library/sha3.c117
-rw-r--r--library/ssl_client.c13
-rw-r--r--library/ssl_debug_helpers.h1
-rw-r--r--library/ssl_misc.h58
-rw-r--r--library/ssl_msg.c61
-rw-r--r--library/ssl_ticket.c2
-rw-r--r--library/ssl_tls.c136
-rw-r--r--library/ssl_tls13_client.c95
-rw-r--r--library/ssl_tls13_server.c62
20 files changed, 996 insertions, 437 deletions
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 47ecf17..835604f 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -56,6 +56,7 @@ set(src_crypto
padlock.c
pem.c
pk.c
+ pk_ecc.c
pk_wrap.c
pkcs12.c
pkcs5.c
diff --git a/library/Makefile b/library/Makefile
index d11a98d..52d7944 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -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
diff --git a/library/cmac.c b/library/cmac.c
index f40cae2..c4f0b54 100644
--- a/library/cmac.c
+++ b/library/cmac.c
@@ -56,22 +56,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, mask;
- 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;
}
/* mask = ( input[0] >> 7 ) ? 0xff : 0x00
@@ -217,6 +224,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 &&
@@ -284,6 +295,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));
diff --git a/library/gcm.c b/library/gcm.c
index 90c1d1d..5dfac23 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -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;
diff --git a/library/pk.c b/library/pk.c
index 003ef4a..ec3741b 100644
--- a/library/pk.c
+++ b/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
@@ -1017,7 +1156,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 +1322,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 +1333,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;
}
diff --git a/library/pk_ecc.c b/library/pk_ecc.c
new file mode 100644
index 0000000..86218ff
--- /dev/null
+++ b/library/pk_ecc.c
@@ -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 */
diff --git a/library/pk_internal.h b/library/pk_internal.h
index f5924ad..e86a3a0 100644
--- a/library/pk_internal.h
+++ b/library/pk_internal.h
@@ -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 */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 846175e..256863a 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -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);
diff --git a/library/pkparse.c b/library/pkparse.c
index 5a3d3b2..4f6ee13 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -46,302 +46,6 @@
/***********************************************************************
*
- * 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
*
* There are two functions here that are used by the rest of the code:
@@ -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;
}
}
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index f1ea265..d7f5b18 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -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.
diff --git a/library/rsa.c b/library/rsa.c
index 5debc69..7eb4a25 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -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,
diff --git a/library/sha3.c b/library/sha3.c
index 27d495f..5738559 100644
--- a/library/sha3.c
+++ b/library/sha3.c
@@ -14,6 +14,33 @@
#if defined(MBEDTLS_SHA3_C)
+/*
+ * These macros select manually unrolled implementations of parts of the main permutation function.
+ *
+ * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot
+ * from manually unrolling at higher optimisation levels.
+ *
+ * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust
+ * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and
+ * x86-64.
+ */
+#if !defined(MBEDTLS_SHA3_THETA_UNROLL)
+ #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names
+#endif
+#if !defined(MBEDTLS_SHA3_CHI_UNROLL)
+ #if defined(__OPTIMIZE_SIZE__)
+ #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names
+ #else
+ #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names
+ #endif
+#endif
+#if !defined(MBEDTLS_SHA3_PI_UNROLL)
+ #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names
+#endif
+#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
+ #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names
+#endif
+
#include "mbedtls/sha3.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
@@ -56,18 +83,15 @@ static const uint8_t iota_r_packed[24] = {
};
#undef H
-static const uint8_t rho[24] = {
- 1, 62, 28, 27, 36, 44, 6, 55, 20,
- 3, 10, 43, 25, 39, 41, 45, 15,
- 21, 8, 18, 2, 61, 56, 14
+static const uint32_t rho[6] = {
+ 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
};
-static const uint8_t pi[24] = {
- 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
- 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
+static const uint32_t pi[6] = {
+ 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916
};
-#define ROT64(x, y) (((x) << (y)) | ((x) >> (64U - (y))))
+#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
} while (0)
#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
@@ -84,39 +108,97 @@ static void keccak_f1600(mbedtls_sha3_context *ctx)
uint64_t t;
/* Theta */
+#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names
+ for (i = 0; i < 5; i++) {
+ lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
+ }
+ for (i = 0; i < 5; i++) {
+ t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
+ s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
+ }
+#else
lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
- t = lane[4] ^ ROT64(lane[1], 1);
+ t = lane[4] ^ ROTR64(lane[1], 63);
s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
- t = lane[0] ^ ROT64(lane[2], 1);
+ t = lane[0] ^ ROTR64(lane[2], 63);
s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
- t = lane[1] ^ ROT64(lane[3], 1);
+ t = lane[1] ^ ROTR64(lane[3], 63);
s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
- t = lane[2] ^ ROT64(lane[4], 1);
+ t = lane[2] ^ ROTR64(lane[4], 63);
s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
- t = lane[3] ^ ROT64(lane[0], 1);
+ t = lane[3] ^ ROTR64(lane[0], 63);
s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
+#endif
/* Rho */
- for (i = 1; i < 25; i++) {
- s[i] = ROT64(s[i], rho[i-1]);
+ for (i = 1; i < 25; i += 4) {
+ uint32_t r = rho[(i - 1) >> 2];
+#if MBEDTLS_SHA3_RHO_UNROLL == 0
+ for (int j = i; j < i + 4; j++) {
+ uint8_t r8 = (uint8_t) (r >> 24);
+ r <<= 8;
+ s[j] = ROTR64(s[j], r8);
+ }
+#else
+ s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
+ s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
+ s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
+ s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
+#endif
}
/* Pi */
t = s[1];
- for (i = 0; i < 24; i++) {
- SWAP(s[pi[i]], t);
+#if MBEDTLS_SHA3_PI_UNROLL == 0
+ for (i = 0; i < 24; i += 4) {
+ uint32_t p = pi[i >> 2];
+ for (unsigned j = 0; j < 4; j++) {
+ SWAP(s[p & 0xff], t);
+ p >>= 8;
+ }
}
+#else
+ uint32_t p = pi[0];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[1];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[2];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[3];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[4];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[5];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+#endif
/* Chi */
+#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
+ for (i = 0; i <= 20; i += 5) {
+ lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
+ lane[3] = s[i + 3]; lane[4] = s[i + 4];
+ s[i + 0] ^= (~lane[1]) & lane[2];
+ s[i + 1] ^= (~lane[2]) & lane[3];
+ s[i + 2] ^= (~lane[3]) & lane[4];
+ s[i + 3] ^= (~lane[4]) & lane[0];
+ s[i + 4] ^= (~lane[0]) & lane[1];
+ }
+#else
lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
s[0] ^= (~lane[1]) & lane[2];
s[1] ^= (~lane[2]) & lane[3];
@@ -151,6 +233,7 @@ static void keccak_f1600(mbedtls_sha3_context *ctx)
s[22] ^= (~lane[3]) & lane[4];
s[23] ^= (~lane[4]) & lane[0];
s[24] ^= (~lane[0]) & lane[1];
+#endif
/* Iota */
/* Decompress the round masks (see definition of rc) */
diff --git a/library/ssl_client.c b/library/ssl_client.c
index 8892acf..345e608 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -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;
+ }
}
}
diff --git a/library/ssl_debug_helpers.h b/library/ssl_debug_helpers.h
index a8e3140..4889e77 100644
--- a/library/ssl_debug_helpers.h
+++ b/library/ssl_debug_helpers.h
@@ -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);
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 883b988..a8807f6 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -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)
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 0c71157..b07cd96 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -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 */
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index 5da3887..6a31b0b 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.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);
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 1bfd180..ac53853 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -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;
@@ -3750,9 +3765,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) {
@@ -3771,6 +3793,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)
@@ -3813,13 +3844,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)
@@ -3894,16 +3938,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)
@@ -4060,6 +4129,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
@@ -4070,6 +4146,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) ( \
@@ -4086,7 +4163,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,
@@ -4161,8 +4240,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;
@@ -4852,6 +4935,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));
}
@@ -5350,7 +5438,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;
}
@@ -9798,4 +9886,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 */
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 88d6c9e..7fcc394 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.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 */
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 887c5c6..e8afe45 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -467,7 +467,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;
}
@@ -1812,7 +1819,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) {
@@ -1839,6 +1845,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 */
@@ -3137,6 +3165,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,
@@ -3266,20 +3303,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));