]> granicus.if.org Git - esp-idf/commitdiff
esp32 hwcrypto: Use AES registers directly
authorAngus Gratton <angus@espressif.com>
Tue, 15 Aug 2017 22:58:33 +0000 (08:58 +1000)
committerAngus Gratton <gus@projectgus.com>
Fri, 25 Aug 2017 06:08:03 +0000 (16:08 +1000)
components/esp32/hwcrypto/aes.c
components/esp32/include/hwcrypto/aes.h
components/mbedtls/port/include/aes_alt.h
components/soc/esp32/include/soc/hwcrypto_reg.h
components/soc/esp32/include/soc/soc.h

index e1acf536f0557fd3c8f1fe841cd5bc213f729794..7a9c93f32fc01adf927bda39fc8ab17cde3a7040 100644 (file)
@@ -3,7 +3,7 @@
  * Based on mbedTLS FIPS-197 compliant version.
  *
  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
+ *  Additions Copyright (C) 2016-2017, Espressif Systems (Shanghai) PTE Ltd
  *  SPDX-License-Identifier: Apache-2.0
  *
  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
  *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
  */
 #include <string.h>
+#include "mbedtls/aes.h"
 #include "hwcrypto/aes.h"
-#include "rom/aes.h"
 #include "soc/dport_reg.h"
+#include "soc/hwcrypto_reg.h"
 #include <sys/lock.h>
 
 static _lock_t aes_lock;
@@ -81,83 +82,60 @@ void esp_aes_free( esp_aes_context *ctx )
     bzero( ctx, sizeof( esp_aes_context ) );
 }
 
-/* Translate number of bits to an AES_BITS enum */
-static int keybits_to_aesbits(unsigned int keybits)
-{
-    switch (keybits) {
-    case 128:
-        return AES128;
-    case 192:
-        return AES192;
-        break;
-    case 256:
-        return AES256;
-    default:
-        return ( ERR_ESP_AES_INVALID_KEY_LENGTH );
-    }
-}
-
 /*
- * AES key schedule (encryption)
+ * AES key schedule (same for encryption or decryption, as hardware handles schedule)
  *
  */
-int esp_aes_setkey_enc( esp_aes_context *ctx, const unsigned char *key,
-                        unsigned int keybits )
+int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
+                    unsigned int keybits )
 {
-    uint16_t keybytes = keybits / 8;
-    int aesbits = keybits_to_aesbits(keybits);
-    if (aesbits < 0) {
-        return aesbits;
+    if (keybits != 128 && keybits != 192 && keybits != 256) {
+        return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
     }
-    ctx->enc.aesbits = aesbits;
-    bzero(ctx->enc.key, sizeof(ctx->enc.key));
-    memcpy(ctx->enc.key, key, keybytes);
+    ctx->key_bytes = keybits / 8;
+    memcpy(ctx->key, key, ctx->key_bytes);
     return 0;
 }
 
 /*
- * AES key schedule (decryption)
+ * Helper function to copy key from esp_aes_context buffer
+ * to hardware key registers.
  *
+ * Call only while holding esp_aes_acquire_hardware().
  */
-int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key,
-                        unsigned int keybits )
+static inline void esp_aes_setkey_hardware( esp_aes_context *ctx, int mode)
 {
-    uint16_t keybytes = keybits / 8;
-    int aesbits = keybits_to_aesbits(keybits);
-    if (aesbits < 0) {
-        return aesbits;
-    }
-    ctx->dec.aesbits = aesbits;
-    bzero(ctx->dec.key, sizeof(ctx->dec.key));
-    memcpy(ctx->dec.key, key, keybytes);
-    return 0;
+    const uint32_t MODE_DECRYPT_BIT = 4;
+    unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
+
+    memcpy((uint32_t *)AES_KEY_BASE, ctx->key, ctx->key_bytes);
+    DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
 }
 
-/*
- * Helper function to copy key from esp_aes_context buffer
- * to hardware key registers.
+/* Run a single 16 byte block of AES, using the hardware engine.
  *
- * Only call when protected by esp_aes_acquire_hardware().
+ * Call only while holding esp_aes_acquire_hardware().
  */
