/* * Copyright 2017-2023 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #ifndef FSL_HASHCRYPT_H_ #define FSL_HASHCRYPT_H_ #include "fsl_common.h" /*! @brief HASHCRYPT status return codes. */ enum _hashcrypt_status { kStatus_HASHCRYPT_Again = MAKE_STATUS(kStatusGroup_HASHCRYPT, 0), /*!< Non-blocking function shall be called again. */ }; /******************************************************************************* * Definitions *******************************************************************************/ /*! * @addtogroup hashcrypt_driver * @{ */ /*! @name Driver version */ /*! @{ */ /*! @brief HASHCRYPT driver version. Version 2.2.14. * * Current version: 2.2.14 * * Change log: * - Version 2.0.0 * - Initial version * - Version 2.0.1 * - Support loading AES key from unaligned address * - Version 2.0.2 * - Support loading AES key from unaligned address for different compiler and core variants * - Version 2.0.3 * - Remove SHA512 and AES ICB algorithm definitions * - Version 2.0.4 * - Add SHA context switch support * - Version 2.1.0 * - Update the register name and macro to align with new header. * - Version 2.1.1 * - Fix MISRA C-2012. * - Version 2.1.2 * - Support loading AES input data from unaligned address. * - Version 2.1.3 * - Fix MISRA C-2012. * - Version 2.1.4 * - Fix context switch cannot work when switching from AES. * - Version 2.1.5 * - Add data synchronization barrier inside hashcrypt_sha_ldm_stm_16_words() * to prevent possible optimization issue. * - Version 2.2.0 * - Add AES-OFB and AES-CFB mixed IP/SW modes. * - Version 2.2.1 * - Add data synchronization barrier inside hashcrypt_sha_ldm_stm_16_words() * prevent compiler from reordering memory write when -O2 or higher is used. * - Version 2.2.2 * - Add data synchronization barrier inside hashcrypt_sha_ldm_stm_16_words() * to fix optimization issue * - Version 2.2.3 * - Added check for size in hashcrypt_aes_one_block to prevent overflowing COUNT field in MEMCTRL register, if its * bigger than COUNT field do a multiple runs. * - Version 2.2.4 * - In all HASHCRYPT_AES_xx functions have been added setting CTRL_MODE bitfield to 0 after processing data, which * decreases power consumption. * - Version 2.2.5 * - Add data synchronization barrier and instruction synchronization barrier inside * hashcrypt_sha_process_message_data() to fix optimization issue * - Version 2.2.6 * - Add data synchronization barrier inside HASHCRYPT_SHA_Update() and hashcrypt_get_data() function to fix * optimization issue on MDK and ARMGCC release targets * - Version 2.2.7 * - Add data synchronization barrier inside HASHCRYPT_SHA_Update() to fix optimization issue on MCUX IDE release * target * - Version 2.2.8 * - Unify hashcrypt hashing behavior between aligned and unaligned input data * - Version 2.2.9 * - Add handling of set ERROR bit in the STATUS register * - Version 2.2.10 * - Fix missing error statement in hashcrypt_save_running_hash() * - Version 2.2.11 * - Fix incorrect SHA-256 calculation for long messages with reload * - Version 2.2.12 * - Fix hardfault issue on the Keil compiler due to unaligned memcpy() input on some optimization levels * - Version 2.2.13 * - Added function hashcrypt_seed_prng() which loading random number into PRNG_SEED register before AES operation for * SCA protection * - Version 2.2.14 * - Modify function hashcrypt_get_data() to prevent issue with unaligned access */ #define FSL_HASHCRYPT_DRIVER_VERSION (MAKE_VERSION(2, 2, 14)) /*! @} */ /*! @brief Algorithm definitions correspond with the values for Mode field in Control register !*/ #define HASHCRYPT_MODE_SHA1 0x1 #define HASHCRYPT_MODE_SHA256 0x2 #define HASHCRYPT_MODE_AES 0x4 /*! @brief Algorithm used for Hashcrypt operation */ typedef enum _hashcrypt_algo_t { kHASHCRYPT_Sha1 = HASHCRYPT_MODE_SHA1, /*!< SHA_1 */ kHASHCRYPT_Sha256 = HASHCRYPT_MODE_SHA256, /*!< SHA_256 */ kHASHCRYPT_Aes = HASHCRYPT_MODE_AES, /*!< AES */ } hashcrypt_algo_t; /*! @} */ /******************************************************************************* * AES Definitions *******************************************************************************/ /*! * @addtogroup hashcrypt_driver_aes * @{ */ /*! AES block size in bytes */ #define HASHCRYPT_AES_BLOCK_SIZE 16U #define AES_ENCRYPT 0 #define AES_DECRYPT 1 /*! @brief AES mode */ typedef enum _hashcrypt_aes_mode_t { kHASHCRYPT_AesEcb = 0U, /*!< AES ECB mode */ kHASHCRYPT_AesCbc = 1U, /*!< AES CBC mode */ kHASHCRYPT_AesCtr = 2U, /*!< AES CTR mode */ } hashcrypt_aes_mode_t; /*! @brief Size of AES key */ typedef enum _hashcrypt_aes_keysize_t { kHASHCRYPT_Aes128 = 0U, /*!< AES 128 bit key */ kHASHCRYPT_Aes192 = 1U, /*!< AES 192 bit key */ kHASHCRYPT_Aes256 = 2U, /*!< AES 256 bit key */ kHASHCRYPT_InvalidKey = 3U, /*!< AES invalid key */ } hashcrypt_aes_keysize_t; /*! @brief HASHCRYPT key source selection. * */ typedef enum _hashcrypt_key { kHASHCRYPT_UserKey = 0xc3c3U, /*!< HASHCRYPT user key */ kHASHCRYPT_SecretKey = 0x3c3cU, /*!< HASHCRYPT secret key (dedicated hw bus from PUF) */ } hashcrypt_key_t; /*! @brief Specify HASHCRYPT's key resource. */ struct _hashcrypt_handle { uint32_t keyWord[8]; /*!< Copy of user key (set by HASHCRYPT_AES_SetKey(). */ hashcrypt_aes_keysize_t keySize; hashcrypt_key_t keyType; /*!< For operations with key (such as AES encryption/decryption), specify key type. */ } __attribute__((aligned)); typedef struct _hashcrypt_handle hashcrypt_handle_t; /*! *@} */ /* end of hashcrypt_driver_aes */ /******************************************************************************* * HASH Definitions ******************************************************************************/ /*! * @addtogroup hashcrypt_driver_hash * @{ */ /*! @brief HASHCRYPT HASH Context size. */ #if defined(FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE) && (FSL_FEATURE_HASHCRYPT_HAS_RELOAD_FEATURE > 0) #define HASHCRYPT_HASH_CTX_SIZE 30 #else #define HASHCRYPT_HASH_CTX_SIZE 22 #endif /*! @brief Storage type used to save hash context. */ typedef struct _hashcrypt_hash_ctx_t { uint32_t x[HASHCRYPT_HASH_CTX_SIZE]; /*!< storage */ } hashcrypt_hash_ctx_t; /*! @brief HASHCRYPT background hash callback function. */ typedef void (*hashcrypt_callback_t)(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, status_t status, void *userData); /*! *@} */ /* end of hashcrypt_driver_hash */ /******************************************************************************* * API ******************************************************************************/ #if defined(__cplusplus) extern "C" { #endif /*! * @addtogroup hashcrypt_driver * @{ */ /*! * @brief Enables clock and disables reset for HASHCRYPT peripheral. * * Enable clock and disable reset for HASHCRYPT. * * @param base HASHCRYPT base address */ void HASHCRYPT_Init(HASHCRYPT_Type *base); /*! * @brief Disables clock for HASHCRYPT peripheral. * * Disable clock and enable reset. * * @param base HASHCRYPT base address */ void HASHCRYPT_Deinit(HASHCRYPT_Type *base); /*! *@} */ /* end of hashcrypt_driver */ /******************************************************************************* * AES API ******************************************************************************/ /*! * @addtogroup hashcrypt_driver_aes * @{ */ /*! * @brief Set AES key to hashcrypt_handle_t struct and optionally to HASHCRYPT. * * Sets the AES key for encryption/decryption with the hashcrypt_handle_t structure. * The hashcrypt_handle_t input argument specifies key source. * * @param base HASHCRYPT peripheral base address. * @param handle Handle used for the request. * @param key 0-mod-4 aligned pointer to AES key. * @param keySize AES key size in bytes. Shall equal 16, 24 or 32. * @return status from set key operation */ status_t HASHCRYPT_AES_SetKey(HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *key, size_t keySize); /*! * @brief Encrypts AES on one or multiple 128-bit block(s). * * Encrypts AES. * The source plaintext and destination ciphertext can overlap in system memory. * * @param base HASHCRYPT peripheral base address * @param handle Handle used for this request. * @param plaintext Input plain text to encrypt * @param[out] ciphertext Output cipher text * @param size Size of input and output data in bytes. Must be multiple of 16 bytes. * @return Status from encrypt operation */ status_t HASHCRYPT_AES_EncryptEcb( HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size); /*! * @brief Decrypts AES on one or multiple 128-bit block(s). * * Decrypts AES. * The source ciphertext and destination plaintext can overlap in system memory. * * @param base HASHCRYPT peripheral base address * @param handle Handle used for this request. * @param ciphertext Input plain text to encrypt * @param[out] plaintext Output cipher text * @param size Size of input and output data in bytes. Must be multiple of 16 bytes. * @return Status from decrypt operation */ status_t HASHCRYPT_AES_DecryptEcb( HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size); /*! * @brief Encrypts AES using CBC block mode. * * @param base HASHCRYPT peripheral base address * @param handle Handle used for this request. * @param plaintext Input plain text to encrypt * @param[out] ciphertext Output cipher text * @param size Size of input and output data in bytes. Must be multiple of 16 bytes. * @param iv Input initial vector to combine with the first input block. * @return Status from encrypt operation */ status_t HASHCRYPT_AES_EncryptCbc(HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size, const uint8_t iv[16]); /*! * @brief Decrypts AES using CBC block mode. * * @param base HASHCRYPT peripheral base address * @param handle Handle used for this request. * @param ciphertext Input cipher text to decrypt * @param[out] plaintext Output plain text * @param size Size of input and output data in bytes. Must be multiple of 16 bytes. * @param iv Input initial vector to combine with the first input block. * @return Status from decrypt operation */ status_t HASHCRYPT_AES_DecryptCbc(HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size, const uint8_t iv[16]); /*! * @brief Encrypts or decrypts AES using CTR block mode. * * Encrypts or decrypts AES using CTR block mode. * AES CTR mode uses only forward AES cipher and same algorithm for encryption and decryption. * The only difference between encryption and decryption is that, for encryption, the input argument * is plain text and the output argument is cipher text. For decryption, the input argument is cipher text * and the output argument is plain text. * * @param base HASHCRYPT peripheral base address * @param handle Handle used for this request. * @param input Input data for CTR block mode * @param[out] output Output data for CTR block mode * @param size Size of input and output data in bytes * @param[in,out] counter Input counter (updates on return) * @param[out] counterlast Output cipher of last counter, for chained CTR calls (statefull encryption). NULL can be * passed if chained calls are * not used. * @param[out] szLeft Output number of bytes in left unused in counterlast block. NULL can be passed if chained calls * are not used. * @return Status from encrypt operation */ status_t HASHCRYPT_AES_CryptCtr(HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *input, uint8_t *output, size_t size, uint8_t counter[HASHCRYPT_AES_BLOCK_SIZE], uint8_t counterlast[HASHCRYPT_AES_BLOCK_SIZE], size_t *szLeft); /*! * @brief Encrypts or decrypts AES using OFB block mode. * * Encrypts or decrypts AES using OFB block mode. * AES OFB mode uses only forward AES cipher and same algorithm for encryption and decryption. * The only difference between encryption and decryption is that, for encryption, the input argument * is plain text and the output argument is cipher text. For decryption, the input argument is cipher text * and the output argument is plain text. * * @param base HASHCRYPT peripheral base address * @param handle Handle used for this request. * @param input Input data for OFB block mode * @param[out] output Output data for OFB block mode * @param size Size of input and output data in bytes * @param iv Input initial vector to combine with the first input block. * @return Status from encrypt operation */ status_t HASHCRYPT_AES_CryptOfb(HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *input, uint8_t *output, size_t size, const uint8_t iv[HASHCRYPT_AES_BLOCK_SIZE]); /*! * @brief Encrypts AES using CFB block mode. * * @param base HASHCRYPT peripheral base address * @param handle Handle used for this request. * @param plaintext Input plain text to encrypt * @param[out] ciphertext Output cipher text * @param size Size of input and output data in bytes. Must be multiple of 16 bytes. * @param iv Input initial vector to combine with the first input block. * @return Status from encrypt operation */ status_t HASHCRYPT_AES_EncryptCfb(HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *plaintext, uint8_t *ciphertext, size_t size, const uint8_t iv[16]); /*! * @brief Decrypts AES using CFB block mode. * * @param base HASHCRYPT peripheral base address * @param handle Handle used for this request. * @param ciphertext Input cipher text to decrypt * @param[out] plaintext Output plaintext text * @param size Size of input and output data in bytes. Must be multiple of 16 bytes. * @param iv Input initial vector to combine with the first input block. * @return Status from encrypt operation */ status_t HASHCRYPT_AES_DecryptCfb(HASHCRYPT_Type *base, hashcrypt_handle_t *handle, const uint8_t *ciphertext, uint8_t *plaintext, size_t size, const uint8_t iv[16]); /*! *@} */ /* end of hashcrypt_driver_aes */ /******************************************************************************* * HASH API ******************************************************************************/ /*! * @addtogroup hashcrypt_driver_hash * @{ */ /*! * @brief Create HASH on given data * * Perform the full SHA in one function call. The function is blocking. * * @param base HASHCRYPT peripheral base address * @param algo Underlaying algorithm to use for hash computation. * @param input Input data * @param inputSize Size of input data in bytes * @param[out] output Output hash data * @param[out] outputSize Output parameter storing the size of the output hash in bytes * @return Status of the one call hash operation. */ status_t HASHCRYPT_SHA(HASHCRYPT_Type *base, hashcrypt_algo_t algo, const uint8_t *input, size_t inputSize, uint8_t *output, size_t *outputSize); /*! * @brief Initialize HASH context * * This function initializes the HASH. * * @param base HASHCRYPT peripheral base address * @param[out] ctx Output hash context * @param algo Underlaying algorithm to use for hash computation. * @return Status of initialization */ status_t HASHCRYPT_SHA_Init(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, hashcrypt_algo_t algo); /*! * @brief Add data to current HASH * * Add data to current HASH. This can be called repeatedly with an arbitrary amount of data to be * hashed. The functions blocks. If it returns kStatus_Success, the running hash * has been updated (HASHCRYPT has processed the input data), so the memory at \p input pointer * can be released back to system. The HASHCRYPT context buffer is updated with the running hash * and with all necessary information to support possible context switch. * * @param base HASHCRYPT peripheral base address * @param[in,out] ctx HASH context * @param input Input data * @param inputSize Size of input data in bytes * @return Status of the hash update operation */ status_t HASHCRYPT_SHA_Update(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize); /*! * @brief Finalize hashing * * Outputs the final hash (computed by HASHCRYPT_HASH_Update()) and erases the context. * * @param base HASHCRYPT peripheral base address * @param[in,out] ctx Input hash context * @param[out] output Output hash data * @param[in,out] outputSize Optional parameter (can be passed as NULL). On function entry, it specifies the size of * output[] buffer. On function return, it stores the number of updated output bytes. * @return Status of the hash finish operation */ status_t HASHCRYPT_SHA_Finish(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, uint8_t *output, size_t *outputSize); /*! *@} */ /* end of hashcrypt_driver_hash */ /*! * @addtogroup hashcrypt_background_driver_hash * @{ */ /*! * @brief Initializes the HASHCRYPT handle for background hashing. * * This function initializes the hash context for background hashing * (Non-blocking) APIs. This is less typical interface to hash function, but can be used * for parallel processing, when main CPU has something else to do. * Example is digital signature RSASSA-PKCS1-V1_5-VERIFY((n,e),M,S) algorithm, where * background hashing of M can be started, then CPU can compute S^e mod n * (in parallel with background hashing) and once the digest becomes available, * CPU can proceed to comparison of EM with EM'. * * @param base HASHCRYPT peripheral base address. * @param[out] ctx Hash context. * @param callback Callback function. * @param userData User data (to be passed as an argument to callback function, once callback is invoked from isr). */ void HASHCRYPT_SHA_SetCallback(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, hashcrypt_callback_t callback, void *userData); /*! * @brief Create running hash on given data. * * Configures the HASHCRYPT to compute new running hash as AHB master * and returns immediately. HASHCRYPT AHB Master mode supports only aligned \p input * address and can be called only once per continuous block of data. Every call to this function * must be preceded with HASHCRYPT_SHA_Init() and finished with HASHCRYPT_SHA_Finish(). * Once callback function is invoked by HASHCRYPT isr, it should set a flag * for the main application to finalize the hashing (padding) and to read out the final digest * by calling HASHCRYPT_SHA_Finish(). * * @param base HASHCRYPT peripheral base address * @param ctx Specifies callback. Last incomplete 512-bit block of the input is copied into clear buffer for padding. * @param input 32-bit word aligned pointer to Input data. * @param inputSize Size of input data in bytes (must be word aligned) * @return Status of the hash update operation. */ status_t HASHCRYPT_SHA_UpdateNonBlocking(HASHCRYPT_Type *base, hashcrypt_hash_ctx_t *ctx, const uint8_t *input, size_t inputSize); /*! *@} */ /* end of hashcrypt_background_driver_hash */ #if defined(__cplusplus) } #endif #endif /* FSL_HASHCRYPT_H_ */