From 9bc259ae6fef5206e542324f5f3b9beee8c224b8 Mon Sep 17 00:00:00 2001 From: Kamatham Pushyanth Date: Sun, 16 Nov 2025 00:12:09 +0530 Subject: [PATCH] Enable hardware acceleration for AES on PSoC6. - Implemented AES ECB, CBC, CFB, and GCM modes with hardware acceleration. - Ensured proper mutex locking for concurrent access to hardware resources during - Adjusted the aes.h header to include PSoC6 specific definitions and structures. - Updated README for PSoC6 port. --- wolfcrypt/src/aes.c | 108 +- wolfcrypt/src/port/cypress/README.md | 104 +- wolfcrypt/src/port/cypress/psoc6_crypto.c | 1025 ++++++++++++++++- wolfcrypt/src/sha512.c | 2 +- wolfssl/wolfcrypt/aes.h | 9 + wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h | 91 +- 6 files changed, 1296 insertions(+), 43 deletions(-) diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index 4c43d4ebdd..fae339cb6b 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -93,6 +93,11 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #include #else + +#if defined(WOLFSSL_PSOC6_CRYPTO) + #include +#endif /* WOLFSSL_PSOC6_CRYPTO */ + #ifdef NO_INLINE #include #else @@ -1118,6 +1123,24 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, #elif defined(WOLFSSL_SILABS_SE_ACCEL) /* implemented in wolfcrypt/src/port/silabs/silabs_aes.c */ +#elif defined(WOLFSSL_PSOC6_CRYPTO) + + #if (defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT)) + static WARN_UNUSED_RESULT int wc_AesEncrypt( + Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_Psoc6_Aes_Encrypt(aes, inBlock, outBlock); + } + #endif + + #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT) + static WARN_UNUSED_RESULT int wc_AesDecrypt( + Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_Psoc6_Aes_Decrypt(aes, inBlock, outBlock); + } + + #endif #else /* using wolfCrypt software implementation */ @@ -4405,6 +4428,22 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt( return AesSetKey(aes, userKey, keylen, iv, dir); } #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */ + +#elif defined(WOLFSSL_PSOC6_CRYPTO) + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_Psoc6_Aes_SetKey(aes, userKey, keylen, iv, dir); + } + + #if defined(WOLFSSL_AES_DIRECT) + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } + #endif /* WOLFSSL_AES_DIRECT */ #else #define NEED_SOFTWARE_AES_SETKEY #endif @@ -6108,6 +6147,20 @@ int wc_AesSetIV(Aes* aes, const byte* iv) #elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_AES) /* implemented in wolfcrypt/src/port/psa/psa_aes.c */ +#elif defined(WOLFSSL_PSOC6_CRYPTO) + + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return wc_Psoc6_Aes_CbcEncrypt(aes, out, in, sz); + } + + #if defined(HAVE_AES_DECRYPT) + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return wc_Psoc6_Aes_CbcDecrypt(aes, out, in, sz); + } + #endif /* HAVE_AES_DECRYPT */ + #else /* Reminder: Some HW implementations may also define this as needed. * (e.g. for unsupported key length fallback) */ @@ -7237,7 +7290,7 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) } else #endif -#if !defined(FREESCALE_LTC_AES_GCM) +#if !defined(FREESCALE_LTC_AES_GCM) && !defined(WOLFSSL_PSOC6_CRYPTO) if (ret == 0) { VECTOR_REGISTERS_PUSH; /* AES-NI code generates its own H value, but generate it here too, to @@ -7275,7 +7328,7 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) } #endif /* GCM_TABLE || GCM_TABLE_4BIT */ } -#endif /* FREESCALE_LTC_AES_GCM */ +#endif /* !FREESCALE_LTC_AES_GCM && !WOLFSSL_PSOC6_CRYPTO */ #endif #if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_AFALG_XILINX_AES) @@ -9380,6 +9433,11 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, authTag, authTagSz, authIn, authInSz); #endif /* STM32_CRYPTO_AES_GCM */ +#if defined(WOLFSSL_PSOC6_CRYPTO) + return wc_Psoc6_Aes_GcmEncrypt(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); +#endif /* WOLFSSL_PSOC6_CRYPTO */ + VECTOR_REGISTERS_PUSH; #if !defined(__aarch64__) && defined(WOLFSSL_ARMASM) @@ -10060,6 +10118,11 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, authTag, authTagSz, authIn, authInSz); #endif /* STM32_CRYPTO_AES_GCM */ +#if defined(WOLFSSL_PSOC6_CRYPTO) + return wc_Psoc6_Aes_GcmDecrypt(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); +#endif /* WOLFSSL_PSOC6_CRYPTO */ + VECTOR_REGISTERS_PUSH; #if !defined(__aarch64__) && defined(WOLFSSL_ARMASM) @@ -13100,6 +13163,30 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) return AES_ECB_decrypt(aes, in, out, sz); } +#elif defined(WOLFSSL_PSOC6_CRYPTO) + +int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + + return wc_Psoc6_Aes_EcbEncrypt(aes, out, in, sz); +} + +#define _AesEcbEncrypt(aes, out, in, sz) wc_AesEcbEncrypt(aes, out, in, sz) + +#ifdef HAVE_AES_DECRYPT +int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + + return wc_Psoc6_Aes_EcbDecrypt(aes, out, in, sz); +} + +#define _AesEcbDecrypt(aes, out, in, sz) wc_AesEcbDecrypt(aes, out, in, sz) +#endif /* HAVE_AES_DECRYPT */ + #else /* Software AES - ECB */ @@ -13264,6 +13351,22 @@ int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) #endif /* HAVE_AES_ECB */ #if defined(WOLFSSL_AES_CFB) + +#if defined(WOLFSSL_PSOC6_CRYPTO) + +int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_Psoc6_Aes_CfbEncrypt(aes, out, in, sz); +} + +#ifdef HAVE_AES_DECRYPT +int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + return wc_Psoc6_Aes_CfbDecrypt(aes, out, in, sz); +} +#endif /* HAVE_AES_DECRYPT */ + +#else /* Feedback AES mode * * aes structure holding key to use for encryption @@ -13456,6 +13559,7 @@ int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) return AesCfbDecrypt_C(aes, out, in, sz, AES_CFB_MODE); } #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_PSOC6_CRYPTO */ #ifndef WOLFSSL_NO_AES_CFB_1_8 /* shift the whole WC_AES_BLOCK_SIZE array left by 8 or 1 bits */ diff --git a/wolfcrypt/src/port/cypress/README.md b/wolfcrypt/src/port/cypress/README.md index 66f8ac42ca..f426c14d81 100644 --- a/wolfcrypt/src/port/cypress/README.md +++ b/wolfcrypt/src/port/cypress/README.md @@ -1,6 +1,6 @@ # PSoC6 Hardware Crypto Port for wolfSSL -This directory provides a hardware-accelerated cryptography port for Cypress PSoC6 devices, integrating the PSoC6 hardware crypto block with the wolfSSL cryptography library. The implementation leverages the PSoC6 hardware to accelerate various cryptographic hash and ECC operations, improving performance and reducing CPU load. +This directory provides a hardware-accelerated cryptography port for Cypress PSoC6 devices, integrating the PSoC6 hardware crypto block with the wolfSSL cryptography library. The implementation leverages the PSoC6 hardware to accelerate various cryptographic operations including hash functions, AES encryption/decryption, and ECC verification, improving performance and reducing CPU load. ## Implemented Features @@ -21,68 +21,126 @@ The following hash algorithms are implemented using the PSoC6 hardware crypto bl All hash operations are offloaded to the PSoC6 hardware, with mutex protection for thread safety. -### 2. Hardware-Accelerated ECDSA Verification +### 2. Hardware-Accelerated AES Functions + +The following AES cipher modes are implemented using the PSoC6 hardware crypto block: + +- **AES Block Operations** + - Single-block encryption/decryption: `wc_Psoc6_Aes_Encrypt`, `wc_Psoc6_Aes_Decrypt` + - Direct AES operations: `wc_Psoc6_Aes_EncryptDirect`, `wc_Psoc6_Aes_DecryptDirect` (enabled with `WOLFSSL_AES_DIRECT`) + - Supports AES-128, AES-192, and AES-256 key sizes + +- **AES-ECB (Electronic Codebook) Mode** + - Multi-block encryption: `wc_Psoc6_Aes_EcbEncrypt` + - Multi-block decryption: `wc_Psoc6_Aes_EcbDecrypt` + - Enabled with `HAVE_AES_ECB` + +- **AES-CBC (Cipher Block Chaining) Mode** + - Multi-block encryption with IV chaining: `wc_Psoc6_Aes_CbcEncrypt` + - Multi-block decryption with IV chaining: `wc_Psoc6_Aes_CbcDecrypt` + - Automatically enabled with `HAVE_AES_CBC` + +- **AES-CFB (Cipher Feedback) Mode** + - Stream encryption: `wc_Psoc6_Aes_CfbEncrypt` + - Stream decryption: `wc_Psoc6_Aes_CfbDecrypt` + - Enabled with `WOLFSSL_AES_CFB` + +- **AES-GCM (Galois/Counter Mode)** + - Authenticated encryption: `wc_Psoc6_Aes_GcmEncrypt` + - Authenticated decryption with tag verification: `wc_Psoc6_Aes_GcmDecrypt` + - Provides both confidentiality and authenticity + - Enabled with `HAVE_AESGCM` + +All AES operations are offloaded to the PSoC6 hardware with mutex protection for thread safety. +### 3. Hardware-Accelerated ECDSA Verification - **ECDSA Signature Verification** - Function: `psoc6_ecc_verify_hash_ex` - Uses PSoC6 hardware to verify ECDSA signatures for supported curves (up to secp521r1). - Enabled when `HAVE_ECC` is defined. -### 3. Crypto Block Initialization and Resource Management +### 4. Crypto Block Initialization and Resource Management - **Initialization** - Function: `psoc6_crypto_port_init` - Enables the PSoC6 crypto hardware block. - **Resource Cleanup** - - Function: `wc_Psoc6_Sha_Free` - - Clears and synchronizes the hardware register buffer. + - Hash functions: `wc_Psoc6_Sha_Free` — Clears and synchronizes the hardware register buffer + - AES functions: `wc_Psoc6_Aes_Free` — Frees internal AES buffers and state ## Enable Hardware Acceleration -To enable PSoC6 hardware crypto acceleration for hash and ECC algorithms, ensure the following macros are defined: +To enable PSoC6 hardware crypto acceleration, ensure the following macros are defined: + +### Core Macro +- `WOLFSSL_PSOC6_CRYPTO` — Enables the PSoC6 hardware crypto port (required for all features) -- `WOLFSSL_PSOC6_CRYPTO` — Enables the PSoC6 hardware crypto port. +### Hash Function Macros - The following are defined in `psoc6_crypto.h` and control which hardware hash accelerations are available: - - `PSOC6_HASH_SHA1` — Enables SHA-1 hardware acceleration. - - `PSOC6_HASH_SHA2` — Enables SHA-2 family (SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256) hardware acceleration. - - `PSOC6_HASH_SHA3` — Enables SHA-3 family hardware acceleration. -- To enable the corresponding algorithms in wolfSSL, define the following macros as needed (typically in your `wolfssl/wolfcrypt/settings.h` or build system): - - `WOLFSSL_SHA224` — Enable SHA-224 support. - - `WOLFSSL_SHA384` — Enable SHA-384 support. - - `WOLFSSL_SHA512` — Enable SHA-512, SHA-512/224, SHA-512/256 support. - - `WOLFSSL_SHA3` — Enable SHA-3 support. - - `WOLFSSL_SHAKE128`, `WOLFSSL_SHAKE256` — Enable SHAKE support. - - `HAVE_ECC` — Enable ECC and ECDSA support. - -**Example: Enabling SHA-1, SHA-2, and SHA-3 Hardware Acceleration** + - `PSOC6_HASH_SHA1` — Enables SHA-1 hardware acceleration + - `PSOC6_HASH_SHA2` — Enables SHA-2 family hardware acceleration + - `PSOC6_HASH_SHA3` — Enables SHA-3 family hardware acceleration +- To enable the corresponding algorithms in wolfSSL, define these macros (typically in your `wolfssl/wolfcrypt/settings.h` or build system): + - `WOLFSSL_SHA224` — Enable SHA-224 support + - `WOLFSSL_SHA384` — Enable SHA-384 support + - `WOLFSSL_SHA512` — Enable SHA-512, SHA-512/224, SHA-512/256 support + - `WOLFSSL_SHA3` — Enable SHA-3 support + - `WOLFSSL_SHAKE128`, `WOLFSSL_SHAKE256` — Enable SHAKE support + +### AES Function Macros +- AES hardware acceleration is automatically enabled when `NO_AES` is not defined +- To enable specific AES modes, define: + - `HAVE_AES_ECB` — Enable AES-ECB mode + - `HAVE_AES_CBC` — Enable AES-CBC mode (typically enabled by default) + - `HAVE_AES_DECRYPT` — Enable AES decryption functions + - `WOLFSSL_AES_DIRECT` — Enable direct AES block operations + - `WOLFSSL_AES_CFB` — Enable AES-CFB mode + - `HAVE_AESGCM` — Enable AES-GCM authenticated encryption + +### ECC Function Macros +- `HAVE_ECC` — Enable ECC and ECDSA support + +**Example: Enabling Full Hardware Acceleration** In your build configuration or `wolfssl/wolfcrypt/settings.h`: ```c #define WOLFSSL_PSOC6_CRYPTO + +/* Hash functions */ #define WOLFSSL_SHA224 #define WOLFSSL_SHA384 #define WOLFSSL_SHA512 #define WOLFSSL_SHA3 #define WOLFSSL_SHAKE128 #define WOLFSSL_SHAKE256 + +/* AES cipher modes */ +#define HAVE_AES_ECB +#define HAVE_AES_CBC +#define HAVE_AES_DECRYPT +#define WOLFSSL_AES_DIRECT +#define WOLFSSL_AES_CFB +#define HAVE_AESGCM + +/* ECC */ #define HAVE_ECC ``` -- No need to define `PSOC6_HASH_SHA1`, `PSOC6_HASH_SHA2`, or `PSOC6_HASH_SHA3` yourself; they are defined in `psoc6_crypto.h`. +- Note: `PSOC6_HASH_SHA1`, `PSOC6_HASH_SHA2`, and `PSOC6_HASH_SHA3` are automatically defined in `psoc6_crypto.h`; you don't need to define them explicitly. ## File Overview - `psoc6_crypto.h` Header file declaring the hardware crypto interface and configuration macros. - `psoc6_crypto.c` - Implementation of the hardware-accelerated hash and ECC functions for PSoC6. + Implementation of the hardware-accelerated hash, AES, and ECC functions for PSoC6. ## Integration Notes - The port expects the PSoC6 PDL (Peripheral Driver Library) to be available and included in your project. - The hardware crypto block is initialized on first use; no manual initialization is required unless you wish to call `psoc6_crypto_port_init` directly. -- Hash operations are mutex-protected for thread safety. +- Hash and AES operations are mutex-protected for thread safety. - ECC hardware operations are not mutex-protected; if you use ECC functions from multiple threads, you must provide your own synchronization. -- The implementation is designed to be compatible with the wolfSSL API, so existing code using wolfSSL hash/ECC functions will automatically benefit from hardware acceleration when enabled. +- The implementation is designed to be compatible with the wolfSSL API, so existing code using wolfSSL hash/AES/ECC functions will automatically benefit from hardware acceleration when enabled. --- diff --git a/wolfcrypt/src/port/cypress/psoc6_crypto.c b/wolfcrypt/src/port/cypress/psoc6_crypto.c index aca67d1b47..90d9ce2082 100644 --- a/wolfcrypt/src/port/cypress/psoc6_crypto.c +++ b/wolfcrypt/src/port/cypress/psoc6_crypto.c @@ -46,7 +46,16 @@ #ifdef HAVE_ECC #include -#endif +#endif /* HAVE_ECC */ + +#ifndef NO_AES +#include + +#include "cy_crypto_common.h" +#include "cy_crypto_core_aes.h" +#include "cy_crypto_core_aes_v2.h" + +#endif /* NO_AES */ #if defined(PSOC6_HASH_SHA3) @@ -188,15 +197,26 @@ int wc_Psoc6_Sha1_Sha2_Init(void* sha, wc_psoc6_hash_sha1_sha2_t hash_mode, * engine. * * No parameters. - * No return value. + * returns 0 on success, error code if mutex lock fails. */ -void wc_Psoc6_Sha_Free(void) +int wc_Psoc6_Sha_Free(void) { - /* Clear the register buffer */ - Cy_Crypto_Core_V2_RBClear(crypto_base); + int ret; - /* Wait until the instruction is complete */ - Cy_Crypto_Core_V2_Sync(crypto_base); + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + /* Clear the register buffer */ + Cy_Crypto_Core_V2_RBClear(crypto_base); + + /* Wait until the instruction is complete */ + Cy_Crypto_Core_V2_Sync(crypto_base); + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + } + + return ret; } /* SHA */ @@ -413,8 +433,8 @@ int wc_Sha224Final(wc_Sha224* sha, byte* hash) return wc_InitSha224(sha); } -#endif /* #if !NO_SHA224 */ -#endif /* #if !NO_SHA256 */ +#endif /* WOLFSSL_SHA224 */ +#endif /* !NO_SHA256 */ /* SHA-384 */ #if defined(WOLFSSL_SHA384) @@ -1015,6 +1035,991 @@ int wc_Psoc6_Shake_SqueezeBlocks(void* shake, byte* out, word32 blockCnt) #endif /* WOLFSSL_SHA3 && PSOC6_HASH_SHA3 */ +#if defined(PSOC6_CRYPTO_AES) + +/* Convert wolfSSL AES key length to PSoC6 crypto key length enumeration. + * + * This helper function maps standard AES key sizes to the corresponding + * PSoC6 hardware crypto enumeration values. + * + * keyLen AES key length in bytes (16, 24, or 32) + * returns Corresponding PSoC6 key length enumeration value + * - CY_CRYPTO_KEY_AES_128 for 16-byte keys (AES-128) + * - CY_CRYPTO_KEY_AES_192 for 24-byte keys (AES-192) + * - CY_CRYPTO_KEY_AES_256 for 32-byte keys (AES-256) + * - CY_CRYPTO_KEY_AES_128 as safe default (key validation done + * earlier) + */ +static cy_en_crypto_aes_key_length_t psoc6_get_aes_key_length(word32 keyLen) +{ + switch (keyLen) { + case 16: + return CY_CRYPTO_KEY_AES_128; + case 24: + return CY_CRYPTO_KEY_AES_192; + case 32: + return CY_CRYPTO_KEY_AES_256; + default: + /* Safe default - validation done in wc_Psoc6_Aes_SetKey */ + return CY_CRYPTO_KEY_AES_128; + } +} + +/* Initialize AES context with key and optional IV for PSoC6 hardware + * acceleration. + * + * Sets up the AES context structure with the provided key and optional + * initialization vector. This function validates key length, stores key + * information, and prepares the context for subsequent crypto operations. + * The actual hardware key scheduling is performed during encrypt/decrypt calls. + * + * aes Pointer to AES context structure to initialize + * userKey Pointer to AES key buffer (16, 24, or 32 bytes) + * len Key length in bytes (must be 16, 24, or 32) + * iv Pointer to initialization vector (AES_BLOCK_SIZE bytes, optional) + * dir Encryption direction (currently unused, direction handled + * per-operation) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters + * + * Note: This function only stores the key and IV in the wolfSSL context. + * Hardware initialization occurs during actual crypto operations. + */ +int wc_Psoc6_Aes_SetKey(Aes* aes, const byte* userKey, word32 len, + const byte* iv, int dir) +{ + int ret = 0; + + if (aes == NULL || userKey == NULL) { + return BAD_FUNC_ARG; + } + + /* Validate key length */ + if (len != 16 && len != 24 && len != 32) { + return BAD_FUNC_ARG; + } + + /* Store key information in wolfSSL structure */ + aes->keylen = len; + aes->rounds = len / 4 + 6; + aes->left = 0; + + XMEMCPY(aes->key, userKey, len); + + /* Store IV if provided */ + if (iv != NULL) { + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + } + + (void)dir; /* Direction is handled per-operation */ + + return ret; +} + +/* Free the internal AES buffers used by PSOC6 CRYPTO block. + * + * This function clears the internal AES buffers allocated + * in the AES context. It is called after encryption/decryption operations + * to ensure sensitive data is not left in memory. + * + * aes Pointer to initialized AES context + * + * Note: Thread safety is implemented in the functions it is called, so no + * need to lock the mutex again here. + */ +void wc_Psoc6_Aes_Free(Aes* aes) +{ + /* Only aes_buffers are cleared here. aes_state is cleared in wc_AesFree() + */ + if (aes->aes_state.buffers != NULL) { + Cy_Crypto_Core_V2_MemSet( + crypto_base, (void*)aes->aes_state.buffers, 0u, + ((uint16_t)sizeof(cy_stc_crypto_aes_buffers_t))); + } + +#ifdef HAVE_AESGCM + /* No need to clear the buffers again if internal buffers are not + * initialized */ + if (aes->aes_gcm_state.aes_buffer != NULL) { + Cy_Crypto_Core_Aes_GCM_Free(crypto_base, &aes->aes_gcm_state); + } +#endif /* HAVE_AESGCM */ +} + +/* Encrypt a single AES block using PSoC6 hardware acceleration. + * + * Performs AES encryption on exactly one block (16 bytes) of data using + * the PSoC6 crypto hardware in ECB mode. The function initializes the + * hardware with the key from the AES context, performs the encryption, + * and cleans up resources. + * + * aes Pointer to initialized AES context containing key + * in Pointer to input plaintext block (exactly AES_BLOCK_SIZE bytes) + * out Pointer to output ciphertext buffer (exactly AES_BLOCK_SIZE bytes) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters, WC_HW_E for + * hardware errors, or mutex error codes + */ +int wc_Psoc6_Aes_Encrypt(Aes* aes, const byte* in, byte* out) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + if (aes == NULL || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* Initialize AES state with key */ + status = Cy_Crypto_Core_Aes_Init(crypto_base, (const uint8_t*)aes->key, + keyLength, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + + /* Encrypt single block using ECB mode */ + status = Cy_Crypto_Core_Aes_Ecb(crypto_base, CY_CRYPTO_ENCRYPT, out, in, + &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} + +#ifdef WOLFSSL_AES_DIRECT +/* Direct AES encryption wrapper with parameter order compatibility. + * + * Provides parameter order compatibility with wolfSSL's direct AES interface. + * This is a simple wrapper around wc_Psoc6_Aes_Encrypt that reorders parameters + * to match the expected direct encryption API. + * + * aes Pointer to initialized AES context containing key + * out Pointer to output ciphertext buffer (exactly AES_BLOCK_SIZE bytes) + * in Pointer to input plaintext block (exactly AES_BLOCK_SIZE bytes) + * + * returns 0 on success, or error codes from wc_Psoc6_Aes_Encrypt + */ +int wc_Psoc6_Aes_EncryptDirect(Aes* aes, byte* out, const byte* in) +{ + return wc_Psoc6_Aes_Encrypt(aes, in, out); +} +#endif /* WOLFSSL_AES_DIRECT */ + +#ifdef HAVE_AES_DECRYPT +/* Decrypt a single AES block using PSoC6 hardware acceleration. + * + * Performs AES decryption on exactly one block (16 bytes) of data using + * the PSoC6 crypto hardware in ECB mode. The function initializes the + * hardware with the key from the AES context, performs the decryption, + * and cleans up resources. + * + * aes Pointer to initialized AES context containing key + * in Pointer to input ciphertext block (exactly AES_BLOCK_SIZE bytes) + * out Pointer to output plaintext buffer (exactly AES_BLOCK_SIZE bytes) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters, WC_HW_E for + * hardware errors, or mutex error codes + */ +int wc_Psoc6_Aes_Decrypt(Aes* aes, const byte* in, byte* out) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + if (aes == NULL || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* Initialize AES state with key */ + status = Cy_Crypto_Core_Aes_Init(crypto_base, (const uint8_t*)aes->key, + keyLength, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + + /* Decrypt single block using ECB mode */ + status = Cy_Crypto_Core_Aes_Ecb(crypto_base, CY_CRYPTO_DECRYPT, out, in, + &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} + +#ifdef WOLFSSL_AES_DIRECT +/* Direct AES decryption wrapper with parameter order compatibility. + * + * Provides parameter order compatibility with wolfSSL's direct AES interface. + * This is a simple wrapper around wc_Psoc6_Aes_Decrypt that reorders parameters + * to match the expected direct decryption API. + * + * aes Pointer to initialized AES context containing key + * out Pointer to output plaintext buffer (exactly AES_BLOCK_SIZE bytes) + * in Pointer to input ciphertext block (exactly AES_BLOCK_SIZE bytes) + * + * returns 0 on success, or error codes from wc_Psoc6_Aes_Decrypt + */ +int wc_Psoc6_Aes_DecryptDirect(Aes* aes, byte* out, const byte* in) +{ + return wc_Psoc6_Aes_Decrypt(aes, in, out); +} +#endif /* WOLFSSL_AES_DIRECT */ +#endif /* HAVE_AES_DECRYPT */ + +#if defined(HAVE_AES_ECB) +/* Encrypt multiple blocks using AES-ECB mode with PSoC6 hardware. + * + * Performs AES encryption on multiple blocks of data using Electronic + * Codebook (ECB) mode. Each block is encrypted independently using the + * same key. The input size must be a multiple of AES_BLOCK_SIZE. + * + * aes Pointer to initialized AES context containing key + * out Pointer to output ciphertext buffer (sz bytes) + * in Pointer to input plaintext buffer (sz bytes) + * sz Size of data in bytes (must be multiple of AES_BLOCK_SIZE) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters (including + * non-block-aligned sizes), WC_HW_E for hardware errors, or + * mutex error codes + */ +int wc_Psoc6_Aes_EcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + if (aes == NULL || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + if (sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* Initialize AES state once for all blocks */ + status = Cy_Crypto_Core_Aes_Init(crypto_base, (const uint8_t*)aes->key, + keyLength, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + Cy_Crypto_Core_V2_Aes_LoadEncKey(crypto_base, &aes->aes_state); + Cy_Crypto_Core_V2_FFContinue(crypto_base, CY_CRYPTO_V2_RB_FF_LOAD0, in, sz); + Cy_Crypto_Core_V2_FFStart(crypto_base, CY_CRYPTO_V2_RB_FF_STORE, out, sz); + + for (; sz > 0; sz -= CY_CRYPTO_AES_BLOCK_SIZE) { + Cy_Crypto_Core_V2_BlockMov(crypto_base, CY_CRYPTO_V2_RB_BLOCK0, + CY_CRYPTO_V2_RB_FF_LOAD0, + CY_CRYPTO_AES_BLOCK_SIZE); + Cy_Crypto_Core_V2_RunAes(crypto_base); + + Cy_Crypto_Core_V2_BlockMov(crypto_base, CY_CRYPTO_V2_RB_FF_STORE, + CY_CRYPTO_V2_RB_BLOCK1, + CY_CRYPTO_AES_BLOCK_SIZE); + } + + Cy_Crypto_Core_WaitForReady(crypto_base); + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} + +#ifdef HAVE_AES_DECRYPT +/* Decrypt multiple blocks using AES-ECB mode with PSoC6 hardware. + * + * Performs AES decryption on multiple blocks of data using Electronic + * Codebook (ECB) mode. Each block is decrypted independently using the + * same key. The input size must be a multiple of AES_BLOCK_SIZE. + * + * aes Pointer to initialized AES context containing key + * out Pointer to output plaintext buffer (sz bytes) + * in Pointer to input ciphertext buffer (sz bytes) + * sz Size of data in bytes (must be multiple of AES_BLOCK_SIZE) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters (including + * non-block-aligned sizes), WC_HW_E for hardware errors, or + * mutex error codes + */ +int wc_Psoc6_Aes_EcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + if (aes == NULL || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + if (sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* Initialize AES state once for all blocks */ + status = Cy_Crypto_Core_Aes_Init(crypto_base, (const uint8_t*)aes->key, + keyLength, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + + Cy_Crypto_Core_V2_Aes_LoadDecKey(crypto_base, &aes->aes_state); + Cy_Crypto_Core_V2_FFContinue(crypto_base, CY_CRYPTO_V2_RB_FF_LOAD0, in, sz); + Cy_Crypto_Core_V2_FFStart(crypto_base, CY_CRYPTO_V2_RB_FF_STORE, out, sz); + + for (; sz > 0; sz -= CY_CRYPTO_AES_BLOCK_SIZE) { + Cy_Crypto_Core_V2_BlockMov(crypto_base, CY_CRYPTO_V2_RB_BLOCK0, + CY_CRYPTO_V2_RB_FF_LOAD0, + CY_CRYPTO_AES_BLOCK_SIZE); + Cy_Crypto_Core_V2_RunAesInv(crypto_base); + + Cy_Crypto_Core_V2_BlockMov(crypto_base, CY_CRYPTO_V2_RB_FF_STORE, + CY_CRYPTO_V2_RB_BLOCK1, + CY_CRYPTO_AES_BLOCK_SIZE); + } + + Cy_Crypto_Core_WaitForReady(crypto_base); + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_ECB */ + +/* AES CBC */ +#ifdef HAVE_AES_CBC +/* Encrypt multiple blocks using AES-CBC mode with PSoC6 hardware. + * + * Performs AES encryption using Cipher Block Chaining (CBC) mode where + * each plaintext block is XORed with the previous ciphertext block before + * encryption. The initialization vector (IV) from the AES context is used + * for the first block and updated during the operation. + * + * aes Pointer to initialized AES context containing key and IV + * out Pointer to output ciphertext buffer (sz bytes) + * in Pointer to input plaintext buffer (sz bytes) + * sz Size of data in bytes (must be multiple of AES_BLOCK_SIZE) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters (including + * non-block-aligned sizes), WC_HW_E for hardware errors, or + * mutex error codes + */ +int wc_Psoc6_Aes_CbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + if (aes == NULL || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + if (sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* Initialize AES state with key */ + status = Cy_Crypto_Core_Aes_Init(crypto_base, (const uint8_t*)aes->key, + keyLength, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + status = + Cy_Crypto_Core_Aes_Cbc(crypto_base, CY_CRYPTO_ENCRYPT, sz, + (uint8_t*)aes->reg, out, in, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} + +#ifdef HAVE_AES_DECRYPT +/* Decrypt multiple blocks using AES-CBC mode with PSoC6 hardware. + * + * Performs AES decryption using Cipher Block Chaining (CBC) mode where + * each ciphertext block is decrypted and XORed with the previous ciphertext + * block. The initialization vector (IV) from the AES context is used for + * the first block and updated during the operation. + * + * aes Pointer to initialized AES context containing key and IV + * out Pointer to output plaintext buffer (sz bytes) + * in Pointer to input ciphertext buffer (sz bytes) + * sz Size of data in bytes (must be multiple of AES_BLOCK_SIZE) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters (including + * non-block-aligned sizes), WC_HW_E for hardware errors, or + * mutex error codes + */ +int wc_Psoc6_Aes_CbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + if (aes == NULL || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + if (sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* Initialize AES state with key */ + status = Cy_Crypto_Core_Aes_Init(crypto_base, (const uint8_t*)aes->key, + keyLength, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + + status = + Cy_Crypto_Core_Aes_Cbc(crypto_base, CY_CRYPTO_DECRYPT, sz, + (uint8_t*)aes->reg, out, in, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC */ + +/* AES CFB */ +#ifdef WOLFSSL_AES_CFB +/* Encrypt data using AES-CFB mode with PSoC6 hardware acceleration. + * + * Performs AES encryption using Cipher Feedback (CFB) mode, which operates + * as a stream cipher. CFB can handle data that is not block-aligned and + * maintains state between calls for streaming operations. The IV and + * partial block state are managed automatically. + * + * aes Pointer to initialized AES context containing key, IV, and state + * out Pointer to output ciphertext buffer (sz bytes) + * in Pointer to input plaintext buffer (sz bytes) + * sz Size of data in bytes (can be any length, not limited to block size) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters, WC_HW_E for + * hardware errors, or mutex error codes + */ +int wc_Psoc6_Aes_CfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + if (aes == NULL || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* Initialize AES state with key */ + status = Cy_Crypto_Core_Aes_Init(crypto_base, (const uint8_t*)aes->key, + keyLength, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + + /* Setup CFB mode */ + status = Cy_Crypto_Core_Aes_Cfb_Setup(crypto_base, CY_CRYPTO_ENCRYPT, + &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Set IV */ + status = Cy_Crypto_Core_Aes_Cfb_Set_IV(crypto_base, (uint8_t*)aes->reg, + &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Copy the unprocessed bytes */ + aes->aes_state.unProcessedBytes = aes->left; + XMEMCPY(aes->aes_state.buffers->unProcessedData, aes->tmp, AES_BLOCK_SIZE); + + /* Update operation */ + status = Cy_Crypto_Core_Aes_Cfb_Update(crypto_base, sz, out, in, + &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Finish operation */ + status = Cy_Crypto_Core_Aes_Cfb_Finish(crypto_base, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Copy the updated IV into the AES context */ + XMEMCPY(aes->reg, aes->aes_state.buffers->iv, AES_BLOCK_SIZE); + + /* Copy the number of bytes processed in the current block */ + aes->left = aes->aes_state.unProcessedBytes; + XMEMCPY(aes->tmp, aes->aes_state.buffers->unProcessedData, AES_BLOCK_SIZE); + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} + +#ifdef HAVE_AES_DECRYPT +/* Decrypt data using AES-CFB mode with PSoC6 hardware acceleration. + * + * Performs AES decryption using Cipher Feedback (CFB) mode, which operates + * as a stream cipher. CFB can handle data that is not block-aligned and + * maintains state between calls for streaming operations. The IV and + * partial block state are managed automatically. + * + * aes Pointer to initialized AES context containing key, IV, and state + * out Pointer to output plaintext buffer (sz bytes) + * in Pointer to input ciphertext buffer (sz bytes) + * sz Size of data in bytes (can be any length, not limited to block size) + * + * returns 0 on success, BAD_FUNC_ARG for invalid parameters, WC_HW_E for + * hardware errors, or mutex error codes + */ +int wc_Psoc6_Aes_CfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + if (aes == NULL || in == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + /* Initialize AES state with key */ + status = Cy_Crypto_Core_Aes_Init(crypto_base, (const uint8_t*)aes->key, + keyLength, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + + /* Setup CFB mode */ + status = Cy_Crypto_Core_Aes_Cfb_Setup(crypto_base, CY_CRYPTO_DECRYPT, + &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Set IV */ + status = Cy_Crypto_Core_Aes_Cfb_Set_IV(crypto_base, (uint8_t*)aes->reg, + &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Copy the unprocessed bytes */ + aes->aes_state.unProcessedBytes = aes->left; + XMEMCPY(aes->aes_state.buffers->unProcessedData, aes->tmp, AES_BLOCK_SIZE); + + /* Update operation */ + status = Cy_Crypto_Core_Aes_Cfb_Update(crypto_base, sz, out, in, + &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Finish operation */ + status = Cy_Crypto_Core_Aes_Cfb_Finish(crypto_base, &aes->aes_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Copy the updated IV into the AES context */ + XMEMCPY(aes->reg, aes->aes_state.buffers->iv, AES_BLOCK_SIZE); + + /* Copy the number of bytes processed in the current block */ + aes->left = aes->aes_state.unProcessedBytes; + XMEMCPY(aes->tmp, aes->aes_state.buffers->unProcessedData, AES_BLOCK_SIZE); + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_CFB */ + +/* AES GCM */ +#ifdef HAVE_AESGCM + +/* Perform authenticated AES-GCM encryption using PSoC6 hardware. + * + * Encrypts plaintext data and generates an authentication tag using + * AES-GCM (Galois/Counter Mode). This mode provides both confidentiality + * and authenticity in a single operation, making it ideal for secure + * communications. + * + * aes Pointer to initialized AES-GCM context (key must be set) + * out Pointer to output ciphertext buffer (sz bytes, can be NULL if + * sz=0) in Pointer to input plaintext buffer (sz bytes, can be NULL if + * sz=0) sz Size of plaintext/ciphertext data in bytes iv Pointer to + * initialization vector/nonce buffer ivSz Size of IV in bytes + * (recommended: 12 bytes for GCM) authTag Pointer to output authentication + * tag buffer (authTagSz bytes) authTagSz Size of authentication tag (typically + * 12 or 16 bytes) authIn Pointer to additional authenticated data (AAD), + * can be NULL authInSz Size of AAD in bytes (0 if no AAD) + * + * returns 0 on success WC_HW_E for hardware errors, or mutex error codes + */ +int wc_Psoc6_Aes_GcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, byte* authTag, + word32 authTagSz, const byte* authIn, + word32 authInSz) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + int aesInited = 0; + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Initialize AES GCM state */ + cy_stc_crypto_aes_gcm_buffers_t* aesBuffers = + (cy_stc_crypto_aes_gcm_buffers_t*)(( + void*)Cy_Crypto_Core_GetVuMemoryAddress(crypto_base)); + status = Cy_Crypto_Core_Aes_GCM_Init(crypto_base, aesBuffers, + &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + + /* Set the key */ + status = Cy_Crypto_Core_Aes_GCM_SetKey(crypto_base, (uint8_t*)aes->key, + keyLength, &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Start GCM operation */ + status = Cy_Crypto_Core_Aes_GCM_Start(crypto_base, CY_CRYPTO_ENCRYPT, iv, + ivSz, &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Process AAD if present */ + if (authIn != NULL && authInSz > 0) { + status = Cy_Crypto_Core_Aes_GCM_AAD_Update( + crypto_base, (uint8_t*)authIn, authInSz, &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + } + + /* Encrypt data if present */ + if (sz > 0) { + status = Cy_Crypto_Core_Aes_GCM_Update(crypto_base, in, sz, out, + &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + } + + /* Finalize and get tag */ + status = Cy_Crypto_Core_Aes_GCM_Finish(crypto_base, authTag, authTagSz, + &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} + +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) +/* Perform authenticated AES-GCM decryption using PSoC6 hardware. + * + * Decrypts ciphertext data and verifies the authentication tag using + * AES-GCM (Galois/Counter Mode). The authentication tag is verified + * before returning the plaintext to ensure data authenticity and integrity. + * + * aes Pointer to initialized AES-GCM context (key must be set) + * out Pointer to output plaintext buffer (sz bytes, can be NULL if sz=0) + * in Pointer to input ciphertext buffer (sz bytes, can be NULL if sz=0) + * sz Size of ciphertext/plaintext data in bytes + * iv Pointer to initialization vector/nonce buffer (same as encryption) + * ivSz Size of IV in bytes (must match encryption) + * authTag Pointer to authentication tag from encryption (authTagSz bytes) + * authTagSz Size of authentication tag (must match encryption) + * authIn Pointer to additional authenticated data (AAD), can be NULL + * authInSz Size of AAD in bytes (must match encryption, 0 if no AAD) + * + * returns 0 on success and valid authentication, AES_GCM_AUTH_E for + * authentication failure (tag mismatch), WC_HW_E for hardware errors, or mutex + * error codes + */ +int wc_Psoc6_Aes_GcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, const byte* authTag, + word32 authTagSz, const byte* authIn, + word32 authInSz) +{ + int ret = 0; + cy_en_crypto_status_t status; + cy_en_crypto_aes_key_length_t keyLength; + byte computedTag[AES_BLOCK_SIZE]; + int aesInited = 0; + + /* Lock the mutex to perform crypto operations */ + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + + keyLength = psoc6_get_aes_key_length(aes->keylen); + + /* Initialize AES GCM state */ + cy_stc_crypto_aes_gcm_buffers_t* aesBuffers = + (cy_stc_crypto_aes_gcm_buffers_t*)(( + void*)Cy_Crypto_Core_GetVuMemoryAddress(crypto_base)); + status = Cy_Crypto_Core_Aes_GCM_Init(crypto_base, aesBuffers, + &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + aesInited = 1; + + /* Set the key */ + status = Cy_Crypto_Core_Aes_GCM_SetKey(crypto_base, (uint8_t*)aes->key, + keyLength, &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Start GCM operation */ + status = Cy_Crypto_Core_Aes_GCM_Start(crypto_base, CY_CRYPTO_DECRYPT, iv, + ivSz, &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Process AAD if present */ + if (authIn != NULL && authInSz > 0) { + status = Cy_Crypto_Core_Aes_GCM_AAD_Update( + crypto_base, (uint8_t*)authIn, authInSz, &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + } + + /* Decrypt data if present */ + if (sz > 0) { + status = Cy_Crypto_Core_Aes_GCM_Update(crypto_base, in, sz, out, + &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + } + + /* Finalize and get computed tag */ + status = Cy_Crypto_Core_Aes_GCM_Finish(crypto_base, computedTag, authTagSz, + &aes->aes_gcm_state); + if (status != CY_CRYPTO_SUCCESS) { + ret = WC_HW_E; + goto cleanup; + } + + /* Verify tag */ + if (ConstantCompare(computedTag, authTag, authTagSz) != 0) { + ret = AES_GCM_AUTH_E; + goto cleanup; + } + +cleanup: + if (aesInited) { + wc_Psoc6_Aes_Free(aes); + } + + /* Release the lock */ + wolfSSL_CryptHwMutexUnLock(); + return ret; +} +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* HAVE_AESGCM */ +#endif /* PSOC6_CRYPTO_AES */ + /* ECDSA */ #ifdef HAVE_ECC @@ -1162,4 +2167,4 @@ int psoc6_ecc_verify_hash_ex(MATH_INT_T* r, MATH_INT_T* s, const byte* hash, } #endif /* HAVE_ECC */ -#endif /* defined(WOLFSSL_PSOC6_CRYPTO) */ +#endif /* WOLFSSL_PSOC6_CRYPTO */ diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index dded60eb6c..ceabdc2b8e 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -22,7 +22,7 @@ #include #if (defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)) && \ - !defined(WOLFSSL_PSOC6_CRYPTO) && !defined(WOLFSSL_RISCV_ASM) + !defined(WOLFSSL_RISCV_ASM) /* determine if we are using Espressif SHA hardware acceleration */ #undef WOLFSSL_USE_ESP32_CRYPT_HASH_HW diff --git a/wolfssl/wolfcrypt/aes.h b/wolfssl/wolfcrypt/aes.h index 8efe774533..97d51a1dc4 100644 --- a/wolfssl/wolfcrypt/aes.h +++ b/wolfssl/wolfcrypt/aes.h @@ -156,6 +156,9 @@ WOLFSSL_LOCAL void GHASH(Gcm* gcm, const byte* a, word32 aSz, const byte* c, #include #endif +#if defined(WOLFSSL_PSOC6_CRYPTO) + #include "cy_crypto_common.h" +#endif /* WOLFSSL_PSOC6_CRYPTO */ #ifdef __cplusplus extern "C" { @@ -433,6 +436,12 @@ struct Aes { #ifdef WOLFSSL_AES_CTS byte ctsBlock[WC_AES_BLOCK_SIZE * 2]; #endif +#if defined(WOLFSSL_PSOC6_CRYPTO) + cy_stc_crypto_aes_state_t aes_state; +#ifdef HAVE_AESGCM + cy_stc_crypto_aes_gcm_state_t aes_gcm_state; +#endif +#endif /* WOLFSSL_PSOC6_CRYPTO */ }; #ifndef WC_AES_TYPE_DEFINED diff --git a/wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h b/wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h index c9ef31d804..e8c3e4e6ef 100644 --- a/wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h +++ b/wolfssl/wolfcrypt/port/cypress/psoc6_crypto.h @@ -30,10 +30,26 @@ #include "cy_pdl.h" -/* SHA1, SHA2 and SHA3 are supported for PSOC6 */ -#define PSOC6_HASH_SHA1 -#define PSOC6_HASH_SHA2 -#define PSOC6_HASH_SHA3 +/* Enable SHA-1 hardware acceleration if SHA-1 is enabled in wolfSSL */ +#if !defined(NO_SHA) + #define PSOC6_HASH_SHA1 +#endif + +/* Enable SHA-2 family hardware acceleration if any SHA-2 variant is enabled */ +#if !defined(NO_SHA256) || defined(WOLFSSL_SHA224) || \ + defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + #define PSOC6_HASH_SHA2 +#endif + +/* Enable SHA-3 hardware acceleration if SHA-3 is enabled in wolfSSL */ +#if defined(WOLFSSL_SHA3) + #define PSOC6_HASH_SHA3 +#endif + +/* Enable AES support for PSOC6. */ +#ifndef NO_AES + #define PSOC6_CRYPTO_AES +#endif /* !NO_AES */ typedef enum { WC_PSOC6_SHA1 = 0, @@ -48,12 +64,12 @@ typedef enum { #if defined(PSOC6_HASH_SHA1) || defined(PSOC6_HASH_SHA2) int wc_Psoc6_Sha1_Sha2_Init(void* sha, wc_psoc6_hash_sha1_sha2_t hash_mode, int init_hash); -#endif +#endif /* PSOC6_HASH_SHA1 || PSOC6_HASH_SHA2 */ #if defined(PSOC6_HASH_SHA1) || defined(PSOC6_HASH_SHA2) || \ defined(PSOC6_HASH_SHA3) -void wc_Psoc6_Sha_Free(void); -#endif +int wc_Psoc6_Sha_Free(void); +#endif /* PSOC6_HASH_SHA1 || PSOC6_HASH_SHA2 || PSOC6_HASH_SHA3 */ #if defined(WOLFSSL_SHA3) && defined(PSOC6_HASH_SHA3) @@ -63,6 +79,67 @@ int wc_Psoc6_Sha3_Final(void* sha3, byte padChar, byte* hash, byte p, word32 l); int wc_Psoc6_Shake_SqueezeBlocks(void* shake, byte* out, word32 blockCnt); #endif /* WOLFSSL_SHA3 && PSOC6_HASH_SHA3 */ +/* AES functions */ +#if defined(PSOC6_CRYPTO_AES) +struct Aes; /* Forward declaration */ + +int wc_Psoc6_Aes_SetKey(struct Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir); +void wc_Psoc6_Aes_Free(struct Aes* aes); +int wc_Psoc6_Aes_Encrypt(struct Aes* aes, const byte* in, byte* out); +#ifdef HAVE_AES_DECRYPT +int wc_Psoc6_Aes_Decrypt(struct Aes* aes, const byte* in, byte* out); +#endif /* HAVE_AES_DECRYPT */ + +#ifdef WOLFSSL_AES_DIRECT +int wc_Psoc6_Aes_EncryptDirect(struct Aes* aes, byte* out, const byte* in); +#ifdef HAVE_AES_DECRYPT +int wc_Psoc6_Aes_DecryptDirect(struct Aes* aes, byte* out, const byte* in); +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_DIRECT */ + +#ifdef HAVE_AES_ECB +int wc_Psoc6_Aes_EcbEncrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz); +#ifdef HAVE_AES_DECRYPT +int wc_Psoc6_Aes_EcbDecrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_ECB */ + +#ifdef HAVE_AES_CBC +int wc_Psoc6_Aes_CbcEncrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz); +#ifdef HAVE_AES_DECRYPT +int wc_Psoc6_Aes_CbcDecrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_CBC */ + +#ifdef WOLFSSL_AES_CFB +int wc_Psoc6_Aes_CfbEncrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz); +#ifdef HAVE_AES_DECRYPT +int wc_Psoc6_Aes_CfbDecrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_CFB */ + +#ifdef HAVE_AESGCM +int wc_Psoc6_Aes_Gcm_SetKey(struct Aes* aes, const byte* key, word32 len); +int wc_Psoc6_Aes_GcmEncrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz, const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, const byte* authIn, + word32 authInSz); +#ifdef HAVE_AES_DECRYPT +int wc_Psoc6_Aes_GcmDecrypt(struct Aes* aes, byte* out, const byte* in, + word32 sz, const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AESGCM */ +#endif /* NO_AES */ + #ifdef HAVE_ECC /* Forward declaration of ecc_key structure.