-static inline int esp_aes_setkey_hardware( esp_aes_context *ctx, int mode)
+static inline void esp_aes_block(const void *input, void *output)
 {
-    DPORT_ACCESS_BLOCK() {
-        // ROM AES functions access DPORT, so need to be protected as such
-        if ( mode == ESP_AES_ENCRYPT ) {
-            ets_aes_setkey_enc(ctx->enc.key, ctx->enc.aesbits);
-        } else {
-            ets_aes_setkey_dec(ctx->dec.key, ctx->dec.aesbits);
-        }
+    const uint32_t *input_words = (const uint32_t *)input;
+    uint32_t *output_words = (uint32_t *)output;
+    uint32_t *mem_block = (uint32_t *)AES_TEXT_BASE;
+
+    for(int i = 0; i < 4; i++) {
+        mem_block[i] = input_words[i];
     }
-    return 0;
-}
 
-static inline void esp_aes_block(const uint8_t input[16], uint8_t output[16])
-{
-    DPORT_ACCESS_BLOCK() {
-        // ROM AES functions access DPORT, so need to be protected as such
-        ets_aes_crypt(input, output);
+    DPORT_REG_WRITE(AES_START_REG, 1);
+
+    DPORT_STALL_OTHER_CPU_START();
+    {
+        while (_DPORT_REG_READ(AES_IDLE_REG) != 1) { }
+        for (int i = 0; i < 4; i++) {
+            output_words[i] = mem_block[i];
+        }
     }
+    DPORT_STALL_OTHER_CPU_END();
 }
 
 /*
@@ -215,6 +193,9 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
                        unsigned char *output )
 {
     int i;
+    uint32_t *output_words = (uint32_t *)output;
+    const uint32_t *input_words = (const uint32_t *)input;
+    uint32_t *iv_words = (uint32_t *)iv;
     unsigned char temp[16];
 
     if ( length % 16 ) {
@@ -222,34 +203,36 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
     }
 
     esp_aes_acquire_hardware();
+
     esp_aes_setkey_hardware(ctx, mode);
 
     if ( mode == ESP_AES_DECRYPT ) {
         while ( length > 0 ) {
-            memcpy( temp, input, 16 );
-            esp_aes_block(input, output);
+            memcpy(temp, input_words, 16);
+            esp_aes_block(input_words, output_words);
 
-            for ( i = 0; i < 16; i++ ) {
-                output[i] = (unsigned char)( output[i] ^ iv[i] );
+            for ( i = 0; i < 4; i++ ) {
+                output_words[i] = output_words[i] ^ iv_words[i];
             }
 
-            memcpy( iv, temp, 16 );
+            memcpy( iv_words, temp, 16 );
 
-            input  += 16;
-            output += 16;
+            input_words += 4;
+            output_words += 4;
             length -= 16;
         }
     } else { // ESP_AES_ENCRYPT
         while ( length > 0 ) {
-            for ( i = 0; i < 16; i++ ) {
-                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            for ( i = 0; i < 4; i++ ) {
+                output_words[i] = input_words[i] ^ iv_words[i];
             }
 
-            esp_aes_block(output, output);
-            memcpy( iv, output, 16 );
+            esp_aes_block(output_words, output_words);
+            memcpy( iv_words, output_words, 16 );
 
-            input  += 16;
-            output += 16;
+            input_words  += 4;
+            output_words += 4;
             length -= 16;
         }
     }
@@ -274,6 +257,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
     size_t n = *iv_off;
 
     esp_aes_acquire_hardware();
+
     esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
 
     if ( mode == ESP_AES_DECRYPT ) {
@@ -321,6 +305,7 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
     unsigned char ov[17];
 
     esp_aes_acquire_hardware();
+
     esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
 
     while ( length-- ) {
@@ -360,6 +345,7 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
     size_t n = *nc_off;
 
     esp_aes_acquire_hardware();
+
     esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
 
     while ( length-- ) {
index b6a632affc6f2f7835d0b82e4f00b387e5d311d6..0bcd1f490cab92070dc530637b5b0b71d8a40784 100644 (file)
@@ -38,11 +38,6 @@ extern "C" {
 #define ERR_ESP_AES_INVALID_KEY_LENGTH                -0x0020  /**< Invalid key length. */
 #define ERR_ESP_AES_INVALID_INPUT_LENGTH              -0x0022  /**< Invalid data input length. */
 
-typedef struct {
-    enum AES_BITS aesbits;
-    uint8_t key[32];
-} key_context, KEY_CTX;
-
 /**
  * \brief          AES context structure
  *
@@ -52,10 +47,8 @@ typedef struct {
  *                 generating an extra round key
  */
 typedef struct {
-    int nr;                     /*!<  number of rounds  */
-    uint32_t *rk;               /*!<  AES round keys    */
-    KEY_CTX enc;
-    KEY_CTX dec;
+    uint8_t key_bytes;
+    uint8_t key[32];
 } esp_aes_context;
 
 /**
@@ -94,7 +87,7 @@ void esp_aes_init( esp_aes_context *ctx );
 void esp_aes_free( esp_aes_context *ctx );
 
 /**
- * \brief          AES key schedule (encryption)
+ * \brief          AES set key schedule (encryption or decryption)
  *
  * \param ctx      AES context to be initialized
  * \param key      encryption key
@@ -102,18 +95,7 @@ void esp_aes_free( esp_aes_context *ctx );
  *
  * \return         0 if successful, or ERR_AES_INVALID_KEY_LENGTH
  */
-int esp_aes_setkey_enc( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
-
-/**
- * \brief          AES key schedule (decryption)
- *
- * \param ctx      AES context to be initialized
- * \param key      decryption key
- * \param keybits  must be 128, 192 or 256
- *
- * \return         0 if successful, or ERR_AES_INVALID_KEY_LENGTH
- */
-int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
+int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
 
 /**
  * \brief          AES-ECB block encryption/decryption
index d4da6ca8784bfab81b0f36565502a28ede242ac5..a4d0b70c3a171ff26591a2dab6a238c5b8aa3456 100644 (file)
@@ -34,8 +34,8 @@ typedef esp_aes_context mbedtls_aes_context;
 
 #define mbedtls_aes_init            esp_aes_init
 #define mbedtls_aes_free            esp_aes_free
-#define mbedtls_aes_setkey_enc      esp_aes_setkey_enc
-#define mbedtls_aes_setkey_dec      esp_aes_setkey_dec
+#define mbedtls_aes_setkey_enc      esp_aes_setkey
+#define mbedtls_aes_setkey_dec      esp_aes_setkey
 #define mbedtls_aes_crypt_ecb       esp_aes_crypt_ecb
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 #define mbedtls_aes_crypt_cbc       esp_aes_crypt_cbc
index 10e80d935f3942db2c630310c51c9cccece69ee4..d0dfa748589630fcabcc5923bb8bf9e8eeb745b3 100644 (file)
 #define SHA_512_LOAD_REG        ((DR_REG_SHA_BASE) + 0xb8)
 #define SHA_512_BUSY_REG        ((DR_REG_SHA_BASE) + 0xbc)
 
+/* AES acceleration registers */
+#define AES_START_REG           ((DR_REG_AES_BASE) + 0x00)
+#define AES_IDLE_REG            ((DR_REG_AES_BASE) + 0x04)
+#define AES_MODE_REG            ((DR_REG_AES_BASE) + 0x08)
+#define AES_KEY_BASE            ((DR_REG_AES_BASE) + 0x10)
+#define AES_TEXT_BASE           ((DR_REG_AES_BASE) + 0x30)
+#define AES_ENDIAN              ((DR_REG_AES_BASE) + 0x40)
+
 #endif
index b758f559eb2d1b1339217f199589dfe1ff711d62..f3448a190fb6e2f4c82b61156ddcd310727b0b15 100644 (file)
@@ -69,6 +69,7 @@
 #define SOC_RTC_DATA_HIGH 0x50002000
 
 #define DR_REG_DPORT_BASE                       0x3ff00000
+#define DR_REG_AES_BASE                         0x3ff01000
 #define DR_REG_RSA_BASE                         0x3ff02000
 #define DR_REG_SHA_BASE                         0x3ff03000
 #define DR_REG_DPORT_END                        0x3ff03FFC