1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-29 11:41:15 +03:00

Merge remote-tracking branch 'development' into pk_import_into_psa-implement_import

Conflicts:
* tests/suites/test_suite_pk.function: consecutive changes to the
  depends_on line of pk_sign_verify and its argument list.
This commit is contained in:
Gilles Peskine
2024-02-21 12:10:40 +01:00
79 changed files with 2428 additions and 768 deletions

View File

@ -334,7 +334,7 @@ static void aesce_setkey_enc(unsigned char *rk,
* - Section 5, Nr = Nk + 6
* - Section 5.2, the length of round keys is Nb*(Nr+1)
*/
const uint32_t key_len_in_words = key_bit_length / 32; /* Nk */
const size_t key_len_in_words = key_bit_length / 32; /* Nk */
const size_t round_key_len_in_words = 4; /* Nb */
const size_t rounds_needed = key_len_in_words + 6; /* Nr */
const size_t round_keys_len_in_words =

View File

@ -65,7 +65,8 @@ static int local_err_translation(psa_status_t status)
#define H_TREE_HEIGHT_MAX 10
#define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
#define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \
(1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)))
#define D_CONST_LEN (2)
static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };

View File

@ -683,6 +683,18 @@ static const oid_cipher_alg_t oid_cipher_alg[] =
OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC"),
MBEDTLS_CIPHER_DES_EDE3_CBC,
},
{
OID_DESCRIPTOR(MBEDTLS_OID_AES_128_CBC, "aes128-cbc", "AES128-CBC"),
MBEDTLS_CIPHER_AES_128_CBC,
},
{
OID_DESCRIPTOR(MBEDTLS_OID_AES_192_CBC, "aes192-cbc", "AES192-CBC"),
MBEDTLS_CIPHER_AES_192_CBC,
},
{
OID_DESCRIPTOR(MBEDTLS_OID_AES_256_CBC, "aes256-cbc", "AES256-CBC"),
MBEDTLS_CIPHER_AES_256_CBC,
},
{
NULL_OID_DESCRIPTOR,
MBEDTLS_CIPHER_NONE,

View File

@ -240,6 +240,29 @@ exit:
}
#endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)
static int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len)
{
/* input_len > 0 is guaranteed by mbedtls_pem_read_buffer(). */
size_t pad_len = input[input_len - 1];
size_t i;
if (pad_len > input_len) {
return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
}
*data_len = input_len - pad_len;
for (i = *data_len; i < input_len; i++) {
if (input[i] != pad_len) {
return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
}
}
return 0;
}
#endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */
#endif /* PEM_RFC1421 */
int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,
@ -389,6 +412,10 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
}
if (len == 0) {
return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
}
if ((buf = mbedtls_calloc(1, len)) == NULL) {
return MBEDTLS_ERR_PEM_ALLOC_FAILED;
}
@ -426,20 +453,20 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
#endif /* MBEDTLS_AES_C */
if (ret != 0) {
mbedtls_free(buf);
mbedtls_zeroize_and_free(buf, len);
return ret;
}
/*
* The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
* length bytes (allow 4 to be sure) in all known use cases.
*
* Use that as a heuristic to try to detect password mismatches.
*/
if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) {
/* Check PKCS padding and update data length based on padding info.
* This can be used to detect invalid padding data and password
* mismatches. */
size_t unpadded_len;
ret = pem_check_pkcs_padding(buf, len, &unpadded_len);
if (ret != 0) {
mbedtls_zeroize_and_free(buf, len);
return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
return ret;
}
len = unpadded_len;
#else
mbedtls_zeroize_and_free(buf, len);
return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;

View File

@ -383,7 +383,7 @@ static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,
{
if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
if (want_crypt) {
mbedtls_md_type_t md_type = mbedtls_rsa_get_md_alg(rsa);
mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa);
return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type));
} else {
return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH);

View File

