Add integrity check for curve parameters
We don't really need a secure hash for that, something like CRC32 would
probably be enough - but we have SHA-256 handy, not CRC32, so use that for the
sake of simplicity.
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index fe9c594..ce348d9 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -110,6 +110,10 @@
#error "MBEDTLS_USE_TINYCRYPT defined, but it cannot be defined with MBEDTLS_NO_64BIT_MULTIPLICATION"
#endif
+#if defined(MBEDTLS_USE_TINYCRYPT) && !defined(MBEDTLS_SHA256_C)
+#error "MBEDTLS_USE_TINYCRYPT defined, but not MBEDTLS_SHA256_C"
+#endif
+
#if defined(MBEDTLS_USE_TINYCRYPT) && \
!( defined(MBEDTLS_SSL_CONF_SINGLE_EC) && \
MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID == 23 && \
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 87012da..dbb84b4 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -2649,6 +2649,7 @@
* MBEDTLS_SSL_CONF_SINGLE_EC
* MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID == 23
* MBEDTLS_SSL_CONF_SINGLE_UECC_GRP_ID == MBEDTLS_UECC_DP_SECP256R1
+ * MBEDTLS_SHA256_C
*
* \see MBEDTLS_SSL_CONF_RNG
*
diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c
index 62517df..381beff 100644
--- a/tinycrypt/ecc.c
+++ b/tinycrypt/ecc.c
@@ -66,6 +66,7 @@
#if defined(MBEDTLS_USE_TINYCRYPT)
#include <tinycrypt/ecc.h>
#include "mbedtls/platform_util.h"
+#include "mbedtls/sha256.h"
#include <string.h>
/* Parameters for curve NIST P-256 aka secp256r1 */
@@ -98,6 +99,73 @@
BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
};
+static int uECC_update_param_sha256(mbedtls_sha256_context *ctx,
+ const uECC_word_t val[NUM_ECC_WORDS])
+{
+ uint8_t bytes[NUM_ECC_BYTES];
+
+ uECC_vli_nativeToBytes(bytes, NUM_ECC_BYTES, val);
+ return mbedtls_sha256_update_ret(ctx, bytes, NUM_ECC_BYTES);
+}
+
+static int uECC_compute_param_sha256(unsigned char output[32])
+{
+ int ret = UECC_FAILURE;
+ mbedtls_sha256_context ctx;
+
+ mbedtls_sha256_init( &ctx );
+
+ if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) {
+ goto exit;
+ }
+
+ if (uECC_update_param_sha256(&ctx, curve_p) != 0 ||
+ uECC_update_param_sha256(&ctx, curve_n) != 0 ||
+ uECC_update_param_sha256(&ctx, curve_G) != 0 ||
+ uECC_update_param_sha256(&ctx, curve_G + NUM_ECC_WORDS) != 0 ||
+ uECC_update_param_sha256(&ctx, curve_b) != 0)
+ {
+ goto exit;
+ }
+
+ if (mbedtls_sha256_finish_ret(&ctx, output) != 0) {
+ goto exit;
+ }
+
+ ret = UECC_SUCCESS;
+
+exit:
+ mbedtls_sha256_free( &ctx );
+
+ return ret;
+}
+
+/*
+ * Check integrity of curve parameters.
+ * Return 0 if everything's OK, non-zero otherwise.
+ */
+static int uECC_check_curve_integrity(void)
+{
+ unsigned char computed[32];
+ unsigned char reference[32] = {
+ 0x2d, 0xa1, 0xa4, 0x64, 0x45, 0x28, 0x0d, 0xe1,
+ 0x93, 0xf9, 0x29, 0x2f, 0xac, 0x3e, 0xe2, 0x92,
+ 0x76, 0x0a, 0xe2, 0xbc, 0xce, 0x2a, 0xa2, 0xc6,
+ 0x38, 0xf2, 0x19, 0x1d, 0x76, 0x72, 0x93, 0x49,
+ };
+ volatile unsigned char diff = 0;
+ unsigned char i;
+
+ if (uECC_compute_param_sha256(computed) != UECC_SUCCESS) {
+ return UECC_FAILURE;
+ }
+
+ for (i = 0; i < 32; i++)
+ diff |= computed[i] ^ reference[i];
+
+ return diff;
+}
+
/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
* has access to enough entropy in order to feed the PRNG regularly. */
#if default_RNG_defined
@@ -955,6 +1023,11 @@
uECC_word_t *initial_Z = 0;
int r;
+ /* Protect against faults modifying curve paremeters in flash */
+ if (uECC_check_curve_integrity() != 0) {
+ return 0;
+ }
+
/* Protects against invalid curves attacks */
if (uECC_valid_point(point) != 0 ) {
return 0;
@@ -983,6 +1056,12 @@
goto clear_and_out;
}
+ /* Protect against faults modifying curve paremeters in flash */
+ if (uECC_check_curve_integrity() != 0) {
+ r = 0;
+ goto clear_and_out;
+ }
+
r = 1;
clear_and_out: