Abstracting mcuboot crypto functions for cleaner porting and less of an ifdef hell.

- The enc_context needs to initialize.

boot_enc_load seems to always be used to start the process, so calling
init inside makes sense.

- Handle boot_encrypt getting called with size of 0.

- No need to free contexts because Zephyr sets MBEDTLS_PLATFORM_NO_STD_FUNCTIONS.

I don't quite like this because it's implicit and will leak memory on
other ports.

Signed-off-by: Blaž Hrastnik <blaz@mxxn.io>
diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c
index b62a31e..aff2d45 100644
--- a/boot/bootutil/src/encrypted.c
+++ b/boot/bootutil/src/encrypted.c
@@ -19,24 +19,20 @@
 #endif
 
 #if defined(MCUBOOT_ENCRYPT_KW)
-#  if defined(MCUBOOT_USE_MBED_TLS)
-#    include "mbedtls/nist_kw.h"
-#    include "mbedtls/aes.h"
-#  else
-#    include "tinycrypt/aes.h"
-#  endif
+#include "bootutil/crypto/aes_kw.h"
 #endif
 
 #if defined(MCUBOOT_ENCRYPT_EC256)
-#include "tinycrypt/ecc.h"
-#include "tinycrypt/ecc_dh.h"
+#include "bootutil/crypto/ecdh_p256.h"
+#endif
+
+#if defined(MCUBOOT_ENCRYPT_X25519)
+#include "bootutil/crypto/ecdh_x25519.h"
 #endif
 
 #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
-#include "tinycrypt/utils.h"
-#include "tinycrypt/constants.h"
-#include "tinycrypt/ctr_mode.h"
-#include "tinycrypt/hmac.h"
+#include "bootutil/crypto/sha256.h"
+#include "bootutil/crypto/hmac_sha256.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/asn1.h"
 #endif
@@ -47,79 +43,49 @@
 
 #include "bootutil_priv.h"
 
+#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
+#if defined(_compare)
+static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
+{
+    return _compare(a, b, size);
+}
+#else
+static int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
+{
+    const uint8_t *tempa = a;
+    const uint8_t *tempb = b;
+    uint8_t result = 0;
+    unsigned int i;
+
+    for (i = 0; i < size; i++) {
+        result |= tempa[i] ^ tempb[i];
+    }
+    return result;
+}
+#endif
+#endif
+
 #if defined(MCUBOOT_ENCRYPT_KW)
-#if defined(MCUBOOT_USE_MBED_TLS)
 static int
 key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
 {
-    mbedtls_nist_kw_context kw;
+    bootutil_aes_kw_context aes_kw;
     int rc;
-    size_t olen;
 
-    mbedtls_nist_kw_init(&kw);
-
-    rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES,
-            bootutil_enc_key.key, *bootutil_enc_key.len * 8, 0);
-    if (rc) {
+    bootutil_aes_kw_init(&aes_kw);
+    rc = bootutil_aes_kw_set_unwrap_key(&aes_kw, bootutil_enc_key.key, *bootutil_enc_key.len);
+    if (rc != 0) {
+        goto done;
+    }
+    rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE);
+    if (rc != 0) {
         goto done;
     }
 
-    rc = mbedtls_nist_kw_unwrap(&kw, MBEDTLS_KW_MODE_KW, wrapped, TLV_ENC_KW_SZ,
-            enckey, &olen, BOOT_ENC_KEY_SIZE);
-
 done:
-    mbedtls_nist_kw_free(&kw);
+    bootutil_aes_kw_drop(&aes_kw);
     return rc;
 }