@ -58,7 +58,7 @@ static int rsa_can_do(mbedtls_pk_type_t type)
static size_t rsa_get_bitlen(mbedtls_pk_context *pk)
{
const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx;
return 8 * mbedtls_rsa_get_len(rsa);
return mbedtls_rsa_get_bitlen(rsa);
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
@ -74,8 +74,7 @@ static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
int key_len;
unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
unsigned char *p = buf + sizeof(buf);
psa_algorithm_t psa_alg_md =
PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
psa_algorithm_t psa_alg_md;
size_t rsa_len = mbedtls_rsa_get_len(rsa);
#if SIZE_MAX > UINT_MAX
@ -84,6 +83,12 @@ static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
}
#endif
if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
psa_alg_md = PSA_ALG_RSA_PSS(mbedtls_md_psa_alg_from_type(md_alg));
} else {
psa_alg_md = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
}
if (sig_len < rsa_len) {
return MBEDTLS_ERR_RSA_VERIFY_FAILED;
}
@ -235,10 +240,14 @@ static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
if (psa_md_alg == 0) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
psa_algorithm_t psa_alg;
if (mbedtls_rsa_get_padding_mode(mbedtls_pk_rsa(*pk)) == MBEDTLS_RSA_PKCS_V21) {
psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
} else {
psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg);
}
return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN(
psa_md_alg),
pk->pk_ctx, hash, hash_len,
return mbedtls_pk_psa_rsa_sign_ext(psa_alg, pk->pk_ctx, hash, hash_len,
sig, sig_size, sig_len);
}
#else /* MBEDTLS_USE_PSA_CRYPTO */
@ -276,6 +285,7 @@ static int rsa_decrypt_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, decrypt_alg;
psa_status_t status;
int key_len;
unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
@ -284,12 +294,6 @@ static int rsa_decrypt_wrap(mbedtls_pk_context *pk,
((void) f_rng);
((void) p_rng);
#if !defined(MBEDTLS_RSA_ALT)
if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
return MBEDTLS_ERR_RSA_INVALID_PADDING;
}
#endif /* !MBEDTLS_RSA_ALT */
if (ilen != mbedtls_rsa_get_len(rsa)) {
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
}
@ -301,7 +305,13 @@ static int rsa_decrypt_wrap(mbedtls_pk_context *pk,
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
psa_md_alg = mbedtls_md_psa_alg_from_type(mbedtls_rsa_get_md_alg(rsa));
decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);
} else {
decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
}
psa_set_key_algorithm(&attributes, decrypt_alg);
status = psa_import_key(&attributes,
buf + sizeof(buf) - key_len, key_len,
@ -311,7 +321,7 @@ static int rsa_decrypt_wrap(mbedtls_pk_context *pk,
goto cleanup;
}
status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
status = psa_asymmetric_decrypt(key_id, decrypt_alg,
input, ilen,
NULL, 0,
output, osize, olen);
@ -358,6 +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_status_t status;
int key_len;
unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
@ -366,12 +377,6 @@ static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
((void) f_rng);
((void) p_rng);
#if !defined(MBEDTLS_RSA_ALT)
if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
return MBEDTLS_ERR_RSA_INVALID_PADDING;
}
#endif
if (mbedtls_rsa_get_len(rsa) > osize) {
return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
}
@ -382,7 +387,12 @@ static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
}
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
psa_md_alg = mbedtls_md_psa_alg_from_type(mbedtls_rsa_get_md_alg(rsa));
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_OAEP(psa_md_alg));
} else {
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
}
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
status = psa_import_key(&attributes,

View File

@ -1089,6 +1089,14 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key)
return status;
}
#if defined(MBEDTLS_THREADING_C)
/* We cannot unlock between setting the state to PENDING_DELETION
* and destroying the key in storage, as otherwise another thread
* could load the key into a new slot and the key will not be
* fully destroyed. */
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(
&mbedtls_threading_key_slot_mutex));
#endif
/* Set the key slot containing the key description's state to
* PENDING_DELETION. This stops new operations from registering
* to read the slot. Current readers can safely continue to access
@ -1097,7 +1105,12 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key)
* If the key is persistent, we can now delete the copy of the key
* from memory. If the key is opaque, we require the driver to
* deal with the deletion. */
slot->state = PSA_SLOT_PENDING_DELETION;
status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL,
PSA_SLOT_PENDING_DELETION);
if (status != PSA_SUCCESS) {
goto exit;
}
if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) {
/* Refuse the destruction of a read-only key (which may or may not work
@ -1152,11 +1165,6 @@ psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key)
if (overall_status == PSA_SUCCESS) {
overall_status = status;
}
/* TODO: other slots may have a copy of the same key. We should
* invalidate them.
* https://github.com/ARMmbed/mbed-crypto/issues/214
*/
}
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
@ -1182,6 +1190,14 @@ exit:
if (status != PSA_SUCCESS) {
overall_status = status;
}
#if defined(MBEDTLS_THREADING_C)
/* Don't overwrite existing errors if the unlock fails. */
status = overall_status;
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
#endif
return overall_status;
}
@ -1663,7 +1679,15 @@ static psa_status_t psa_start_key_creation(
return status;
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
&mbedtls_threading_key_slot_mutex));
#endif
status = psa_reserve_free_key_slot(&volatile_key_id, p_slot);
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
#endif
if (status != PSA_SUCCESS) {
return status;
}
@ -1783,6 +1807,11 @@ static psa_status_t psa_finish_key_creation(
(void) slot;
(void) driver;
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
&mbedtls_threading_key_slot_mutex));
#endif
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@ -1822,6 +1851,11 @@ static psa_status_t psa_finish_key_creation(
status = psa_save_se_persistent_data(driver);
if (status != PSA_SUCCESS) {
psa_destroy_persistent_key(slot->attr.id);
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
#endif
return status;
}
status = psa_crypto_stop_transaction();
@ -1837,6 +1871,10 @@ static psa_status_t psa_finish_key_creation(
}
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
#endif
return status;
}
@ -1861,6 +1899,13 @@ static void psa_fail_key_creation(psa_key_slot_t *slot,
return;
}
#if defined(MBEDTLS_THREADING_C)
/* If the lock operation fails we still wipe the slot.
* Operations will no longer work after a failed lock,
* but we still need to wipe the slot of confidential data. */
mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex);
#endif
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* TODO: If the key has already been created in the secure
* element, and the failure happened later (when saving metadata
@ -1879,6 +1924,10 @@ static void psa_fail_key_creation(psa_key_slot_t *slot,
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
psa_wipe_key_slot(slot);
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex);
#endif
}
/** Validate optional attributes during key creation.

View File

@ -521,44 +521,78 @@ psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle)
psa_status_t psa_close_key(psa_key_handle_t handle)
{
psa_status_t status;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
if (psa_key_handle_is_null(handle)) {
return PSA_SUCCESS;
}
#if defined(MBEDTLS_THREADING_C)
/* We need to set status as success, otherwise CORRUPTION_DETECTED
* would be returned if the lock fails. */
status = PSA_SUCCESS;
PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
&mbedtls_threading_key_slot_mutex));
#endif
status = psa_get_and_lock_key_slot_in_memory(handle, &slot);
if (status != PSA_SUCCESS) {
if (status == PSA_ERROR_DOES_NOT_EXIST) {
status = PSA_ERROR_INVALID_HANDLE;
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
#endif
return status;
}
if (slot->registered_readers == 1) {
return psa_wipe_key_slot(slot);
status = psa_wipe_key_slot(slot);
} else {
return psa_unregister_read(slot);
status = psa_unregister_read(slot);
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
#endif
return status;
}
psa_status_t psa_purge_key(mbedtls_svc_key_id_t key)
{
psa_status_t status;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
#if defined(MBEDTLS_THREADING_C)
/* We need to set status as success, otherwise CORRUPTION_DETECTED
* would be returned if the lock fails. */
status = PSA_SUCCESS;
PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
&mbedtls_threading_key_slot_mutex));
#endif
status = psa_get_and_lock_key_slot_in_memory(key, &slot);
if (status != PSA_SUCCESS) {
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
#endif
return status;
}
if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
(slot->registered_readers == 1)) {
return psa_wipe_key_slot(slot);
status = psa_wipe_key_slot(slot);
} else {
return psa_unregister_read(slot);
status = psa_unregister_read(slot);
}
#if defined(MBEDTLS_THREADING_C)
PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
&mbedtls_threading_key_slot_mutex));
#endif
return status;
}
void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats)

