/* * Copyright (c) 2018-2024, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /*!**************************************************************************** * @file AESCTR.h * * @brief AESCTR driver header * * @anchor ti_drivers_AESCTR_Overview *

Overview

* The Counter (CTR) mode of operation is a generic block cipher mode of operation * that can be used with any block cipher including AES which is used in this * implementation. * * CTR mode encrypts and decrypts messages. It is not required for the message * length to be evenly divisible by the cipher block size. This also means * that padding the message is not required. * *

Operation

* CTR encryption and decryption perform the following steps: * -# Set the counter value to the initial counter value * -# Encrypt the counter value under the symmetric key * -# XOR the encrypted counter value with the input block (plaintext or ciphertext) * -# Increment the counter value. Interpret the byte array as a big-endian number. * -# Repeat steps 2 to 4 until the input is completely processed. If the * input is not evenly divisible by the block size, XOR the last * (u = input length % block size) input bytes with the most significant * u bytes of the last encrypted counter value. * * CTR performs the same steps regardless of whether it is used to * encrypt or decrypt a message. The input merely changes. * *

Choosing Initial Counter Values

* CTR requires that each counter value used to encrypt a block of a message * is unique for each key used. If this requirement is not kept, the * confidentiality of that message block may be compromised. * * There are two general strategies when choosing the initial counter value * of a CTR operation to ensure this requirement holds. * * The first is to choose an initial counter value for the first message * and increment the initial counter value for a subsequent message by * by message length % block length (16-bytes for AES). This effectively * turns a sequence of messages into one long message. If 0 is chosen * as the initial counter value, up to 2^128 - 1 blocks may be encrypted before * key rotation is mandatory. * * The second is to split the initial counter value into a nonce and * counter section. The nonce of length n bits must be unique per message. * This allows for up to 2^n - 1 messages to be encrypted before * key rotation is required. The counter section of length c is incremented * as usual. This limits messages to a length of at most 2^c - 1 blocks. * n and c must be chosen such that n + c = block length in bits * (128 bits for AES) holds. * * @anchor ti_drivers_AESCTR_Usage *

Usage

*

Before starting a CTR operation

* * Before starting a CTR operation, the application must do the following: * - Call #AESCTR_init() to initialize the driver * - Call #AESCTR_Params_init() to initialize the #AESCTR_Params to default values. * - Modify the #AESCTR_Params as desired * - Call #AESCTR_open() to open an instance of the driver * - Initialize a CryptoKey. These opaque data structures are representations * of keying material and its storage. Depending on how the keying material * is stored (RAM or flash, key store), the CryptoKey must be * initialized differently. The AESCTR API can handle all types of CryptoKey. * However, not all device-specific implementations support all types of CryptoKey. * Devices without a key store will not support CryptoKeys with keying material * stored in a key store for example. * All devices support plaintext CryptoKeys. * - Initialize a single-step AESCTR operation using #AESCTR_OneStepOperation_init() * which is equivalent to the deprecated #AESCTR_Operation_init(). If it's * a segmented AESCTR operation, use #AESCTR_SegmentedOperation_init() instead. * Then set all the fields of the one-step or segmented operation struct accordingly. * *

Starting a CTR operation

* * The AESCTR_oneStepEncrypt() and AESCTR_oneStepDecrypt() functions perform a CTR operation * in a single call. * *

After the CTR operation completes

* * After the CTR operation completes, the application should either start * another operation or close the driver by calling #AESCTR_close(). * * @anchor ti_drivers_AESCTR_Synopsis * ## Synopsis * * @anchor ti_drivers_AESCTR_Synopsis_Code * @code * * // Import AESCTR Driver definitions * #include * * // Define name for AESCTR channel index * #define AESCTR_INSTANCE 0 * * AESCTR_init(); * * handle = AESCTR_open(AESCTR_INSTANCE, NULL); * * // Initialize symmetric key * CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial)); * * // Set up AESCTR_Operation * AESCTR_OneStepOperation_init(&operation); * operation.key = &cryptoKey; * operation.input = plaintext; * operation.output = ciphertext; * operation.inputLength = sizeof(plaintext); * operation.initialCounter = initialCounter; * * encryptionResult = AESCTR_oneStepEncrypt(handle, &operation); * * AESCTR_close(handle); * @endcode * * @anchor ti_drivers_AESCTR_Examples *

Examples

* *
One step CTR encryption with plaintext CryptoKey in blocking return mode
* @code * * #include * #include * * ... * * AESCTR_Handle handle; * CryptoKey cryptoKey; * int_fast16_t encryptionResult; * * // For example purposes only. Generate IVs in a non-static way in practice. * // Test vector from NIST SP 800-38A * uint8_t initialCounter[16] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, * 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}; * uint8_t plaintext[64] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, * 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, * 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, * 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, * 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, * 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, * 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, * 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10}; * uint8_t ciphertext[sizeof(plaintext)]; * uint8_t keyingMaterial[16] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, * 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; * * handle = AESCTR_open(0, NULL); * * if (handle == NULL) { * // handle error * while(1); * } * * CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial)); * * AESCTR_OneStepOperation operation; * AESCTR_OneStepOperation_init(&operation); * * operation.key = &cryptoKey; * operation.input = plaintext; * operation.output = ciphertext; * operation.inputLength = sizeof(plaintext); * operation.initialCounter = initialCounter; * * encryptionResult = AESCTR_oneStepEncrypt(handle, &operation); * * if (encryptionResult != AESCTR_STATUS_SUCCESS) { * // handle error * while(1); * } * * // The ciphertext should be the following after the encryption operation: * // 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, * // 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, * // 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, * // 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, * // 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, * // 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, * // 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, * // 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee * * AESCTR_close(handle); * * @endcode * *

The following code snippet is for CC27XX devices only and leverages the HSM which is a seperate Hardware * Accelerator

* *
One step CTR encryption with plaintext CryptoKey in blocking return mode using the HSM accelerator
* @code * * #include * #include * * ... * * AESCTR_Handle handle; * CryptoKey cryptoKey; * int_fast16_t encryptionResult; * * // For example purposes only. Generate IVs in a non-static way in practice. * // Test vector from NIST SP 800-38A * uint8_t initialCounter[16] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, * 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}; * uint8_t plaintext[64] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, * 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, * 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, * 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, * 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, * 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, * 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, * 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10}; * uint8_t ciphertext[sizeof(plaintext)]; * uint8_t keyingMaterial[16] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, * 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; * * handle = AESCTR_open(0, NULL); * * if (handle == NULL) { * // handle error * while(1); * } * * CryptoKeyPlaintextHSM_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial)); * * AESCTR_OneStepOperation operation; * AESCTR_OneStepOperation_init(&operation); * * operation.key = &cryptoKey; * operation.input = plaintext; * operation.output = ciphertext; * operation.inputLength = sizeof(plaintext); * operation.initialCounter = initialCounter; * * encryptionResult = AESCTR_oneStepEncrypt(handle, &operation); * * if (encryptionResult != AESCTR_STATUS_SUCCESS) { * // handle error * while(1); * } * * // The ciphertext should be the following after the encryption operation: * // 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, * // 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, * // 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, * // 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, * // 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, * // 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, * // 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, * // 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee * * AESCTR_close(handle); * * @endcode * *
One step CTR decryption with plaintext CryptoKey in callback return mode
* @code * * #include * #include * * ... * * * void ctrCallback(AESCTR_Handle handle, * int_fast16_t returnValue, * AESCTR_OperationUnion *operation, * AESCTR_OperationType operationType) { * * if (returnValue != AESCTR_STATUS_SUCCESS) { * // handle error * while(1); * } * } * AESCTR_Operation operation; * * void ctrStartFunction(void) { * uint8_t initialCounter[16] = {0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, * 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01}; * uint8_t ciphertext[] = {0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, * 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, * 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, * 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, * 0x25, 0xB2, 0x07, 0x2F}; * uint8_t keyingMaterial[] = {0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, * 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC}; * uint8_t plaintext[sizeof(ciphertext)]; * * AESCTR_Handle handle; * AESCTR_Params params; * CryptoKey cryptoKey; * int_fast16_t decryptionResult; * * AESCTR_OneStepOperation operation; * * AESCTR_Params_init(¶ms); * params.returnBehavior = AESCTR_RETURN_BEHAVIOR_CALLBACK; * params.callbackFxn = ctrCallback; * * handle = AESCTR_open(0, ¶ms); * * if (handle == NULL) { * // handle error * while(1); * } * * CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial)); * * AESCTR_OneStepOperation_init(&operation); // Optional as all struct members will be set before use. * * operation.key = &cryptoKey; * operation.input = ciphertext; * operation.output = plaintext; * operation.inputLength = sizeof(ciphertext); * operation.initialCounter = initialCounter; * * decryptionResult = AESCTR_oneStepDecrypt(handle, &operation); * * if (decryptionResult != AESCTR_STATUS_SUCCESS) { * // handle error * while(1); * } * * // do other things while CTR operation completes in the background * * // After the operation completes and the callback is invoked, the resultant * // plaintext should be: * // 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, * // 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, * // 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, * // 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, * // 0x20, 0x21, 0x22, 0x23 * * AESCTR_close(handle); * } * * @endcode * *
Multi-step AES CTR encrypt with plaintext CryptoKey in polling return mode
* @code * * #include * #include * * #define AES_BLOCK_SIZE 16 // bytes * ... * * AESCTR_Params params; * AESCTR_Handle handle; * CryptoKey cryptoKey; * int_fast16_t retVal; * * // For example purposes only. * uint8_t plaintext[36] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, * 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, * 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, * 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, * 0x20, 0x21, 0x22, 0x23}; * uint8_t initialCounter[] = {0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, * 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01}; * uint8_t keyingMaterial[] = {0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, * 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC}; * uint8_t ciphertext[sizeof(plaintext)]; * * AESCTR_Params_init(¶ms) * params.returnBehavior = AESCTR_RETURN_BEHAVIOR_POLLING; * * handle = AESCTR_open(0, ¶ms); * * if (handle == NULL) { * // handle error * } * * CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial)); * * AESCTR_SegmentedOperation operation; * AESCTR_SegmentedOperation_init(&operation); // Optional as all struct members will be set before use. * * retVal = AESCTR_setupEncrypt(handle, &cryptoKey, initialCounter); * * if (retVal != AESCTR_STATUS_SUCCESS) { * // handle error * } * * operation.input = plaintext; * operation.inputLength = AES_BLOCK_SIZE; // Only block multiple lengths are permitted when adding data. * operation.output = ciphertext; * * retVal = AESCTR_addData(handle, &operation); * * if (retVal != AESCTR_STATUS_SUCCESS) { * // handle error * } * * operation.input = plaintext + AES_BLOCK_SIZE; * operation.inputLength = sizeof(plaintext) - AES_BLOCK_SIZE; // Non-block multiple length permitted during * finalization. operation.output = ciphertext + AES_BLOCK_SIZE; * * retVal = AESCTR_finalize(handle, &operation); * * if (retVal != AESCTR_STATUS_SUCCESS) { * // handle error * } * * // Upon successful return, the resulting ciphertext should be: * // 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, * // 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, * // 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, * // 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, * // 0x25, 0xB2, 0x07, 0x2F * * AESCTR_close(handle); * * @endcode */ #ifndef ti_drivers_AESCTR__include #define ti_drivers_AESCTR__include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /*! * Common AESCTR status code reservation offset. * AESCTR driver implementations should offset status codes with * #AESCTR_STATUS_RESERVED growing negatively. * * Example implementation specific status codes: * @code * #define AESCTRXYZ_STATUS_ERROR0 AESCTR_STATUS_RESERVED - 0 * #define AESCTRXYZ_STATUS_ERROR1 AESCTR_STATUS_RESERVED - 1 * #define AESCTRXYZ_STATUS_ERROR2 AESCTR_STATUS_RESERVED - 2 * @endcode */ #define AESCTR_STATUS_RESERVED AES_STATUS_RESERVED /*! * @brief Successful status code. * * Functions return #AESCTR_STATUS_SUCCESS if the function was executed * successfully. */ #define AESCTR_STATUS_SUCCESS AES_STATUS_SUCCESS /*! * @brief Generic error status code. * * Functions return #AESCTR_STATUS_ERROR if the function was not executed * successfully and no more pertinent error code could be returned. */ #define AESCTR_STATUS_ERROR AES_STATUS_ERROR /*! * @brief An error status code returned if the hardware or software resource * is currently unavailable. * * AESCTR driver implementations may have hardware or software limitations on how * many clients can simultaneously perform operations. This status code is returned * if the mutual exclusion mechanism signals that an operation cannot currently be performed. */ #define AESCTR_STATUS_RESOURCE_UNAVAILABLE AES_STATUS_RESOURCE_UNAVAILABLE /*! * @brief The ongoing operation was canceled. */ #define AESCTR_STATUS_CANCELED AES_STATUS_CANCELED /*! * @brief The operation requested is not supported. */ #define AESCTR_STATUS_FEATURE_NOT_SUPPORTED AES_STATUS_FEATURE_NOT_SUPPORTED /*! * @brief The operation tried to load a key from the keystore using an invalid key ID. */ #define AESCTR_STATUS_KEYSTORE_INVALID_ID AES_STATUS_KEYSTORE_INVALID_ID /*! * @brief The key store module returned a generic error. See key store documentation * for additional details. */ #define AESCTR_STATUS_KEYSTORE_GENERIC_ERROR AES_STATUS_KEYSTORE_GENERIC_ERROR /*! * @brief The operation does not support non-word-aligned input and/or output. * * AESCTR driver implementations may have restrictions on the alignment of * input/output data due to performance limitations of the hardware. */ #define AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED AES_STATUS_UNALIGNED_IO_NOT_SUPPORTED /*! * @brief The way in which CTR function calls return after performing an * encryption or decryption operation. * * Not all CTR operations exhibit the specified return behavior. Functions that do not * require significant computation and cannot offload that computation to a background thread * behave like regular functions. Which functions exhibit the specified return behavior is not * implementation dependent. Specifically, a software-backed implementation run on the same * CPU as the application will emulate the return behavior while not actually offloading * the computation to the background thread. * * AESCTR functions exhibiting the specified return behavior have restrictions on the * context from which they may be called. * * | | Task | Hwi | Swi | * |--------------------------------|-------|-------|-------| * |AESCTR_RETURN_BEHAVIOR_CALLBACK | X | X | X | * |AESCTR_RETURN_BEHAVIOR_BLOCKING | X | | | * |AESCTR_RETURN_BEHAVIOR_POLLING | X | X | X | * */ typedef enum { AESCTR_RETURN_BEHAVIOR_CALLBACK = AES_RETURN_BEHAVIOR_CALLBACK, /*!< The function call will return immediately while the * CTR operation goes on in the background. The registered * callback function is called after the operation completes. * The context the callback function is called (task, HWI, SWI) * is implementation-dependent. */ AESCTR_RETURN_BEHAVIOR_BLOCKING = AES_RETURN_BEHAVIOR_BLOCKING, /*!< The function call will block while the CTR operation goes * on in the background. CTR operation results are available * after the function returns. */ AESCTR_RETURN_BEHAVIOR_POLLING = AES_RETURN_BEHAVIOR_POLLING, /*!< The function call will continuously poll a flag while CTR * operation goes on in the background. CTR operation results * are available after the function returns. */ } AESCTR_ReturnBehavior; /*! * @brief Struct containing the parameters required for encrypting/decrypting * a message using a one-step operation. * * The driver may access it at any point during the operation. It must remain * in scope for the entire duration of the operation. */ typedef struct { const CryptoKey *key; /*!< Pointer to a previously initialized CryptoKey. */ const uint8_t *input; /*!< * - Encryption: The plaintext buffer to be * encrypted in the CTR operation. * - Decryption: The ciphertext to be decrypted. */ uint8_t *output; /*!< * - Encryption: The output ciphertext buffer that * the encrypted plaintext is copied to. * - Decryption: The plaintext derived from the * decrypted ciphertext is copied here. * Size of the output buffer must be greater than * or equal to the inputLength. */ const uint8_t *initialCounter; /*!< A buffer containing an initial counter. Under * the same key, each counter value may only be * used to encrypt or decrypt a single input * block. If NULL, zero will be used for the * initial counter value. The buffer's size must * be at least 16-bytes. */ size_t inputLength; /*!< Length of the input in bytes. An equal number * of bytes will be output by the operation. * Max length supported may be limited depending on * the return behavior. */ } AESCTR_OneStepOperation; /*! * @brief Struct containing the parameters required for encrypting/decrypting * a message using a segmented operation. This struct must be updated * for each "add data" and "finalize" step. Modifying the structure and any buffers that * it points to while an operation is in progress is prohibited. * * The driver may access it at any point during the operation. It must remain * in scope for the entire duration of the operation. */ typedef struct { const uint8_t *input; /*!< * - Encryption: The plaintext buffer to be * encrypted in the CTR operation. * - Decryption: The ciphertext to be decrypted. */ uint8_t *output; /*!< * - Encryption: The output ciphertext buffer that * the encrypted plaintext is copied to. * - Decryption: The plaintext derived from the * decrypted ciphertext is copied here. * Size of the output buffer must be greater than * or equal to the inputLength. */ size_t inputLength; /*!< Length of the input in bytes. An equal number * of bytes will be output by the operation. Must * be a non-zero multiple of block size (16-bytes) when * calling #AESCTR_addData(). May be zero when calling * #AESCTR_finalize() to finalize a segmented * operation without additional data. */ } AESCTR_SegmentedOperation; /** * @deprecated * Define a typedef for deprecated operation AESCTR_Operation. * Existing code should be refactored to use AESCTR_OneStepOperation. * This reference may be removed at some point in the future. */ typedef AESCTR_OneStepOperation AESCTR_Operation; /*! * @brief Union containing a reference to a one-step and segmented operation * structure. */ typedef union { AESCTR_OneStepOperation oneStepOperation; /* One-step operation element of the operation union */ AESCTR_SegmentedOperation segmentedOperation; /* Segmented operation element of the operation union */ } AESCTR_OperationUnion; /*! * @brief Enum for the direction of the CTR operation. */ typedef enum { AESCTR_MODE_ENCRYPT = 1, AESCTR_MODE_DECRYPT = 2, } AESCTR_Mode; /*! * @brief Mask for the operation mode. */ #define AESCTR_OP_MODE_MASK 0x0F /*! * @brief Flag indicating a segmented operation. */ #define AESCTR_OP_FLAG_SEGMENTED 0x10 /* bit 4 */ /*! * @brief Flag indicating a finalize operation. */ #define AESCTR_OP_FLAG_FINALIZE 0x20 /* bit 5 */ /*! * @brief Mask for all valid operation flags. */ #define AESCTR_OP_FLAGS_MASK (AESCTR_OP_FLAG_SEGMENTED | AESCTR_OP_FLAG_FINALIZE) /*! * @brief Enum for the operation types supported by the driver. */ typedef enum { AESCTR_OPERATION_TYPE_ENCRYPT = AESCTR_MODE_ENCRYPT, AESCTR_OPERATION_TYPE_DECRYPT = AESCTR_MODE_DECRYPT, AESCTR_OPERATION_TYPE_ENCRYPT_SEGMENTED = (AESCTR_MODE_ENCRYPT | AESCTR_OP_FLAG_SEGMENTED), AESCTR_OPERATION_TYPE_DECRYPT_SEGMENTED = (AESCTR_MODE_DECRYPT | AESCTR_OP_FLAG_SEGMENTED), AESCTR_OPERATION_TYPE_ENCRYPT_FINALIZE = (AESCTR_MODE_ENCRYPT | AESCTR_OP_FLAG_FINALIZE), AESCTR_OPERATION_TYPE_DECRYPT_FINALIZE = (AESCTR_MODE_DECRYPT | AESCTR_OP_FLAG_FINALIZE), } AESCTR_OperationType; /*! * @brief AESCTR Global configuration * * The #AESCTR_Config structure contains a set of pointers used to characterize * the AESCTR driver implementation. * * This structure needs to be defined before calling #AESCTR_init() and it must * not be changed thereafter. * * @sa #AESCTR_init() */ typedef AESCommon_Config AESCTR_Config; /*! * @brief A handle that is returned from an #AESCTR_open() call. */ typedef AESCTR_Config *AESCTR_Handle; /*! * @brief The definition of a callback function used by the AESCTR driver * when used in ::AESCTR_RETURN_BEHAVIOR_CALLBACK * * @param handle Handle of the client that started the CTR operation. * * @param returnValue The result of the CTR operation. May contain an error code. * Informs the application of why the callback function was * called. * * @param operation Pointer to the operation union struct. * * @param operationType This parameter determines which operation the * callback refers to. */ typedef void (*AESCTR_CallbackFxn)(AESCTR_Handle handle, int_fast16_t returnValue, AESCTR_OperationUnion *operation, AESCTR_OperationType operationType); /*! * @brief CTR Parameters * * CTR Parameters are for #AESCTR_open() and #AESCTR_construct() calls. * Default values for these parameters are set using #AESCTR_Params_init(). * * @sa #AESCTR_Params_init() */ typedef struct { AESCTR_ReturnBehavior returnBehavior; /*!< Blocking, callback, or polling return behavior */ AESCTR_CallbackFxn callbackFxn; /*!< Callback function pointer */ uint32_t timeout; /*!< Timeout before the driver returns an error in * ::AESCTR_RETURN_BEHAVIOR_BLOCKING */ void *custom; /*!< Custom argument used by driver * implementation */ } AESCTR_Params; /*! * @brief Default #AESCTR_Params structure * * @sa #AESCTR_Params_init() */ extern const AESCTR_Params AESCTR_defaultParams; /*! * @brief This function initializes the CTR module. * * @pre The AESCTR_config structure must exist and be persistent before this * function can be called. This function must also be called before * any other CTR driver APIs. This function call does not modify any * peripheral registers. */ void AESCTR_init(void); /*! * @brief Function to initialize the #AESCTR_Params struct to its defaults * * @param [in] params Pointer to #AESCTR_Params structure for * initialization * * Defaults values are: * returnBehavior = AESCTR_RETURN_BEHAVIOR_BLOCKING * callbackFxn = NULL * timeout = SemaphoreP_WAIT_FOREVER * custom = NULL */ void AESCTR_Params_init(AESCTR_Params *params); /*! * @brief This function opens a given AESCTR peripheral. * * @pre AESCTR driver has been initialized using #AESCTR_init() * * @param [in] index Logical peripheral number for the CTR indexed into * the AESCTR_config table * * @param [in] params Pointer to a parameter block, if NULL it will use * default values. * * @return A #AESCTR_Handle on success or a NULL on an error or if it has * been opened already. * * @sa #AESCTR_init() * @sa #AESCTR_close() */ AESCTR_Handle AESCTR_open(uint_least8_t index, const AESCTR_Params *params); /*! * @brief Function to close a CTR peripheral specified by the AESCTR handle * * @pre #AESCTR_open() or #AESCTR_construct() * * @param [in] handle AESCTR handle * * @sa #AESCTR_open() */ void AESCTR_close(AESCTR_Handle handle); /*! * @brief Function to prepare a segmented AESCTR encryption operation. * * This function sets up a segmented AESCTR encryption operation. * * @pre #AESCTR_open() or #AESCTR_construct() * * @param [in] handle AESCTR handle * @param [in] key Pointer to a previously initialized CryptoKey * @param [in] initialCounter Pointer to initial counter value. * The buffer size must be at least 16-bytes. * If NULL, zero will be used for the initial counter value. * * @retval #AESCTR_STATUS_SUCCESS The operation succeeded. * @retval #AESCTR_STATUS_ERROR The operation failed. * * @post #AESCTR_addData() */ int_fast16_t AESCTR_setupEncrypt(AESCTR_Handle handle, const CryptoKey *key, const uint8_t *initialCounter); /*! * @brief Function to prepare a segmented AESCTR decryption operation. * * This function sets up a segmented AESCTR decryption operation. * * @pre #AESCTR_open() or #AESCTR_construct() * * @param [in] handle AESCTR handle * @param [in] key Pointer to a previously initialized CryptoKey. * @param [in] initialCounter Pointer to initial counter value. * The buffer size must be at least 16-bytes. * If NULL, zero will be used for the initial counter value. * * @retval #AESCTR_STATUS_SUCCESS The operation succeeded. * @retval #AESCTR_STATUS_ERROR The operation failed. * * @post #AESCTR_addData() */ int_fast16_t AESCTR_setupDecrypt(AESCTR_Handle handle, const CryptoKey *key, const uint8_t *initialCounter); /*! * @brief Encrypts or decrypts a segment of @a data with a @a length * * The @a inputLength must be a non-zero multiple of the block size (16-bytes). * #AESCTR_addData() may be called an arbitrary number of times before * finishing the operation with #AESCTR_finalize(). * * This function blocks until the final stream bytes have been computed. * It returns immediately when ::AESCTR_RETURN_BEHAVIOR_CALLBACK is set. * * @pre A segmented operation has been setup using #AESCTR_setupEncrypt() or * #AESCTR_setupDecrypt() * * @param [in] handle AESCTR handle * @param [in] operation Pointer to #AESCTR_SegmentedOperation structure * containing the parameters required to perform the operation. * * @retval #AESCTR_STATUS_SUCCESS The operation succeeded. * @retval #AESCTR_STATUS_ERROR The operation failed. * @retval #AESCTR_STATUS_RESOURCE_UNAVAILABLE The required hardware * resource was not available. * Try again later. * @retval #AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned. * * @post #AESCTR_addData() or #AESCTR_finalize() */ int_fast16_t AESCTR_addData(AESCTR_Handle handle, AESCTR_SegmentedOperation *operation); /*! * @brief Finalize the AES operation. If new data needs to be added, * @c inputLength will be used to govern how many bytes will be written. * * @note To finalize an operation without any additional data, * set @c inputLength to zero. The input and output buffers * will not be used in this scenario. * * @pre #AESCTR_setupEncrypt() or #AESCTR_setupDecrypt() * @pre #AESCTR_addData() * * @param [in] handle AESCTR handle * @param [in] operation Pointer to #AESCTR_SegmentedOperation structure * containing the parameters required to perform the operation. * * @retval #AESCTR_STATUS_SUCCESS In ::AESCTR_RETURN_BEHAVIOR_BLOCKING and * ::AESCTR_RETURN_BEHAVIOR_POLLING, this means the CTR * was generated successfully. In ::AESCTR_RETURN_BEHAVIOR_CALLBACK, * this means the operation started successfully. * @retval #AESCTR_STATUS_ERROR The operation failed. * @retval #AESCTR_STATUS_RESOURCE_UNAVAILABLE The required hardware * resource was not available. * Try again later. * @retval #AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned. */ int_fast16_t AESCTR_finalize(AESCTR_Handle handle, AESCTR_SegmentedOperation *operation); /*! * @brief Function to initialize an #AESCTR_Operation struct to its defaults (all zeroes) * * @deprecated Use #AESCTR_OneStepOperation_init() or #AESCTR_SegmentedOperation_init() * based on whether it is a one-step or a segmented AESCTR operation. * * @param operation Pointer to an #AESCTR_Operation structure for * initialization */ void AESCTR_Operation_init(AESCTR_Operation *operation); /*! * @brief Function to initialize an #AESCTR_OneStepOperation struct to its defaults (all zeroes) * * @param [in] operation Pointer to an #AESCTR_OneStepOperation structure for * initialization */ void AESCTR_OneStepOperation_init(AESCTR_OneStepOperation *operation); /*! * @brief Function to initialize an #AESCTR_SegmentedOperation struct to its defaults (all zeroes) * * @param [in] operation Pointer to an #AESCTR_SegmentedOperation structure for * initialization */ void AESCTR_SegmentedOperation_init(AESCTR_SegmentedOperation *operation); /*! * @brief Function to perform an AESCTR encryption operation in one call. * * @note None of the buffers provided as arguments may be altered by the application during an ongoing operation. * Doing so can yield corrupted ciphertext. * * @pre #AESCTR_open() or #AESCTR_construct() * * @param [in] handle AESCTR handle * @param [in] operation Pointer to a struct containing the parameters required to perform the operation. * * @retval #AESCTR_STATUS_SUCCESS The operation succeeded. * @retval #AESCTR_STATUS_ERROR The operation failed. * @retval #AESCTR_STATUS_RESOURCE_UNAVAILABLE The required hardware resource was not available. Try again later. * @retval #AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned. * * @sa #AESCTR_oneStepDecrypt() */ int_fast16_t AESCTR_oneStepEncrypt(AESCTR_Handle handle, AESCTR_OneStepOperation *operation); /*! * @brief Function to perform an AESCTR decryption operation in one call. * * @note None of the buffers provided as arguments may be altered by the application during an ongoing operation. * Doing so can yield corrupted plaintext. * * @pre #AESCTR_open() or #AESCTR_construct() * * @param [in] handle AESCTR handle * @param [in] operation Pointer to a struct containing the parameters required to perform the operation. * * @retval #AESCTR_STATUS_SUCCESS The operation succeeded. * @retval #AESCTR_STATUS_ERROR The operation failed. * @retval #AESCTR_STATUS_RESOURCE_UNAVAILABLE The required hardware resource was not available. Try again later. * @retval #AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned. * * @sa AESCTR_oneStepEncrypt() */ int_fast16_t AESCTR_oneStepDecrypt(AESCTR_Handle handle, AESCTR_OneStepOperation *operation); /*! * @brief Cancels an ongoing AESCTR operation. * * Asynchronously cancels an AESCTR operation. Only available when using * AESCTR_RETURN_BEHAVIOR_CALLBACK. * The operation will terminate as though an error occurred. The * return status code of the operation will be AESCTR_STATUS_CANCELED. * * @param [in] handle AESCTR handle * * @retval #AESCTR_STATUS_SUCCESS The operation was canceled or the operation had already completed. */ int_fast16_t AESCTR_cancelOperation(AESCTR_Handle handle); /** * @brief Constructs a new AESCTR object * * Unlike #AESCTR_open(), #AESCTR_construct() does not require the hwAttrs and * object to be allocated in a #AESCTR_Config array that is indexed into. * Instead, the #AESCTR_Config, hwAttrs, and object can be allocated at any * location. This allows for relatively simple run-time allocation of temporary * driver instances on the stack or the heap. * The drawback is that this makes it more difficult to write device-agnostic * code. If you use an ifdef with DeviceFamily, you can choose the correct * object and hwAttrs to allocate. That compilation unit will be tied to the * device it was compiled for at this point. To change devices, recompilation * of the application with a different DeviceFamily setting is necessary. * * @pre The object struct @c config points to must be zeroed out prior to * calling this function. Otherwise, unexpected behavior may occur. * * @param [in] config #AESCTR_Config describing the location of the object and hwAttrs. * * @param [in] params #AESCTR_Params to configure the driver instance. * * @return Returns a #AESCTR_Handle on success or NULL on failure. * */ AESCTR_Handle AESCTR_construct(AESCTR_Config *config, const AESCTR_Params *params); #ifdef __cplusplus } #endif #endif /* ti_drivers_AESCTR__include */