-#else /* !MCUBOOT_USE_MBED_TLS */
-/*
- * Implements AES key unwrapping following RFC-3394 section 2.2.2, using
- * tinycrypt for AES-128 decryption.
- */
-static int
-key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
-{
-    struct tc_aes_key_sched_struct aes;
-    uint8_t A[8];
-    uint8_t B[16];
-    int8_t i, j, k;
-
-    if (tc_aes128_set_decrypt_key(&aes, bootutil_enc_key.key) == 0) {
-        return -1;
-    }
-
-    for (k = 0; k < 8; k++) {
-        A[k]          = wrapped[k];
-        enckey[k]     = wrapped[8 + k];
-        enckey[8 + k] = wrapped[16 + k];
-    }
-
-    for (j = 5; j >= 0; j--) {
-        for (i = 2; i > 0; i--) {
-            for (k = 0; k < 8; k++) {
-                B[k] = A[k];
-                B[8 + k] = enckey[((i-1) * 8) + k];
-            }
-            B[7] ^= 2 * j + i;
-            if (tc_aes_decrypt((uint8_t *)&B, (uint8_t *)&B, &aes) == 0) {
-                return -1;
-            }
-            for (k = 0; k < 8; k++) {
-                A[k] = B[k];
-                enckey[((i-1) * 8) + k] = B[8 + k];
-            }
-        }
-    }
-
-    for (i = 0, k = 0; i < 8; i++) {
-        k |= A[i] ^ 0xa6;
-    }
-    if (k) {
-        return -1;
-    }
-    return 0;
-}
-#endif /* MCUBOOT_USE_MBED_TLS */
 #endif /* MCUBOOT_ENCRYPT_KW */
 
 #if defined(MCUBOOT_ENCRYPT_RSA)
@@ -198,7 +164,7 @@
  * curve keypair. See RFC5208 and RFC5915.
  */
 static int
-parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *pk)
+parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
 {
     int rc;
     size_t len;
@@ -259,7 +225,7 @@
         return -12;
     }
 
-    memcpy(pk, *p, len);
+    memcpy(private_key, *p, len);
 
     /* publicKey usually follows but is not parsed here */
 
@@ -272,14 +238,11 @@
 static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
                                        MBEDTLS_OID_ORG_GOV X25519_OID;
 
-extern int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
-                  const uint8_t peer_public_value[32]);
-
 #define SHARED_KEY_LEN 32
 #define PRIV_KEY_LEN   32
 
 static int
-parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *pk)
+parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
 {
     size_t len;
     int version;
@@ -321,7 +284,7 @@
         return -8;
     }
 
-    memcpy(pk, *p, PRIV_KEY_LEN);
+    memcpy(private_key, *p, PRIV_KEY_LEN);
     return 0;
 }
 #endif /* defined(MCUBOOT_ENCRYPT_X25519) */
