Bootutil/Crypto: add encryption with mbedTLS

Signed-off-by: Bohdan Kovalchuk <bohd@cypress.com>
Signed-off-by: Roman Okhrimenko <roman.okhrimenko@infineon.com>
diff --git a/boot/bootutil/include/bootutil/crypto/ecdh_p256.h b/boot/bootutil/include/bootutil/crypto/ecdh_p256.h
index 19d6a06..a37d50a 100644
--- a/boot/bootutil/include/bootutil/crypto/ecdh_p256.h
+++ b/boot/bootutil/include/bootutil/crypto/ecdh_p256.h
@@ -12,10 +12,17 @@
 
 #include "mcuboot_config/mcuboot_config.h"
 
-#if (defined(MCUBOOT_USE_TINYCRYPT)) != 1
-    #error "One crypto backend must be defined: TINYCRYPT"
+#if (defined(MCUBOOT_USE_MBED_TLS) + \
+     defined(MCUBOOT_USE_TINYCRYPT)) != 1
+    #error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT"
 #endif
 
+#if defined(MCUBOOT_USE_MBED_TLS)
+    #include <mbedtls/ecp.h>
+    #include <mbedtls/ecdh.h>
+    #define EC256_PUBK_LEN (65)
+#endif /* MCUBOOT_USE_MBED_TLS */
+
 #if defined(MCUBOOT_USE_TINYCRYPT)
     #include <tinycrypt/ecc_dh.h>
     #include <tinycrypt/constants.h>
@@ -43,12 +50,16 @@
     int rc;
     (void)ctx;
 
-    rc = uECC_valid_public_key(pk, uECC_secp256r1());
+    if (pk[0] != 0x04) {
+        return -1;
+    }
+
+    rc = uECC_valid_public_key(&pk[1], uECC_secp256r1());
     if (rc != 0) {
         return -1;
     }
 
-    rc = uECC_shared_secret(pk, sk, z, uECC_secp256r1());
+    rc = uECC_shared_secret(&pk[1], sk, z, uECC_secp256r1());
     if (rc != TC_CRYPTO_SUCCESS) {
         return -1;
     }
@@ -56,6 +67,72 @@
 }
 #endif /* MCUBOOT_USE_TINYCRYPT */
 
+#if defined(MCUBOOT_USE_MBED_TLS)
+typedef struct bootutil_ecdh_p256_context {
+    mbedtls_ecp_group grp;
+    mbedtls_ecp_point P;
+    mbedtls_mpi z;
+    mbedtls_mpi d;
+} bootutil_ecdh_p256_context;
+
+static inline void bootutil_ecdh_p256_init(bootutil_ecdh_p256_context *ctx)
+{
+    mbedtls_mpi_init(&ctx->z);
+    mbedtls_mpi_init(&ctx->d);
+
+    mbedtls_ecp_group_init(&ctx->grp);
+    mbedtls_ecp_point_init(&ctx->P);
+
+    if (mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1) != 0) {
+        mbedtls_ecp_group_free(&ctx->grp);
+        mbedtls_ecp_point_free(&ctx->P);
+    }
+}
+
+static inline void bootutil_ecdh_p256_drop(bootutil_ecdh_p256_context *ctx)
+{
+    mbedtls_mpi_free(&ctx->d);
+    mbedtls_mpi_free(&ctx->z);
+    mbedtls_ecp_group_free(&ctx->grp);
+    mbedtls_ecp_point_free(&ctx->P);
+}
+
+static inline int bootutil_ecdh_p256_shared_secret(bootutil_ecdh_p256_context *ctx, const uint8_t *pk, const uint8_t *sk, uint8_t *z)
+{
+    int rc;
+
+    rc = mbedtls_ecp_point_read_binary(&ctx->grp,
+                                       &ctx->P,
+                                       pk,
+                                       EC256_PUBK_LEN);
+    if (rc != 0) {
+        mbedtls_ecp_group_free(&ctx->grp);
+        mbedtls_ecp_point_free(&ctx->P);
+        return -1;
+    }
+
+    rc = mbedtls_ecp_check_pubkey(&ctx->grp, &ctx->P);
+    if (rc != 0) {
+        mbedtls_ecp_group_free(&ctx->grp);
+        mbedtls_ecp_point_free(&ctx->P);
+        return -1;
+    }
+
+    mbedtls_mpi_read_binary(&ctx->d, sk, NUM_ECC_BYTES);
+
+    rc = mbedtls_ecdh_compute_shared(&ctx->grp,
+                                     &ctx->z,
+                                     &ctx->P,
+                                     &ctx->d,
+                                     NULL,
+                                     NULL);
+
+    mbedtls_mpi_write_binary(&ctx->z, z, NUM_ECC_BYTES);
+
+    return rc;
+}
+#endif /* MCUBOOT_USE_MBED_TLS */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/boot/bootutil/include/bootutil/crypto/hmac_sha256.h b/boot/bootutil/include/bootutil/crypto/hmac_sha256.h
index c834124..49d372a 100644
--- a/boot/bootutil/include/bootutil/crypto/hmac_sha256.h
+++ b/boot/bootutil/include/bootutil/crypto/hmac_sha256.h
@@ -12,10 +12,19 @@
 
 #include "mcuboot_config/mcuboot_config.h"
 