View File

@ -92,6 +92,8 @@ psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
psa_status_t psa_initialize_key_slots(void);
/** Delete all data from key slots in memory.
* This function is not thread safe, it wipes every key slot regardless of
* state and reader count. It should only be called when no slot is in use.
*
* This does not affect persistent storage. */
void psa_wipe_all_key_slots(void);
@ -105,6 +107,9 @@ void psa_wipe_all_key_slots(void);
* It is the responsibility of the caller to change the slot's state to
* PSA_SLOT_EMPTY/FULL once key creation has finished.
*
* If multi-threading is enabled, the caller must hold the
* global key slot mutex.
*
* \param[out] volatile_key_id On success, volatile key identifier
* associated to the returned slot.
* \param[out] p_slot On success, a pointer to the slot.

View File

@ -108,8 +108,9 @@ int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, si
return ret;
}
/* mbedtls_asn1_get_tag() already ensures that len is valid (i.e. p+len <= end)*/
end = p + len;
if (end != p + len) {
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
}
if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
return ret;
@ -241,8 +242,9 @@ int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key,
return ret;
}
/* mbedtls_asn1_get_tag() already ensures that len is valid (i.e. p+len <= end)*/
end = p + len;
if (end != p + len) {
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
}
/* Import N */
if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
@ -1014,6 +1016,14 @@ int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx)
return ctx->hash_id;
}
/*
* Get length in bits of RSA modulus
*/
size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx)
{
return mbedtls_mpi_bitlen(&ctx->N);
}
/*
* Get length in bytes of RSA modulus
*/

View File

@ -26,33 +26,35 @@
#define XOR_BYTE 0x6
typedef struct mbedtls_sha3_family_functions {
mbedtls_sha3_id id;
uint16_t r;
uint16_t olen;
}
mbedtls_sha3_family_functions;
/*
* List of supported SHA-3 families
/* Precomputed masks for the iota transform.
*
* Each round uses a 64-bit mask value. In each mask values, only
* bits whose position is of the form 2^k-1 can be set, thus only
* 7 of 64 bits of the mask need to be known for each mask value.
*
* We use a compressed encoding of the mask where bits 63, 31 and 15
* are moved to bits 4-6. This allows us to make each mask value
* 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with
* perhaps a little variation due to alignment). Decompressing this
* requires a little code, but much less than the savings on the table.
*
* The impact on performance depends on the platform and compiler.
* There's a bit more computation, but less memory bandwidth. A quick
* benchmark on x86_64 shows a 7% speed improvement with GCC and a
* 5% speed penalty with Clang, compared to the naive uint64_t[24] table.
* YMMV.
*/
static const mbedtls_sha3_family_functions sha3_families[] = {
{ MBEDTLS_SHA3_224, 1152, 224 },
{ MBEDTLS_SHA3_256, 1088, 256 },
{ MBEDTLS_SHA3_384, 832, 384 },
{ MBEDTLS_SHA3_512, 576, 512 },
{ MBEDTLS_SHA3_NONE, 0, 0 }
};
static const uint64_t rc[24] = {
0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
/* Helper macro to set the values of the higher bits in unused low positions */
#define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4)
static const uint8_t iota_r_packed[24] = {
H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00,
H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09,
H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a,
H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03,
H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a,
H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08,
};
#undef H
static const uint8_t rho[24] = {
1, 62, 28, 27, 36, 44, 6, 55, 20,
@ -151,7 +153,11 @@ static void keccak_f1600(mbedtls_sha3_context *ctx)
s[24] ^= (~lane[0]) & lane[1];
/* Iota */
s[0] ^= rc[round];
/* Decompress the round masks (see definition of rc) */
s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 |
(iota_r_packed[round] & 0x20ull) << 26 |
(iota_r_packed[round] & 0x10ull) << 11 |
(iota_r_packed[round] & 0x8f));
}
}
@ -180,21 +186,27 @@ void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
*/
int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
{
const mbedtls_sha3_family_functions *p = NULL;
for (p = sha3_families; p->id != MBEDTLS_SHA3_NONE; p++) {
if (p->id == id) {
switch (id) {
case MBEDTLS_SHA3_224:
ctx->olen = 224 / 8;
ctx->max_block_size = 1152 / 8;
break;
}
case MBEDTLS_SHA3_256:
ctx->olen = 256 / 8;
ctx->max_block_size = 1088 / 8;
break;
case MBEDTLS_SHA3_384:
ctx->olen = 384 / 8;
ctx->max_block_size = 832 / 8;
break;
case MBEDTLS_SHA3_512:
ctx->olen = 512 / 8;
ctx->max_block_size = 576 / 8;
break;
default:
return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
}
if (p->id == MBEDTLS_SHA3_NONE) {
return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
}
ctx->olen = p->olen / 8;
ctx->max_block_size = p->r / 8;
memset(ctx->state, 0, sizeof(ctx->state));
ctx->index = 0;

View File

@ -731,14 +731,23 @@ struct mbedtls_ssl_handshake_params {
uint8_t key_exchange_mode; /*!< Selected key exchange mode */
/** Number of HelloRetryRequest messages received/sent from/to the server. */
int hello_retry_request_count;
uint8_t hello_retry_request_count;
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
/**
* Number of dummy change_cipher_spec (CCS) record sent. Used to send only
* one CCS per handshake without having to complicate the handshake state
* transitions.
*/
uint8_t ccs_count;
#endif
#if defined(MBEDTLS_SSL_SRV_C)
/** selected_group of key_share extension in HelloRetryRequest message. */
uint16_t hrr_selected_group;
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */
#endif
/** selected_group of key_share extension in HelloRetryRequest message. */
uint16_t hrr_selected_group;
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
uint16_t new_session_tickets_count; /*!< number of session tickets */
#endif
@ -2136,6 +2145,38 @@ int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
size_t *out_len);
#if defined(MBEDTLS_SSL_CLI_C)
/*
* The client has not sent the first ClientHello yet, it is unknown if the
* client will send an early data indication extension or not.
*/
#define MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN 0
/*
* 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 and early data cannot be sent yet.
*/
#define MBEDTLS_SSL_EARLY_DATA_STATUS_SENT 4
/*
* 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.
*/
#define MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE 5
/*
* 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.
*/
#define MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED 6
#endif /* MBEDTLS_SSL_CLI_C */
#endif /* MBEDTLS_SSL_EARLY_DATA */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */

View File

@ -1100,7 +1100,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_NOT_SENT;
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN;
#endif
#if defined(MBEDTLS_SSL_SRV_C)
ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;

View File

@ -1180,26 +1180,21 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
#endif
#if defined(MBEDTLS_SSL_EARLY_DATA)
if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&
ssl_tls13_early_data_has_valid_ticket(ssl) &&
ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED &&
ssl->handshake->hello_retry_request_count == 0) {
if (ssl->handshake->hello_retry_request_count == 0) {
if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&
ssl_tls13_early_data_has_valid_ticket(ssl) &&
ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
ret = mbedtls_ssl_tls13_write_early_data_ext(
ssl, 0, p, end, &ext_len);
if (ret != 0) {
return ret;
}
p += ext_len;
ret = mbedtls_ssl_tls13_write_early_data_ext(
ssl, 0, p, end, &ext_len);
if (ret != 0) {
return ret;
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SENT;
} else {
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
}
p += ext_len;
/* Initializes the status to `rejected`. It will be updated to
* `accepted` if the EncryptedExtension message contain an early data
* indication extension.
*/
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
} else {
MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write early_data extension"));
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@ -1236,7 +1231,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_REJECTED) {
if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT) {
MBEDTLS_SSL_DEBUG_MSG(
1, ("Set hs psk for early data when writing the first psk"));
@ -1299,6 +1294,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;
#endif
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@ -1971,6 +1967,13 @@ 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;
}
#endif
return 0;
}
@ -2230,6 +2233,8 @@ static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl)
}
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;
}
#endif
@ -2567,9 +2572,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;
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);
} else if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
} else
#endif /* MBEDTLS_SSL_EARLY_DATA */
{
@ -3059,18 +3063,25 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)
*/
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
if (ret == 0) {
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
ret = 0;
if (ssl->handshake->ccs_count == 0) {
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
if (ret != 0) {
break;
}
}
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
break;
case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
if (ret == 0) {
mbedtls_ssl_handshake_set_state(
ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
ret = 0;
if (ssl->handshake->ccs_count == 0) {
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
if (ret != 0) {
break;
}
}
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
break;
#if defined(MBEDTLS_SSL_EARLY_DATA)
@ -3083,6 +3094,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;
}
break;
#endif /* MBEDTLS_SSL_EARLY_DATA */

View File

@ -1390,6 +1390,8 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl)
/* Dispatch message */
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0));
ssl->handshake->ccs_count++;
cleanup:
MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec"));

View File

@ -3482,10 +3482,14 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl)
break;
case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO:
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
if (ret == 0) {
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
ret = 0;
if (ssl->handshake->ccs_count == 0) {
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
if (ret != 0) {
break;
}
}
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
break;
#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */