Add key unwrap functionality using tinycrypt

This implements AES key unwrapping following RFC-3394 section 2.2.2
using tinycrypt for AES-128 decryption. It is enabled when ECDSA was
chosen as the signature algorithm.

Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/boot/bootutil/src/encrypted.c b/boot/bootutil/src/encrypted.c
index 5cf2603..fa502fe 100644
--- a/boot/bootutil/src/encrypted.c
+++ b/boot/bootutil/src/encrypted.c
@@ -24,6 +24,7 @@
 #include <stddef.h>
 #include <inttypes.h>
 #include <string.h>
+#include <stdio.h>
 
 #include "hal/hal_flash.h"
 
@@ -33,10 +34,14 @@
 #endif
 
 #if defined(MCUBOOT_ENCRYPT_KW)
-#include "mbedtls/nist_kw.h"
+#  if defined(MCUBOOT_USE_MBED_TLS)
+#    include "mbedtls/nist_kw.h"
+#    include "mbedtls/aes.h"
+#  else
+#    include "tinycrypt/aes.h"
+#  endif
 #endif
 
-#include "mbedtls/aes.h"
 
 #include "bootutil/image.h"
 #include "bootutil/enc_key.h"
@@ -49,6 +54,81 @@
 #define TLV_ENC_RSA_SZ  256
 #define TLV_ENC_KW_SZ   24
 
+#if defined(MCUBOOT_ENCRYPT_KW)
+#if defined(MCUBOOT_USE_MBED_TLS)
+int
+key_unwrap(uint8_t *wrapped, uint8_t *enckey)
+{
+    mbedtls_nist_kw_context 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) {
+        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);
+    return rc;
+}
+#else /* !MCUBOOT_USE_MBED_TLS */
+/*
+ * Implements AES key unwrapping following RFC-3394 section 2.2.2, using
+ * tinycrypt for AES-128 decryption.
+ */
+int
+key_unwrap(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)
 static int
 parse_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
@@ -104,12 +184,19 @@
 {
     int rc;
 
+#if defined(MCUBOOT_USE_MBED_TLS)
     mbedtls_aes_init(&enc_state[slot].aes);
     rc = mbedtls_aes_setkey_enc(&enc_state[slot].aes, enckey, BOOT_ENC_KEY_SIZE_BITS);
     if (rc) {
         mbedtls_aes_free(&enc_state[slot].aes);
         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, enckey);
+#endif
 
     enc_state[slot].valid = 1;
 
@@ -135,11 +222,8 @@
     mbedtls_rsa_context rsa;
     uint8_t *cp;
     uint8_t *cpend;
-#endif
-#if defined(MCUBOOT_ENCRYPT_KW)
-    mbedtls_nist_kw_context kw;
-#endif
     size_t olen;
+#endif
     uint32_t off;
     uint32_t end;
     struct image_tlv_info info;
@@ -202,7 +286,7 @@
         rc = parse_enckey(&rsa, &cp, cpend);
         if (rc) {
             mbedtls_rsa_free(&rsa);
-            goto done;
+            return rc;
         }
 
         rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
@@ -210,24 +294,11 @@
         mbedtls_rsa_free(&rsa);
 
 #elif defined(MCUBOOT_ENCRYPT_KW)
-        mbedtls_nist_kw_init(&kw);
-
         assert(*bootutil_enc_key.len == 16);
-        rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES,
-                bootutil_enc_key.key, *bootutil_enc_key.len * 8, 0);
-        if (rc) {
-            mbedtls_nist_kw_free(&kw);
-            goto done;
-        }
-
-        rc = mbedtls_nist_kw_unwrap(&kw, MBEDTLS_KW_MODE_KW, buf, TLV_ENC_KW_SZ,
-                enckey, &olen, BOOT_ENC_KEY_SIZE);
-
-        mbedtls_nist_kw_free(&kw);
+        rc = key_unwrap(buf, enckey);
 #endif
     }
 
-done:
     return rc;
 }
 
@@ -258,7 +329,11 @@
     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) {