@@ -341,10 +304,10 @@
 hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len,
         uint8_t *okm, uint16_t *okm_len)
 {
-    struct tc_hmac_state_struct hmac;
-    uint8_t salt[TC_SHA256_DIGEST_SIZE];
-    uint8_t prk[TC_SHA256_DIGEST_SIZE];
-    uint8_t T[TC_SHA256_DIGEST_SIZE];
+    bootutil_hmac_sha256_context hmac;
+    uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
+    uint8_t prk[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
+    uint8_t T[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
     uint16_t off;
     uint16_t len;
     uint8_t counter;
@@ -359,25 +322,22 @@
         return -1;
     }
 
-    memset(salt, 0, TC_SHA256_DIGEST_SIZE);
-    rc = tc_hmac_set_key(&hmac, salt, TC_SHA256_DIGEST_SIZE);
-    if (rc != TC_CRYPTO_SUCCESS) {
-        return -1;
+    bootutil_hmac_sha256_init(&hmac);
+
+    memset(salt, 0, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+    rc = bootutil_hmac_sha256_set_key(&hmac, salt, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+    if (rc != 0) {
+        goto error;
     }
 
-    rc = tc_hmac_init(&hmac);
-    if (rc != TC_CRYPTO_SUCCESS) {
-        return -1;
+    rc = bootutil_hmac_sha256_update(&hmac, ikm, ikm_len);
+    if (rc != 0) {
+        goto error;
     }
 
-    rc = tc_hmac_update(&hmac, ikm, ikm_len);
-    if (rc != TC_CRYPTO_SUCCESS) {
-        return -1;
-    }
-
-    rc = tc_hmac_final(prk, TC_SHA256_DIGEST_SIZE, &hmac);
-    if (rc != TC_CRYPTO_SUCCESS) {
-        return -1;
+    rc = bootutil_hmac_sha256_finish(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+    if (rc != 0) {
+        goto error;
     }
 
     /*
@@ -387,74 +347,82 @@
     len = *okm_len;
     counter = 1;
     first = true;
-    for (off = 0; len > 0; off += TC_SHA256_DIGEST_SIZE, ++counter) {
-        rc = tc_hmac_set_key(&hmac, prk, TC_SHA256_DIGEST_SIZE);
-        if (rc != TC_CRYPTO_SUCCESS) {
-            return -1;
-        }
+    for (off = 0; len > 0; off += BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, ++counter) {
+        bootutil_hmac_sha256_init(&hmac);
 
-        rc = tc_hmac_init(&hmac);
-        if (rc != TC_CRYPTO_SUCCESS) {
-            return -1;
+        rc = bootutil_hmac_sha256_set_key(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+        if (rc != 0) {
+            goto error;
         }
 
         if (first) {
             first = false;
         } else {
-            rc = tc_hmac_update(&hmac, T, TC_SHA256_DIGEST_SIZE);
-            if (rc != TC_CRYPTO_SUCCESS) {
-                return -1;
+            rc = bootutil_hmac_sha256_update(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+            if (rc != 0) {
+                goto error;
             }
         }
 
-        rc = tc_hmac_update(&hmac, info, info_len);
-        if (rc != TC_CRYPTO_SUCCESS) {
-            return -1;
+        rc = bootutil_hmac_sha256_update(&hmac, info, info_len);
+        if (rc != 0) {
+            goto error;
         }
 
-        rc = tc_hmac_update(&hmac, &counter, 1);
-        if (rc != TC_CRYPTO_SUCCESS) {
-            return -1;
+        rc = bootutil_hmac_sha256_update(&hmac, &counter, 1);
+        if (rc != 0) {
+            goto error;
         }
 
-        rc = tc_hmac_final(T, TC_SHA256_DIGEST_SIZE, &hmac);
-        if (rc != TC_CRYPTO_SUCCESS) {
-            return -1;
+        rc = bootutil_hmac_sha256_finish(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+        if (rc != 0) {
+            goto error;
         }
 
-        if (len > TC_SHA256_DIGEST_SIZE) {
-            memcpy(&okm[off], T, TC_SHA256_DIGEST_SIZE);
-            len -= TC_SHA256_DIGEST_SIZE;
+        if (len > BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) {
+            memcpy(&okm[off], T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+            len -= BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
         } else {
             memcpy(&okm[off], T, len);
             len = 0;
         }
     }
 
+    bootutil_hmac_sha256_drop(&hmac);
     return 0;
+
+error:
+    bootutil_hmac_sha256_drop(&hmac);
+    return -1;
 }
 #endif
 
 int
+boot_enc_init(struct enc_key_data *enc_state, uint8_t slot)
+{
+    bootutil_aes_ctr_init(&enc_state[slot].aes_ctr);
+    return 0;
+}
+
+int
+boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot)
+{
+    bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr);
+    return 0;
+}
+
+int
 boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
         const struct boot_status *bs)
 {
     int rc;
 
-#if defined(MCUBOOT_USE_MBED_TLS)
-    mbedtls_aes_init(&enc_state[slot].aes);
-    rc = mbedtls_aes_setkey_enc(&enc_state[slot].aes, bs->enckey[slot],
-            BOOT_ENC_KEY_SIZE_BITS);
-    if (rc) {
-        mbedtls_aes_free(&enc_state[slot].aes);
+    rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]);
+    if (rc != 0) {
+        boot_enc_drop(enc_state, slot);
+        enc_state[slot].valid = 0;
         return -1;
     }
-#else
-    (void)rc;
-
-    /* set_encrypt and set_decrypt do the same thing in tinycrypt */
-    tc_aes128_set_encrypt_key(&enc_state[slot].aes, bs->enckey[slot]);
-#endif
 
     enc_state[slot].valid = 1;
 
@@ -498,16 +466,22 @@
     uint8_t *cpend;
     size_t olen;
 #endif
+#if defined(MCUBOOT_ENCRYPT_EC256)
+    bootutil_ecdh_p256_context ecdh_p256;
+#endif
+#if defined(MCUBOOT_ENCRYPT_X25519)
+    bootutil_ecdh_x25519_context ecdh_x25519;
+#endif
 #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
-    struct tc_hmac_state_struct hmac;
-    struct tc_aes_key_sched_struct aes;
-    uint8_t tag[TC_SHA256_DIGEST_SIZE];
+    bootutil_hmac_sha256_context hmac;
+    bootutil_aes_ctr_context aes_ctr;
+    uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
     uint8_t shared[SHARED_KEY_LEN];
-    uint8_t derived_key[TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE];
+    uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
     uint8_t *cp;
     uint8_t *cpend;
-    uint8_t pk[PRIV_KEY_LEN];
-    uint8_t counter[TC_AES_BLOCK_SIZE];
+    uint8_t private_key[PRIV_KEY_LEN];
+    uint8_t counter[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
     uint16_t len;
 #endif
     int rc = -1;
@@ -547,7 +521,7 @@
      * Load the stored EC256 decryption private key
      */
 
-    rc = parse_ec256_enckey(&cp, cpend, pk);
+    rc = parse_ec256_enckey(&cp, cpend, private_key);
     if (rc) {
         return rc;
     }
@@ -560,13 +534,11 @@
     /*
      * First "element" in the TLV is the curve point (public key)
      */
-    rc = uECC_valid_public_key(&buf[EC_PUBK_INDEX], uECC_secp256r1());
-    if (rc != 0) {
-        return -1;
-    }
+    bootutil_ecdh_p256_init(&ecdh_p256);
 
-    rc = uECC_shared_secret(&buf[EC_PUBK_INDEX], pk, shared, uECC_secp256r1());
-    if (rc != TC_CRYPTO_SUCCESS) {
+    rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared);
+    bootutil_ecdh_p256_drop(&ecdh_p256);
+    if (rc != 0) {
         return -1;
     }
 
@@ -581,7 +553,7 @@
      * Load the stored X25519 decryption private key
      */
 
-    rc = parse_x25519_enckey(&cp, cpend, pk);
+    rc = parse_x25519_enckey(&cp, cpend, private_key);
     if (rc) {
         return rc;
     }
@@ -590,7 +562,10 @@
      * First "element" in the TLV is the curve point (public key)
      */
 
-    rc = X25519(shared, pk, &buf[EC_PUBK_INDEX]);
+    bootutil_ecdh_x25519_init(&ecdh_x25519);
+
+    rc = bootutil_ecdh_x25519_shared_secret(&ecdh_x25519, &buf[EC_PUBK_INDEX], private_key, shared);
+    bootutil_ecdh_x25519_drop(&ecdh_x25519);
     if (!rc) {
         return -1;
     }
@@ -603,10 +578,10 @@
      * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
      */
 
-    len = TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE;
+    len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
     rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
             derived_key, &len);
-    if (rc != 0 || len != (TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE)) {
+    if (rc != 0 || len != (BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)) {
         return -1;
     }
 
@@ -614,47 +589,59 @@
      * HMAC the key and check that our received MAC matches the generated tag
      */
 
-    rc = tc_hmac_set_key(&hmac, &derived_key[16], 32);
-    if (rc != TC_CRYPTO_SUCCESS) {
+    bootutil_hmac_sha256_init(&hmac);
+
+    rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[16], 32);
+    if (rc != 0) {
+        (void)bootutil_hmac_sha256_drop(&hmac);
         return -1;
     }
 
-    rc = tc_hmac_init(&hmac);
-    if (rc != TC_CRYPTO_SUCCESS) {
-        return -1;
-    }
-
-    rc = tc_hmac_update(&hmac, &buf[EC_CIPHERKEY_INDEX], 16);
-    if (rc != TC_CRYPTO_SUCCESS) {
+    rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], 16);
+    if (rc != 0) {
+        (void)bootutil_hmac_sha256_drop(&hmac);
         return -1;
     }
 
     /* Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes */
-    rc = tc_hmac_final(tag, TC_SHA256_DIGEST_SIZE, &hmac);
-    if (rc != TC_CRYPTO_SUCCESS) {
+    rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
+    if (rc != 0) {
+        (void)bootutil_hmac_sha256_drop(&hmac);
         return -1;
     }
 
-    if (_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
+    if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
+        (void)bootutil_hmac_sha256_drop(&hmac);
         return -1;
     }
 
+    bootutil_hmac_sha256_drop(&hmac);
+
     /*
      * Finally decrypt the received ciphered key
      */
 
-    rc = tc_aes128_set_decrypt_key(&aes, derived_key);
-    if (rc != TC_CRYPTO_SUCCESS) {
+    bootutil_aes_ctr_init(&aes_ctr);
+    if (rc != 0) {
+        bootutil_aes_ctr_drop(&aes_ctr);
         return -1;
     }
 
-    memset(counter, 0, TC_AES_BLOCK_SIZE);
-    rc = tc_ctr_mode(enckey, TC_AES_KEY_SIZE, &buf[EC_CIPHERKEY_INDEX],
-            TC_AES_KEY_SIZE, counter, &aes);
-    if (rc != TC_CRYPTO_SUCCESS) {
+    rc = bootutil_aes_ctr_set_key(&aes_ctr, derived_key);
+    if (rc != 0) {
+        bootutil_aes_ctr_drop(&aes_ctr);
         return -1;
     }
 
+    memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
+    rc = bootutil_aes_ctr_decrypt(&aes_ctr, counter, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, 0, enckey);
+    if (rc != 0) {
+        bootutil_aes_ctr_drop(&aes_ctr);
+        return -1;
+    }
+
+    bootutil_aes_ctr_drop(&aes_ctr);
+
     rc = 0;
 
 #endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
@@ -692,6 +679,9 @@
         return 1;
     }
 
+    /* Initialize the AES context */
+    boot_enc_init(enc_state, slot);
+
     rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
     if (rc) {
         return -1;
@@ -741,12 +731,15 @@
         uint32_t blk_off, uint8_t *buf)
 {
     struct enc_key_data *enc;
-    uint32_t i, j;
-    uint8_t u8;
     uint8_t nonce[16];
-    uint8_t blk[16];
     int rc;
 
+    /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over
+       the TLVs. */
+    if (sz == 0) {
+       return;
+    }
+
     memset(nonce, 0, 12);
     off >>= 4;
     nonce[12] = (uint8_t)(off >> 24);
@@ -762,25 +755,7 @@
 
     enc = &enc_state[rc];
     assert(enc->valid == 1);
-    for (i = 0; i < sz; i++) {
-        if (i == 0 || blk_off == 0) {
-#if defined(MCUBOOT_USE_MBED_TLS)
-            mbedtls_aes_crypt_ecb(&enc->aes, MBEDTLS_AES_ENCRYPT, nonce, blk);
-#else
-            tc_aes_encrypt(blk, nonce, &enc->aes);
-#endif
-
-            for (j = 16; j > 0; --j) {
-                if (++nonce[j - 1] != 0) {
-                    break;
-                }
-            }
-        }
-
-        u8 = *buf;
-        *buf++ = u8 ^ blk[blk_off];
-        blk_off = (blk_off + 1) & 0x0f;
-    }
+    bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf);
 }
 
 /**
@@ -789,6 +764,10 @@
 void
 boot_enc_zeroize(struct enc_key_data *enc_state)
 {
+    uint8_t slot;
+    for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
+        (void)boot_enc_drop(enc_state, slot);
+    }
     memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
 }