summaryrefslogtreecommitdiff
path: root/wolfcrypt/src/port/Espressif/esp32_aes.c
diff options
context:
space:
mode:
authorauth12 <[email protected]>2020-07-22 08:34:12 -0700
committerauth12 <[email protected]>2020-07-22 08:34:12 -0700
commit5015ddb9b1eee748efc24056e46f81888c975f7a (patch)
treea810f6ee90f8bfe0e934fdd9142198e6b3862957 /wolfcrypt/src/port/Espressif/esp32_aes.c
downloadwolfssl_windows-5015ddb9b1eee748efc24056e46f81888c975f7a.tar.xz
wolfssl_windows-5015ddb9b1eee748efc24056e46f81888c975f7a.zip
Initial commit
Diffstat (limited to 'wolfcrypt/src/port/Espressif/esp32_aes.c')
-rw-r--r--wolfcrypt/src/port/Espressif/esp32_aes.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/wolfcrypt/src/port/Espressif/esp32_aes.c b/wolfcrypt/src/port/Espressif/esp32_aes.c
new file mode 100644
index 0000000..f2fb8a5
--- /dev/null
+++ b/wolfcrypt/src/port/Espressif/esp32_aes.c
@@ -0,0 +1,299 @@
+/* esp32_aes.c
+ *
+ * Copyright (C) 2006-2020 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+#include <wolfssl/wolfcrypt/settings.h>
+
+#ifndef NO_AES
+
+#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
+ !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)
+
+#include <wolfssl/wolfcrypt/aes.h>
+#include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
+
+static const char* TAG = "wolf_hw_aes";
+/* mutex */
+static wolfSSL_Mutex aes_mutex;
+static int espaes_CryptHwMutexInit = 0;
+
+/*
+* lock hw engine.
+* this should be called before using engine.
+*/
+static int esp_aes_hw_InUse()
+{
+ int ret = 0;
+
+ ESP_LOGV(TAG, "enter esp_aes_hw_InUse");
+
+ if(espaes_CryptHwMutexInit == 0) {
+ ret = esp_CryptHwMutexInit(&aes_mutex);
+ if(ret == 0){
+ espaes_CryptHwMutexInit = 1;
+ } else {
+ ESP_LOGE(TAG, "aes mutx initialization failed.");
+ return -1;
+ }
+ }
+ /* lock hardware */
+ ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY);
+ if(ret != 0) {
+ ESP_LOGE(TAG, "aes engine lock failed.");
+ return -1;
+ }
+ /* Enable AES hardware */
+ periph_module_enable(PERIPH_AES_MODULE);
+
+ ESP_LOGV(TAG, "leave esp_aes_hw_InUse");
+ return ret;
+}
+
+/*
+* release hw engine
+*/
+static void esp_aes_hw_Leave( void )
+{
+ ESP_LOGV(TAG, "enter esp_aes_hw_Leave");
+ /* Disable AES hardware */
+ periph_module_disable(PERIPH_AES_MODULE);
+
+ /* unlock */
+ esp_CryptHwMutexUnLock(&aes_mutex);
+
+ ESP_LOGV(TAG, "leave esp_aes_hw_Leave");
+}
+
+/*
+ * set key to hardware key registers.
+ */
+static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
+{
+ int i;
+ word32 mode_ = 0;
+
+ ESP_LOGV(TAG, "enter esp_aes_hw_Set_KeyMode");
+
+ /* check mode */
+ if(mode == ESP32_AES_UPDATEKEY_ENCRYPT) {
+ mode_ = 0;
+ } else if(mode == ESP32_AES_UPDATEKEY_DECRYPT){
+ mode_ = 4;
+ } else {
+ ESP_LOGE(TAG, "unexpected error.");
+ return;
+ }
+
+ /* update key */
+ for(i=0;i<(ctx->keylen)/sizeof(word32);i++){
+ DPORT_REG_WRITE(AES_KEY_BASE + (i*4), *(((word32*)ctx->key) + i));
+ }
+
+ /* mode
+ * 0 AES-128 Encryption
+ * 1 AES-192 Encryption
+ * 2 AES-256 Encryption
+ * 4 AES-128 Decryption
+ * 5 AES-192 Decryption
+ * 6 AES-256 Decryption
+ */
+ switch(ctx->keylen){
+ case 24: mode_ += 1; break;
+ case 32: mode_ += 2; break;
+ default: break;
+ }
+
+ DPORT_REG_WRITE(AES_MODE_REG, mode_);
+ ESP_LOGV(TAG, "leave esp_aes_hw_Setkey");
+}
+
+/*
+ * Process a one block of AES
+ */
+static void esp_aes_bk(const byte* in, byte* out)
+{
+ const word32 *inwords = (const word32 *)in;
+ word32 *outwords = (word32 *)out;
+
+ ESP_LOGV(TAG, "enter esp_aes_bk");
+
+ /* copy text for encrypting/decrypting blocks */
+ DPORT_REG_WRITE(AES_TEXT_BASE, inwords[0]);
+ DPORT_REG_WRITE(AES_TEXT_BASE + 4, inwords[1]);
+ DPORT_REG_WRITE(AES_TEXT_BASE + 8, inwords[2]);
+ DPORT_REG_WRITE(AES_TEXT_BASE + 12, inwords[3]);
+
+ /* start engine */
+ DPORT_REG_WRITE(AES_START_REG, 1);
+
+ /* wait until finishing the process */
+ while(1) {
+ if(DPORT_REG_READ(AES_IDLE_REG) == 1)
+ break;
+ }
+
+ /* read-out blocks */
+ esp_dport_access_read_buffer(outwords, AES_TEXT_BASE, 4);
+ ESP_LOGV(TAG, "leave esp_aes_bk");
+}
+
+/*
+* wc_esp32AesEncrypt
+* @brief: a one block encrypt of the input block, into the output block
+* @param aes: a pointer of the AES object used to encrypt data
+* @param in : a pointer of the input buffer containing plain text to be encrypted
+* @param out: a pointer of the output buffer in which to store the cipher text of
+* the encrypted message
+*/
+int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out)
+{
+ ESP_LOGV(TAG, "enter wc_esp32AesEncrypt");
+ /* lock the hw engine */
+ esp_aes_hw_InUse();
+ /* load the key into the register */
+ esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT);
+ /* process a one block of AES */
+ esp_aes_bk(in, out);
+ /* release hw */
+ esp_aes_hw_Leave();
+ return 0;
+}
+/*
+* wc_esp32AesDecrypt
+* @brief: a one block decrypt of the input block, into the output block
+* @param aes: a pointer of the AES object used to decrypt data
+* @param in : a pointer of the input buffer containing plain text to be decrypted
+* @param out: a pointer of the output buffer in which to store the cipher text of
+* the decrypted message
+*/
+int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out)
+{
+ ESP_LOGV(TAG, "enter wc_esp32AesDecrypt");
+ /* lock the hw engine */
+ esp_aes_hw_InUse();
+ /* load the key into the register */
+ esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
+ /* process a one block of AES */
+ esp_aes_bk(in, out);
+ /* release hw engine */
+ esp_aes_hw_Leave();
+ return 0;
+}
+/*
+* wc_esp32AesCbcEncrypt
+* @brief: Encrypts a plain text message from the input buffer, and places the
+* resulting cipher text into the output buffer using cipher block chaining
+* with AES.
+* @param aes: a pointer of the AES object used to encrypt data
+* @param out: a pointer of the output buffer in which to store the cipher text of
+* the encrypted message
+* @param in : a pointer of the input buffer containing plain text to be encrypted
+* @param sz : size of input message
+*/
+int wc_esp32AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+ int i;
+ int offset = 0;
+ word32 blocks = (sz / AES_BLOCK_SIZE);
+ byte *iv;
+ byte temp_block[AES_BLOCK_SIZE];
+
+ ESP_LOGV(TAG, "enter wc_esp32AesCbcEncrypt");
+
+ iv = (byte*)aes->reg;
+
+ esp_aes_hw_InUse();
+
+ esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_ENCRYPT);
+
+ while (blocks--) {
+ XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
+
+ /* XOR block with IV for CBC */
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ temp_block[i] ^= iv[i];
+
+ esp_aes_bk(temp_block, (out + offset));
+
+ offset += AES_BLOCK_SIZE;
+
+ /* store IV for next block */
+ XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+ }
+
+ esp_aes_hw_Leave();
+ ESP_LOGV(TAG, "leave wc_esp32AesCbcEncrypt");
+ return 0;
+}
+/*
+* wc_esp32AesCbcDecrypt
+* @brief: Encrypts a plain text message from the input buffer, and places the
+* resulting cipher text into the output buffer using cipher block chaining
+* with AES.
+* @param aes: a pointer of the AES object used to decrypt data
+* @param out: a pointer of the output buffer in which to store the cipher text of
+* the decrypted message
+* @param in : a pointer of the input buffer containing plain text to be decrypted
+* @param sz : size of input message
+*/
+int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
+{
+ int i;
+ int offset = 0;
+ word32 blocks = (sz / AES_BLOCK_SIZE);
+ byte* iv;
+ byte temp_block[AES_BLOCK_SIZE];
+
+ ESP_LOGV(TAG, "enter wc_esp32AesCbcDecrypt");
+
+ iv = (byte*)aes->reg;
+
+ esp_aes_hw_InUse();
+
+ esp_aes_hw_Set_KeyMode(aes, ESP32_AES_UPDATEKEY_DECRYPT);
+
+ while (blocks--) {
+ XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE);
+
+ esp_aes_bk((in + offset), (out + offset));
+
+ /* XOR block with IV for CBC */
+ for (i = 0; i < AES_BLOCK_SIZE; i++)
+ (out + offset)[i] ^= iv[i];
+
+ /* store IV for next block */
+ XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);
+
+ offset += AES_BLOCK_SIZE;
+ }
+
+ esp_aes_hw_Leave();
+ ESP_LOGV(TAG, "leave wc_esp32AesCbcDecrypt");
+ return 0;
+}
+
+#endif /* WOLFSSL_ESP32WROOM32_CRYPT */
+#endif /* NO_AES */