-#if (defined(MCUBOOT_USE_TINYCRYPT)) != 1
-    #error "One crypto backend must be defined: TINYCRYPT"
+#if (defined(MCUBOOT_USE_MBED_TLS) + \
+     defined(MCUBOOT_USE_TINYCRYPT)) != 1
+    #error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT"
 #endif
 
+#if defined(MCUBOOT_USE_MBED_TLS)
+    #include <stdint.h>
+    #include <stddef.h>
+    #include <mbedtls/cmac.h>
+    #include <mbedtls/md.h>
+    #include <mbedtls/md_internal.h>
+#endif /* MCUBOOT_USE_MBED_TLS */
+
 #if defined(MCUBOOT_USE_TINYCRYPT)
     #include <tinycrypt/sha256.h>
     #include <tinycrypt/utils.h>
@@ -76,6 +85,49 @@
 }
 #endif /* MCUBOOT_USE_TINYCRYPT */
 
+#if defined(MCUBOOT_USE_MBED_TLS)
+/**
+ * The generic message-digest context.
+ */
+typedef mbedtls_md_context_t bootutil_hmac_sha256_context;
+
+static inline void bootutil_hmac_sha256_init(bootutil_hmac_sha256_context *ctx)
+{
+    mbedtls_md_init(ctx);
+}
+
+static inline void bootutil_hmac_sha256_drop(bootutil_hmac_sha256_context *ctx)
+{
+    mbedtls_md_free(ctx);
+}
+
+static inline int bootutil_hmac_sha256_set_key(bootutil_hmac_sha256_context *ctx, const uint8_t *key, unsigned int key_size)
+{
+    int rc;
+
+    rc = mbedtls_md_setup(ctx, mbedtls_md_info_from_string("SHA256"), 1);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = mbedtls_md_hmac_starts(ctx, key, key_size);
+    return rc;
+}
+
+static inline int bootutil_hmac_sha256_update(bootutil_hmac_sha256_context *ctx, const void *data, unsigned int data_length)
+{
+    return mbedtls_md_hmac_update(ctx, data, data_length);
+}
+
+static inline int bootutil_hmac_sha256_finish(bootutil_hmac_sha256_context *ctx, uint8_t *tag, unsigned int taglen)
+{
+    (void)taglen;
+    /*
+     * HMAC the key and check that our received MAC matches the generated tag
+     */
+    return mbedtls_md_hmac_finish(ctx, tag);
+}
+#endif /* MCUBOOT_USE_MBED_TLS */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c
index aff2d45..d14855b 100644
--- a/boot/bootutil/src/encrypted.c
+++ b/boot/bootutil/src/encrypted.c
@@ -437,7 +437,7 @@
 #    define EXPECTED_ENC_TLV    IMAGE_TLV_ENC_KW128
 #elif defined(MCUBOOT_ENCRYPT_EC256)
 #    define EXPECTED_ENC_TLV    IMAGE_TLV_ENC_EC256
-#    define EC_PUBK_INDEX       (1)
+#    define EC_PUBK_INDEX       (0)
 #    define EC_TAG_INDEX        (65)
 #    define EC_CIPHERKEY_INDEX  (65 + 32)
 _Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
@@ -526,11 +526,6 @@
         return rc;
     }
 
-    /* is EC point uncompressed? */
-    if (buf[0] != 0x04) {
-        return -1;
-    }
-
     /*
      * First "element" in the TLV is the curve point (public key)
      */
@@ -603,7 +598,7 @@
         return -1;
     }
 
-    /* Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes */
+    /* Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes */
     rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
     if (rc != 0) {
         (void)bootutil_hmac_sha256_drop(&hmac);