diff --git a/TESTS/mbed-crypto/sanity/main.cpp b/TESTS/mbed-crypto/sanity/main.cpp
index 98cd169e47..9fdeca3689 100644
--- a/TESTS/mbed-crypto/sanity/main.cpp
+++ b/TESTS/mbed-crypto/sanity/main.cpp
@@ -262,13 +262,13 @@ void test_crypto_asymmetric_sign_verify(void)
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key, sizeof(key), &key_handle));
- TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_sign(key_handle, alg, input, sizeof(input),
- signature, sizeof(signature), &signature_len));
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_sign_hash(key_handle, alg, input, sizeof(input),
+ signature, sizeof(signature), &signature_len));
TEST_ASSERT_EQUAL(sizeof(signature), signature_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_signature, signature, signature_len);
- TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_verify(key_handle, alg, input, sizeof(input),
- signature, signature_len));
+ TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_verify_hash(key_handle, alg, input, sizeof(input),
+ signature, signature_len));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle));
}
diff --git a/TESTS/psa/attestation/main.cpp b/TESTS/psa/attestation/main.cpp
index 52430eea28..4bba662405 100755
--- a/TESTS/psa/attestation/main.cpp
+++ b/TESTS/psa/attestation/main.cpp
@@ -98,7 +98,7 @@ static void check_initial_attestation_get_token()
TEST_ASSERT_EQUAL(status, PSA_SUCCESS);
status = psa_attestation_inject_key(private_key_data,
sizeof(private_key_data),
- PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1),
+ PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1),
exported,
sizeof(exported),
&exported_length);
diff --git a/TESTS/psa/crypto_access_control/COMPONENT_NSPE/main.cpp b/TESTS/psa/crypto_access_control/COMPONENT_NSPE/main.cpp
index f260e96f18..88d0d33e65 100644
--- a/TESTS/psa/crypto_access_control/COMPONENT_NSPE/main.cpp
+++ b/TESTS/psa/crypto_access_control/COMPONENT_NSPE/main.cpp
@@ -348,7 +348,7 @@ void test_use_other_partition_key_aead(void)
void test_use_other_partition_key_asymmetric_sign_verify(void)
{
static const psa_key_id_t key_id = 999;
- static const psa_key_type_t key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1);
+ static const psa_key_type_t key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1);
static const psa_algorithm_t key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
static const psa_key_usage_t key_usage = PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY;
static const size_t key_bits = 256;
@@ -373,12 +373,12 @@ void test_use_other_partition_key_asymmetric_sign_verify(void)
TEST_ASSERT_NOT_EQUAL(0, key_handle);
/* try to asymmetric sign using the key that was created by the test partition */
- TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_asymmetric_sign(key_handle, key_alg, input, sizeof(input),
- signature, sizeof(signature), &len));
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_sign_hash(key_handle, key_alg, input, sizeof(input),
+ signature, sizeof(signature), &len));
/* try to asymmetric verify using the key that was created by the test partition */
- TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_asymmetric_verify(key_handle, key_alg, input, sizeof(input),
- signature, sizeof(signature)));
+ TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_HANDLE, psa_verify_hash(key_handle, key_alg, input, sizeof(input),
+ signature, sizeof(signature)));
/* via test partition - destroy the key created by the test partition */
TEST_ASSERT_EQUAL(PSA_SUCCESS, test_partition_crypto_destroy_key(key_handle));
diff --git a/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto.c b/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto.c
index 60252919ac..f92fc18f56 100755
--- a/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto.c
+++ b/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto.c
@@ -58,13 +58,13 @@ t_cose_crypto_pub_key_sign(int32_t cose_alg_id,
return T_COSE_ERR_NO_KID;
}
- crypto_ret = psa_asymmetric_sign(handle,
- PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256),
- hash_to_sign.ptr,
- hash_to_sign.len,
- signature_buffer.ptr,
- signature_buffer.len,
- &(signature->len));
+ crypto_ret = psa_sign_hash(handle,
+ PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256),
+ hash_to_sign.ptr,
+ hash_to_sign.len,
+ signature_buffer.ptr,
+ signature_buffer.len,
+ &(signature->len));
if (crypto_ret != PSA_SUCCESS)
diff --git a/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c b/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c
index e3b19a0749..e67227c8ff 100755
--- a/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c
+++ b/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/attest_crypto_keys.c
@@ -48,21 +48,12 @@ static psa_status_t get_curve(psa_key_type_t type, enum ecc_curve_t *curve_type)
{
psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE(type);
switch (curve) {
- case PSA_ECC_CURVE_SECP256R1:
+ case PSA_ECC_CURVE_SECP_R1:
*curve_type = P_256;
break;
- case PSA_ECC_CURVE_SECP384R1:
- *curve_type = P_384;
- break;
- case PSA_ECC_CURVE_SECP521R1:
- *curve_type = P_521;
- break;
- case PSA_ECC_CURVE_CURVE25519:
+ case PSA_ECC_CURVE_MONTGOMERY:
*curve_type = X25519;
break;
- case PSA_ECC_CURVE_CURVE448:
- *curve_type = X448;
- break;
default:
return (PSA_ERROR_NOT_SUPPORTED);
}
diff --git a/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/tfm_impl/attestation_core.c b/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/tfm_impl/attestation_core.c
index 87a5486ce7..a7e46dab26 100755
--- a/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/tfm_impl/attestation_core.c
+++ b/components/TARGET_PSA/services/attestation/COMPONENT_PSA_SRV_IMPL/tfm_impl/attestation_core.c
@@ -942,7 +942,7 @@ error:
/* Limitations of the current implementation:
* - Token is not signed yet properly, just a fake signature is added to the
- * token due to lack of psa_asymmetric_sign() implementation in crypto
+ * token due to lack of psa_sign_hash() implementation in crypto
* service.
*/
enum psa_attest_err_t
diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/crypto_platform_spe.h b/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/crypto_platform_spe.h
index 6783e292f4..05fe728fbf 100644
--- a/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/crypto_platform_spe.h
+++ b/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/crypto_platform_spe.h
@@ -87,8 +87,8 @@ typedef enum psa_sec_function_s {
PSA_AEAD_FINISH,
PSA_AEAD_VERIFY,
PSA_AEAD_ABORT,
- PSA_ASYMMETRIC_SIGN,
- PSA_ASYMMETRIC_VERIFY,
+ PSA_SIGN_HASH,
+ PSA_VERIFY_HASH,
PSA_ASYMMETRIC_ENCRYPT,
PSA_ASYMMETRIC_DECRYPT,
PSA_KEY_DERIVATION_SETUP,
diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/psa_crypto_spm.c b/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/psa_crypto_spm.c
index a1d09e2587..c50004a8e9 100644
--- a/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/psa_crypto_spm.c
+++ b/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/psa_crypto_spm.c
@@ -1216,16 +1216,16 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation)
return ipc_call(&operation->handle, &in_vec, 1, NULL, 0, true);
}
-psa_status_t psa_asymmetric_sign(psa_key_handle_t handle,
- psa_algorithm_t alg,
- const uint8_t *hash,
- size_t hash_length,
- uint8_t *signature,
- size_t signature_size,
- size_t *signature_length)
+psa_status_t psa_sign_hash(psa_key_handle_t handle,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ uint8_t *signature,
+ size_t signature_size,
+ size_t *signature_length)
{
psa_crypto_ipc_asymmetric_t psa_crypto_ipc = {
- .func = PSA_ASYMMETRIC_SIGN,
+ .func = PSA_SIGN_HASH,
.handle = handle,
.alg = alg,
.input_length = 0,
@@ -1246,15 +1246,15 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle,
return (status);
}
-psa_status_t psa_asymmetric_verify(psa_key_handle_t handle,
- psa_algorithm_t alg,
- const uint8_t *hash,
- size_t hash_length,
- const uint8_t *signature,
- size_t signature_size)
+psa_status_t psa_verify_hash(psa_key_handle_t handle,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_size)
{
psa_crypto_ipc_asymmetric_t psa_crypto_ipc = {
- .func = PSA_ASYMMETRIC_VERIFY,
+ .func = PSA_VERIFY_HASH,
.handle = handle,
.alg = alg,
.input_length = 0,
diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/crypto_spe.h b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/crypto_spe.h
index 6b6bf19370..be55586abd 100644
--- a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/crypto_spe.h
+++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/crypto_spe.h
@@ -59,8 +59,8 @@ extern "C" {
#define psa_aead_finish psa_sec_aead_finish
#define psa_aead_verify psa_sec_aead_verify
#define psa_aead_abort psa_sec_aead_abort
-#define psa_asymmetric_sign psa_sec_asymmetric_sign
-#define psa_asymmetric_verify psa_sec_asymmetric_verify
+#define psa_sign_hash psa_sec_sign_hash
+#define psa_verify_hash psa_sec_verify_hash
#define psa_asymmetric_encrypt psa_sec_asymmetric_encrypt
#define psa_asymmetric_decrypt psa_sec_asymmetric_decrypt
#define psa_key_derivation_setup psa_sec_key_derivation_setup
diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_partition.c b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_partition.c
index 08893ce757..b6522bcdb9 100644
--- a/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_partition.c
+++ b/components/TARGET_PSA/services/crypto/COMPONENT_SPE/psa_crypto_partition.c
@@ -989,7 +989,7 @@ static void psa_asymmetric_operation(void)
}
switch (psa_crypto.func) {
- case PSA_ASYMMETRIC_SIGN: {
+ case PSA_SIGN_HASH: {
uint8_t *signature = NULL;
uint8_t *hash = NULL;
size_t signature_length = 0,
@@ -1015,9 +1015,9 @@ static void psa_asymmetric_operation(void)
}
if (status == PSA_SUCCESS) {
- status = psa_asymmetric_sign(psa_crypto.handle, psa_crypto.alg,
- hash, hash_size,
- signature, signature_size, &signature_length);
+ status = psa_sign_hash(psa_crypto.handle, psa_crypto.alg,
+ hash, hash_size,
+ signature, signature_size, &signature_length);
if (status == PSA_SUCCESS) {
psa_write(msg.handle, 0, signature, signature_length);
@@ -1030,7 +1030,7 @@ static void psa_asymmetric_operation(void)
break;
}
- case PSA_ASYMMETRIC_VERIFY: {
+ case PSA_VERIFY_HASH: {
uint8_t *signature = NULL;
uint8_t *hash = NULL;
size_t signature_size = msg.in_size[1],
@@ -1060,9 +1060,9 @@ static void psa_asymmetric_operation(void)
}
if (status == PSA_SUCCESS) {
- status = psa_asymmetric_verify(psa_crypto.handle, psa_crypto.alg,
- hash, hash_size,
- signature, signature_size);
+ status = psa_verify_hash(psa_crypto.handle, psa_crypto.alg,
+ hash, hash_size,
+ signature, signature_size);
}
mbedtls_free(signature);
diff --git a/features/frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp b/features/frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp
index ab1803ddc1..8eb71f15c2 100644
--- a/features/frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp
+++ b/features/frameworks/TARGET_PSA/pal/pal_mbed_os_intf.cpp
@@ -63,7 +63,7 @@ static void psa_attestation_inject_key_for_test(void)
psa_attestation_destroy_key_for_test();
psa_attestation_inject_key(private_key_data,
sizeof(private_key_data),
- PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1),
+ PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1),
exported,
sizeof(exported),
&exported_length);
diff --git a/features/mbedtls/VERSION.txt b/features/mbedtls/VERSION.txt
index 25ccba53c2..ac08791e86 100644
--- a/features/mbedtls/VERSION.txt
+++ b/features/mbedtls/VERSION.txt
@@ -1 +1 @@
-mbedtls-2.20.0d0
+mbedtls-2.21.0
diff --git a/features/mbedtls/importer/Makefile b/features/mbedtls/importer/Makefile
index b737e5bb97..eb7cf9372e 100644
--- a/features/mbedtls/importer/Makefile
+++ b/features/mbedtls/importer/Makefile
@@ -27,8 +27,8 @@
#
# Set the mbed TLS release to import (this can/should be edited before import)
-MBED_TLS_RELEASE ?= mbedtls-2.20.0d0
-MBED_TLS_REPO_URL ?= git@github.com:ARMmbed/mbedtls-restricted.git
+MBED_TLS_RELEASE ?= mbedtls-2.21.0
+MBED_TLS_REPO_URL ?= git@github.com:ARMmbed/mbedtls.git
# Translate between mbed TLS namespace and mbed namespace
TARGET_PREFIX:=../
diff --git a/features/mbedtls/inc/mbedtls/check_config.h b/features/mbedtls/inc/mbedtls/check_config.h
index 7e0e3575c8..46d9117f1e 100644
--- a/features/mbedtls/inc/mbedtls/check_config.h
+++ b/features/mbedtls/inc/mbedtls/check_config.h
@@ -342,6 +342,14 @@
#error "MBEDTLS_PKCS11_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_PKCS11_C)
+#if defined(MBEDTLS_DEPRECATED_REMOVED)
+#error "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS"
+#elif defined(MBEDTLS_DEPRECATED_WARNING)
+#warning "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS"
+#endif
+#endif /* MBEDTLS_PKCS11_C */
+
#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites"
#endif
@@ -769,6 +777,22 @@
#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously"
#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+#if defined(MBEDTLS_DEPRECATED_REMOVED)
+#error "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS"
+#elif defined(MBEDTLS_DEPRECATED_WARNING)
+#warning "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS"
+#endif
+#endif /* MBEDTLS_SSL_PROTO_SSL3 */
+
+#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+#if defined(MBEDTLS_DEPRECATED_REMOVED)
+#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS"
+#elif defined(MBEDTLS_DEPRECATED_WARNING)
+#warning "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS"
+#endif
+#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
+
/*
* Avoid warning from -pedantic. This is a convenient place for this
* workaround since this is included by every single file before the
diff --git a/features/mbedtls/inc/mbedtls/config.h b/features/mbedtls/inc/mbedtls/config.h
index e6b459dc11..4a913cfae8 100644
--- a/features/mbedtls/inc/mbedtls/config.h
+++ b/features/mbedtls/inc/mbedtls/config.h
@@ -249,27 +249,27 @@
/**
* \def MBEDTLS_DEPRECATED_WARNING
*
- * Mark deprecated functions so that they generate a warning if used.
- * Functions deprecated in one version will usually be removed in the next
- * version. You can enable this to help you prepare the transition to a new
- * major version by making sure your code is not using these functions.
+ * Mark deprecated functions and features so that they generate a warning if
+ * used. Functionality deprecated in one version will usually be removed in the
+ * next version. You can enable this to help you prepare the transition to a
+ * new major version by making sure your code is not using this functionality.
*
* This only works with GCC and Clang. With other compilers, you may want to
* use MBEDTLS_DEPRECATED_REMOVED
*
- * Uncomment to get warnings on using deprecated functions.
+ * Uncomment to get warnings on using deprecated functions and features.
*/
//#define MBEDTLS_DEPRECATED_WARNING
/**
* \def MBEDTLS_DEPRECATED_REMOVED
*
- * Remove deprecated functions so that they generate an error if used.
- * Functions deprecated in one version will usually be removed in the next
- * version. You can enable this to help you prepare the transition to a new
- * major version by making sure your code is not using these functions.
+ * Remove deprecated functions and features so that they generate an error if
+ * used. Functionality deprecated in one version will usually be removed in the
+ * next version. You can enable this to help you prepare the transition to a
+ * new major version by making sure your code is not using this functionality.
*
- * Uncomment to get errors on using deprecated functions.
+ * Uncomment to get errors on using deprecated functions and features.
*/
//#define MBEDTLS_DEPRECATED_REMOVED
@@ -1587,6 +1587,9 @@
* Enable support for receiving and parsing SSLv2 Client Hello messages for the
* SSL Server module (MBEDTLS_SSL_SRV_C).
*
+ * \deprecated This option is deprecated and will be removed in a future
+ * version of Mbed TLS.
+ *
* Uncomment this macro to enable support for SSLv2 Client Hello messages.
*/
//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
@@ -1618,6 +1621,9 @@
* Requires: MBEDTLS_MD5_C
* MBEDTLS_SHA1_C
*
+ * \deprecated This option is deprecated and will be removed in a future
+ * version of Mbed TLS.
+ *
* Comment this macro to disable support for SSL 3.0
*/
//#define MBEDTLS_SSL_PROTO_SSL3
@@ -2828,7 +2834,10 @@
/**
* \def MBEDTLS_PKCS11_C
*
- * Enable wrapper for PKCS#11 smartcard support.
+ * Enable wrapper for PKCS#11 smartcard support via the pkcs11-helper library.
+ *
+ * \deprecated This option is deprecated and will be removed in a future
+ * version of Mbed TLS.
*
* Module: library/pkcs11.c
* Caller: library/pk.c
diff --git a/features/mbedtls/inc/mbedtls/error.h b/features/mbedtls/inc/mbedtls/error.h
index 06bb1c9cac..82b018813e 100644
--- a/features/mbedtls/inc/mbedtls/error.h
+++ b/features/mbedtls/inc/mbedtls/error.h
@@ -52,9 +52,10 @@
* For historical reasons, low-level error codes are divided in even and odd,
* even codes were assigned first, and -1 is reserved for other errors.
*
- * Low-level module errors (0x0002-0x007E, 0x0003-0x007F)
+ * Low-level module errors (0x0002-0x007E, 0x0001-0x007F)
*
* Module Nr Codes assigned
+ * ERROR 2 0x006E 0x0001
* MPI 7 0x0002-0x0010
* GCM 3 0x0012-0x0014 0x0013-0x0013
* BLOWFISH 3 0x0016-0x0018 0x0017-0x0017
@@ -86,7 +87,7 @@
* CHACHA20 3 0x0051-0x0055
* POLY1305 3 0x0057-0x005B
* CHACHAPOLY 2 0x0054-0x0056
- * PLATFORM 1 0x0070-0x0072
+ * PLATFORM 2 0x0070-0x0072
*
* High-level module nr (3 bits - 0x0...-0x7...)
* Name ID Nr of Errors
@@ -112,6 +113,9 @@
extern "C" {
#endif
+#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 /**< Generic error */
+#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E /**< This is a bug in the library */
+
/**
* \brief Translate a mbed TLS error code into a string representation,
* Result is truncated if necessary and always includes a terminating
diff --git a/features/mbedtls/inc/mbedtls/pkcs11.h b/features/mbedtls/inc/mbedtls/pkcs11.h
index d9f45db676..cf8d8c4297 100644
--- a/features/mbedtls/inc/mbedtls/pkcs11.h
+++ b/features/mbedtls/inc/mbedtls/pkcs11.h
@@ -47,6 +47,8 @@
extern "C" {
#endif
+#if defined(MBEDTLS_DEPRECATED_REMOVED)
+
/**
* Context for PKCS #11 private keys.
*/
@@ -56,47 +58,71 @@ typedef struct mbedtls_pkcs11_context
int len;
} mbedtls_pkcs11_context;
+#if defined(MBEDTLS_DEPRECATED_WARNING)
+#define MBEDTLS_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDTLS_DEPRECATED
+#endif
+
/**
* Initialize a mbedtls_pkcs11_context.
* (Just making memory references valid.)
+ *
+ * \deprecated This function is deprecated and will be removed in a
+ * future version of the library.
*/
-void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx );
+MBEDTLS_DEPRECATED void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx );
/**
* Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate.
*
+ * \deprecated This function is deprecated and will be removed in a
+ * future version of the library.
+ *
* \param cert X.509 certificate to fill
* \param pkcs11h_cert PKCS #11 helper certificate
*
* \return 0 on success.
*/
-int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert );
+MBEDTLS_DEPRECATED int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert,
+ pkcs11h_certificate_t pkcs11h_cert );
/**
* Set up a mbedtls_pkcs11_context storing the given certificate. Note that the
* mbedtls_pkcs11_context will take over control of the certificate, freeing it when
* done.
*
+ * \deprecated This function is deprecated and will be removed in a
+ * future version of the library.
+ *
* \param priv_key Private key structure to fill.
* \param pkcs11_cert PKCS #11 helper certificate
*
* \return 0 on success
*/
-int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key,
- pkcs11h_certificate_t pkcs11_cert );
+MBEDTLS_DEPRECATED int mbedtls_pkcs11_priv_key_bind(
+ mbedtls_pkcs11_context *priv_key,
+ pkcs11h_certificate_t pkcs11_cert );
/**
* Free the contents of the given private key context. Note that the structure
* itself is not freed.
*
+ * \deprecated This function is deprecated and will be removed in a
+ * future version of the library.
+ *
* \param priv_key Private key structure to cleanup
*/
-void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key );
+MBEDTLS_DEPRECATED void mbedtls_pkcs11_priv_key_free(
+ mbedtls_pkcs11_context *priv_key );
/**
* \brief Do an RSA private key decrypt, then remove the message
* padding
*
+ * \deprecated This function is deprecated and will be removed in a future
+ * version of the library.
+ *
* \param ctx PKCS #11 context
* \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature
* \param input buffer holding the encrypted data
@@ -110,15 +136,18 @@ void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key );
* of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
* an error is thrown.
*/
-int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx,
- int mode, size_t *olen,
- const unsigned char *input,
- unsigned char *output,
- size_t output_max_len );
+MBEDTLS_DEPRECATED int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input,
+ unsigned char *output,
+ size_t output_max_len );
/**
* \brief Do a private RSA to sign a message digest
*
+ * \deprecated This function is deprecated and will be removed in a future
+ * version of the library.
+ *
* \param ctx PKCS #11 context
* \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature
* \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data)
@@ -132,28 +161,58 @@ int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx,
* \note The "sig" buffer must be as large as the size
* of ctx->N (eg. 128 bytes if RSA-1024 is used).
*/
-int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx,
- int mode,
- mbedtls_md_type_t md_alg,
- unsigned int hashlen,
- const unsigned char *hash,
- unsigned char *sig );
+MBEDTLS_DEPRECATED int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx,
+ int mode,
+ mbedtls_md_type_t md_alg,
+ unsigned int hashlen,
+ const unsigned char *hash,
+ unsigned char *sig );
/**
* SSL/TLS wrappers for PKCS#11 functions
+ *
+ * \deprecated This function is deprecated and will be removed in a future
+ * version of the library.
*/
-static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen,
- const unsigned char *input, unsigned char *output,
- size_t output_max_len )
+MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx,
+ int mode, size_t *olen,
+ const unsigned char *input, unsigned char *output,
+ size_t output_max_len )
{
return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output,
output_max_len );
}
-static inline int mbedtls_ssl_pkcs11_sign( void *ctx,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
- int mode, mbedtls_md_type_t md_alg, unsigned int hashlen,
- const unsigned char *hash, unsigned char *sig )
+/**
+ * \brief This function signs a message digest using RSA.
+ *
+ * \deprecated This function is deprecated and will be removed in a future
+ * version of the library.
+ *
+ * \param ctx The PKCS #11 context.
+ * \param f_rng The RNG function. This parameter is unused.
+ * \param p_rng The RNG context. This parameter is unused.
+ * \param mode The operation to run. This must be set to
+ * MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's
+ * signature.
+ * \param md_alg The message digest algorithm. One of the MBEDTLS_MD_XXX
+ * must be passed to this function and MBEDTLS_MD_NONE can be
+ * used for signing raw data.
+ * \param hashlen The message digest length (for MBEDTLS_MD_NONE only).
+ * \param hash The buffer holding the message digest.
+ * \param sig The buffer that will hold the ciphertext.
+ *
+ * \return \c 0 if the signing operation was successful.
+ * \return A non-zero error code on failure.
+ *
+ * \note The \p sig buffer must be as large as the size of
+ * ctx->N
. For example, 128 bytes if RSA-1024 is
+ * used.
+ */
+MBEDTLS_DEPRECATED static inline int mbedtls_ssl_pkcs11_sign( void *ctx,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+ int mode, mbedtls_md_type_t md_alg, unsigned int hashlen,
+ const unsigned char *hash, unsigned char *sig )
{
((void) f_rng);
((void) p_rng);
@@ -161,11 +220,25 @@ static inline int mbedtls_ssl_pkcs11_sign( void *ctx,
hashlen, hash, sig );
}
-static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx )
+/**
+ * This function gets the length of the private key.
+ *
+ * \deprecated This function is deprecated and will be removed in a future
+ * version of the library.
+ *
+ * \param ctx The PKCS #11 context.
+ *
+ * \return The length of the private key.
+ */
+MBEDTLS_DEPRECATED static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx )
{
return ( (mbedtls_pkcs11_context *) ctx )->len;
}
+#undef MBEDTLS_DEPRECATED
+
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
#ifdef __cplusplus
}
#endif
diff --git a/features/mbedtls/inc/mbedtls/ssl_internal.h b/features/mbedtls/inc/mbedtls/ssl_internal.h
index f703da99b4..6332d148f6 100644
--- a/features/mbedtls/inc/mbedtls/ssl_internal.h
+++ b/features/mbedtls/inc/mbedtls/ssl_internal.h
@@ -319,7 +319,8 @@ struct mbedtls_ssl_handshake_params
mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
- psa_ecc_curve_t ecdh_psa_curve;
+ psa_key_type_t ecdh_psa_type;
+ uint16_t ecdh_bits;
psa_key_handle_t ecdh_psa_privkey;
unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
size_t ecdh_psa_peerkey_len;
@@ -1062,4 +1063,46 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
mbedtls_ssl_transform *transform,
mbedtls_record *rec );
+/* Length of the "epoch" field in the record header */
+static inline size_t mbedtls_ssl_ep_len( const mbedtls_ssl_context *ssl )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ return( 2 );
+#else
+ ((void) ssl);
+#endif
+ return( 0 );
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs );
+int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl );
+
+void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
+void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform );
+void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl );
+
+int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial );
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl );
+#endif
+
+void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl );
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl );
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl );
+void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl );
+void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
#endif /* ssl_internal.h */
diff --git a/features/mbedtls/inc/mbedtls/version.h b/features/mbedtls/inc/mbedtls/version.h
index ae694eeda2..35af4cc432 100644
--- a/features/mbedtls/inc/mbedtls/version.h
+++ b/features/mbedtls/inc/mbedtls/version.h
@@ -39,17 +39,17 @@
* Major, Minor, Patchlevel
*/
#define MBEDTLS_VERSION_MAJOR 2
-#define MBEDTLS_VERSION_MINOR 19
-#define MBEDTLS_VERSION_PATCH 1
+#define MBEDTLS_VERSION_MINOR 21
+#define MBEDTLS_VERSION_PATCH 0
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x02130100
-#define MBEDTLS_VERSION_STRING "2.19.1"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.19.1"
+#define MBEDTLS_VERSION_NUMBER 0x02150000
+#define MBEDTLS_VERSION_STRING "2.21.0"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.21.0"
#if defined(MBEDTLS_VERSION_C)
diff --git a/features/mbedtls/mbed-crypto/VERSION.txt b/features/mbedtls/mbed-crypto/VERSION.txt
index 20ff92fea1..1a81f64d1d 100644
--- a/features/mbedtls/mbed-crypto/VERSION.txt
+++ b/features/mbedtls/mbed-crypto/VERSION.txt
@@ -1 +1 @@
-mbedcrypto-2.1.0d0
+mbedcrypto-3.1.0
diff --git a/features/mbedtls/mbed-crypto/importer/Makefile b/features/mbedtls/mbed-crypto/importer/Makefile
index 74b65784ce..2c44e78e2a 100644
--- a/features/mbedtls/mbed-crypto/importer/Makefile
+++ b/features/mbedtls/mbed-crypto/importer/Makefile
@@ -29,8 +29,8 @@
# Set the Mbed Crypto release to import (this can/should be edited before
# import)
-CRYPTO_RELEASE ?= mbedcrypto-2.1.0d0
-CRYPTO_REPO_URL ?= git@github.com:ARMmbed/mbedtls-psa.git
+CRYPTO_RELEASE ?= mbedcrypto-3.1.0
+CRYPTO_REPO_URL ?= git@github.com:ARMmbed/mbed-crypto.git
# Translate between Mbed Crypto namespace and Mbed OS namespace
TARGET_PREFIX:=..
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/asn1.h b/features/mbedtls/mbed-crypto/inc/mbedtls/asn1.h
index 1a76111684..33b30041a6 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/asn1.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/asn1.h
@@ -75,6 +75,7 @@
#define MBEDTLS_ASN1_OCTET_STRING 0x04
#define MBEDTLS_ASN1_NULL 0x05
#define MBEDTLS_ASN1_OID 0x06
+#define MBEDTLS_ASN1_ENUMERATED 0x0A
#define MBEDTLS_ASN1_UTF8_STRING 0x0C
#define MBEDTLS_ASN1_SEQUENCE 0x10
#define MBEDTLS_ASN1_SET 0x11
@@ -89,6 +90,18 @@
#define MBEDTLS_ASN1_CONSTRUCTED 0x20
#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80
+/* Slightly smaller way to check if tag is a string tag
+ * compared to canonical implementation. */
+#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \
+ ( ( tag ) < 32u && ( \
+ ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \
+ ( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \
+ ( 1u << MBEDTLS_ASN1_T61_STRING ) | \
+ ( 1u << MBEDTLS_ASN1_IA5_STRING ) | \
+ ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \
+ ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \
+ ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) )
+
/*
* Bit masks for each of the components of an ASN.1 tag as specified in
* ITU X.690 (08/2015), section 8.1 "General rules for encoding",
@@ -119,6 +132,10 @@
( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \
memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
+#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \
+ ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \
+ memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 )
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -254,13 +271,32 @@ int mbedtls_asn1_get_bool( unsigned char **p,
* a valid ASN.1 INTEGER.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
- * \return An ASN.1 error code if the input does not start with
- * a valid ASN.1 INTEGER.
*/
int mbedtls_asn1_get_int( unsigned char **p,
const unsigned char *end,
int *val );
+/**
+ * \brief Retrieve an enumerated ASN.1 tag and its value.
+ * Updates the pointer to immediately behind the full tag.
+ *
+ * \param p On entry, \c *p points to the start of the ASN.1 element.
+ * On successful completion, \c *p points to the first byte
+ * beyond the ASN.1 element.
+ * On error, the value of \c *p is undefined.
+ * \param end End of data.
+ * \param val On success, the parsed value.
+ *
+ * \return 0 if successful.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 ENUMERATED.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
+ * not fit in an \c int.
+ */
+int mbedtls_asn1_get_enum( unsigned char **p,
+ const unsigned char *end,
+ int *val );
+
/**
* \brief Retrieve a bitstring ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
@@ -307,6 +343,9 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p,
* \brief Parses and splits an ASN.1 "SEQUENCE OF ".
* Updates the pointer to immediately behind the full sequence tag.
*
+ * This function allocates memory for the sequence elements. You can free
+ * the allocated memory with mbedtls_asn1_sequence_free().
+ *
* \note On error, this function may return a partial list in \p cur.
* You must set `cur->next = NULL` before calling this function!
* Otherwise it is impossible to distinguish a previously non-null
@@ -340,14 +379,133 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p,
* \return 0 if successful.
* \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains
* extra data after a valid SEQUENCE OF \p tag.
+ * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with
+ * an ASN.1 SEQUENCE in which an element has a tag that
+ * is different from \p tag.
* \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed.
* \return An ASN.1 error code if the input does not start with
- * a valid ASN.1 BIT STRING.
+ * a valid ASN.1 SEQUENCE.
*/
int mbedtls_asn1_get_sequence_of( unsigned char **p,
const unsigned char *end,
mbedtls_asn1_sequence *cur,
int tag );
+/**
+ * \brief Free a heap-allocated linked list presentation of
+ * an ASN.1 sequence, including the first element.
+ *
+ * There are two common ways to manage the memory used for the representation
+ * of a parsed ASN.1 sequence:
+ * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc().
+ * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of().
+ * When you have finished processing the sequence,
+ * call mbedtls_asn1_sequence_free() on `head`.
+ * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner,
+ * for example on the stack. Make sure that `head->next == NULL`.
+ * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of().
+ * When you have finished processing the sequence,
+ * call mbedtls_asn1_sequence_free() on `head->cur`,
+ * then free `head` itself in the appropriate manner.
+ *
+ * \param seq The address of the first sequence component. This may
+ * be \c NULL, in which case this functions returns
+ * immediately.
+ */
+void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq );
+
+/**
+ * \brief Traverse an ASN.1 SEQUENCE container and
+ * call a callback for each entry.
+ *
+ * This function checks that the input is a SEQUENCE of elements that
+ * each have a "must" tag, and calls a callback function on the elements
+ * that have a "may" tag.
+ *
+ * For example, to validate that the input is a SEQUENCE of `tag1` and call
+ * `cb` on each element, use
+ * ```
+ * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx);
+ * ```
+ *
+ * To validate that the input is a SEQUENCE of ANY and call `cb` on
+ * each element, use
+ * ```
+ * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx);
+ * ```
+ *
+ * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING}
+ * and call `cb` on each element that is an OCTET STRING, use
+ * ```
+ * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx);
+ * ```
+ *
+ * The callback is called on the elements with a "may" tag from left to
+ * right. If the input is not a valid SEQUENCE of elements with a "must" tag,
+ * the callback is called on the elements up to the leftmost point where
+ * the input is invalid.
+ *
+ * \warning This function is still experimental and may change
+ * at any time.
+ *
+ * \param p The address of the pointer to the beginning of
+ * the ASN.1 SEQUENCE header. This is updated to
+ * point to the end of the ASN.1 SEQUENCE container
+ * on a successful invocation.
+ * \param end The end of the ASN.1 SEQUENCE container.
+ * \param tag_must_mask A mask to be applied to the ASN.1 tags found within
+ * the SEQUENCE before comparing to \p tag_must_value.
+ * \param tag_must_val The required value of each ASN.1 tag found in the
+ * SEQUENCE, after masking with \p tag_must_mask.
+ * Mismatching tags lead to an error.
+ * For example, a value of \c 0 for both \p tag_must_mask
+ * and \p tag_must_val means that every tag is allowed,
+ * while a value of \c 0xFF for \p tag_must_mask means
+ * that \p tag_must_val is the only allowed tag.
+ * \param tag_may_mask A mask to be applied to the ASN.1 tags found within
+ * the SEQUENCE before comparing to \p tag_may_value.
+ * \param tag_may_val The desired value of each ASN.1 tag found in the
+ * SEQUENCE, after masking with \p tag_may_mask.
+ * Mismatching tags will be silently ignored.
+ * For example, a value of \c 0 for \p tag_may_mask and
+ * \p tag_may_val means that any tag will be considered,
+ * while a value of \c 0xFF for \p tag_may_mask means
+ * that all tags with value different from \p tag_may_val
+ * will be ignored.
+ * \param cb The callback to trigger for each component
+ * in the ASN.1 SEQUENCE that matches \p tag_may_val.
+ * The callback function is called with the following
+ * parameters:
+ * - \p ctx.
+ * - The tag of the current element.
+ * - A pointer to the start of the current element's
+ * content inside the input.
+ * - The length of the content of the current element.
+ * If the callback returns a non-zero value,
+ * the function stops immediately,
+ * forwarding the callback's return value.
+ * \param ctx The context to be passed to the callback \p cb.
+ *
+ * \return \c 0 if successful the entire ASN.1 SEQUENCE
+ * was traversed without parsing or callback errors.
+ * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input
+ * contains extra data after a valid SEQUENCE
+ * of elements with an accepted tag.
+ * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts
+ * with an ASN.1 SEQUENCE in which an element has a tag
+ * that is not accepted.
+ * \return An ASN.1 error code if the input does not start with
+ * a valid ASN.1 SEQUENCE.
+ * \return A non-zero error code forwarded from the callback
+ * \p cb in case the latter returns a non-zero value.
+ */
+int mbedtls_asn1_traverse_sequence_of(
+ unsigned char **p,
+ const unsigned char *end,
+ unsigned char tag_must_mask, unsigned char tag_must_val,
+ unsigned char tag_may_mask, unsigned char tag_may_val,
+ int (*cb)( void *ctx, int tag,
+ unsigned char* start, size_t len ),
+ void *ctx );
#if defined(MBEDTLS_BIGNUM_C)
/**
@@ -367,8 +525,6 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p,
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
* \return An MPI error code if the parsed value is too large.
- * \return An ASN.1 error code if the input does not start with
- * a valid ASN.1 INTEGER.
*/
int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end,
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/asn1write.h b/features/mbedtls/mbed-crypto/inc/mbedtls/asn1write.h
index 982414626e..0bce28ed13 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/asn1write.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/asn1write.h
@@ -192,6 +192,21 @@ int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start,
*/
int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
+/**
+ * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value
+ * in ASN.1 format.
+ *
+ * \note This function works backwards in data buffer.
+ *
+ * \param p The reference to the current position pointer.
+ * \param start The start of the buffer, for bounds-checking.
+ * \param val The integer value to write.
+ *
+ * \return The number of bytes written to \p p on success.
+ * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val );
+
/**
* \brief Write a string in ASN.1 format using a specific
* string encoding tag.
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/bignum.h b/features/mbedtls/mbed-crypto/inc/mbedtls/bignum.h
index 2c5ace6901..1d00c560a6 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/bignum.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/bignum.h
@@ -185,7 +185,7 @@ extern "C" {
*/
typedef struct mbedtls_mpi
{
- int s; /*!< integer sign */
+ int s; /*!< Sign: -1 if the mpi is negative, 1 otherwise */
size_t n; /*!< total # of limbs */
mbedtls_mpi_uint *p; /*!< pointer to limbs */
}
@@ -594,6 +594,24 @@ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y );
*/
int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y );
+/**
+ * \brief Check if an MPI is less than the other in constant time.
+ *
+ * \param X The left-hand MPI. This must point to an initialized MPI
+ * with the same allocated length as Y.
+ * \param Y The right-hand MPI. This must point to an initialized MPI
+ * with the same allocated length as X.
+ * \param ret The result of the comparison:
+ * \c 1 if \p X is less than \p Y.
+ * \c 0 if \p X is greater than or equal to \p Y.
+ *
+ * \return 0 on success.
+ * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of
+ * the two input MPIs is not the same.
+ */
+int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
+ unsigned *ret );
+
/**
* \brief Compare an MPI with an integer.
*
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/ctr_drbg.h b/features/mbedtls/mbed-crypto/inc/mbedtls/ctr_drbg.h
index 2db4021336..234e6a0364 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/ctr_drbg.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/ctr_drbg.h
@@ -12,30 +12,14 @@
* The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
* (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time)
* as the underlying block cipher, with a derivation function.
- * The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy.
- * See the documentation of mbedtls_ctr_drbg_seed() for more details.
*
- * Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2,
- * here are the security strengths achieved in typical configuration:
- * - 256 bits under the default configuration of the library, with AES-256
- * and with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more.
- * - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set
- * to 32 or more, and the DRBG is initialized with an explicit
- * nonce in the \c custom parameter to mbedtls_ctr_drbg_seed().
- * - 128 bits if AES-256 is used but #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
- * between 24 and 47 and the DRBG is not initialized with an explicit
- * nonce (see mbedtls_ctr_drbg_seed()).
- * - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
- * and #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set to 24 or more (which is
- * always the case unless it is explicitly set to a different value
- * in config.h).
- *
- * Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to:
- * - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol
- * \c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled at compile time.
- * This is the default configuration of the library.
- * - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time.
- * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time.
+ * The security strength as defined in NIST SP 800-90A is
+ * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
+ * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
+ * kept at its default value (and not overridden in config.h) and that the
+ * DRBG instance is set up with default parameters.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more
+ * information.
*/
/*
* Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved
@@ -163,20 +147,49 @@
extern "C" {
#endif
+#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
+/** The default length of the nonce read from the entropy source.
+ *
+ * This is \c 0 because a single read from the entropy source is sufficient
+ * to include a nonce.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more information.
+ */
+#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0
+#else
+/** The default length of the nonce read from the entropy source.
+ *
+ * This is half of the default entropy length because a single read from
+ * the entropy source does not provide enough material to form a nonce.
+ * See the documentation of mbedtls_ctr_drbg_seed() for more information.
+ */
+#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2
+#endif
+
/**
* \brief The CTR_DRBG context structure.
*/
typedef struct mbedtls_ctr_drbg_context
{
unsigned char counter[16]; /*!< The counter (V). */
- int reseed_counter; /*!< The reseed counter. */
+ int reseed_counter; /*!< The reseed counter.
+ * This is the number of requests that have
+ * been made since the last (re)seeding,
+ * minus one.
+ * Before the initial seeding, this field
+ * contains the amount of entropy in bytes
+ * to use as a nonce for the initial seeding,
+ * or -1 if no nonce length has been explicitly
+ * set (see mbedtls_ctr_drbg_set_nonce_len()).
+ */
int prediction_resistance; /*!< This determines whether prediction
resistance is enabled, that is
whether to systematically reseed before
each random generation. */
size_t entropy_len; /*!< The amount of entropy grabbed on each
- seed or reseed operation. */
- int reseed_interval; /*!< The reseed interval. */
+ seed or reseed operation, in bytes. */
+ int reseed_interval; /*!< The reseed interval.
+ * This is the maximum number of requests
+ * that can be made between reseedings. */
mbedtls_aes_context aes_ctx; /*!< The AES context. */
@@ -214,47 +227,71 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
* with mbedtls_entropy_init() (which registers the platform's default
* entropy sources).
*
- * \p f_entropy is always called with a buffer size equal to the entropy
- * length. The entropy length is initially #MBEDTLS_CTR_DRBG_ENTROPY_LEN
- * and this value is always used for the initial seeding. You can change
- * the entropy length for subsequent seeding by calling
- * mbedtls_ctr_drbg_set_entropy_len() after this function.
+ * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
+ * You can override it by calling mbedtls_ctr_drbg_set_entropy_len().
*
- * You can provide a personalization string in addition to the
+ * The entropy nonce length is:
+ * - \c 0 if the entropy length is at least 3/2 times the entropy length,
+ * which guarantees that the security strength is the maximum permitted
+ * by the key size and entropy length according to NIST SP 800-90A §10.2.1;
+ * - Half the entropy length otherwise.
+ * You can override it by calling mbedtls_ctr_drbg_set_nonce_len().
+ * With the default entropy length, the entropy nonce length is
+ * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN.
+ *
+ * You can provide a nonce and personalization string in addition to the
* entropy source, to make this instantiation as unique as possible.
+ * See SP 800-90A §8.6.7 for more details about nonces.
*
- * \note The _seed_material_ value passed to the derivation
- * function in the CTR_DRBG Instantiate Process
- * described in NIST SP 800-90A §10.2.1.3.2
- * is the concatenation of the string obtained from
- * calling \p f_entropy and the \p custom string.
- * The origin of the nonce depends on the value of
- * the entropy length relative to the security strength.
- * - If the entropy length is at least 1.5 times the
- * security strength then the nonce is taken from the
- * string obtained with \p f_entropy.
- * - If the entropy length is less than the security
- * strength, then the nonce is taken from \p custom.
- * In this case, for compliance with SP 800-90A,
- * you must pass a unique value of \p custom at
- * each invocation. See SP 800-90A §8.6.7 for more
- * details.
+ * The _seed_material_ value passed to the derivation function in
+ * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2
+ * is the concatenation of the following strings:
+ * - A string obtained by calling \p f_entropy function for the entropy
+ * length.
*/
-#if MBEDTLS_CTR_DRBG_ENTROPY_LEN < MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
-/** \warning When #MBEDTLS_CTR_DRBG_ENTROPY_LEN is less than
- * #MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2, to achieve the
- * maximum security strength permitted by CTR_DRBG,
- * you must pass a value of \p custom that is a nonce:
- * this value must never be repeated in subsequent
- * runs of the same application or on a different
- * device.
+#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0
+/**
+ * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string
+ * obtained by calling \p f_entropy function for the specified length.
+ */
+#else
+/**
+ * - A string obtained by calling \p f_entropy function for the entropy nonce
+ * length. If the entropy nonce length is \c 0, this function does not
+ * make a second call to \p f_entropy.
*/
#endif
/**
+ * - The \p custom string.
+ *
+ * \note To achieve the nominal security strength permitted
+ * by CTR_DRBG, the entropy length must be:
+ * - at least 16 bytes for a 128-bit strength
+ * (maximum achievable strength when using AES-128);
+ * - at least 32 bytes for a 256-bit strength
+ * (maximum achievable strength when using AES-256).
+ *
+ * In addition, if you do not pass a nonce in \p custom,
+ * the sum of the entropy length
+ * and the entropy nonce length must be:
+ * - at least 24 bytes for a 128-bit strength
+ * (maximum achievable strength when using AES-128);
+ * - at least 48 bytes for a 256-bit strength
+ * (maximum achievable strength when using AES-256).
+ *
* \param ctx The CTR_DRBG context to seed.
+ * It must have been initialized with
+ * mbedtls_ctr_drbg_init().
+ * After a successful call to mbedtls_ctr_drbg_seed(),
+ * you may not call mbedtls_ctr_drbg_seed() again on
+ * the same context unless you call
+ * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
+ * again first.
* \param f_entropy The entropy callback, taking as arguments the
* \p p_entropy context, the buffer to fill, and the
* length of the buffer.
+ * \p f_entropy is always called with a buffer size
+ * less than or equal to the entropy length.
* \param p_entropy The entropy context to pass to \p f_entropy.
* \param custom The personalization string.
* This can be \c NULL, in which case the personalization
@@ -298,15 +335,10 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
/**
* \brief This function sets the amount of entropy grabbed on each
- * subsequent reseed.
+ * seed or reseed.
*
* The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
*
- * \note mbedtls_ctr_drbg_seed() always sets the entropy length
- * to #MBEDTLS_CTR_DRBG_ENTROPY_LEN, so this function
- * only has an effect when it is called after
- * mbedtls_ctr_drbg_seed().
- *
* \note The security strength of CTR_DRBG is bounded by the
* entropy length. Thus:
* - When using AES-256
@@ -321,11 +353,35 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
*
* \param ctx The CTR_DRBG context.
* \param len The amount of entropy to grab, in bytes.
- * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
+ * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ * and at most the maximum length accepted by the
+ * entropy function that is set in the context.
*/
void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
size_t len );
+/**
+ * \brief This function sets the amount of entropy grabbed
+ * as a nonce for the initial seeding.
+ *
+ * Call this function before calling mbedtls_ctr_drbg_seed() to read
+ * a nonce from the entropy source during the initial seeding.
+ *
+ * \param ctx The CTR_DRBG context.
+ * \param len The amount of entropy to grab for the nonce, in bytes.
+ * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
+ * and at most the maximum length accepted by the
+ * entropy function that is set in the context.
+ *
+ * \return \c 0 on success.
+ * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is
+ * more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
+ * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
+ * if the initial seeding has already taken place.
+ */
+int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
+ size_t len );
+
/**
* \brief This function sets the reseed interval.
*
@@ -499,11 +555,6 @@ int mbedtls_ctr_drbg_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
-/* Internal functions (do not call directly) */
-int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *,
- int (*)(void *, unsigned char *, size_t), void *,
- const unsigned char *, size_t, size_t );
-
#ifdef __cplusplus
}
#endif
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/hmac_drbg.h b/features/mbedtls/mbed-crypto/inc/mbedtls/hmac_drbg.h
index 519d692fba..00be9df408 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/hmac_drbg.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/hmac_drbg.h
@@ -139,13 +139,11 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
* Note that SHA-256 is just as efficient as SHA-224.
* The security strength can be reduced if a smaller
* entropy length is set with
- * mbedtls_hmac_drbg_set_entropy_len() afterwards.
+ * mbedtls_hmac_drbg_set_entropy_len().
*
- * \note The entropy length for the initial seeding is
- * the security strength (converted from bits to bytes).
- * You can set a different entropy length for subsequent
- * seeding by calling mbedtls_hmac_drbg_set_entropy_len()
- * after this function.
+ * \note The default entropy length is the security strength
+ * (converted from bits to bytes). You can override
+ * it by calling mbedtls_hmac_drbg_set_entropy_len().
*
* \note During the initial seeding, this function calls
* the entropy source to obtain a nonce
@@ -224,14 +222,9 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx
/**
* \brief This function sets the amount of entropy grabbed on each
- * reseed.
+ * seed or reseed.
*
- * The default value is set by mbedtls_hmac_drbg_seed().
- *
- * \note mbedtls_hmac_drbg_seed() always sets the entropy length
- * to the default value based on the chosen MD algorithm,
- * so this function only has an effect if it is called
- * after mbedtls_hmac_drbg_seed().
+ * See the documentation of mbedtls_hmac_drbg_seed() for the default value.
*
* \param ctx The HMAC_DRBG context.
* \param len The amount of entropy to grab, in bytes.
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/md_internal.h b/features/mbedtls/mbed-crypto/inc/mbedtls/md_internal.h
index bb876efc5b..0922dff9d3 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/md_internal.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/md_internal.h
@@ -79,7 +79,9 @@ extern const mbedtls_md_info_t mbedtls_sha224_info;
extern const mbedtls_md_info_t mbedtls_sha256_info;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
extern const mbedtls_md_info_t mbedtls_sha384_info;
+#endif
extern const mbedtls_md_info_t mbedtls_sha512_info;
#endif
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/pk.h b/features/mbedtls/mbed-crypto/inc/mbedtls/pk.h
index d750004d56..99e7a55a1d 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/pk.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/pk.h
@@ -101,6 +101,58 @@ typedef struct mbedtls_pk_rsassa_pss_options
} mbedtls_pk_rsassa_pss_options;
+/**
+ * \brief Maximum size of a signature made by mbedtls_pk_sign().
+ */
+/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature
+ * size among the supported signature types. Do it by starting at 0,
+ * then incrementally increasing to be large enough for each supported
+ * signature mechanism.
+ *
+ * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled
+ * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C
+ * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT).
+ */
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0
+
+#if ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ) && \
+ MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE
+/* For RSA, the signature can be as large as the bignum module allows.
+ * For RSA_ALT, the signature size is not necessarily tied to what the
+ * bignum module can do, but in the absence of any specific setting,
+ * we use that (rsa_alt_sign_wrap in pk_wrap will check). */
+#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
+#endif
+
+#if defined(MBEDTLS_ECDSA_C) && \
+ MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE
+/* For ECDSA, the ecdsa module exports a constant for the maximum
+ * signature size. */
+#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE
+/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made
+ * through the PSA API in the PSA representation. */
+#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE
+#endif
+
+#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE
+/* The Mbed TLS representation is different for ECDSA signatures:
+ * PSA uses the raw concatenation of r and s,
+ * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs).
+ * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the
+ * types, lengths (represented by up to 2 bytes), and potential leading
+ * zeros of the INTEGERs and the SEQUENCE. */
+#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
+#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 )
+#endif
+#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */
+
/**
* \brief Types for interfacing with the debug module
*/
@@ -442,8 +494,13 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
* \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes)
- * \param sig Place to write the signature
- * \param sig_len Number of bytes written
+ * \param sig Place to write the signature.
+ * It must have enough room for the signature.
+ * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.
+ * You may use a smaller buffer if it is large enough
+ * given the key type.
+ * \param sig_len On successful return,
+ * the number of bytes written to \p sig.
* \param f_rng RNG function
* \param p_rng RNG parameter
*
@@ -474,16 +531,21 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
*
* \param ctx The PK context to use. It must have been set up
* with a private key.
- * \param md_alg Hash algorithm used (see notes)
+ * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign())
* \param hash Hash of the message to sign
- * \param hash_len Hash length or 0 (see notes)
- * \param sig Place to write the signature
- * \param sig_len Number of bytes written
+ * \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign())
+ * \param sig Place to write the signature.
+ * It must have enough room for the signature.
+ * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.
+ * You may use a smaller buffer if it is large enough
+ * given the key type.
+ * \param sig_len On successful return,
+ * the number of bytes written to \p sig.
* \param f_rng RNG function
* \param p_rng RNG parameter
* \param rs_ctx Restart context (NULL to disable restart)
*
- * \return See \c mbedtls_pk_sign(), or
+ * \return See \c mbedtls_pk_sign().
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/psa_util.h b/features/mbedtls/mbed-crypto/inc/mbedtls/psa_util.h
index 8d18fcc57e..513bc5feb7 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/psa_util.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/psa_util.h
@@ -160,79 +160,96 @@ static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg
/* Translations for ECC. */
static inline int mbedtls_psa_get_ecc_oid_from_id(
- psa_ecc_curve_t curve, char const **oid, size_t *oid_len )
+ psa_ecc_curve_t curve, size_t bits,
+ char const **oid, size_t *oid_len )
{
switch( curve )
{
+ case PSA_ECC_CURVE_SECP_R1:
+ switch( bits )
+ {
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
- case PSA_ECC_CURVE_SECP192R1:
- *oid = MBEDTLS_OID_EC_GRP_SECP192R1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 );
- return( 0 );
+ case 192:
+ *oid = MBEDTLS_OID_EC_GRP_SECP192R1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
- case PSA_ECC_CURVE_SECP224R1:
- *oid = MBEDTLS_OID_EC_GRP_SECP224R1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 );
- return( 0 );
+ case 224:
+ *oid = MBEDTLS_OID_EC_GRP_SECP224R1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
- case PSA_ECC_CURVE_SECP256R1:
- *oid = MBEDTLS_OID_EC_GRP_SECP256R1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 );
- return( 0 );
+ case 256:
+ *oid = MBEDTLS_OID_EC_GRP_SECP256R1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
- case PSA_ECC_CURVE_SECP384R1:
- *oid = MBEDTLS_OID_EC_GRP_SECP384R1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 );
- return( 0 );
+ case 384:
+ *oid = MBEDTLS_OID_EC_GRP_SECP384R1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
- case PSA_ECC_CURVE_SECP521R1:
- *oid = MBEDTLS_OID_EC_GRP_SECP521R1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 );
- return( 0 );
+ case 521:
+ *oid = MBEDTLS_OID_EC_GRP_SECP521R1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+ }
+ break;
+ case PSA_ECC_CURVE_SECP_K1:
+ switch( bits )
+ {
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
- case PSA_ECC_CURVE_SECP192K1:
- *oid = MBEDTLS_OID_EC_GRP_SECP192K1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 );
- return( 0 );
+ case 192:
+ *oid = MBEDTLS_OID_EC_GRP_SECP192K1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
- case PSA_ECC_CURVE_SECP224K1:
- *oid = MBEDTLS_OID_EC_GRP_SECP224K1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 );
- return( 0 );
+ case 224:
+ *oid = MBEDTLS_OID_EC_GRP_SECP224K1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
- case PSA_ECC_CURVE_SECP256K1:
- *oid = MBEDTLS_OID_EC_GRP_SECP256K1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 );
- return( 0 );
+ case 256:
+ *oid = MBEDTLS_OID_EC_GRP_SECP256K1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+ }
+ break;
+ case PSA_ECC_CURVE_BRAINPOOL_P_R1:
+ switch( bits )
+ {
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
- case PSA_ECC_CURVE_BRAINPOOL_P256R1:
- *oid = MBEDTLS_OID_EC_GRP_BP256R1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 );
- return( 0 );
+ case 256:
+ *oid = MBEDTLS_OID_EC_GRP_BP256R1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
- case PSA_ECC_CURVE_BRAINPOOL_P384R1:
- *oid = MBEDTLS_OID_EC_GRP_BP384R1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 );
- return( 0 );
+ case 384:
+ *oid = MBEDTLS_OID_EC_GRP_BP384R1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
- case PSA_ECC_CURVE_BRAINPOOL_P512R1:
- *oid = MBEDTLS_OID_EC_GRP_BP512R1;
- *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 );
- return( 0 );
+ case 512:
+ *oid = MBEDTLS_OID_EC_GRP_BP512R1;
+ *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 );
+ return( 0 );
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+ }
+ break;
}
-
- return( -1 );
+ (void) oid;
+ (void) oid_len;
+ return( -1 );
}
#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1
@@ -315,85 +332,6 @@ static inline int mbedtls_psa_get_ecc_oid_from_id(
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
-static inline psa_ecc_curve_t mbedtls_psa_translate_ecc_group( mbedtls_ecp_group_id grpid )
-{
- switch( grpid )
- {
-#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
- case MBEDTLS_ECP_DP_SECP192R1:
- return( PSA_ECC_CURVE_SECP192R1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
- case MBEDTLS_ECP_DP_SECP224R1:
- return( PSA_ECC_CURVE_SECP224R1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
- case MBEDTLS_ECP_DP_SECP256R1:
- return( PSA_ECC_CURVE_SECP256R1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
- case MBEDTLS_ECP_DP_SECP384R1:
- return( PSA_ECC_CURVE_SECP384R1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
- case MBEDTLS_ECP_DP_SECP521R1:
- return( PSA_ECC_CURVE_SECP521R1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
- case MBEDTLS_ECP_DP_BP256R1:
- return( PSA_ECC_CURVE_BRAINPOOL_P256R1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
- case MBEDTLS_ECP_DP_BP384R1:
- return( PSA_ECC_CURVE_BRAINPOOL_P384R1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
- case MBEDTLS_ECP_DP_BP512R1:
- return( PSA_ECC_CURVE_BRAINPOOL_P512R1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
- case MBEDTLS_ECP_DP_CURVE25519:
- return( PSA_ECC_CURVE_CURVE25519 );
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
- case MBEDTLS_ECP_DP_SECP192K1:
- return( PSA_ECC_CURVE_SECP192K1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
- case MBEDTLS_ECP_DP_SECP224K1:
- return( PSA_ECC_CURVE_SECP224K1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
- case MBEDTLS_ECP_DP_SECP256K1:
- return( PSA_ECC_CURVE_SECP256K1 );
-#endif
-#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
- case MBEDTLS_ECP_DP_CURVE448:
- return( PSA_ECC_CURVE_CURVE448 );
-#endif
- default:
- return( 0 );
- }
-}
-
-
-#define MBEDTLS_PSA_ECC_KEY_BITS_OF_CURVE( curve ) \
- ( curve == PSA_ECC_CURVE_SECP192R1 ? 192 : \
- curve == PSA_ECC_CURVE_SECP224R1 ? 224 : \
- curve == PSA_ECC_CURVE_SECP256R1 ? 256 : \
- curve == PSA_ECC_CURVE_SECP384R1 ? 384 : \
- curve == PSA_ECC_CURVE_SECP521R1 ? 521 : \
- curve == PSA_ECC_CURVE_SECP192K1 ? 192 : \
- curve == PSA_ECC_CURVE_SECP224K1 ? 224 : \
- curve == PSA_ECC_CURVE_SECP256K1 ? 256 : \
- curve == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \
- curve == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \
- curve == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \
- 0 )
-
-#define MBEDTLS_PSA_ECC_KEY_BYTES_OF_CURVE( curve ) \
- ( ( MBEDTLS_PSA_ECC_KEY_BITS_OF_CURVE( curve ) + 7 ) / 8 )
-
/* Translations for PK layer */
static inline int mbedtls_psa_err_translate_pk( psa_status_t status )
@@ -427,13 +365,18 @@ static inline int mbedtls_psa_err_translate_pk( psa_status_t status )
/* This function transforms an ECC group identifier from
* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
* into a PSA ECC group identifier. */
-static inline psa_ecc_curve_t mbedtls_psa_parse_tls_ecc_group(
- uint16_t tls_ecc_grp_reg_id )
+#if defined(MBEDTLS_ECP_C)
+static inline psa_key_type_t mbedtls_psa_parse_tls_ecc_group(
+ uint16_t tls_ecc_grp_reg_id, size_t *bits )
{
- /* The PSA identifiers are currently aligned with those from
- * the TLS Supported Groups registry, so no conversion is necessary. */
- return( (psa_ecc_curve_t) tls_ecc_grp_reg_id );
+ const mbedtls_ecp_curve_info *curve_info =
+ mbedtls_ecp_curve_info_from_tls_id( tls_ecc_grp_reg_id );
+ if( curve_info == NULL )
+ return( 0 );
+ return( PSA_KEY_TYPE_ECC_KEY_PAIR(
+ mbedtls_ecc_group_to_psa( curve_info->grp_id, bits ) ) );
}
+#endif /* MBEDTLS_ECP_C */
/* This function takes a buffer holding an EC public key
* exported through psa_export_public_key(), and converts
@@ -460,15 +403,12 @@ static inline int mbedtls_psa_tls_psa_ec_to_ecpoint( unsigned char *src,
* exchanges) and converts it into a format that the PSA key
* agreement API understands.
*/
-static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( psa_ecc_curve_t curve,
- unsigned char const *src,
+static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src,
size_t srclen,
unsigned char *dst,
size_t dstlen,
size_t *olen )
{
- ((void) curve);
-
if( srclen > dstlen )
return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/rsa.h b/features/mbedtls/mbed-crypto/inc/mbedtls/rsa.h
index 840540b0d9..ec8d0d8ded 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/rsa.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/rsa.h
@@ -907,7 +907,8 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
* the size of the hash corresponding to \p md_alg.
* \param sig The buffer to hold the signature. This must be a writable
* buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
- * for an 2048-bit RSA modulus.
+ * for an 2048-bit RSA modulus. A buffer length of
+ * #MBEDTLS_MPI_MAX_SIZE is always safe.
*
* \return \c 0 if the signing operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -954,7 +955,8 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
* the size of the hash corresponding to \p md_alg.
* \param sig The buffer to hold the signature. This must be a writable
* buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
- * for an 2048-bit RSA modulus.
+ * for an 2048-bit RSA modulus. A buffer length of
+ * #MBEDTLS_MPI_MAX_SIZE is always safe.
*
* \return \c 0 if the signing operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -1015,7 +1017,8 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
* the size of the hash corresponding to \p md_alg.
* \param sig The buffer to hold the signature. This must be a writable
* buffer of length \c ctx->len Bytes. For example, \c 256 Bytes
- * for an 2048-bit RSA modulus.
+ * for an 2048-bit RSA modulus. A buffer length of
+ * #MBEDTLS_MPI_MAX_SIZE is always safe.
*
* \return \c 0 if the signing operation was successful.
* \return An \c MBEDTLS_ERR_RSA_XXX error code on failure.
diff --git a/features/mbedtls/mbed-crypto/inc/mbedtls/sha512.h b/features/mbedtls/mbed-crypto/inc/mbedtls/sha512.h
index 48923e5bc6..8e54ce01a7 100644
--- a/features/mbedtls/mbed-crypto/inc/mbedtls/sha512.h
+++ b/features/mbedtls/mbed-crypto/inc/mbedtls/sha512.h
@@ -59,8 +59,10 @@ typedef struct mbedtls_sha512_context
uint64_t total[2]; /*!< The number of Bytes processed. */
uint64_t state[8]; /*!< The intermediate digest state. */
unsigned char buffer[128]; /*!< The data block being processed. */
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
int is384; /*!< Determines which function to use:
0: Use SHA-512, or 1: Use SHA-384. */
+#endif
}
mbedtls_sha512_context;
@@ -101,7 +103,11 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
*
* \param ctx The SHA-512 context to use. This must be initialized.
* \param is384 Determines which function to use. This must be
- * either \c for SHA-512, or \c 1 for SHA-384.
+ * either \c 0 for SHA-512, or \c 1 for SHA-384.
+ *
+ * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must
+ * be \c 0, or the function will return
+ * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.
*
* \return \c 0 on success.
* \return A negative error code on failure.
@@ -169,6 +175,9 @@ int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
* \param ctx The SHA-512 context to use. This must be initialized.
* \param is384 Determines which function to use. This must be either
* \c 0 for SHA-512 or \c 1 for SHA-384.
+ *
+ * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must
+ * be \c 0, or the function will fail to work.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
int is384 );
@@ -239,6 +248,10 @@ MBEDTLS_DEPRECATED void mbedtls_sha512_process(
* \param is384 Determines which function to use. This must be either
* \c 0 for SHA-512, or \c 1 for SHA-384.
*
+ * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must
+ * be \c 0, or the function will return
+ * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.
+ *
* \return \c 0 on success.
* \return A negative error code on failure.
*/
@@ -273,6 +286,9 @@ int mbedtls_sha512_ret( const unsigned char *input,
* be a writable buffer of length \c 64 Bytes.
* \param is384 Determines which function to use. This must be either
* \c 0 for SHA-512, or \c 1 for SHA-384.
+ *
+ * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must
+ * be \c 0, or the function will fail to work.
*/
MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input,
size_t ilen,
diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto.h b/features/mbedtls/mbed-crypto/inc/psa/crypto.h
index 7291c3e576..2b07b7471c 100644
--- a/features/mbedtls/mbed-crypto/inc/psa/crypto.h
+++ b/features/mbedtls/mbed-crypto/inc/psa/crypto.h
@@ -932,7 +932,7 @@ psa_status_t psa_hash_compare(psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
const uint8_t *hash,
- const size_t hash_length);
+ size_t hash_length);
/** The type of the state data structure for multipart hash operations.
*
@@ -1300,7 +1300,7 @@ psa_status_t psa_mac_verify(psa_key_handle_t handle,
const uint8_t *input,
size_t input_length,
const uint8_t *mac,
- const size_t mac_length);
+ size_t mac_length);
/** The type of the state data structure for multipart MAC operations.
*
@@ -2879,7 +2879,7 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation);
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p signature buffer is too small. You can
* determine a sufficient buffer size by calling
- * #PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
* where \c key_type and \c key_bits are the type and bit-size
* respectively of \p handle.
* \retval #PSA_ERROR_NOT_SUPPORTED
@@ -2895,13 +2895,13 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation);
* It is implementation-dependent whether a failure to initialize
* results in this error code.
*/
-psa_status_t psa_asymmetric_sign(psa_key_handle_t handle,
- psa_algorithm_t alg,
- const uint8_t *hash,
- size_t hash_length,
- uint8_t *signature,
- size_t signature_size,
- size_t *signature_length);
+psa_status_t psa_sign_hash(psa_key_handle_t handle,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ uint8_t *signature,
+ size_t signature_size,
+ size_t *signature_length);
/**
* \brief Verify the signature a hash or short message using a public key.
@@ -2941,12 +2941,12 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t handle,
* It is implementation-dependent whether a failure to initialize
* results in this error code.
*/
-psa_status_t psa_asymmetric_verify(psa_key_handle_t handle,
- psa_algorithm_t alg,
- const uint8_t *hash,
- size_t hash_length,
- const uint8_t *signature,
- size_t signature_length);
+psa_status_t psa_verify_hash(psa_key_handle_t handle,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_length);
/**
* \brief Encrypt a short message with a public key.
@@ -3502,10 +3502,10 @@ psa_status_t psa_key_derivation_output_bytes(
* length is determined by the curve, and sets the mandatory bits
* accordingly. That is:
*
- * - #PSA_ECC_CURVE_CURVE25519: draw a 32-byte string
- * and process it as specified in RFC 7748 §5.
- * - #PSA_ECC_CURVE_CURVE448: draw a 56-byte string
- * and process it as specified in RFC 7748 §5.
+ * - Curve25519 (#PSA_ECC_CURVE_MONTGOMERY, 255 bits): draw a 32-byte
+ * string and process it as specified in RFC 7748 §5.
+ * - Curve448 (#PSA_ECC_CURVE_MONTGOMERY, 448 bits): draw a 56-byte
+ * string and process it as specified in RFC 7748 §5.
*
* - For key types for which the key is represented by a single sequence of
* \p bits bits with constraints as to which bit sequences are acceptable,
diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_compat.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_compat.h
new file mode 100644
index 0000000000..1ed5f052b2
--- /dev/null
+++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_compat.h
@@ -0,0 +1,196 @@
+/**
+ * \file psa/crypto_compat.h
+ *
+ * \brief PSA cryptography module: Backward compatibility aliases
+ *
+ * This header declares alternative names for macro and functions.
+ * New application code should not use these names.
+ * These names may be removed in a future version of Mbed Crypto.
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ */
+/*
+ * Copyright (C) 2019, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_COMPAT_H
+#define PSA_CRYPTO_COMPAT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+
+/*
+ * Mechanism for declaring deprecated values
+ */
+#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED)
+#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated))
+#else
+#define MBEDTLS_PSA_DEPRECATED
+#endif
+
+typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t;
+typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t;
+typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t;
+typedef MBEDTLS_PSA_DEPRECATED psa_ecc_curve_t mbedtls_deprecated_psa_ecc_curve_t;
+typedef MBEDTLS_PSA_DEPRECATED psa_dh_group_t mbedtls_deprecated_psa_dh_group_t;
+
+#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \
+ ( (mbedtls_deprecated_##type) ( value ) )
+
+/*
+ * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2)
+ */
+#define PSA_ERROR_UNKNOWN_ERROR \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR )
+#define PSA_ERROR_OCCUPIED_SLOT \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS )
+#define PSA_ERROR_EMPTY_SLOT \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST )
+#define PSA_ERROR_INSUFFICIENT_CAPACITY \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA )
+#define PSA_ERROR_TAMPERING_DETECTED \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED )
+
+/*
+ * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3)
+ */
+#define PSA_KEY_USAGE_SIGN \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH )
+#define PSA_KEY_USAGE_VERIFY \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH )
+
+/*
+ * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3)
+ */
+#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \
+ MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE )
+#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \
+ MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) )
+
+/*
+ * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3)
+ */
+MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_sign( psa_key_handle_t key,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ uint8_t *signature,
+ size_t signature_size,
+ size_t *signature_length )
+{
+ return psa_sign_hash( key, alg, hash, hash_length, signature, signature_size, signature_length );
+}
+
+MBEDTLS_PSA_DEPRECATED static inline psa_status_t psa_asymmetric_verify( psa_key_handle_t key,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_length )
+{
+ return psa_verify_hash( key, alg, hash, hash_length, signature, signature_length );
+}
+
+
+
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+/*
+ * Size-specific elliptic curve and Diffie-Hellman group names
+ */
+#define PSA_ECC_CURVE_SECP160K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 )
+#define PSA_ECC_CURVE_SECP192K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 )
+#define PSA_ECC_CURVE_SECP224K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 )
+#define PSA_ECC_CURVE_SECP256K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_K1 )
+#define PSA_ECC_CURVE_SECP160R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 )
+#define PSA_ECC_CURVE_SECP192R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 )
+#define PSA_ECC_CURVE_SECP224R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 )
+#define PSA_ECC_CURVE_SECP256R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 )
+#define PSA_ECC_CURVE_SECP384R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 )
+#define PSA_ECC_CURVE_SECP521R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R1 )
+#define PSA_ECC_CURVE_SECP160R2 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECP_R2 )
+#define PSA_ECC_CURVE_SECT163K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 )
+#define PSA_ECC_CURVE_SECT233K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 )
+#define PSA_ECC_CURVE_SECT239K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 )
+#define PSA_ECC_CURVE_SECT283K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 )
+#define PSA_ECC_CURVE_SECT409K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 )
+#define PSA_ECC_CURVE_SECT571K1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_K1 )
+#define PSA_ECC_CURVE_SECT163R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 )
+#define PSA_ECC_CURVE_SECT193R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 )
+#define PSA_ECC_CURVE_SECT233R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 )
+#define PSA_ECC_CURVE_SECT283R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 )
+#define PSA_ECC_CURVE_SECT409R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 )
+#define PSA_ECC_CURVE_SECT571R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R1 )
+#define PSA_ECC_CURVE_SECT163R2 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R2 )
+#define PSA_ECC_CURVE_SECT193R2 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_SECT_R2 )
+#define PSA_ECC_CURVE_BRAINPOOL_P256R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 )
+#define PSA_ECC_CURVE_BRAINPOOL_P384R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 )
+#define PSA_ECC_CURVE_BRAINPOOL_P512R1 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_BRAINPOOL_P_R1 )
+#define PSA_ECC_CURVE_CURVE25519 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_MONTGOMERY )
+#define PSA_ECC_CURVE_CURVE448 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_ecc_curve_t, PSA_ECC_CURVE_MONTGOMERY )
+
+#define PSA_DH_GROUP_FFDHE2048 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 )
+#define PSA_DH_GROUP_FFDHE3072 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 )
+#define PSA_DH_GROUP_FFDHE4096 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 )
+#define PSA_DH_GROUP_FFDHE6144 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 )
+#define PSA_DH_GROUP_FFDHE8192 \
+ MBEDTLS_DEPRECATED_CONSTANT( psa_dh_group_t, PSA_DH_GROUP_RFC7919 )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PSA_CRYPTO_COMPAT_H */
diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h
index c5313d619e..e9fa31189c 100644
--- a/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h
+++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h
@@ -32,6 +32,8 @@
#include "mbedtls/platform_util.h"
+#include "crypto_compat.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -39,21 +41,6 @@ extern "C" {
/* UID for secure storage seed */
#define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52
-/*
- * Deprecated PSA Crypto error code definitions
- */
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-#define PSA_ERROR_UNKNOWN_ERROR \
- MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( PSA_ERROR_GENERIC_ERROR )
-#define PSA_ERROR_OCCUPIED_SLOT \
- MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( PSA_ERROR_ALREADY_EXISTS )
-#define PSA_ERROR_EMPTY_SLOT \
- MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( PSA_ERROR_DOES_NOT_EXIST )
-#define PSA_ERROR_INSUFFICIENT_CAPACITY \
- MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( PSA_ERROR_INSUFFICIENT_DATA )
-#define PSA_ERROR_TAMPERING_DETECTED \
- MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( PSA_ERROR_CORRUPTION_DETECTED )
-#endif
/** \addtogroup attributes
* @{
@@ -342,7 +329,7 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
* string. The length of the byte string is the length of the base prime `p`
* in bytes.
*/
-#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000)
+#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x4002)
/** DSA key pair (private and public key).
*
@@ -360,7 +347,7 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
* Add 1 to the resulting integer and use this as the private key *x*.
*
*/
-#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x70020000)
+#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x7002)
/** Whether a key type is an DSA key (pair or public-only). */
#define PSA_KEY_TYPE_IS_DSA(type) \
@@ -384,7 +371,7 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
#define PSA_ALG_DSA(hash_alg) \
(PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x10050000)
-#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000)
+#define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG
/** Deterministic DSA signature with hashing.
*
* This is the deterministic variant defined by RFC 6979 of
@@ -431,9 +418,7 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
* #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_GROUP_CUSTOM), the group data comes
* from domain parameters set by psa_set_key_domain_parameters().
*/
-/* This value is a deprecated value meaning an explicit curve in the IANA
- * registry. */
-#define PSA_DH_GROUP_CUSTOM ((psa_dh_group_t) 0xff01)
+#define PSA_DH_GROUP_CUSTOM ((psa_dh_group_t) 0x7e)
/**
@@ -573,6 +558,50 @@ psa_status_t psa_get_key_domain_parameters(
/**@}*/
+/** \defgroup psa_tls_helpers TLS helper functions
+ * @{
+ */
+
+#if defined(MBEDTLS_ECP_C)
+#include
+
+/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA.
+ *
+ * \note This function is provided solely for the convenience of
+ * Mbed TLS and may be removed at any time without notice.
+ *
+ * \param grpid An Mbed TLS elliptic curve identifier
+ * (`MBEDTLS_ECP_DP_xxx`).
+ * \param[out] bits On success, the bit size of the curve.
+ *
+ * \return The corresponding PSA elliptic curve identifier
+ * (`PSA_ECC_CURVE_xxx`).
+ * \return \c 0 on failure (\p grpid is not recognized).
+ */
+psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid,
+ size_t *bits );
+
+/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS.
+ *
+ * \note This function is provided solely for the convenience of
+ * Mbed TLS and may be removed at any time without notice.
+ *
+ * \param curve A PSA elliptic curve identifier
+ * (`PSA_ECC_CURVE_xxx`).
+ * \param byte_length The byte-length of a private key on \p curve.
+ *
+ * \return The corresponding Mbed TLS elliptic curve identifier
+ * (`MBEDTLS_ECP_DP_xxx`).
+ * \return #MBEDTLS_ECP_DP_NONE if \c curve is not recognized.
+ * \return #MBEDTLS_ECP_DP_NONE if \p byte_length is not
+ * correct for \p curve.
+ */
+mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve,
+ size_t byte_length );
+#endif /* MBEDTLS_ECP_C */
+
+/**@}*/
+
#ifdef __cplusplus
}
#endif
diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h
index bcca72482f..1f04222c24 100644
--- a/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h
+++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h
@@ -190,47 +190,6 @@
#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0
#endif
-/** Bit size associated with an elliptic curve.
- *
- * \param curve An elliptic curve (value of type #psa_ecc_curve_t).
- *
- * \return The size associated with \p curve, in bits.
- * This may be 0 if the implementation does not support
- * the specified curve.
- */
-#define PSA_ECC_CURVE_BITS(curve) \
- ((curve) == PSA_ECC_CURVE_SECT163K1 ? 163 : \
- (curve) == PSA_ECC_CURVE_SECT163R1 ? 163 : \
- (curve) == PSA_ECC_CURVE_SECT163R2 ? 163 : \
- (curve) == PSA_ECC_CURVE_SECT193R1 ? 193 : \
- (curve) == PSA_ECC_CURVE_SECT193R2 ? 193 : \
- (curve) == PSA_ECC_CURVE_SECT233K1 ? 233 : \
- (curve) == PSA_ECC_CURVE_SECT233R1 ? 233 : \
- (curve) == PSA_ECC_CURVE_SECT239K1 ? 239 : \
- (curve) == PSA_ECC_CURVE_SECT283K1 ? 283 : \
- (curve) == PSA_ECC_CURVE_SECT283R1 ? 283 : \
- (curve) == PSA_ECC_CURVE_SECT409K1 ? 409 : \
- (curve) == PSA_ECC_CURVE_SECT409R1 ? 409 : \
- (curve) == PSA_ECC_CURVE_SECT571K1 ? 571 : \
- (curve) == PSA_ECC_CURVE_SECT571R1 ? 571 : \
- (curve) == PSA_ECC_CURVE_SECP160K1 ? 160 : \
- (curve) == PSA_ECC_CURVE_SECP160R1 ? 160 : \
- (curve) == PSA_ECC_CURVE_SECP160R2 ? 160 : \
- (curve) == PSA_ECC_CURVE_SECP192K1 ? 192 : \
- (curve) == PSA_ECC_CURVE_SECP192R1 ? 192 : \
- (curve) == PSA_ECC_CURVE_SECP224K1 ? 224 : \
- (curve) == PSA_ECC_CURVE_SECP224R1 ? 224 : \
- (curve) == PSA_ECC_CURVE_SECP256K1 ? 256 : \
- (curve) == PSA_ECC_CURVE_SECP256R1 ? 256 : \
- (curve) == PSA_ECC_CURVE_SECP384R1 ? 384 : \
- (curve) == PSA_ECC_CURVE_SECP521R1 ? 521 : \
- (curve) == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \
- (curve) == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \
- (curve) == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \
- (curve) == PSA_ECC_CURVE_CURVE25519 ? 255 : \
- (curve) == PSA_ECC_CURVE_CURVE448 ? 448 : \
- 0)
-
/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN
*
* This macro returns the maximum length of the PSK supported
@@ -247,21 +206,6 @@
*/
#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128
-/** \def PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE
- *
- * Maximum size of an asymmetric signature.
- *
- * This macro must expand to a compile-time constant integer. This value
- * should be the maximum size of a MAC supported by the implementation,
- * in bytes, and must be no smaller than this maximum.
- */
-#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \
- PSA_BITS_TO_BYTES( \
- PSA_VENDOR_RSA_MAX_KEY_BITS > PSA_VENDOR_ECC_MAX_CURVE_BITS ? \
- PSA_VENDOR_RSA_MAX_KEY_BITS : \
- PSA_VENDOR_ECC_MAX_CURVE_BITS \
- )
-
/** The maximum size of a block cipher supported by the implementation. */
#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16
@@ -426,7 +370,7 @@
#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \
(PSA_BITS_TO_BYTES(curve_bits) * 2)
-/** Sufficient signature buffer size for psa_asymmetric_sign().
+/** Sufficient signature buffer size for psa_sign_hash().
*
* This macro returns a sufficient buffer size for a signature using a key
* of the specified type and size, with the specified algorithm.
@@ -444,7 +388,7 @@
*
* \return If the parameters are valid and supported, return
* a buffer size in bytes that guarantees that
- * psa_asymmetric_sign() will not fail with
+ * psa_sign_hash() will not fail with
* #PSA_ERROR_BUFFER_TOO_SMALL.
* If the parameters are a valid combination that is not supported
* by the implementation, this macro shall return either a
@@ -452,11 +396,27 @@
* If the parameters are not valid, the
* return value is unspecified.
*/
-#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \
+#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \
(PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \
PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \
((void)alg, 0))
+#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \
+ PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
+
+/** \def PSA_SIGNATURE_MAX_SIZE
+ *
+ * Maximum size of an asymmetric signature.
+ *
+ * This macro must expand to a compile-time constant integer. This value
+ * should be the maximum size of a signature supported by the implementation,
+ * in bytes, and must be no smaller than this maximum.
+ */
+#define PSA_SIGNATURE_MAX_SIZE \
+ (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \
+ PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \
+ PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE)
+
/** Sufficient output buffer size for psa_asymmetric_encrypt().
*
* This macro returns a sufficient buffer size for a ciphertext produced using
@@ -681,7 +641,7 @@
*
* \return If the parameters are valid and supported, return
* a buffer size in bytes that guarantees that
- * psa_asymmetric_sign() will not fail with
+ * psa_sign_hash() will not fail with
* #PSA_ERROR_BUFFER_TOO_SMALL.
* If the parameters are a valid combination that is not supported
* by the implementation, this macro shall return either a
diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h
index c4f9acd460..d96c66e5c4 100644
--- a/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h
+++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h
@@ -63,85 +63,29 @@ typedef int32_t psa_status_t;
/** \brief Encoding of a key type.
*/
-typedef uint32_t psa_key_type_t;
+typedef uint16_t psa_key_type_t;
-/** The type of PSA elliptic curve identifiers.
+/** The type of PSA elliptic curve family identifiers.
*
* The curve identifier is required to create an ECC key using the
* PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY()
* macros.
*
- * The encoding of curve identifiers is taken from the
- * TLS Supported Groups Registry (formerly known as the
- * TLS EC Named Curve Registry)
- * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
- *
- * This specification defines identifiers for some of the curves in the IANA
- * registry. Implementations that support other curves that are in the IANA
- * registry should use the IANA value and a implementation-specific identifier.
- * Implemenations that support non-IANA curves should use one of the following
- * approaches for allocating a key type:
- *
- * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to
- * #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use
- * range.
- * 2. Use a ::psa_key_type_t value that is vendor-defined.
- *
- * The first option is recommended.
+ * Values defined by this standard will never be in the range 0x80-0xff.
+ * Vendors who define additional families must use an encoding in this range.
*/
-typedef uint16_t psa_ecc_curve_t;
+typedef uint8_t psa_ecc_curve_t;
-/** The type of PSA Diffie-Hellman group identifiers.
+/** The type of PSA Diffie-Hellman group family identifiers.
*
* The group identifier is required to create an Diffie-Hellman key using the
* PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY()
* macros.
*
- * The encoding of group identifiers is taken from the
- * TLS Supported Groups Registry (formerly known as the
- * TLS EC Named Curve Registry)
- * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
- *
- * This specification defines identifiers for some of the groups in the IANA
- * registry. Implementations that support other groups that are in the IANA
- * registry should use the IANA value and a implementation-specific identifier.
- * Implemenations that support non-IANA groups should use one of the following
- * approaches for allocating a key type:
- *
- * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to
- * #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use
- * range.
- * 2. Select a ::psa_dh_group_t value from the named groups allocated for
- * GREASE in the IETF draft specification. The GREASE specification and
- * values are listed below.
- * 3. Use a ::psa_key_type_t value that is vendor-defined.
- *
- * Option 1 or 2 are recommended.
- *
- * The current draft of the GREASE specification is
- * https://datatracker.ietf.org/doc/draft-ietf-tls-grease
- *
- * The following GREASE values are allocated for named groups:
- * \code
- * 0x0A0A
- * 0x1A1A
- * 0x2A2A
- * 0x3A3A
- * 0x4A4A
- * 0x5A5A
- * 0x6A6A
- * 0x7A7A
- * 0x8A8A
- * 0x9A9A
- * 0xAAAA
- * 0xBABA
- * 0xCACA
- * 0xDADA
- * 0xEAEA
- * 0xFAFA
- * \endcode
+ * Values defined by this standard will never be in the range 0x80-0xff.
+ * Vendors who define additional families must use an encoding in this range.
*/
-typedef uint16_t psa_dh_group_t;
+typedef uint8_t psa_dh_group_t;
/** \brief Encoding of a cryptographic algorithm.
*
diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h
index 1e0c2136a0..baaabff1e0 100644
--- a/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h
+++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h
@@ -282,7 +282,7 @@
*
* Zero is not the encoding of any key type.
*/
-#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000)
+#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x0000)
/** Vendor-defined key type flag.
*
@@ -291,15 +291,15 @@
* must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should
* respect the bitwise structure used by standard encodings whenever practical.
*/
-#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000)
+#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x8000)
-#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000)
-#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000)
-#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000)
-#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000)
-#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000)
+#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7000)
+#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x1000)
+#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x2000)
+#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x4000)
+#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x7000)
-#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000)
+#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x3000)
/** Whether a key type is vendor-defined.
*
@@ -313,8 +313,8 @@
* This encompasses both symmetric keys and non-key data.
*/
#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \
- (((type) & PSA_KEY_TYPE_CATEGORY_MASK & ~(psa_key_type_t)0x10000000) == \
- PSA_KEY_TYPE_CATEGORY_SYMMETRIC)
+ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \
+ ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC)
/** Whether a key type is asymmetric: either a key pair or a public key. */
#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \
@@ -357,7 +357,7 @@
*
* A "key" of this type cannot be used for any cryptographic operation.
* Applications may use this type to store arbitrary data in the keystore. */
-#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x50000001)
+#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x1001)
/** HMAC key.
*
@@ -367,21 +367,21 @@
* HMAC keys should generally have the same size as the underlying hash.
* This size can be calculated with #PSA_HASH_SIZE(\c alg) where
* \c alg is the HMAC algorithm or the underlying hash algorithm. */
-#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000)
+#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x1100)
/** A secret for key derivation.
*
* The key policy determines which key derivation algorithm the key
* can be used for.
*/
-#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000)
+#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x1200)
/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher.
*
* The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or
* 32 bytes (AES-256).
*/
-#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x40000001)
+#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x2400)
/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).
*
@@ -392,17 +392,17 @@
* deprecated and should only be used to decrypt legacy data. 3-key 3DES
* is weak and deprecated and should only be used in legacy protocols.
*/
-#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002)
+#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x2301)
/** Key for a cipher, AEAD or MAC algorithm based on the
* Camellia block cipher. */
-#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003)
+#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x2403)
/** Key for the RC4 stream cipher.
*
* Note that RC4 is weak and deprecated and should only be used in
* legacy protocols. */
-#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004)
+#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x2002)
/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm.
*
@@ -411,19 +411,19 @@
* Implementations must support 12-byte nonces, may support 8-byte nonces,
* and should reject other sizes.
*/
-#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x40000005)
+#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x2004)
/** RSA public key. */
-#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000)
+#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x4001)
/** RSA key pair (private and public key). */
-#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x70010000)
+#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x7001)
/** Whether a key type is an RSA key (pair or public-only). */
#define PSA_KEY_TYPE_IS_RSA(type) \
(PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY)
-#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000)
-#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x70030000)
-#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff)
+#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x4100)
+#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x7100)
+#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x00ff)
/** Elliptic curve key pair.
*
* \param curve A value of type ::psa_ecc_curve_t that identifies the
@@ -458,70 +458,82 @@
((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \
0))
-/* The encoding of curve identifiers is currently aligned with the
- * TLS Supported Groups Registry (formerly known as the
- * TLS EC Named Curve Registry)
- * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
- * The values are defined by RFC 8422 and RFC 7027. */
-#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001)
-#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002)
-#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003)
-#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004)
-#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005)
-#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006)
-#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007)
-#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008)
-#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009)
-#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a)
-#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b)
-#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c)
-#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d)
-#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e)
-#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f)
-#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010)
-#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011)
-#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012)
-#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013)
-#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014)
-#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015)
-#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016)
-#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017)
-#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018)
-#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019)
-#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a)
-#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b)
-#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c)
-/** Curve25519.
+/** SEC Koblitz curves over prime fields.
*
- * This is the curve defined in Bernstein et al.,
- * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006.
- * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve.
+ * This family comprises the following curves:
+ * secp192k1, secp224k1, secp256k1.
+ * They are defined in _Standards for Efficient Cryptography_,
+ * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
+ * https://www.secg.org/sec2-v2.pdf
*/
-#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d)
-/** Curve448
- *
- * This is the curve defined in Hamburg,
- * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015.
- * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve.
- */
-#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e)
+#define PSA_ECC_CURVE_SECP_K1 ((psa_ecc_curve_t) 0x17)
-/** Minimum value for a vendor-defined ECC curve identifier
+/** SEC random curves over prime fields.
*
- * The range for vendor-defined curve identifiers is a subset of the IANA
- * registry private use range, `0xfe00` - `0xfeff`.
+ * This family comprises the following curves:
+ * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1.
+ * They are defined in _Standards for Efficient Cryptography_,
+ * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
+ * https://www.secg.org/sec2-v2.pdf
*/
-#define PSA_ECC_CURVE_VENDOR_MIN ((psa_ecc_curve_t) 0xfe00)
-/** Maximum value for a vendor-defined ECC curve identifier
- *
- * The range for vendor-defined curve identifiers is a subset of the IANA
- * registry private use range, `0xfe00` - `0xfeff`.
- */
-#define PSA_ECC_CURVE_VENDOR_MAX ((psa_ecc_curve_t) 0xfe7f)
+#define PSA_ECC_CURVE_SECP_R1 ((psa_ecc_curve_t) 0x12)
+/* SECP160R2 (SEC2 v1, obsolete) */
+#define PSA_ECC_CURVE_SECP_R2 ((psa_ecc_curve_t) 0x1b)
-#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000)
-#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x70040000)
-#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff)
+/** SEC Koblitz curves over binary fields.
+ *
+ * This family comprises the following curves:
+ * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1.
+ * They are defined in _Standards for Efficient Cryptography_,
+ * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
+ * https://www.secg.org/sec2-v2.pdf
+ */
+#define PSA_ECC_CURVE_SECT_K1 ((psa_ecc_curve_t) 0x27)
+
+/** SEC random curves over binary fields.
+ *
+ * This family comprises the following curves:
+ * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1.
+ * They are defined in _Standards for Efficient Cryptography_,
+ * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
+ * https://www.secg.org/sec2-v2.pdf
+ */
+#define PSA_ECC_CURVE_SECT_R1 ((psa_ecc_curve_t) 0x22)
+
+/** SEC additional random curves over binary fields.
+ *
+ * This family comprises the following curve:
+ * sect163r2.
+ * It is defined in _Standards for Efficient Cryptography_,
+ * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
+ * https://www.secg.org/sec2-v2.pdf
+ */
+#define PSA_ECC_CURVE_SECT_R2 ((psa_ecc_curve_t) 0x2b)
+
+/** Brainpool P random curves.
+ *
+ * This family comprises the following curves:
+ * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1,
+ * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1.
+ * It is defined in RFC 5639.
+ */
+#define PSA_ECC_CURVE_BRAINPOOL_P_R1 ((psa_ecc_curve_t) 0x30)
+
+/** Curve25519 and Curve448.
+ *
+ * This family comprises the following Montgomery curves:
+ * - 255-bit: Bernstein et al.,
+ * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006.
+ * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve.
+ * - 448-bit: Hamburg,
+ * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015.
+ * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve.
+ */
+#define PSA_ECC_CURVE_MONTGOMERY ((psa_ecc_curve_t) 0x41)
+
+#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x4200)
+#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x7200)
+#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x00ff)
/** Diffie-Hellman key pair.
*
* \param group A value of type ::psa_dh_group_t that identifies the
@@ -556,30 +568,16 @@
((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \
0))
-/* The encoding of group identifiers is currently aligned with the
- * TLS Supported Groups Registry (formerly known as the
- * TLS EC Named Curve Registry)
- * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
- * The values are defined by RFC 7919. */
-#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100)
-#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101)
-#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102)
-#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103)
-#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104)
-
-/** Minimum value for a vendor-defined Diffie Hellman group identifier
+/** Diffie-Hellman groups defined in RFC 7919 Appendix A.
*
- * The range for vendor-defined group identifiers is a subset of the IANA
- * registry private use range, `0x01fc` - `0x01ff`.
+ * This family includes groups with the following key sizes (in bits):
+ * 2048, 3072, 4096, 6144, 8192. A given implementation may support
+ * all of these sizes or only a subset.
*/
-#define PSA_DH_GROUP_VENDOR_MIN ((psa_dh_group_t) 0x01fc)
-/** Maximum value for a vendor-defined Diffie Hellman group identifier
- *
- * The range for vendor-defined group identifiers is a subset of the IANA
- * registry private use range, `0x01fc` - `0x01ff`.
- */
-#define PSA_DH_GROUP_VENDOR_MAX ((psa_dh_group_t) 0x01fd)
+#define PSA_DH_GROUP_RFC7919 ((psa_dh_group_t) 0x03)
+#define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \
+ (((type) >> 8) & 7)
/** The block size of a block cipher.
*
* \param type A cipher key type (value of type #psa_key_type_t).
@@ -599,12 +597,9 @@
* \warning This macro may evaluate its argument multiple times.
*/
#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \
- ( \
- (type) == PSA_KEY_TYPE_AES ? 16 : \
- (type) == PSA_KEY_TYPE_DES ? 8 : \
- (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \
- (type) == PSA_KEY_TYPE_ARC4 ? 1 : \
- 0)
+ (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \
+ 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \
+ 0u)
/** Vendor-defined algorithm flag.
*
@@ -766,17 +761,17 @@
* Then you may create and use a key as follows:
* - Set the key usage field using #PSA_ALG_ANY_HASH, for example:
* ```
- * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN); // or VERIFY
+ * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY
* psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH));
* ```
* - Import or generate key material.
- * - Call psa_asymmetric_sign() or psa_asymmetric_verify(), passing
+ * - Call psa_sign_hash() or psa_verify_hash(), passing
* an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each
* call to sign or verify a message may use a different hash.
* ```
- * psa_asymmetric_sign(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...);
- * psa_asymmetric_sign(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...);
- * psa_asymmetric_sign(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...);
+ * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...);
+ * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...);
+ * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...);
* ```
*
* This value may not be used to build other algorithms that are
@@ -1197,11 +1192,12 @@
*/
#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \
(PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK))
+#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000)
#define PSA_ALG_IS_ECDSA(alg) \
- (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \
+ (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \
PSA_ALG_ECDSA_BASE)
#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \
- (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0)
+ (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0)
#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \
(PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg))
#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \
@@ -1640,7 +1636,7 @@
*
* For a key pair, this concerns the private key.
*/
-#define PSA_KEY_USAGE_SIGN ((psa_key_usage_t)0x00000400)
+#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400)
/** Whether the key may be used to verify a message signature.
*
@@ -1650,7 +1646,7 @@
*
* For a key pair, this concerns the public key.
*/
-#define PSA_KEY_USAGE_VERIFY ((psa_key_usage_t)0x00000800)
+#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800)
/** Whether the key may be used to derive other keys.
*/
diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h b/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h
index 9f55484e2f..938abd07b8 100644
--- a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h
+++ b/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h
@@ -330,14 +330,14 @@ typedef uint16_t psa_key_attributes_flag_t;
typedef struct
{
psa_key_type_t type;
+ psa_key_bits_t bits;
psa_key_lifetime_t lifetime;
psa_key_id_t id;
psa_key_policy_t policy;
- psa_key_bits_t bits;
psa_key_attributes_flag_t flags;
} psa_core_key_attributes_t;
-#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0}
+#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0}
struct psa_key_attributes_s
{
diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c b/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c
index 42c2969bfd..733a2e46c4 100644
--- a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c
+++ b/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto.c
@@ -75,6 +75,7 @@
#include "mbedtls/pk.h"
#include "mbedtls/pk_internal.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include "mbedtls/ripemd160.h"
#include "mbedtls/rsa.h"
#include "mbedtls/sha1.h"
@@ -351,6 +352,8 @@ static psa_status_t mbedtls_to_psa_error( int ret )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
case MBEDTLS_ERR_ECP_HW_ACCEL_FAILED:
return( PSA_ERROR_HARDWARE_FAILURE );
+ case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
+ return( PSA_ERROR_CORRUPTION_DETECTED );
default:
return( PSA_ERROR_GENERIC_ERROR );
@@ -372,71 +375,118 @@ static inline int psa_key_slot_is_external( const psa_key_slot_t *slot )
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
#if defined(MBEDTLS_ECP_C)
-static psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid )
+psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid,
+ size_t *bits )
{
switch( grpid )
{
case MBEDTLS_ECP_DP_SECP192R1:
- return( PSA_ECC_CURVE_SECP192R1 );
+ *bits = 192;
+ return( PSA_ECC_CURVE_SECP_R1 );
case MBEDTLS_ECP_DP_SECP224R1:
- return( PSA_ECC_CURVE_SECP224R1 );
+ *bits = 224;
+ return( PSA_ECC_CURVE_SECP_R1 );
case MBEDTLS_ECP_DP_SECP256R1:
- return( PSA_ECC_CURVE_SECP256R1 );
+ *bits = 256;
+ return( PSA_ECC_CURVE_SECP_R1 );
case MBEDTLS_ECP_DP_SECP384R1:
- return( PSA_ECC_CURVE_SECP384R1 );
+ *bits = 384;
+ return( PSA_ECC_CURVE_SECP_R1 );
case MBEDTLS_ECP_DP_SECP521R1:
- return( PSA_ECC_CURVE_SECP521R1 );
+ *bits = 521;
+ return( PSA_ECC_CURVE_SECP_R1 );
case MBEDTLS_ECP_DP_BP256R1:
- return( PSA_ECC_CURVE_BRAINPOOL_P256R1 );
+ *bits = 256;
+ return( PSA_ECC_CURVE_BRAINPOOL_P_R1 );
case MBEDTLS_ECP_DP_BP384R1:
- return( PSA_ECC_CURVE_BRAINPOOL_P384R1 );
+ *bits = 384;
+ return( PSA_ECC_CURVE_BRAINPOOL_P_R1 );
case MBEDTLS_ECP_DP_BP512R1:
- return( PSA_ECC_CURVE_BRAINPOOL_P512R1 );
+ *bits = 512;
+ return( PSA_ECC_CURVE_BRAINPOOL_P_R1 );
case MBEDTLS_ECP_DP_CURVE25519:
- return( PSA_ECC_CURVE_CURVE25519 );
+ *bits = 255;
+ return( PSA_ECC_CURVE_MONTGOMERY );
case MBEDTLS_ECP_DP_SECP192K1:
- return( PSA_ECC_CURVE_SECP192K1 );
+ *bits = 192;
+ return( PSA_ECC_CURVE_SECP_K1 );
case MBEDTLS_ECP_DP_SECP224K1:
- return( PSA_ECC_CURVE_SECP224K1 );
+ *bits = 224;
+ return( PSA_ECC_CURVE_SECP_K1 );
case MBEDTLS_ECP_DP_SECP256K1:
- return( PSA_ECC_CURVE_SECP256K1 );
+ *bits = 256;
+ return( PSA_ECC_CURVE_SECP_K1 );
case MBEDTLS_ECP_DP_CURVE448:
- return( PSA_ECC_CURVE_CURVE448 );
+ *bits = 448;
+ return( PSA_ECC_CURVE_MONTGOMERY );
default:
return( 0 );
}
}
-static mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve )
+mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_curve_t curve,
+ size_t byte_length )
{
switch( curve )
{
- case PSA_ECC_CURVE_SECP192R1:
- return( MBEDTLS_ECP_DP_SECP192R1 );
- case PSA_ECC_CURVE_SECP224R1:
- return( MBEDTLS_ECP_DP_SECP224R1 );
- case PSA_ECC_CURVE_SECP256R1:
- return( MBEDTLS_ECP_DP_SECP256R1 );
- case PSA_ECC_CURVE_SECP384R1:
- return( MBEDTLS_ECP_DP_SECP384R1 );
- case PSA_ECC_CURVE_SECP521R1:
- return( MBEDTLS_ECP_DP_SECP521R1 );
- case PSA_ECC_CURVE_BRAINPOOL_P256R1:
- return( MBEDTLS_ECP_DP_BP256R1 );
- case PSA_ECC_CURVE_BRAINPOOL_P384R1:
- return( MBEDTLS_ECP_DP_BP384R1 );
- case PSA_ECC_CURVE_BRAINPOOL_P512R1:
- return( MBEDTLS_ECP_DP_BP512R1 );
- case PSA_ECC_CURVE_CURVE25519:
- return( MBEDTLS_ECP_DP_CURVE25519 );
- case PSA_ECC_CURVE_SECP192K1:
- return( MBEDTLS_ECP_DP_SECP192K1 );
- case PSA_ECC_CURVE_SECP224K1:
- return( MBEDTLS_ECP_DP_SECP224K1 );
- case PSA_ECC_CURVE_SECP256K1:
- return( MBEDTLS_ECP_DP_SECP256K1 );
- case PSA_ECC_CURVE_CURVE448:
- return( MBEDTLS_ECP_DP_CURVE448 );
+ case PSA_ECC_CURVE_SECP_R1:
+ switch( byte_length )
+ {
+ case PSA_BITS_TO_BYTES( 192 ):
+ return( MBEDTLS_ECP_DP_SECP192R1 );
+ case PSA_BITS_TO_BYTES( 224 ):
+ return( MBEDTLS_ECP_DP_SECP224R1 );
+ case PSA_BITS_TO_BYTES( 256 ):
+ return( MBEDTLS_ECP_DP_SECP256R1 );
+ case PSA_BITS_TO_BYTES( 384 ):
+ return( MBEDTLS_ECP_DP_SECP384R1 );
+ case PSA_BITS_TO_BYTES( 521 ):
+ return( MBEDTLS_ECP_DP_SECP521R1 );
+ default:
+ return( MBEDTLS_ECP_DP_NONE );
+ }
+ break;
+
+ case PSA_ECC_CURVE_BRAINPOOL_P_R1:
+ switch( byte_length )
+ {
+ case PSA_BITS_TO_BYTES( 256 ):
+ return( MBEDTLS_ECP_DP_BP256R1 );
+ case PSA_BITS_TO_BYTES( 384 ):
+ return( MBEDTLS_ECP_DP_BP384R1 );
+ case PSA_BITS_TO_BYTES( 512 ):
+ return( MBEDTLS_ECP_DP_BP512R1 );
+ default:
+ return( MBEDTLS_ECP_DP_NONE );
+ }
+ break;
+
+ case PSA_ECC_CURVE_MONTGOMERY:
+ switch( byte_length )
+ {
+ case PSA_BITS_TO_BYTES( 255 ):
+ return( MBEDTLS_ECP_DP_CURVE25519 );
+ case PSA_BITS_TO_BYTES( 448 ):
+ return( MBEDTLS_ECP_DP_CURVE448 );
+ default:
+ return( MBEDTLS_ECP_DP_NONE );
+ }
+ break;
+
+ case PSA_ECC_CURVE_SECP_K1:
+ switch( byte_length )
+ {
+ case PSA_BITS_TO_BYTES( 192 ):
+ return( MBEDTLS_ECP_DP_SECP192K1 );
+ case PSA_BITS_TO_BYTES( 224 ):
+ return( MBEDTLS_ECP_DP_SECP224K1 );
+ case PSA_BITS_TO_BYTES( 256 ):
+ return( MBEDTLS_ECP_DP_SECP256K1 );
+ default:
+ return( MBEDTLS_ECP_DP_NONE );
+ }
+ break;
+
default:
return( MBEDTLS_ECP_DP_NONE );
}
@@ -584,6 +634,37 @@ exit:
#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */
#if defined(MBEDTLS_ECP_C)
+static psa_status_t psa_prepare_import_ec_key( psa_ecc_curve_t curve,
+ size_t data_length,
+ int is_public,
+ mbedtls_ecp_keypair **p_ecp )
+{
+ mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
+ *p_ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
+ if( *p_ecp == NULL )
+ return( PSA_ERROR_INSUFFICIENT_MEMORY );
+ mbedtls_ecp_keypair_init( *p_ecp );
+
+ if( is_public )
+ {
+ /* A public key is represented as:
+ * - The byte 0x04;
+ * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
+ * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
+ * So its data length is 2m+1 where n is the key size in bits.
+ */
+ if( ( data_length & 1 ) == 0 )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ data_length = data_length / 2;
+ }
+
+ /* Load the group. */
+ grp_id = mbedtls_ecc_group_of_psa( curve, data_length );
+ if( grp_id == MBEDTLS_ECP_DP_NONE )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+ return( mbedtls_to_psa_error(
+ mbedtls_ecp_group_load( &( *p_ecp )->grp, grp_id ) ) );
+}
/* Import a public key given as the uncompressed representation defined by SEC1
* 2.3.3 as the content of an ECPoint. */
@@ -594,19 +675,11 @@ static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve,
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
- mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve );
- *p_ecp = NULL;
- ecp = mbedtls_calloc( 1, sizeof( *ecp ) );
- if( ecp == NULL )
- return( PSA_ERROR_INSUFFICIENT_MEMORY );
- mbedtls_ecp_keypair_init( ecp );
-
- /* Load the group. */
- status = mbedtls_to_psa_error(
- mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
+ status = psa_prepare_import_ec_key( curve, data_length, 1, &ecp );
if( status != PSA_SUCCESS )
goto exit;
+
/* Load the public value. */
status = mbedtls_to_psa_error(
mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q,
@@ -631,9 +704,7 @@ exit:
}
return( status );
}
-#endif /* defined(MBEDTLS_ECP_C) */
-#if defined(MBEDTLS_ECP_C)
/* Import a private key given as a byte string which is the private value
* in big-endian order. */
static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve,
@@ -643,22 +714,11 @@ static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve,
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
- mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve );
- if( PSA_BITS_TO_BYTES( PSA_ECC_CURVE_BITS( curve ) ) != data_length )
- return( PSA_ERROR_INVALID_ARGUMENT );
-
- *p_ecp = NULL;
- ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) );
- if( ecp == NULL )
- return( PSA_ERROR_INSUFFICIENT_MEMORY );
- mbedtls_ecp_keypair_init( ecp );
-
- /* Load the group. */
- status = mbedtls_to_psa_error(
- mbedtls_ecp_group_load( &ecp->grp, grp_id ) );
+ status = psa_prepare_import_ec_key( curve, data_length, 0, &ecp );
if( status != PSA_SUCCESS )
goto exit;
+
/* Load the secret value. */
status = mbedtls_to_psa_error(
mbedtls_mpi_read_binary( &ecp->d, data, data_length ) );
@@ -1145,7 +1205,7 @@ static psa_status_t psa_get_rsa_public_exponent(
psa_key_attributes_t *attributes )
{
mbedtls_mpi mpi;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint8_t *buffer = NULL;
size_t buflen;
mbedtls_mpi_init( &mpi );
@@ -1249,7 +1309,7 @@ psa_status_t psa_get_key_slot_number(
static int pk_write_pubkey_simple( mbedtls_pk_context *key,
unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *c;
size_t len = 0;
@@ -1334,7 +1394,7 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot,
PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
{
mbedtls_pk_context pk;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
{
#if defined(MBEDTLS_RSA_C)
@@ -1462,8 +1522,8 @@ static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy )
PSA_KEY_USAGE_COPY |
PSA_KEY_USAGE_ENCRYPT |
PSA_KEY_USAGE_DECRYPT |
- PSA_KEY_USAGE_SIGN |
- PSA_KEY_USAGE_VERIFY |
+ PSA_KEY_USAGE_SIGN_HASH |
+ PSA_KEY_USAGE_VERIFY_HASH |
PSA_KEY_USAGE_DERIVE ) ) != 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
@@ -1782,7 +1842,7 @@ static psa_status_t psa_validate_optional_attributes(
if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
{
mbedtls_mpi actual, required;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_init( &actual );
mbedtls_mpi_init( &required );
ret = mbedtls_rsa_export( slot->data.rsa,
@@ -2006,6 +2066,7 @@ exit:
/* Message digests */
/****************************************************************/
+#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_DETERMINISTIC)
static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )
{
switch( alg )
@@ -2037,8 +2098,10 @@ static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )
return( &mbedtls_sha256_info );
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case PSA_ALG_SHA_384:
return( &mbedtls_sha384_info );
+#endif
case PSA_ALG_SHA_512:
return( &mbedtls_sha512_info );
#endif
@@ -2046,6 +2109,7 @@ static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )
return( NULL );
}
}
+#endif
psa_status_t psa_hash_abort( psa_hash_operation_t *operation )
{
@@ -2088,7 +2152,9 @@ psa_status_t psa_hash_abort( psa_hash_operation_t *operation )
break;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case PSA_ALG_SHA_384:
+#endif
case PSA_ALG_SHA_512:
mbedtls_sha512_free( &operation->ctx.sha512 );
break;
@@ -2103,7 +2169,7 @@ psa_status_t psa_hash_abort( psa_hash_operation_t *operation )
psa_status_t psa_hash_setup( psa_hash_operation_t *operation,
psa_algorithm_t alg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* A context must be freshly initialized before it can be set up. */
if( operation->alg != 0 )
@@ -2154,10 +2220,12 @@ psa_status_t psa_hash_setup( psa_hash_operation_t *operation,
break;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case PSA_ALG_SHA_384:
mbedtls_sha512_init( &operation->ctx.sha512 );
ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 1 );
break;
+#endif
case PSA_ALG_SHA_512:
mbedtls_sha512_init( &operation->ctx.sha512 );
ret = mbedtls_sha512_starts_ret( &operation->ctx.sha512, 0 );
@@ -2179,7 +2247,7 @@ psa_status_t psa_hash_update( psa_hash_operation_t *operation,
const uint8_t *input,
size_t input_length )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Don't require hash implementations to behave correctly on a
* zero-length input, which may have an invalid pointer. */
@@ -2226,7 +2294,9 @@ psa_status_t psa_hash_update( psa_hash_operation_t *operation,
break;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case PSA_ALG_SHA_384:
+#endif
case PSA_ALG_SHA_512:
ret = mbedtls_sha512_update_ret( &operation->ctx.sha512,
input, input_length );
@@ -2247,7 +2317,7 @@ psa_status_t psa_hash_finish( psa_hash_operation_t *operation,
size_t *hash_length )
{
psa_status_t status;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t actual_hash_length = PSA_HASH_SIZE( operation->alg );
/* Fill the output buffer with something that isn't a valid hash
@@ -2299,7 +2369,9 @@ psa_status_t psa_hash_finish( psa_hash_operation_t *operation,
break;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case PSA_ALG_SHA_384:
+#endif
case PSA_ALG_SHA_512:
ret = mbedtls_sha512_finish_ret( &operation->ctx.sha512, hash );
break;
@@ -2340,6 +2412,58 @@ psa_status_t psa_hash_verify( psa_hash_operation_t *operation,
return( PSA_SUCCESS );
}
+psa_status_t psa_hash_compute( psa_algorithm_t alg,
+ const uint8_t *input, size_t input_length,
+ uint8_t *hash, size_t hash_size,
+ size_t *hash_length )
+{
+ psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+ *hash_length = hash_size;
+ status = psa_hash_setup( &operation, alg );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ status = psa_hash_update( &operation, input, input_length );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ status = psa_hash_finish( &operation, hash, hash_size, hash_length );
+ if( status != PSA_SUCCESS )
+ goto exit;
+
+exit:
+ if( status == PSA_SUCCESS )
+ status = psa_hash_abort( &operation );
+ else
+ psa_hash_abort( &operation );
+ return( status );
+}
+
+psa_status_t psa_hash_compare( psa_algorithm_t alg,
+ const uint8_t *input, size_t input_length,
+ const uint8_t *hash, size_t hash_length )
+{
+ psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+ status = psa_hash_setup( &operation, alg );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ status = psa_hash_update( &operation, input, input_length );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ status = psa_hash_verify( &operation, hash, hash_length );
+ if( status != PSA_SUCCESS )
+ goto exit;
+
+exit:
+ if( status == PSA_SUCCESS )
+ status = psa_hash_abort( &operation );
+ else
+ psa_hash_abort( &operation );
+ return( status );
+}
+
psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation,
psa_hash_operation_t *target_operation )
{
@@ -2388,7 +2512,9 @@ psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation,
break;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case PSA_ALG_SHA_384:
+#endif
case PSA_ALG_SHA_512:
mbedtls_sha512_clone( &target_operation->ctx.sha512,
&source_operation->ctx.sha512 );
@@ -2630,7 +2756,7 @@ static int psa_cmac_setup( psa_mac_operation_t *operation,
psa_key_slot_t *slot,
const mbedtls_cipher_info_t *cipher_info )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
operation->mac_size = cipher_info->block_size;
@@ -2672,14 +2798,8 @@ static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac,
if( key_length > block_size )
{
- status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
- if( status != PSA_SUCCESS )
- goto cleanup;
- status = psa_hash_update( &hmac->hash_ctx, key, key_length );
- if( status != PSA_SUCCESS )
- goto cleanup;
- status = psa_hash_finish( &hmac->hash_ctx,
- ipad, sizeof( ipad ), &key_length );
+ status = psa_hash_compute( hash_alg, key, key_length,
+ ipad, sizeof( ipad ), &key_length );
if( status != PSA_SUCCESS )
goto cleanup;
}
@@ -2724,7 +2844,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
psa_key_slot_t *slot;
size_t key_bits;
psa_key_usage_t usage =
- is_sign ? PSA_KEY_USAGE_SIGN : PSA_KEY_USAGE_VERIFY;
+ is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH;
uint8_t truncated = PSA_MAC_TRUNCATED_LENGTH( alg );
psa_algorithm_t full_length_alg = PSA_ALG_FULL_LENGTH_MAC( alg );
@@ -2751,7 +2871,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
const mbedtls_cipher_info_t *cipher_info =
mbedtls_cipher_info_from_psa( full_length_alg,
slot->attr.type, key_bits, NULL );
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( cipher_info == NULL )
{
status = PSA_ERROR_NOT_SUPPORTED;
@@ -3029,6 +3149,8 @@ psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation,
status = psa_mac_finish_internal( operation,
actual_mac, sizeof( actual_mac ) );
+ if( status != PSA_SUCCESS )
+ goto cleanup;
if( safer_memcmp( mac, actual_mac, mac_length ) != 0 )
status = PSA_ERROR_INVALID_SIGNATURE;
@@ -3103,7 +3225,7 @@ static psa_status_t psa_rsa_sign( mbedtls_rsa_context *rsa,
size_t *signature_length )
{
psa_status_t status;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
@@ -3161,7 +3283,7 @@ static psa_status_t psa_rsa_verify( mbedtls_rsa_context *rsa,
size_t signature_length )
{
psa_status_t status;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
status = psa_rsa_decode_md_type( alg, hash_length, &md_alg );
@@ -3227,7 +3349,7 @@ static psa_status_t psa_ecdsa_sign( mbedtls_ecp_keypair *ecp,
size_t signature_size,
size_t *signature_length )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi r, s;
size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
mbedtls_mpi_init( &r );
@@ -3282,7 +3404,7 @@ static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp,
const uint8_t *signature,
size_t signature_length )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi r, s;
size_t curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits );
mbedtls_mpi_init( &r );
@@ -3308,13 +3430,13 @@ cleanup:
}
#endif /* MBEDTLS_ECDSA_C */
-psa_status_t psa_asymmetric_sign( psa_key_handle_t handle,
- psa_algorithm_t alg,
- const uint8_t *hash,
- size_t hash_length,
- uint8_t *signature,
- size_t signature_size,
- size_t *signature_length )
+psa_status_t psa_sign_hash( psa_key_handle_t handle,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ uint8_t *signature,
+ size_t signature_size,
+ size_t *signature_length )
{
psa_key_slot_t *slot;
psa_status_t status;
@@ -3331,7 +3453,7 @@ psa_status_t psa_asymmetric_sign( psa_key_handle_t handle,
if( signature_size == 0 )
return( PSA_ERROR_BUFFER_TOO_SMALL );
- status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN, alg );
+ status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN_HASH, alg );
if( status != PSA_SUCCESS )
goto exit;
if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) )
@@ -3412,12 +3534,12 @@ exit:
return( status );
}
-psa_status_t psa_asymmetric_verify( psa_key_handle_t handle,
- psa_algorithm_t alg,
- const uint8_t *hash,
- size_t hash_length,
- const uint8_t *signature,
- size_t signature_length )
+psa_status_t psa_verify_hash( psa_key_handle_t handle,
+ psa_algorithm_t alg,
+ const uint8_t *hash,
+ size_t hash_length,
+ const uint8_t *signature,
+ size_t signature_length )
{
psa_key_slot_t *slot;
psa_status_t status;
@@ -3426,7 +3548,7 @@ psa_status_t psa_asymmetric_verify( psa_key_handle_t handle,
psa_drv_se_context_t *drv_context;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
- status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY, alg );
+ status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg );
if( status != PSA_SUCCESS )
return( status );
@@ -3521,7 +3643,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle,
if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
{
mbedtls_rsa_context *rsa = slot->data.rsa;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( output_size < mbedtls_rsa_get_len( rsa ) )
return( PSA_ERROR_BUFFER_TOO_SMALL );
#if defined(MBEDTLS_PKCS1_V15)
@@ -3600,7 +3722,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle,
if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
{
mbedtls_rsa_context *rsa = slot->data.rsa;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( input_length != mbedtls_rsa_get_len( rsa ) )
return( PSA_ERROR_INVALID_ARGUMENT );
@@ -3797,7 +3919,7 @@ psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation,
size_t *iv_length )
{
psa_status_t status;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( operation->iv_set || ! operation->iv_required )
{
return( PSA_ERROR_BAD_STATE );
@@ -3829,7 +3951,7 @@ psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation,
size_t iv_length )
{
psa_status_t status;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( operation->iv_set || ! operation->iv_required )
{
return( PSA_ERROR_BAD_STATE );
@@ -3857,7 +3979,7 @@ psa_status_t psa_cipher_update( psa_cipher_operation_t *operation,
size_t *output_length )
{
psa_status_t status;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t expected_output_size;
if( operation->alg == 0 )
@@ -5192,12 +5314,13 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
mbedtls_ecp_keypair *their_key = NULL;
mbedtls_ecdh_context ecdh;
psa_status_t status;
+ size_t bits = 0;
+ psa_ecc_curve_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits );
mbedtls_ecdh_init( &ecdh );
- status = psa_import_ec_public_key(
- mbedtls_ecc_group_to_psa( our_key->grp.id ),
- peer_key, peer_key_length,
- &their_key );
+ status = psa_import_ec_public_key( curve,
+ peer_key, peer_key_length,
+ &their_key );
if( status != PSA_SUCCESS )
goto exit;
@@ -5216,8 +5339,14 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
shared_secret, shared_secret_size,
mbedtls_ctr_drbg_random,
&global_data.ctr_drbg ) );
+ if( status != PSA_SUCCESS )
+ goto exit;
+ if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length )
+ status = PSA_ERROR_CORRUPTION_DETECTED;
exit:
+ if( status != PSA_SUCCESS )
+ mbedtls_platform_zeroize( shared_secret, shared_secret_size );
mbedtls_ecdh_free( &ecdh );
mbedtls_ecp_keypair_free( their_key );
mbedtls_free( their_key );
@@ -5367,7 +5496,7 @@ exit:
psa_status_t psa_generate_random( uint8_t *output,
size_t output_size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
GUARD_MODULE_INITIALIZED;
while( output_size > MBEDTLS_CTR_DRBG_MAX_REQUEST )
@@ -5462,7 +5591,7 @@ static psa_status_t psa_generate_key_internal(
if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
{
mbedtls_rsa_context *rsa;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int exponent;
psa_status_t status;
if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
@@ -5500,11 +5629,12 @@ static psa_status_t psa_generate_key_internal(
if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
{
psa_ecc_curve_t curve = PSA_KEY_TYPE_GET_CURVE( type );
- mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve );
+ mbedtls_ecp_group_id grp_id =
+ mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( bits ) );
const mbedtls_ecp_curve_info *curve_info =
mbedtls_ecp_curve_info_from_grp_id( grp_id );
mbedtls_ecp_keypair *ecp;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( domain_parameters_size != 0 )
return( PSA_ERROR_NOT_SUPPORTED );
if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c b/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c
index a27442cd90..fa1214c86d 100644
--- a/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c
+++ b/features/mbedtls/mbed-crypto/platform/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c
@@ -259,7 +259,9 @@ typedef struct {
uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
uint8_t version[4];
uint8_t lifetime[sizeof( psa_key_lifetime_t )];
- uint8_t type[sizeof( psa_key_type_t )];
+ uint8_t type[4]; /* Size=4 for a 2-byte type to keep the structure more
+ * regular and aligned and to make potential future
+ * extensibility easier. */
uint8_t policy[sizeof( psa_key_policy_t )];
uint8_t data_len[4];
uint8_t key_data[];
@@ -276,7 +278,7 @@ void psa_format_key_data_for_storage( const uint8_t *data,
memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH );
PUT_UINT32_LE( 0, storage_format->version, 0 );
PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
- PUT_UINT32_LE( attr->type, storage_format->type, 0 );
+ PUT_UINT32_LE( (uint32_t) attr->type, storage_format->type, 0 );
PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
@@ -302,6 +304,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
const psa_persistent_key_storage_format *storage_format =
(const psa_persistent_key_storage_format *)storage_data;
uint32_t version;
+ uint32_t type;
if( storage_data_length < sizeof(*storage_format) )
return( PSA_ERROR_STORAGE_FAILURE );
@@ -332,7 +335,11 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
}
GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
- GET_UINT32_LE( attr->type, storage_format->type, 0 );
+ GET_UINT32_LE( type, storage_format->type, 0 );
+ if( type <= (psa_key_type_t) -1 )
+ attr->type = (psa_key_type_t) type;
+ else
+ return( PSA_ERROR_STORAGE_FAILURE );
GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
@@ -419,7 +426,7 @@ psa_status_t psa_crypto_save_transaction( void )
{
struct psa_storage_info_t p_info;
psa_status_t status;
- status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info );
+ status = psa_its_get_info( PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info );
if( status == PSA_SUCCESS )
{
/* This shouldn't happen: we're trying to start a transaction while
diff --git a/features/mbedtls/mbed-crypto/platform/COMPONENT_SPE/crypto_struct_spe.h b/features/mbedtls/mbed-crypto/platform/COMPONENT_SPE/crypto_struct_spe.h
index fa0466e6ca..35a25f1ff9 100644
--- a/features/mbedtls/mbed-crypto/platform/COMPONENT_SPE/crypto_struct_spe.h
+++ b/features/mbedtls/mbed-crypto/platform/COMPONENT_SPE/crypto_struct_spe.h
@@ -330,10 +330,10 @@ typedef uint16_t psa_key_attributes_flag_t;
typedef struct
{
psa_key_type_t type;
+ psa_key_bits_t bits;
psa_key_lifetime_t lifetime;
psa_key_id_t id;
psa_key_policy_t policy;
- psa_key_bits_t bits;
psa_key_attributes_flag_t flags;
} psa_core_key_attributes_t;
@@ -344,14 +344,14 @@ typedef struct
typedef struct
{
psa_key_type_t type;
+ psa_key_bits_t bits;
psa_key_lifetime_t lifetime;
psa_app_key_id_t id;
psa_key_policy_t policy;
- psa_key_bits_t bits;
- uint16_t flags;
+ psa_key_attributes_flag_t flags;
} psa_client_core_key_attributes_t;
-#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0}
+#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0}
struct psa_key_attributes_s
{
@@ -368,6 +368,7 @@ struct psa_key_attributes_s
#else
#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0}
#endif
+
typedef struct psa_client_key_attributes_s
{
psa_client_core_key_attributes_t core;
diff --git a/features/mbedtls/mbed-crypto/src/aes.c b/features/mbedtls/mbed-crypto/src/aes.c
index aff0a9939a..604d0f3d7f 100644
--- a/features/mbedtls/mbed-crypto/src/aes.c
+++ b/features/mbedtls/mbed-crypto/src/aes.c
@@ -38,6 +38,7 @@
#include "mbedtls/aes.h"
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h"
#endif
@@ -766,7 +767,7 @@ int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
@@ -791,7 +792,7 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
@@ -918,6 +919,18 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
PUT_UINT32_LE( X2, output, 8 );
PUT_UINT32_LE( X3, output, 12 );
+ mbedtls_platform_zeroize( &X0, sizeof( X0 ) );
+ mbedtls_platform_zeroize( &X1, sizeof( X1 ) );
+ mbedtls_platform_zeroize( &X2, sizeof( X2 ) );
+ mbedtls_platform_zeroize( &X3, sizeof( X3 ) );
+
+ mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) );
+ mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) );
+ mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) );
+ mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) );
+
+ mbedtls_platform_zeroize( &RK, sizeof( RK ) );
+
return( 0 );
}
#endif /* !MBEDTLS_AES_ENCRYPT_ALT */
@@ -986,6 +999,18 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
PUT_UINT32_LE( X2, output, 8 );
PUT_UINT32_LE( X3, output, 12 );
+ mbedtls_platform_zeroize( &X0, sizeof( X0 ) );
+ mbedtls_platform_zeroize( &X1, sizeof( X1 ) );
+ mbedtls_platform_zeroize( &X2, sizeof( X2 ) );
+ mbedtls_platform_zeroize( &X3, sizeof( X3 ) );
+
+ mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) );
+ mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) );
+ mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) );
+ mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) );
+
+ mbedtls_platform_zeroize( &RK, sizeof( RK ) );
+
return( 0 );
}
#endif /* !MBEDTLS_AES_DECRYPT_ALT */
@@ -1175,7 +1200,7 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t blocks = length / 16;
size_t leftover = length % 16;
unsigned char tweak[16];
diff --git a/features/mbedtls/mbed-crypto/src/asn1parse.c b/features/mbedtls/mbed-crypto/src/asn1parse.c
index 412259e358..34c660775d 100644
--- a/features/mbedtls/mbed-crypto/src/asn1parse.c
+++ b/features/mbedtls/mbed-crypto/src/asn1parse.c
@@ -29,6 +29,7 @@
#include "mbedtls/asn1.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -124,7 +125,7 @@ int mbedtls_asn1_get_bool( unsigned char **p,
const unsigned char *end,
int *val )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 )
@@ -139,17 +140,20 @@ int mbedtls_asn1_get_bool( unsigned char **p,
return( 0 );
}
-int mbedtls_asn1_get_int( unsigned char **p,
- const unsigned char *end,
- int *val )
+static int asn1_get_tagged_int( unsigned char **p,
+ const unsigned char *end,
+ int tag, int *val )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
- if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
+ if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 )
return( ret );
- /* len==0 is malformed (0 must be represented as 020100). */
+ /*
+ * len==0 is malformed (0 must be represented as 020100 for INTEGER,
+ * or 0A0100 for ENUMERATED tags
+ */
if( len == 0 )
return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
/* This is a cryptography library. Reject negative integers. */
@@ -180,12 +184,26 @@ int mbedtls_asn1_get_int( unsigned char **p,
return( 0 );
}
+int mbedtls_asn1_get_int( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) );
+}
+
+int mbedtls_asn1_get_enum( unsigned char **p,
+ const unsigned char *end,
+ int *val )
+{
+ return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) );
+}
+
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end,
mbedtls_mpi *X )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
@@ -202,7 +220,7 @@ int mbedtls_asn1_get_mpi( unsigned char **p,
int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
mbedtls_asn1_bitstring *bs)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Certificate type is a single byte bitstring */
if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
@@ -229,13 +247,65 @@ int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
return( 0 );
}
+/*
+ * Traverse an ASN.1 "SEQUENCE OF "
+ * and call a callback for each entry found.
+ */
+int mbedtls_asn1_traverse_sequence_of(
+ unsigned char **p,
+ const unsigned char *end,
+ unsigned char tag_must_mask, unsigned char tag_must_val,
+ unsigned char tag_may_mask, unsigned char tag_may_val,
+ int (*cb)( void *ctx, int tag,
+ unsigned char *start, size_t len ),
+ void *ctx )
+{
+ int ret;
+ size_t len;
+
+ /* Get main sequence tag */
+ if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ if( *p + len != end )
+ return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+
+ while( *p < end )
+ {
+ unsigned char const tag = *(*p)++;
+
+ if( ( tag & tag_must_mask ) != tag_must_val )
+ return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
+
+ if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 )
+ return( ret );
+
+ if( ( tag & tag_may_mask ) == tag_may_val )
+ {
+ if( cb != NULL )
+ {
+ ret = cb( ctx, tag, *p, len );
+ if( ret != 0 )
+ return( ret );
+ }
+ }
+
+ *p += len;
+ }
+
+ return( 0 );
+}
+
/*
* Get a bit string without unused bits
*/
int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
size_t *len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
return( ret );
@@ -251,7 +321,51 @@ int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end
return( 0 );
}
+void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq )
+{
+ while( seq != NULL )
+ {
+ mbedtls_asn1_sequence *next = seq->next;
+ mbedtls_platform_zeroize( seq, sizeof( *seq ) );
+ mbedtls_free( seq );
+ seq = next;
+ }
+}
+typedef struct
+{
+ int tag;
+ mbedtls_asn1_sequence *cur;
+} asn1_get_sequence_of_cb_ctx_t;
+
+static int asn1_get_sequence_of_cb( void *ctx,
+ int tag,
+ unsigned char *start,
+ size_t len )
+{
+ asn1_get_sequence_of_cb_ctx_t *cb_ctx =
+ (asn1_get_sequence_of_cb_ctx_t *) ctx;
+ mbedtls_asn1_sequence *cur =
+ cb_ctx->cur;
+
+ if( cur->buf.p != NULL )
+ {
+ cur->next =
+ mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) );
+
+ if( cur->next == NULL )
+ return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
+
+ cur = cur->next;
+ }
+
+ cur->buf.p = start;
+ cur->buf.len = len;
+ cur->buf.tag = tag;
+
+ cb_ctx->cur = cur;
+ return( 0 );
+}
/*
* Parses and splits an ASN.1 "SEQUENCE OF "
@@ -261,56 +375,18 @@ int mbedtls_asn1_get_sequence_of( unsigned char **p,
mbedtls_asn1_sequence *cur,
int tag)
{
- int ret;
- size_t len;
- mbedtls_asn1_buf *buf;
-
- /* Get main sequence tag */
- if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
- return( ret );
-
- if( *p + len != end )
- return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
- while( *p < end )
- {
- buf = &(cur->buf);
- buf->tag = **p;
-
- if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 )
- return( ret );
-
- buf->p = *p;
- *p += buf->len;
-
- /* Allocate and assign next pointer */
- if( *p < end )
- {
- cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1,
- sizeof( mbedtls_asn1_sequence ) );
-
- if( cur->next == NULL )
- return( MBEDTLS_ERR_ASN1_ALLOC_FAILED );
-
- cur = cur->next;
- }
- }
-
- /* Set final sequence entry's next pointer to NULL */
- cur->next = NULL;
-
- if( *p != end )
- return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
-
- return( 0 );
+ asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
+ memset( cur, 0, sizeof( mbedtls_asn1_sequence ) );
+ return( mbedtls_asn1_traverse_sequence_of(
+ p, end, 0xFF, tag, 0, 0,
+ asn1_get_sequence_of_cb, &cb_ctx ) );
}
int mbedtls_asn1_get_alg( unsigned char **p,
const unsigned char *end,
mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -354,7 +430,7 @@ int mbedtls_asn1_get_alg_null( unsigned char **p,
const unsigned char *end,
mbedtls_asn1_buf *alg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf params;
memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) );
diff --git a/features/mbedtls/mbed-crypto/src/asn1write.c b/features/mbedtls/mbed-crypto/src/asn1write.c
index a138d0b75c..503db930b5 100644
--- a/features/mbedtls/mbed-crypto/src/asn1write.c
+++ b/features/mbedtls/mbed-crypto/src/asn1write.c
@@ -28,6 +28,7 @@
#if defined(MBEDTLS_ASN1_WRITE_C)
#include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
#include
@@ -131,7 +132,7 @@ int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
// Write the MPI
@@ -168,7 +169,7 @@ cleanup:
int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
// Write NULL
@@ -182,7 +183,7 @@ int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
@@ -197,7 +198,7 @@ int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *s
const char *oid, size_t oid_len,
size_t par_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( par_len == 0 )
@@ -216,7 +217,7 @@ int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *s
int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( *p - start < 1 )
@@ -231,9 +232,9 @@ int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolea
return( (int) len );
}
-int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
do
@@ -255,15 +256,25 @@ int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
}
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
+ MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return( (int) len );
}
+int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
+{
+ return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
+}
+
+int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val )
+{
+ return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) );
+}
+
int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag,
const char *text, size_t text_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
@@ -339,7 +350,7 @@ int mbedtls_asn1_write_named_bitstring( unsigned char **p,
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t bits )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
size_t unused_bits, byte_len;
@@ -372,7 +383,7 @@ int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
diff --git a/features/mbedtls/mbed-crypto/src/bignum.c b/features/mbedtls/mbed-crypto/src/bignum.c
index d5bde8b2cb..d53aefd5b0 100644
--- a/features/mbedtls/mbed-crypto/src/bignum.c
+++ b/features/mbedtls/mbed-crypto/src/bignum.c
@@ -46,6 +46,7 @@
#include "mbedtls/bignum.h"
#include "mbedtls/bn_mul.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -157,9 +158,10 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs )
if( nblimbs > MBEDTLS_MPI_MAX_LIMBS )
return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
- /* Actually resize up in this case */
+ /* Actually resize up if there are currently fewer than nblimbs limbs. */
if( X->n <= nblimbs )
return( mbedtls_mpi_grow( X, nblimbs ) );
+ /* After this point, then X->n > nblimbs and in particular X->n > 0. */
for( i = X->n - 1; i > 0; i-- )
if( X->p[i] != 0 )
@@ -198,7 +200,7 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y )
if( X == Y )
return( 0 );
- if( Y->p == NULL )
+ if( Y->n == 0 )
{
mbedtls_mpi_free( X );
return( 0 );
@@ -314,7 +316,7 @@ cleanup:
*/
int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MPI_VALIDATE_RET( X != NULL );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) );
@@ -457,7 +459,7 @@ static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c )
*/
int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, j, slen, n;
mbedtls_mpi_uint d;
mbedtls_mpi T;
@@ -532,7 +534,7 @@ cleanup:
static int mpi_write_hlp( mbedtls_mpi *X, int radix,
char **p, const size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_uint r;
size_t length = 0;
char *p_end = *p + buflen;
@@ -697,7 +699,7 @@ int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin )
*/
int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n, slen, plen;
/*
* Buffer should have space for (short) label and decimal formatted MPI,
@@ -832,7 +834,7 @@ static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs )
int mbedtls_mpi_read_binary_le( mbedtls_mpi *X,
const unsigned char *buf, size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
size_t const limbs = CHARS_TO_LIMBS( buflen );
@@ -864,7 +866,7 @@ cleanup:
*/
int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t const limbs = CHARS_TO_LIMBS( buflen );
size_t const overhead = ( limbs * ciL ) - buflen;
unsigned char *Xp;
@@ -991,7 +993,7 @@ int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
*/
int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, v0, t1;
mbedtls_mpi_uint r0 = 0, r1;
MPI_VALIDATE_RET( X != NULL );
@@ -1148,6 +1150,107 @@ int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y )
return( 0 );
}
+/** Decide if an integer is less than the other, without branches.
+ *
+ * \param x First integer.
+ * \param y Second integer.
+ *
+ * \return 1 if \p x is less than \p y, 0 otherwise
+ */
+static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x,
+ const mbedtls_mpi_uint y )
+{
+ mbedtls_mpi_uint ret;
+ mbedtls_mpi_uint cond;
+
+ /*
+ * Check if the most significant bits (MSB) of the operands are different.
+ */
+ cond = ( x ^ y );
+ /*
+ * If the MSB are the same then the difference x-y will be negative (and
+ * have its MSB set to 1 during conversion to unsigned) if and only if x> ( biL - 1 );
+
+ return (unsigned) ret;
+}
+
+/*
+ * Compare signed values in constant time
+ */
+int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y,
+ unsigned *ret )
+{
+ size_t i;
+ /* The value of any of these variables is either 0 or 1 at all times. */
+ unsigned cond, done, X_is_negative, Y_is_negative;
+
+ MPI_VALIDATE_RET( X != NULL );
+ MPI_VALIDATE_RET( Y != NULL );
+ MPI_VALIDATE_RET( ret != NULL );
+
+ if( X->n != Y->n )
+ return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+ /*
+ * Set sign_N to 1 if N >= 0, 0 if N < 0.
+ * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
+ */
+ X_is_negative = ( X->s & 2 ) >> 1;
+ Y_is_negative = ( Y->s & 2 ) >> 1;
+
+ /*
+ * If the signs are different, then the positive operand is the bigger.
+ * That is if X is negative (X_is_negative == 1), then X < Y is true and it
+ * is false if X is positive (X_is_negative == 0).
+ */
+ cond = ( X_is_negative ^ Y_is_negative );
+ *ret = cond & X_is_negative;
+
+ /*
+ * This is a constant-time function. We might have the result, but we still
+ * need to go through the loop. Record if we have the result already.
+ */
+ done = cond;
+
+ for( i = X->n; i > 0; i-- )
+ {
+ /*
+ * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
+ * X and Y are negative.
+ *
+ * Again even if we can make a decision, we just mark the result and
+ * the fact that we are done and continue looping.
+ */
+ cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] );
+ *ret |= cond & ( 1 - done ) & X_is_negative;
+ done |= cond;
+
+ /*
+ * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
+ * X and Y are positive.
+ *
+ * Again even if we can make a decision, we just mark the result and
+ * the fact that we are done and continue looping.
+ */
+ cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] );
+ *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative );
+ done |= cond;
+ }
+
+ return( 0 );
+}
+
/*
* Compare signed values
*/
@@ -1170,7 +1273,7 @@ int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z )
*/
int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, j;
mbedtls_mpi_uint *o, *p, c, tmp;
MPI_VALIDATE_RET( X != NULL );
@@ -1251,7 +1354,7 @@ static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d )
int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
mbedtls_mpi TB;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
@@ -1474,7 +1577,7 @@ void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mp
*/
int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, j;
mbedtls_mpi TA, TB;
MPI_VALIDATE_RET( X != NULL );
@@ -1629,9 +1732,10 @@ static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1,
int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n, t, k;
mbedtls_mpi X, Y, Z, T1, T2;
+ mbedtls_mpi_uint TP2[3];
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
@@ -1639,7 +1743,17 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO );
mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z );
- mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
+ mbedtls_mpi_init( &T1 );
+ /*
+ * Avoid dynamic memory allocations for constant-size T2.
+ *
+ * T2 is used for comparison only and the 3 limbs are assigned explicitly,
+ * so nobody increase the size of the MPI and we're safe to use an on-stack
+ * buffer.
+ */
+ T2.s = 1;
+ T2.n = sizeof( TP2 ) / sizeof( *TP2 );
+ T2.p = TP2;
if( mbedtls_mpi_cmp_abs( A, B ) < 0 )
{
@@ -1655,7 +1769,6 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) );
- MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) );
k = mbedtls_mpi_bitlen( &Y ) % biL;
if( k < biL - 1 )
@@ -1687,6 +1800,10 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
Y.p[t], NULL);
}
+ T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
+ T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
+ T2.p[2] = X.p[i];
+
Z.p[i - t - 1]++;
do
{
@@ -1696,11 +1813,6 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1];
T1.p[1] = Y.p[t];
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
-
- MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) );
- T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2];
- T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1];
- T2.p[2] = X.p[i];
}
while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 );
@@ -1736,7 +1848,8 @@ int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
cleanup:
mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z );
- mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 );
+ mbedtls_mpi_free( &T1 );
+ mbedtls_platform_zeroize( TP2, sizeof( TP2 ) );
return( ret );
}
@@ -1765,7 +1878,7 @@ int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R,
*/
int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MPI_VALIDATE_RET( R != NULL );
MPI_VALIDATE_RET( A != NULL );
MPI_VALIDATE_RET( B != NULL );
@@ -1927,7 +2040,7 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *E, const mbedtls_mpi *N,
mbedtls_mpi *_RR )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t wbits, wsize, one = 1;
size_t i, j, nblimbs;
size_t bufsize, nbits;
@@ -2142,7 +2255,7 @@ cleanup:
*/
int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t lz, lzt;
mbedtls_mpi TA, TB;
@@ -2204,7 +2317,7 @@ int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t const limbs = CHARS_TO_LIMBS( size );
size_t const overhead = ( limbs * ciL ) - size;
unsigned char *Xp;
@@ -2235,7 +2348,7 @@ cleanup:
*/
int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( A != NULL );
@@ -2488,7 +2601,7 @@ int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi XX;
MPI_VALIDATE_RET( X != NULL );
MPI_VALIDATE_RET( f_rng != NULL );
diff --git a/features/mbedtls/mbed-crypto/src/ccm.c b/features/mbedtls/mbed-crypto/src/ccm.c
index a7e360ecf4..eaef106a11 100644
--- a/features/mbedtls/mbed-crypto/src/ccm.c
+++ b/features/mbedtls/mbed-crypto/src/ccm.c
@@ -38,6 +38,7 @@
#include "mbedtls/ccm.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -74,7 +75,7 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
const unsigned char *key,
unsigned int keybits )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
CCM_VALIDATE_RET( ctx != NULL );
@@ -156,7 +157,7 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char i;
unsigned char q;
size_t len_left, olen;
@@ -366,7 +367,7 @@ int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
unsigned char i;
int diff;
@@ -479,7 +480,7 @@ int mbedtls_ccm_self_test( int verbose )
unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
size_t i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ccm_init( &ctx );
diff --git a/features/mbedtls/mbed-crypto/src/chacha20.c b/features/mbedtls/mbed-crypto/src/chacha20.c
index 8a3610f0e0..343b2167cd 100644
--- a/features/mbedtls/mbed-crypto/src/chacha20.c
+++ b/features/mbedtls/mbed-crypto/src/chacha20.c
@@ -33,6 +33,7 @@
#include "mbedtls/chacha20.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
#include
@@ -325,7 +326,7 @@ int mbedtls_chacha20_crypt( const unsigned char key[32],
unsigned char* output )
{
mbedtls_chacha20_context ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CHACHA20_VALIDATE_RET( key != NULL );
CHACHA20_VALIDATE_RET( nonce != NULL );
@@ -536,7 +537,7 @@ int mbedtls_chacha20_self_test( int verbose )
{
unsigned char output[381];
unsigned i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
for( i = 0U; i < 2U; i++ )
{
diff --git a/features/mbedtls/mbed-crypto/src/chachapoly.c b/features/mbedtls/mbed-crypto/src/chachapoly.c
index dc643dd618..f0af5ded26 100644
--- a/features/mbedtls/mbed-crypto/src/chachapoly.c
+++ b/features/mbedtls/mbed-crypto/src/chachapoly.c
@@ -30,6 +30,7 @@
#include "mbedtls/chachapoly.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -122,7 +123,7 @@ void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx )
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
const unsigned char key[32] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( key != NULL );
@@ -135,7 +136,7 @@ int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
const unsigned char nonce[12],
mbedtls_chachapoly_mode_t mode )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char poly1305_key[64];
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( nonce != NULL );
@@ -191,7 +192,7 @@ int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
@@ -240,7 +241,7 @@ int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
unsigned char mac[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char len_block[16];
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( mac != NULL );
@@ -304,7 +305,7 @@ static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx,
unsigned char *output,
unsigned char tag[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_chachapoly_starts( ctx, nonce, mode );
if( ret != 0 )
@@ -354,7 +355,7 @@ int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx,
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
size_t i;
int diff;
@@ -492,7 +493,7 @@ int mbedtls_chachapoly_self_test( int verbose )
{
mbedtls_chachapoly_context ctx;
unsigned i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output[200];
unsigned char mac[16];
diff --git a/features/mbedtls/mbed-crypto/src/cipher.c b/features/mbedtls/mbed-crypto/src/cipher.c
index 69079aae7a..409c3fe674 100644
--- a/features/mbedtls/mbed-crypto/src/cipher.c
+++ b/features/mbedtls/mbed-crypto/src/cipher.c
@@ -34,6 +34,7 @@
#include "mbedtls/cipher.h"
#include "mbedtls/cipher_internal.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
#include
@@ -504,7 +505,7 @@ int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
size_t ilen, unsigned char *output, size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t block_size;
CIPHER_VALIDATE_RET( ctx != NULL );
@@ -526,6 +527,10 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
*olen = 0;
block_size = mbedtls_cipher_get_block_size( ctx );
+ if ( 0 == block_size )
+ {
+ return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
+ }
if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
{
@@ -561,11 +566,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
}
#endif
- if ( 0 == block_size )
- {
- return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
- }
-
if( input == output &&
( ctx->unprocessed_len != 0 || ilen % block_size ) )
{
@@ -624,11 +624,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i
*/
if( 0 != ilen )
{
- if( 0 == block_size )
- {
- return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT );
- }
-
/* Encryption: only cache partial blocks
* Decryption w/ padding: always keep at least one whole block
* Decryption w/o padding: only cache partial blocks
@@ -1134,7 +1129,7 @@ int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len )
{
unsigned char check_tag[16];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
CIPHER_VALIDATE_RET( ctx != NULL );
CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
@@ -1211,7 +1206,7 @@ int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t finish_olen;
CIPHER_VALIDATE_RET( ctx != NULL );
@@ -1455,7 +1450,7 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
*olen = ilen;
ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
@@ -1471,7 +1466,7 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
#if defined(MBEDTLS_CCM_C)
if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
*olen = ilen;
ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
@@ -1487,7 +1482,7 @@ int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
#if defined(MBEDTLS_CHACHAPOLY_C)
if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* ChachaPoly has fixed length nonce and MAC (tag) */
if ( ( iv_len != ctx->cipher_info->iv_size ) ||
diff --git a/features/mbedtls/mbed-crypto/src/cipher_wrap.c b/features/mbedtls/mbed-crypto/src/cipher_wrap.c
index 7fc40b5f0c..a813426be2 100644
--- a/features/mbedtls/mbed-crypto/src/cipher_wrap.c
+++ b/features/mbedtls/mbed-crypto/src/cipher_wrap.c
@@ -32,6 +32,7 @@
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher_internal.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
@@ -1916,7 +1917,7 @@ static int chacha20_stream_wrap( void *ctx, size_t length,
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_chacha20_update( ctx, length, input, output );
if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
diff --git a/features/mbedtls/mbed-crypto/src/cmac.c b/features/mbedtls/mbed-crypto/src/cmac.c
index 5d101e1c7d..642680d556 100644
--- a/features/mbedtls/mbed-crypto/src/cmac.c
+++ b/features/mbedtls/mbed-crypto/src/cmac.c
@@ -50,6 +50,7 @@
#include "mbedtls/cmac.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -136,7 +137,7 @@ static int cmac_multiply_by_u( unsigned char *output,
static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx,
unsigned char* K1, unsigned char* K2 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
size_t olen, block_size;
@@ -315,7 +316,7 @@ int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen, block_size;
if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ||
@@ -393,7 +394,7 @@ int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
unsigned char *output )
{
mbedtls_cipher_context_t ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( cipher_info == NULL || key == NULL || input == NULL || output == NULL )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
@@ -427,7 +428,7 @@ int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length,
const unsigned char *input, size_t in_len,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE];
unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE];
@@ -894,7 +895,7 @@ exit:
static int test_aes128_cmac_prf( int verbose )
{
int i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output[MBEDTLS_AES_BLOCK_SIZE];
for( i = 0; i < NB_PRF_TESTS; i++ )
@@ -921,7 +922,7 @@ static int test_aes128_cmac_prf( int verbose )
int mbedtls_cmac_self_test( int verbose )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_AES_C)
/* AES-128 */
diff --git a/features/mbedtls/mbed-crypto/src/ctr_drbg.c b/features/mbedtls/mbed-crypto/src/ctr_drbg.c
index 0db7beb29d..8a2920a328 100644
--- a/features/mbedtls/mbed-crypto/src/ctr_drbg.c
+++ b/features/mbedtls/mbed-crypto/src/ctr_drbg.c
@@ -34,6 +34,7 @@
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -56,76 +57,15 @@
void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
+ /* Indicate that the entropy nonce length is not set explicitly.
+ * See mbedtls_ctr_drbg_set_nonce_len(). */
+ ctx->reseed_counter = -1;
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex );
#endif
}
-/*
- * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
- * NIST tests to succeed (which require known length fixed entropy)
- */
-/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
- * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
- * custom, len, entropy_len)
- * implements
- * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
- * security_strength) -> initial_working_state
- * with inputs
- * custom[:len] = nonce || personalization_string
- * where entropy_input comes from f_entropy for entropy_len bytes
- * and with outputs
- * ctx = initial_working_state
- */
-int mbedtls_ctr_drbg_seed_entropy_len(
- mbedtls_ctr_drbg_context *ctx,
- int (*f_entropy)(void *, unsigned char *, size_t),
- void *p_entropy,
- const unsigned char *custom,
- size_t len,
- size_t entropy_len )
-{
- int ret;
- unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
-
- memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
-
- mbedtls_aes_init( &ctx->aes_ctx );
-
- ctx->f_entropy = f_entropy;
- ctx->p_entropy = p_entropy;
-
- ctx->entropy_len = entropy_len;
- ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
-
- /*
- * Initialize with an empty key
- */
- if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
- MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
- {
- return( ret );
- }
-
- if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
- {
- return( ret );
- }
- return( 0 );
-}
-
-int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
- int (*f_entropy)(void *, unsigned char *, size_t),
- void *p_entropy,
- const unsigned char *custom,
- size_t len )
-{
- return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy,
- custom, len,
- MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
-}
-
void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
{
if( ctx == NULL )
@@ -150,6 +90,32 @@ void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
ctx->entropy_len = len;
}
+int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
+ size_t len )
+{
+ /* If mbedtls_ctr_drbg_seed() has already been called, it's
+ * too late. Return the error code that's closest to making sense. */
+ if( ctx->f_entropy != NULL )
+ return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+
+ if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+ return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+#if SIZE_MAX > INT_MAX
+ /* This shouldn't be an issue because
+ * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible
+ * configuration, but make sure anyway. */
+ if( len > INT_MAX )
+ return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+#endif
+
+ /* For backward compatibility with Mbed TLS <= 2.19, store the
+ * entropy nonce length in a field that already exists, but isn't
+ * used until after the initial seeding. */
+ /* Due to the capping of len above, the value fits in an int. */
+ ctx->reseed_counter = (int) len;
+ return( 0 );
+}
+
void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
int interval )
{
@@ -354,7 +320,7 @@ int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
size_t add_len )
{
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( add_len == 0 )
return( 0 );
@@ -383,7 +349,7 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
#endif /* MBEDTLS_DEPRECATED_REMOVED */
/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2)
- * mbedtls_ctr_drbg_reseed(ctx, additional, len)
+ * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len)
* implements
* CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
* -> new_working_state
@@ -391,51 +357,57 @@ void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
* ctx contains working_state
* additional[:len] = additional_input
* and entropy_input comes from calling ctx->f_entropy
+ * for (ctx->entropy_len + nonce_len) bytes
* and with output
* ctx contains new_working_state
*/
-int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
- const unsigned char *additional, size_t len )
+static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t len,
+ size_t nonce_len )
{
unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
size_t seedlen = 0;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
- len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
+ if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
+ return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+ if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
+ return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
+ if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len )
return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
- /*
- * Gather entropy_len bytes of entropy to seed state
- */
- if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
- ctx->entropy_len ) )
+ /* Gather entropy_len bytes of entropy to seed state. */
+ if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) )
{
return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
}
-
seedlen += ctx->entropy_len;
- /*
- * Add additional data
- */
- if( additional && len )
+ /* Gather entropy for a nonce if requested. */
+ if( nonce_len != 0 )
+ {
+ if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) )
+ {
+ return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
+ }
+ seedlen += nonce_len;
+ }
+
+ /* Add additional data if provided. */
+ if( additional != NULL && len != 0 )
{
memcpy( seed + seedlen, additional, len );
seedlen += len;
}
- /*
- * Reduce to 384 bits
- */
+ /* Reduce to 384 bits. */
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
goto exit;
- /*
- * Update state
- */
+ /* Update state. */
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
goto exit;
ctx->reseed_counter = 1;
@@ -445,6 +417,81 @@ exit:
return( ret );
}
+int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional, size_t len )
+{
+ return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) );
+}
+
+/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length
+ * is sufficient to achieve the maximum security strength given the key
+ * size and entropy length. If there is enough entropy in the initial
+ * call to the entropy function to serve as both the entropy input and
+ * the nonce, don't make a second call to get a nonce. */
+static size_t good_nonce_len( size_t entropy_len )
+{
+ if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 )
+ return( 0 );
+ else
+ return( ( entropy_len + 1 ) / 2 );
+}
+
+/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2)
+ * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len)
+ * implements
+ * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
+ * security_strength) -> initial_working_state
+ * with inputs
+ * custom[:len] = nonce || personalization_string
+ * where entropy_input comes from f_entropy for ctx->entropy_len bytes
+ * and with outputs
+ * ctx = initial_working_state
+ */
+int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
+ int (*f_entropy)(void *, unsigned char *, size_t),
+ void *p_entropy,
+ const unsigned char *custom,
+ size_t len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
+ size_t nonce_len;
+
+ memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
+
+ mbedtls_aes_init( &ctx->aes_ctx );
+
+ ctx->f_entropy = f_entropy;
+ ctx->p_entropy = p_entropy;
+
+ if( ctx->entropy_len == 0 )
+ ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN;
+ /* ctx->reseed_counter contains the desired amount of entropy to
+ * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()).
+ * If it's -1, indicating that the entropy nonce length was not set
+ * explicitly, use a sufficiently large nonce for security. */
+ nonce_len = ( ctx->reseed_counter >= 0 ?
+ (size_t) ctx->reseed_counter :
+ good_nonce_len( ctx->entropy_len ) );
+
+ ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
+
+ /* Initialize with an empty key. */
+ if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
+ MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ /* Do the initial seeding. */
+ if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len,
+ nonce_len ) ) != 0 )
+ {
+ return( ret );
+ }
+ return( 0 );
+}
+
/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2)
* mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
* implements
@@ -538,13 +585,13 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
exit:
mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
- return( 0 );
+ return( ret );
}
int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
size_t output_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
#if defined(MBEDTLS_THREADING_C)
@@ -666,6 +713,15 @@ static const unsigned char nonce_pers_nopr[16] =
{ 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
+#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
+static const unsigned char result_pr[16] =
+ { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7,
+ 0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a };
+
+static const unsigned char result_nopr[16] =
+ { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb,
+ 0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 };
+#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
static const unsigned char result_pr[16] =
{ 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
@@ -673,6 +729,7 @@ static const unsigned char result_pr[16] =
static const unsigned char result_nopr[16] =
{ 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
+#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
static size_t test_offset;
static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
@@ -708,8 +765,12 @@ int mbedtls_ctr_drbg_self_test( int verbose )
mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
test_offset = 0;
- CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
- (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
+ mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+ mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+ CHK( mbedtls_ctr_drbg_seed( &ctx,
+ ctr_drbg_self_test_entropy,
+ (void *) entropy_source_pr,
+ nonce_pers_pr, 16 ) );
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
@@ -729,8 +790,12 @@ int mbedtls_ctr_drbg_self_test( int verbose )
mbedtls_ctr_drbg_init( &ctx );
test_offset = 0;
- CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
- (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
+ mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 );
+ mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 );
+ CHK( mbedtls_ctr_drbg_seed( &ctx,
+ ctr_drbg_self_test_entropy,
+ (void *) entropy_source_nopr,
+ nonce_pers_nopr, 16 ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
diff --git a/features/mbedtls/mbed-crypto/src/dhm.c b/features/mbedtls/mbed-crypto/src/dhm.c
index 8255632a99..392ed0c150 100644
--- a/features/mbedtls/mbed-crypto/src/dhm.c
+++ b/features/mbedtls/mbed-crypto/src/dhm.c
@@ -37,6 +37,7 @@
#include "mbedtls/dhm.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -137,7 +138,7 @@ int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
unsigned char **p,
const unsigned char *end )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( p != NULL && *p != NULL );
DHM_VALIDATE_RET( end != NULL );
@@ -239,7 +240,7 @@ int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
const mbedtls_mpi *P,
const mbedtls_mpi *G )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( P != NULL );
DHM_VALIDATE_RET( G != NULL );
@@ -260,7 +261,7 @@ int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
const unsigned char *input, size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( input != NULL );
@@ -396,7 +397,7 @@ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi GYb;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
@@ -473,7 +474,7 @@ void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
size_t dhminlen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p, *end;
#if defined(MBEDTLS_PEM_PARSE_C)
@@ -627,7 +628,7 @@ static int load_file( const char *path, unsigned char **buf, size_t *n )
*/
int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
DHM_VALIDATE_RET( dhm != NULL );
@@ -679,7 +680,7 @@ static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_param
*/
int mbedtls_dhm_self_test( int verbose )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_dhm_context dhm;
mbedtls_dhm_init( &dhm );
diff --git a/features/mbedtls/mbed-crypto/src/ecdh.c b/features/mbedtls/mbed-crypto/src/ecdh.c
index 914eb5055d..3cf5333712 100644
--- a/features/mbedtls/mbed-crypto/src/ecdh.c
+++ b/features/mbedtls/mbed-crypto/src/ecdh.c
@@ -36,6 +36,7 @@
#include "mbedtls/ecdh.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -80,7 +81,7 @@ static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* If multiplication is in progress, we already generated a privkey */
#if defined(MBEDTLS_ECP_RESTARTABLE)
@@ -121,7 +122,7 @@ static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point P;
mbedtls_ecp_point_init( &P );
@@ -199,7 +200,7 @@ void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
mbedtls_ecp_group_id grp_id )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
if( ret != 0 )
@@ -307,7 +308,7 @@ static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
void *p_rng,
int restart_enabled )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t grp_len, pt_len;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
@@ -414,7 +415,7 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
const unsigned char **buf,
const unsigned char *end )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group_id grp_id;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( buf != NULL );
@@ -451,7 +452,7 @@ static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* If it's not our key, just import the public part as Qp */
if( side == MBEDTLS_ECDH_THEIRS )
@@ -475,7 +476,7 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( key != NULL );
ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
@@ -530,7 +531,7 @@ static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
void *p_rng,
int restart_enabled )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
@@ -602,7 +603,7 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
const unsigned char *buf, size_t blen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *p = buf;
if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
@@ -652,7 +653,7 @@ static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
void *p_rng,
int restart_enabled )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
diff --git a/features/mbedtls/mbed-crypto/src/ecdsa.c b/features/mbedtls/mbed-crypto/src/ecdsa.c
index bda9262c9e..5acd2d00e8 100644
--- a/features/mbedtls/mbed-crypto/src/ecdsa.c
+++ b/features/mbedtls/mbed-crypto/src/ecdsa.c
@@ -51,6 +51,7 @@
#endif
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
/* Parameter validation macros based on platform_util.h */
#define ECDSA_VALIDATE_RET( cond ) \
@@ -229,7 +230,7 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
const unsigned char *buf, size_t blen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n_size = ( grp->nbits + 7 ) / 8;
size_t use_size = blen > n_size ? n_size : blen;
@@ -297,7 +298,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
*p_sign_tries = 0;
do
{
- if( *p_sign_tries++ > 10 )
+ if( (*p_sign_tries)++ > 10 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
@@ -310,7 +311,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
*p_key_tries = 0;
do
{
- if( *p_key_tries++ > 10 )
+ if( (*p_key_tries)++ > 10 )
{
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
@@ -363,6 +364,7 @@ modn:
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
+ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
@@ -429,7 +431,7 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
void *p_rng_blind,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context rng_ctx;
mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
@@ -599,7 +601,7 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
const mbedtls_mpi *r, const mbedtls_mpi *s,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi e, s_inv, u1, u2;
mbedtls_ecp_point R;
mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
@@ -723,7 +725,7 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
unsigned char *sig, size_t *slen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
unsigned char *p = buf + sizeof( buf );
size_t len = 0;
@@ -752,7 +754,7 @@ int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi r, s;
ECDSA_VALIDATE_RET( ctx != NULL );
ECDSA_VALIDATE_RET( hash != NULL );
@@ -845,7 +847,7 @@ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
const unsigned char *sig, size_t slen,
mbedtls_ecdsa_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = (unsigned char *) sig;
const unsigned char *end = sig + slen;
size_t len;
@@ -925,7 +927,7 @@ int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
*/
int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECDSA_VALIDATE_RET( ctx != NULL );
ECDSA_VALIDATE_RET( key != NULL );
diff --git a/features/mbedtls/mbed-crypto/src/ecjpake.c b/features/mbedtls/mbed-crypto/src/ecjpake.c
index 1845c936ab..79ea3cbec4 100644
--- a/features/mbedtls/mbed-crypto/src/ecjpake.c
+++ b/features/mbedtls/mbed-crypto/src/ecjpake.c
@@ -34,6 +34,7 @@
#include "mbedtls/ecjpake.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -110,7 +111,7 @@ int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
const unsigned char *secret,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECJPAKE_VALIDATE_RET( ctx != NULL );
ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT ||
@@ -159,7 +160,7 @@ static int ecjpake_write_len_point( unsigned char **p,
const int pf,
const mbedtls_ecp_point *P )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
/* Need at least 4 for length plus 1 for point */
@@ -199,7 +200,7 @@ static int ecjpake_hash( const mbedtls_md_info_t *md_info,
const char *id,
mbedtls_mpi *h )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[ECJPAKE_HASH_BUF_LEN];
unsigned char *p = buf;
const unsigned char *end = buf + sizeof( buf );
@@ -249,7 +250,7 @@ static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
const unsigned char **p,
const unsigned char *end )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point V, VV;
mbedtls_mpi r, h;
size_t r_len;
@@ -324,7 +325,7 @@ static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point V;
mbedtls_mpi v;
mbedtls_mpi h; /* later recycled to hold r */
@@ -382,7 +383,7 @@ static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info,
const unsigned char **p,
const unsigned char *end )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( end < *p )
return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
@@ -422,7 +423,7 @@ static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( end < *p )
@@ -457,7 +458,7 @@ static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *p = buf;
const unsigned char *end = buf + len;
@@ -495,7 +496,7 @@ static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = buf;
const unsigned char *end = buf + len;
@@ -553,7 +554,7 @@ static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_ecp_point *B,
const mbedtls_ecp_point *C )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi one;
mbedtls_mpi_init( &one );
@@ -575,7 +576,7 @@ int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *p = buf;
const unsigned char *end = buf + len;
mbedtls_ecp_group grp;
@@ -639,7 +640,7 @@ static int ecjpake_mul_secret( mbedtls_mpi *R, int sign,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi b; /* Blinding value, then s + N * blinding */
mbedtls_mpi_init( &b );
@@ -668,7 +669,7 @@ int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point G; /* C: GA, S: GB */
mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
mbedtls_mpi xm; /* C: xc, S: xs */
@@ -750,7 +751,7 @@ int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point K;
mbedtls_mpi m_xm2_s, one;
unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
@@ -956,7 +957,7 @@ static int ecjpake_test_load( mbedtls_ecjpake_context *ctx,
const unsigned char *xm1, size_t len1,
const unsigned char *xm2, size_t len2 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) );
@@ -1004,7 +1005,7 @@ static int ecjpake_lgc( void *p, unsigned char *out, size_t len )
*/
int mbedtls_ecjpake_self_test( int verbose )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecjpake_context cli;
mbedtls_ecjpake_context srv;
unsigned char buf[512], pms[32];
diff --git a/features/mbedtls/mbed-crypto/src/ecp.c b/features/mbedtls/mbed-crypto/src/ecp.c
index c281d84195..e156fcbe2d 100644
--- a/features/mbedtls/mbed-crypto/src/ecp.c
+++ b/features/mbedtls/mbed-crypto/src/ecp.c
@@ -81,6 +81,7 @@
#include "mbedtls/ecp.h"
#include "mbedtls/threading.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -634,7 +635,7 @@ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key )
*/
int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( P != NULL );
ECP_VALIDATE_RET( Q != NULL );
@@ -662,7 +663,7 @@ int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src
*/
int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( pt != NULL );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) );
@@ -708,7 +709,7 @@ int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,
const char *x, const char *y )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( P != NULL );
ECP_VALIDATE_RET( x != NULL );
ECP_VALIDATE_RET( y != NULL );
@@ -903,7 +904,7 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp
int format, size_t *olen,
unsigned char *buf, size_t blen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( pt != NULL );
ECP_VALIDATE_RET( olen != NULL );
@@ -936,7 +937,7 @@ int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp
int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp,
const unsigned char **buf, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group_id grp_id;
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( buf != NULL );
@@ -1031,7 +1032,7 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen,
*/
static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( grp->modp == NULL )
return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) );
@@ -1088,7 +1089,7 @@ static inline int mbedtls_mpi_mul_mod( const mbedtls_ecp_group *grp,
const mbedtls_mpi *A,
const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( X, A, B ) );
MOD_MUL( *X );
cleanup:
@@ -1108,7 +1109,7 @@ static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp,
const mbedtls_mpi *A,
const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( X, A, B ) );
MOD_SUB( *X );
cleanup:
@@ -1129,7 +1130,7 @@ static inline int mbedtls_mpi_add_mod( const mbedtls_ecp_group *grp,
const mbedtls_mpi *A,
const mbedtls_mpi *B )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, A, B ) );
MOD_ADD( *X );
cleanup:
@@ -1140,7 +1141,7 @@ static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp,
mbedtls_mpi *X,
size_t count )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, count ) );
MOD_ADD( *X );
cleanup:
@@ -1162,7 +1163,7 @@ cleanup:
*/
static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi Zi, ZZi;
if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 )
@@ -1214,7 +1215,7 @@ cleanup:
static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *T[], size_t T_size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi *c, u, Zi, ZZi;
@@ -1303,7 +1304,7 @@ static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *Q,
unsigned char inv )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char nonzero;
mbedtls_mpi mQY;
@@ -1337,7 +1338,7 @@ cleanup:
static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_ecp_point *P )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi M, S, T, U;
#if defined(MBEDTLS_SELF_TEST)
@@ -1433,7 +1434,7 @@ cleanup:
static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi T1, T2, T3, T4, X, Y, Z;
#if defined(MBEDTLS_SELF_TEST)
@@ -1521,7 +1522,7 @@ cleanup:
static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi l, ll;
size_t p_size;
int count = 0;
@@ -1693,7 +1694,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp,
unsigned char w, size_t d,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char i;
size_t j = 0;
const unsigned char T_size = 1U << ( w - 1 );
@@ -1829,7 +1830,7 @@ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
const mbedtls_ecp_point T[], unsigned char T_size,
unsigned char i )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char ii, j;
/* Ignore the "sign" bit and scale down */
@@ -1862,7 +1863,7 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point Txi;
size_t i;
@@ -1942,7 +1943,7 @@ static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp,
unsigned char w,
unsigned char *parity_trick )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi M, mm;
mbedtls_mpi_init( &M );
@@ -1988,7 +1989,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char parity_trick;
unsigned char k[COMB_MAX_D + 1];
mbedtls_ecp_point *RR = R;
@@ -2083,7 +2084,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char w, p_eq_g, i;
size_t d;
unsigned char T_size, T_ok;
@@ -2215,7 +2216,7 @@ cleanup:
*/
static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
if( mbedtls_internal_ecp_grp_capable( grp ) )
@@ -2241,7 +2242,7 @@ cleanup:
static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi l;
size_t p_size;
int count = 0;
@@ -2296,7 +2297,7 @@ static int ecp_double_add_mxz( const mbedtls_ecp_group *grp,
const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q,
const mbedtls_mpi *d )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB;
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
@@ -2344,7 +2345,7 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
unsigned char b;
mbedtls_ecp_point RP;
@@ -2484,7 +2485,7 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
*/
static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi YY, RHS;
/* pt coordinates must be normalized for our checks */
@@ -2537,7 +2538,7 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp,
const mbedtls_ecp_point *P,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( mbedtls_mpi_cmp_int( m, 1 ) == 0 )
{
@@ -2569,7 +2570,7 @@ int mbedtls_ecp_muladd_restartable(
const mbedtls_mpi *n, const mbedtls_ecp_point *Q,
mbedtls_ecp_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point mP;
mbedtls_ecp_point *pmP = &mP;
mbedtls_ecp_point *pR = R;
@@ -2803,6 +2804,7 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
{
/* SEC1 3.2.1: Generate d such that 1 <= n < N */
int count = 0;
+ unsigned cmp = 0;
/*
* Match the procedure given in RFC 6979 (deterministic ECDSA):
@@ -2827,9 +2829,14 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp,
*/
if( ++count > 30 )
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
+
+ ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp );
+ if( ret != 0 )
+ {
+ goto cleanup;
+ }
}
- while( mbedtls_mpi_cmp_int( d, 1 ) < 0 ||
- mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 );
+ while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 );
}
#endif /* ECP_SHORTWEIERSTRASS */
@@ -2846,7 +2853,7 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( grp != NULL );
ECP_VALIDATE_RET( d != NULL );
ECP_VALIDATE_RET( G != NULL );
@@ -2882,7 +2889,7 @@ int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp,
int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ECP_VALIDATE_RET( key != NULL );
ECP_VALIDATE_RET( f_rng != NULL );
@@ -2966,7 +2973,7 @@ cleanup:
*/
int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point Q;
mbedtls_ecp_group grp;
ECP_VALIDATE_RET( pub != NULL );
@@ -3012,7 +3019,7 @@ cleanup:
*/
int mbedtls_ecp_self_test( int verbose )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_ecp_group grp;
mbedtls_ecp_point R, P;
diff --git a/features/mbedtls/mbed-crypto/src/ecp_curves.c b/features/mbedtls/mbed-crypto/src/ecp_curves.c
index dcc70739d0..a24a50c031 100644
--- a/features/mbedtls/mbed-crypto/src/ecp_curves.c
+++ b/features/mbedtls/mbed-crypto/src/ecp_curves.c
@@ -29,6 +29,7 @@
#include "mbedtls/ecp.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -669,7 +670,7 @@ static int ecp_mod_p256k1( mbedtls_mpi * );
*/
static int ecp_use_curve25519( mbedtls_ecp_group *grp )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Actually ( A + 2 ) / 4 */
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) );
@@ -709,7 +710,7 @@ cleanup:
static int ecp_use_curve448( mbedtls_ecp_group *grp )
{
mbedtls_mpi Ns;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_init( &Ns );
@@ -900,7 +901,7 @@ static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry )
*/
static int ecp_mod_p192( mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi_uint c = 0;
mbedtls_mpi_uint *p, *end;
@@ -991,7 +992,7 @@ static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
* (see fix_negative for the motivation of C)
*/
#define INIT( b ) \
- int ret; \
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \
signed char c = 0, cc; \
uint32_t cur; \
size_t i = 0, bits = (b); \
@@ -1027,7 +1028,7 @@ static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry )
*/
static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* C = - c * 2^(bits + 32) */
#if !defined(MBEDTLS_HAVE_INT64)
@@ -1185,7 +1186,7 @@ cleanup:
*/
static int ecp_mod_p521( mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi M;
mbedtls_mpi_uint Mp[P521_WIDTH + 1];
@@ -1234,7 +1235,7 @@ cleanup:
*/
static int ecp_mod_p255( mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi M;
mbedtls_mpi_uint Mp[P255_WIDTH + 2];
@@ -1291,7 +1292,7 @@ cleanup:
*/
static int ecp_mod_p448( mbedtls_mpi *N )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi M, Q;
mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH];
@@ -1353,7 +1354,7 @@ cleanup:
static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs,
size_t adjust, size_t shift, mbedtls_mpi_uint mask )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_mpi M, R;
mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1];
diff --git a/features/mbedtls/mbed-crypto/src/entropy.c b/features/mbedtls/mbed-crypto/src/entropy.c
index f8db1a5503..102f9f1c40 100644
--- a/features/mbedtls/mbed-crypto/src/entropy.c
+++ b/features/mbedtls/mbed-crypto/src/entropy.c
@@ -36,6 +36,7 @@
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -236,7 +237,7 @@ cleanup:
int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
const unsigned char *data, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C)
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
@@ -258,7 +259,9 @@ int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
*/
static int entropy_gather_internal( mbedtls_entropy_context *ctx )
{
- int ret, i, have_one_strong = 0;
+ int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+ int i;
+ int have_one_strong = 0;
unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
size_t olen;
@@ -306,7 +309,7 @@ cleanup:
*/
int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C)
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
@@ -325,7 +328,8 @@ int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
{
- int ret, count = 0, i, done;
+ int ret, count = 0, i, thresholds_reached;
+ size_t strong_size;
mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
@@ -363,12 +367,17 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
goto exit;
- done = 1;
+ thresholds_reached = 1;
+ strong_size = 0;
for( i = 0; i < ctx->source_count; i++ )
+ {
if( ctx->source[i].size < ctx->source[i].threshold )
- done = 0;
+ thresholds_reached = 0;
+ if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
+ strong_size += ctx->source[i].size;
+ }
}
- while( ! done );
+ while( ! thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE );
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
diff --git a/features/mbedtls/mbed-crypto/src/entropy_poll.c b/features/mbedtls/mbed-crypto/src/entropy_poll.c
index 4556f88a55..c9b2c95c60 100644
--- a/features/mbedtls/mbed-crypto/src/entropy_poll.c
+++ b/features/mbedtls/mbed-crypto/src/entropy_poll.c
@@ -36,6 +36,7 @@
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_TIMING_C)
#include "mbedtls/timing.h"
@@ -121,7 +122,7 @@ int mbedtls_platform_entropy_poll( void *data,
{
FILE *file;
size_t read_len;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
((void) data);
#if defined(HAVE_GETRANDOM)
diff --git a/features/mbedtls/mbed-crypto/src/gcm.c b/features/mbedtls/mbed-crypto/src/gcm.c
index 5121a7ac7e..e34f1dae40 100644
--- a/features/mbedtls/mbed-crypto/src/gcm.c
+++ b/features/mbedtls/mbed-crypto/src/gcm.c
@@ -39,6 +39,7 @@
#include "mbedtls/gcm.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -168,7 +169,7 @@ int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
const unsigned char *key,
unsigned int keybits )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
GCM_VALIDATE_RET( ctx != NULL );
@@ -246,7 +247,7 @@ static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16],
for( i = 15; i >= 0; i-- )
{
lo = x[i] & 0xf;
- hi = x[i] >> 4;
+ hi = ( x[i] >> 4 ) & 0xf;
if( i != 15 )
{
@@ -280,7 +281,7 @@ int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
const unsigned char *add,
size_t add_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char work_buf[16];
size_t i;
const unsigned char *p;
@@ -365,7 +366,7 @@ int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char ectr[16];
size_t i;
const unsigned char *p;
@@ -476,7 +477,7 @@ int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx,
size_t tag_len,
unsigned char *tag )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
GCM_VALIDATE_RET( ctx != NULL );
GCM_VALIDATE_RET( iv != NULL );
@@ -508,7 +509,7 @@ int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
size_t i;
int diff;
diff --git a/features/mbedtls/mbed-crypto/src/hkdf.c b/features/mbedtls/mbed-crypto/src/hkdf.c
index 82d8a429f4..379035ddbb 100644
--- a/features/mbedtls/mbed-crypto/src/hkdf.c
+++ b/features/mbedtls/mbed-crypto/src/hkdf.c
@@ -29,13 +29,14 @@
#include
#include "mbedtls/hkdf.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt,
size_t salt_len, const unsigned char *ikm, size_t ikm_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char prk[MBEDTLS_MD_MAX_SIZE];
ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk );
diff --git a/features/mbedtls/mbed-crypto/src/hmac_drbg.c b/features/mbedtls/mbed-crypto/src/hmac_drbg.c
index 50d88bd54b..f811885c9f 100644
--- a/features/mbedtls/mbed-crypto/src/hmac_drbg.c
+++ b/features/mbedtls/mbed-crypto/src/hmac_drbg.c
@@ -35,6 +35,7 @@
#include "mbedtls/hmac_drbg.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -74,7 +75,7 @@ int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
unsigned char sep[1];
unsigned char K[MBEDTLS_MD_MAX_SIZE];
- int ret;
+ int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
{
@@ -127,7 +128,7 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
const mbedtls_md_info_t * md_info,
const unsigned char *data, size_t data_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
return( ret );
@@ -159,7 +160,7 @@ static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx,
{
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen = 0;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
{
size_t total_entropy_len;
@@ -251,7 +252,7 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
const unsigned char *custom,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t md_size;
if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
@@ -273,16 +274,19 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
- /*
- * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
- * each hash function, then according to SP800-90A rev1 10.1 table 2,
- * min_entropy_len (in bits) is security_strength.
- *
- * (This also matches the sizes used in the NIST test vectors.)
- */
- ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
- md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
- 32; /* better (256+) -> 256 bits */
+ if( ctx->entropy_len == 0 )
+ {
+ /*
+ * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
+ * each hash function, then according to SP800-90A rev1 10.1 table 2,
+ * min_entropy_len (in bits) is security_strength.
+ *
+ * (This also matches the sizes used in the NIST test vectors.)
+ */
+ ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
+ md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
+ 32; /* better (256+) -> 256 bits */
+ }
if( ( ret = hmac_drbg_reseed_core( ctx, custom, len,
1 /* add nonce */ ) ) != 0 )
@@ -303,7 +307,7 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx
}
/*
- * Set entropy length grabbed for reseeds
+ * Set entropy length grabbed for seeding
*/
void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
{
@@ -326,7 +330,7 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t out_len,
const unsigned char *additional, size_t add_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
size_t left = out_len;
@@ -395,7 +399,7 @@ exit:
*/
int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
#if defined(MBEDTLS_THREADING_C)
@@ -431,7 +435,7 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
#if defined(MBEDTLS_FS_IO)
int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
FILE *f;
unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
diff --git a/features/mbedtls/mbed-crypto/src/md.c b/features/mbedtls/mbed-crypto/src/md.c
index e1b5183b6a..e235bc8daf 100644
--- a/features/mbedtls/mbed-crypto/src/md.c
+++ b/features/mbedtls/mbed-crypto/src/md.c
@@ -34,6 +34,7 @@
#include "mbedtls/md.h"
#include "mbedtls/md_internal.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include "mbedtls/md2.h"
#include "mbedtls/md4.h"
@@ -119,12 +120,14 @@ const mbedtls_md_info_t mbedtls_sha256_info = {
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
const mbedtls_md_info_t mbedtls_sha384_info = {
"SHA384",
MBEDTLS_MD_SHA384,
48,
128,
};
+#endif
const mbedtls_md_info_t mbedtls_sha512_info = {
"SHA512",
@@ -141,8 +144,10 @@ static const int supported_digests[] = {
#if defined(MBEDTLS_SHA512_C)
MBEDTLS_MD_SHA512,
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
MBEDTLS_MD_SHA384,
#endif
+#endif
#if defined(MBEDTLS_SHA256_C)
MBEDTLS_MD_SHA256,
@@ -210,8 +215,10 @@ const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name )
return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
if( !strcmp( "SHA384", md_name ) )
return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 );
+#endif
if( !strcmp( "SHA512", md_name ) )
return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 );
#endif
@@ -249,8 +256,10 @@ const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type )
return( &mbedtls_sha256_info );
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
return( &mbedtls_sha384_info );
+#endif
case MBEDTLS_MD_SHA512:
return( &mbedtls_sha512_info );
#endif
@@ -305,7 +314,9 @@ void mbedtls_md_free( mbedtls_md_context_t *ctx )
break;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
+#endif
case MBEDTLS_MD_SHA512:
mbedtls_sha512_free( ctx->md_ctx );
break;
@@ -371,7 +382,9 @@ int mbedtls_md_clone( mbedtls_md_context_t *dst,
break;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
+#endif
case MBEDTLS_MD_SHA512:
mbedtls_sha512_clone( dst->md_ctx, src->md_ctx );
break;
@@ -438,7 +451,9 @@ int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_inf
break;
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
+#endif
case MBEDTLS_MD_SHA512:
ALLOC( sha512 );
break;
@@ -497,8 +512,10 @@ int mbedtls_md_starts( mbedtls_md_context_t *ctx )
return( mbedtls_sha256_starts_ret( ctx->md_ctx, 0 ) );
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
return( mbedtls_sha512_starts_ret( ctx->md_ctx, 1 ) );
+#endif
case MBEDTLS_MD_SHA512:
return( mbedtls_sha512_starts_ret( ctx->md_ctx, 0 ) );
#endif
@@ -541,8 +558,10 @@ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, si
return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) );
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) );
+#endif
case MBEDTLS_MD_SHA512:
return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) );
#endif
@@ -585,8 +604,10 @@ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output )
return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) );
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) );
+#endif
case MBEDTLS_MD_SHA512:
return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) );
#endif
@@ -630,8 +651,10 @@ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, si
return( mbedtls_sha256_ret( input, ilen, output, 0 ) );
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
return( mbedtls_sha512_ret( input, ilen, output, 1 ) );
+#endif
case MBEDTLS_MD_SHA512:
return( mbedtls_sha512_ret( input, ilen, output, 0 ) );
#endif
@@ -643,7 +666,7 @@ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, si
#if defined(MBEDTLS_FS_IO)
int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
FILE *f;
size_t n;
mbedtls_md_context_t ctx;
@@ -683,7 +706,7 @@ cleanup:
int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char sum[MBEDTLS_MD_MAX_SIZE];
unsigned char *ipad, *opad;
size_t i;
@@ -738,7 +761,7 @@ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *inpu
int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
unsigned char *opad;
@@ -762,7 +785,7 @@ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *ipad;
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
@@ -781,7 +804,7 @@ int mbedtls_md_hmac( const mbedtls_md_info_t *md_info,
unsigned char *output )
{
mbedtls_md_context_t ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
@@ -838,8 +861,10 @@ int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data )
return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) );
#endif
#if defined(MBEDTLS_SHA512_C)
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
case MBEDTLS_MD_SHA384:
return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) );
+#endif
case MBEDTLS_MD_SHA512:
return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) );
#endif
diff --git a/features/mbedtls/mbed-crypto/src/md2.c b/features/mbedtls/mbed-crypto/src/md2.c
index 1c0b3df52d..82aed8e73c 100644
--- a/features/mbedtls/mbed-crypto/src/md2.c
+++ b/features/mbedtls/mbed-crypto/src/md2.c
@@ -35,6 +35,7 @@
#include "mbedtls/md2.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -170,7 +171,7 @@ int mbedtls_md2_update_ret( mbedtls_md2_context *ctx,
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
while( ilen > 0 )
@@ -212,7 +213,7 @@ void mbedtls_md2_update( mbedtls_md2_context *ctx,
int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
unsigned char x;
@@ -250,7 +251,7 @@ int mbedtls_md2_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md2_context ctx;
mbedtls_md2_init( &ctx );
diff --git a/features/mbedtls/mbed-crypto/src/md4.c b/features/mbedtls/mbed-crypto/src/md4.c
index 828fd42999..6a658e31d4 100644
--- a/features/mbedtls/mbed-crypto/src/md4.c
+++ b/features/mbedtls/mbed-crypto/src/md4.c
@@ -35,6 +35,7 @@
#include "mbedtls/md4.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -253,7 +254,7 @@ int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -323,7 +324,7 @@ static const unsigned char md4_padding[64] =
int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
@@ -371,7 +372,7 @@ int mbedtls_md4_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md4_context ctx;
mbedtls_md4_init( &ctx );
diff --git a/features/mbedtls/mbed-crypto/src/md5.c b/features/mbedtls/mbed-crypto/src/md5.c
index a93da8a061..2306855f46 100644
--- a/features/mbedtls/mbed-crypto/src/md5.c
+++ b/features/mbedtls/mbed-crypto/src/md5.c
@@ -34,6 +34,7 @@
#include "mbedtls/md5.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -259,7 +260,7 @@ int mbedtls_md5_update_ret( mbedtls_md5_context *ctx,
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -318,7 +319,7 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx,
int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t used;
uint32_t high, low;
@@ -386,7 +387,7 @@ int mbedtls_md5_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md5_context ctx;
mbedtls_md5_init( &ctx );
diff --git a/features/mbedtls/mbed-crypto/src/nist_kw.c b/features/mbedtls/mbed-crypto/src/nist_kw.c
index 317a2426ae..03e807202d 100644
--- a/features/mbedtls/mbed-crypto/src/nist_kw.c
+++ b/features/mbedtls/mbed-crypto/src/nist_kw.c
@@ -39,6 +39,7 @@
#include "mbedtls/nist_kw.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
#include
@@ -116,7 +117,7 @@ int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx,
unsigned int keybits,
const int is_wrap )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
cipher_info = mbedtls_cipher_info_from_values( cipher,
diff --git a/features/mbedtls/mbed-crypto/src/oid.c b/features/mbedtls/mbed-crypto/src/oid.c
index 27c455e877..891d3cdea9 100644
--- a/features/mbedtls/mbed-crypto/src/oid.c
+++ b/features/mbedtls/mbed-crypto/src/oid.c
@@ -31,6 +31,7 @@
#include "mbedtls/oid.h"
#include "mbedtls/rsa.h"
+#include "mbedtls/error.h"
#include
#include
@@ -732,7 +733,7 @@ FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pb
int mbedtls_oid_get_numeric_string( char *buf, size_t size,
const mbedtls_asn1_buf *oid )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n;
unsigned int value;
char *p;
diff --git a/features/mbedtls/mbed-crypto/src/pem.c b/features/mbedtls/mbed-crypto/src/pem.c
index 897c8a0d6f..31f4a9a25e 100644
--- a/features/mbedtls/mbed-crypto/src/pem.c
+++ b/features/mbedtls/mbed-crypto/src/pem.c
@@ -34,6 +34,7 @@
#include "mbedtls/md5.h"
#include "mbedtls/cipher.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -85,7 +86,7 @@ static int pem_pbkdf1( unsigned char *key, size_t keylen,
mbedtls_md5_context md5_ctx;
unsigned char md5sum[16];
size_t use_len;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md5_init( &md5_ctx );
@@ -146,7 +147,7 @@ static int pem_des_decrypt( unsigned char des_iv[8],
{
mbedtls_des_context des_ctx;
unsigned char des_key[8];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_des_init( &des_ctx );
@@ -174,7 +175,7 @@ static int pem_des3_decrypt( unsigned char des3_iv[8],
{
mbedtls_des3_context des3_ctx;
unsigned char des3_key[24];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_des3_init( &des3_ctx );
@@ -204,7 +205,7 @@ static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
{
mbedtls_aes_context aes_ctx;
unsigned char aes_key[32];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_aes_init( &aes_ctx );
@@ -439,7 +440,7 @@ int mbedtls_pem_write_buffer( const char *header, const char *footer,
const unsigned char *der_data, size_t der_len,
unsigned char *buf, size_t buf_len, size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *encode_buf = NULL, *c, *p = buf;
size_t len = 0, use_len, add_len = 0;
diff --git a/features/mbedtls/mbed-crypto/src/pk.c b/features/mbedtls/mbed-crypto/src/pk.c
index e93ccfdab9..b83ba8e71d 100644
--- a/features/mbedtls/mbed-crypto/src/pk.c
+++ b/features/mbedtls/mbed-crypto/src/pk.c
@@ -30,6 +30,7 @@
#include "mbedtls/pk_internal.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
@@ -297,7 +298,7 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
mbedtls_ecp_restart_is_enabled() &&
ctx->pk_info->verify_rs_func != NULL )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
return( ret );
@@ -354,7 +355,7 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
if( type == MBEDTLS_PK_RSASSA_PSS )
{
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_pk_rsassa_pss_options *pss_opts;
#if SIZE_MAX > UINT_MAX
@@ -420,7 +421,7 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
mbedtls_ecp_restart_is_enabled() &&
ctx->pk_info->sign_rs_func != NULL )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
return( ret );
@@ -604,7 +605,8 @@ int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
psa_ecc_curve_t curve_id;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type;
- int ret;
+ size_t bits;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* export the private key material in the format PSA wants */
if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY )
@@ -615,13 +617,13 @@ int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 )
return( ret );
- curve_id = mbedtls_ecp_curve_info_from_grp_id( ec->grp.id )->tls_id;
- key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(
- mbedtls_psa_parse_tls_ecc_group ( curve_id ) );
+ curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits );
+ key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id );
/* prepare the key attributes */
psa_set_key_type( &attributes, key_type );
- psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN );
+ psa_set_key_bits( &attributes, bits );
+ psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) );
/* import private key into PSA */
diff --git a/features/mbedtls/mbed-crypto/src/pk_wrap.c b/features/mbedtls/mbed-crypto/src/pk_wrap.c
index 5a699c030b..f736431495 100644
--- a/features/mbedtls/mbed-crypto/src/pk_wrap.c
+++ b/features/mbedtls/mbed-crypto/src/pk_wrap.c
@@ -27,6 +27,7 @@
#if defined(MBEDTLS_PK_C)
#include "mbedtls/pk_internal.h"
+#include "mbedtls/error.h"
/* Even if RSA not activated, for the sake of RSA-alt */
#include "mbedtls/rsa.h"
@@ -83,7 +84,7 @@ static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
size_t rsa_len = mbedtls_rsa_get_len( rsa );
@@ -248,7 +249,7 @@ static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init( &ecdsa );
@@ -266,7 +267,7 @@ static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init( &ecdsa );
@@ -340,7 +341,7 @@ static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *sig, size_t sig_len,
void *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
eckey_restart_ctx *rs = rs_ctx;
/* Should never happen */
@@ -365,7 +366,7 @@ static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
void *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
eckey_restart_ctx *rs = rs_ctx;
/* Should never happen */
@@ -490,7 +491,7 @@ static int ecdsa_can_do( mbedtls_pk_type_t type )
static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end,
unsigned char *to, size_t to_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t unpadded_len, padding_len;
if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len,
@@ -524,7 +525,7 @@ static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end
static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
unsigned char *sig, size_t int_size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t tmp_size;
if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size,
@@ -541,11 +542,12 @@ static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end,
return( 0 );
}
-static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
+static int ecdsa_verify_wrap( void *ctx_arg, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- int ret;
+ mbedtls_ecdsa_context *ctx = ctx_arg;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_handle_t key_handle = 0;
psa_status_t status;
@@ -556,9 +558,10 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
unsigned char *p;
mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
psa_algorithm_t psa_sig_md, psa_md;
- psa_ecc_curve_t curve = mbedtls_psa_translate_ecc_group(
- ( (mbedtls_ecdsa_context *) ctx )->grp.id );
- const size_t signature_part_size = ( ( (mbedtls_ecdsa_context *) ctx )->grp.nbits + 7 ) / 8;
+ size_t curve_bits;
+ psa_ecc_curve_t curve =
+ mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits );
+ const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8;
if( curve == 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
@@ -578,7 +581,7 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
psa_sig_md = PSA_ALG_ECDSA( psa_md );
psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) );
- psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY );
+ psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
psa_set_key_algorithm( &attributes, psa_sig_md );
status = psa_import_key( &attributes,
@@ -605,9 +608,9 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
goto cleanup;
}
- if( psa_asymmetric_verify( key_handle, psa_sig_md,
- hash, hash_len,
- buf, 2 * signature_part_size )
+ if( psa_verify_hash( key_handle, psa_sig_md,
+ hash, hash_len,
+ buf, 2 * signature_part_size )
!= PSA_SUCCESS )
{
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
@@ -630,7 +633,7 @@ static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
((void) md_alg);
ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx,
@@ -658,7 +661,7 @@ static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *sig, size_t sig_len,
void *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
((void) md_alg);
ret = mbedtls_ecdsa_read_signature_restartable(
@@ -774,6 +777,8 @@ static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
#endif /* SIZE_MAX > UINT_MAX */
*sig_len = rsa_alt->key_len_func( rsa_alt->key );
+ if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
md_alg, (unsigned int) hash_len, hash, sig ) );
@@ -802,7 +807,7 @@ static int rsa_alt_check_pair( const void *pub, const void *prv )
unsigned char sig[MBEDTLS_MPI_MAX_SIZE];
unsigned char hash[32];
size_t sig_len = 0;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
@@ -923,7 +928,7 @@ static int pk_opaque_can_do( mbedtls_pk_type_t type )
static int asn1_write_mpibuf( unsigned char **p, unsigned char *start,
size_t n_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( (size_t)( *p - start ) < n_len )
@@ -975,7 +980,7 @@ static int asn1_write_mpibuf( unsigned char **p, unsigned char *start,
static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len,
size_t buf_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
const size_t rs_len = *sig_len / 2;
unsigned char *p = sig + buf_len;
@@ -1017,10 +1022,12 @@ static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
return( mbedtls_psa_err_translate_pk( status ) );
buf_len = MBEDTLS_ECDSA_MAX_SIG_LEN( psa_get_key_bits( &attributes ) );
psa_reset_key_attributes( &attributes );
+ if( buf_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE )
+ return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
/* make the signature */
- status = psa_asymmetric_sign( *key, alg, hash, hash_len,
- sig, buf_len, sig_len );
+ status = psa_sign_hash( *key, alg, hash, hash_len,
+ sig, buf_len, sig_len );
if( status != PSA_SUCCESS )
return( mbedtls_psa_err_translate_pk( status ) );
diff --git a/features/mbedtls/mbed-crypto/src/pkcs12.c b/features/mbedtls/mbed-crypto/src/pkcs12.c
index 7edf064c13..96c64ad63c 100644
--- a/features/mbedtls/mbed-crypto/src/pkcs12.c
+++ b/features/mbedtls/mbed-crypto/src/pkcs12.c
@@ -37,6 +37,7 @@
#include "mbedtls/asn1.h"
#include "mbedtls/cipher.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -53,7 +54,7 @@
static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char **p = ¶ms->p;
const unsigned char *end = params->p + params->len;
@@ -145,7 +146,7 @@ int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode,
((void) output);
return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE );
#else
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char key[16];
mbedtls_arc4_context ctx;
((void) mode);
@@ -250,7 +251,7 @@ int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen,
const unsigned char *salt, size_t saltlen,
mbedtls_md_type_t md_type, int id, int iterations )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned int j;
unsigned char diversifier[128];
diff --git a/features/mbedtls/mbed-crypto/src/pkcs5.c b/features/mbedtls/mbed-crypto/src/pkcs5.c
index 3d29fd7e59..8832322257 100644
--- a/features/mbedtls/mbed-crypto/src/pkcs5.c
+++ b/features/mbedtls/mbed-crypto/src/pkcs5.c
@@ -38,6 +38,7 @@
#if defined(MBEDTLS_PKCS5_C)
#include "mbedtls/pkcs5.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_ASN1_PARSE_C)
#include "mbedtls/asn1.h"
@@ -59,7 +60,7 @@ static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf prf_alg_oid;
unsigned char *p = params->p;
const unsigned char *end = params->p + params->len;
diff --git a/features/mbedtls/mbed-crypto/src/pkparse.c b/features/mbedtls/mbed-crypto/src/pkparse.c
index ae210bca6a..1cbb8cc339 100644
--- a/features/mbedtls/mbed-crypto/src/pkparse.c
+++ b/features/mbedtls/mbed-crypto/src/pkparse.c
@@ -31,6 +31,7 @@
#include "mbedtls/asn1.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -130,7 +131,7 @@ int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n )
int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
const char *path, const char *pwd )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -157,7 +158,7 @@ int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
*/
int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -188,7 +189,7 @@ int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path )
static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
mbedtls_asn1_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ( end - *p < 1 )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
@@ -243,7 +244,7 @@ static int pk_get_ecparams( unsigned char **p, const unsigned char *end,
*/
static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = params->p;
const unsigned char * const end = params->p + params->len;
const unsigned char *end_field, *end_curve;
@@ -433,7 +434,7 @@ cleanup:
static int pk_group_id_from_specified( const mbedtls_asn1_buf *params,
mbedtls_ecp_group_id *grp_id )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group grp;
mbedtls_ecp_group_init( &grp );
@@ -460,7 +461,7 @@ cleanup:
*/
static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group_id grp_id;
if( params->tag == MBEDTLS_ASN1_OID )
@@ -500,7 +501,7 @@ static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *g
static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
mbedtls_ecp_keypair *key )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q,
(const unsigned char *) *p, end - *p ) ) == 0 )
@@ -528,7 +529,7 @@ static int pk_get_rsapubkey( unsigned char **p,
const unsigned char *end,
mbedtls_rsa_context *rsa )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -583,7 +584,7 @@ static int pk_get_pk_alg( unsigned char **p,
const unsigned char *end,
mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf alg_oid;
memset( params, 0, sizeof(mbedtls_asn1_buf) );
@@ -615,7 +616,7 @@ static int pk_get_pk_alg( unsigned char **p,
int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
mbedtls_pk_context *pk )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
mbedtls_asn1_buf alg_params;
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
@@ -677,6 +678,32 @@ int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
}
#if defined(MBEDTLS_RSA_C)
+/*
+ * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
+ *
+ * The value zero is:
+ * - never a valid value for an RSA parameter
+ * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
+ *
+ * Since values can't be omitted in PKCS#1, passing a zero value to
+ * rsa_complete() would be incorrect, so reject zero values early.
+ */
+static int asn1_get_nonzero_mpi( unsigned char **p,
+ const unsigned char *end,
+ mbedtls_mpi *X )
+{
+ int ret;
+
+ ret = mbedtls_asn1_get_mpi( p, end, X );
+ if( ret != 0 )
+ return( ret );
+
+ if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
+ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
+
+ return( 0 );
+}
+
/*
* Parse a PKCS#1 encoded private RSA key
*/
@@ -729,54 +756,84 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
}
/* Import N */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0,
- NULL, 0, NULL, 0 ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL,
+ NULL, NULL ) ) != 0 )
goto cleanup;
- p += len;
/* Import E */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
- NULL, 0, p, len ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL,
+ NULL, &T ) ) != 0 )
goto cleanup;
- p += len;
/* Import D */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
- p, len, NULL, 0 ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL,
+ &T, NULL ) ) != 0 )
goto cleanup;
- p += len;
/* Import P */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0,
- NULL, 0, NULL, 0 ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL,
+ NULL, NULL ) ) != 0 )
goto cleanup;
- p += len;
/* Import Q */
- if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
- MBEDTLS_ASN1_INTEGER ) ) != 0 ||
- ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len,
- NULL, 0, NULL, 0 ) ) != 0 )
- goto cleanup;
- p += len;
-
- /* Complete the RSA private key */
- if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T,
+ NULL, NULL ) ) != 0 )
goto cleanup;
- /* Check optional parameters */
- if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
- ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
- ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
+#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
+ /*
+ * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
+ * that they can be easily recomputed from D, P and Q. However by
+ * parsing them from the PKCS1 structure it is possible to avoid
+ * recalculating them which both reduces the overhead of loading
+ * RSA private keys into memory and also avoids side channels which
+ * can arise when computing those values, since all of D, P, and Q
+ * are secret. See https://eprint.iacr.org/2020/055 for a
+ * description of one such attack.
+ */
+
+ /* Import DP */
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 )
+ goto cleanup;
+
+ /* Import DQ */
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 )
+ goto cleanup;
+
+ /* Import QP */
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 )
+ goto cleanup;
+
+#else
+ /* Verify existance of the CRT params */
+ if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
+ ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 )
+ goto cleanup;
+#endif
+
+ /* rsa_complete() doesn't complete anything with the default
+ * implementation but is still called:
+ * - for the benefit of alternative implementation that may want to
+ * pre-compute stuff beyond what's provided (eg Montgomery factors)
+ * - as is also sanity-checks the key
+ *
+ * Furthermore, we also check the public part for consistency with
+ * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
+ */
+ if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ||
+ ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 )
+ {
goto cleanup;
+ }
if( p != end )
{
@@ -811,7 +868,7 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck,
const unsigned char *key,
size_t keylen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int version, pubkey_done;
size_t len;
mbedtls_asn1_buf params;
@@ -1164,7 +1221,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
const unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_pk_info_t *pk_info;
#if defined(MBEDTLS_PEM_PARSE_C)
size_t len;
@@ -1376,7 +1433,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
const unsigned char *key, size_t keylen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p;
#if defined(MBEDTLS_RSA_C)
const mbedtls_pk_info_t *pk_info;
diff --git a/features/mbedtls/mbed-crypto/src/pkwrite.c b/features/mbedtls/mbed-crypto/src/pkwrite.c
index 4388160786..b1b5f4685a 100644
--- a/features/mbedtls/mbed-crypto/src/pkwrite.c
+++ b/features/mbedtls/mbed-crypto/src/pkwrite.c
@@ -31,6 +31,7 @@
#include "mbedtls/asn1write.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -38,7 +39,9 @@
#include "mbedtls/rsa.h"
#endif
#if defined(MBEDTLS_ECP_C)
+#include "mbedtls/bignum.h"
#include "mbedtls/ecp.h"
+#include "mbedtls/platform_util.h"
#endif
#if defined(MBEDTLS_ECDSA_C)
#include "mbedtls/ecdsa.h"
@@ -75,7 +78,7 @@
static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
mbedtls_rsa_context *rsa )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
mbedtls_mpi T;
@@ -114,7 +117,7 @@ end_of_export:
static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
@@ -142,7 +145,7 @@ static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
static int pk_write_ec_param( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
const char *oid;
size_t oid_len;
@@ -154,12 +157,32 @@ static int pk_write_ec_param( unsigned char **p, unsigned char *start,
return( (int) len );
}
+
+/*
+ * privateKey OCTET STRING -- always of length ceil(log2(n)/8)
+ */
+static int pk_write_ec_private( unsigned char **p, unsigned char *start,
+ mbedtls_ecp_keypair *ec )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t byte_length = ( ec->grp.pbits + 7 ) / 8;
+ unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
+
+ ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length );
+ if( ret != 0 )
+ goto exit;
+ ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length );
+
+exit:
+ mbedtls_platform_zeroize( tmp, byte_length );
+ return( ret );
+}
#endif /* MBEDTLS_ECP_C */
int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
const mbedtls_pk_context *key )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
PK_VALIDATE_RET( p != NULL );
@@ -207,7 +230,7 @@ int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *c;
size_t len = 0, par_len = 0, oid_len;
mbedtls_pk_type_t pk_type;
@@ -250,18 +273,20 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si
psa_key_type_t key_type;
psa_key_handle_t handle;
psa_ecc_curve_t curve;
+ size_t bits;
handle = *((psa_key_handle_t*) key->pk_ctx );
if( PSA_SUCCESS != psa_get_key_attributes( handle, &attributes ) )
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
key_type = psa_get_key_type( &attributes );
+ bits = psa_get_key_bits( &attributes );
psa_reset_key_attributes( &attributes );
curve = PSA_KEY_TYPE_GET_CURVE( key_type );
if( curve == 0 )
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
- ret = mbedtls_psa_get_ecc_oid_from_id( curve, &oid, &oid_len );
+ ret = mbedtls_psa_get_ecc_oid_from_id( curve, bits, &oid, &oid_len );
if( ret != 0 )
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
@@ -293,7 +318,7 @@ int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, si
int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *c;
size_t len = 0;
@@ -424,9 +449,8 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) );
len += par_len;
- /* privateKey: write as MPI then fix tag */
- MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) );
- *c = MBEDTLS_ASN1_OCTET_STRING;
+ /* privateKey */
+ MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) );
/* version */
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) );
@@ -537,7 +561,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output_buf[PUB_DER_MAX_BYTES];
size_t olen = 0;
@@ -562,7 +586,7 @@ int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, si
int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output_buf[PRV_DER_MAX_BYTES];
const char *begin, *end;
size_t olen = 0;
diff --git a/features/mbedtls/mbed-crypto/src/platform.c b/features/mbedtls/mbed-crypto/src/platform.c
index 5756159543..420d09ea1e 100644
--- a/features/mbedtls/mbed-crypto/src/platform.c
+++ b/features/mbedtls/mbed-crypto/src/platform.c
@@ -29,6 +29,7 @@
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
/* The compile time configuration of memory allocation via the macros
* MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime
@@ -86,7 +87,7 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
#include
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
va_list argp;
va_start( argp, fmt );
@@ -131,7 +132,7 @@ int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
#include
int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Avoid calling the invalid parameter handler by checking ourselves */
if( s == NULL || n == 0 || fmt == NULL )
diff --git a/features/mbedtls/mbed-crypto/src/poly1305.c b/features/mbedtls/mbed-crypto/src/poly1305.c
index 2b56c5f7ef..bc1e8a6496 100644
--- a/features/mbedtls/mbed-crypto/src/poly1305.c
+++ b/features/mbedtls/mbed-crypto/src/poly1305.c
@@ -30,6 +30,7 @@
#include "mbedtls/poly1305.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -423,7 +424,7 @@ int mbedtls_poly1305_mac( const unsigned char key[32],
unsigned char mac[16] )
{
mbedtls_poly1305_context ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
POLY1305_VALIDATE_RET( key != NULL );
POLY1305_VALIDATE_RET( mac != NULL );
POLY1305_VALIDATE_RET( ilen == 0 || input != NULL );
@@ -529,7 +530,7 @@ int mbedtls_poly1305_self_test( int verbose )
{
unsigned char mac[16];
unsigned i;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
for( i = 0U; i < 2U; i++ )
{
diff --git a/features/mbedtls/mbed-crypto/src/ripemd160.c b/features/mbedtls/mbed-crypto/src/ripemd160.c
index 0791ae4cc9..a62f4b824e 100644
--- a/features/mbedtls/mbed-crypto/src/ripemd160.c
+++ b/features/mbedtls/mbed-crypto/src/ripemd160.c
@@ -35,6 +35,7 @@
#include "mbedtls/ripemd160.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -322,7 +323,7 @@ int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx,
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -390,7 +391,7 @@ static const unsigned char ripemd160_padding[64] =
int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx,
unsigned char output[20] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
@@ -439,7 +440,7 @@ int mbedtls_ripemd160_ret( const unsigned char *input,
size_t ilen,
unsigned char output[20] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ripemd160_context ctx;
mbedtls_ripemd160_init( &ctx );
diff --git a/features/mbedtls/mbed-crypto/src/rsa.c b/features/mbedtls/mbed-crypto/src/rsa.c
index a35af44746..6c457468ea 100644
--- a/features/mbedtls/mbed-crypto/src/rsa.c
+++ b/features/mbedtls/mbed-crypto/src/rsa.c
@@ -49,6 +49,7 @@
#include "mbedtls/rsa_internal.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -98,7 +99,7 @@ int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *E )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
RSA_VALIDATE_RET( ctx != NULL );
if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) ||
@@ -249,6 +250,9 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
{
int ret = 0;
int have_N, have_P, have_Q, have_D, have_E;
+#if !defined(MBEDTLS_RSA_NO_CRT)
+ int have_DP, have_DQ, have_QP;
+#endif
int n_missing, pq_missing, d_missing, is_pub, is_priv;
RSA_VALIDATE_RET( ctx != NULL );
@@ -259,6 +263,12 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
+#if !defined(MBEDTLS_RSA_NO_CRT)
+ have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 );
+ have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 );
+ have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 );
+#endif
+
/*
* Check whether provided parameters are enough
* to deduce all others. The following incomplete
@@ -324,7 +334,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
*/
#if !defined(MBEDTLS_RSA_NO_CRT)
- if( is_priv )
+ if( is_priv && ! ( have_DP && have_DQ && have_QP ) )
{
ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP );
@@ -392,7 +402,7 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,
mbedtls_mpi *D, mbedtls_mpi *E )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int is_priv;
RSA_VALIDATE_RET( ctx != NULL );
@@ -436,7 +446,7 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int is_priv;
RSA_VALIDATE_RET( ctx != NULL );
@@ -527,7 +537,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
void *p_rng,
unsigned int nbits, int exponent )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi H, G, L;
int prime_quality = 0;
RSA_VALIDATE_RET( ctx != NULL );
@@ -719,7 +729,7 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen;
mbedtls_mpi T;
RSA_VALIDATE_RET( ctx != NULL );
@@ -832,7 +842,7 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
const unsigned char *input,
unsigned char *output )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen;
/* Temporary holding the result */
@@ -1125,7 +1135,7 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
unsigned char *output )
{
size_t olen;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = output;
unsigned int hlen;
const mbedtls_md_info_t *md_info;
@@ -1212,7 +1222,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
unsigned char *output )
{
size_t nb_pad, olen;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = output;
RSA_VALIDATE_RET( ctx != NULL );
@@ -1322,7 +1332,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
unsigned char *output,
size_t output_max_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t ilen, i, pad_len;
unsigned char *p, bad, pad_done;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
@@ -1558,7 +1568,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
unsigned char *output,
size_t output_max_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t ilen, i, plaintext_max_size;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
/* The following variables take sensitive values: their value must
@@ -1774,7 +1784,7 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
unsigned char *p = sig;
unsigned char salt[MBEDTLS_MD_MAX_SIZE];
size_t slen, min_slen, hlen, offset = 0;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t msb;
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
@@ -2029,7 +2039,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
const unsigned char *hash,
unsigned char *sig )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *sig_try = NULL, *verif = NULL;
RSA_VALIDATE_RET( ctx != NULL );
@@ -2151,7 +2161,7 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
int expected_salt_len,
const unsigned char *sig )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t siglen;
unsigned char *p;
unsigned char *hash_start;
@@ -2448,7 +2458,7 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
*/
int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
RSA_VALIDATE_RET( dst != NULL );
RSA_VALIDATE_RET( src != NULL );
diff --git a/features/mbedtls/mbed-crypto/src/sha1.c b/features/mbedtls/mbed-crypto/src/sha1.c
index 355c83d2f7..9233943415 100644
--- a/features/mbedtls/mbed-crypto/src/sha1.c
+++ b/features/mbedtls/mbed-crypto/src/sha1.c
@@ -34,6 +34,7 @@
#include "mbedtls/sha1.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -307,7 +308,7 @@ int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx,
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -368,7 +369,7 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx,
unsigned char output[20] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t used;
uint32_t high, low;
@@ -440,7 +441,7 @@ int mbedtls_sha1_ret( const unsigned char *input,
size_t ilen,
unsigned char output[20] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_sha1_context ctx;
SHA1_VALIDATE_RET( ilen == 0 || input != NULL );
diff --git a/features/mbedtls/mbed-crypto/src/sha256.c b/features/mbedtls/mbed-crypto/src/sha256.c
index 2dc0e1a2c9..087a8e349c 100644
--- a/features/mbedtls/mbed-crypto/src/sha256.c
+++ b/features/mbedtls/mbed-crypto/src/sha256.c
@@ -34,6 +34,7 @@
#include "mbedtls/sha256.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#include
@@ -275,7 +276,7 @@ int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx,
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
@@ -336,7 +337,7 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx,
unsigned char output[32] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t used;
uint32_t high, low;
@@ -414,7 +415,7 @@ int mbedtls_sha256_ret( const unsigned char *input,
unsigned char output[32],
int is224 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_sha256_context ctx;
SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 );
diff --git a/features/mbedtls/mbed-crypto/src/sha512.c b/features/mbedtls/mbed-crypto/src/sha512.c
index 2e2b797872..30dd719540 100644
--- a/features/mbedtls/mbed-crypto/src/sha512.c
+++ b/features/mbedtls/mbed-crypto/src/sha512.c
@@ -34,6 +34,7 @@
#include "mbedtls/sha512.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define UL64(x) x##ui64
@@ -131,7 +132,11 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
{
SHA512_VALIDATE_RET( ctx != NULL );
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
+#else
+ SHA512_VALIDATE_RET( is384 == 0 );
+#endif
ctx->total[0] = 0;
ctx->total[1] = 0;
@@ -150,6 +155,9 @@ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
}
else
{
+#if defined(MBEDTLS_SHA512_NO_SHA384)
+ return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA );
+#else
/* SHA-384 */
ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
ctx->state[1] = UL64(0x629A292A367CD507);
@@ -159,9 +167,12 @@ int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
ctx->state[5] = UL64(0x8EB44A8768581511);
ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
+#endif /* MBEDTLS_SHA512_NO_SHA384 */
}
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
ctx->is384 = is384;
+#endif
return( 0 );
}
@@ -323,7 +334,7 @@ int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx,
const unsigned char *input,
size_t ilen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
unsigned int left;
@@ -383,7 +394,7 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
unsigned char output[64] )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned used;
uint64_t high, low;
@@ -436,7 +447,9 @@ int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
sha512_put_uint64_be( ctx->state[4], output, 32 );
sha512_put_uint64_be( ctx->state[5], output, 40 );
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
if( ctx->is384 == 0 )
+#endif
{
sha512_put_uint64_be( ctx->state[6], output, 48 );
sha512_put_uint64_be( ctx->state[7], output, 56 );
@@ -463,10 +476,14 @@ int mbedtls_sha512_ret( const unsigned char *input,
unsigned char output[64],
int is384 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_sha512_context ctx;
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
+#else
+ SHA512_VALIDATE_RET( is384 == 0 );
+#endif
SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
@@ -515,8 +532,9 @@ static const size_t sha512_test_buflen[3] =
3, 112, 1000
};
-static const unsigned char sha512_test_sum[6][64] =
+static const unsigned char sha512_test_sum[][64] =
{
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
/*
* SHA-384 test vectors
*/
@@ -538,6 +556,7 @@ static const unsigned char sha512_test_sum[6][64] =
0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
+#endif /* !MBEDTLS_SHA512_NO_SHA384 */
/*
* SHA-512 test vectors
@@ -568,6 +587,8 @@ static const unsigned char sha512_test_sum[6][64] =
0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
};
+#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) )
+
/*
* Checkup routine
*/
@@ -589,10 +610,14 @@ int mbedtls_sha512_self_test( int verbose )
mbedtls_sha512_init( &ctx );
- for( i = 0; i < 6; i++ )
+ for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ )
{
j = i % 3;
+#if !defined(MBEDTLS_SHA512_NO_SHA384)
k = i < 3;
+#else
+ k = 0;
+#endif
if( verbose != 0 )
mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
@@ -648,6 +673,8 @@ exit:
return( ret );
}
+#undef ARRAY_LENGTH
+
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_SHA512_C */
diff --git a/features/mbedtls/src/Makefile b/features/mbedtls/src/Makefile
index 501421fb64..6debdfd93d 100644
--- a/features/mbedtls/src/Makefile
+++ b/features/mbedtls/src/Makefile
@@ -37,7 +37,7 @@ endif
SOEXT_TLS=so.13
SOEXT_X509=so.1
-SOEXT_CRYPTO=so.3
+SOEXT_CRYPTO=so.4
# Set AR_DASH= (empty string) to use an ar implementation that does not accept
# the - prefix for command line options (e.g. llvm-ar)
@@ -77,6 +77,7 @@ OBJS_X509= certs.o pkcs11.o x509.o \
OBJS_TLS= debug.o net_sockets.o \
ssl_cache.o ssl_ciphersuites.o \
ssl_cli.o ssl_cookie.o \
+ ssl_msg.o \
ssl_srv.o ssl_ticket.o \
ssl_tls.o
@@ -146,17 +147,22 @@ libmbedx509.so: libmbedx509.$(SOEXT_X509)
echo " LN $@ -> $<"
ln -sf $< $@
-libmbedx509.dylib: $(OBJS_X509) libmbedcrypto.dylib
+libmbedx509.dylib: $(OBJS_X509) $(CRYPTO)libmbedcrypto.dylib
echo " LD $@"
$(CC) -dynamiclib -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509)
-libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll
+libmbedx509.dll: $(OBJS_X509) $(CRYPTO)libmbedcrypto.dll
echo " LD $@"
$(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS)
libmbedcrypto.%:
$(MAKE) CRYPTO_INCLUDES:="-I../../include -I../include" -C ../crypto/library $@
+libmbedcrypto.$(DLEXT): $(CRYPTO)libmbedcrypto.$(DLEXT)
+
+$(CRYPTO)libmbedcrypto.$(DLEXT): | libmbedcrypto.a
+ $(MAKE) CRYPTO_INCLUDES:="-I../../include -I../include" -C ../crypto/library libmbedcrypto.$(DLEXT)
+
.c.o:
echo " CC $<"
$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
diff --git a/features/mbedtls/src/debug.c b/features/mbedtls/src/debug.c
index 0c46c0690d..ae78a697a4 100644
--- a/features/mbedtls/src/debug.c
+++ b/features/mbedtls/src/debug.c
@@ -39,6 +39,7 @@
#endif
#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
#include
#include
@@ -85,7 +86,7 @@ void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level,
{
va_list argp;
char str[DEBUG_BUF_SIZE];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( NULL == ssl ||
NULL == ssl->conf ||
diff --git a/features/mbedtls/src/error.c b/features/mbedtls/src/error.c
index d8b5780483..c451f4ddff 100644
--- a/features/mbedtls/src/error.c
+++ b/features/mbedtls/src/error.c
@@ -25,8 +25,7 @@
#include MBEDTLS_CONFIG_FILE
#endif
-#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-#include "mbedtls/error.h"
+#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
#include
#endif
@@ -109,6 +108,10 @@
#include "mbedtls/entropy.h"
#endif
+#if defined(MBEDTLS_ERROR_C)
+#include "mbedtls/error.h"
+#endif
+
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
@@ -754,6 +757,13 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" );
#endif /* MBEDTLS_ENTROPY_C */
+#if defined(MBEDTLS_ERROR_C)
+ if( use_ret == -(MBEDTLS_ERR_ERROR_GENERIC_ERROR) )
+ mbedtls_snprintf( buf, buflen, "ERROR - Generic error" );
+ if( use_ret == -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED) )
+ mbedtls_snprintf( buf, buflen, "ERROR - This is a bug in the library" );
+#endif /* MBEDTLS_ERROR_C */
+
#if defined(MBEDTLS_GCM_C)
if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) )
mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
diff --git a/features/mbedtls/src/net_sockets.c b/features/mbedtls/src/net_sockets.c
index c7b358d057..dbde510db8 100644
--- a/features/mbedtls/src/net_sockets.c
+++ b/features/mbedtls/src/net_sockets.c
@@ -45,6 +45,7 @@
#endif
#include "mbedtls/net_sockets.h"
+#include "mbedtls/error.h"
#include
@@ -147,7 +148,7 @@ void mbedtls_net_init( mbedtls_net_context *ctx )
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host,
const char *port, int proto )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct addrinfo hints, *addr_list, *cur;
if( ( ret = net_prepare() ) != 0 )
@@ -313,7 +314,7 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
mbedtls_net_context *client_ctx,
void *client_ip, size_t buf_size, size_t *ip_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int type;
struct sockaddr_storage client_addr;
@@ -455,7 +456,7 @@ int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct timeval tv;
fd_set read_fds;
@@ -540,7 +541,7 @@ void mbedtls_net_usleep( unsigned long usec )
*/
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int fd = ((mbedtls_net_context *) ctx)->fd;
if( fd < 0 )
@@ -577,7 +578,7 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
size_t len, uint32_t timeout )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct timeval tv;
fd_set read_fds;
int fd = ((mbedtls_net_context *) ctx)->fd;
@@ -620,7 +621,7 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
*/
int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int fd = ((mbedtls_net_context *) ctx)->fd;
if( fd < 0 )
diff --git a/features/mbedtls/src/ssl_cli.c b/features/mbedtls/src/ssl_cli.c
index 57e5d8ab97..0f6a26b184 100644
--- a/features/mbedtls/src/ssl_cli.c
+++ b/features/mbedtls/src/ssl_cli.c
@@ -35,9 +35,10 @@
#define mbedtls_free free
#endif
-#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "mbedtls/psa_util.h"
@@ -402,7 +403,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t kkpp_len;
@@ -766,7 +767,7 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
*/
static int ssl_generate_random( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = ssl->handshake->randbytes;
#if defined(MBEDTLS_HAVE_TIME)
mbedtls_time_t t;
@@ -858,7 +859,7 @@ static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_inf
static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n, olen, ext_len = 0;
unsigned char *buf;
unsigned char *p, *q;
@@ -1470,7 +1471,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ssl->handshake->ciphersuite_info->key_exchange !=
MBEDTLS_KEY_EXCHANGE_ECJPAKE )
@@ -2243,6 +2244,7 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
unsigned char *end )
{
uint16_t tls_id;
+ size_t ecdh_bits = 0;
uint8_t ecpoint_len;
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
@@ -2263,11 +2265,14 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
tls_id |= *(*p)++;
/* Convert EC group to PSA key type. */
- if( ( handshake->ecdh_psa_curve =
- mbedtls_psa_parse_tls_ecc_group( tls_id ) ) == 0 )
+ if( ( handshake->ecdh_psa_type =
+ mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 )
{
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
+ if( ecdh_bits > 0xffff )
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+ handshake->ecdh_bits = (uint16_t) ecdh_bits;
/*
* Put peer's ECDH public key in the format understood by PSA.
@@ -2277,7 +2282,7 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
if( (size_t)( end - *p ) < ecpoint_len )
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
- if( mbedtls_psa_tls_ecpoint_to_psa_ec( handshake->ecdh_psa_curve,
+ if( mbedtls_psa_tls_ecpoint_to_psa_ec(
*p, ecpoint_len,
handshake->ecdh_psa_peerkey,
sizeof( handshake->ecdh_psa_peerkey ),
@@ -2384,7 +2389,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
size_t offset, size_t *olen,
size_t pms_offset )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
unsigned char *p = ssl->handshake->premaster + pms_offset;
mbedtls_pk_context * peer_pk;
@@ -2531,7 +2536,7 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_ecp_keypair *peer_key;
mbedtls_pk_context * peer_pk;
@@ -2582,7 +2587,7 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->handshake->ciphersuite_info;
unsigned char *p = NULL, *end = NULL;
@@ -2971,7 +2976,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
#else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *buf;
size_t n = 0;
size_t cert_type_len = 0, dn_len = 0;
@@ -3135,7 +3140,7 @@ exit:
static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
@@ -3174,7 +3179,7 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t header_len;
size_t content_len;
@@ -3256,11 +3261,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
key_attributes = psa_key_attributes_init();
psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE );
psa_set_key_algorithm( &key_attributes, PSA_ALG_ECDH );
- psa_set_key_type( &key_attributes,
- PSA_KEY_TYPE_ECC_KEY_PAIR( handshake->ecdh_psa_curve )
- );
- psa_set_key_bits( &key_attributes,
- PSA_ECC_CURVE_BITS( handshake->ecdh_psa_curve ) );
+ psa_set_key_type( &key_attributes, handshake->ecdh_psa_type );
+ psa_set_key_bits( &key_attributes, handshake->ecdh_bits );
/* Generate ECDH private key. */
status = psa_generate_key( &key_attributes,
@@ -3595,7 +3597,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->handshake->ciphersuite_info;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) );
@@ -3790,7 +3792,7 @@ sign:
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t lifetime;
size_t ticket_len;
unsigned char *ticket;
diff --git a/features/mbedtls/src/ssl_cookie.c b/features/mbedtls/src/ssl_cookie.c
index 56e9bdd2bf..4bf9058af4 100644
--- a/features/mbedtls/src/ssl_cookie.c
+++ b/features/mbedtls/src/ssl_cookie.c
@@ -40,6 +40,7 @@
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/ssl_internal.h"
+#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include
@@ -104,7 +105,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char key[COOKIE_MD_OUTLEN];
if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 )
@@ -157,7 +158,7 @@ int mbedtls_ssl_cookie_write( void *p_ctx,
unsigned char **p, unsigned char *end,
const unsigned char *cli_id, size_t cli_id_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx;
unsigned long t;
diff --git a/features/mbedtls/src/ssl_msg.c b/features/mbedtls/src/ssl_msg.c
new file mode 100644
index 0000000000..9c2d615095
--- /dev/null
+++ b/features/mbedtls/src/ssl_msg.c
@@ -0,0 +1,5691 @@
+/*
+ * Generic SSL/TLS messaging layer functions
+ * (record layer + retransmission state machine)
+ *
+ * Copyright (C) 2006-2020, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This file is part of mbed TLS (https://tls.mbed.org)
+ */
+/*
+ * The SSL 3.0 specification was drafted by Netscape in 1996,
+ * and became an IETF standard in 1999.
+ *
+ * http://wp.netscape.com/eng/ssl3/
+ * http://www.ietf.org/rfc/rfc2246.txt
+ * http://www.ietf.org/rfc/rfc4346.txt
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_SSL_TLS_C)
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include
+#define mbedtls_calloc calloc
+#define mbedtls_free free
+#endif
+
+#include "mbedtls/ssl.h"
+#include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+#include "mbedtls/platform_util.h"
+#include "mbedtls/version.h"
+
+#include
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#include "psa/crypto.h"
+#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#include "mbedtls/oid.h"
+#endif
+
+static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
+
+/*
+ * Start a timer.
+ * Passing millisecs = 0 cancels a running timer.
+ */
+void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs )
+{
+ if( ssl->f_set_timer == NULL )
+ return;
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) );
+ ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs );
+}
+
+/*
+ * Return -1 is timer is expired, 0 if it isn't.
+ */
+int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl )
+{
+ if( ssl->f_get_timer == NULL )
+ return( 0 );
+
+ if( ssl->f_get_timer( ssl->p_timer ) == 2 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) );
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
+ unsigned char *buf,
+ size_t len,
+ mbedtls_record *rec );
+
+int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
+ unsigned char *buf,
+ size_t buflen )
+{
+ int ret = 0;
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen );
+
+ /* We don't support record checking in TLS because
+ * (a) there doesn't seem to be a usecase for it, and
+ * (b) In SSLv3 and TLS 1.0, CBC record decryption has state
+ * and we'd need to backup the transform here.
+ */
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
+ {
+ ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ goto exit;
+ }
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ else
+ {
+ mbedtls_record rec;
+
+ ret = ssl_parse_record_header( ssl, buf, buflen, &rec );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret );
+ goto exit;
+ }
+
+ if( ssl->transform_in != NULL )
+ {
+ ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret );
+ goto exit;
+ }
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+exit:
+ /* On success, we have decrypted the buffer in-place, so make
+ * sure we don't leak any plaintext data. */
+ mbedtls_platform_zeroize( buf, buflen );
+
+ /* For the purpose of this API, treat messages with unexpected CID
+ * as well as such from future epochs as unexpected. */
+ if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID ||
+ ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+ {
+ ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) );
+ return( ret );
+}
+#endif /* MBEDTLS_SSL_RECORD_CHECKING */
+
+#define SSL_DONT_FORCE_FLUSH 0
+#define SSL_FORCE_FLUSH 1
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+/* Forward declarations for functions related to message buffering. */
+static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
+ uint8_t slot );
+static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
+static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
+static int ssl_buffer_message( mbedtls_ssl_context *ssl );
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
+ mbedtls_record const *rec );
+static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
+
+static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
+{
+ size_t mtu = mbedtls_ssl_get_current_mtu( ssl );
+
+ if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN )
+ return( mtu );
+
+ return( MBEDTLS_SSL_OUT_BUFFER_LEN );
+}
+
+static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
+{
+ size_t const bytes_written = ssl->out_left;
+ size_t const mtu = ssl_get_maximum_datagram_size( ssl );
+
+ /* Double-check that the write-index hasn't gone
+ * past what we can transmit in a single datagram. */
+ if( bytes_written > mtu )
+ {
+ /* Should never happen... */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ return( (int) ( mtu - bytes_written ) );
+}
+
+static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t remaining, expansion;
+ size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
+
+ if( max_len > mfl )
+ max_len = mfl;
+
+ /* By the standard (RFC 6066 Sect. 4), the MFL extension
+ * only limits the maximum record payload size, so in theory
+ * we would be allowed to pack multiple records of payload size
+ * MFL into a single datagram. However, this would mean that there's
+ * no way to explicitly communicate MTU restrictions to the peer.
+ *
+ * The following reduction of max_len makes sure that we never
+ * write datagrams larger than MFL + Record Expansion Overhead.
+ */
+ if( max_len <= ssl->out_left )
+ return( 0 );
+
+ max_len -= ssl->out_left;
+#endif
+
+ ret = ssl_get_remaining_space_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+ remaining = (size_t) ret;
+
+ ret = mbedtls_ssl_get_record_expansion( ssl );
+ if( ret < 0 )
+ return( ret );
+ expansion = (size_t) ret;
+
+ if( remaining <= expansion )
+ return( 0 );
+
+ remaining -= expansion;
+ if( remaining >= max_len )
+ remaining = max_len;
+
+ return( (int) remaining );
+}
+
+/*
+ * Double the retransmit timeout value, within the allowed range,
+ * returning -1 if the maximum value has already been reached.
+ */
+static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
+{
+ uint32_t new_timeout;
+
+ if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
+ return( -1 );
+
+ /* Implement the final paragraph of RFC 6347 section 4.1.1.1
+ * in the following way: after the initial transmission and a first
+ * retransmission, back off to a temporary estimated MTU of 508 bytes.
+ * This value is guaranteed to be deliverable (if not guaranteed to be
+ * delivered) of any compliant IPv4 (and IPv6) network, and should work
+ * on most non-IP stacks too. */
+ if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
+ {
+ ssl->handshake->mtu = 508;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
+ }
+
+ new_timeout = 2 * ssl->handshake->retransmit_timeout;
+
+ /* Avoid arithmetic overflow and range overflow */
+ if( new_timeout < ssl->handshake->retransmit_timeout ||
+ new_timeout > ssl->conf->hs_timeout_max )
+ {
+ new_timeout = ssl->conf->hs_timeout_max;
+ }
+
+ ssl->handshake->retransmit_timeout = new_timeout;
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
+ ssl->handshake->retransmit_timeout ) );
+
+ return( 0 );
+}
+
+static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
+{
+ ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
+ ssl->handshake->retransmit_timeout ) );
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
+int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl,
+ const unsigned char *key_enc, const unsigned char *key_dec,
+ size_t keylen,
+ const unsigned char *iv_enc, const unsigned char *iv_dec,
+ size_t ivlen,
+ const unsigned char *mac_enc, const unsigned char *mac_dec,
+ size_t maclen ) = NULL;
+int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL;
+int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL;
+int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL;
+int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL;
+int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL;
+#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
+
+/* The function below is only used in the Lucky 13 counter-measure in
+ * mbedtls_ssl_decrypt_buf(). These are the defines that guard the call site. */
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) && \
+ ( defined(MBEDTLS_SSL_PROTO_TLS1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2) )
+/* This function makes sure every byte in the memory region is accessed
+ * (in ascending addresses order) */
+static void ssl_read_memory( unsigned char *p, size_t len )
+{
+ unsigned char acc = 0;
+ volatile unsigned char force;
+
+ for( ; len != 0; p++, len-- )
+ acc ^= *p;
+
+ force = acc;
+ (void) force;
+}
+#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */
+
+/*
+ * Encryption/decryption functions
+ */
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+/* This functions transforms a DTLS plaintext fragment and a record content
+ * type into an instance of the DTLSInnerPlaintext structure:
+ *
+ * struct {
+ * opaque content[DTLSPlaintext.length];
+ * ContentType real_type;
+ * uint8 zeros[length_of_padding];
+ * } DTLSInnerPlaintext;
+ *
+ * Input:
+ * - `content`: The beginning of the buffer holding the
+ * plaintext to be wrapped.
+ * - `*content_size`: The length of the plaintext in Bytes.
+ * - `max_len`: The number of Bytes available starting from
+ * `content`. This must be `>= *content_size`.
+ * - `rec_type`: The desired record content type.
+ *
+ * Output:
+ * - `content`: The beginning of the resulting DTLSInnerPlaintext structure.
+ * - `*content_size`: The length of the resulting DTLSInnerPlaintext structure.
+ *
+ * Returns:
+ * - `0` on success.
+ * - A negative error code if `max_len` didn't offer enough space
+ * for the expansion.
+ */
+static int ssl_cid_build_inner_plaintext( unsigned char *content,
+ size_t *content_size,
+ size_t remaining,
+ uint8_t rec_type )
+{
+ size_t len = *content_size;
+ size_t pad = ( MBEDTLS_SSL_CID_PADDING_GRANULARITY -
+ ( len + 1 ) % MBEDTLS_SSL_CID_PADDING_GRANULARITY ) %
+ MBEDTLS_SSL_CID_PADDING_GRANULARITY;
+
+ /* Write real content type */
+ if( remaining == 0 )
+ return( -1 );
+ content[ len ] = rec_type;
+ len++;
+ remaining--;
+
+ if( remaining < pad )
+ return( -1 );
+ memset( content + len, 0, pad );
+ len += pad;
+ remaining -= pad;
+
+ *content_size = len;
+ return( 0 );
+}
+
+/* This function parses a DTLSInnerPlaintext structure.
+ * See ssl_cid_build_inner_plaintext() for details. */
+static int ssl_cid_parse_inner_plaintext( unsigned char const *content,
+ size_t *content_size,
+ uint8_t *rec_type )
+{
+ size_t remaining = *content_size;
+
+ /* Determine length of padding by skipping zeroes from the back. */
+ do
+ {
+ if( remaining == 0 )
+ return( -1 );
+ remaining--;
+ } while( content[ remaining ] == 0 );
+
+ *content_size = remaining;
+ *rec_type = content[ remaining ];
+
+ return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+/* `add_data` must have size 13 Bytes if the CID extension is disabled,
+ * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */
+static void ssl_extract_add_data_from_record( unsigned char* add_data,
+ size_t *add_data_len,
+ mbedtls_record *rec )
+{
+ /* Quoting RFC 5246 (TLS 1.2):
+ *
+ * additional_data = seq_num + TLSCompressed.type +
+ * TLSCompressed.version + TLSCompressed.length;
+ *
+ * For the CID extension, this is extended as follows
+ * (quoting draft-ietf-tls-dtls-connection-id-05,
+ * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05):
+ *
+ * additional_data = seq_num + DTLSPlaintext.type +
+ * DTLSPlaintext.version +
+ * cid +
+ * cid_length +
+ * length_of_DTLSInnerPlaintext;
+ */
+
+ memcpy( add_data, rec->ctr, sizeof( rec->ctr ) );
+ add_data[8] = rec->type;
+ memcpy( add_data + 9, rec->ver, sizeof( rec->ver ) );
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ if( rec->cid_len != 0 )
+ {
+ memcpy( add_data + 11, rec->cid, rec->cid_len );
+ add_data[11 + rec->cid_len + 0] = rec->cid_len;
+ add_data[11 + rec->cid_len + 1] = ( rec->data_len >> 8 ) & 0xFF;
+ add_data[11 + rec->cid_len + 2] = ( rec->data_len >> 0 ) & 0xFF;
+ *add_data_len = 13 + 1 + rec->cid_len;
+ }
+ else
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ {
+ add_data[11 + 0] = ( rec->data_len >> 8 ) & 0xFF;
+ add_data[11 + 1] = ( rec->data_len >> 0 ) & 0xFF;
+ *add_data_len = 13;
+ }
+}
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+
+#define SSL3_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */
+
+/*
+ * SSLv3.0 MAC functions
+ */
+static void ssl_mac( mbedtls_md_context_t *md_ctx,
+ const unsigned char *secret,
+ const unsigned char *buf, size_t len,
+ const unsigned char *ctr, int type,
+ unsigned char out[SSL3_MAC_MAX_BYTES] )
+{
+ unsigned char header[11];
+ unsigned char padding[48];
+ int padlen;
+ int md_size = mbedtls_md_get_size( md_ctx->md_info );
+ int md_type = mbedtls_md_get_type( md_ctx->md_info );
+
+ /* Only MD5 and SHA-1 supported */
+ if( md_type == MBEDTLS_MD_MD5 )
+ padlen = 48;
+ else
+ padlen = 40;
+
+ memcpy( header, ctr, 8 );
+ header[ 8] = (unsigned char) type;
+ header[ 9] = (unsigned char)( len >> 8 );
+ header[10] = (unsigned char)( len );
+
+ memset( padding, 0x36, padlen );
+ mbedtls_md_starts( md_ctx );
+ mbedtls_md_update( md_ctx, secret, md_size );
+ mbedtls_md_update( md_ctx, padding, padlen );
+ mbedtls_md_update( md_ctx, header, 11 );
+ mbedtls_md_update( md_ctx, buf, len );
+ mbedtls_md_finish( md_ctx, out );
+
+ memset( padding, 0x5C, padlen );
+ mbedtls_md_starts( md_ctx );
+ mbedtls_md_update( md_ctx, secret, md_size );
+ mbedtls_md_update( md_ctx, padding, padlen );
+ mbedtls_md_update( md_ctx, out, md_size );
+ mbedtls_md_finish( md_ctx, out );
+}
+#endif /* MBEDTLS_SSL_PROTO_SSL3 */
+
+int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform,
+ mbedtls_record *rec,
+ int (*f_rng)(void *, unsigned char *, size_t),
+ void *p_rng )
+{
+ mbedtls_cipher_mode_t mode;
+ int auth_done = 0;
+ unsigned char * data;
+ unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ];
+ size_t add_data_len;
+ size_t post_avail;
+
+ /* The SSL context is only used for debugging purposes! */
+#if !defined(MBEDTLS_DEBUG_C)
+ ssl = NULL; /* make sure we don't use it except for debug */
+ ((void) ssl);
+#endif
+
+ /* The PRNG is used for dynamic IV generation that's used
+ * for CBC transformations in TLS 1.1 and TLS 1.2. */
+#if !( defined(MBEDTLS_CIPHER_MODE_CBC) && \
+ ( defined(MBEDTLS_AES_C) || \
+ defined(MBEDTLS_ARIA_C) || \
+ defined(MBEDTLS_CAMELLIA_C) ) && \
+ ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) )
+ ((void) f_rng);
+ ((void) p_rng);
+#endif
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
+
+ if( transform == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ if( rec == NULL
+ || rec->buf == NULL
+ || rec->buf_len < rec->data_offset
+ || rec->buf_len - rec->data_offset < rec->data_len
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ || rec->cid_len != 0
+#endif
+ )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ data = rec->buf + rec->data_offset;
+ post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
+ data, rec->data_len );
+
+ mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc );
+
+ if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
+ (unsigned) rec->data_len,
+ MBEDTLS_SSL_OUT_CONTENT_LEN ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /*
+ * Add CID information
+ */
+ rec->cid_len = transform->out_cid_len;
+ memcpy( rec->cid, transform->out_cid, transform->out_cid_len );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len );
+
+ if( rec->cid_len != 0 )
+ {
+ /*
+ * Wrap plaintext into DTLSInnerPlaintext structure.
+ * See ssl_cid_build_inner_plaintext() for more information.
+ *
+ * Note that this changes `rec->data_len`, and hence
+ * `post_avail` needs to be recalculated afterwards.
+ */
+ if( ssl_cid_build_inner_plaintext( data,
+ &rec->data_len,
+ post_avail,
+ rec->type ) != 0 )
+ {
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ rec->type = MBEDTLS_SSL_MSG_CID;
+ }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
+
+ /*
+ * Add MAC before if needed
+ */
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ if( mode == MBEDTLS_MODE_STREAM ||
+ ( mode == MBEDTLS_MODE_CBC
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED
+#endif
+ ) )
+ {
+ if( post_avail < transform->maclen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+ {
+ unsigned char mac[SSL3_MAC_MAX_BYTES];
+ ssl_mac( &transform->md_ctx_enc, transform->mac_enc,
+ data, rec->data_len, rec->ctr, rec->type, mac );
+ memcpy( data + rec->data_len, mac, transform->maclen );
+ }
+ else
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
+ {
+ unsigned char mac[MBEDTLS_SSL_MAC_ADD];
+
+ ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
+
+ mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
+ add_data_len );
+ mbedtls_md_hmac_update( &transform->md_ctx_enc,
+ data, rec->data_len );
+ mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
+ mbedtls_md_hmac_reset( &transform->md_ctx_enc );
+
+ memcpy( data + rec->data_len, mac, transform->maclen );
+ }
+ else
+#endif
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len,
+ transform->maclen );
+
+ rec->data_len += transform->maclen;
+ post_avail -= transform->maclen;
+ auth_done++;
+ }
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+
+ /*
+ * Encrypt
+ */
+#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
+ if( mode == MBEDTLS_MODE_STREAM )
+ {
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t olen;
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including %d bytes of padding",
+ rec->data_len, 0 ) );
+
+ if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
+ transform->iv_enc, transform->ivlen,
+ data, rec->data_len,
+ data, &olen ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
+ return( ret );
+ }
+
+ if( rec->data_len != olen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+ else
+#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
+
+#if defined(MBEDTLS_GCM_C) || \
+ defined(MBEDTLS_CCM_C) || \
+ defined(MBEDTLS_CHACHAPOLY_C)
+ if( mode == MBEDTLS_MODE_GCM ||
+ mode == MBEDTLS_MODE_CCM ||
+ mode == MBEDTLS_MODE_CHACHAPOLY )
+ {
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char iv[12];
+ size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
+
+ /* Check that there's space for both the authentication tag
+ * and the explicit IV before and after the record content. */
+ if( post_avail < transform->taglen ||
+ rec->data_offset < explicit_iv_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ /*
+ * Generate IV
+ */
+ if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
+ {
+ /* GCM and CCM: fixed || explicit (=seqnum) */
+ memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
+ memcpy( iv + transform->fixed_ivlen, rec->ctr,
+ explicit_iv_len );
+ /* Prefix record content with explicit IV. */
+ memcpy( data - explicit_iv_len, rec->ctr, explicit_iv_len );
+ }
+ else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
+ {
+ /* ChachaPoly: fixed XOR sequence number */
+ unsigned char i;
+
+ memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
+
+ for( i = 0; i < 8; i++ )
+ iv[i+4] ^= rec->ctr[i];
+ }
+ else
+ {
+ /* Reminder if we ever add an AEAD mode with a different size */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
+ iv, transform->ivlen );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
+ data - explicit_iv_len, explicit_iv_len );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+ add_data, add_data_len );
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including 0 bytes of padding",
+ rec->data_len ) );
+
+ /*
+ * Encrypt and authenticate
+ */
+
+ if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc,
+ iv, transform->ivlen,
+ add_data, add_data_len, /* add data */
+ data, rec->data_len, /* source */
+ data, &rec->data_len, /* destination */
+ data + rec->data_len, transform->taglen ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret );
+ return( ret );
+ }
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag",
+ data + rec->data_len, transform->taglen );
+
+ rec->data_len += transform->taglen + explicit_iv_len;
+ rec->data_offset -= explicit_iv_len;
+ post_avail -= transform->taglen;
+ auth_done++;
+ }
+ else
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CIPHER_MODE_CBC) && \
+ ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) )
+ if( mode == MBEDTLS_MODE_CBC )
+ {
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t padlen, i;
+ size_t olen;
+
+ /* Currently we're always using minimal padding
+ * (up to 255 bytes would be allowed). */
+ padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen;
+ if( padlen == transform->ivlen )
+ padlen = 0;
+
+ /* Check there's enough space in the buffer for the padding. */
+ if( post_avail < padlen + 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ for( i = 0; i <= padlen; i++ )
+ data[rec->data_len + i] = (unsigned char) padlen;
+
+ rec->data_len += padlen + 1;
+ post_avail -= padlen + 1;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ /*
+ * Prepend per-record IV for block cipher in TLS v1.1 and up as per
+ * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
+ */
+ if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ if( f_rng == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ if( rec->data_offset < transform->ivlen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ /*
+ * Generate IV
+ */
+ ret = f_rng( p_rng, transform->iv_enc, transform->ivlen );
+ if( ret != 0 )
+ return( ret );
+
+ memcpy( data - transform->ivlen, transform->iv_enc,
+ transform->ivlen );
+
+ }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
+ "including %d bytes of IV and %d bytes of padding",
+ rec->data_len, transform->ivlen,
+ padlen + 1 ) );
+
+ if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
+ transform->iv_enc,
+ transform->ivlen,
+ data, rec->data_len,
+ data, &olen ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
+ return( ret );
+ }
+
+ if( rec->data_len != olen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
+ if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ /*
+ * Save IV in SSL3 and TLS1
+ */
+ memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv,
+ transform->ivlen );
+ }
+ else
+#endif
+ {
+ data -= transform->ivlen;
+ rec->data_offset -= transform->ivlen;
+ rec->data_len += transform->ivlen;
+ }
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ if( auth_done == 0 )
+ {
+ unsigned char mac[MBEDTLS_SSL_MAC_ADD];
+
+ /*
+ * MAC(MAC_write_key, seq_num +
+ * TLSCipherText.type +
+ * TLSCipherText.version +
+ * length_of( (IV +) ENC(...) ) +
+ * IV + // except for TLS 1.0
+ * ENC(content + padding + padding_length));
+ */
+
+ if( post_avail < transform->maclen)
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+ }
+
+ ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
+ add_data_len );
+
+ mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
+ add_data_len );
+ mbedtls_md_hmac_update( &transform->md_ctx_enc,
+ data, rec->data_len );
+ mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
+ mbedtls_md_hmac_reset( &transform->md_ctx_enc );
+
+ memcpy( data + rec->data_len, mac, transform->maclen );
+
+ rec->data_len += transform->maclen;
+ post_avail -= transform->maclen;
+ auth_done++;
+ }
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+ }
+ else
+#endif /* MBEDTLS_CIPHER_MODE_CBC &&
+ ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ /* Make extra sure authentication was performed, exactly once */
+ if( auth_done != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
+
+ return( 0 );
+}
+
+int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
+ mbedtls_ssl_transform *transform,
+ mbedtls_record *rec )
+{
+ size_t olen;
+ mbedtls_cipher_mode_t mode;
+ int ret, auth_done = 0;
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ size_t padlen = 0, correct = 1;
+#endif
+ unsigned char* data;
+ unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ];
+ size_t add_data_len;
+
+#if !defined(MBEDTLS_DEBUG_C)
+ ssl = NULL; /* make sure we don't use it except for debug */
+ ((void) ssl);
+#endif
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
+ if( rec == NULL ||
+ rec->buf == NULL ||
+ rec->buf_len < rec->data_offset ||
+ rec->buf_len - rec->data_offset < rec->data_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ data = rec->buf + rec->data_offset;
+ mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec );
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /*
+ * Match record's CID with incoming CID.
+ */
+ if( rec->cid_len != transform->in_cid_len ||
+ memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 )
+ {
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_CID );
+ }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
+ if( mode == MBEDTLS_MODE_STREAM )
+ {
+ padlen = 0;
+ if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
+ transform->iv_dec,
+ transform->ivlen,
+ data, rec->data_len,
+ data, &olen ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
+ return( ret );
+ }
+
+ if( rec->data_len != olen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+ else
+#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
+#if defined(MBEDTLS_GCM_C) || \
+ defined(MBEDTLS_CCM_C) || \
+ defined(MBEDTLS_CHACHAPOLY_C)
+ if( mode == MBEDTLS_MODE_GCM ||
+ mode == MBEDTLS_MODE_CCM ||
+ mode == MBEDTLS_MODE_CHACHAPOLY )
+ {
+ unsigned char iv[12];
+ size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
+
+ /*
+ * Prepare IV from explicit and implicit data.
+ */
+
+ /* Check that there's enough space for the explicit IV
+ * (at the beginning of the record) and the MAC (at the
+ * end of the record). */
+ if( rec->data_len < explicit_iv_len + transform->taglen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
+ "+ taglen (%d)", rec->data_len,
+ explicit_iv_len, transform->taglen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
+ }
+
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
+ if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
+ {
+ /* GCM and CCM: fixed || explicit */
+
+ /* Fixed */
+ memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
+ /* Explicit */
+ memcpy( iv + transform->fixed_ivlen, data, 8 );
+ }
+ else
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
+ {
+ /* ChachaPoly: fixed XOR sequence number */
+ unsigned char i;
+
+ memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
+
+ for( i = 0; i < 8; i++ )
+ iv[i+4] ^= rec->ctr[i];
+ }
+ else
+#endif /* MBEDTLS_CHACHAPOLY_C */
+ {
+ /* Reminder if we ever add an AEAD mode with a different size */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ /* Group changes to data, data_len, and add_data, because
+ * add_data depends on data_len. */
+ data += explicit_iv_len;
+ rec->data_offset += explicit_iv_len;
+ rec->data_len -= explicit_iv_len + transform->taglen;
+
+ ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
+ add_data, add_data_len );
+
+ /* Because of the check above, we know that there are
+ * explicit_iv_len Bytes preceeding data, and taglen
+ * bytes following data + data_len. This justifies
+ * the debug message and the invocation of
+ * mbedtls_cipher_auth_decrypt() below. */
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len,
+ transform->taglen );
+
+ /*
+ * Decrypt and authenticate
+ */
+ if( ( ret = mbedtls_cipher_auth_decrypt( &transform->cipher_ctx_dec,
+ iv, transform->ivlen,
+ add_data, add_data_len,
+ data, rec->data_len,
+ data, &olen,
+ data + rec->data_len,
+ transform->taglen ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret );
+
+ if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
+
+ return( ret );
+ }
+ auth_done++;
+
+ /* Double-check that AEAD decryption doesn't change content length. */
+ if( olen != rec->data_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+ else
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CIPHER_MODE_CBC) && \
+ ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) )
+ if( mode == MBEDTLS_MODE_CBC )
+ {
+ size_t minlen = 0;
+
+ /*
+ * Check immediate ciphertext sanity
+ */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ /* The ciphertext is prefixed with the CBC IV. */
+ minlen += transform->ivlen;
+ }
+#endif
+
+ /* Size considerations:
+ *
+ * - The CBC cipher text must not be empty and hence
+ * at least of size transform->ivlen.
+ *
+ * Together with the potential IV-prefix, this explains
+ * the first of the two checks below.
+ *
+ * - The record must contain a MAC, either in plain or
+ * encrypted, depending on whether Encrypt-then-MAC
+ * is used or not.
+ * - If it is, the message contains the IV-prefix,
+ * the CBC ciphertext, and the MAC.
+ * - If it is not, the padded plaintext, and hence
+ * the CBC ciphertext, has at least length maclen + 1
+ * because there is at least the padding length byte.
+ *
+ * As the CBC ciphertext is not empty, both cases give the
+ * lower bound minlen + maclen + 1 on the record size, which
+ * we test for in the second check below.
+ */
+ if( rec->data_len < minlen + transform->ivlen ||
+ rec->data_len < minlen + transform->maclen + 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) "
+ "+ 1 ) ( + expl IV )", rec->data_len,
+ transform->ivlen,
+ transform->maclen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
+ }
+
+ /*
+ * Authenticate before decrypt if enabled
+ */
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
+ {
+ unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
+
+ /* Update data_len in tandem with add_data.
+ *
+ * The subtraction is safe because of the previous check
+ * data_len >= minlen + maclen + 1.
+ *
+ * Afterwards, we know that data + data_len is followed by at
+ * least maclen Bytes, which justifies the call to
+ * mbedtls_ssl_safer_memcmp() below.
+ *
+ * Further, we still know that data_len > minlen */
+ rec->data_len -= transform->maclen;
+ ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
+
+ /* Calculate expected MAC. */
+ MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
+ add_data_len );
+ mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
+ add_data_len );
+ mbedtls_md_hmac_update( &transform->md_ctx_dec,
+ data, rec->data_len );
+ mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
+ mbedtls_md_hmac_reset( &transform->md_ctx_dec );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len,
+ transform->maclen );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect,
+ transform->maclen );
+
+ /* Compare expected MAC with MAC at the end of the record. */
+ if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect,
+ transform->maclen ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
+ }
+ auth_done++;
+ }
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+
+ /*
+ * Check length sanity
+ */
+
+ /* We know from above that data_len > minlen >= 0,
+ * so the following check in particular implies that
+ * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */
+ if( rec->data_len % transform->ivlen != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
+ rec->data_len, transform->ivlen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ /*
+ * Initialize for prepended IV for block cipher in TLS v1.1 and up
+ */
+ if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */
+ memcpy( transform->iv_dec, data, transform->ivlen );
+
+ data += transform->ivlen;
+ rec->data_offset += transform->ivlen;
+ rec->data_len -= transform->ivlen;
+ }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+
+ /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */
+
+ if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
+ transform->iv_dec, transform->ivlen,
+ data, rec->data_len, data, &olen ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
+ return( ret );
+ }
+
+ /* Double-check that length hasn't changed during decryption. */
+ if( rec->data_len != olen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
+ if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ /*
+ * Save IV in SSL3 and TLS1, where CBC decryption of consecutive
+ * records is equivalent to CBC decryption of the concatenation
+ * of the records; in other words, IVs are maintained across
+ * record decryptions.
+ */
+ memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv,
+ transform->ivlen );
+ }
+#endif
+
+ /* Safe since data_len >= minlen + maclen + 1, so after having
+ * subtracted at most minlen and maclen up to this point,
+ * data_len > 0 (because of data_len % ivlen == 0, it's actually
+ * >= ivlen ). */
+ padlen = data[rec->data_len - 1];
+
+ if( auth_done == 1 )
+ {
+ correct *= ( rec->data_len >= padlen + 1 );
+ padlen *= ( rec->data_len >= padlen + 1 );
+ }
+ else
+ {
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
+ if( rec->data_len < transform->maclen + padlen + 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
+ rec->data_len,
+ transform->maclen,
+ padlen + 1 ) );
+ }
+#endif
+
+ correct *= ( rec->data_len >= transform->maclen + padlen + 1 );
+ padlen *= ( rec->data_len >= transform->maclen + padlen + 1 );
+ }
+
+ padlen++;
+
+ /* Regardless of the validity of the padding,
+ * we have data_len >= padlen here. */
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+ {
+ if( padlen > transform->ivlen )
+ {
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
+ "should be no more than %d",
+ padlen, transform->ivlen ) );
+#endif
+ correct = 0;
+ }
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_SSL3 */
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
+ {
+ /* The padding check involves a series of up to 256
+ * consecutive memory reads at the end of the record
+ * plaintext buffer. In order to hide the length and
+ * validity of the padding, always perform exactly
+ * `min(256,plaintext_len)` reads (but take into account
+ * only the last `padlen` bytes for the padding check). */
+ size_t pad_count = 0;
+ size_t real_count = 0;
+ volatile unsigned char* const check = data;
+
+ /* Index of first padding byte; it has been ensured above
+ * that the subtraction is safe. */
+ size_t const padding_idx = rec->data_len - padlen;
+ size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256;
+ size_t const start_idx = rec->data_len - num_checks;
+ size_t idx;
+
+ for( idx = start_idx; idx < rec->data_len; idx++ )
+ {
+ real_count |= ( idx >= padding_idx );
+ pad_count += real_count * ( check[idx] == padlen - 1 );
+ }
+ correct &= ( pad_count == padlen );
+
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
+ if( padlen > 0 && correct == 0 )
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
+#endif
+ padlen &= correct * 0x1FF;
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
+ MBEDTLS_SSL_PROTO_TLS1_2 */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ /* If the padding was found to be invalid, padlen == 0
+ * and the subtraction is safe. If the padding was found valid,
+ * padlen hasn't been changed and the previous assertion
+ * data_len >= padlen still holds. */
+ rec->data_len -= padlen;
+ }
+ else
+#endif /* MBEDTLS_CIPHER_MODE_CBC &&
+ ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
+ MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption",
+ data, rec->data_len );
+#endif
+
+ /*
+ * Authenticate if not done yet.
+ * Compute the MAC regardless of the padding result (RFC4346, CBCTIME).
+ */
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ if( auth_done == 0 )
+ {
+ unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
+
+ /* If the initial value of padlen was such that
+ * data_len < maclen + padlen + 1, then padlen
+ * got reset to 1, and the initial check
+ * data_len >= minlen + maclen + 1
+ * guarantees that at this point we still
+ * have at least data_len >= maclen.
+ *
+ * If the initial value of padlen was such that
+ * data_len >= maclen + padlen + 1, then we have
+ * subtracted either padlen + 1 (if the padding was correct)
+ * or 0 (if the padding was incorrect) since then,
+ * hence data_len >= maclen in any case.
+ */
+ rec->data_len -= transform->maclen;
+ ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+ {
+ ssl_mac( &transform->md_ctx_dec,
+ transform->mac_dec,
+ data, rec->data_len,
+ rec->ctr, rec->type,
+ mac_expect );
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_SSL3 */
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
+ {
+ /*
+ * Process MAC and always update for padlen afterwards to make
+ * total time independent of padlen.
+ *
+ * Known timing attacks:
+ * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
+ *
+ * To compensate for different timings for the MAC calculation
+ * depending on how much padding was removed (which is determined
+ * by padlen), process extra_run more blocks through the hash
+ * function.
+ *
+ * The formula in the paper is
+ * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 )
+ * where L1 is the size of the header plus the decrypted message
+ * plus CBC padding and L2 is the size of the header plus the
+ * decrypted message. This is for an underlying hash function
+ * with 64-byte blocks.
+ * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values
+ * correctly. We round down instead of up, so -56 is the correct
+ * value for our calculations instead of -55.
+ *
+ * Repeat the formula rather than defining a block_size variable.
+ * This avoids requiring division by a variable at runtime
+ * (which would be marginally less efficient and would require
+ * linking an extra division function in some builds).
+ */
+ size_t j, extra_run = 0;
+ unsigned char tmp[MBEDTLS_MD_MAX_BLOCK_SIZE];
+
+ /*
+ * The next two sizes are the minimum and maximum values of
+ * in_msglen over all padlen values.
+ *
+ * They're independent of padlen, since we previously did
+ * data_len -= padlen.
+ *
+ * Note that max_len + maclen is never more than the buffer
+ * length, as we previously did in_msglen -= maclen too.
+ */
+ const size_t max_len = rec->data_len + padlen;
+ const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
+
+ memset( tmp, 0, sizeof( tmp ) );
+
+ switch( mbedtls_md_get_type( transform->md_ctx_dec.md_info ) )
+ {
+#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \
+ defined(MBEDTLS_SHA256_C)
+ case MBEDTLS_MD_MD5:
+ case MBEDTLS_MD_SHA1:
+ case MBEDTLS_MD_SHA256:
+ /* 8 bytes of message size, 64-byte compression blocks */
+ extra_run =
+ ( add_data_len + rec->data_len + padlen + 8 ) / 64 -
+ ( add_data_len + rec->data_len + 8 ) / 64;
+ break;
+#endif
+#if defined(MBEDTLS_SHA512_C)
+ case MBEDTLS_MD_SHA384:
+ /* 16 bytes of message size, 128-byte compression blocks */
+ extra_run =
+ ( add_data_len + rec->data_len + padlen + 16 ) / 128 -
+ ( add_data_len + rec->data_len + 16 ) / 128;
+ break;
+#endif
+ default:
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ extra_run &= correct * 0xFF;
+
+ mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
+ add_data_len );
+ mbedtls_md_hmac_update( &transform->md_ctx_dec, data,
+ rec->data_len );
+ /* Make sure we access everything even when padlen > 0. This
+ * makes the synchronisation requirements for just-in-time
+ * Prime+Probe attacks much tighter and hopefully impractical. */
+ ssl_read_memory( data + rec->data_len, padlen );
+ mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
+
+ /* Call mbedtls_md_process at least once due to cache attacks
+ * that observe whether md_process() was called of not */
+ for( j = 0; j < extra_run + 1; j++ )
+ mbedtls_md_process( &transform->md_ctx_dec, tmp );
+
+ mbedtls_md_hmac_reset( &transform->md_ctx_dec );
+
+ /* Make sure we access all the memory that could contain the MAC,
+ * before we check it in the next code block. This makes the
+ * synchronisation requirements for just-in-time Prime+Probe
+ * attacks much tighter and hopefully impractical. */
+ ssl_read_memory( data + min_len,
+ max_len - min_len + transform->maclen );
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
+ MBEDTLS_SSL_PROTO_TLS1_2 */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
+ MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, transform->maclen );
+#endif
+
+ if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect,
+ transform->maclen ) != 0 )
+ {
+#if defined(MBEDTLS_SSL_DEBUG_ALL)
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
+#endif
+ correct = 0;
+ }
+ auth_done++;
+ }
+
+ /*
+ * Finally check the correct flag
+ */
+ if( correct == 0 )
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
+#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+
+ /* Make extra sure authentication was performed, exactly once */
+ if( auth_done != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ if( rec->cid_len != 0 )
+ {
+ ret = ssl_cid_parse_inner_plaintext( data, &rec->data_len,
+ &rec->type );
+ if( ret != 0 )
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
+
+ return( 0 );
+}
+
+#undef MAC_NONE
+#undef MAC_PLAINTEXT
+#undef MAC_CIPHERTEXT
+
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+/*
+ * Compression/decompression functions
+ */
+static int ssl_compress_buf( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char *msg_post = ssl->out_msg;
+ ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf;
+ size_t len_pre = ssl->out_msglen;
+ unsigned char *msg_pre = ssl->compress_buf;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) );
+
+ if( len_pre == 0 )
+ return( 0 );
+
+ memcpy( msg_pre, ssl->out_msg, len_pre );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ",
+ ssl->out_msglen ) );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+ ssl->transform_out->ctx_deflate.next_in = msg_pre;
+ ssl->transform_out->ctx_deflate.avail_in = len_pre;
+ ssl->transform_out->ctx_deflate.next_out = msg_post;
+ ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written;
+
+ ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
+ if( ret != Z_OK )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) );
+ return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
+ }
+
+ ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN -
+ ssl->transform_out->ctx_deflate.avail_out - bytes_written;
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
+ ssl->out_msglen ) );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload",
+ ssl->out_msg, ssl->out_msglen );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) );
+
+ return( 0 );
+}
+
+static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char *msg_post = ssl->in_msg;
+ ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf;
+ size_t len_pre = ssl->in_msglen;
+ unsigned char *msg_pre = ssl->compress_buf;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) );
+
+ if( len_pre == 0 )
+ return( 0 );
+
+ memcpy( msg_pre, ssl->in_msg, len_pre );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ",
+ ssl->in_msglen ) );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload",
+ ssl->in_msg, ssl->in_msglen );
+
+ ssl->transform_in->ctx_inflate.next_in = msg_pre;
+ ssl->transform_in->ctx_inflate.avail_in = len_pre;
+ ssl->transform_in->ctx_inflate.next_out = msg_post;
+ ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN -
+ header_bytes;
+
+ ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
+ if( ret != Z_OK )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) );
+ return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
+ }
+
+ ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN -
+ ssl->transform_in->ctx_inflate.avail_out - header_bytes;
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
+ ssl->in_msglen ) );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload",
+ ssl->in_msg, ssl->in_msglen );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_ZLIB_SUPPORT */
+
+/*
+ * Fill the input message buffer by appending data to it.
+ * The amount of data already fetched is in ssl->in_left.
+ *
+ * If we return 0, is it guaranteed that (at least) nb_want bytes are
+ * available (from this read and/or a previous one). Otherwise, an error code
+ * is returned (possibly EOF or WANT_READ).
+ *
+ * With stream transport (TLS) on success ssl->in_left == nb_want, but
+ * with datagram transport (DTLS) on success ssl->in_left >= nb_want,
+ * since we always read a whole datagram at once.
+ *
+ * For DTLS, it is up to the caller to set ssl->next_record_offset when
+ * they're done reading a record.
+ */
+int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
+
+ if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
+ "or mbedtls_ssl_set_bio()" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ uint32_t timeout;
+
+ /* Just to be sure */
+ if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use "
+ "mbedtls_ssl_set_timer_cb() for DTLS" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ /*
+ * The point is, we need to always read a full datagram at once, so we
+ * sometimes read more then requested, and handle the additional data.
+ * It could be the rest of the current record (while fetching the
+ * header) and/or some other records in the same datagram.
+ */
+
+ /*
+ * Move to the next record in the already read datagram if applicable
+ */
+ if( ssl->next_record_offset != 0 )
+ {
+ if( ssl->in_left < ssl->next_record_offset )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ ssl->in_left -= ssl->next_record_offset;
+
+ if( ssl->in_left != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d",
+ ssl->next_record_offset ) );
+ memmove( ssl->in_hdr,
+ ssl->in_hdr + ssl->next_record_offset,
+ ssl->in_left );
+ }
+
+ ssl->next_record_offset = 0;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+ ssl->in_left, nb_want ) );
+
+ /*
+ * Done if we already have enough data.
+ */
+ if( nb_want <= ssl->in_left)
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
+ return( 0 );
+ }
+
+ /*
+ * A record can't be split across datagrams. If we need to read but
+ * are not at the beginning of a new record, the caller did something
+ * wrong.
+ */
+ if( ssl->in_left != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ /*
+ * Don't even try to read if time's out already.
+ * This avoids by-passing the timer when repeatedly receiving messages
+ * that will end up being dropped.
+ */
+ if( mbedtls_ssl_check_timer( ssl ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) );
+ ret = MBEDTLS_ERR_SSL_TIMEOUT;
+ }
+ else
+ {
+ len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
+
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ timeout = ssl->handshake->retransmit_timeout;
+ else
+ timeout = ssl->conf->read_timeout;
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) );
+
+ if( ssl->f_recv_timeout != NULL )
+ ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
+ timeout );
+ else
+ ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len );
+
+ MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
+
+ if( ret == 0 )
+ return( MBEDTLS_ERR_SSL_CONN_EOF );
+ }
+
+ if( ret == MBEDTLS_ERR_SSL_TIMEOUT )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) );
+ mbedtls_ssl_set_timer( ssl, 0 );
+
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ {
+ if( ssl_double_retransmit_timeout( ssl ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) );
+ return( MBEDTLS_ERR_SSL_TIMEOUT );
+ }
+
+ if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
+ return( ret );
+ }
+
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+ }
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
+ else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
+ {
+ if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
+ ret );
+ return( ret );
+ }
+
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+ }
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
+ }
+
+ if( ret < 0 )
+ return( ret );
+
+ ssl->in_left = ret;
+ }
+ else
+#endif
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+ ssl->in_left, nb_want ) );
+
+ while( ssl->in_left < nb_want )
+ {
+ len = nb_want - ssl->in_left;
+
+ if( mbedtls_ssl_check_timer( ssl ) != 0 )
+ ret = MBEDTLS_ERR_SSL_TIMEOUT;
+ else
+ {
+ if( ssl->f_recv_timeout != NULL )
+ {
+ ret = ssl->f_recv_timeout( ssl->p_bio,
+ ssl->in_hdr + ssl->in_left, len,
+ ssl->conf->read_timeout );
+ }
+ else
+ {
+ ret = ssl->f_recv( ssl->p_bio,
+ ssl->in_hdr + ssl->in_left, len );
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
+ ssl->in_left, nb_want ) );
+ MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
+
+ if( ret == 0 )
+ return( MBEDTLS_ERR_SSL_CONN_EOF );
+
+ if( ret < 0 )
+ return( ret );
+
+ if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1,
+ ( "f_recv returned %d bytes but only %lu were requested",
+ ret, (unsigned long)len ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ ssl->in_left += ret;
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
+
+ return( 0 );
+}
+
+/*
+ * Flush any data not yet written
+ */
+int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char *buf;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
+
+ if( ssl->f_send == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
+ "or mbedtls_ssl_set_bio()" ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ /* Avoid incrementing counter if data is flushed */
+ if( ssl->out_left == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
+ return( 0 );
+ }
+
+ while( ssl->out_left > 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
+ mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
+
+ buf = ssl->out_hdr - ssl->out_left;
+ ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left );
+
+ MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret );
+
+ if( ret <= 0 )
+ return( ret );
+
+ if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1,
+ ( "f_send returned %d bytes but only %lu bytes were sent",
+ ret, (unsigned long)ssl->out_left ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ ssl->out_left -= ret;
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->out_hdr = ssl->out_buf;
+ }
+ else
+#endif
+ {
+ ssl->out_hdr = ssl->out_buf + 8;
+ }
+ mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
+
+ return( 0 );
+}
+
+/*
+ * Functions to handle the DTLS retransmission state machine
+ */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+/*
+ * Append current handshake message to current outgoing flight
+ */
+static int ssl_flight_append( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_flight_item *msg;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight",
+ ssl->out_msg, ssl->out_msglen );
+
+ /* Allocate space for current message */
+ if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed",
+ sizeof( mbedtls_ssl_flight_item ) ) );
+ return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+ }
+
+ if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) );
+ mbedtls_free( msg );
+ return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+ }
+
+ /* Copy current handshake message with headers */
+ memcpy( msg->p, ssl->out_msg, ssl->out_msglen );
+ msg->len = ssl->out_msglen;
+ msg->type = ssl->out_msgtype;
+ msg->next = NULL;
+
+ /* Append to the current flight */
+ if( ssl->handshake->flight == NULL )
+ ssl->handshake->flight = msg;
+ else
+ {
+ mbedtls_ssl_flight_item *cur = ssl->handshake->flight;
+ while( cur->next != NULL )
+ cur = cur->next;
+ cur->next = msg;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) );
+ return( 0 );
+}
+
+/*
+ * Free the current flight of handshake messages
+ */
+void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight )
+{
+ mbedtls_ssl_flight_item *cur = flight;
+ mbedtls_ssl_flight_item *next;
+
+ while( cur != NULL )
+ {
+ next = cur->next;
+
+ mbedtls_free( cur->p );
+ mbedtls_free( cur );
+
+ cur = next;
+ }
+}
+
+/*
+ * Swap transform_out and out_ctr with the alternative ones
+ */
+static void ssl_swap_epochs( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_transform *tmp_transform;
+ unsigned char tmp_out_ctr[8];
+
+ if( ssl->transform_out == ssl->handshake->alt_transform_out )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) );
+ return;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) );
+
+ /* Swap transforms */
+ tmp_transform = ssl->transform_out;
+ ssl->transform_out = ssl->handshake->alt_transform_out;
+ ssl->handshake->alt_transform_out = tmp_transform;
+
+ /* Swap epoch + sequence_number */
+ memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 );
+ memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 );
+ memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 );
+
+ /* Adjust to the newly activated transform */
+ mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
+
+#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
+ if( mbedtls_ssl_hw_record_activate != NULL )
+ {
+ if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+ }
+#endif
+}
+
+/*
+ * Retransmit the current flight of messages.
+ */
+int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
+{
+ int ret = 0;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
+
+ ret = mbedtls_ssl_flight_transmit( ssl );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
+
+ return( ret );
+}
+
+/*
+ * Transmit or retransmit the current flight of messages.
+ *
+ * Need to remember the current message in case flush_output returns
+ * WANT_WRITE, causing us to exit this function and come back later.
+ * This function must be called until state is no longer SENDING.
+ */
+int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
+
+ if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) );
+
+ ssl->handshake->cur_msg = ssl->handshake->flight;
+ ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
+ ssl_swap_epochs( ssl );
+
+ ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
+ }
+
+ while( ssl->handshake->cur_msg != NULL )
+ {
+ size_t max_frag_len;
+ const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
+
+ int const is_finished =
+ ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ cur->p[0] == MBEDTLS_SSL_HS_FINISHED );
+
+ uint8_t const force_flush = ssl->disable_datagram_packing == 1 ?
+ SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
+
+ /* Swap epochs before sending Finished: we can't do it after
+ * sending ChangeCipherSpec, in case write returns WANT_READ.
+ * Must be done before copying, may change out_msg pointer */
+ if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
+ ssl_swap_epochs( ssl );
+ }
+
+ ret = ssl_get_remaining_payload_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+ max_frag_len = (size_t) ret;
+
+ /* CCS is copied as is, while HS messages may need fragmentation */
+ if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ if( max_frag_len == 0 )
+ {
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ continue;
+ }
+
+ memcpy( ssl->out_msg, cur->p, cur->len );
+ ssl->out_msglen = cur->len;
+ ssl->out_msgtype = cur->type;
+
+ /* Update position inside current message */
+ ssl->handshake->cur_msg_p += cur->len;
+ }
+ else
+ {
+ const unsigned char * const p = ssl->handshake->cur_msg_p;
+ const size_t hs_len = cur->len - 12;
+ const size_t frag_off = p - ( cur->p + 12 );
+ const size_t rem_len = hs_len - frag_off;
+ size_t cur_hs_frag_len, max_hs_frag_len;
+
+ if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
+ {
+ if( is_finished )
+ ssl_swap_epochs( ssl );
+
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ continue;
+ }
+ max_hs_frag_len = max_frag_len - 12;
+
+ cur_hs_frag_len = rem_len > max_hs_frag_len ?
+ max_hs_frag_len : rem_len;
+
+ if( frag_off == 0 && cur_hs_frag_len != hs_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)",
+ (unsigned) cur_hs_frag_len,
+ (unsigned) max_hs_frag_len ) );
+ }
+
+ /* Messages are stored with handshake headers as if not fragmented,
+ * copy beginning of headers then fill fragmentation fields.
+ * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
+ memcpy( ssl->out_msg, cur->p, 6 );
+
+ ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff );
+ ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff );
+ ssl->out_msg[8] = ( ( frag_off ) & 0xff );
+
+ ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff );
+ ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff );
+ ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff );
+
+ MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
+
+ /* Copy the handshake message content and set records fields */
+ memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
+ ssl->out_msglen = cur_hs_frag_len + 12;
+ ssl->out_msgtype = cur->type;
+
+ /* Update position inside current message */
+ ssl->handshake->cur_msg_p += cur_hs_frag_len;
+ }
+
+ /* If done with the current message move to the next one if any */
+ if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
+ {
+ if( cur->next != NULL )
+ {
+ ssl->handshake->cur_msg = cur->next;
+ ssl->handshake->cur_msg_p = cur->next->p + 12;
+ }
+ else
+ {
+ ssl->handshake->cur_msg = NULL;
+ ssl->handshake->cur_msg_p = NULL;
+ }
+ }
+
+ /* Actually send the message out */
+ if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ return( ret );
+ }
+ }
+
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ /* Update state and set timer */
+ if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
+ else
+ {
+ ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
+ mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) );
+
+ return( 0 );
+}
+
+/*
+ * To be called when the last message of an incoming flight is received.
+ */
+void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl )
+{
+ /* We won't need to resend that one any more */
+ mbedtls_ssl_flight_free( ssl->handshake->flight );
+ ssl->handshake->flight = NULL;
+ ssl->handshake->cur_msg = NULL;
+
+ /* The next incoming flight will start with this msg_seq */
+ ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;
+
+ /* We don't want to remember CCS's across flight boundaries. */
+ ssl->handshake->buffering.seen_ccs = 0;
+
+ /* Clear future message buffering structure. */
+ mbedtls_ssl_buffering_free( ssl );
+
+ /* Cancel timer */
+ mbedtls_ssl_set_timer( ssl, 0 );
+
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
+ {
+ ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
+ }
+ else
+ ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;
+}
+
+/*
+ * To be called when the last message of an outgoing flight is send.
+ */
+void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl )
+{
+ ssl_reset_retransmit_timeout( ssl );
+ mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
+
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
+ {
+ ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
+ }
+ else
+ ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+/*
+ * Handshake layer functions
+ */
+
+/*
+ * Write (DTLS: or queue) current handshake (including CCS) message.
+ *
+ * - fill in handshake headers
+ * - update handshake checksum
+ * - DTLS: save message for resending
+ * - then pass to the record layer
+ *
+ * DTLS: except for HelloRequest, messages are only queued, and will only be
+ * actually sent when calling flight_transmit() or resend().
+ *
+ * Inputs:
+ * - ssl->out_msglen: 4 + actual handshake message len
+ * (4 is the size of handshake headers for TLS)
+ * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)
+ * - ssl->out_msg + 4: the handshake message body
+ *
+ * Outputs, ie state before passing to flight_append() or write_record():
+ * - ssl->out_msglen: the length of the record contents
+ * (including handshake headers but excluding record headers)
+ * - ssl->out_msg: the record contents (handshake headers + content)
+ */
+int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ const size_t hs_len = ssl->out_msglen - 4;
+ const unsigned char hs_type = ssl->out_msg[0];
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) );
+
+ /*
+ * Sanity checks
+ */
+ if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE &&
+ ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ /* In SSLv3, the client might send a NoCertificate alert. */
+#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
+ if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
+ ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT &&
+ ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
+#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+
+ /* Whenever we send anything different from a
+ * HelloRequest we should be in a handshake - double check. */
+ if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) &&
+ ssl->handshake == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl->handshake != NULL &&
+ ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+#endif
+
+ /* Double-check that we did not exceed the bounds
+ * of the outgoing record buffer.
+ * This should never fail as the various message
+ * writing functions must obey the bounds of the
+ * outgoing record buffer, but better be safe.
+ *
+ * Note: We deliberately do not check for the MTU or MFL here.
+ */
+ if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
+ "size %u, maximum %u",
+ (unsigned) ssl->out_msglen,
+ (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ /*
+ * Fill handshake headers
+ */
+ if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
+ {
+ ssl->out_msg[1] = (unsigned char)( hs_len >> 16 );
+ ssl->out_msg[2] = (unsigned char)( hs_len >> 8 );
+ ssl->out_msg[3] = (unsigned char)( hs_len );
+
+ /*
+ * DTLS has additional fields in the Handshake layer,
+ * between the length field and the actual payload:
+ * uint16 message_seq;
+ * uint24 fragment_offset;
+ * uint24 fragment_length;
+ */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ /* Make room for the additional DTLS fields */
+ if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
+ "size %u, maximum %u",
+ (unsigned) ( hs_len ),
+ (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+
+ memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len );
+ ssl->out_msglen += 8;
+
+ /* Write message_seq and update it, except for HelloRequest */
+ if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
+ {
+ ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF;
+ ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF;
+ ++( ssl->handshake->out_msg_seq );
+ }
+ else
+ {
+ ssl->out_msg[4] = 0;
+ ssl->out_msg[5] = 0;
+ }
+
+ /* Handshake hashes are computed without fragmentation,
+ * so set frag_offset = 0 and frag_len = hs_len for now */
+ memset( ssl->out_msg + 6, 0x00, 3 );
+ memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 );
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ /* Update running hashes of handshake messages seen */
+ if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
+ ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
+ }
+
+ /* Either send now, or just save to be sent (and resent) later */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) )
+ {
+ if( ( ret = ssl_flight_append( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret );
+ return( ret );
+ }
+ }
+ else
+#endif
+ {
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret );
+ return( ret );
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) );
+
+ return( 0 );
+}
+
+/*
+ * Record layer functions
+ */
+
+/*
+ * Write current record.
+ *
+ * Uses:
+ * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)
+ * - ssl->out_msglen: length of the record content (excl headers)
+ * - ssl->out_msg: record content
+ */
+int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
+{
+ int ret, done = 0;
+ size_t len = ssl->out_msglen;
+ uint8_t flush = force_flush;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
+
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ if( ssl->transform_out != NULL &&
+ ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
+ {
+ if( ( ret = ssl_compress_buf( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret );
+ return( ret );
+ }
+
+ len = ssl->out_msglen;
+ }
+#endif /*MBEDTLS_ZLIB_SUPPORT */
+
+#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
+ if( mbedtls_ssl_hw_record_write != NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) );
+
+ ret = mbedtls_ssl_hw_record_write( ssl );
+ if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ if( ret == 0 )
+ done = 1;
+ }
+#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
+ if( !done )
+ {
+ unsigned i;
+ size_t protected_record_size;
+
+ /* Skip writing the record content type to after the encryption,
+ * as it may change when using the CID extension. */
+
+ mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
+ ssl->conf->transport, ssl->out_hdr + 1 );
+
+ memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
+ ssl->out_len[0] = (unsigned char)( len >> 8 );
+ ssl->out_len[1] = (unsigned char)( len );
+
+ if( ssl->transform_out != NULL )
+ {
+ mbedtls_record rec;
+
+ rec.buf = ssl->out_iv;
+ rec.buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN -
+ ( ssl->out_iv - ssl->out_buf );
+ rec.data_len = ssl->out_msglen;
+ rec.data_offset = ssl->out_msg - rec.buf;
+
+ memcpy( &rec.ctr[0], ssl->out_ctr, 8 );
+ mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
+ ssl->conf->transport, rec.ver );
+ rec.type = ssl->out_msgtype;
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /* The CID is set by mbedtls_ssl_encrypt_buf(). */
+ rec.cid_len = 0;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec,
+ ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
+ return( ret );
+ }
+
+ if( rec.data_offset != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ /* Update the record content type and CID. */
+ ssl->out_msgtype = rec.type;
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
+ memcpy( ssl->out_cid, rec.cid, rec.cid_len );
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->out_msglen = len = rec.data_len;
+ ssl->out_len[0] = (unsigned char)( rec.data_len >> 8 );
+ ssl->out_len[1] = (unsigned char)( rec.data_len );
+ }
+
+ protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ /* In case of DTLS, double-check that we don't exceed
+ * the remaining space in the datagram. */
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ret = ssl_get_remaining_space_in_datagram( ssl );
+ if( ret < 0 )
+ return( ret );
+
+ if( protected_record_size > (size_t) ret )
+ {
+ /* Should never happen */
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ /* Now write the potentially updated record content type. */
+ ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
+ "version = [%d:%d], msglen = %d",
+ ssl->out_hdr[0], ssl->out_hdr[1],
+ ssl->out_hdr[2], len ) );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
+ ssl->out_hdr, protected_record_size );
+
+ ssl->out_left += protected_record_size;
+ ssl->out_hdr += protected_record_size;
+ mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
+
+ for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
+ if( ++ssl->cur_out_ctr[i - 1] != 0 )
+ break;
+
+ /* The loop goes to its end iff the counter is wrapping */
+ if( i == mbedtls_ssl_ep_len( ssl ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
+ return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+ }
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ flush == SSL_DONT_FORCE_FLUSH )
+ {
+ size_t remaining;
+ ret = ssl_get_remaining_payload_in_datagram( ssl );
+ if( ret < 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram",
+ ret );
+ return( ret );
+ }
+
+ remaining = (size_t) ret;
+ if( remaining == 0 )
+ {
+ flush = SSL_FORCE_FLUSH;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ if( ( flush == SSL_FORCE_FLUSH ) &&
+ ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
+ return( ret );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) );
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
+{
+ if( ssl->in_msglen < ssl->in_hslen ||
+ memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 ||
+ memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 )
+ {
+ return( 1 );
+ }
+ return( 0 );
+}
+
+static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[9] << 16 ) |
+ ( ssl->in_msg[10] << 8 ) |
+ ssl->in_msg[11] );
+}
+
+static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[6] << 16 ) |
+ ( ssl->in_msg[7] << 8 ) |
+ ssl->in_msg[8] );
+}
+
+static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
+{
+ uint32_t msg_len, frag_off, frag_len;
+
+ msg_len = ssl_get_hs_total_len( ssl );
+ frag_off = ssl_get_hs_frag_off( ssl );
+ frag_len = ssl_get_hs_frag_len( ssl );
+
+ if( frag_off > msg_len )
+ return( -1 );
+
+ if( frag_len > msg_len - frag_off )
+ return( -1 );
+
+ if( frag_len + 12 > ssl->in_msglen )
+ return( -1 );
+
+ return( 0 );
+}
+
+/*
+ * Mark bits in bitmask (used for DTLS HS reassembly)
+ */
+static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len )
+{
+ unsigned int start_bits, end_bits;
+
+ start_bits = 8 - ( offset % 8 );
+ if( start_bits != 8 )
+ {
+ size_t first_byte_idx = offset / 8;
+
+ /* Special case */
+ if( len <= start_bits )
+ {
+ for( ; len != 0; len-- )
+ mask[first_byte_idx] |= 1 << ( start_bits - len );
+
+ /* Avoid potential issues with offset or len becoming invalid */
+ return;
+ }
+
+ offset += start_bits; /* Now offset % 8 == 0 */
+ len -= start_bits;
+
+ for( ; start_bits != 0; start_bits-- )
+ mask[first_byte_idx] |= 1 << ( start_bits - 1 );
+ }
+
+ end_bits = len % 8;
+ if( end_bits != 0 )
+ {
+ size_t last_byte_idx = ( offset + len ) / 8;
+
+ len -= end_bits; /* Now len % 8 == 0 */
+
+ for( ; end_bits != 0; end_bits-- )
+ mask[last_byte_idx] |= 1 << ( 8 - end_bits );
+ }
+
+ memset( mask + offset / 8, 0xFF, len / 8 );
+}
+
+/*
+ * Check that bitmask is full
+ */
+static int ssl_bitmask_check( unsigned char *mask, size_t len )
+{
+ size_t i;
+
+ for( i = 0; i < len / 8; i++ )
+ if( mask[i] != 0xFF )
+ return( -1 );
+
+ for( i = 0; i < len % 8; i++ )
+ if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 )
+ return( -1 );
+
+ return( 0 );
+}
+
+/* msg_len does not include the handshake header */
+static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
+ unsigned add_bitmap )
+{
+ size_t alloc_len;
+
+ alloc_len = 12; /* Handshake header */
+ alloc_len += msg_len; /* Content buffer */
+
+ if( add_bitmap )
+ alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */
+
+ return( alloc_len );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
+{
+ return( ( ssl->in_msg[1] << 16 ) |
+ ( ssl->in_msg[2] << 8 ) |
+ ssl->in_msg[3] );
+}
+
+int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
+{
+ if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d",
+ ssl->in_msglen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
+ " %d, type = %d, hslen = %d",
+ ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+
+ if( ssl_check_hs_header( ssl ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->handshake != NULL &&
+ ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
+ recv_msg_seq != ssl->handshake->in_msg_seq ) ||
+ ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
+ ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
+ {
+ if( recv_msg_seq > ssl->handshake->in_msg_seq )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)",
+ recv_msg_seq,
+ ssl->handshake->in_msg_seq ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+
+ /* Retransmit only on last message from previous flight, to avoid
+ * too many retransmissions.
+ * Besides, No sane server ever retransmits HelloVerifyRequest */
+ if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 &&
+ ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, "
+ "message_seq = %d, start_of_flight = %d",
+ recv_msg_seq,
+ ssl->handshake->in_flight_start_seq ) );
+
+ if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
+ return( ret );
+ }
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: "
+ "message_seq = %d, expected = %d",
+ recv_msg_seq,
+ ssl->handshake->in_msg_seq ) );
+ }
+
+ return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
+ }
+ /* Wait until message completion to increment in_msg_seq */
+
+ /* Message reassembly is handled alongside buffering of future
+ * messages; the commonality is that both handshake fragments and
+ * future messages cannot be forwarded immediately to the
+ * handshake logic layer. */
+ if( ssl_hs_is_proper_fragment( ssl ) == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ /* With TLS we don't handle fragmentation (for now) */
+ if( ssl->in_msglen < ssl->in_hslen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) );
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
+
+ return( 0 );
+}
+
+void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
+ {
+ ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
+ }
+
+ /* Handshake message is complete, increment counter */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl->handshake != NULL )
+ {
+ unsigned offset;
+ mbedtls_ssl_hs_buffer *hs_buf;
+
+ /* Increment handshake sequence number */
+ hs->in_msg_seq++;
+
+ /*
+ * Clear up handshake buffering and reassembly structure.
+ */
+
+ /* Free first entry */
+ ssl_buffering_free_slot( ssl, 0 );
+
+ /* Shift all other entries */
+ for( offset = 0, hs_buf = &hs->buffering.hs[0];
+ offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
+ offset++, hs_buf++ )
+ {
+ *hs_buf = *(hs_buf + 1);
+ }
+
+ /* Create a fresh last entry */
+ memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
+ }
+#endif
+}
+
+/*
+ * DTLS anti-replay: RFC 6347 4.1.2.6
+ *
+ * in_window is a field of bits numbered from 0 (lsb) to 63 (msb).
+ * Bit n is set iff record number in_window_top - n has been seen.
+ *
+ * Usually, in_window_top is the last record number seen and the lsb of
+ * in_window is set. The only exception is the initial state (record number 0
+ * not seen yet).
+ */
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl )
+{
+ ssl->in_window_top = 0;
+ ssl->in_window = 0;
+}
+
+static inline uint64_t ssl_load_six_bytes( unsigned char *buf )
+{
+ return( ( (uint64_t) buf[0] << 40 ) |
+ ( (uint64_t) buf[1] << 32 ) |
+ ( (uint64_t) buf[2] << 24 ) |
+ ( (uint64_t) buf[3] << 16 ) |
+ ( (uint64_t) buf[4] << 8 ) |
+ ( (uint64_t) buf[5] ) );
+}
+
+static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ unsigned char *original_in_ctr;
+
+ // save original in_ctr
+ original_in_ctr = ssl->in_ctr;
+
+ // use counter from record
+ ssl->in_ctr = record_in_ctr;
+
+ ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl );
+
+ // restore the counter
+ ssl->in_ctr = original_in_ctr;
+
+ return ret;
+}
+
+/*
+ * Return 0 if sequence number is acceptable, -1 otherwise
+ */
+int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl )
+{
+ uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
+ uint64_t bit;
+
+ if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
+ return( 0 );
+
+ if( rec_seqnum > ssl->in_window_top )
+ return( 0 );
+
+ bit = ssl->in_window_top - rec_seqnum;
+
+ if( bit >= 64 )
+ return( -1 );
+
+ if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 )
+ return( -1 );
+
+ return( 0 );
+}
+
+/*
+ * Update replay window on new validated record
+ */
+void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
+{
+ uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
+
+ if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
+ return;
+
+ if( rec_seqnum > ssl->in_window_top )
+ {
+ /* Update window_top and the contents of the window */
+ uint64_t shift = rec_seqnum - ssl->in_window_top;
+
+ if( shift >= 64 )
+ ssl->in_window = 1;
+ else
+ {
+ ssl->in_window <<= shift;
+ ssl->in_window |= 1;
+ }
+
+ ssl->in_window_top = rec_seqnum;
+ }
+ else
+ {
+ /* Mark that number as seen in the current window */
+ uint64_t bit = ssl->in_window_top - rec_seqnum;
+
+ if( bit < 64 ) /* Always true, but be extra sure */
+ ssl->in_window |= (uint64_t) 1 << bit;
+ }
+}
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
+
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+/*
+ * Without any SSL context, check if a datagram looks like a ClientHello with
+ * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message.
+ * Both input and output include full DTLS headers.
+ *
+ * - if cookie is valid, return 0
+ * - if ClientHello looks superficially valid but cookie is not,
+ * fill obuf and set olen, then
+ * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
+ * - otherwise return a specific error code
+ */
+static int ssl_check_dtls_clihlo_cookie(
+ mbedtls_ssl_cookie_write_t *f_cookie_write,
+ mbedtls_ssl_cookie_check_t *f_cookie_check,
+ void *p_cookie,
+ const unsigned char *cli_id, size_t cli_id_len,
+ const unsigned char *in, size_t in_len,
+ unsigned char *obuf, size_t buf_len, size_t *olen )
+{
+ size_t sid_len, cookie_len;
+ unsigned char *p;
+
+ /*
+ * Structure of ClientHello with record and handshake headers,
+ * and expected values. We don't need to check a lot, more checks will be
+ * done when actually parsing the ClientHello - skipping those checks
+ * avoids code duplication and does not make cookie forging any easier.
+ *
+ * 0-0 ContentType type; copied, must be handshake
+ * 1-2 ProtocolVersion version; copied
+ * 3-4 uint16 epoch; copied, must be 0
+ * 5-10 uint48 sequence_number; copied
+ * 11-12 uint16 length; (ignored)
+ *
+ * 13-13 HandshakeType msg_type; (ignored)
+ * 14-16 uint24 length; (ignored)
+ * 17-18 uint16 message_seq; copied
+ * 19-21 uint24 fragment_offset; copied, must be 0
+ * 22-24 uint24 fragment_length; (ignored)
+ *
+ * 25-26 ProtocolVersion client_version; (ignored)
+ * 27-58 Random random; (ignored)
+ * 59-xx SessionID session_id; 1 byte len + sid_len content
+ * 60+ opaque cookie<0..2^8-1>; 1 byte len + content
+ * ...
+ *
+ * Minimum length is 61 bytes.
+ */
+ if( in_len < 61 ||
+ in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
+ in[3] != 0 || in[4] != 0 ||
+ in[19] != 0 || in[20] != 0 || in[21] != 0 )
+ {
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+
+ sid_len = in[59];
+ if( sid_len > in_len - 61 )
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+ cookie_len = in[60 + sid_len];
+ if( cookie_len > in_len - 60 )
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+
+ if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len,
+ cli_id, cli_id_len ) == 0 )
+ {
+ /* Valid cookie */
+ return( 0 );
+ }
+
+ /*
+ * If we get here, we've got an invalid cookie, let's prepare HVR.
+ *
+ * 0-0 ContentType type; copied
+ * 1-2 ProtocolVersion version; copied
+ * 3-4 uint16 epoch; copied
+ * 5-10 uint48 sequence_number; copied
+ * 11-12 uint16 length; olen - 13
+ *
+ * 13-13 HandshakeType msg_type; hello_verify_request
+ * 14-16 uint24 length; olen - 25
+ * 17-18 uint16 message_seq; copied
+ * 19-21 uint24 fragment_offset; copied
+ * 22-24 uint24 fragment_length; olen - 25
+ *
+ * 25-26 ProtocolVersion server_version; 0xfe 0xff
+ * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie
+ *
+ * Minimum length is 28.
+ */
+ if( buf_len < 28 )
+ return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
+
+ /* Copy most fields and adapt others */
+ memcpy( obuf, in, 25 );
+ obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
+ obuf[25] = 0xfe;
+ obuf[26] = 0xff;
+
+ /* Generate and write actual cookie */
+ p = obuf + 28;
+ if( f_cookie_write( p_cookie,
+ &p, obuf + buf_len, cli_id, cli_id_len ) != 0 )
+ {
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ *olen = p - obuf;
+
+ /* Go back and fill length fields */
+ obuf[27] = (unsigned char)( *olen - 28 );
+
+ obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 );
+ obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 );
+ obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) );
+
+ obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 );
+ obuf[12] = (unsigned char)( ( *olen - 13 ) );
+
+ return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
+}
+
+/*
+ * Handle possible client reconnect with the same UDP quadruplet
+ * (RFC 6347 Section 4.2.8).
+ *
+ * Called by ssl_parse_record_header() in case we receive an epoch 0 record
+ * that looks like a ClientHello.
+ *
+ * - if the input looks like a ClientHello without cookies,
+ * send back HelloVerifyRequest, then
+ * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
+ * - if the input looks like a ClientHello with a valid cookie,
+ * reset the session of the current context, and
+ * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
+ * - if anything goes wrong, return a specific error code
+ *
+ * mbedtls_ssl_read_record() will ignore the record if anything else than
+ * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function
+ * cannot not return 0.
+ */
+static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len;
+
+ if( ssl->conf->f_cookie_write == NULL ||
+ ssl->conf->f_cookie_check == NULL )
+ {
+ /* If we can't use cookies to verify reachability of the peer,
+ * drop the record. */
+ return( 0 );
+ }
+
+ ret = ssl_check_dtls_clihlo_cookie(
+ ssl->conf->f_cookie_write,
+ ssl->conf->f_cookie_check,
+ ssl->conf->p_cookie,
+ ssl->cli_id, ssl->cli_id_len,
+ ssl->in_buf, ssl->in_left,
+ ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
+
+ MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
+
+ if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
+ {
+ /* Don't check write errors as we can't do anything here.
+ * If the error is permanent we'll catch it later,
+ * if it's not, then hopefully it'll work next time. */
+ (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len );
+ ret = 0;
+ }
+
+ if( ret == 0 )
+ {
+ /* Got a valid cookie, partially reset context */
+ if( ( ret = mbedtls_ssl_session_reset_int( ssl, 1 ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret );
+ return( ret );
+ }
+
+ return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT );
+ }
+
+ return( ret );
+}
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+
+static int ssl_check_record_type( uint8_t record_type )
+{
+ if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
+ record_type != MBEDTLS_SSL_MSG_ALERT &&
+ record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
+ record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
+ {
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ return( 0 );
+}
+
+/*
+ * ContentType type;
+ * ProtocolVersion version;
+ * uint16 epoch; // DTLS only
+ * uint48 sequence_number; // DTLS only
+ * uint16 length;
+ *
+ * Return 0 if header looks sane (and, for DTLS, the record is expected)
+ * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad,
+ * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected.
+ *
+ * With DTLS, mbedtls_ssl_read_record() will:
+ * 1. proceed with the record if this function returns 0
+ * 2. drop only the current record if this function returns UNEXPECTED_RECORD
+ * 3. return CLIENT_RECONNECT if this function return that value
+ * 4. drop the whole datagram if this function returns anything else.
+ * Point 2 is needed when the peer is resending, and we have already received
+ * the first record from a datagram but are still waiting for the others.
+ */
+static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
+ unsigned char *buf,
+ size_t len,
+ mbedtls_record *rec )
+{
+ int major_ver, minor_ver;
+
+ size_t const rec_hdr_type_offset = 0;
+ size_t const rec_hdr_type_len = 1;
+
+ size_t const rec_hdr_version_offset = rec_hdr_type_offset +
+ rec_hdr_type_len;
+ size_t const rec_hdr_version_len = 2;
+
+ size_t const rec_hdr_ctr_len = 8;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ uint32_t rec_epoch;
+ size_t const rec_hdr_ctr_offset = rec_hdr_version_offset +
+ rec_hdr_version_len;
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset +
+ rec_hdr_ctr_len;
+ size_t rec_hdr_cid_len = 0;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ size_t rec_hdr_len_offset; /* To be determined */
+ size_t const rec_hdr_len_len = 2;
+
+ /*
+ * Check minimum lengths for record header.
+ */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len;
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len;
+ }
+
+ if( len < rec_hdr_len_offset + rec_hdr_len_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u",
+ (unsigned) len,
+ (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /*
+ * Parse and validate record content type
+ */
+
+ rec->type = buf[ rec_hdr_type_offset ];
+
+ /* Check record content type */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ rec->cid_len = 0;
+
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl->conf->cid_len != 0 &&
+ rec->type == MBEDTLS_SSL_MSG_CID )
+ {
+ /* Shift pointers to account for record header including CID
+ * struct {
+ * ContentType special_type = tls12_cid;
+ * ProtocolVersion version;
+ * uint16 epoch;
+ * uint48 sequence_number;
+ * opaque cid[cid_length]; // Additional field compared to
+ * // default DTLS record format
+ * uint16 length;
+ * opaque enc_content[DTLSCiphertext.length];
+ * } DTLSCiphertext;
+ */
+
+ /* So far, we only support static CID lengths
+ * fixed in the configuration. */
+ rec_hdr_cid_len = ssl->conf->cid_len;
+ rec_hdr_len_offset += rec_hdr_cid_len;
+
+ if( len < rec_hdr_len_offset + rec_hdr_len_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u",
+ (unsigned) len,
+ (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /* configured CID len is guaranteed at most 255, see
+ * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */
+ rec->cid_len = (uint8_t) rec_hdr_cid_len;
+ memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len );
+ }
+ else
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ {
+ if( ssl_check_record_type( rec->type ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u",
+ (unsigned) rec->type ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+ }
+
+ /*
+ * Parse and validate record version
+ */
+
+ rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
+ rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
+ mbedtls_ssl_read_version( &major_ver, &minor_ver,
+ ssl->conf->transport,
+ &rec->ver[0] );
+
+ if( major_ver != ssl->major_ver )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( minor_ver > ssl->conf->max_minor_ver )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /*
+ * Parse/Copy record sequence number.
+ */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ /* Copy explicit record sequence number from input buffer. */
+ memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset,
+ rec_hdr_ctr_len );
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ /* Copy implicit record sequence number from SSL context structure. */
+ memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len );
+ }
+
+ /*
+ * Parse record length.
+ */
+
+ rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len;
+ rec->data_len = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) |
+ ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset );
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
+ "version = [%d:%d], msglen = %d",
+ rec->type,
+ major_ver, minor_ver, rec->data_len ) );
+
+ rec->buf = buf;
+ rec->buf_len = rec->data_offset + rec->data_len;
+
+ if( rec->data_len == 0 )
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+
+ /*
+ * DTLS-related tests.
+ * Check epoch before checking length constraint because
+ * the latter varies with the epoch. E.g., if a ChangeCipherSpec
+ * message gets duplicated before the corresponding Finished message,
+ * the second ChangeCipherSpec should be discarded because it belongs
+ * to an old epoch, but not because its length is shorter than
+ * the minimum record length for packets using the new record transform.
+ * Note that these two kinds of failures are handled differently,
+ * as an unexpected record is silently skipped but an invalid
+ * record leads to the entire datagram being dropped.
+ */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1];
+
+ /* Check that the datagram is large enough to contain a record
+ * of the advertised length. */
+ if( len < rec->data_offset + rec->data_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.",
+ (unsigned) len,
+ (unsigned)( rec->data_offset + rec->data_len ) ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /* Records from other, non-matching epochs are silently discarded.
+ * (The case of same-port Client reconnects must be considered in
+ * the caller). */
+ if( rec_epoch != ssl->in_epoch )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
+ "expected %d, received %d",
+ ssl->in_epoch, rec_epoch ) );
+
+ /* Records from the next epoch are considered for buffering
+ * (concretely: early Finished messages). */
+ if( rec_epoch == (unsigned) ssl->in_epoch + 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+ }
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+ /* For records from the correct epoch, check whether their
+ * sequence number has been seen before. */
+ else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl,
+ &rec->ctr[0] ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+ }
+#endif
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ return( 0 );
+}
+
+
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
+{
+ unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
+
+ /*
+ * Check for an epoch 0 ClientHello. We can't use in_msg here to
+ * access the first byte of record content (handshake type), as we
+ * have an active transform (possibly iv_len != 0), so use the
+ * fact that the record header len is 13 instead.
+ */
+ if( rec_epoch == 0 &&
+ ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
+ ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ ssl->in_left > 13 &&
+ ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
+ "from the same port" ) );
+ return( ssl_handle_possible_reconnect( ssl ) );
+ }
+
+ return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+
+/*
+ * If applicable, decrypt record content
+ */
+static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
+ mbedtls_record *rec )
+{
+ int ret, done = 0;
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network",
+ rec->buf, rec->buf_len );
+
+#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
+ if( mbedtls_ssl_hw_record_read != NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) );
+
+ ret = mbedtls_ssl_hw_record_read( ssl );
+ if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+
+ if( ret == 0 )
+ done = 1;
+ }
+#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
+ if( !done && ssl->transform_in != NULL )
+ {
+ unsigned char const old_msg_type = rec->type;
+
+ if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in,
+ rec ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
+ ssl->conf->ignore_unexpected_cid
+ == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) );
+ ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+ }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ return( ret );
+ }
+
+ if( old_msg_type != rec->type )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d",
+ old_msg_type, rec->type ) );
+ }
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
+ rec->buf + rec->data_offset, rec->data_len );
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ /* We have already checked the record content type
+ * in ssl_parse_record_header(), failing or silently
+ * dropping the record in the case of an unknown type.
+ *
+ * Since with the use of CIDs, the record content type
+ * might change during decryption, re-check the record
+ * content type, but treat a failure as fatal this time. */
+ if( ssl_check_record_type( rec->type ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ if( rec->data_len == 0 )
+ {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
+ && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
+ {
+ /* TLS v1.2 explicitly disallows zero-length messages which are not application data */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+ ssl->nb_zero++;
+
+ /*
+ * Three or more empty messages may be a DoS attack
+ * (excessive CPU consumption).
+ */
+ if( ssl->nb_zero > 3 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
+ "messages, possible DoS attack" ) );
+ /* Treat the records as if they were not properly authenticated,
+ * thereby failing the connection if we see more than allowed
+ * by the configured bad MAC threshold. */
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
+ }
+ }
+ else
+ ssl->nb_zero = 0;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ; /* in_ctr read from peer, not maintained internally */
+ }
+ else
+#endif
+ {
+ unsigned i;
+ for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
+ if( ++ssl->in_ctr[i - 1] != 0 )
+ break;
+
+ /* The loop goes to its end iff the counter is wrapping */
+ if( i == mbedtls_ssl_ep_len( ssl ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) );
+ return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+ }
+ }
+
+ }
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ mbedtls_ssl_dtls_replay_update( ssl );
+ }
+#endif
+
+ /* Check actual (decrypted) record content length against
+ * configured maximum. */
+ if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ return( 0 );
+}
+
+/*
+ * Read a record.
+ *
+ * Silently ignore non-fatal alert (and for DTLS, invalid records as well,
+ * RFC 6347 4.1.2.7) and continue reading until a valid record is found.
+ *
+ */
+
+/* Helper functions for mbedtls_ssl_read_record(). */
+static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
+static int ssl_get_next_record( mbedtls_ssl_context *ssl );
+static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
+
+int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
+ unsigned update_hs_digest )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) );
+
+ if( ssl->keep_current_message == 0 )
+ {
+ do {
+
+ ret = ssl_consume_current_message( ssl );
+ if( ret != 0 )
+ return( ret );
+
+ if( ssl_record_is_in_progress( ssl ) == 0 )
+ {
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ int have_buffered = 0;
+
+ /* We only check for buffered messages if the
+ * current datagram is fully consumed. */
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl_next_record_is_in_datagram( ssl ) == 0 )
+ {
+ if( ssl_load_buffered_message( ssl ) == 0 )
+ have_buffered = 1;
+ }
+
+ if( have_buffered == 0 )
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ ret = ssl_get_next_record( ssl );
+ if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
+ continue;
+
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
+ return( ret );
+ }
+ }
+ }
+
+ ret = mbedtls_ssl_handle_message_type( ssl );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+ {
+ /* Buffer future message */
+ ret = ssl_buffer_message( ssl );
+ if( ret != 0 )
+ return( ret );
+
+ ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
+ MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
+
+ if( 0 != ret )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ update_hs_digest == 1 )
+ {
+ mbedtls_ssl_update_handshake_status( ssl );
+ }
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
+ ssl->keep_current_message = 0;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) );
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
+{
+ if( ssl->in_left > ssl->next_record_offset )
+ return( 1 );
+
+ return( 0 );
+}
+
+static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ mbedtls_ssl_hs_buffer * hs_buf;
+ int ret = 0;
+
+ if( hs == NULL )
+ return( -1 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
+
+ if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
+ ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
+ {
+ /* Check if we have seen a ChangeCipherSpec before.
+ * If yes, synthesize a CCS record. */
+ if( !hs->buffering.seen_ccs )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) );
+ ret = -1;
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
+ ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
+ ssl->in_msglen = 1;
+ ssl->in_msg[0] = 1;
+
+ /* As long as they are equal, the exact value doesn't matter. */
+ ssl->in_left = 0;
+ ssl->next_record_offset = 0;
+
+ hs->buffering.seen_ccs = 0;
+ goto exit;
+ }
+
+#if defined(MBEDTLS_DEBUG_C)
+ /* Debug only */
+ {
+ unsigned offset;
+ for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+ {
+ hs_buf = &hs->buffering.hs[offset];
+ if( hs_buf->is_valid == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
+ hs->in_msg_seq + offset,
+ hs_buf->is_complete ? "fully" : "partially" ) );
+ }
+ }
+ }
+#endif /* MBEDTLS_DEBUG_C */
+
+ /* Check if we have buffered and/or fully reassembled the
+ * next handshake message. */
+ hs_buf = &hs->buffering.hs[0];
+ if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) )
+ {
+ /* Synthesize a record containing the buffered HS message. */
+ size_t msg_len = ( hs_buf->data[1] << 16 ) |
+ ( hs_buf->data[2] << 8 ) |
+ hs_buf->data[3];
+
+ /* Double-check that we haven't accidentally buffered
+ * a message that doesn't fit into the input buffer. */
+ if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)",
+ hs_buf->data, msg_len + 12 );
+
+ ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+ ssl->in_hslen = msg_len + 12;
+ ssl->in_msglen = msg_len + 12;
+ memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen );
+
+ ret = 0;
+ goto exit;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered",
+ hs->in_msg_seq ) );
+ }
+
+ ret = -1;
+
+exit:
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) );
+ return( ret );
+}
+
+static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
+ size_t desired )
+{
+ int offset;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available",
+ (unsigned) desired ) );
+
+ /* Get rid of future records epoch first, if such exist. */
+ ssl_free_buffered_record( ssl );
+
+ /* Check if we have enough space available now. */
+ if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) );
+ return( 0 );
+ }
+
+ /* We don't have enough space to buffer the next expected handshake
+ * message. Remove buffers used for future messages to gain space,
+ * starting with the most distant one. */
+ for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
+ offset >= 0; offset-- )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message",
+ offset ) );
+
+ ssl_buffering_free_slot( ssl, (uint8_t) offset );
+
+ /* Check if we have enough space available now. */
+ if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) );
+ return( 0 );
+ }
+ }
+
+ return( -1 );
+}
+
+static int ssl_buffer_message( mbedtls_ssl_context *ssl )
+{
+ int ret = 0;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+ if( hs == NULL )
+ return( 0 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) );
+
+ switch( ssl->in_msgtype )
+ {
+ case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) );
+
+ hs->buffering.seen_ccs = 1;
+ break;
+
+ case MBEDTLS_SSL_MSG_HANDSHAKE:
+ {
+ unsigned recv_msg_seq_offset;
+ unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
+ mbedtls_ssl_hs_buffer *hs_buf;
+ size_t msg_len = ssl->in_hslen - 12;
+
+ /* We should never receive an old handshake
+ * message - double-check nonetheless. */
+ if( recv_msg_seq < ssl->handshake->in_msg_seq )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;
+ if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+ {
+ /* Silently ignore -- message too far in the future */
+ MBEDTLS_SSL_DEBUG_MSG( 2,
+ ( "Ignore future HS message with sequence number %u, "
+ "buffering window %u - %u",
+ recv_msg_seq, ssl->handshake->in_msg_seq,
+ ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) );
+
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ",
+ recv_msg_seq, recv_msg_seq_offset ) );
+
+ hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ];
+
+ /* Check if the buffering for this seq nr has already commenced. */
+ if( !hs_buf->is_valid )
+ {
+ size_t reassembly_buf_sz;
+
+ hs_buf->is_fragmented =
+ ( ssl_hs_is_proper_fragment( ssl ) == 1 );
+
+ /* We copy the message back into the input buffer
+ * after reassembly, so check that it's not too large.
+ * This is an implementation-specific limitation
+ * and not one from the standard, hence it is not
+ * checked in ssl_check_hs_header(). */
+ if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ /* Ignore message */
+ goto exit;
+ }
+
+ /* Check if we have enough space to buffer the message. */
+ if( hs->buffering.total_bytes_buffered >
+ MBEDTLS_SSL_DTLS_MAX_BUFFERING )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len,
+ hs_buf->is_fragmented );
+
+ if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ if( recv_msg_seq_offset > 0 )
+ {
+ /* If we can't buffer a future message because
+ * of space limitations -- ignore. */
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
+ (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ goto exit;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n",
+ (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ }
+
+ if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n",
+ (unsigned) msg_len,
+ (unsigned) reassembly_buf_sz,
+ MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+ goto exit;
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
+ msg_len ) );
+
+ hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
+ if( hs_buf->data == NULL )
+ {
+ ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ goto exit;
+ }
+ hs_buf->data_len = reassembly_buf_sz;
+
+ /* Prepare final header: copy msg_type, length and message_seq,
+ * then add standardised fragment_offset and fragment_length */
+ memcpy( hs_buf->data, ssl->in_msg, 6 );
+ memset( hs_buf->data + 6, 0, 3 );
+ memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 );
+
+ hs_buf->is_valid = 1;
+
+ hs->buffering.total_bytes_buffered += reassembly_buf_sz;
+ }
+ else
+ {
+ /* Make sure msg_type and length are consistent */
+ if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) );
+ /* Ignore */
+ goto exit;
+ }
+ }
+
+ if( !hs_buf->is_complete )
+ {
+ size_t frag_len, frag_off;
+ unsigned char * const msg = hs_buf->data + 12;
+
+ /*
+ * Check and copy current fragment
+ */
+
+ /* Validation of header fields already done in
+ * mbedtls_ssl_prepare_handshake_record(). */
+ frag_off = ssl_get_hs_frag_off( ssl );
+ frag_len = ssl_get_hs_frag_len( ssl );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
+ frag_off, frag_len ) );
+ memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
+
+ if( hs_buf->is_fragmented )
+ {
+ unsigned char * const bitmask = msg + msg_len;
+ ssl_bitmask_set( bitmask, frag_off, frag_len );
+ hs_buf->is_complete = ( ssl_bitmask_check( bitmask,
+ msg_len ) == 0 );
+ }
+ else
+ {
+ hs_buf->is_complete = 1;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete",
+ hs_buf->is_complete ? "" : "not yet " ) );
+ }
+
+ break;
+ }
+
+ default:
+ /* We don't buffer other types of messages. */
+ break;
+ }
+
+exit:
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) );
+ return( ret );
+}
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
+{
+ /*
+ * Consume last content-layer message and potentially
+ * update in_msglen which keeps track of the contents'
+ * consumption state.
+ *
+ * (1) Handshake messages:
+ * Remove last handshake message, move content
+ * and adapt in_msglen.
+ *
+ * (2) Alert messages:
+ * Consume whole record content, in_msglen = 0.
+ *
+ * (3) Change cipher spec:
+ * Consume whole record content, in_msglen = 0.
+ *
+ * (4) Application data:
+ * Don't do anything - the record layer provides
+ * the application data as a stream transport
+ * and consumes through mbedtls_ssl_read only.
+ *
+ */
+
+ /* Case (1): Handshake messages */
+ if( ssl->in_hslen != 0 )
+ {
+ /* Hard assertion to be sure that no application data
+ * is in flight, as corrupting ssl->in_msglen during
+ * ssl->in_offt != NULL is fatal. */
+ if( ssl->in_offt != NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ /*
+ * Get next Handshake message in the current record
+ */
+
+ /* Notes:
+ * (1) in_hslen is not necessarily the size of the
+ * current handshake content: If DTLS handshake
+ * fragmentation is used, that's the fragment
+ * size instead. Using the total handshake message
+ * size here is faulty and should be changed at
+ * some point.
+ * (2) While it doesn't seem to cause problems, one
+ * has to be very careful not to assume that in_hslen
+ * is always <= in_msglen in a sensible communication.
+ * Again, it's wrong for DTLS handshake fragmentation.
+ * The following check is therefore mandatory, and
+ * should not be treated as a silently corrected assertion.
+ * Additionally, ssl->in_hslen might be arbitrarily out of
+ * bounds after handling a DTLS message with an unexpected
+ * sequence number, see mbedtls_ssl_prepare_handshake_record.
+ */
+ if( ssl->in_hslen < ssl->in_msglen )
+ {
+ ssl->in_msglen -= ssl->in_hslen;
+ memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
+ ssl->in_msglen );
+
+ MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record",
+ ssl->in_msg, ssl->in_msglen );
+ }
+ else
+ {
+ ssl->in_msglen = 0;
+ }
+
+ ssl->in_hslen = 0;
+ }
+ /* Case (4): Application data */
+ else if( ssl->in_offt != NULL )
+ {
+ return( 0 );
+ }
+ /* Everything else (CCS & Alerts) */
+ else
+ {
+ ssl->in_msglen = 0;
+ }
+
+ return( 0 );
+}
+
+static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
+{
+ if( ssl->in_msglen > 0 )
+ return( 1 );
+
+ return( 0 );
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ if( hs == NULL )
+ return;
+
+ if( hs->buffering.future_record.data != NULL )
+ {
+ hs->buffering.total_bytes_buffered -=
+ hs->buffering.future_record.len;
+
+ mbedtls_free( hs->buffering.future_record.data );
+ hs->buffering.future_record.data = NULL;
+ }
+}
+
+static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ unsigned char * rec;
+ size_t rec_len;
+ unsigned rec_epoch;
+
+ if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ return( 0 );
+
+ if( hs == NULL )
+ return( 0 );
+
+ rec = hs->buffering.future_record.data;
+ rec_len = hs->buffering.future_record.len;
+ rec_epoch = hs->buffering.future_record.epoch;
+
+ if( rec == NULL )
+ return( 0 );
+
+ /* Only consider loading future records if the
+ * input buffer is empty. */
+ if( ssl_next_record_is_in_datagram( ssl ) == 1 )
+ return( 0 );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
+
+ if( rec_epoch != ssl->in_epoch )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) );
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) );
+
+ /* Double-check that the record is not too large */
+ if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN -
+ (size_t)( ssl->in_hdr - ssl->in_buf ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+ memcpy( ssl->in_hdr, rec, rec_len );
+ ssl->in_left = rec_len;
+ ssl->next_record_offset = 0;
+
+ ssl_free_buffered_record( ssl );
+
+exit:
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) );
+ return( 0 );
+}
+
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
+ mbedtls_record const *rec )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+ /* Don't buffer future records outside handshakes. */
+ if( hs == NULL )
+ return( 0 );
+
+ /* Only buffer handshake records (we are only interested
+ * in Finished messages). */
+ if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE )
+ return( 0 );
+
+ /* Don't buffer more than one future epoch record. */
+ if( hs->buffering.future_record.data != NULL )
+ return( 0 );
+
+ /* Don't buffer record if there's not enough buffering space remaining. */
+ if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ hs->buffering.total_bytes_buffered ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
+ (unsigned) rec->buf_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) hs->buffering.total_bytes_buffered ) );
+ return( 0 );
+ }
+
+ /* Buffer record */
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
+ ssl->in_epoch + 1 ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len );
+
+ /* ssl_parse_record_header() only considers records
+ * of the next epoch as candidates for buffering. */
+ hs->buffering.future_record.epoch = ssl->in_epoch + 1;
+ hs->buffering.future_record.len = rec->buf_len;
+
+ hs->buffering.future_record.data =
+ mbedtls_calloc( 1, hs->buffering.future_record.len );
+ if( hs->buffering.future_record.data == NULL )
+ {
+ /* If we run out of RAM trying to buffer a
+ * record from the next epoch, just ignore. */
+ return( 0 );
+ }
+
+ memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len );
+
+ hs->buffering.total_bytes_buffered += rec->buf_len;
+ return( 0 );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+static int ssl_get_next_record( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_record rec;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ /* We might have buffered a future record; if so,
+ * and if the epoch matches now, load it.
+ * On success, this call will set ssl->in_left to
+ * the length of the buffered record, so that
+ * the calls to ssl_fetch_input() below will
+ * essentially be no-ops. */
+ ret = ssl_load_buffered_record( ssl );
+ if( ret != 0 )
+ return( ret );
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ /* Ensure that we have enough space available for the default form
+ * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS,
+ * with no space for CIDs counted in). */
+ ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec );
+ if( ret != 0 )
+ {
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+ {
+ ret = ssl_buffer_future_record( ssl, &rec );
+ if( ret != 0 )
+ return( ret );
+
+ /* Fall through to handling of unexpected records */
+ ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
+ }
+
+ if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
+ {
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+ /* Reset in pointers to default state for TLS/DTLS records,
+ * assuming no CID and no offset between record content and
+ * record plaintext. */
+ mbedtls_ssl_update_in_pointers( ssl );
+
+ /* Setup internal message pointers from record structure. */
+ ssl->in_msgtype = rec.type;
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl->in_len = ssl->in_cid + rec.cid_len;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->in_iv = ssl->in_msg = ssl->in_len + 2;
+ ssl->in_msglen = rec.data_len;
+
+ ret = ssl_check_client_reconnect( ssl );
+ if( ret != 0 )
+ return( ret );
+#endif
+
+ /* Skip unexpected record (but not whole datagram) */
+ ssl->next_record_offset = rec.buf_len;
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record "
+ "(header)" ) );
+ }
+ else
+ {
+ /* Skip invalid record and the rest of the datagram */
+ ssl->next_record_offset = 0;
+ ssl->in_left = 0;
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record "
+ "(header)" ) );
+ }
+
+ /* Get next record */
+ return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
+ }
+ else
+#endif
+ {
+ return( ret );
+ }
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ /* Remember offset of next record within datagram. */
+ ssl->next_record_offset = rec.buf_len;
+ if( ssl->next_record_offset < ssl->in_left )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
+ }
+ }
+ else
+#endif
+ {
+ /*
+ * Fetch record contents from underlying transport.
+ */
+ ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
+ return( ret );
+ }
+
+ ssl->in_left = 0;
+ }
+
+ /*
+ * Decrypt record contents.
+ */
+
+ if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 )
+ {
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ /* Silently discard invalid records */
+ if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
+ {
+ /* Except when waiting for Finished as a bad mac here
+ * probably means something went wrong in the handshake
+ * (eg wrong psk used, mitm downgrade attempt, etc.) */
+ if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED ||
+ ssl->state == MBEDTLS_SSL_SERVER_FINISHED )
+ {
+#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
+ if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
+ {
+ mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
+ }
+#endif
+ return( ret );
+ }
+
+#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
+ if( ssl->conf->badmac_limit != 0 &&
+ ++ssl->badmac_seen >= ssl->conf->badmac_limit )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_MAC );
+ }
+#endif
+
+ /* As above, invalid records cause
+ * dismissal of the whole datagram. */
+
+ ssl->next_record_offset = 0;
+ ssl->in_left = 0;
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
+ return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
+ }
+
+ return( ret );
+ }
+ else
+#endif
+ {
+ /* Error out (and send alert) on invalid records */
+#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
+ if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
+ {
+ mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
+ }
+#endif
+ return( ret );
+ }
+ }
+
+
+ /* Reset in pointers to default state for TLS/DTLS records,
+ * assuming no CID and no offset between record content and
+ * record plaintext. */
+ mbedtls_ssl_update_in_pointers( ssl );
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl->in_len = ssl->in_cid + rec.cid_len;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->in_iv = ssl->in_len + 2;
+
+ /* The record content type may change during decryption,
+ * so re-read it. */
+ ssl->in_msgtype = rec.type;
+ /* Also update the input buffer, because unfortunately
+ * the server-side ssl_parse_client_hello() reparses the
+ * record header when receiving a ClientHello initiating
+ * a renegotiation. */
+ ssl->in_hdr[0] = rec.type;
+ ssl->in_msg = rec.buf + rec.data_offset;
+ ssl->in_msglen = rec.data_len;
+ ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 );
+ ssl->in_len[1] = (unsigned char)( rec.data_len );
+
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ if( ssl->transform_in != NULL &&
+ ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
+ {
+ if( ( ret = ssl_decompress_buf( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret );
+ return( ret );
+ }
+
+ /* Check actual (decompress) record content length against
+ * configured maximum. */
+ if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+ }
+#endif /* MBEDTLS_ZLIB_SUPPORT */
+
+ return( 0 );
+}
+
+int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ /*
+ * Handle particular types of records
+ */
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
+ {
+ if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 )
+ {
+ return( ret );
+ }
+ }
+
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ if( ssl->in_msglen != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d",
+ ssl->in_msglen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( ssl->in_msg[0] != 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x",
+ ssl->in_msg[0] ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
+ ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
+ {
+ if( ssl->handshake == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
+ }
+#endif
+ }
+
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
+ {
+ if( ssl->in_msglen != 2 )
+ {
+ /* Note: Standard allows for more than one 2 byte alert
+ to be packed in a single message, but Mbed TLS doesn't
+ currently support this. */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d",
+ ssl->in_msglen ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
+ ssl->in_msg[0], ssl->in_msg[1] ) );
+
+ /*
+ * Ignore non-fatal alerts, except close_notify and no_renegotiation
+ */
+ if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)",
+ ssl->in_msg[1] ) );
+ return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE );
+ }
+
+ if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
+ return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY );
+ }
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED)
+ if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) );
+ /* Will be handled when trying to parse ServerHello */
+ return( 0 );
+ }
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C)
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
+ ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
+ ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) );
+ /* Will be handled in mbedtls_ssl_parse_certificate() */
+ return( 0 );
+ }
+#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
+
+ /* Silently ignore: fetch new message */
+ return MBEDTLS_ERR_SSL_NON_FATAL;
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ /* Drop unexpected ApplicationData records,
+ * except at the beginning of renegotiations */
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
+ ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
+ ssl->state == MBEDTLS_SSL_SERVER_HELLO )
+#endif
+ )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
+ return( MBEDTLS_ERR_SSL_NON_FATAL );
+ }
+
+ if( ssl->handshake != NULL &&
+ ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ {
+ mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl );
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ return( 0 );
+}
+
+int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl )
+{
+ return( mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) );
+}
+
+int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
+ unsigned char level,
+ unsigned char message )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ if( ssl == NULL || ssl->conf == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
+
+ ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;
+ ssl->out_msglen = 2;
+ ssl->out_msg[0] = level;
+ ssl->out_msg[1] = message;
+
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ return( ret );
+ }
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
+
+ return( 0 );
+}
+
+int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
+
+ ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
+ ssl->out_msglen = 1;
+ ssl->out_msg[0] = 1;
+
+ ssl->state++;
+
+ if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
+ return( ret );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
+
+ return( 0 );
+}
+
+int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
+
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ /* CCS records are only accepted if they have length 1 and content '1',
+ * so we don't need to check this here. */
+
+ /*
+ * Switch to our negotiated transform and session parameters for inbound
+ * data.
+ */
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
+ ssl->transform_in = ssl->transform_negotiate;
+ ssl->session_in = ssl->session_negotiate;
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+ mbedtls_ssl_dtls_replay_reset( ssl );
+#endif
+
+ /* Increment epoch */
+ if( ++ssl->in_epoch == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) );
+ /* This is highly unlikely to happen for legitimate reasons, so
+ treat it as an attack and don't send an alert. */
+ return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
+ }
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ memset( ssl->in_ctr, 0, 8 );
+
+ mbedtls_ssl_update_in_pointers( ssl );
+
+#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
+ if( mbedtls_ssl_hw_record_activate != NULL )
+ {
+ if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
+ }
+#endif
+
+ ssl->state++;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
+
+ return( 0 );
+}
+
+/* Once ssl->out_hdr as the address of the beginning of the
+ * next outgoing record is set, deduce the other pointers.
+ *
+ * Note: For TLS, we save the implicit record sequence number
+ * (entering MAC computation) in the 8 bytes before ssl->out_hdr,
+ * and the caller has to make sure there's space for this.
+ */
+
+void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl,
+ mbedtls_ssl_transform *transform )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->out_ctr = ssl->out_hdr + 3;
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl->out_cid = ssl->out_ctr + 8;
+ ssl->out_len = ssl->out_cid;
+ if( transform != NULL )
+ ssl->out_len += transform->out_cid_len;
+#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->out_len = ssl->out_ctr + 8;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->out_iv = ssl->out_len + 2;
+ }
+ else
+#endif
+ {
+ ssl->out_ctr = ssl->out_hdr - 8;
+ ssl->out_len = ssl->out_hdr + 3;
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl->out_cid = ssl->out_len;
+#endif
+ ssl->out_iv = ssl->out_hdr + 5;
+ }
+
+ /* Adjust out_msg to make space for explicit IV, if used. */
+ if( transform != NULL &&
+ ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ {
+ ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen;
+ }
+ else
+ ssl->out_msg = ssl->out_iv;
+}
+
+/* Once ssl->in_hdr as the address of the beginning of the
+ * next incoming record is set, deduce the other pointers.
+ *
+ * Note: For TLS, we save the implicit record sequence number
+ * (entering MAC computation) in the 8 bytes before ssl->in_hdr,
+ * and the caller has to make sure there's space for this.
+ */
+
+void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl )
+{
+ /* This function sets the pointers to match the case
+ * of unprotected TLS/DTLS records, with both ssl->in_iv
+ * and ssl->in_msg pointing to the beginning of the record
+ * content.
+ *
+ * When decrypting a protected record, ssl->in_msg
+ * will be shifted to point to the beginning of the
+ * record plaintext.
+ */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ /* This sets the header pointers to match records
+ * without CID. When we receive a record containing
+ * a CID, the fields are shifted accordingly in
+ * ssl_parse_record_header(). */
+ ssl->in_ctr = ssl->in_hdr + 3;
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl->in_cid = ssl->in_ctr + 8;
+ ssl->in_len = ssl->in_cid; /* Default: no CID */
+#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->in_len = ssl->in_ctr + 8;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->in_iv = ssl->in_len + 2;
+ }
+ else
+#endif
+ {
+ ssl->in_ctr = ssl->in_hdr - 8;
+ ssl->in_len = ssl->in_hdr + 3;
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl->in_cid = ssl->in_len;
+#endif
+ ssl->in_iv = ssl->in_hdr + 5;
+ }
+
+ /* This will be adjusted at record decryption time. */
+ ssl->in_msg = ssl->in_iv;
+}
+
+/*
+ * Setup an SSL context
+ */
+
+void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl )
+{
+ /* Set the incoming and outgoing record pointers. */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ ssl->out_hdr = ssl->out_buf;
+ ssl->in_hdr = ssl->in_buf;
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ {
+ ssl->out_hdr = ssl->out_buf + 8;
+ ssl->in_hdr = ssl->in_buf + 8;
+ }
+
+ /* Derive other internal pointers. */
+ mbedtls_ssl_update_out_pointers( ssl, NULL /* no transform enabled */ );
+ mbedtls_ssl_update_in_pointers ( ssl );
+}
+
+/*
+ * SSL get accessors
+ */
+size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl )
+{
+ return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
+}
+
+int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
+{
+ /*
+ * Case A: We're currently holding back
+ * a message for further processing.
+ */
+
+ if( ssl->keep_current_message == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) );
+ return( 1 );
+ }
+
+ /*
+ * Case B: Further records are pending in the current datagram.
+ */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl->in_left > ssl->next_record_offset )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) );
+ return( 1 );
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ /*
+ * Case C: A handshake message is being processed.
+ */
+
+ if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) );
+ return( 1 );
+ }
+
+ /*
+ * Case D: An application data message is being processed
+ */
+ if( ssl->in_offt != NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) );
+ return( 1 );
+ }
+
+ /*
+ * In all other cases, the rest of the message can be dropped.
+ * As in ssl_get_next_record, this needs to be adapted if
+ * we implement support for multiple alerts in single records.
+ */
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) );
+ return( 0 );
+}
+
+
+int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
+{
+ size_t transform_expansion = 0;
+ const mbedtls_ssl_transform *transform = ssl->transform_out;
+ unsigned block_size;
+
+ size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl );
+
+ if( transform == NULL )
+ return( (int) out_hdr_len );
+
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
+ return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+#endif
+
+ switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
+ {
+ case MBEDTLS_MODE_GCM:
+ case MBEDTLS_MODE_CCM:
+ case MBEDTLS_MODE_CHACHAPOLY:
+ case MBEDTLS_MODE_STREAM:
+ transform_expansion = transform->minlen;
+ break;
+
+ case MBEDTLS_MODE_CBC:
+
+ block_size = mbedtls_cipher_get_block_size(
+ &transform->cipher_ctx_enc );
+
+ /* Expansion due to the addition of the MAC. */
+ transform_expansion += transform->maclen;
+
+ /* Expansion due to the addition of CBC padding;
+ * Theoretically up to 256 bytes, but we never use
+ * more than the block size of the underlying cipher. */
+ transform_expansion += block_size;
+
+ /* For TLS 1.1 or higher, an explicit IV is added
+ * after the record header. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
+ transform_expansion += block_size;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+
+ break;
+
+ default:
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ if( transform->out_cid_len != 0 )
+ transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ return( (int)( out_hdr_len + transform_expansion ) );
+}
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+/*
+ * Check record counters and renegotiate if they're above the limit.
+ */
+static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
+{
+ size_t ep_len = mbedtls_ssl_ep_len( ssl );
+ int in_ctr_cmp;
+ int out_ctr_cmp;
+
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ||
+ ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||
+ ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED )
+ {
+ return( 0 );
+ }
+
+ in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
+ ssl->conf->renego_period + ep_len, 8 - ep_len );
+ out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
+ ssl->conf->renego_period + ep_len, 8 - ep_len );
+
+ if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
+ {
+ return( 0 );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) );
+ return( mbedtls_ssl_renegotiate( ssl ) );
+}
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+/*
+ * Receive application data decrypted from the SSL layer
+ */
+int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t n;
+
+ if( ssl == NULL || ssl->conf == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ return( ret );
+
+ if( ssl->handshake != NULL &&
+ ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
+ {
+ if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
+ return( ret );
+ }
+ }
+#endif
+
+ /*
+ * Check if renegotiation is necessary and/or handshake is
+ * in process. If yes, perform/continue, and fall through
+ * if an unexpected packet is received while the client
+ * is waiting for the ServerHello.
+ *
+ * (There is no equivalent to the last condition on
+ * the server-side as it is not treated as within
+ * a handshake while waiting for the ClientHello
+ * after a renegotiation request.)
+ */
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ ret = ssl_check_ctr_renegotiate( ssl );
+ if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
+ ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
+ return( ret );
+ }
+#endif
+
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ {
+ ret = mbedtls_ssl_handshake( ssl );
+ if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
+ ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
+ return( ret );
+ }
+ }
+
+ /* Loop as long as no application data record is available */
+ while( ssl->in_offt == NULL )
+ {
+ /* Start timer if not already running */
+ if( ssl->f_get_timer != NULL &&
+ ssl->f_get_timer( ssl->p_timer ) == -1 )
+ {
+ mbedtls_ssl_set_timer( ssl, ssl->conf->read_timeout );
+ }
+
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
+ {
+ if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
+ return( 0 );
+
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
+ return( ret );
+ }
+
+ if( ssl->in_msglen == 0 &&
+ ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA )
+ {
+ /*
+ * OpenSSL sends empty messages to randomize the IV
+ */
+ if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
+ {
+ if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
+ return( 0 );
+
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
+ return( ret );
+ }
+ }
+
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
+
+ /*
+ * - For client-side, expect SERVER_HELLO_REQUEST.
+ * - For server-side, expect CLIENT_HELLO.
+ * - Fail (TLS) or silently drop record (DTLS) in other cases.
+ */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+ ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
+ ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
+
+ /* With DTLS, drop the packet (probably from last handshake) */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ continue;
+ }
+#endif
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+#endif /* MBEDTLS_SSL_CLI_C */
+
+#if defined(MBEDTLS_SSL_SRV_C)
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
+
+ /* With DTLS, drop the packet (probably from last handshake) */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ continue;
+ }
+#endif
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+#endif /* MBEDTLS_SSL_SRV_C */
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ /* Determine whether renegotiation attempt should be accepted */
+ if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
+ ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
+ ssl->conf->allow_legacy_renegotiation ==
+ MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
+ {
+ /*
+ * Accept renegotiation request
+ */
+
+ /* DTLS clients need to know renego is server-initiated */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+ ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
+ {
+ ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
+ }
+#endif
+ ret = mbedtls_ssl_start_renegotiation( ssl );
+ if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
+ ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation",
+ ret );
+ return( ret );
+ }
+ }
+ else
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+ {
+ /*
+ * Refuse renegotiation
+ */
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+ {
+ /* SSLv3 does not have a "no_renegotiation" warning, so
+ we send a fatal alert and abort the connection. */
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_SSL3 */
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
+ {
+ if( ( ret = mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_WARNING,
+ MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
+ {
+ return( ret );
+ }
+ }
+ else
+#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 ||
+ MBEDTLS_SSL_PROTO_TLS1_2 */
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+ }
+ }
+
+ /* At this point, we don't know whether the renegotiation has been
+ * completed or not. The cases to consider are the following:
+ * 1) The renegotiation is complete. In this case, no new record
+ * has been read yet.
+ * 2) The renegotiation is incomplete because the client received
+ * an application data record while awaiting the ServerHello.
+ * 3) The renegotiation is incomplete because the client received
+ * a non-handshake, non-application data message while awaiting
+ * the ServerHello.
+ * In each of these case, looping will be the proper action:
+ * - For 1), the next iteration will read a new record and check
+ * if it's application data.
+ * - For 2), the loop condition isn't satisfied as application data
+ * is present, hence continue is the same as break
+ * - For 3), the loop condition is satisfied and read_record
+ * will re-deliver the message that was held back by the client
+ * when expecting the ServerHello.
+ */
+ continue;
+ }
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
+ {
+ if( ssl->conf->renego_max_records >= 0 )
+ {
+ if( ++ssl->renego_records_seen > ssl->conf->renego_max_records )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
+ "but not honored by client" ) );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+ }
+ }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+ /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) );
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+ }
+
+ if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ ssl->in_offt = ssl->in_msg;
+
+ /* We're going to return something now, cancel timer,
+ * except if handshake (renegotiation) is in progress */
+ if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ mbedtls_ssl_set_timer( ssl, 0 );
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ /* If we requested renego but received AppData, resend HelloRequest.
+ * Do it now, after setting in_offt, to avoid taking this branch
+ * again if ssl_write_hello_request() returns WANT_WRITE */
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
+ if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
+ ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
+ {
+ if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request",
+ ret );
+ return( ret );
+ }
+ }
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ }
+
+ n = ( len < ssl->in_msglen )
+ ? len : ssl->in_msglen;
+
+ memcpy( buf, ssl->in_offt, n );
+ ssl->in_msglen -= n;
+
+ if( ssl->in_msglen == 0 )
+ {
+ /* all bytes consumed */
+ ssl->in_offt = NULL;
+ ssl->keep_current_message = 0;
+ }
+ else
+ {
+ /* more data available */
+ ssl->in_offt += n;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) );
+
+ return( (int) n );
+}
+
+/*
+ * Send application data to be encrypted by the SSL layer, taking care of max
+ * fragment length and buffer size.
+ *
+ * According to RFC 5246 Section 6.2.1:
+ *
+ * Zero-length fragments of Application data MAY be sent as they are
+ * potentially useful as a traffic analysis countermeasure.
+ *
+ * Therefore, it is possible that the input message length is 0 and the
+ * corresponding return code is 0 on success.
+ */
+static int ssl_write_real( mbedtls_ssl_context *ssl,
+ const unsigned char *buf, size_t len )
+{
+ int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
+ const size_t max_len = (size_t) ret;
+
+ if( ret < 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
+ return( ret );
+ }
+
+ if( len > max_len )
+ {
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) "
+ "maximum fragment length: %d > %d",
+ len, max_len ) );
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ }
+ else
+#endif
+ len = max_len;
+ }
+
+ if( ssl->out_left != 0 )
+ {
+ /*
+ * The user has previously tried to send the data and
+ * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
+ * written. In this case, we expect the high-level write function
+ * (e.g. mbedtls_ssl_write()) to be called with the same parameters
+ */
+ if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
+ return( ret );
+ }
+ }
+ else
+ {
+ /*
+ * The user is trying to send a message the first time, so we need to
+ * copy the data into the internal buffers and setup the data structure
+ * to keep track of partial writes
+ */
+ ssl->out_msglen = len;
+ ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
+ memcpy( ssl->out_msg, buf, len );
+
+ if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
+ return( ret );
+ }
+ }
+
+ return( (int) len );
+}
+
+/*
+ * Write application data, doing 1/n-1 splitting if necessary.
+ *
+ * With non-blocking I/O, ssl_write_real() may return WANT_WRITE,
+ * then the caller will call us again with the same arguments, so
+ * remember whether we already did the split or not.
+ */
+#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
+static int ssl_write_split( mbedtls_ssl_context *ssl,
+ const unsigned char *buf, size_t len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ if( ssl->conf->cbc_record_splitting ==
+ MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ||
+ len <= 1 ||
+ ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 ||
+ mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc )
+ != MBEDTLS_MODE_CBC )
+ {
+ return( ssl_write_real( ssl, buf, len ) );
+ }
+
+ if( ssl->split_done == 0 )
+ {
+ if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 )
+ return( ret );
+ ssl->split_done = 1;
+ }
+
+ if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 )
+ return( ret );
+ ssl->split_done = 0;
+
+ return( ret + 1 );
+}
+#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
+
+/*
+ * Write application data (public-facing wrapper)
+ */
+int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) );
+
+ if( ssl == NULL || ssl->conf == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
+ return( ret );
+ }
+#endif
+
+ if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
+ {
+ if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
+ return( ret );
+ }
+ }
+
+#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
+ ret = ssl_write_split( ssl, buf, len );
+#else
+ ret = ssl_write_real( ssl, buf, len );
+#endif
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) );
+
+ return( ret );
+}
+
+/*
+ * Notify the peer that the connection is being closed
+ */
+int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl )
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ if( ssl == NULL || ssl->conf == NULL )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
+
+ if( ssl->out_left != 0 )
+ return( mbedtls_ssl_flush_output( ssl ) );
+
+ if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
+ {
+ if( ( ret = mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_WARNING,
+ MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret );
+ return( ret );
+ }
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
+
+ return( 0 );
+}
+
+void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform )
+{
+ if( transform == NULL )
+ return;
+
+#if defined(MBEDTLS_ZLIB_SUPPORT)
+ deflateEnd( &transform->ctx_deflate );
+ inflateEnd( &transform->ctx_inflate );
+#endif
+
+ mbedtls_cipher_free( &transform->cipher_ctx_enc );
+ mbedtls_cipher_free( &transform->cipher_ctx_dec );
+
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+ mbedtls_md_free( &transform->md_ctx_enc );
+ mbedtls_md_free( &transform->md_ctx_dec );
+#endif
+
+ mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
+}
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+
+void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl )
+{
+ unsigned offset;
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+
+ if( hs == NULL )
+ return;
+
+ ssl_free_buffered_record( ssl );
+
+ for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
+ ssl_buffering_free_slot( ssl, offset );
+}
+
+static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
+ uint8_t slot )
+{
+ mbedtls_ssl_handshake_params * const hs = ssl->handshake;
+ mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];
+
+ if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS )
+ return;
+
+ if( hs_buf->is_valid == 1 )
+ {
+ hs->buffering.total_bytes_buffered -= hs_buf->data_len;
+ mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len );
+ mbedtls_free( hs_buf->data );
+ memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
+ }
+}
+
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+/*
+ * Convert version numbers to/from wire format
+ * and, for DTLS, to/from TLS equivalent.
+ *
+ * For TLS this is the identity.
+ * For DTLS, use 1's complement (v -> 255 - v, and then map as follows:
+ * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1)
+ * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2)
+ */
+void mbedtls_ssl_write_version( int major, int minor, int transport,
+ unsigned char ver[2] )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ if( minor == MBEDTLS_SSL_MINOR_VERSION_2 )
+ --minor; /* DTLS 1.0 stored as TLS 1.1 internally */
+
+ ver[0] = (unsigned char)( 255 - ( major - 2 ) );
+ ver[1] = (unsigned char)( 255 - ( minor - 1 ) );
+ }
+ else
+#else
+ ((void) transport);
+#endif
+ {
+ ver[0] = (unsigned char) major;
+ ver[1] = (unsigned char) minor;
+ }
+}
+
+void mbedtls_ssl_read_version( int *major, int *minor, int transport,
+ const unsigned char ver[2] )
+{
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
+ {
+ *major = 255 - ver[0] + 2;
+ *minor = 255 - ver[1] + 1;
+
+ if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 )
+ ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */
+ }
+ else
+#else
+ ((void) transport);
+#endif
+ {
+ *major = ver[0];
+ *minor = ver[1];
+ }
+}
+
+#endif /* MBEDTLS_SSL_TLS_C */
diff --git a/features/mbedtls/src/ssl_srv.c b/features/mbedtls/src/ssl_srv.c
index b1da073ece..b0b09cd97f 100644
--- a/features/mbedtls/src/ssl_srv.c
+++ b/features/mbedtls/src/ssl_srv.c
@@ -35,9 +35,10 @@
#define mbedtls_free free
#endif
-#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include
@@ -85,7 +86,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t servername_list_size, hostname_len;
const unsigned char *p;
@@ -432,7 +433,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 )
{
@@ -624,7 +625,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_session session;
mbedtls_ssl_session_init( &session );
@@ -2428,7 +2429,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
size_t *olen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = buf;
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
size_t kkpp_len;
@@ -2506,7 +2507,7 @@ static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = ssl->out_msg + 4;
unsigned char *cookie_len_byte;
@@ -2580,7 +2581,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_HAVE_TIME)
mbedtls_time_t t;
#endif
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen, ext_len = 0, n;
unsigned char *buf, *p;
@@ -3007,7 +3008,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) )
{
@@ -3088,7 +3089,7 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
ret = mbedtls_ecjpake_write_round_two(
@@ -3128,7 +3129,7 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
@@ -3193,7 +3194,7 @@ static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
*/
const mbedtls_ecp_curve_info **curve = NULL;
const mbedtls_ecp_group_id *gid;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
/* Match our preference list against the offered curves */
@@ -3251,7 +3252,7 @@ curve_matching_done:
size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
size_t hashlen = 0;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/*
* 2.1: Choose hash algorithm:
@@ -3424,7 +3425,7 @@ curve_matching_done:
* machine. */
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t signature_len = 0;
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -3521,7 +3522,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) );
@@ -3625,7 +3626,7 @@ static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
size_t *peer_pmslen,
size_t peer_pmssize )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
size_t len = mbedtls_pk_get_len( public_key );
@@ -3714,7 +3715,7 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *end,
size_t pms_offset )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *pms = ssl->handshake->premaster + pms_offset;
unsigned char ver[2];
unsigned char fake_pms[48], peer_pms[48];
@@ -3868,7 +3869,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha
static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
unsigned char *p, *end;
@@ -4385,7 +4386,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t tlen;
uint32_t lifetime;
diff --git a/features/mbedtls/src/ssl_ticket.c b/features/mbedtls/src/ssl_ticket.c
index 6dad5d1b29..8a76b42b6b 100644
--- a/features/mbedtls/src/ssl_ticket.c
+++ b/features/mbedtls/src/ssl_ticket.c
@@ -36,6 +36,7 @@
#endif
#include "mbedtls/ssl_ticket.h"
+#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include
@@ -73,7 +74,7 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
unsigned char index )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MAX_KEY_BYTES];
mbedtls_ssl_ticket_key *key = ctx->keys + index;
@@ -133,7 +134,7 @@ int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx,
mbedtls_cipher_type_t cipher,
uint32_t lifetime )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
ctx->f_rng = f_rng;
@@ -206,7 +207,7 @@ int mbedtls_ssl_ticket_write( void *p_ticket,
size_t *tlen,
uint32_t *ticket_lifetime )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_ticket_context *ctx = p_ticket;
mbedtls_ssl_ticket_key *key;
unsigned char *key_name = start;
@@ -306,7 +307,7 @@ int mbedtls_ssl_ticket_parse( void *p_ticket,
unsigned char *buf,
size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ssl_ticket_context *ctx = p_ticket;
mbedtls_ssl_ticket_key *key;
unsigned char *key_name = buf;
diff --git a/features/mbedtls/src/ssl_tls.c b/features/mbedtls/src/ssl_tls.c
index 4e7c01bc9e..63bc5c850c 100644
--- a/features/mbedtls/src/ssl_tls.c
+++ b/features/mbedtls/src/ssl_tls.c
@@ -43,9 +43,10 @@
#define mbedtls_free free
#endif
-#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_internal.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/version.h"
@@ -60,123 +61,6 @@
#include "mbedtls/oid.h"
#endif
-static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
-static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl );
-
-/* Length of the "epoch" field in the record header */
-static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl )
-{
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- return( 2 );
-#else
- ((void) ssl);
-#endif
- return( 0 );
-}
-
-/*
- * Start a timer.
- * Passing millisecs = 0 cancels a running timer.
- */
-static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs )
-{
- if( ssl->f_set_timer == NULL )
- return;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) );
- ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs );
-}
-
-/*
- * Return -1 is timer is expired, 0 if it isn't.
- */
-static int ssl_check_timer( mbedtls_ssl_context *ssl )
-{
- if( ssl->f_get_timer == NULL )
- return( 0 );
-
- if( ssl->f_get_timer( ssl->p_timer ) == 2 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) );
- return( -1 );
- }
-
- return( 0 );
-}
-
-static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
- mbedtls_ssl_transform *transform );
-static void ssl_update_in_pointers( mbedtls_ssl_context *ssl );
-
-#if defined(MBEDTLS_SSL_RECORD_CHECKING)
-static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
- unsigned char *buf,
- size_t len,
- mbedtls_record *rec );
-
-int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
- unsigned char *buf,
- size_t buflen )
-{
- int ret = 0;
- mbedtls_record rec;
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) );
- MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen );
-
- /* We don't support record checking in TLS because
- * (a) there doesn't seem to be a usecase for it, and
- * (b) In SSLv3 and TLS 1.0, CBC record decryption has state
- * and we'd need to backup the transform here.
- */
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
- {
- ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
- goto exit;
- }
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- else
- {
- ret = ssl_parse_record_header( ssl, buf, buflen, &rec );
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret );
- goto exit;
- }
-
- if( ssl->transform_in != NULL )
- {
- ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec );
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret );
- goto exit;
- }
- }
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-exit:
- /* On success, we have decrypted the buffer in-place, so make
- * sure we don't leak any plaintext data. */
- mbedtls_platform_zeroize( buf, buflen );
-
- /* For the purpose of this API, treat messages with unexpected CID
- * as well as such from future epochs as unexpected. */
- if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID ||
- ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
- {
- ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) );
- return( ret );
-}
-#endif /* MBEDTLS_SSL_RECORD_CHECKING */
-
-#define SSL_DONT_FORCE_FLUSH 0
-#define SSL_FORCE_FLUSH 1
-
#if defined(MBEDTLS_SSL_PROTO_DTLS)
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
@@ -272,137 +156,6 @@ int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-/* Forward declarations for functions related to message buffering. */
-static void ssl_buffering_free( mbedtls_ssl_context *ssl );
-static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
- uint8_t slot );
-static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
-static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
-static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
-static int ssl_buffer_message( mbedtls_ssl_context *ssl );
-static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
- mbedtls_record const *rec );
-static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
-
-static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl );
-static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
-{
- size_t mtu = ssl_get_current_mtu( ssl );
-
- if( mtu != 0 && mtu < MBEDTLS_SSL_OUT_BUFFER_LEN )
- return( mtu );
-
- return( MBEDTLS_SSL_OUT_BUFFER_LEN );
-}
-
-static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
-{
- size_t const bytes_written = ssl->out_left;
- size_t const mtu = ssl_get_maximum_datagram_size( ssl );
-
- /* Double-check that the write-index hasn't gone
- * past what we can transmit in a single datagram. */
- if( bytes_written > mtu )
- {
- /* Should never happen... */
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- return( (int) ( mtu - bytes_written ) );
-}
-
-static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
-{
- int ret;
- size_t remaining, expansion;
- size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
- const size_t mfl = mbedtls_ssl_get_max_frag_len( ssl );
-
- if( max_len > mfl )
- max_len = mfl;
-
- /* By the standard (RFC 6066 Sect. 4), the MFL extension
- * only limits the maximum record payload size, so in theory
- * we would be allowed to pack multiple records of payload size
- * MFL into a single datagram. However, this would mean that there's
- * no way to explicitly communicate MTU restrictions to the peer.
- *
- * The following reduction of max_len makes sure that we never
- * write datagrams larger than MFL + Record Expansion Overhead.
- */
- if( max_len <= ssl->out_left )
- return( 0 );
-
- max_len -= ssl->out_left;
-#endif
-
- ret = ssl_get_remaining_space_in_datagram( ssl );
- if( ret < 0 )
- return( ret );
- remaining = (size_t) ret;
-
- ret = mbedtls_ssl_get_record_expansion( ssl );
- if( ret < 0 )
- return( ret );
- expansion = (size_t) ret;
-
- if( remaining <= expansion )
- return( 0 );
-
- remaining -= expansion;
- if( remaining >= max_len )
- remaining = max_len;
-
- return( (int) remaining );
-}
-
-/*
- * Double the retransmit timeout value, within the allowed range,
- * returning -1 if the maximum value has already been reached.
- */
-static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
-{
- uint32_t new_timeout;
-
- if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max )
- return( -1 );
-
- /* Implement the final paragraph of RFC 6347 section 4.1.1.1
- * in the following way: after the initial transmission and a first
- * retransmission, back off to a temporary estimated MTU of 508 bytes.
- * This value is guaranteed to be deliverable (if not guaranteed to be
- * delivered) of any compliant IPv4 (and IPv6) network, and should work
- * on most non-IP stacks too. */
- if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min )
- {
- ssl->handshake->mtu = 508;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) );
- }
-
- new_timeout = 2 * ssl->handshake->retransmit_timeout;
-
- /* Avoid arithmetic overflow and range overflow */
- if( new_timeout < ssl->handshake->retransmit_timeout ||
- new_timeout > ssl->conf->hs_timeout_max )
- {
- new_timeout = ssl->conf->hs_timeout_max;
- }
-
- ssl->handshake->retransmit_timeout = new_timeout;
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
- ssl->handshake->retransmit_timeout ) );
-
- return( 0 );
-}
-
-static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl )
-{
- ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min;
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
- ssl->handshake->retransmit_timeout ) );
-}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
@@ -445,7 +198,7 @@ int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
if( src->peer_cert != NULL )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) );
if( dst->peer_cert == NULL )
@@ -492,21 +245,6 @@ int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
return( 0 );
}
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
-int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl,
- const unsigned char *key_enc, const unsigned char *key_dec,
- size_t keylen,
- const unsigned char *iv_enc, const unsigned char *iv_dec,
- size_t ivlen,
- const unsigned char *mac_enc, const unsigned char *mac_dec,
- size_t maclen ) = NULL;
-int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL;
-int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL;
-int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL;
-int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL;
-int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL;
-#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
-
/*
* Key material generation
*/
@@ -585,7 +323,7 @@ static int tls1_prf( const unsigned char *secret, size_t slen,
unsigned char h_i[20];
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_init( &md_ctx );
@@ -831,7 +569,7 @@ static int tls_prf_generic( mbedtls_md_type_t md_type,
unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_init( &md_ctx );
@@ -1682,7 +1420,7 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake,
unsigned char *master,
const mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* cf. RFC 5246, Section 8.1:
* "The master secret is always exactly 48 bytes in length." */
@@ -1809,7 +1547,7 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake,
int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
ssl->handshake->ciphersuite_info;
@@ -1878,7 +1616,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl )
/* Allocate compression buffer */
#if defined(MBEDTLS_ZLIB_SUPPORT)
- if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE &&
+ if( ssl->session_negotiate->compression == MBEDTLS_SSL_COMPRESS_DEFLATE &&
ssl->compress_buf == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) );
@@ -2139,7 +1877,7 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
/* Write length only when we know the actual value */
@@ -2161,7 +1899,7 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t zlen;
if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen,
@@ -2205,1361 +1943,11 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
-/*
- * SSLv3.0 MAC functions
- */
-#define SSL_MAC_MAX_BYTES 20 /* MD-5 or SHA-1 */
-static void ssl_mac( mbedtls_md_context_t *md_ctx,
- const unsigned char *secret,
- const unsigned char *buf, size_t len,
- const unsigned char *ctr, int type,
- unsigned char out[SSL_MAC_MAX_BYTES] )
-{
- unsigned char header[11];
- unsigned char padding[48];
- int padlen;
- int md_size = mbedtls_md_get_size( md_ctx->md_info );
- int md_type = mbedtls_md_get_type( md_ctx->md_info );
-
- /* Only MD5 and SHA-1 supported */
- if( md_type == MBEDTLS_MD_MD5 )
- padlen = 48;
- else
- padlen = 40;
-
- memcpy( header, ctr, 8 );
- header[ 8] = (unsigned char) type;
- header[ 9] = (unsigned char)( len >> 8 );
- header[10] = (unsigned char)( len );
-
- memset( padding, 0x36, padlen );
- mbedtls_md_starts( md_ctx );
- mbedtls_md_update( md_ctx, secret, md_size );
- mbedtls_md_update( md_ctx, padding, padlen );
- mbedtls_md_update( md_ctx, header, 11 );
- mbedtls_md_update( md_ctx, buf, len );
- mbedtls_md_finish( md_ctx, out );
-
- memset( padding, 0x5C, padlen );
- mbedtls_md_starts( md_ctx );
- mbedtls_md_update( md_ctx, secret, md_size );
- mbedtls_md_update( md_ctx, padding, padlen );
- mbedtls_md_update( md_ctx, out, md_size );
- mbedtls_md_finish( md_ctx, out );
-}
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-
-/* The function below is only used in the Lucky 13 counter-measure in
- * mbedtls_ssl_decrypt_buf(). These are the defines that guard the call site. */
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) && \
- ( defined(MBEDTLS_SSL_PROTO_TLS1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_2) )
-/* This function makes sure every byte in the memory region is accessed
- * (in ascending addresses order) */
-static void ssl_read_memory( unsigned char *p, size_t len )
-{
- unsigned char acc = 0;
- volatile unsigned char force;
-
- for( ; len != 0; p++, len-- )
- acc ^= *p;
-
- force = acc;
- (void) force;
-}
-#endif /* SSL_SOME_MODES_USE_MAC && ( TLS1 || TLS1_1 || TLS1_2 ) */
-
-/*
- * Encryption/decryption functions
- */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-/* This functions transforms a DTLS plaintext fragment and a record content
- * type into an instance of the DTLSInnerPlaintext structure:
- *
- * struct {
- * opaque content[DTLSPlaintext.length];
- * ContentType real_type;
- * uint8 zeros[length_of_padding];
- * } DTLSInnerPlaintext;
- *
- * Input:
- * - `content`: The beginning of the buffer holding the
- * plaintext to be wrapped.
- * - `*content_size`: The length of the plaintext in Bytes.
- * - `max_len`: The number of Bytes available starting from
- * `content`. This must be `>= *content_size`.
- * - `rec_type`: The desired record content type.
- *
- * Output:
- * - `content`: The beginning of the resulting DTLSInnerPlaintext structure.
- * - `*content_size`: The length of the resulting DTLSInnerPlaintext structure.
- *
- * Returns:
- * - `0` on success.
- * - A negative error code if `max_len` didn't offer enough space
- * for the expansion.
- */
-static int ssl_cid_build_inner_plaintext( unsigned char *content,
- size_t *content_size,
- size_t remaining,
- uint8_t rec_type )
-{
- size_t len = *content_size;
- size_t pad = ( MBEDTLS_SSL_CID_PADDING_GRANULARITY -
- ( len + 1 ) % MBEDTLS_SSL_CID_PADDING_GRANULARITY ) %
- MBEDTLS_SSL_CID_PADDING_GRANULARITY;
-
- /* Write real content type */
- if( remaining == 0 )
- return( -1 );
- content[ len ] = rec_type;
- len++;
- remaining--;
-
- if( remaining < pad )
- return( -1 );
- memset( content + len, 0, pad );
- len += pad;
- remaining -= pad;
-
- *content_size = len;
- return( 0 );
-}
-
-/* This function parses a DTLSInnerPlaintext structure.
- * See ssl_cid_build_inner_plaintext() for details. */
-static int ssl_cid_parse_inner_plaintext( unsigned char const *content,
- size_t *content_size,
- uint8_t *rec_type )
-{
- size_t remaining = *content_size;
-
- /* Determine length of padding by skipping zeroes from the back. */
- do
- {
- if( remaining == 0 )
- return( -1 );
- remaining--;
- } while( content[ remaining ] == 0 );
-
- *content_size = remaining;
- *rec_type = content[ remaining ];
-
- return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-/* `add_data` must have size 13 Bytes if the CID extension is disabled,
- * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */
-static void ssl_extract_add_data_from_record( unsigned char* add_data,
- size_t *add_data_len,
- mbedtls_record *rec )
-{
- /* Quoting RFC 5246 (TLS 1.2):
- *
- * additional_data = seq_num + TLSCompressed.type +
- * TLSCompressed.version + TLSCompressed.length;
- *
- * For the CID extension, this is extended as follows
- * (quoting draft-ietf-tls-dtls-connection-id-05,
- * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05):
- *
- * additional_data = seq_num + DTLSPlaintext.type +
- * DTLSPlaintext.version +
- * cid +
- * cid_length +
- * length_of_DTLSInnerPlaintext;
- */
-
- memcpy( add_data, rec->ctr, sizeof( rec->ctr ) );
- add_data[8] = rec->type;
- memcpy( add_data + 9, rec->ver, sizeof( rec->ver ) );
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- if( rec->cid_len != 0 )
- {
- memcpy( add_data + 11, rec->cid, rec->cid_len );
- add_data[11 + rec->cid_len + 0] = rec->cid_len;
- add_data[11 + rec->cid_len + 1] = ( rec->data_len >> 8 ) & 0xFF;
- add_data[11 + rec->cid_len + 2] = ( rec->data_len >> 0 ) & 0xFF;
- *add_data_len = 13 + 1 + rec->cid_len;
- }
- else
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- {
- add_data[11 + 0] = ( rec->data_len >> 8 ) & 0xFF;
- add_data[11 + 1] = ( rec->data_len >> 0 ) & 0xFF;
- *add_data_len = 13;
- }
-}
-
-int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
- mbedtls_ssl_transform *transform,
- mbedtls_record *rec,
- int (*f_rng)(void *, unsigned char *, size_t),
- void *p_rng )
-{
- mbedtls_cipher_mode_t mode;
- int auth_done = 0;
- unsigned char * data;
- unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ];
- size_t add_data_len;
- size_t post_avail;
-
- /* The SSL context is only used for debugging purposes! */
-#if !defined(MBEDTLS_DEBUG_C)
- ssl = NULL; /* make sure we don't use it except for debug */
- ((void) ssl);
-#endif
-
- /* The PRNG is used for dynamic IV generation that's used
- * for CBC transformations in TLS 1.1 and TLS 1.2. */
-#if !( defined(MBEDTLS_CIPHER_MODE_CBC) && \
- ( defined(MBEDTLS_AES_C) || \
- defined(MBEDTLS_ARIA_C) || \
- defined(MBEDTLS_CAMELLIA_C) ) && \
- ( defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) ) )
- ((void) f_rng);
- ((void) p_rng);
-#endif
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) );
-
- if( transform == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- if( rec == NULL
- || rec->buf == NULL
- || rec->buf_len < rec->data_offset
- || rec->buf_len - rec->data_offset < rec->data_len
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- || rec->cid_len != 0
-#endif
- )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- data = rec->buf + rec->data_offset;
- post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
- MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload",
- data, rec->data_len );
-
- mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc );
-
- if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %u too large, maximum %d",
- (unsigned) rec->data_len,
- MBEDTLS_SSL_OUT_CONTENT_LEN ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- /*
- * Add CID information
- */
- rec->cid_len = transform->out_cid_len;
- memcpy( rec->cid, transform->out_cid, transform->out_cid_len );
- MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len );
-
- if( rec->cid_len != 0 )
- {
- /*
- * Wrap plaintext into DTLSInnerPlaintext structure.
- * See ssl_cid_build_inner_plaintext() for more information.
- *
- * Note that this changes `rec->data_len`, and hence
- * `post_avail` needs to be recalculated afterwards.
- */
- if( ssl_cid_build_inner_plaintext( data,
- &rec->data_len,
- post_avail,
- rec->type ) != 0 )
- {
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- }
-
- rec->type = MBEDTLS_SSL_MSG_CID;
- }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
- post_avail = rec->buf_len - ( rec->data_len + rec->data_offset );
-
- /*
- * Add MAC before if needed
- */
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
- if( mode == MBEDTLS_MODE_STREAM ||
- ( mode == MBEDTLS_MODE_CBC
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED
-#endif
- ) )
- {
- if( post_avail < transform->maclen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- unsigned char mac[SSL_MAC_MAX_BYTES];
- ssl_mac( &transform->md_ctx_enc, transform->mac_enc,
- data, rec->data_len, rec->ctr, rec->type, mac );
- memcpy( data + rec->data_len, mac, transform->maclen );
- }
- else
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
- {
- unsigned char mac[MBEDTLS_SSL_MAC_ADD];
-
- ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
-
- mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
- add_data_len );
- mbedtls_md_hmac_update( &transform->md_ctx_enc,
- data, rec->data_len );
- mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
- mbedtls_md_hmac_reset( &transform->md_ctx_enc );
-
- memcpy( data + rec->data_len, mac, transform->maclen );
- }
- else
-#endif
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len,
- transform->maclen );
-
- rec->data_len += transform->maclen;
- post_avail -= transform->maclen;
- auth_done++;
- }
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
-
- /*
- * Encrypt
- */
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
- if( mode == MBEDTLS_MODE_STREAM )
- {
- int ret;
- size_t olen;
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including %d bytes of padding",
- rec->data_len, 0 ) );
-
- if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
- transform->iv_enc, transform->ivlen,
- data, rec->data_len,
- data, &olen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
- return( ret );
- }
-
- if( rec->data_len != olen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- }
- else
-#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
-
-#if defined(MBEDTLS_GCM_C) || \
- defined(MBEDTLS_CCM_C) || \
- defined(MBEDTLS_CHACHAPOLY_C)
- if( mode == MBEDTLS_MODE_GCM ||
- mode == MBEDTLS_MODE_CCM ||
- mode == MBEDTLS_MODE_CHACHAPOLY )
- {
- int ret;
- unsigned char iv[12];
- size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
-
- /* Check that there's space for both the authentication tag
- * and the explicit IV before and after the record content. */
- if( post_avail < transform->taglen ||
- rec->data_offset < explicit_iv_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- }
-
- /*
- * Generate IV
- */
- if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
- {
- /* GCM and CCM: fixed || explicit (=seqnum) */
- memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
- memcpy( iv + transform->fixed_ivlen, rec->ctr,
- explicit_iv_len );
- /* Prefix record content with explicit IV. */
- memcpy( data - explicit_iv_len, rec->ctr, explicit_iv_len );
- }
- else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
- {
- /* ChachaPoly: fixed XOR sequence number */
- unsigned char i;
-
- memcpy( iv, transform->iv_enc, transform->fixed_ivlen );
-
- for( i = 0; i < 8; i++ )
- iv[i+4] ^= rec->ctr[i];
- }
- else
- {
- /* Reminder if we ever add an AEAD mode with a different size */
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)",
- iv, transform->ivlen );
- MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)",
- data - explicit_iv_len, explicit_iv_len );
- MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
- add_data, add_data_len );
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including 0 bytes of padding",
- rec->data_len ) );
-
- /*
- * Encrypt and authenticate
- */
-
- if( ( ret = mbedtls_cipher_auth_encrypt( &transform->cipher_ctx_enc,
- iv, transform->ivlen,
- add_data, add_data_len, /* add data */
- data, rec->data_len, /* source */
- data, &rec->data_len, /* destination */
- data + rec->data_len, transform->taglen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret );
- return( ret );
- }
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag",
- data + rec->data_len, transform->taglen );
-
- rec->data_len += transform->taglen + explicit_iv_len;
- rec->data_offset -= explicit_iv_len;
- post_avail -= transform->taglen;
- auth_done++;
- }
- else
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
-#if defined(MBEDTLS_CIPHER_MODE_CBC) && \
- ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) )
- if( mode == MBEDTLS_MODE_CBC )
- {
- int ret;
- size_t padlen, i;
- size_t olen;
-
- /* Currently we're always using minimal padding
- * (up to 255 bytes would be allowed). */
- padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen;
- if( padlen == transform->ivlen )
- padlen = 0;
-
- /* Check there's enough space in the buffer for the padding. */
- if( post_avail < padlen + 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- }
-
- for( i = 0; i <= padlen; i++ )
- data[rec->data_len + i] = (unsigned char) padlen;
-
- rec->data_len += padlen + 1;
- post_avail -= padlen + 1;
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
- /*
- * Prepend per-record IV for block cipher in TLS v1.1 and up as per
- * Method 1 (6.2.3.2. in RFC4346 and RFC5246)
- */
- if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- if( f_rng == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- if( rec->data_offset < transform->ivlen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- }
-
- /*
- * Generate IV
- */
- ret = f_rng( p_rng, transform->iv_enc, transform->ivlen );
- if( ret != 0 )
- return( ret );
-
- memcpy( data - transform->ivlen, transform->iv_enc,
- transform->ivlen );
-
- }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
- "including %d bytes of IV and %d bytes of padding",
- rec->data_len, transform->ivlen,
- padlen + 1 ) );
-
- if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc,
- transform->iv_enc,
- transform->ivlen,
- data, rec->data_len,
- data, &olen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
- return( ret );
- }
-
- if( rec->data_len != olen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
- if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- /*
- * Save IV in SSL3 and TLS1
- */
- memcpy( transform->iv_enc, transform->cipher_ctx_enc.iv,
- transform->ivlen );
- }
- else
-#endif
- {
- data -= transform->ivlen;
- rec->data_offset -= transform->ivlen;
- rec->data_len += transform->ivlen;
- }
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- if( auth_done == 0 )
- {
- unsigned char mac[MBEDTLS_SSL_MAC_ADD];
-
- /*
- * MAC(MAC_write_key, seq_num +
- * TLSCipherText.type +
- * TLSCipherText.version +
- * length_of( (IV +) ENC(...) ) +
- * IV + // except for TLS 1.0
- * ENC(content + padding + padding_length));
- */
-
- if( post_avail < transform->maclen)
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) );
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
- }
-
- ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
- MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
- add_data_len );
-
- mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data,
- add_data_len );
- mbedtls_md_hmac_update( &transform->md_ctx_enc,
- data, rec->data_len );
- mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac );
- mbedtls_md_hmac_reset( &transform->md_ctx_enc );
-
- memcpy( data + rec->data_len, mac, transform->maclen );
-
- rec->data_len += transform->maclen;
- post_avail -= transform->maclen;
- auth_done++;
- }
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
- }
- else
-#endif /* MBEDTLS_CIPHER_MODE_CBC &&
- ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- /* Make extra sure authentication was performed, exactly once */
- if( auth_done != 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) );
-
- return( 0 );
-}
-
-int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
- mbedtls_ssl_transform *transform,
- mbedtls_record *rec )
-{
- size_t olen;
- mbedtls_cipher_mode_t mode;
- int ret, auth_done = 0;
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
- size_t padlen = 0, correct = 1;
-#endif
- unsigned char* data;
- unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ];
- size_t add_data_len;
-
-#if !defined(MBEDTLS_DEBUG_C)
- ssl = NULL; /* make sure we don't use it except for debug */
- ((void) ssl);
-#endif
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
- if( rec == NULL ||
- rec->buf == NULL ||
- rec->buf_len < rec->data_offset ||
- rec->buf_len - rec->data_offset < rec->data_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- data = rec->buf + rec->data_offset;
- mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec );
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- /*
- * Match record's CID with incoming CID.
- */
- if( rec->cid_len != transform->in_cid_len ||
- memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 )
- {
- return( MBEDTLS_ERR_SSL_UNEXPECTED_CID );
- }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
- if( mode == MBEDTLS_MODE_STREAM )
- {
- padlen = 0;
- if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
- transform->iv_dec,
- transform->ivlen,
- data, rec->data_len,
- data, &olen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
- return( ret );
- }
-
- if( rec->data_len != olen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- }
- else
-#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */
-#if defined(MBEDTLS_GCM_C) || \
- defined(MBEDTLS_CCM_C) || \
- defined(MBEDTLS_CHACHAPOLY_C)
- if( mode == MBEDTLS_MODE_GCM ||
- mode == MBEDTLS_MODE_CCM ||
- mode == MBEDTLS_MODE_CHACHAPOLY )
- {
- unsigned char iv[12];
- size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
-
- /*
- * Prepare IV from explicit and implicit data.
- */
-
- /* Check that there's enough space for the explicit IV
- * (at the beginning of the record) and the MAC (at the
- * end of the record). */
- if( rec->data_len < explicit_iv_len + transform->taglen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
- "+ taglen (%d)", rec->data_len,
- explicit_iv_len, transform->taglen ) );
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
-
-#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
- if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
- {
- /* GCM and CCM: fixed || explicit */
-
- /* Fixed */
- memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
- /* Explicit */
- memcpy( iv + transform->fixed_ivlen, data, 8 );
- }
- else
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
-#if defined(MBEDTLS_CHACHAPOLY_C)
- if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
- {
- /* ChachaPoly: fixed XOR sequence number */
- unsigned char i;
-
- memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
-
- for( i = 0; i < 8; i++ )
- iv[i+4] ^= rec->ctr[i];
- }
- else
-#endif /* MBEDTLS_CHACHAPOLY_C */
- {
- /* Reminder if we ever add an AEAD mode with a different size */
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- /* Group changes to data, data_len, and add_data, because
- * add_data depends on data_len. */
- data += explicit_iv_len;
- rec->data_offset += explicit_iv_len;
- rec->data_len -= explicit_iv_len + transform->taglen;
-
- ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
- MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
- add_data, add_data_len );
-
- /* Because of the check above, we know that there are
- * explicit_iv_len Bytes preceeding data, and taglen
- * bytes following data + data_len. This justifies
- * the debug message and the invocation of
- * mbedtls_cipher_auth_decrypt() below. */
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
- MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len,
- transform->taglen );
-
- /*
- * Decrypt and authenticate
- */
- if( ( ret = mbedtls_cipher_auth_decrypt( &transform->cipher_ctx_dec,
- iv, transform->ivlen,
- add_data, add_data_len,
- data, rec->data_len,
- data, &olen,
- data + rec->data_len,
- transform->taglen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret );
-
- if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED )
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
-
- return( ret );
- }
- auth_done++;
-
- /* Double-check that AEAD decryption doesn't change content length. */
- if( olen != rec->data_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- }
- else
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
-#if defined(MBEDTLS_CIPHER_MODE_CBC) && \
- ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) || defined(MBEDTLS_ARIA_C) )
- if( mode == MBEDTLS_MODE_CBC )
- {
- size_t minlen = 0;
-
- /*
- * Check immediate ciphertext sanity
- */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- /* The ciphertext is prefixed with the CBC IV. */
- minlen += transform->ivlen;
- }
-#endif
-
- /* Size considerations:
- *
- * - The CBC cipher text must not be empty and hence
- * at least of size transform->ivlen.
- *
- * Together with the potential IV-prefix, this explains
- * the first of the two checks below.
- *
- * - The record must contain a MAC, either in plain or
- * encrypted, depending on whether Encrypt-then-MAC
- * is used or not.
- * - If it is, the message contains the IV-prefix,
- * the CBC ciphertext, and the MAC.
- * - If it is not, the padded plaintext, and hence
- * the CBC ciphertext, has at least length maclen + 1
- * because there is at least the padding length byte.
- *
- * As the CBC ciphertext is not empty, both cases give the
- * lower bound minlen + maclen + 1 on the record size, which
- * we test for in the second check below.
- */
- if( rec->data_len < minlen + transform->ivlen ||
- rec->data_len < minlen + transform->maclen + 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) "
- "+ 1 ) ( + expl IV )", rec->data_len,
- transform->ivlen,
- transform->maclen ) );
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
-
- /*
- * Authenticate before decrypt if enabled
- */
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED )
- {
- unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
-
- /* Update data_len in tandem with add_data.
- *
- * The subtraction is safe because of the previous check
- * data_len >= minlen + maclen + 1.
- *
- * Afterwards, we know that data + data_len is followed by at
- * least maclen Bytes, which justifies the call to
- * mbedtls_ssl_safer_memcmp() below.
- *
- * Further, we still know that data_len > minlen */
- rec->data_len -= transform->maclen;
- ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
-
- /* Calculate expected MAC. */
- MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
- add_data_len );
- mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
- add_data_len );
- mbedtls_md_hmac_update( &transform->md_ctx_dec,
- data, rec->data_len );
- mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
- mbedtls_md_hmac_reset( &transform->md_ctx_dec );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len,
- transform->maclen );
- MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect,
- transform->maclen );
-
- /* Compare expected MAC with MAC at the end of the record. */
- if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect,
- transform->maclen ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
- auth_done++;
- }
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
-
- /*
- * Check length sanity
- */
-
- /* We know from above that data_len > minlen >= 0,
- * so the following check in particular implies that
- * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */
- if( rec->data_len % transform->ivlen != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
- rec->data_len, transform->ivlen ) );
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
- /*
- * Initialize for prepended IV for block cipher in TLS v1.1 and up
- */
- if( transform->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */
- memcpy( transform->iv_dec, data, transform->ivlen );
-
- data += transform->ivlen;
- rec->data_offset += transform->ivlen;
- rec->data_len -= transform->ivlen;
- }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
-
- /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */
-
- if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
- transform->iv_dec, transform->ivlen,
- data, rec->data_len, data, &olen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret );
- return( ret );
- }
-
- /* Double-check that length hasn't changed during decryption. */
- if( rec->data_len != olen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1)
- if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- /*
- * Save IV in SSL3 and TLS1, where CBC decryption of consecutive
- * records is equivalent to CBC decryption of the concatenation
- * of the records; in other words, IVs are maintained across
- * record decryptions.
- */
- memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv,
- transform->ivlen );
- }
-#endif
-
- /* Safe since data_len >= minlen + maclen + 1, so after having
- * subtracted at most minlen and maclen up to this point,
- * data_len > 0 (because of data_len % ivlen == 0, it's actually
- * >= ivlen ). */
- padlen = data[rec->data_len - 1];
-
- if( auth_done == 1 )
- {
- correct *= ( rec->data_len >= padlen + 1 );
- padlen *= ( rec->data_len >= padlen + 1 );
- }
- else
- {
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
- if( rec->data_len < transform->maclen + padlen + 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)",
- rec->data_len,
- transform->maclen,
- padlen + 1 ) );
- }
-#endif
-
- correct *= ( rec->data_len >= transform->maclen + padlen + 1 );
- padlen *= ( rec->data_len >= transform->maclen + padlen + 1 );
- }
-
- padlen++;
-
- /* Regardless of the validity of the padding,
- * we have data_len >= padlen here. */
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- if( padlen > transform->ivlen )
- {
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, "
- "should be no more than %d",
- padlen, transform->ivlen ) );
-#endif
- correct = 0;
- }
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- /* The padding check involves a series of up to 256
- * consecutive memory reads at the end of the record
- * plaintext buffer. In order to hide the length and
- * validity of the padding, always perform exactly
- * `min(256,plaintext_len)` reads (but take into account
- * only the last `padlen` bytes for the padding check). */
- size_t pad_count = 0;
- size_t real_count = 0;
- volatile unsigned char* const check = data;
-
- /* Index of first padding byte; it has been ensured above
- * that the subtraction is safe. */
- size_t const padding_idx = rec->data_len - padlen;
- size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256;
- size_t const start_idx = rec->data_len - num_checks;
- size_t idx;
-
- for( idx = start_idx; idx < rec->data_len; idx++ )
- {
- real_count |= ( idx >= padding_idx );
- pad_count += real_count * ( check[idx] == padlen - 1 );
- }
- correct &= ( pad_count == padlen );
-
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
- if( padlen > 0 && correct == 0 )
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
-#endif
- padlen &= correct * 0x1FF;
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
- MBEDTLS_SSL_PROTO_TLS1_2 */
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- /* If the padding was found to be invalid, padlen == 0
- * and the subtraction is safe. If the padding was found valid,
- * padlen hasn't been changed and the previous assertion
- * data_len >= padlen still holds. */
- rec->data_len -= padlen;
- }
- else
-#endif /* MBEDTLS_CIPHER_MODE_CBC &&
- ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C || MBEDTLS_ARIA_C ) */
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
- MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption",
- data, rec->data_len );
-#endif
-
- /*
- * Authenticate if not done yet.
- * Compute the MAC regardless of the padding result (RFC4346, CBCTIME).
- */
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
- if( auth_done == 0 )
- {
- unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
-
- /* If the initial value of padlen was such that
- * data_len < maclen + padlen + 1, then padlen
- * got reset to 1, and the initial check
- * data_len >= minlen + maclen + 1
- * guarantees that at this point we still
- * have at least data_len >= maclen.
- *
- * If the initial value of padlen was such that
- * data_len >= maclen + padlen + 1, then we have
- * subtracted either padlen + 1 (if the padding was correct)
- * or 0 (if the padding was incorrect) since then,
- * hence data_len >= maclen in any case.
- */
- rec->data_len -= transform->maclen;
- ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- ssl_mac( &transform->md_ctx_dec,
- transform->mac_dec,
- data, rec->data_len,
- rec->ctr, rec->type,
- mac_expect );
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( transform->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- /*
- * Process MAC and always update for padlen afterwards to make
- * total time independent of padlen.
- *
- * Known timing attacks:
- * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf)
- *
- * To compensate for different timings for the MAC calculation
- * depending on how much padding was removed (which is determined
- * by padlen), process extra_run more blocks through the hash
- * function.
- *
- * The formula in the paper is
- * extra_run = ceil( (L1-55) / 64 ) - ceil( (L2-55) / 64 )
- * where L1 is the size of the header plus the decrypted message
- * plus CBC padding and L2 is the size of the header plus the
- * decrypted message. This is for an underlying hash function
- * with 64-byte blocks.
- * We use ( (Lx+8) / 64 ) to handle 'negative Lx' values
- * correctly. We round down instead of up, so -56 is the correct
- * value for our calculations instead of -55.
- *
- * Repeat the formula rather than defining a block_size variable.
- * This avoids requiring division by a variable at runtime
- * (which would be marginally less efficient and would require
- * linking an extra division function in some builds).
- */
- size_t j, extra_run = 0;
- unsigned char tmp[MBEDTLS_MD_MAX_BLOCK_SIZE];
-
- /*
- * The next two sizes are the minimum and maximum values of
- * in_msglen over all padlen values.
- *
- * They're independent of padlen, since we previously did
- * data_len -= padlen.
- *
- * Note that max_len + maclen is never more than the buffer
- * length, as we previously did in_msglen -= maclen too.
- */
- const size_t max_len = rec->data_len + padlen;
- const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0;
-
- memset( tmp, 0, sizeof( tmp ) );
-
- switch( mbedtls_md_get_type( transform->md_ctx_dec.md_info ) )
- {
-#if defined(MBEDTLS_MD5_C) || defined(MBEDTLS_SHA1_C) || \
- defined(MBEDTLS_SHA256_C)
- case MBEDTLS_MD_MD5:
- case MBEDTLS_MD_SHA1:
- case MBEDTLS_MD_SHA256:
- /* 8 bytes of message size, 64-byte compression blocks */
- extra_run =
- ( add_data_len + rec->data_len + padlen + 8 ) / 64 -
- ( add_data_len + rec->data_len + 8 ) / 64;
- break;
-#endif
-#if defined(MBEDTLS_SHA512_C)
- case MBEDTLS_MD_SHA384:
- /* 16 bytes of message size, 128-byte compression blocks */
- extra_run =
- ( add_data_len + rec->data_len + padlen + 16 ) / 128 -
- ( add_data_len + rec->data_len + 16 ) / 128;
- break;
-#endif
- default:
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- extra_run &= correct * 0xFF;
-
- mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
- add_data_len );
- mbedtls_md_hmac_update( &transform->md_ctx_dec, data,
- rec->data_len );
- /* Make sure we access everything even when padlen > 0. This
- * makes the synchronisation requirements for just-in-time
- * Prime+Probe attacks much tighter and hopefully impractical. */
- ssl_read_memory( data + rec->data_len, padlen );
- mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect );
-
- /* Call mbedtls_md_process at least once due to cache attacks
- * that observe whether md_process() was called of not */
- for( j = 0; j < extra_run + 1; j++ )
- mbedtls_md_process( &transform->md_ctx_dec, tmp );
-
- mbedtls_md_hmac_reset( &transform->md_ctx_dec );
-
- /* Make sure we access all the memory that could contain the MAC,
- * before we check it in the next code block. This makes the
- * synchronisation requirements for just-in-time Prime+Probe
- * attacks much tighter and hopefully impractical. */
- ssl_read_memory( data + min_len,
- max_len - min_len + transform->maclen );
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
- MBEDTLS_SSL_PROTO_TLS1_2 */
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
- MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen );
- MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, transform->maclen );
-#endif
-
- if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect,
- transform->maclen ) != 0 )
- {
-#if defined(MBEDTLS_SSL_DEBUG_ALL)
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) );
-#endif
- correct = 0;
- }
- auth_done++;
- }
-
- /*
- * Finally check the correct flag
- */
- if( correct == 0 )
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
-
- /* Make extra sure authentication was performed, exactly once */
- if( auth_done != 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- if( rec->cid_len != 0 )
- {
- ret = ssl_cid_parse_inner_plaintext( data, &rec->data_len,
- &rec->type );
- if( ret != 0 )
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) );
-
- return( 0 );
-}
-
-#undef MAC_NONE
-#undef MAC_PLAINTEXT
-#undef MAC_CIPHERTEXT
-
-#if defined(MBEDTLS_ZLIB_SUPPORT)
-/*
- * Compression/decompression functions
- */
-static int ssl_compress_buf( mbedtls_ssl_context *ssl )
-{
- int ret;
- unsigned char *msg_post = ssl->out_msg;
- ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf;
- size_t len_pre = ssl->out_msglen;
- unsigned char *msg_pre = ssl->compress_buf;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) );
-
- if( len_pre == 0 )
- return( 0 );
-
- memcpy( msg_pre, ssl->out_msg, len_pre );
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ",
- ssl->out_msglen ) );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload",
- ssl->out_msg, ssl->out_msglen );
-
- ssl->transform_out->ctx_deflate.next_in = msg_pre;
- ssl->transform_out->ctx_deflate.avail_in = len_pre;
- ssl->transform_out->ctx_deflate.next_out = msg_post;
- ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_OUT_BUFFER_LEN - bytes_written;
-
- ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH );
- if( ret != Z_OK )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) );
- return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
- }
-
- ssl->out_msglen = MBEDTLS_SSL_OUT_BUFFER_LEN -
- ssl->transform_out->ctx_deflate.avail_out - bytes_written;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ",
- ssl->out_msglen ) );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload",
- ssl->out_msg, ssl->out_msglen );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) );
-
- return( 0 );
-}
-
-static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
-{
- int ret;
- unsigned char *msg_post = ssl->in_msg;
- ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf;
- size_t len_pre = ssl->in_msglen;
- unsigned char *msg_pre = ssl->compress_buf;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) );
-
- if( len_pre == 0 )
- return( 0 );
-
- memcpy( msg_pre, ssl->in_msg, len_pre );
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ",
- ssl->in_msglen ) );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload",
- ssl->in_msg, ssl->in_msglen );
-
- ssl->transform_in->ctx_inflate.next_in = msg_pre;
- ssl->transform_in->ctx_inflate.avail_in = len_pre;
- ssl->transform_in->ctx_inflate.next_out = msg_post;
- ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_IN_BUFFER_LEN -
- header_bytes;
-
- ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH );
- if( ret != Z_OK )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) );
- return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED );
- }
-
- ssl->in_msglen = MBEDTLS_SSL_IN_BUFFER_LEN -
- ssl->transform_in->ctx_inflate.avail_out - header_bytes;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ",
- ssl->in_msglen ) );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload",
- ssl->in_msg, ssl->in_msglen );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) );
-
- return( 0 );
-}
-#endif /* MBEDTLS_ZLIB_SUPPORT */
-
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
static int ssl_write_hello_request( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
-static int ssl_resend_hello_request( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl )
{
/* If renegotiation is not enforced, retransmit until we would reach max
* timeout if we were using the usual handshake doubling scheme */
@@ -3586,3045 +1974,6 @@ static int ssl_resend_hello_request( mbedtls_ssl_context *ssl )
#endif
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
-/*
- * Fill the input message buffer by appending data to it.
- * The amount of data already fetched is in ssl->in_left.
- *
- * If we return 0, is it guaranteed that (at least) nb_want bytes are
- * available (from this read and/or a previous one). Otherwise, an error code
- * is returned (possibly EOF or WANT_READ).
- *
- * With stream transport (TLS) on success ssl->in_left == nb_want, but
- * with datagram transport (DTLS) on success ssl->in_left >= nb_want,
- * since we always read a whole datagram at once.
- *
- * For DTLS, it is up to the caller to set ssl->next_record_offset when
- * they're done reading a record.
- */
-int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
-{
- int ret;
- size_t len;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) );
-
- if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
- "or mbedtls_ssl_set_bio()" ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
-
- if( nb_want > MBEDTLS_SSL_IN_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- uint32_t timeout;
-
- /* Just to be sure */
- if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use "
- "mbedtls_ssl_set_timer_cb() for DTLS" ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
-
- /*
- * The point is, we need to always read a full datagram at once, so we
- * sometimes read more then requested, and handle the additional data.
- * It could be the rest of the current record (while fetching the
- * header) and/or some other records in the same datagram.
- */
-
- /*
- * Move to the next record in the already read datagram if applicable
- */
- if( ssl->next_record_offset != 0 )
- {
- if( ssl->in_left < ssl->next_record_offset )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- ssl->in_left -= ssl->next_record_offset;
-
- if( ssl->in_left != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d",
- ssl->next_record_offset ) );
- memmove( ssl->in_hdr,
- ssl->in_hdr + ssl->next_record_offset,
- ssl->in_left );
- }
-
- ssl->next_record_offset = 0;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
- ssl->in_left, nb_want ) );
-
- /*
- * Done if we already have enough data.
- */
- if( nb_want <= ssl->in_left)
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
- return( 0 );
- }
-
- /*
- * A record can't be split across datagrams. If we need to read but
- * are not at the beginning of a new record, the caller did something
- * wrong.
- */
- if( ssl->in_left != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- /*
- * Don't even try to read if time's out already.
- * This avoids by-passing the timer when repeatedly receiving messages
- * that will end up being dropped.
- */
- if( ssl_check_timer( ssl ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) );
- ret = MBEDTLS_ERR_SSL_TIMEOUT;
- }
- else
- {
- len = MBEDTLS_SSL_IN_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
-
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
- timeout = ssl->handshake->retransmit_timeout;
- else
- timeout = ssl->conf->read_timeout;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) );
-
- if( ssl->f_recv_timeout != NULL )
- ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
- timeout );
- else
- ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len );
-
- MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
-
- if( ret == 0 )
- return( MBEDTLS_ERR_SSL_CONN_EOF );
- }
-
- if( ret == MBEDTLS_ERR_SSL_TIMEOUT )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) );
- ssl_set_timer( ssl, 0 );
-
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
- {
- if( ssl_double_retransmit_timeout( ssl ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) );
- return( MBEDTLS_ERR_SSL_TIMEOUT );
- }
-
- if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
- return( ret );
- }
-
- return( MBEDTLS_ERR_SSL_WANT_READ );
- }
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
- else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
- {
- if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret );
- return( ret );
- }
-
- return( MBEDTLS_ERR_SSL_WANT_READ );
- }
-#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
- }
-
- if( ret < 0 )
- return( ret );
-
- ssl->in_left = ret;
- }
- else
-#endif
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
- ssl->in_left, nb_want ) );
-
- while( ssl->in_left < nb_want )
- {
- len = nb_want - ssl->in_left;
-
- if( ssl_check_timer( ssl ) != 0 )
- ret = MBEDTLS_ERR_SSL_TIMEOUT;
- else
- {
- if( ssl->f_recv_timeout != NULL )
- {
- ret = ssl->f_recv_timeout( ssl->p_bio,
- ssl->in_hdr + ssl->in_left, len,
- ssl->conf->read_timeout );
- }
- else
- {
- ret = ssl->f_recv( ssl->p_bio,
- ssl->in_hdr + ssl->in_left, len );
- }
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d",
- ssl->in_left, nb_want ) );
- MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret );
-
- if( ret == 0 )
- return( MBEDTLS_ERR_SSL_CONN_EOF );
-
- if( ret < 0 )
- return( ret );
-
- if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1,
- ( "f_recv returned %d bytes but only %lu were requested",
- ret, (unsigned long)len ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- ssl->in_left += ret;
- }
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) );
-
- return( 0 );
-}
-
-/*
- * Flush any data not yet written
- */
-int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
-{
- int ret;
- unsigned char *buf;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) );
-
- if( ssl->f_send == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() "
- "or mbedtls_ssl_set_bio()" ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
-
- /* Avoid incrementing counter if data is flushed */
- if( ssl->out_left == 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
- return( 0 );
- }
-
- while( ssl->out_left > 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d",
- mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) );
-
- buf = ssl->out_hdr - ssl->out_left;
- ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left );
-
- MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret );
-
- if( ret <= 0 )
- return( ret );
-
- if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > SIZE_MAX ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1,
- ( "f_send returned %d bytes but only %lu bytes were sent",
- ret, (unsigned long)ssl->out_left ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- ssl->out_left -= ret;
- }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- ssl->out_hdr = ssl->out_buf;
- }
- else
-#endif
- {
- ssl->out_hdr = ssl->out_buf + 8;
- }
- ssl_update_out_pointers( ssl, ssl->transform_out );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) );
-
- return( 0 );
-}
-
-/*
- * Functions to handle the DTLS retransmission state machine
- */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-/*
- * Append current handshake message to current outgoing flight
- */
-static int ssl_flight_append( mbedtls_ssl_context *ssl )
-{
- mbedtls_ssl_flight_item *msg;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) );
- MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight",
- ssl->out_msg, ssl->out_msglen );
-
- /* Allocate space for current message */
- if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed",
- sizeof( mbedtls_ssl_flight_item ) ) );
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- }
-
- if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) );
- mbedtls_free( msg );
- return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
- }
-
- /* Copy current handshake message with headers */
- memcpy( msg->p, ssl->out_msg, ssl->out_msglen );
- msg->len = ssl->out_msglen;
- msg->type = ssl->out_msgtype;
- msg->next = NULL;
-
- /* Append to the current flight */
- if( ssl->handshake->flight == NULL )
- ssl->handshake->flight = msg;
- else
- {
- mbedtls_ssl_flight_item *cur = ssl->handshake->flight;
- while( cur->next != NULL )
- cur = cur->next;
- cur->next = msg;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) );
- return( 0 );
-}
-
-/*
- * Free the current flight of handshake messages
- */
-static void ssl_flight_free( mbedtls_ssl_flight_item *flight )
-{
- mbedtls_ssl_flight_item *cur = flight;
- mbedtls_ssl_flight_item *next;
-
- while( cur != NULL )
- {
- next = cur->next;
-
- mbedtls_free( cur->p );
- mbedtls_free( cur );
-
- cur = next;
- }
-}
-
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl );
-#endif
-
-/*
- * Swap transform_out and out_ctr with the alternative ones
- */
-static void ssl_swap_epochs( mbedtls_ssl_context *ssl )
-{
- mbedtls_ssl_transform *tmp_transform;
- unsigned char tmp_out_ctr[8];
-
- if( ssl->transform_out == ssl->handshake->alt_transform_out )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) );
- return;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) );
-
- /* Swap transforms */
- tmp_transform = ssl->transform_out;
- ssl->transform_out = ssl->handshake->alt_transform_out;
- ssl->handshake->alt_transform_out = tmp_transform;
-
- /* Swap epoch + sequence_number */
- memcpy( tmp_out_ctr, ssl->cur_out_ctr, 8 );
- memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, 8 );
- memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 );
-
- /* Adjust to the newly activated transform */
- ssl_update_out_pointers( ssl, ssl->transform_out );
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
- if( mbedtls_ssl_hw_record_activate != NULL )
- {
- if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
- }
- }
-#endif
-}
-
-/*
- * Retransmit the current flight of messages.
- */
-int mbedtls_ssl_resend( mbedtls_ssl_context *ssl )
-{
- int ret = 0;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) );
-
- ret = mbedtls_ssl_flight_transmit( ssl );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) );
-
- return( ret );
-}
-
-/*
- * Transmit or retransmit the current flight of messages.
- *
- * Need to remember the current message in case flush_output returns
- * WANT_WRITE, causing us to exit this function and come back later.
- * This function must be called until state is no longer SENDING.
- */
-int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl )
-{
- int ret;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) );
-
- if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) );
-
- ssl->handshake->cur_msg = ssl->handshake->flight;
- ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12;
- ssl_swap_epochs( ssl );
-
- ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING;
- }
-
- while( ssl->handshake->cur_msg != NULL )
- {
- size_t max_frag_len;
- const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg;
-
- int const is_finished =
- ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE &&
- cur->p[0] == MBEDTLS_SSL_HS_FINISHED );
-
- uint8_t const force_flush = ssl->disable_datagram_packing == 1 ?
- SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH;
-
- /* Swap epochs before sending Finished: we can't do it after
- * sending ChangeCipherSpec, in case write returns WANT_READ.
- * Must be done before copying, may change out_msg pointer */
- if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) );
- ssl_swap_epochs( ssl );
- }
-
- ret = ssl_get_remaining_payload_in_datagram( ssl );
- if( ret < 0 )
- return( ret );
- max_frag_len = (size_t) ret;
-
- /* CCS is copied as is, while HS messages may need fragmentation */
- if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
- {
- if( max_frag_len == 0 )
- {
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
- return( ret );
-
- continue;
- }
-
- memcpy( ssl->out_msg, cur->p, cur->len );
- ssl->out_msglen = cur->len;
- ssl->out_msgtype = cur->type;
-
- /* Update position inside current message */
- ssl->handshake->cur_msg_p += cur->len;
- }
- else
- {
- const unsigned char * const p = ssl->handshake->cur_msg_p;
- const size_t hs_len = cur->len - 12;
- const size_t frag_off = p - ( cur->p + 12 );
- const size_t rem_len = hs_len - frag_off;
- size_t cur_hs_frag_len, max_hs_frag_len;
-
- if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) )
- {
- if( is_finished )
- ssl_swap_epochs( ssl );
-
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
- return( ret );
-
- continue;
- }
- max_hs_frag_len = max_frag_len - 12;
-
- cur_hs_frag_len = rem_len > max_hs_frag_len ?
- max_hs_frag_len : rem_len;
-
- if( frag_off == 0 && cur_hs_frag_len != hs_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)",
- (unsigned) cur_hs_frag_len,
- (unsigned) max_hs_frag_len ) );
- }
-
- /* Messages are stored with handshake headers as if not fragmented,
- * copy beginning of headers then fill fragmentation fields.
- * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */
- memcpy( ssl->out_msg, cur->p, 6 );
-
- ssl->out_msg[6] = ( ( frag_off >> 16 ) & 0xff );
- ssl->out_msg[7] = ( ( frag_off >> 8 ) & 0xff );
- ssl->out_msg[8] = ( ( frag_off ) & 0xff );
-
- ssl->out_msg[ 9] = ( ( cur_hs_frag_len >> 16 ) & 0xff );
- ssl->out_msg[10] = ( ( cur_hs_frag_len >> 8 ) & 0xff );
- ssl->out_msg[11] = ( ( cur_hs_frag_len ) & 0xff );
-
- MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 );
-
- /* Copy the handshake message content and set records fields */
- memcpy( ssl->out_msg + 12, p, cur_hs_frag_len );
- ssl->out_msglen = cur_hs_frag_len + 12;
- ssl->out_msgtype = cur->type;
-
- /* Update position inside current message */
- ssl->handshake->cur_msg_p += cur_hs_frag_len;
- }
-
- /* If done with the current message move to the next one if any */
- if( ssl->handshake->cur_msg_p >= cur->p + cur->len )
- {
- if( cur->next != NULL )
- {
- ssl->handshake->cur_msg = cur->next;
- ssl->handshake->cur_msg_p = cur->next->p + 12;
- }
- else
- {
- ssl->handshake->cur_msg = NULL;
- ssl->handshake->cur_msg_p = NULL;
- }
- }
-
- /* Actually send the message out */
- if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
- return( ret );
- }
- }
-
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
- return( ret );
-
- /* Update state and set timer */
- if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
- ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
- else
- {
- ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
- ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) );
-
- return( 0 );
-}
-
-/*
- * To be called when the last message of an incoming flight is received.
- */
-void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl )
-{
- /* We won't need to resend that one any more */
- ssl_flight_free( ssl->handshake->flight );
- ssl->handshake->flight = NULL;
- ssl->handshake->cur_msg = NULL;
-
- /* The next incoming flight will start with this msg_seq */
- ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;
-
- /* We don't want to remember CCS's across flight boundaries. */
- ssl->handshake->buffering.seen_ccs = 0;
-
- /* Clear future message buffering structure. */
- ssl_buffering_free( ssl );
-
- /* Cancel timer */
- ssl_set_timer( ssl, 0 );
-
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
- ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
- {
- ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
- }
- else
- ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING;
-}
-
-/*
- * To be called when the last message of an outgoing flight is send.
- */
-void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl )
-{
- ssl_reset_retransmit_timeout( ssl );
- ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
-
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
- ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
- {
- ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED;
- }
- else
- ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
-}
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-/*
- * Handshake layer functions
- */
-
-/*
- * Write (DTLS: or queue) current handshake (including CCS) message.
- *
- * - fill in handshake headers
- * - update handshake checksum
- * - DTLS: save message for resending
- * - then pass to the record layer
- *
- * DTLS: except for HelloRequest, messages are only queued, and will only be
- * actually sent when calling flight_transmit() or resend().
- *
- * Inputs:
- * - ssl->out_msglen: 4 + actual handshake message len
- * (4 is the size of handshake headers for TLS)
- * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc)
- * - ssl->out_msg + 4: the handshake message body
- *
- * Outputs, ie state before passing to flight_append() or write_record():
- * - ssl->out_msglen: the length of the record contents
- * (including handshake headers but excluding record headers)
- * - ssl->out_msg: the record contents (handshake headers + content)
- */
-int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl )
-{
- int ret;
- const size_t hs_len = ssl->out_msglen - 4;
- const unsigned char hs_type = ssl->out_msg[0];
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) );
-
- /*
- * Sanity checks
- */
- if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE &&
- ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
- {
- /* In SSLv3, the client might send a NoCertificate alert. */
-#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C)
- if( ! ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
- ssl->out_msgtype == MBEDTLS_SSL_MSG_ALERT &&
- ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) )
-#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- }
-
- /* Whenever we send anything different from a
- * HelloRequest we should be in a handshake - double check. */
- if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
- hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) &&
- ssl->handshake == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->handshake != NULL &&
- ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-#endif
-
- /* Double-check that we did not exceed the bounds
- * of the outgoing record buffer.
- * This should never fail as the various message
- * writing functions must obey the bounds of the
- * outgoing record buffer, but better be safe.
- *
- * Note: We deliberately do not check for the MTU or MFL here.
- */
- if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: "
- "size %u, maximum %u",
- (unsigned) ssl->out_msglen,
- (unsigned) MBEDTLS_SSL_OUT_CONTENT_LEN ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- /*
- * Fill handshake headers
- */
- if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
- {
- ssl->out_msg[1] = (unsigned char)( hs_len >> 16 );
- ssl->out_msg[2] = (unsigned char)( hs_len >> 8 );
- ssl->out_msg[3] = (unsigned char)( hs_len );
-
- /*
- * DTLS has additional fields in the Handshake layer,
- * between the length field and the actual payload:
- * uint16 message_seq;
- * uint24 fragment_offset;
- * uint24 fragment_length;
- */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- /* Make room for the additional DTLS fields */
- if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: "
- "size %u, maximum %u",
- (unsigned) ( hs_len ),
- (unsigned) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
-
- memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len );
- ssl->out_msglen += 8;
-
- /* Write message_seq and update it, except for HelloRequest */
- if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
- {
- ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF;
- ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF;
- ++( ssl->handshake->out_msg_seq );
- }
- else
- {
- ssl->out_msg[4] = 0;
- ssl->out_msg[5] = 0;
- }
-
- /* Handshake hashes are computed without fragmentation,
- * so set frag_offset = 0 and frag_len = hs_len for now */
- memset( ssl->out_msg + 6, 0x00, 3 );
- memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 );
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- /* Update running hashes of handshake messages seen */
- if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST )
- ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen );
- }
-
- /* Either send now, or just save to be sent (and resent) later */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
- hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) )
- {
- if( ( ret = ssl_flight_append( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret );
- return( ret );
- }
- }
- else
-#endif
- {
- if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret );
- return( ret );
- }
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) );
-
- return( 0 );
-}
-
-/*
- * Record layer functions
- */
-
-/*
- * Write current record.
- *
- * Uses:
- * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS)
- * - ssl->out_msglen: length of the record content (excl headers)
- * - ssl->out_msg: record content
- */
-int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
-{
- int ret, done = 0;
- size_t len = ssl->out_msglen;
- uint8_t flush = force_flush;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) );
-
-#if defined(MBEDTLS_ZLIB_SUPPORT)
- if( ssl->transform_out != NULL &&
- ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
- {
- if( ( ret = ssl_compress_buf( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret );
- return( ret );
- }
-
- len = ssl->out_msglen;
- }
-#endif /*MBEDTLS_ZLIB_SUPPORT */
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
- if( mbedtls_ssl_hw_record_write != NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) );
-
- ret = mbedtls_ssl_hw_record_write( ssl );
- if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret );
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
- }
-
- if( ret == 0 )
- done = 1;
- }
-#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
- if( !done )
- {
- unsigned i;
- size_t protected_record_size;
-
- /* Skip writing the record content type to after the encryption,
- * as it may change when using the CID extension. */
-
- mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
- ssl->conf->transport, ssl->out_hdr + 1 );
-
- memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
- ssl->out_len[0] = (unsigned char)( len >> 8 );
- ssl->out_len[1] = (unsigned char)( len );
-
- if( ssl->transform_out != NULL )
- {
- mbedtls_record rec;
-
- rec.buf = ssl->out_iv;
- rec.buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN -
- ( ssl->out_iv - ssl->out_buf );
- rec.data_len = ssl->out_msglen;
- rec.data_offset = ssl->out_msg - rec.buf;
-
- memcpy( &rec.ctr[0], ssl->out_ctr, 8 );
- mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
- ssl->conf->transport, rec.ver );
- rec.type = ssl->out_msgtype;
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- /* The CID is set by mbedtls_ssl_encrypt_buf(). */
- rec.cid_len = 0;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
- if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec,
- ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret );
- return( ret );
- }
-
- if( rec.data_offset != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- /* Update the record content type and CID. */
- ssl->out_msgtype = rec.type;
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
- memcpy( ssl->out_cid, rec.cid, rec.cid_len );
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- ssl->out_msglen = len = rec.data_len;
- ssl->out_len[0] = (unsigned char)( rec.data_len >> 8 );
- ssl->out_len[1] = (unsigned char)( rec.data_len );
- }
-
- protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- /* In case of DTLS, double-check that we don't exceed
- * the remaining space in the datagram. */
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- ret = ssl_get_remaining_space_in_datagram( ssl );
- if( ret < 0 )
- return( ret );
-
- if( protected_record_size > (size_t) ret )
- {
- /* Should never happen */
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- /* Now write the potentially updated record content type. */
- ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype;
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, "
- "version = [%d:%d], msglen = %d",
- ssl->out_hdr[0], ssl->out_hdr[1],
- ssl->out_hdr[2], len ) );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network",
- ssl->out_hdr, protected_record_size );
-
- ssl->out_left += protected_record_size;
- ssl->out_hdr += protected_record_size;
- ssl_update_out_pointers( ssl, ssl->transform_out );
-
- for( i = 8; i > ssl_ep_len( ssl ); i-- )
- if( ++ssl->cur_out_ctr[i - 1] != 0 )
- break;
-
- /* The loop goes to its end iff the counter is wrapping */
- if( i == ssl_ep_len( ssl ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) );
- return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
- }
- }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- flush == SSL_DONT_FORCE_FLUSH )
- {
- size_t remaining;
- ret = ssl_get_remaining_payload_in_datagram( ssl );
- if( ret < 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram",
- ret );
- return( ret );
- }
-
- remaining = (size_t) ret;
- if( remaining == 0 )
- {
- flush = SSL_FORCE_FLUSH;
- }
- else
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) );
- }
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- if( ( flush == SSL_FORCE_FLUSH ) &&
- ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
- return( ret );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) );
-
- return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-
-static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
-{
- if( ssl->in_msglen < ssl->in_hslen ||
- memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 ||
- memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 )
- {
- return( 1 );
- }
- return( 0 );
-}
-
-static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl )
-{
- return( ( ssl->in_msg[9] << 16 ) |
- ( ssl->in_msg[10] << 8 ) |
- ssl->in_msg[11] );
-}
-
-static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
-{
- return( ( ssl->in_msg[6] << 16 ) |
- ( ssl->in_msg[7] << 8 ) |
- ssl->in_msg[8] );
-}
-
-static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
-{
- uint32_t msg_len, frag_off, frag_len;
-
- msg_len = ssl_get_hs_total_len( ssl );
- frag_off = ssl_get_hs_frag_off( ssl );
- frag_len = ssl_get_hs_frag_len( ssl );
-
- if( frag_off > msg_len )
- return( -1 );
-
- if( frag_len > msg_len - frag_off )
- return( -1 );
-
- if( frag_len + 12 > ssl->in_msglen )
- return( -1 );
-
- return( 0 );
-}
-
-/*
- * Mark bits in bitmask (used for DTLS HS reassembly)
- */
-static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len )
-{
- unsigned int start_bits, end_bits;
-
- start_bits = 8 - ( offset % 8 );
- if( start_bits != 8 )
- {
- size_t first_byte_idx = offset / 8;
-
- /* Special case */
- if( len <= start_bits )
- {
- for( ; len != 0; len-- )
- mask[first_byte_idx] |= 1 << ( start_bits - len );
-
- /* Avoid potential issues with offset or len becoming invalid */
- return;
- }
-
- offset += start_bits; /* Now offset % 8 == 0 */
- len -= start_bits;
-
- for( ; start_bits != 0; start_bits-- )
- mask[first_byte_idx] |= 1 << ( start_bits - 1 );
- }
-
- end_bits = len % 8;
- if( end_bits != 0 )
- {
- size_t last_byte_idx = ( offset + len ) / 8;
-
- len -= end_bits; /* Now len % 8 == 0 */
-
- for( ; end_bits != 0; end_bits-- )
- mask[last_byte_idx] |= 1 << ( 8 - end_bits );
- }
-
- memset( mask + offset / 8, 0xFF, len / 8 );
-}
-
-/*
- * Check that bitmask is full
- */
-static int ssl_bitmask_check( unsigned char *mask, size_t len )
-{
- size_t i;
-
- for( i = 0; i < len / 8; i++ )
- if( mask[i] != 0xFF )
- return( -1 );
-
- for( i = 0; i < len % 8; i++ )
- if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 )
- return( -1 );
-
- return( 0 );
-}
-
-/* msg_len does not include the handshake header */
-static size_t ssl_get_reassembly_buffer_size( size_t msg_len,
- unsigned add_bitmap )
-{
- size_t alloc_len;
-
- alloc_len = 12; /* Handshake header */
- alloc_len += msg_len; /* Content buffer */
-
- if( add_bitmap )
- alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */
-
- return( alloc_len );
-}
-
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl )
-{
- return( ( ssl->in_msg[1] << 16 ) |
- ( ssl->in_msg[2] << 8 ) |
- ssl->in_msg[3] );
-}
-
-int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
-{
- if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d",
- ssl->in_msglen ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl );
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen ="
- " %d, type = %d, hslen = %d",
- ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- int ret;
- unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
-
- if( ssl_check_hs_header( ssl ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- if( ssl->handshake != NULL &&
- ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
- recv_msg_seq != ssl->handshake->in_msg_seq ) ||
- ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
- ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
- {
- if( recv_msg_seq > ssl->handshake->in_msg_seq )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)",
- recv_msg_seq,
- ssl->handshake->in_msg_seq ) );
- return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
- }
-
- /* Retransmit only on last message from previous flight, to avoid
- * too many retransmissions.
- * Besides, No sane server ever retransmits HelloVerifyRequest */
- if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 &&
- ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, "
- "message_seq = %d, start_of_flight = %d",
- recv_msg_seq,
- ssl->handshake->in_flight_start_seq ) );
-
- if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
- return( ret );
- }
- }
- else
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: "
- "message_seq = %d, expected = %d",
- recv_msg_seq,
- ssl->handshake->in_msg_seq ) );
- }
-
- return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
- }
- /* Wait until message completion to increment in_msg_seq */
-
- /* Message reassembly is handled alongside buffering of future
- * messages; the commonality is that both handshake fragments and
- * future messages cannot be forwarded immediately to the
- * handshake logic layer. */
- if( ssl_hs_is_proper_fragment( ssl ) == 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) );
- return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
- }
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- /* With TLS we don't handle fragmentation (for now) */
- if( ssl->in_msglen < ssl->in_hslen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) );
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
- }
-
- return( 0 );
-}
-
-void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl )
-{
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
-
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL )
- {
- ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen );
- }
-
- /* Handshake message is complete, increment counter */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->handshake != NULL )
- {
- unsigned offset;
- mbedtls_ssl_hs_buffer *hs_buf;
-
- /* Increment handshake sequence number */
- hs->in_msg_seq++;
-
- /*
- * Clear up handshake buffering and reassembly structure.
- */
-
- /* Free first entry */
- ssl_buffering_free_slot( ssl, 0 );
-
- /* Shift all other entries */
- for( offset = 0, hs_buf = &hs->buffering.hs[0];
- offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS;
- offset++, hs_buf++ )
- {
- *hs_buf = *(hs_buf + 1);
- }
-
- /* Create a fresh last entry */
- memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
- }
-#endif
-}
-
-/*
- * DTLS anti-replay: RFC 6347 4.1.2.6
- *
- * in_window is a field of bits numbered from 0 (lsb) to 63 (msb).
- * Bit n is set iff record number in_window_top - n has been seen.
- *
- * Usually, in_window_top is the last record number seen and the lsb of
- * in_window is set. The only exception is the initial state (record number 0
- * not seen yet).
- */
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl )
-{
- ssl->in_window_top = 0;
- ssl->in_window = 0;
-}
-
-static inline uint64_t ssl_load_six_bytes( unsigned char *buf )
-{
- return( ( (uint64_t) buf[0] << 40 ) |
- ( (uint64_t) buf[1] << 32 ) |
- ( (uint64_t) buf[2] << 24 ) |
- ( (uint64_t) buf[3] << 16 ) |
- ( (uint64_t) buf[4] << 8 ) |
- ( (uint64_t) buf[5] ) );
-}
-
-/*
- * Return 0 if sequence number is acceptable, -1 otherwise
- */
-int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl )
-{
- uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
- uint64_t bit;
-
- if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
- return( 0 );
-
- if( rec_seqnum > ssl->in_window_top )
- return( 0 );
-
- bit = ssl->in_window_top - rec_seqnum;
-
- if( bit >= 64 )
- return( -1 );
-
- if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 )
- return( -1 );
-
- return( 0 );
-}
-
-/*
- * Update replay window on new validated record
- */
-void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
-{
- uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
-
- if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED )
- return;
-
- if( rec_seqnum > ssl->in_window_top )
- {
- /* Update window_top and the contents of the window */
- uint64_t shift = rec_seqnum - ssl->in_window_top;
-
- if( shift >= 64 )
- ssl->in_window = 1;
- else
- {
- ssl->in_window <<= shift;
- ssl->in_window |= 1;
- }
-
- ssl->in_window_top = rec_seqnum;
- }
- else
- {
- /* Mark that number as seen in the current window */
- uint64_t bit = ssl->in_window_top - rec_seqnum;
-
- if( bit < 64 ) /* Always true, but be extra sure */
- ssl->in_window |= (uint64_t) 1 << bit;
- }
-}
-#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
-
-#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
-/* Forward declaration */
-static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial );
-
-/*
- * Without any SSL context, check if a datagram looks like a ClientHello with
- * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message.
- * Both input and output include full DTLS headers.
- *
- * - if cookie is valid, return 0
- * - if ClientHello looks superficially valid but cookie is not,
- * fill obuf and set olen, then
- * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
- * - otherwise return a specific error code
- */
-static int ssl_check_dtls_clihlo_cookie(
- mbedtls_ssl_cookie_write_t *f_cookie_write,
- mbedtls_ssl_cookie_check_t *f_cookie_check,
- void *p_cookie,
- const unsigned char *cli_id, size_t cli_id_len,
- const unsigned char *in, size_t in_len,
- unsigned char *obuf, size_t buf_len, size_t *olen )
-{
- size_t sid_len, cookie_len;
- unsigned char *p;
-
- /*
- * Structure of ClientHello with record and handshake headers,
- * and expected values. We don't need to check a lot, more checks will be
- * done when actually parsing the ClientHello - skipping those checks
- * avoids code duplication and does not make cookie forging any easier.
- *
- * 0-0 ContentType type; copied, must be handshake
- * 1-2 ProtocolVersion version; copied
- * 3-4 uint16 epoch; copied, must be 0
- * 5-10 uint48 sequence_number; copied
- * 11-12 uint16 length; (ignored)
- *
- * 13-13 HandshakeType msg_type; (ignored)
- * 14-16 uint24 length; (ignored)
- * 17-18 uint16 message_seq; copied
- * 19-21 uint24 fragment_offset; copied, must be 0
- * 22-24 uint24 fragment_length; (ignored)
- *
- * 25-26 ProtocolVersion client_version; (ignored)
- * 27-58 Random random; (ignored)
- * 59-xx SessionID session_id; 1 byte len + sid_len content
- * 60+ opaque cookie<0..2^8-1>; 1 byte len + content
- * ...
- *
- * Minimum length is 61 bytes.
- */
- if( in_len < 61 ||
- in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
- in[3] != 0 || in[4] != 0 ||
- in[19] != 0 || in[20] != 0 || in[21] != 0 )
- {
- return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
- }
-
- sid_len = in[59];
- if( sid_len > in_len - 61 )
- return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-
- cookie_len = in[60 + sid_len];
- if( cookie_len > in_len - 60 )
- return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
-
- if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len,
- cli_id, cli_id_len ) == 0 )
- {
- /* Valid cookie */
- return( 0 );
- }
-
- /*
- * If we get here, we've got an invalid cookie, let's prepare HVR.
- *
- * 0-0 ContentType type; copied
- * 1-2 ProtocolVersion version; copied
- * 3-4 uint16 epoch; copied
- * 5-10 uint48 sequence_number; copied
- * 11-12 uint16 length; olen - 13
- *
- * 13-13 HandshakeType msg_type; hello_verify_request
- * 14-16 uint24 length; olen - 25
- * 17-18 uint16 message_seq; copied
- * 19-21 uint24 fragment_offset; copied
- * 22-24 uint24 fragment_length; olen - 25
- *
- * 25-26 ProtocolVersion server_version; 0xfe 0xff
- * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie
- *
- * Minimum length is 28.
- */
- if( buf_len < 28 )
- return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
-
- /* Copy most fields and adapt others */
- memcpy( obuf, in, 25 );
- obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
- obuf[25] = 0xfe;
- obuf[26] = 0xff;
-
- /* Generate and write actual cookie */
- p = obuf + 28;
- if( f_cookie_write( p_cookie,
- &p, obuf + buf_len, cli_id, cli_id_len ) != 0 )
- {
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- *olen = p - obuf;
-
- /* Go back and fill length fields */
- obuf[27] = (unsigned char)( *olen - 28 );
-
- obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 );
- obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 );
- obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) );
-
- obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 );
- obuf[12] = (unsigned char)( ( *olen - 13 ) );
-
- return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
-}
-
-/*
- * Handle possible client reconnect with the same UDP quadruplet
- * (RFC 6347 Section 4.2.8).
- *
- * Called by ssl_parse_record_header() in case we receive an epoch 0 record
- * that looks like a ClientHello.
- *
- * - if the input looks like a ClientHello without cookies,
- * send back HelloVerifyRequest, then
- * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
- * - if the input looks like a ClientHello with a valid cookie,
- * reset the session of the current context, and
- * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
- * - if anything goes wrong, return a specific error code
- *
- * mbedtls_ssl_read_record() will ignore the record if anything else than
- * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function
- * cannot not return 0.
- */
-static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
-{
- int ret;
- size_t len;
-
- if( ssl->conf->f_cookie_write == NULL ||
- ssl->conf->f_cookie_check == NULL )
- {
- /* If we can't use cookies to verify reachability of the peer,
- * drop the record. */
- return( 0 );
- }
-
- ret = ssl_check_dtls_clihlo_cookie(
- ssl->conf->f_cookie_write,
- ssl->conf->f_cookie_check,
- ssl->conf->p_cookie,
- ssl->cli_id, ssl->cli_id_len,
- ssl->in_buf, ssl->in_left,
- ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
-
- MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
-
- if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
- {
- /* Don't check write errors as we can't do anything here.
- * If the error is permanent we'll catch it later,
- * if it's not, then hopefully it'll work next time. */
- (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len );
- ret = 0;
- }
-
- if( ret == 0 )
- {
- /* Got a valid cookie, partially reset context */
- if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret );
- return( ret );
- }
-
- return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT );
- }
-
- return( ret );
-}
-#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
-
-static int ssl_check_record_type( uint8_t record_type )
-{
- if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
- record_type != MBEDTLS_SSL_MSG_ALERT &&
- record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
- record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
- {
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- return( 0 );
-}
-
-/*
- * ContentType type;
- * ProtocolVersion version;
- * uint16 epoch; // DTLS only
- * uint48 sequence_number; // DTLS only
- * uint16 length;
- *
- * Return 0 if header looks sane (and, for DTLS, the record is expected)
- * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad,
- * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected.
- *
- * With DTLS, mbedtls_ssl_read_record() will:
- * 1. proceed with the record if this function returns 0
- * 2. drop only the current record if this function returns UNEXPECTED_RECORD
- * 3. return CLIENT_RECONNECT if this function return that value
- * 4. drop the whole datagram if this function returns anything else.
- * Point 2 is needed when the peer is resending, and we have already received
- * the first record from a datagram but are still waiting for the others.
- */
-static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
- unsigned char *buf,
- size_t len,
- mbedtls_record *rec )
-{
- int major_ver, minor_ver;
-
- size_t const rec_hdr_type_offset = 0;
- size_t const rec_hdr_type_len = 1;
-
- size_t const rec_hdr_version_offset = rec_hdr_type_offset +
- rec_hdr_type_len;
- size_t const rec_hdr_version_len = 2;
-
- size_t const rec_hdr_ctr_len = 8;
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- uint32_t rec_epoch;
- size_t const rec_hdr_ctr_offset = rec_hdr_version_offset +
- rec_hdr_version_len;
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset +
- rec_hdr_ctr_len;
- size_t rec_hdr_cid_len = 0;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- size_t rec_hdr_len_offset; /* To be determined */
- size_t const rec_hdr_len_len = 2;
-
- /*
- * Check minimum lengths for record header.
- */
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len;
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- {
- rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len;
- }
-
- if( len < rec_hdr_len_offset + rec_hdr_len_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u",
- (unsigned) len,
- (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- /*
- * Parse and validate record content type
- */
-
- rec->type = buf[ rec_hdr_type_offset ];
-
- /* Check record content type */
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- rec->cid_len = 0;
-
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->conf->cid_len != 0 &&
- rec->type == MBEDTLS_SSL_MSG_CID )
- {
- /* Shift pointers to account for record header including CID
- * struct {
- * ContentType special_type = tls12_cid;
- * ProtocolVersion version;
- * uint16 epoch;
- * uint48 sequence_number;
- * opaque cid[cid_length]; // Additional field compared to
- * // default DTLS record format
- * uint16 length;
- * opaque enc_content[DTLSCiphertext.length];
- * } DTLSCiphertext;
- */
-
- /* So far, we only support static CID lengths
- * fixed in the configuration. */
- rec_hdr_cid_len = ssl->conf->cid_len;
- rec_hdr_len_offset += rec_hdr_cid_len;
-
- if( len < rec_hdr_len_offset + rec_hdr_len_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u",
- (unsigned) len,
- (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- /* configured CID len is guaranteed at most 255, see
- * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */
- rec->cid_len = (uint8_t) rec_hdr_cid_len;
- memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len );
- }
- else
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- {
- if( ssl_check_record_type( rec->type ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u",
- (unsigned) rec->type ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
- }
-
- /*
- * Parse and validate record version
- */
-
- rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
- rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
- mbedtls_ssl_read_version( &major_ver, &minor_ver,
- ssl->conf->transport,
- &rec->ver[0] );
-
- if( major_ver != ssl->major_ver )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- if( minor_ver > ssl->conf->max_minor_ver )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- /*
- * Parse/Copy record sequence number.
- */
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- /* Copy explicit record sequence number from input buffer. */
- memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset,
- rec_hdr_ctr_len );
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- {
- /* Copy implicit record sequence number from SSL context structure. */
- memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len );
- }
-
- /*
- * Parse record length.
- */
-
- rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len;
- rec->data_len = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) |
- ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 );
- MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset );
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
- "version = [%d:%d], msglen = %d",
- rec->type,
- major_ver, minor_ver, rec->data_len ) );
-
- rec->buf = buf;
- rec->buf_len = rec->data_offset + rec->data_len;
-
- if( rec->data_len == 0 )
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
-
- /*
- * DTLS-related tests.
- * Check epoch before checking length constraint because
- * the latter varies with the epoch. E.g., if a ChangeCipherSpec
- * message gets duplicated before the corresponding Finished message,
- * the second ChangeCipherSpec should be discarded because it belongs
- * to an old epoch, but not because its length is shorter than
- * the minimum record length for packets using the new record transform.
- * Note that these two kinds of failures are handled differently,
- * as an unexpected record is silently skipped but an invalid
- * record leads to the entire datagram being dropped.
- */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1];
-
- /* Check that the datagram is large enough to contain a record
- * of the advertised length. */
- if( len < rec->data_offset + rec->data_len )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.",
- (unsigned) len,
- (unsigned)( rec->data_offset + rec->data_len ) ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- /* Records from other, non-matching epochs are silently discarded.
- * (The case of same-port Client reconnects must be considered in
- * the caller). */
- if( rec_epoch != ssl->in_epoch )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
- "expected %d, received %d",
- ssl->in_epoch, rec_epoch ) );
-
- /* Records from the next epoch are considered for buffering
- * (concretely: early Finished messages). */
- if( rec_epoch == (unsigned) ssl->in_epoch + 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
- return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
- }
-
- return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
- }
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
- /* For records from the correct epoch, check whether their
- * sequence number has been seen before. */
- else if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
- }
-#endif
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- return( 0 );
-}
-
-
-#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
-static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
-{
- unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
-
- /*
- * Check for an epoch 0 ClientHello. We can't use in_msg here to
- * access the first byte of record content (handshake type), as we
- * have an active transform (possibly iv_len != 0), so use the
- * fact that the record header len is 13 instead.
- */
- if( rec_epoch == 0 &&
- ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
- ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
- ssl->in_left > 13 &&
- ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
- "from the same port" ) );
- return( ssl_handle_possible_reconnect( ssl ) );
- }
-
- return( 0 );
-}
-#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
-
-/*
- * If applicable, decrypt (and decompress) record content
- */
-static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
- mbedtls_record *rec )
-{
- int ret, done = 0;
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network",
- rec->buf, rec->buf_len );
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
- if( mbedtls_ssl_hw_record_read != NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) );
-
- ret = mbedtls_ssl_hw_record_read( ssl );
- if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret );
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
- }
-
- if( ret == 0 )
- done = 1;
- }
-#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
- if( !done && ssl->transform_in != NULL )
- {
- unsigned char const old_msg_type = rec->type;
-
- if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in,
- rec ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
- ssl->conf->ignore_unexpected_cid
- == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) );
- ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
- }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
- return( ret );
- }
-
- if( old_msg_type != rec->type )
- {
- MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d",
- old_msg_type, rec->type ) );
- }
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
- rec->buf + rec->data_offset, rec->data_len );
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- /* We have already checked the record content type
- * in ssl_parse_record_header(), failing or silently
- * dropping the record in the case of an unknown type.
- *
- * Since with the use of CIDs, the record content type
- * might change during decryption, re-check the record
- * content type, but treat a failure as fatal this time. */
- if( ssl_check_record_type( rec->type ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
- if( rec->data_len == 0 )
- {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3
- && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
- {
- /* TLS v1.2 explicitly disallows zero-length messages which are not application data */
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-
- ssl->nb_zero++;
-
- /*
- * Three or more empty messages may be a DoS attack
- * (excessive CPU consumption).
- */
- if( ssl->nb_zero > 3 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty "
- "messages, possible DoS attack" ) );
- /* Treat the records as if they were not properly authenticated,
- * thereby failing the connection if we see more than allowed
- * by the configured bad MAC threshold. */
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
- }
- else
- ssl->nb_zero = 0;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- ; /* in_ctr read from peer, not maintained internally */
- }
- else
-#endif
- {
- unsigned i;
- for( i = 8; i > ssl_ep_len( ssl ); i-- )
- if( ++ssl->in_ctr[i - 1] != 0 )
- break;
-
- /* The loop goes to its end iff the counter is wrapping */
- if( i == ssl_ep_len( ssl ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) );
- return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
- }
- }
-
- }
-
-#if defined(MBEDTLS_ZLIB_SUPPORT)
- if( ssl->transform_in != NULL &&
- ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE )
- {
- if( ( ret = ssl_decompress_buf( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret );
- return( ret );
- }
- }
-#endif /* MBEDTLS_ZLIB_SUPPORT */
-
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- mbedtls_ssl_dtls_replay_update( ssl );
- }
-#endif
-
- /* Check actual (decrypted) record content length against
- * configured maximum. */
- if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- return( 0 );
-}
-
-static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl );
-
-/*
- * Read a record.
- *
- * Silently ignore non-fatal alert (and for DTLS, invalid records as well,
- * RFC 6347 4.1.2.7) and continue reading until a valid record is found.
- *
- */
-
-/* Helper functions for mbedtls_ssl_read_record(). */
-static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
-static int ssl_get_next_record( mbedtls_ssl_context *ssl );
-static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
-
-int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
- unsigned update_hs_digest )
-{
- int ret;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) );
-
- if( ssl->keep_current_message == 0 )
- {
- do {
-
- ret = ssl_consume_current_message( ssl );
- if( ret != 0 )
- return( ret );
-
- if( ssl_record_is_in_progress( ssl ) == 0 )
- {
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- int have_buffered = 0;
-
- /* We only check for buffered messages if the
- * current datagram is fully consumed. */
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl_next_record_is_in_datagram( ssl ) == 0 )
- {
- if( ssl_load_buffered_message( ssl ) == 0 )
- have_buffered = 1;
- }
-
- if( have_buffered == 0 )
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- {
- ret = ssl_get_next_record( ssl );
- if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING )
- continue;
-
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret );
- return( ret );
- }
- }
- }
-
- ret = mbedtls_ssl_handle_message_type( ssl );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
- {
- /* Buffer future message */
- ret = ssl_buffer_message( ssl );
- if( ret != 0 )
- return( ret );
-
- ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
- MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
-
- if( 0 != ret )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
- return( ret );
- }
-
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
- update_hs_digest == 1 )
- {
- mbedtls_ssl_update_handshake_status( ssl );
- }
- }
- else
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) );
- ssl->keep_current_message = 0;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) );
-
- return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
-{
- if( ssl->in_left > ssl->next_record_offset )
- return( 1 );
-
- return( 0 );
-}
-
-static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
-{
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- mbedtls_ssl_hs_buffer * hs_buf;
- int ret = 0;
-
- if( hs == NULL )
- return( -1 );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
-
- if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
- ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
- {
- /* Check if we have seen a ChangeCipherSpec before.
- * If yes, synthesize a CCS record. */
- if( !hs->buffering.seen_ccs )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) );
- ret = -1;
- goto exit;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) );
- ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
- ssl->in_msglen = 1;
- ssl->in_msg[0] = 1;
-
- /* As long as they are equal, the exact value doesn't matter. */
- ssl->in_left = 0;
- ssl->next_record_offset = 0;
-
- hs->buffering.seen_ccs = 0;
- goto exit;
- }
-
-#if defined(MBEDTLS_DEBUG_C)
- /* Debug only */
- {
- unsigned offset;
- for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
- {
- hs_buf = &hs->buffering.hs[offset];
- if( hs_buf->is_valid == 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.",
- hs->in_msg_seq + offset,
- hs_buf->is_complete ? "fully" : "partially" ) );
- }
- }
- }
-#endif /* MBEDTLS_DEBUG_C */
-
- /* Check if we have buffered and/or fully reassembled the
- * next handshake message. */
- hs_buf = &hs->buffering.hs[0];
- if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) )
- {
- /* Synthesize a record containing the buffered HS message. */
- size_t msg_len = ( hs_buf->data[1] << 16 ) |
- ( hs_buf->data[2] << 8 ) |
- hs_buf->data[3];
-
- /* Double-check that we haven't accidentally buffered
- * a message that doesn't fit into the input buffer. */
- if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) );
- MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)",
- hs_buf->data, msg_len + 12 );
-
- ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
- ssl->in_hslen = msg_len + 12;
- ssl->in_msglen = msg_len + 12;
- memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen );
-
- ret = 0;
- goto exit;
- }
- else
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered",
- hs->in_msg_seq ) );
- }
-
- ret = -1;
-
-exit:
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) );
- return( ret );
-}
-
-static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
- size_t desired )
-{
- int offset;
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available",
- (unsigned) desired ) );
-
- /* Get rid of future records epoch first, if such exist. */
- ssl_free_buffered_record( ssl );
-
- /* Check if we have enough space available now. */
- if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
- hs->buffering.total_bytes_buffered ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) );
- return( 0 );
- }
-
- /* We don't have enough space to buffer the next expected handshake
- * message. Remove buffers used for future messages to gain space,
- * starting with the most distant one. */
- for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1;
- offset >= 0; offset-- )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message",
- offset ) );
-
- ssl_buffering_free_slot( ssl, (uint8_t) offset );
-
- /* Check if we have enough space available now. */
- if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
- hs->buffering.total_bytes_buffered ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) );
- return( 0 );
- }
- }
-
- return( -1 );
-}
-
-static int ssl_buffer_message( mbedtls_ssl_context *ssl )
-{
- int ret = 0;
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
-
- if( hs == NULL )
- return( 0 );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) );
-
- switch( ssl->in_msgtype )
- {
- case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC:
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) );
-
- hs->buffering.seen_ccs = 1;
- break;
-
- case MBEDTLS_SSL_MSG_HANDSHAKE:
- {
- unsigned recv_msg_seq_offset;
- unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
- mbedtls_ssl_hs_buffer *hs_buf;
- size_t msg_len = ssl->in_hslen - 12;
-
- /* We should never receive an old handshake
- * message - double-check nonetheless. */
- if( recv_msg_seq < ssl->handshake->in_msg_seq )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq;
- if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS )
- {
- /* Silently ignore -- message too far in the future */
- MBEDTLS_SSL_DEBUG_MSG( 2,
- ( "Ignore future HS message with sequence number %u, "
- "buffering window %u - %u",
- recv_msg_seq, ssl->handshake->in_msg_seq,
- ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) );
-
- goto exit;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ",
- recv_msg_seq, recv_msg_seq_offset ) );
-
- hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ];
-
- /* Check if the buffering for this seq nr has already commenced. */
- if( !hs_buf->is_valid )
- {
- size_t reassembly_buf_sz;
-
- hs_buf->is_fragmented =
- ( ssl_hs_is_proper_fragment( ssl ) == 1 );
-
- /* We copy the message back into the input buffer
- * after reassembly, so check that it's not too large.
- * This is an implementation-specific limitation
- * and not one from the standard, hence it is not
- * checked in ssl_check_hs_header(). */
- if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN )
- {
- /* Ignore message */
- goto exit;
- }
-
- /* Check if we have enough space to buffer the message. */
- if( hs->buffering.total_bytes_buffered >
- MBEDTLS_SSL_DTLS_MAX_BUFFERING )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len,
- hs_buf->is_fragmented );
-
- if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
- hs->buffering.total_bytes_buffered ) )
- {
- if( recv_msg_seq_offset > 0 )
- {
- /* If we can't buffer a future message because
- * of space limitations -- ignore. */
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
- (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
- (unsigned) hs->buffering.total_bytes_buffered ) );
- goto exit;
- }
- else
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- attempt to make space by freeing buffered future messages\n",
- (unsigned) msg_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
- (unsigned) hs->buffering.total_bytes_buffered ) );
- }
-
- if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %u (%u with bitmap) would exceed the compile-time limit %u (already %u bytes buffered) -- fail\n",
- (unsigned) msg_len,
- (unsigned) reassembly_buf_sz,
- MBEDTLS_SSL_DTLS_MAX_BUFFERING,
- (unsigned) hs->buffering.total_bytes_buffered ) );
- ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
- goto exit;
- }
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d",
- msg_len ) );
-
- hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz );
- if( hs_buf->data == NULL )
- {
- ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
- goto exit;
- }
- hs_buf->data_len = reassembly_buf_sz;
-
- /* Prepare final header: copy msg_type, length and message_seq,
- * then add standardised fragment_offset and fragment_length */
- memcpy( hs_buf->data, ssl->in_msg, 6 );
- memset( hs_buf->data + 6, 0, 3 );
- memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 );
-
- hs_buf->is_valid = 1;
-
- hs->buffering.total_bytes_buffered += reassembly_buf_sz;
- }
- else
- {
- /* Make sure msg_type and length are consistent */
- if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) );
- /* Ignore */
- goto exit;
- }
- }
-
- if( !hs_buf->is_complete )
- {
- size_t frag_len, frag_off;
- unsigned char * const msg = hs_buf->data + 12;
-
- /*
- * Check and copy current fragment
- */
-
- /* Validation of header fields already done in
- * mbedtls_ssl_prepare_handshake_record(). */
- frag_off = ssl_get_hs_frag_off( ssl );
- frag_len = ssl_get_hs_frag_len( ssl );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d",
- frag_off, frag_len ) );
- memcpy( msg + frag_off, ssl->in_msg + 12, frag_len );
-
- if( hs_buf->is_fragmented )
- {
- unsigned char * const bitmask = msg + msg_len;
- ssl_bitmask_set( bitmask, frag_off, frag_len );
- hs_buf->is_complete = ( ssl_bitmask_check( bitmask,
- msg_len ) == 0 );
- }
- else
- {
- hs_buf->is_complete = 1;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete",
- hs_buf->is_complete ? "" : "not yet " ) );
- }
-
- break;
- }
-
- default:
- /* We don't buffer other types of messages. */
- break;
- }
-
-exit:
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) );
- return( ret );
-}
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
-{
- /*
- * Consume last content-layer message and potentially
- * update in_msglen which keeps track of the contents'
- * consumption state.
- *
- * (1) Handshake messages:
- * Remove last handshake message, move content
- * and adapt in_msglen.
- *
- * (2) Alert messages:
- * Consume whole record content, in_msglen = 0.
- *
- * (3) Change cipher spec:
- * Consume whole record content, in_msglen = 0.
- *
- * (4) Application data:
- * Don't do anything - the record layer provides
- * the application data as a stream transport
- * and consumes through mbedtls_ssl_read only.
- *
- */
-
- /* Case (1): Handshake messages */
- if( ssl->in_hslen != 0 )
- {
- /* Hard assertion to be sure that no application data
- * is in flight, as corrupting ssl->in_msglen during
- * ssl->in_offt != NULL is fatal. */
- if( ssl->in_offt != NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- /*
- * Get next Handshake message in the current record
- */
-
- /* Notes:
- * (1) in_hslen is not necessarily the size of the
- * current handshake content: If DTLS handshake
- * fragmentation is used, that's the fragment
- * size instead. Using the total handshake message
- * size here is faulty and should be changed at
- * some point.
- * (2) While it doesn't seem to cause problems, one
- * has to be very careful not to assume that in_hslen
- * is always <= in_msglen in a sensible communication.
- * Again, it's wrong for DTLS handshake fragmentation.
- * The following check is therefore mandatory, and
- * should not be treated as a silently corrected assertion.
- * Additionally, ssl->in_hslen might be arbitrarily out of
- * bounds after handling a DTLS message with an unexpected
- * sequence number, see mbedtls_ssl_prepare_handshake_record.
- */
- if( ssl->in_hslen < ssl->in_msglen )
- {
- ssl->in_msglen -= ssl->in_hslen;
- memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen,
- ssl->in_msglen );
-
- MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record",
- ssl->in_msg, ssl->in_msglen );
- }
- else
- {
- ssl->in_msglen = 0;
- }
-
- ssl->in_hslen = 0;
- }
- /* Case (4): Application data */
- else if( ssl->in_offt != NULL )
- {
- return( 0 );
- }
- /* Everything else (CCS & Alerts) */
- else
- {
- ssl->in_msglen = 0;
- }
-
- return( 0 );
-}
-
-static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
-{
- if( ssl->in_msglen > 0 )
- return( 1 );
-
- return( 0 );
-}
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-
-static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
-{
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- if( hs == NULL )
- return;
-
- if( hs->buffering.future_record.data != NULL )
- {
- hs->buffering.total_bytes_buffered -=
- hs->buffering.future_record.len;
-
- mbedtls_free( hs->buffering.future_record.data );
- hs->buffering.future_record.data = NULL;
- }
-}
-
-static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
-{
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- unsigned char * rec;
- size_t rec_len;
- unsigned rec_epoch;
-
- if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- return( 0 );
-
- if( hs == NULL )
- return( 0 );
-
- rec = hs->buffering.future_record.data;
- rec_len = hs->buffering.future_record.len;
- rec_epoch = hs->buffering.future_record.epoch;
-
- if( rec == NULL )
- return( 0 );
-
- /* Only consider loading future records if the
- * input buffer is empty. */
- if( ssl_next_record_is_in_datagram( ssl ) == 1 )
- return( 0 );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) );
-
- if( rec_epoch != ssl->in_epoch )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) );
- goto exit;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) );
-
- /* Double-check that the record is not too large */
- if( rec_len > MBEDTLS_SSL_IN_BUFFER_LEN -
- (size_t)( ssl->in_hdr - ssl->in_buf ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
- memcpy( ssl->in_hdr, rec, rec_len );
- ssl->in_left = rec_len;
- ssl->next_record_offset = 0;
-
- ssl_free_buffered_record( ssl );
-
-exit:
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) );
- return( 0 );
-}
-
-static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
- mbedtls_record const *rec )
-{
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
-
- /* Don't buffer future records outside handshakes. */
- if( hs == NULL )
- return( 0 );
-
- /* Only buffer handshake records (we are only interested
- * in Finished messages). */
- if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE )
- return( 0 );
-
- /* Don't buffer more than one future epoch record. */
- if( hs->buffering.future_record.data != NULL )
- return( 0 );
-
- /* Don't buffer record if there's not enough buffering space remaining. */
- if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
- hs->buffering.total_bytes_buffered ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
- (unsigned) rec->buf_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
- (unsigned) hs->buffering.total_bytes_buffered ) );
- return( 0 );
- }
-
- /* Buffer record */
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
- ssl->in_epoch + 1 ) );
- MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len );
-
- /* ssl_parse_record_header() only considers records
- * of the next epoch as candidates for buffering. */
- hs->buffering.future_record.epoch = ssl->in_epoch + 1;
- hs->buffering.future_record.len = rec->buf_len;
-
- hs->buffering.future_record.data =
- mbedtls_calloc( 1, hs->buffering.future_record.len );
- if( hs->buffering.future_record.data == NULL )
- {
- /* If we run out of RAM trying to buffer a
- * record from the next epoch, just ignore. */
- return( 0 );
- }
-
- memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len );
-
- hs->buffering.total_bytes_buffered += rec->buf_len;
- return( 0 );
-}
-
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-static int ssl_get_next_record( mbedtls_ssl_context *ssl )
-{
- int ret;
- mbedtls_record rec;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- /* We might have buffered a future record; if so,
- * and if the epoch matches now, load it.
- * On success, this call will set ssl->in_left to
- * the length of the buffered record, so that
- * the calls to ssl_fetch_input() below will
- * essentially be no-ops. */
- ret = ssl_load_buffered_record( ssl );
- if( ret != 0 )
- return( ret );
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- /* Ensure that we have enough space available for the default form
- * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS,
- * with no space for CIDs counted in). */
- ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) );
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
- return( ret );
- }
-
- ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec );
- if( ret != 0 )
- {
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
- {
- ret = ssl_buffer_future_record( ssl, &rec );
- if( ret != 0 )
- return( ret );
-
- /* Fall through to handling of unexpected records */
- ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
- }
-
- if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
- {
-#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
- /* Reset in pointers to default state for TLS/DTLS records,
- * assuming no CID and no offset between record content and
- * record plaintext. */
- ssl_update_in_pointers( ssl );
-
- /* Setup internal message pointers from record structure. */
- ssl->in_msgtype = rec.type;
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- ssl->in_len = ssl->in_cid + rec.cid_len;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- ssl->in_iv = ssl->in_msg = ssl->in_len + 2;
- ssl->in_msglen = rec.data_len;
-
- ret = ssl_check_client_reconnect( ssl );
- if( ret != 0 )
- return( ret );
-#endif
-
- /* Skip unexpected record (but not whole datagram) */
- ssl->next_record_offset = rec.buf_len;
-
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record "
- "(header)" ) );
- }
- else
- {
- /* Skip invalid record and the rest of the datagram */
- ssl->next_record_offset = 0;
- ssl->in_left = 0;
-
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record "
- "(header)" ) );
- }
-
- /* Get next record */
- return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
- }
- else
-#endif
- {
- return( ret );
- }
- }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- /* Remember offset of next record within datagram. */
- ssl->next_record_offset = rec.buf_len;
- if( ssl->next_record_offset < ssl->in_left )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
- }
- }
- else
-#endif
- {
- /*
- * Fetch record contents from underlying transport.
- */
- ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len );
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
- return( ret );
- }
-
- ssl->in_left = 0;
- }
-
- /*
- * Decrypt record contents.
- */
-
- if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 )
- {
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- /* Silently discard invalid records */
- if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
- {
- /* Except when waiting for Finished as a bad mac here
- * probably means something went wrong in the handshake
- * (eg wrong psk used, mitm downgrade attempt, etc.) */
- if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED ||
- ssl->state == MBEDTLS_SSL_SERVER_FINISHED )
- {
-#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
- if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
- {
- mbedtls_ssl_send_alert_message( ssl,
- MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
- }
-#endif
- return( ret );
- }
-
-#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT)
- if( ssl->conf->badmac_limit != 0 &&
- ++ssl->badmac_seen >= ssl->conf->badmac_limit )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) );
- return( MBEDTLS_ERR_SSL_INVALID_MAC );
- }
-#endif
-
- /* As above, invalid records cause
- * dismissal of the whole datagram. */
-
- ssl->next_record_offset = 0;
- ssl->in_left = 0;
-
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
- return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
- }
-
- return( ret );
- }
- else
-#endif
- {
- /* Error out (and send alert) on invalid records */
-#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
- if( ret == MBEDTLS_ERR_SSL_INVALID_MAC )
- {
- mbedtls_ssl_send_alert_message( ssl,
- MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC );
- }
-#endif
- return( ret );
- }
- }
-
-
- /* Reset in pointers to default state for TLS/DTLS records,
- * assuming no CID and no offset between record content and
- * record plaintext. */
- ssl_update_in_pointers( ssl );
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- ssl->in_len = ssl->in_cid + rec.cid_len;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- ssl->in_iv = ssl->in_msg = ssl->in_len + 2;
-
- /* The record content type may change during decryption,
- * so re-read it. */
- ssl->in_msgtype = rec.type;
- /* Also update the input buffer, because unfortunately
- * the server-side ssl_parse_client_hello() reparses the
- * record header when receiving a ClientHello initiating
- * a renegotiation. */
- ssl->in_hdr[0] = rec.type;
- ssl->in_msg = rec.buf + rec.data_offset;
- ssl->in_msglen = rec.data_len;
- ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 );
- ssl->in_len[1] = (unsigned char)( rec.data_len );
-
- return( 0 );
-}
-
-int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
-{
- int ret;
-
- /*
- * Handle particular types of records
- */
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
- {
- if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 )
- {
- return( ret );
- }
- }
-
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
- {
- if( ssl->in_msglen != 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %d",
- ssl->in_msglen ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- if( ssl->in_msg[0] != 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x",
- ssl->in_msg[0] ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
- ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
- {
- if( ssl->handshake == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) );
- return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
- }
-#endif
- }
-
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
- {
- if( ssl->in_msglen != 2 )
- {
- /* Note: Standard allows for more than one 2 byte alert
- to be packed in a single message, but Mbed TLS doesn't
- currently support this. */
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d",
- ssl->in_msglen ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]",
- ssl->in_msg[0], ssl->in_msg[1] ) );
-
- /*
- * Ignore non-fatal alerts, except close_notify and no_renegotiation
- */
- if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)",
- ssl->in_msg[1] ) );
- return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE );
- }
-
- if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
- ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) );
- return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY );
- }
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED)
- if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
- ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) );
- /* Will be handled when trying to parse ServerHello */
- return( 0 );
- }
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
- ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
- ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) );
- /* Will be handled in mbedtls_ssl_parse_certificate() */
- return( 0 );
- }
-#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */
-
- /* Silently ignore: fetch new message */
- return MBEDTLS_ERR_SSL_NON_FATAL;
- }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- /* Drop unexpected ApplicationData records,
- * except at the beginning of renegotiations */
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
- ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
- ssl->state == MBEDTLS_SSL_SERVER_HELLO )
-#endif
- )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
- return( MBEDTLS_ERR_SSL_NON_FATAL );
- }
-
- if( ssl->handshake != NULL &&
- ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
- {
- ssl_handshake_wrapup_free_hs_transform( ssl );
- }
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- return( 0 );
-}
-
-int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl )
-{
- int ret;
-
- if( ( ret = mbedtls_ssl_send_alert_message( ssl,
- MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 )
- {
- return( ret );
- }
-
- return( 0 );
-}
-
-int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
- unsigned char level,
- unsigned char message )
-{
- int ret;
-
- if( ssl == NULL || ssl->conf == NULL )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
-
- ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT;
- ssl->out_msglen = 2;
- ssl->out_msg[0] = level;
- ssl->out_msg[1] = message;
-
- if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
- return( ret );
- }
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) );
-
- return( 0 );
-}
-
#if defined(MBEDTLS_X509_CRT_PARSE_C)
static void ssl_clear_peer_cert( mbedtls_ssl_session *session )
{
@@ -6821,14 +2170,14 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
if( peer_crt->raw.len != crt_buf_len )
return( -1 );
- return( memcmp( peer_crt->raw.p, crt_buf, crt_buf_len ) );
+ return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) );
}
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
unsigned char *crt_buf,
size_t crt_buf_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char const * const peer_cert_digest =
ssl->session->peer_cert_digest;
mbedtls_md_type_t const peer_cert_digest_type =
@@ -6861,7 +2210,7 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *chain )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
int crt_cnt=0;
#endif
@@ -7276,14 +2625,14 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
unsigned char *start, size_t len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Remember digest of the peer's end-CRT. */
ssl->session_negotiate->peer_cert_digest =
mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN );
if( ssl->session_negotiate->peer_cert_digest == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
- sizeof( MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) ) );
+ MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) );
mbedtls_ssl_send_alert_message( ssl,
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
@@ -7308,7 +2657,7 @@ static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
unsigned char *start, size_t len )
{
unsigned char *end = start + len;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Make a copy of the peer's raw public key. */
mbedtls_pk_init( &ssl->handshake->peer_pubkey );
@@ -7476,102 +2825,6 @@ exit:
}
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
-int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
-{
- int ret;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) );
-
- ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
- ssl->out_msglen = 1;
- ssl->out_msg[0] = 1;
-
- ssl->state++;
-
- if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret );
- return( ret );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) );
-
- return( 0 );
-}
-
-int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl )
-{
- int ret;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) );
-
- if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) );
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- /* CCS records are only accepted if they have length 1 and content '1',
- * so we don't need to check this here. */
-
- /*
- * Switch to our negotiated transform and session parameters for inbound
- * data.
- */
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
- ssl->transform_in = ssl->transform_negotiate;
- ssl->session_in = ssl->session_negotiate;
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
- ssl_dtls_replay_reset( ssl );
-#endif
-
- /* Increment epoch */
- if( ++ssl->in_epoch == 0 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) );
- /* This is highly unlikely to happen for legitimate reasons, so
- treat it as an attack and don't send an alert. */
- return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING );
- }
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- memset( ssl->in_ctr, 0, 8 );
-
- ssl_update_in_pointers( ssl );
-
-#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
- if( mbedtls_ssl_hw_record_activate != NULL )
- {
- if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret );
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
- }
- }
-#endif
-
- ssl->state++;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) );
-
- return( 0 );
-}
-
void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t *ciphersuite_info )
{
@@ -7987,7 +3240,7 @@ static void ssl_calc_finished_tls_sha384(
#endif /* MBEDTLS_SHA512_C */
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
+void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) );
@@ -8059,7 +3312,7 @@ void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl )
ssl->handshake->flight != NULL )
{
/* Cancel handshake timer */
- ssl_set_timer( ssl, 0 );
+ mbedtls_ssl_set_timer( ssl, 0 );
/* Keep last flight around in case we need to resend it:
* we need the handshake and transform structures for that */
@@ -8067,7 +3320,7 @@ void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl )
}
else
#endif
- ssl_handshake_wrapup_free_hs_transform( ssl );
+ mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl );
ssl->state++;
@@ -8080,7 +3333,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) );
- ssl_update_out_pointers( ssl, ssl->transform_negotiate );
+ mbedtls_ssl_update_out_pointers( ssl, ssl->transform_negotiate );
ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint );
@@ -8200,7 +3453,7 @@ int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl )
int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned int hash_len;
unsigned char buf[SSL_MAX_HASH_LEN];
@@ -8424,7 +3677,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl )
else
ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING;
- ssl_set_timer( ssl, 0 );
+ mbedtls_ssl_set_timer( ssl, 0 );
}
#endif
@@ -8460,103 +3713,6 @@ static int ssl_cookie_check_dummy( void *ctx,
}
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */
-/* Once ssl->out_hdr as the address of the beginning of the
- * next outgoing record is set, deduce the other pointers.
- *
- * Note: For TLS, we save the implicit record sequence number
- * (entering MAC computation) in the 8 bytes before ssl->out_hdr,
- * and the caller has to make sure there's space for this.
- */
-
-static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
- mbedtls_ssl_transform *transform )
-{
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- ssl->out_ctr = ssl->out_hdr + 3;
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- ssl->out_cid = ssl->out_ctr + 8;
- ssl->out_len = ssl->out_cid;
- if( transform != NULL )
- ssl->out_len += transform->out_cid_len;
-#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- ssl->out_len = ssl->out_ctr + 8;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- ssl->out_iv = ssl->out_len + 2;
- }
- else
-#endif
- {
- ssl->out_ctr = ssl->out_hdr - 8;
- ssl->out_len = ssl->out_hdr + 3;
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- ssl->out_cid = ssl->out_len;
-#endif
- ssl->out_iv = ssl->out_hdr + 5;
- }
-
- /* Adjust out_msg to make space for explicit IV, if used. */
- if( transform != NULL &&
- ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- {
- ssl->out_msg = ssl->out_iv + transform->ivlen - transform->fixed_ivlen;
- }
- else
- ssl->out_msg = ssl->out_iv;
-}
-
-/* Once ssl->in_hdr as the address of the beginning of the
- * next incoming record is set, deduce the other pointers.
- *
- * Note: For TLS, we save the implicit record sequence number
- * (entering MAC computation) in the 8 bytes before ssl->in_hdr,
- * and the caller has to make sure there's space for this.
- */
-
-static void ssl_update_in_pointers( mbedtls_ssl_context *ssl )
-{
- /* This function sets the pointers to match the case
- * of unprotected TLS/DTLS records, with both ssl->in_iv
- * and ssl->in_msg pointing to the beginning of the record
- * content.
- *
- * When decrypting a protected record, ssl->in_msg
- * will be shifted to point to the beginning of the
- * record plaintext.
- */
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- /* This sets the header pointers to match records
- * without CID. When we receive a record containing
- * a CID, the fields are shifted accordingly in
- * ssl_parse_record_header(). */
- ssl->in_ctr = ssl->in_hdr + 3;
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- ssl->in_cid = ssl->in_ctr + 8;
- ssl->in_len = ssl->in_cid; /* Default: no CID */
-#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- ssl->in_len = ssl->in_ctr + 8;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- ssl->in_iv = ssl->in_len + 2;
- }
- else
-#endif
- {
- ssl->in_ctr = ssl->in_hdr - 8;
- ssl->in_len = ssl->in_hdr + 3;
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- ssl->in_cid = ssl->in_len;
-#endif
- ssl->in_iv = ssl->in_hdr + 5;
- }
-
- /* This will be adjusted at record decryption time. */
- ssl->in_msg = ssl->in_iv;
-}
-
/*
* Initialize an SSL context
*/
@@ -8569,31 +3725,10 @@ void mbedtls_ssl_init( mbedtls_ssl_context *ssl )
* Setup an SSL context
*/
-static void ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl )
-{
- /* Set the incoming and outgoing record pointers. */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- ssl->out_hdr = ssl->out_buf;
- ssl->in_hdr = ssl->in_buf;
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- {
- ssl->out_hdr = ssl->out_buf + 8;
- ssl->in_hdr = ssl->in_buf + 8;
- }
-
- /* Derive other internal pointers. */
- ssl_update_out_pointers( ssl, NULL /* no transform enabled */ );
- ssl_update_in_pointers ( ssl );
-}
-
int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
const mbedtls_ssl_config *conf )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ssl->conf = conf;
@@ -8620,7 +3755,7 @@ int mbedtls_ssl_setup( mbedtls_ssl_context *ssl,
goto error;
}
- ssl_reset_in_out_pointers( ssl );
+ mbedtls_ssl_reset_in_out_pointers( ssl );
if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
goto error;
@@ -8658,9 +3793,9 @@ error:
* If partial is non-zero, keep data in the input buffer and client ID.
* (Use when a DTLS client reconnects from the same port.)
*/
-static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
+int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || \
!defined(MBEDTLS_SSL_SRV_C)
@@ -8670,7 +3805,7 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
/* Cancel any possibly running timer */
- ssl_set_timer( ssl, 0 );
+ mbedtls_ssl_set_timer( ssl, 0 );
#if defined(MBEDTLS_SSL_RENEGOTIATION)
ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE;
@@ -8683,7 +3818,7 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION;
ssl->in_offt = NULL;
- ssl_reset_in_out_pointers( ssl );
+ mbedtls_ssl_reset_in_out_pointers( ssl );
ssl->in_msgtype = 0;
ssl->in_msglen = 0;
@@ -8692,7 +3827,7 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
ssl->in_epoch = 0;
#endif
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
- ssl_dtls_replay_reset( ssl );
+ mbedtls_ssl_dtls_replay_reset( ssl );
#endif
ssl->in_hslen = 0;
@@ -8779,7 +3914,7 @@ static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial )
*/
int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl )
{
- return( ssl_session_reset_int( ssl, 0 ) );
+ return( mbedtls_ssl_session_reset_int( ssl, 0 ) );
}
/*
@@ -8890,7 +4025,7 @@ void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl,
ssl->f_get_timer = f_get_timer;
/* Make sure we start with no timer running */
- ssl_set_timer( ssl, 0 );
+ mbedtls_ssl_set_timer( ssl, 0 );
}
#if defined(MBEDTLS_SSL_SRV_C)
@@ -8908,7 +4043,7 @@ void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf,
#if defined(MBEDTLS_SSL_CLI_C)
int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ssl == NULL ||
session == NULL ||
@@ -9152,13 +4287,18 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf,
const unsigned char *psk, size_t psk_len,
const unsigned char *psk_identity, size_t psk_identity_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Remove opaque/raw PSK + PSK Identity */
ssl_conf_remove_psk( conf );
/* Check and set raw PSK */
- if( psk == NULL || psk_len > MBEDTLS_PSK_MAX_LEN )
+ if( psk == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ if( psk_len == 0 )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ if( psk_len > MBEDTLS_PSK_MAX_LEN )
+ return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
conf->psk_len = psk_len;
@@ -9216,7 +4356,7 @@ int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
const unsigned char *psk_identity,
size_t psk_identity_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Clear opaque/raw PSK + PSK Identity, if present. */
ssl_conf_remove_psk( conf );
@@ -9261,7 +4401,7 @@ void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf,
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 ||
( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 )
@@ -9279,7 +4419,7 @@ int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf,
const unsigned char *dhm_P, size_t P_len,
const unsigned char *dhm_G, size_t G_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 ||
( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 )
@@ -9294,7 +4434,7 @@ int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf,
int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 ||
( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 )
@@ -9609,66 +4749,6 @@ void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl,
/*
* SSL get accessors
*/
-size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl )
-{
- return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
-}
-
-int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
-{
- /*
- * Case A: We're currently holding back
- * a message for further processing.
- */
-
- if( ssl->keep_current_message == 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) );
- return( 1 );
- }
-
- /*
- * Case B: Further records are pending in the current datagram.
- */
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->in_left > ssl->next_record_offset )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) );
- return( 1 );
- }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
- /*
- * Case C: A handshake message is being processed.
- */
-
- if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) );
- return( 1 );
- }
-
- /*
- * Case D: An application data message is being processed
- */
- if( ssl->in_offt != NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) );
- return( 1 );
- }
-
- /*
- * In all other cases, the rest of the message can be dropped.
- * As in ssl_get_next_record, this needs to be adapted if
- * we implement support for multiple alerts in single records.
- */
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) );
- return( 0 );
-}
-
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl )
{
if( ssl->session != NULL )
@@ -9726,66 +4806,6 @@ const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl )
}
}
-int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
-{
- size_t transform_expansion = 0;
- const mbedtls_ssl_transform *transform = ssl->transform_out;
- unsigned block_size;
-
- size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl );
-
- if( transform == NULL )
- return( (int) out_hdr_len );
-
-#if defined(MBEDTLS_ZLIB_SUPPORT)
- if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL )
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
-#endif
-
- switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) )
- {
- case MBEDTLS_MODE_GCM:
- case MBEDTLS_MODE_CCM:
- case MBEDTLS_MODE_CHACHAPOLY:
- case MBEDTLS_MODE_STREAM:
- transform_expansion = transform->minlen;
- break;
-
- case MBEDTLS_MODE_CBC:
-
- block_size = mbedtls_cipher_get_block_size(
- &transform->cipher_ctx_enc );
-
- /* Expansion due to the addition of the MAC. */
- transform_expansion += transform->maclen;
-
- /* Expansion due to the addition of CBC padding;
- * Theoretically up to 256 bytes, but we never use
- * more than the block size of the underlying cipher. */
- transform_expansion += block_size;
-
- /* For TLS 1.1 or higher, an explicit IV is added
- * after the record header. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 )
- transform_expansion += block_size;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
-
- break;
-
- default:
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- if( transform->out_cid_len != 0 )
- transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
- return( (int)( out_hdr_len + transform_expansion ) );
-}
-
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl )
{
@@ -9815,7 +4835,7 @@ size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
-static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl )
+size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl )
{
/* Return unlimited mtu for client hello messages to avoid fragmentation. */
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
@@ -9851,9 +4871,9 @@ int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl )
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl_get_current_mtu( ssl ) != 0 )
+ if( mbedtls_ssl_get_current_mtu( ssl ) != 0 )
{
- const size_t mtu = ssl_get_current_mtu( ssl );
+ const size_t mtu = mbedtls_ssl_get_current_mtu( ssl );
const int ret = mbedtls_ssl_get_record_expansion( ssl );
const size_t overhead = (size_t) ret;
@@ -10342,7 +5362,7 @@ static int ssl_session_load( mbedtls_ssl_session *session,
if( cert_len != 0 )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( cert_len > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -10530,7 +5550,7 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl )
*/
static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) );
@@ -10559,9 +5579,9 @@ static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
* If the handshake doesn't complete due to waiting for I/O, it will continue
* during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively.
*/
-static int ssl_start_renegotiation( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) );
@@ -10633,9 +5653,9 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl )
if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 )
+ if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 )
{
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", ret );
return( ret );
}
}
@@ -10651,546 +5671,8 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl )
return( ret );
}
-
-/*
- * Check record counters and renegotiate if they're above the limit.
- */
-static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
-{
- size_t ep_len = ssl_ep_len( ssl );
- int in_ctr_cmp;
- int out_ctr_cmp;
-
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ||
- ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ||
- ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED )
- {
- return( 0 );
- }
-
- in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
- ssl->conf->renego_period + ep_len, 8 - ep_len );
- out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
- ssl->conf->renego_period + ep_len, 8 - ep_len );
-
- if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
- {
- return( 0 );
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) );
- return( mbedtls_ssl_renegotiate( ssl ) );
-}
#endif /* MBEDTLS_SSL_RENEGOTIATION */
-/*
- * Receive application data decrypted from the SSL layer
- */
-int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
-{
- int ret;
- size_t n;
-
- if( ssl == NULL || ssl->conf == NULL )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
- return( ret );
-
- if( ssl->handshake != NULL &&
- ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING )
- {
- if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 )
- return( ret );
- }
- }
-#endif
-
- /*
- * Check if renegotiation is necessary and/or handshake is
- * in process. If yes, perform/continue, and fall through
- * if an unexpected packet is received while the client
- * is waiting for the ServerHello.
- *
- * (There is no equivalent to the last condition on
- * the server-side as it is not treated as within
- * a handshake while waiting for the ClientHello
- * after a renegotiation request.)
- */
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- ret = ssl_check_ctr_renegotiate( ssl );
- if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
- ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
- return( ret );
- }
-#endif
-
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
- {
- ret = mbedtls_ssl_handshake( ssl );
- if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
- ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
- return( ret );
- }
- }
-
- /* Loop as long as no application data record is available */
- while( ssl->in_offt == NULL )
- {
- /* Start timer if not already running */
- if( ssl->f_get_timer != NULL &&
- ssl->f_get_timer( ssl->p_timer ) == -1 )
- {
- ssl_set_timer( ssl, ssl->conf->read_timeout );
- }
-
- if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
- {
- if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
- return( 0 );
-
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
- }
-
- if( ssl->in_msglen == 0 &&
- ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA )
- {
- /*
- * OpenSSL sends empty messages to randomize the IV
- */
- if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
- {
- if( ret == MBEDTLS_ERR_SSL_CONN_EOF )
- return( 0 );
-
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
- return( ret );
- }
- }
-
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) );
-
- /*
- * - For client-side, expect SERVER_HELLO_REQUEST.
- * - For server-side, expect CLIENT_HELLO.
- * - Fail (TLS) or silently drop record (DTLS) in other cases.
- */
-
-#if defined(MBEDTLS_SSL_CLI_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
- ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST ||
- ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) );
-
- /* With DTLS, drop the packet (probably from last handshake) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- continue;
- }
-#endif
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-#endif /* MBEDTLS_SSL_CLI_C */
-
-#if defined(MBEDTLS_SSL_SRV_C)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) );
-
- /* With DTLS, drop the packet (probably from last handshake) */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- continue;
- }
-#endif
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-#endif /* MBEDTLS_SSL_SRV_C */
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- /* Determine whether renegotiation attempt should be accepted */
- if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
- ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
- ssl->conf->allow_legacy_renegotiation ==
- MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
- {
- /*
- * Accept renegotiation request
- */
-
- /* DTLS clients need to know renego is server-initiated */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
- ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
- {
- ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
- }
-#endif
- ret = ssl_start_renegotiation( ssl );
- if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO &&
- ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
- return( ret );
- }
- }
- else
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
- {
- /*
- * Refuse renegotiation
- */
-
- MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) );
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- /* SSLv3 does not have a "no_renegotiation" warning, so
- we send a fatal alert and abort the connection. */
- mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_SSL3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 )
- {
- if( ( ret = mbedtls_ssl_send_alert_message( ssl,
- MBEDTLS_SSL_ALERT_LEVEL_WARNING,
- MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 )
- {
- return( ret );
- }
- }
- else
-#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 ||
- MBEDTLS_SSL_PROTO_TLS1_2 */
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- }
-
- /* At this point, we don't know whether the renegotiation has been
- * completed or not. The cases to consider are the following:
- * 1) The renegotiation is complete. In this case, no new record
- * has been read yet.
- * 2) The renegotiation is incomplete because the client received
- * an application data record while awaiting the ServerHello.
- * 3) The renegotiation is incomplete because the client received
- * a non-handshake, non-application data message while awaiting
- * the ServerHello.
- * In each of these case, looping will be the proper action:
- * - For 1), the next iteration will read a new record and check
- * if it's application data.
- * - For 2), the loop condition isn't satisfied as application data
- * is present, hence continue is the same as break
- * - For 3), the loop condition is satisfied and read_record
- * will re-deliver the message that was held back by the client
- * when expecting the ServerHello.
- */
- continue;
- }
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
- {
- if( ssl->conf->renego_max_records >= 0 )
- {
- if( ++ssl->renego_records_seen > ssl->conf->renego_max_records )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, "
- "but not honored by client" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
- }
- }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
-
- /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */
- if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) );
- return( MBEDTLS_ERR_SSL_WANT_READ );
- }
-
- if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) );
- return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
- }
-
- ssl->in_offt = ssl->in_msg;
-
- /* We're going to return something now, cancel timer,
- * except if handshake (renegotiation) is in progress */
- if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
- ssl_set_timer( ssl, 0 );
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- /* If we requested renego but received AppData, resend HelloRequest.
- * Do it now, after setting in_offt, to avoid taking this branch
- * again if ssl_write_hello_request() returns WANT_WRITE */
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
- if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
- ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
- {
- if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret );
- return( ret );
- }
- }
-#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
- }
-
- n = ( len < ssl->in_msglen )
- ? len : ssl->in_msglen;
-
- memcpy( buf, ssl->in_offt, n );
- ssl->in_msglen -= n;
-
- if( ssl->in_msglen == 0 )
- {
- /* all bytes consumed */
- ssl->in_offt = NULL;
- ssl->keep_current_message = 0;
- }
- else
- {
- /* more data available */
- ssl->in_offt += n;
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) );
-
- return( (int) n );
-}
-
-/*
- * Send application data to be encrypted by the SSL layer, taking care of max
- * fragment length and buffer size.
- *
- * According to RFC 5246 Section 6.2.1:
- *
- * Zero-length fragments of Application data MAY be sent as they are
- * potentially useful as a traffic analysis countermeasure.
- *
- * Therefore, it is possible that the input message length is 0 and the
- * corresponding return code is 0 on success.
- */
-static int ssl_write_real( mbedtls_ssl_context *ssl,
- const unsigned char *buf, size_t len )
-{
- int ret = mbedtls_ssl_get_max_out_record_payload( ssl );
- const size_t max_len = (size_t) ret;
-
- if( ret < 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret );
- return( ret );
- }
-
- if( len > max_len )
- {
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) "
- "maximum fragment length: %d > %d",
- len, max_len ) );
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
- }
- else
-#endif
- len = max_len;
- }
-
- if( ssl->out_left != 0 )
- {
- /*
- * The user has previously tried to send the data and
- * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially
- * written. In this case, we expect the high-level write function
- * (e.g. mbedtls_ssl_write()) to be called with the same parameters
- */
- if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret );
- return( ret );
- }
- }
- else
- {
- /*
- * The user is trying to send a message the first time, so we need to
- * copy the data into the internal buffers and setup the data structure
- * to keep track of partial writes
- */
- ssl->out_msglen = len;
- ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
- memcpy( ssl->out_msg, buf, len );
-
- if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret );
- return( ret );
- }
- }
-
- return( (int) len );
-}
-
-/*
- * Write application data, doing 1/n-1 splitting if necessary.
- *
- * With non-blocking I/O, ssl_write_real() may return WANT_WRITE,
- * then the caller will call us again with the same arguments, so
- * remember whether we already did the split or not.
- */
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
-static int ssl_write_split( mbedtls_ssl_context *ssl,
- const unsigned char *buf, size_t len )
-{
- int ret;
-
- if( ssl->conf->cbc_record_splitting ==
- MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ||
- len <= 1 ||
- ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 ||
- mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc )
- != MBEDTLS_MODE_CBC )
- {
- return( ssl_write_real( ssl, buf, len ) );
- }
-
- if( ssl->split_done == 0 )
- {
- if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 )
- return( ret );
- ssl->split_done = 1;
- }
-
- if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 )
- return( ret );
- ssl->split_done = 0;
-
- return( ret + 1 );
-}
-#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
-
-/*
- * Write application data (public-facing wrapper)
- */
-int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len )
-{
- int ret;
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) );
-
- if( ssl == NULL || ssl->conf == NULL )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
- if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret );
- return( ret );
- }
-#endif
-
- if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
- {
- if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
- return( ret );
- }
- }
-
-#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
- ret = ssl_write_split( ssl, buf, len );
-#else
- ret = ssl_write_real( ssl, buf, len );
-#endif
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) );
-
- return( ret );
-}
-
-/*
- * Notify the peer that the connection is being closed
- */
-int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl )
-{
- int ret;
-
- if( ssl == NULL || ssl->conf == NULL )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
-
- if( ssl->out_left != 0 )
- return( mbedtls_ssl_flush_output( ssl ) );
-
- if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
- {
- if( ( ret = mbedtls_ssl_send_alert_message( ssl,
- MBEDTLS_SSL_ALERT_LEVEL_WARNING,
- MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret );
- return( ret );
- }
- }
-
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) );
-
- return( 0 );
-}
-
-void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform )
-{
- if( transform == NULL )
- return;
-
-#if defined(MBEDTLS_ZLIB_SUPPORT)
- deflateEnd( &transform->ctx_deflate );
- inflateEnd( &transform->ctx_inflate );
-#endif
-
- mbedtls_cipher_free( &transform->cipher_ctx_enc );
- mbedtls_cipher_free( &transform->cipher_ctx_dec );
-
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
- mbedtls_md_free( &transform->md_ctx_enc );
- mbedtls_md_free( &transform->md_ctx_dec );
-#endif
-
- mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
-}
-
#if defined(MBEDTLS_X509_CRT_PARSE_C)
static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert )
{
@@ -11205,42 +5687,6 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert )
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-
-static void ssl_buffering_free( mbedtls_ssl_context *ssl )
-{
- unsigned offset;
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
-
- if( hs == NULL )
- return;
-
- ssl_free_buffered_record( ssl );
-
- for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ )
- ssl_buffering_free_slot( ssl, offset );
-}
-
-static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
- uint8_t slot )
-{
- mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot];
-
- if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS )
- return;
-
- if( hs_buf->is_valid == 1 )
- {
- hs->buffering.total_bytes_buffered -= hs_buf->data_len;
- mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len );
- mbedtls_free( hs_buf->data );
- memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) );
- }
-}
-
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
@@ -11342,8 +5788,8 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_PROTO_DTLS)
mbedtls_free( handshake->verify_cookie );
- ssl_flight_free( handshake->flight );
- ssl_buffering_free( ssl );
+ mbedtls_ssl_flight_free( handshake->flight );
+ mbedtls_ssl_buffering_free( ssl );
#endif
#if defined(MBEDTLS_ECDH_C) && \
@@ -11689,7 +6135,7 @@ int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used );
- return( ssl_session_reset_int( ssl, 0 ) );
+ return( mbedtls_ssl_session_reset_int( ssl, 0 ) );
}
/*
@@ -11727,7 +6173,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
const unsigned char *p = buf;
const unsigned char * const end = buf + len;
size_t session_len;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/*
* The context should have been freshly setup or reset.
@@ -11786,7 +6232,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
p += 4;
/* This has been allocated by ssl_handshake_init(), called by
- * by either ssl_session_reset_int() or mbedtls_ssl_setup(). */
+ * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */
ssl->session = ssl->session_negotiate;
ssl->session_in = ssl->session;
ssl->session_out = ssl->session;
@@ -11809,7 +6255,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
*/
/* This has been allocated by ssl_handshake_init(), called by
- * by either ssl_session_reset_int() or mbedtls_ssl_setup(). */
+ * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */
ssl->transform = ssl->transform_negotiate;
ssl->transform_in = ssl->transform;
ssl->transform_out = ssl->transform;
@@ -11970,7 +6416,7 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
/* Adjust pointers for header fields of outgoing records to
* the given transform, accounting for explicit IV and CID. */
- ssl_update_out_pointers( ssl, ssl->transform );
+ mbedtls_ssl_update_out_pointers( ssl, ssl->transform );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
ssl->in_epoch = 1;
@@ -11978,7 +6424,8 @@ static int ssl_context_load( mbedtls_ssl_context *ssl,
/* mbedtls_ssl_reset() leaves the handshake sub-structure allocated,
* which we don't want - otherwise we'd end up freeing the wrong transform
- * by calling ssl_handshake_wrapup_free_hs_transform() inappropriately. */
+ * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform()
+ * inappropriately. */
if( ssl->handshake != NULL )
{
mbedtls_ssl_handshake_free( ssl );
@@ -12148,7 +6595,7 @@ int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf,
int endpoint, int transport, int preset )
{
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#endif
/* Use the functions here so that they are covered in tests,
@@ -12636,59 +7083,6 @@ int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
-/*
- * Convert version numbers to/from wire format
- * and, for DTLS, to/from TLS equivalent.
- *
- * For TLS this is the identity.
- * For DTLS, use 1's complement (v -> 255 - v, and then map as follows:
- * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1)
- * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2)
- */
-void mbedtls_ssl_write_version( int major, int minor, int transport,
- unsigned char ver[2] )
-{
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- if( minor == MBEDTLS_SSL_MINOR_VERSION_2 )
- --minor; /* DTLS 1.0 stored as TLS 1.1 internally */
-
- ver[0] = (unsigned char)( 255 - ( major - 2 ) );
- ver[1] = (unsigned char)( 255 - ( minor - 1 ) );
- }
- else
-#else
- ((void) transport);
-#endif
- {
- ver[0] = (unsigned char) major;
- ver[1] = (unsigned char) minor;
- }
-}
-
-void mbedtls_ssl_read_version( int *major, int *minor, int transport,
- const unsigned char ver[2] )
-{
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- *major = 255 - ver[0] + 2;
- *minor = 255 - ver[1] + 1;
-
- if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 )
- ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */
- }
- else
-#else
- ((void) transport);
-#endif
- {
- *major = ver[0];
- *minor = ver[1];
- }
-}
-
int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md )
{
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
diff --git a/features/mbedtls/src/x509.c b/features/mbedtls/src/x509.c
index 2e0b0e8f6c..7f8181be27 100644
--- a/features/mbedtls/src/x509.c
+++ b/features/mbedtls/src/x509.c
@@ -39,6 +39,7 @@
#include "mbedtls/x509.h"
#include "mbedtls/asn1.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include
@@ -83,7 +84,7 @@
int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *serial )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( end - *p ) < 1 )
return( MBEDTLS_ERR_X509_INVALID_SERIAL +
@@ -114,7 +115,7 @@ int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end,
int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *alg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
@@ -128,7 +129,7 @@ int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end,
int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *alg, mbedtls_x509_buf *params )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_ALG + ret );
@@ -148,7 +149,7 @@ int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end,
*/
static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p;
const unsigned char *end;
mbedtls_x509_buf md_oid;
@@ -209,7 +210,7 @@ int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
int *salt_len )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p;
const unsigned char *end, *end2;
size_t len;
@@ -352,7 +353,7 @@ static int x509_get_attr_type_value( unsigned char **p,
const unsigned char *end,
mbedtls_x509_name *cur )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
mbedtls_x509_buf *oid;
mbedtls_x509_buf *val;
@@ -433,7 +434,7 @@ static int x509_get_attr_type_value( unsigned char **p,
int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end,
mbedtls_x509_name *cur )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t set_len;
const unsigned char *end_set;
@@ -539,7 +540,7 @@ static int x509_date_is_valid(const mbedtls_x509_time *t )
static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
mbedtls_x509_time *tm )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/*
* Minimum length is 10 or 12 depending on yearlen
@@ -604,7 +605,7 @@ static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen,
int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
mbedtls_x509_time *tm )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len, year_len;
unsigned char tag;
@@ -633,7 +634,7 @@ int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
int tag_type;
@@ -662,7 +663,7 @@ int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x50
mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
void **sig_opts )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( *sig_opts != NULL )
return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
@@ -710,7 +711,7 @@ int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x50
int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
mbedtls_x509_buf *ext, int tag )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
/* Extension structure use EXPLICIT tagging. That is, the actual
@@ -745,7 +746,7 @@ int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
*/
int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n;
unsigned char c, merge = 0;
const mbedtls_x509_name *name;
@@ -807,7 +808,7 @@ int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
*/
int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n, nr;
char *p;
@@ -843,7 +844,7 @@ int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *s
mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
const void *sig_opts )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
char *p = buf;
size_t n = size;
const char *desc = NULL;
@@ -888,7 +889,7 @@ int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name )
{
char *p = buf;
size_t n = buf_size;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_snprintf( p, n, "%s key size", name );
MBEDTLS_X509_SAFE_SNPRINTF;
diff --git a/features/mbedtls/src/x509_create.c b/features/mbedtls/src/x509_create.c
index 546e8fa1a9..7df2f0ed56 100644
--- a/features/mbedtls/src/x509_create.c
+++ b/features/mbedtls/src/x509_create.c
@@ -29,6 +29,7 @@
#include "mbedtls/x509.h"
#include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include
@@ -241,7 +242,7 @@ int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid,
*/
static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
const char *oid = (const char*)cur_name->oid.p;
size_t oid_len = cur_name->oid.len;
@@ -274,7 +275,7 @@ static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn
int mbedtls_x509_write_names( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
mbedtls_asn1_named_data *cur = first;
@@ -295,7 +296,7 @@ int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len,
unsigned char *sig, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if( *p < start || (size_t)( *p - start ) < size )
@@ -325,7 +326,7 @@ int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start,
static int x509_write_extension( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *ext )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1,
@@ -363,7 +364,7 @@ static int x509_write_extension( unsigned char **p, unsigned char *start,
int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start,
mbedtls_asn1_named_data *first )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
mbedtls_asn1_named_data *cur_ext = first;
diff --git a/features/mbedtls/src/x509_crl.c b/features/mbedtls/src/x509_crl.c
index 00f8545d7c..371c446be5 100644
--- a/features/mbedtls/src/x509_crl.c
+++ b/features/mbedtls/src/x509_crl.c
@@ -38,6 +38,7 @@
#if defined(MBEDTLS_X509_CRL_PARSE_C)
#include "mbedtls/x509_crl.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
@@ -74,7 +75,7 @@ static int x509_crl_get_version( unsigned char **p,
const unsigned char *end,
int *ver )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
{
@@ -101,7 +102,7 @@ static int x509_get_crl_ext( unsigned char **p,
const unsigned char *end,
mbedtls_x509_buf *ext )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( *p == end )
return( 0 );
@@ -181,7 +182,7 @@ static int x509_get_crl_entry_ext( unsigned char **p,
const unsigned char *end,
mbedtls_x509_buf *ext )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
/* OPTIONAL */
@@ -235,7 +236,7 @@ static int x509_get_entries( unsigned char **p,
const unsigned char *end,
mbedtls_x509_crl_entry *entry )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t entry_len;
mbedtls_x509_crl_entry *cur_entry = entry;
@@ -300,7 +301,7 @@ static int x509_get_entries( unsigned char **p,
int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
const unsigned char *buf, size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p = NULL, *end = NULL;
mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
@@ -539,8 +540,8 @@ int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain,
int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen )
{
#if defined(MBEDTLS_PEM_PARSE_C)
- int ret;
- size_t use_len;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t use_len = 0;
mbedtls_pem_context pem;
int is_pem = 0;
@@ -603,7 +604,7 @@ int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, s
*/
int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -630,7 +631,7 @@ int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path )
int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix,
const mbedtls_x509_crl *crl )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
char *p;
const mbedtls_x509_crl_entry *entry;
diff --git a/features/mbedtls/src/x509_crt.c b/features/mbedtls/src/x509_crt.c
index 48f244e2e8..1e472303b1 100644
--- a/features/mbedtls/src/x509_crt.c
+++ b/features/mbedtls/src/x509_crt.c
@@ -40,6 +40,7 @@
#if defined(MBEDTLS_X509_CRT_PARSE_C)
#include "mbedtls/x509_crt.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
@@ -390,7 +391,7 @@ static int x509_get_version( unsigned char **p,
const unsigned char *end,
int *ver )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -427,7 +428,7 @@ static int x509_get_dates( unsigned char **p,
mbedtls_x509_time *from,
mbedtls_x509_time *to )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
@@ -456,7 +457,7 @@ static int x509_get_uid( unsigned char **p,
const unsigned char *end,
mbedtls_x509_buf *uid, int n )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( *p == end )
return( 0 );
@@ -483,7 +484,7 @@ static int x509_get_basic_constraints( unsigned char **p,
int *ca_istrue,
int *max_pathlen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
/*
@@ -532,7 +533,7 @@ static int x509_get_ns_cert_type( unsigned char **p,
const unsigned char *end,
unsigned char *ns_cert_type)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_x509_bitstring bs = { 0, 0, NULL };
if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 )
@@ -551,7 +552,7 @@ static int x509_get_key_usage( unsigned char **p,
const unsigned char *end,
unsigned int *key_usage)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
mbedtls_x509_bitstring bs = { 0, 0, NULL };
@@ -581,7 +582,7 @@ static int x509_get_ext_key_usage( unsigned char **p,
const unsigned char *end,
mbedtls_x509_sequence *ext_key_usage)
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret );
@@ -625,7 +626,7 @@ static int x509_get_subject_alt_name( unsigned char **p,
const unsigned char *end,
mbedtls_x509_sequence *subject_alt_name )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len, tag_len;
mbedtls_asn1_buf *buf;
unsigned char tag;
@@ -887,7 +888,7 @@ static int x509_get_crt_ext( unsigned char **p,
const unsigned char *end,
mbedtls_x509_crt *crt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *end_ext_data, *end_ext_octet;
@@ -1056,7 +1057,7 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
size_t buflen,
int make_copy )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p, *end, *crt_end;
mbedtls_x509_buf sig_params1, sig_params2, sig_oid2;
@@ -1318,7 +1319,7 @@ static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
size_t buflen,
int make_copy )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_x509_crt *crt = chain, *prev = NULL;
/*
@@ -1415,7 +1416,7 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
#if defined(MBEDTLS_PEM_PARSE_C)
if( buf_format == MBEDTLS_X509_FORMAT_PEM )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_pem_context pem;
/* 1 rather than 0 since the terminating NULL byte is counted in */
@@ -1499,7 +1500,7 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain,
*/
int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -1737,7 +1738,7 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
*subject_alt_name,
const char *prefix )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n = *size;
char *p = *buf;
const mbedtls_x509_sequence *cur = subject_alt_name;
@@ -1848,7 +1849,7 @@ static int x509_info_subject_alt_name( char **buf, size_t *size,
int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
mbedtls_x509_subject_alternative_name *san )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
switch( san_buf->tag &
( MBEDTLS_ASN1_TAG_CLASS_MASK |
MBEDTLS_ASN1_TAG_VALUE_MASK ) )
@@ -1909,7 +1910,7 @@ int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf,
static int x509_info_cert_type( char **buf, size_t *size,
unsigned char ns_cert_type )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n = *size;
char *p = *buf;
const char *sep = "";
@@ -1936,7 +1937,7 @@ static int x509_info_cert_type( char **buf, size_t *size,
static int x509_info_key_usage( char **buf, size_t *size,
unsigned int key_usage )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n = *size;
char *p = *buf;
const char *sep = "";
@@ -1960,7 +1961,7 @@ static int x509_info_key_usage( char **buf, size_t *size,
static int x509_info_ext_key_usage( char **buf, size_t *size,
const mbedtls_x509_sequence *extended_key_usage )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const char *desc;
size_t n = *size;
char *p = *buf;
@@ -1989,7 +1990,7 @@ static int x509_info_ext_key_usage( char **buf, size_t *size,
static int x509_info_cert_policies( char **buf, size_t *size,
const mbedtls_x509_sequence *certificate_policies )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const char *desc;
size_t n = *size;
char *p = *buf;
@@ -2023,7 +2024,7 @@ static int x509_info_cert_policies( char **buf, size_t *size,
int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix,
const mbedtls_x509_crt *crt )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
char *p;
char key_size_str[BEFORE_COLON];
@@ -2195,7 +2196,7 @@ static const struct x509_crt_verify_string x509_crt_verify_strings[] = {
int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
uint32_t flags )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const struct x509_crt_verify_string *cur;
char *p = buf;
size_t n = size;
@@ -2535,9 +2536,9 @@ static int x509_crt_find_parent_in(
unsigned self_cnt,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_x509_crt *parent, *fallback_parent;
- int signature_is_good, fallback_signature_is_good;
+ int signature_is_good = 0, fallback_signature_is_good;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/* did we have something in progress? */
@@ -2658,7 +2659,7 @@ static int x509_crt_find_parent(
unsigned self_cnt,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_x509_crt *search_list;
*parent_is_trusted = 1;
@@ -2791,7 +2792,7 @@ static int x509_crt_verify_chain(
{
/* Don't initialize any of those variables here, so that the compiler can
* catch potential issues with jumping ahead when restarting */
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t *flags;
mbedtls_x509_crt_verify_chain_item *cur;
mbedtls_x509_crt *child;
@@ -3020,7 +3021,7 @@ static int x509_crt_merge_flags_with_cb(
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
void *p_vrfy )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned i;
uint32_t cur_flags;
const mbedtls_x509_crt_verify_chain_item *cur;
@@ -3068,7 +3069,7 @@ static int x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt,
void *p_vrfy,
mbedtls_x509_crt_restart_ctx *rs_ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_pk_type_t pk_type;
mbedtls_x509_crt_verify_chain ver_chain;
uint32_t ee_flags;
diff --git a/features/mbedtls/src/x509_csr.c b/features/mbedtls/src/x509_csr.c
index c8c08c87b2..7e2cfba2ae 100644
--- a/features/mbedtls/src/x509_csr.c
+++ b/features/mbedtls/src/x509_csr.c
@@ -38,6 +38,7 @@
#if defined(MBEDTLS_X509_CSR_PARSE_C)
#include "mbedtls/x509_csr.h"
+#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
@@ -68,7 +69,7 @@ static int x509_csr_get_version( unsigned char **p,
const unsigned char *end,
int *ver )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
{
@@ -90,7 +91,7 @@ static int x509_csr_get_version( unsigned char **p,
int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
const unsigned char *buf, size_t buflen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p, *end;
mbedtls_x509_buf sig_params;
@@ -262,7 +263,7 @@ int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr,
int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen )
{
#if defined(MBEDTLS_PEM_PARSE_C)
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t use_len;
mbedtls_pem_context pem;
#endif
@@ -312,7 +313,7 @@ int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, siz
*/
int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
@@ -336,7 +337,7 @@ int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path )
int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix,
const mbedtls_x509_csr *csr )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
char *p;
char key_size_str[BEFORE_COLON];
diff --git a/features/mbedtls/src/x509write_crt.c b/features/mbedtls/src/x509write_crt.c
index 03fb3fd945..5947e439de 100644
--- a/features/mbedtls/src/x509write_crt.c
+++ b/features/mbedtls/src/x509write_crt.c
@@ -34,10 +34,11 @@
#if defined(MBEDTLS_X509_CRT_WRITE_C)
#include "mbedtls/x509_crt.h"
-#include "mbedtls/oid.h"
#include "mbedtls/asn1write.h"
-#include "mbedtls/sha1.h"
+#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
+#include "mbedtls/sha1.h"
#include
@@ -45,16 +46,6 @@
#include "mbedtls/pem.h"
#endif /* MBEDTLS_PEM_WRITE_C */
-/*
- * For the currently used signature algorithms the buffer to store any signature
- * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
- */
-#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
-#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
-#else
-#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
-#endif
-
void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx )
{
memset( ctx, 0, sizeof( mbedtls_x509write_cert ) );
@@ -113,7 +104,7 @@ int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx,
int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx,
const mbedtls_mpi *serial )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 )
return( ret );
@@ -150,7 +141,7 @@ int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
int is_ca, int max_pathlen )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[9];
unsigned char *c = buf + sizeof(buf);
size_t len = 0;
@@ -184,7 +175,7 @@ int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx,
#if defined(MBEDTLS_SHA1_C)
int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
unsigned char *c = buf + sizeof(buf);
size_t len = 0;
@@ -212,7 +203,7 @@ int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ct
int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
unsigned char *c = buf + sizeof( buf );
size_t len = 0;
@@ -250,7 +241,7 @@ int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx,
{
unsigned char buf[5], ku[2];
unsigned char *c;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
MBEDTLS_X509_KU_NON_REPUDIATION |
MBEDTLS_X509_KU_KEY_ENCIPHERMENT |
@@ -289,7 +280,7 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
{
unsigned char buf[4];
unsigned char *c;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
c = buf + 4;
@@ -309,7 +300,7 @@ int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx,
static int x509_write_time( unsigned char **p, unsigned char *start,
const char *t, size_t size )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
/*
@@ -342,12 +333,12 @@ int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const char *sig_oid;
size_t sig_oid_len = 0;
unsigned char *c, *c2;
unsigned char hash[64];
- unsigned char sig[SIGNATURE_MAX_SIZE];
+ unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
size_t len = 0;
mbedtls_pk_type_t pk_alg;
@@ -536,7 +527,7 @@ int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen;
if( ( ret = mbedtls_x509write_crt_der( crt, buf, size,
diff --git a/features/mbedtls/src/x509write_csr.c b/features/mbedtls/src/x509write_csr.c
index 0d62d1d485..7c5179862c 100644
--- a/features/mbedtls/src/x509write_csr.c
+++ b/features/mbedtls/src/x509write_csr.c
@@ -33,8 +33,9 @@
#if defined(MBEDTLS_X509_CSR_WRITE_C)
#include "mbedtls/x509_csr.h"
-#include "mbedtls/oid.h"
#include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -49,16 +50,6 @@
#include "mbedtls/pem.h"
#endif
-/*
- * For the currently used signature algorithms the buffer to store any signature
- * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)
- */
-#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
-#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
-#else
-#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
-#endif
-
void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )
{
memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );
@@ -100,7 +91,7 @@ int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned ch
{
unsigned char buf[4];
unsigned char *c;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
c = buf + 4;
@@ -122,7 +113,7 @@ int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,
{
unsigned char buf[4];
unsigned char *c;
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
c = buf + 4;
@@ -143,12 +134,12 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const char *sig_oid;
size_t sig_oid_len = 0;
unsigned char *c, *c2;
unsigned char hash[64];
- unsigned char sig[SIGNATURE_MAX_SIZE];
+ unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
unsigned char tmp_buf[2048];
size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
size_t len = 0;
@@ -223,7 +214,9 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s
return( MBEDTLS_ERR_X509_FATAL_ERROR );
}
#else /* MBEDTLS_USE_PSA_CRYPTO */
- mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
+ ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );
+ if( ret != 0 )
+ return( ret );
#endif
if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,
f_rng, p_rng ) ) != 0 )
@@ -273,18 +266,17 @@ int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, s
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
- int ret;
- unsigned char output_buf[4096];
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen = 0;
- if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf),
+ if( ( ret = mbedtls_x509write_csr_der( ctx, buf, size,
f_rng, p_rng ) ) < 0 )
{
return( ret );
}
if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,
- output_buf + sizeof(output_buf) - ret,
+ buf + size - ret,
ret, buf, size, &olen ) ) != 0 )
{
return( ret );