/*
* Copyright (c) 2017-2023, 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 AESCCM.h
*
* @brief AESCCM driver header
*
* @anchor ti_drivers_AESCCM_Overview
* # Overview #
* The Counter with CBC-MAC (CCM) mode of operation is a generic
* authenticated encryption block cipher mode. It can be used with
* any block cipher.
* AESCCM combines CBC-MAC with an AES block cipher in CTR mode of operation.
*
* This combination of block cipher modes enables CCM to encrypt messages of any
* length and not only multiples of the block cipher block size.
*
* CTR provides confidentiality. The defined application of CBC-MAC provides
* message integrity and authentication.
*
* AESCCM has the following inputs and outputs:
*
*
* AES-CCM input and output parameters
* | Encryption | Decryption |
* | Input |
* | Shared AES key | Shared AES key |
* | Nonce | Nonce |
* | Cleartext | Ciphertext |
* | MAC |
* | AAD (optional) | AAD (optional) |
* | Output |
* | Ciphertext | Cleartext |
* | MAC | |
*
*
* The AES key is a shared secret between the two parties and has a length
* of 128, 192, or 256 bits.
*
* The nonce is generated by the party performing the authenticated
* encryption operation. Within the scope of any authenticated
* encryption key, the nonce value must be unique. That is, the set of
* nonce values used with any given key must not contain any duplicate
* values. Using the same nonce for two different messages encrypted
* with the same key destroys the security properties.
*
* The length of the nonce determines the maximum number of messages that may
* be encrypted and authenticated before you must regenerate the key.
* Reasonable session key rotation schemes will regenerate the key before reaching
* this limit.
* There is a trade-off between the nonce-length and the maximum length of
* the plaintext to encrypt and authenticate per nonce. This is because
* CTR concatenates the nonce and an internal counter into one 16-byte
* IV. The counter is incremented after generating an AES-block-sized
* pseudo-random bitstream. This bitstream is XOR'd with the plaintext.
* The counter would eventually roll over for a sufficiently long message.
* This is must not happen. Hence, the longer the nonce and the more messages
* you can send before needing to rotate the key, the shorter the
* lengths of individual messages sent may be. The minimum and maximum
* nonce length defined by the CCM standard provide for both a reasonable
* number of messages before key rotation and a reasonable maximum message length.
* Check NIST SP 800-38C for details.
*
* The optional additional authentication data (AAD) is authenticated
* but not encrypted. Thus, the AAD is not included in the AES-CCM output.
* It can be used to authenticate packet headers.
*
* After the encryption operation, the ciphertext contains the encrypted
* data. The message authentication code (MAC) is also provided.
*
* # CCM Variations #
* The AESCCM driver supports both classic CCM as defined by NIST SP 800-38C and
* the CCM* variant used in IEEE 802.15.4.
* CCM* allows for unauthenticated encryption using CCM by permitting a MAC length
* of 0. It also imposes the requirement that the MAC length be embedded in
* the nonce used for each message if the MAC length varies within the protocol
* using CCM*.
*
* @anchor ti_drivers_AESCCM_Usage
* # Usage #
*
* ## Before starting a CCM operation #
*
* Before starting a CCM operation, the application must do the following:
* - Call AESCCM_init() to initialize the driver
* - Call AESCCM_Params_init() to initialize the AESCCM_Params to default values.
* - Modify the AESCCM_Params as desired
* - Call AESCCM_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 AESCCM 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 the appropriate AESCCM operation struct using the relevant
* operation init functions and set all fields. For example, one-step (one-shot
* or single call) operations should initialize AESCCM_Operation or
* AESCCM_OneStepOperation using AESCCM_Operation_init() or
* AESCCM_OneStepOperation_init(). For multi-step (segmented or multiple call)
* operations, AESCCM_SegmentedAADOperation must be initialized and set when
* processing AAD. AESCCM_SegmentedDataOperation must be initialized and set when
* dealing with payload data (plaintext or ciphertext). AESCCM_SegmentedFinalizeOperation
* must be initialized and set when finalizing the segmented operation.
*
* ## Starting a CCM operation #
*
* The AESCCM_oneStepEncrypt and AESCCM_oneStepDecrypt functions do a CCM operation in a single call.
* They will always be the most highly optimized routines with the least overhead and the fastest
* runtime. However, they require all AAD and plaintext or ciphertext data to be
* available to the function at the start of the call.
* All devices support single call operations.
*
* When performing a decryption operation with AESCCM_oneStepDecrypt(), the MAC is
* automatically verified.
*
* ## After the CCM operation completes #
*
* After the CCM operation completes, the application should either start another operation
* or close the driver by calling AESCCM_close()
*
* @anchor ti_drivers_AESCCM_Synopsis
* ## Synopsis
*
* @anchor ti_drivers_AESCCM_Synopsis_Code
* @code
*
* // Import AESCCM Driver definitions
* #include
*
* // Define name for AESCCM channel index
* #define AESCCM_INSTANCE 0
*
* AESCCM_init();
*
* handle = AESCCM_open(AESCCM_INSTANCE, NULL);
*
* // Initialize symmetric key
* CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
*
* // Set up AESCCM_OneStepOperation
* AESCCM_OneStepOperation_init(&operation);
* operation.key = &cryptoKey;
* operation.aad = aad;
* operation.aadLength = sizeof(aad);
* operation.input = plaintext;
* operation.output = ciphertext;
* operation.inputLength = sizeof(plaintext);
* operation.nonce = nonce;
* operation.nonceLength = sizeof(nonce);
* operation.mac = mac;
* operation.macLength = sizeof(mac);
*
* encryptionResult = AESCCM_oneStepEncrypt(handle, &operation);
*
* AESCCM_close(handle);
* @endcode
*
* @anchor ti_drivers_AESCCM_Examples
* ## Examples
*
* ### Single call CCM encryption + authentication with plaintext CryptoKey in blocking return mode #
* @code
*
* #include
* #include
*
* ...
*
* AESCCM_Handle handle;
* CryptoKey cryptoKey;
* int_fast16_t encryptionResult;
* uint8_t nonce[] = "Thisisanonce";
* uint8_t aad[] = "This string will be authenticated but not encrypted.";
* uint8_t plaintext[] = "This string will be encrypted and authenticated.";
* uint8_t mac[16];
* uint8_t ciphertext[sizeof(plaintext)];
* uint8_t keyingMaterial[32] = {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};
*
* handle = AESCCM_open(0, NULL);
*
* if (handle == NULL) {
* // handle error
* }
*
* CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
*
* AESCCM_OneStepOperation operation;
* AESCCM_OneStepOperation_init(&operation);
*
* operation.key = &cryptoKey;
* operation.aad = aad;
* operation.aadLength = sizeof(aad);
* operation.input = plaintext;
* operation.output = ciphertext;
* operation.inputLength = sizeof(plaintext);
* operation.nonce = nonce;
* operation.nonceLength = sizeof(nonce);
* operation.mac = mac;
* operation.macLength = sizeof(mac);
*
* encryptionResult = AESCCM_oneStepEncrypt(handle, &operation);
*
* if (encryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_close(handle);
*
* @endcode
* ### The following code snippet is for CC27XX devices only and leverages the HSM
* which is a seperate Hardware Accelerator ###
* ### Single call CCM encryption + authentication with plaintext HSM CryptoKey in Polling Mode ###
*
* @code
*
* #include
* #include
*
* ...
*
* AESCCM_Params params;
* AESCCM_Handle handle;
* CryptoKey cryptoKey;
* int_fast16_t encryptionResult;
* uint8_t nonce[] = "Thisisanonce";
* uint8_t aad[] = "This string will be authenticated but not encrypted.";
* uint8_t plaintext[] = "This string will be encrypted and authenticated.";
* uint8_t mac[16];
* uint8_t ciphertext[sizeof(plaintext)];
* uint8_t keyingMaterial[32] = {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};
*
* AESCCM_Params_init(¶ms)
* params.returnBehavior = AESCCM_RETURN_BEHAVIOR_POLLING;
*
* handle = AESCCM_open(0, ¶ms);
*
* if (handle == NULL) {
* // handle error
* }
*
* CryptoKeyPlaintextHSM_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
*
* AESCCM_OneStepOperation operation;
* AESCCM_OneStepOperation_init(&operation);
*
* operation.key = &cryptoKey;
* operation.aad = aad;
* operation.aadLength = sizeof(aad);
* operation.input = plaintext;
* operation.output = ciphertext;
* operation.inputLength = sizeof(plaintext);
* operation.nonce = nonce;
* operation.nonceLength = sizeof(nonce);
* operation.mac = mac;
* operation.macLength = sizeof(mac);
*
* encryptionResult = AESCCM_oneStepEncrypt(handle, &operation);
*
* if (encryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_close(handle);
*
* @endcode
*
* ### Single call CCM decryption + verification with plaintext CryptoKey in callback return mode #
* @code
*
* #include
* #include
*
* ...
*
* // The following test vector is Packet Vector 1 from RFC 3610 of the IETF.
*
* uint8_t nonce[] = {0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0,
* 0xA1, 0xA2, 0xA3, 0xA4, 0xA5};
* uint8_t aad[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
* uint8_t mac[] = {0x17, 0xE8, 0xD1, 0x2C, 0xFD, 0xF9, 0x26, 0xE0};
* uint8_t ciphertext[] = {0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2,
* 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80,
* 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84};
* uint8_t keyingMaterial[] = {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
* 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF};
* uint8_t plaintext[sizeof(ciphertext)];
*
* // The plaintext should be the following after the decryption operation:
* // {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
* // 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
* // 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E}
*
*
* void ccmCallback(AESCCM_Handle handle,
* int_fast16_t returnValue,
* AESCCM_OperationUnion *operation,
* AESCCM_OperationType operationType) {
*
* if (returnValue != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
* }
*
* AESCCM_OneStepOperation operation;
*
* void ccmStartFunction(void) {
* AESCCM_Handle handle;
* AESCCM_Params params;
* CryptoKey cryptoKey;
* int_fast16_t decryptionResult;
*
* AESCCM_Params_init(¶ms);
* params.returnBehavior = AESCCM_RETURN_BEHAVIOR_CALLBACK;
* params.callbackFxn = ccmCallback;
*
* handle = AESCCM_open(0, ¶ms);
*
* if (handle == NULL) {
* // handle error
* }
*
* CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
*
* AESCCM_OneStepOperation_init(&operation);
*
* operation.key = &cryptoKey;
* operation.aad = aad;
* operation.aadLength = sizeof(aad);
* operation.input = ciphertext;
* operation.output = plaintext;
* operation.inputLength = sizeof(ciphertext);
* operation.nonce = nonce;
* operation.nonceLength = sizeof(nonce);
* operation.mac = mac;
* operation.macLength = sizeof(mac);
*
* decryptionResult = AESCCM_oneStepDecrypt(handle, &operation);
*
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* // do other things while CCM operation completes in the background
*
* }
*
*
* @endcode
*
* ### Multi-step CCM encryption + authentication with plaintext CryptoKey in blocking return mode #
* @code
*
* #include
* #include
*
* ...
*
* #define AES_BLOCK_SIZE 16 // bytes
*
* AESCCM_Handle handle;
* CryptoKey cryptoKey;
* int_fast16_t encryptionResult;
*
* // The following test vector is Packet Vector 1 from RFC 3610 of the IETF.
*
* uint8_t keyingMaterial[16] = {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
* 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF};
* uint8_t aad[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
* uint8_t plaintext[23] = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
* 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
* 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E};
* uint8_t nonce[13] = {0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0,
* 0xA1, 0xA2, 0xA3, 0xA4, 0xA5};
* uint8_t mac[8];
* uint8_t ciphertext[sizeof(plaintext)];
*
* // The ciphertext should be the following after the encryption operation:
* // {0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2,
* // 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80,
* // 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84}
*
* handle = AESCCM_open(0, NULL);
*
* if (handle == NULL) {
* // handle error
* }
*
* CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
*
*
* encryptionResult = AESCCM_setupEncrypt(handle, &cryptoKey, sizeof(aad), sizeof(plaintext), sizeof(mac));
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* encryptionResult = AESCCM_setNonce(handle, nonce, sizeof(nonce));
* if (encryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX) // and the HSM is the engine of choice
*
* CryptoKeyPlaintextHSM_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
*
* // You will also need to populate the mac in handle->object->mac because HSM needs the mac to construct each
* // segmented token.
* encryptionResult = AESCCMLPF3HSM_setMac(handle, &mac[0], 8);
* if (encryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* #endif
*
* AESCCM_SegmentedAADOperation segmentedAADOperation;
* AESCCM_SegmentedAADOperation_init(&segmentedAADOperation);
* segmentedAADOperation.aad = aad;
* segmentedAADOperation.aadLength = sizeof(aad);
*
* encryptionResult = AESCCM_addAAD(handle, &segmentedAADOperation);
* if (encryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_SegmentedDataOperation segmentedDataOperation;
* AESCCM_SegmentedDataOperation_init(&segmentedDataOperation);
* segmentedDataOperation.input = plaintext;
* segmentedDataOperation.output = ciphertext;
* // One should pass in data that is a block-sized multiple length
* // until passing in the last segment of data.
* // In that case, the input length simply needs to be a non-zero value.
* segmentedDataOperation.inputLength = AES_BLOCK_SIZE;
*
* encryptionResult = AESCCM_addData(handle, &segmentedDataOperation);
* if (encryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* segmentedDataOperation.input = plaintext + AES_BLOCK_SIZE;
* segmentedDataOperation.output = ciphertext + AES_BLOCK_SIZE;
* segmentedDataOperation.inputLength = sizeof(plaintext) - AES_BLOCK_SIZE;
*
* encryptionResult = AESCCM_addData(handle, &segmentedDataOperation);
* if (encryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_SegmentedFinalizeOperation segmentedFinalizeOperation;
* AESCCM_SegmentedFinalizeOperation_init(&egmentedFinalizeOperation);
* segmentedFinalizeOperation.input = plaintext;
* segmentedFinalizeOperation.output = ciphertext;
*
* // You can finalize with no new data
* segmentedFinalizeOperation.inputLength = 0;
* segmentedFinalizeOperation.mac = mac;
* segmentedFinalizeOperation.macLength = sizeof(mac);
* encryptionResult = AESCCM_finalizeEncrypt(handle, &segmentedFinalizeOperation);
*
* if (encryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_close(handle);
*
* @endcode
*
* ### Multi-step CCM decryption + verification with plaintext CryptoKey in callback return mode #
* @code
*
* #include
* #include
*
* ...
*
* // The following test vector is Packet Vector 1 from RFC 3610 of the IETF.
*
* uint8_t nonce[] = {0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0,
* 0xA1, 0xA2, 0xA3, 0xA4, 0xA5};
* uint8_t aad[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
* uint8_t mac[] = {0x17, 0xE8, 0xD1, 0x2C, 0xFD, 0xF9, 0x26, 0xE0};
* uint8_t ciphertext[] = {0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2,
* 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80,
* 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84};
* uint8_t keyingMaterial[] = {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
* 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF};
* uint8_t plaintext[sizeof(ciphertext)];
*
* // The plaintext should be the following after the decryption operation:
* // {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
* // 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
* // 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E}
*
*
* void ccmCallback(AESCCM_Handle handle,
* int_fast16_t returnValue,
* AESCCM_OperationUnion *operation,
* AESCCM_OperationType operationType) {
*
* if (returnValue != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* if(operationType == AESCCM_OPERATION_TYPE_DECRYPT ||
* operationType == AESCCM_OPERATION_TYPE_ENCRYPT)
* {
* // Callback fxn only used for one-shot operations
* // Use operation->oneStepOperation
* }
* else if(operationType == AESCCM_OP_TYPE_AAD_DECRYPT ||
* operationType == AESCCM_OP_TYPE_AAD_ENCRYPT)
* {
* // Callback fxn only used for segmented AAD operations
* // Use operation->segmentedAADOperation
* }
* else if(operationType == AESCCM_OP_TYPE_DATA_DECRYPT ||
* operationType == AESCCM_OP_TYPE_DATA_ENCRYPT)
* {
* // Callback fxn only used for segmented data operations
* // Use operation->segmentedDataOperation
* }
* else
* {
* // Callback fxn only used for segmented finalize operations
* // Use operation->segmentedFinalizeOperation
* }
* }
*
* void ccmStartFunction(void) {
* AESCCM_Handle handle;
* AESCCM_Params params;
* CryptoKey cryptoKey;
* int_fast16_t decryptionResult;
*
* AESCCM_Params_init(¶ms);
* params.returnBehavior = AESCCM_RETURN_BEHAVIOR_CALLBACK;
* params.callbackFxn = ccmCallback;
*
* handle = AESCCM_open(0, ¶ms);
*
* if (handle == NULL) {
* // handle error
* }
*
* CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
*
* decryptionResult = AESCCM_setupDecrypt(handle, &cryptoKey, 0, 0, 0);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* // setLengths must be called if the AAD, input, and MAC lengths aren't provided in setupXXXX.
* decryptionResult = AESCCM_setLengths(handle, sizeof(aad), sizeof(ciphertext), sizeof(mac));
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* decryptionResult = AESCCM_setNonce(handle, nonce, sizeof(nonce));
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_SegmentedAADOperation segmentedAADOperation;
* AESCCM_SegmentedAADOperation_init(&segmentedAADOperation);
* segmentedAADOperation.aad = aad;
* segmentedAADOperation.aadLength = sizeof(aad);
*
* decryptionResult = AESCCM_addAAD(handle, &segmentedAADOperation);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_SegmentedDataOperation segmentedDataOperation;
* AESCCM_SegmentedDataOperation_init(&segmentedDataOperation);
* segmentedDataOperation.input = ciphertext;
* segmentedDataOperation.output = plaintext;
* segmentedDataOperation.inputLength = AES_BLOCK_SIZE;
*
* decryptionResult = AESCCM_addData(handle, &segmentedDataOperation);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_SegmentedFinalizeOperation segmentedFinalizeOperation;
* AESCCM_SegmentedFinalizeOperation_init(&egmentedFinalizeOperation);
* segmentedFinalizeOperation.input = ciphertext + AES_BLOCK_SIZE;
* segmentedFinalizeOperation.output = plaintext + AES_BLOCK_SIZE;
* segmentedFinalizeOperation.inputLength = sizeof(ciphertext) - AES_BLOCK_SIZE;
* segmentedFinalizeOperation.mac = mac;
* segmentedFinalizeOperation.macLength = sizeof(mac);
*
* decryptionResult = AESCCM_finalizeDecrypt(handle, &segmentedFinalizeOperation);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* // do other things while CCM operation completes in the background
*
* }
*
* @endcode
*
* ### Multi-step CCM* decryption + verification with plaintext CryptoKey in callback return mode #
* @code
*
* #include
* #include
*
* ...
*
* // The following test vector is Packet Vector 1 from RFC 3610 of the IETF.
*
* uint8_t nonce[] = {0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xA0,
* 0xA1, 0xA2, 0xA3, 0xA4, 0xA5};
* uint8_t aad[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
* uint8_t mac[] = {0};
*
* // CCM* allows for unauthenticated encryption using CCM by allowing a MAC length of 0
* uint8_t macLength = 0;
* uint8_t ciphertext[] = {0x58, 0x8C, 0x97, 0x9A, 0x61, 0xC6, 0x63, 0xD2,
* 0xF0, 0x66, 0xD0, 0xC2, 0xC0, 0xF9, 0x89, 0x80,
* 0x6D, 0x5F, 0x6B, 0x61, 0xDA, 0xC3, 0x84};
* uint8_t keyingMaterial[] = {0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
* 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF};
* uint8_t plaintext[sizeof(ciphertext)];
*
* // The plaintext should be the following after the decryption operation:
* // {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
* // 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
* // 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E}
*
*
* void ccmCallback(AESCCM_Handle handle,
* int_fast16_t returnValue,
* AESCCM_OperationUnion *operation,
* AESCCM_OperationType operationType) {
*
* if (returnValue != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* if(operationType == AESCCM_OPERATION_TYPE_DECRYPT ||
* operationType == AESCCM_OPERATION_TYPE_ENCRYPT)
* {
* // Callback fxn only used for one-shot operations
* // Use operation->oneStepOperation
* }
* else if(operationType == AESCCM_OP_TYPE_AAD_DECRYPT ||
* operationType == AESCCM_OP_TYPE_AAD_ENCRYPT)
* {
* // Callback fxn only used for segmented AAD operations
* // Use operation->segmentedAADOperation
* }
* else if(operationType == AESCCM_OP_TYPE_DATA_DECRYPT ||
* operationType == AESCCM_OP_TYPE_DATA_ENCRYPT)
* {
* // Callback fxn only used for segmented data operations
* // Use operation->segmentedDataOperation
* }
* else
* {
* // Callback fxn only used for segmented finalize operations
* // Use operation->segmentedFinalizeOperation
* }
* }
*
* void ccmStartFunction(void) {
* AESCCM_Handle handle;
* AESCCM_Params params;
* CryptoKey cryptoKey;
* int_fast16_t decryptionResult;
*
* AESCCM_Params_init(¶ms);
* params.returnBehavior = AESCCM_RETURN_BEHAVIOR_CALLBACK;
* params.callbackFxn = ccmCallback;
*
* handle = AESCCM_open(0, ¶ms);
*
* if (handle == NULL) {
* // handle error
* }
*
* CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
*
* decryptionResult = AESCCM_setupDecrypt(handle, &cryptoKey, 0, 0, 0);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* // setLengths must be called if the AAD, input, and MAC lengths aren't provided in setupXXXX.
* decryptionResult = AESCCM_setLengths(handle, sizeof(aad), sizeof(ciphertext), macLength);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* decryptionResult = AESCCM_setNonce(handle, nonce, sizeof(nonce));
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_SegmentedAADOperation segmentedAADOperation;
* AESCCM_SegmentedAADOperation_init(&segmentedAADOperation);
* segmentedAADOperation.aad = aad;
* segmentedAADOperation.aadLength = sizeof(aad);
*
* decryptionResult = AESCCM_addAAD(handle, &segmentedAADOperation);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_SegmentedDataOperation segmentedDataOperation;
* AESCCM_SegmentedDataOperation_init(&segmentedDataOperation);
* segmentedDataOperation.input = ciphertext;
* segmentedDataOperation.output = plaintext;
* segmentedDataOperation.inputLength = AES_BLOCK_SIZE;
*
* decryptionResult = AESCCM_addData(handle, &segmentedDataOperation);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* AESCCM_SegmentedFinalizeOperation segmentedFinalizeOperation;
* AESCCM_SegmentedFinalizeOperation_init(&egmentedFinalizeOperation);
* segmentedFinalizeOperation.input = ciphertext + AES_BLOCK_SIZE;
* segmentedFinalizeOperation.output = plaintext + AES_BLOCK_SIZE;
* segmentedFinalizeOperation.inputLength = sizeof(ciphertext) - AES_BLOCK_SIZE;
* segmentedFinalizeOperation.mac = mac;
* segmentedFinalizeOperation.macLength = macLength;
*
* decryptionResult = AESCCM_finalizeDecrypt(handle, &segmentedFinalizeOperation);
* if (decryptionResult != AESCCM_STATUS_SUCCESS) {
* // handle error
* }
*
* // do other things while CCM operation completes in the background
*
* }
*
* @endcode
*/
#ifndef ti_drivers_AESCCM__include
#define ti_drivers_AESCCM__include
#include
#include
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/*!
* Common AESCCM status code reservation offset.
* AESCCM driver implementations should offset status codes with
* AESCCM_STATUS_RESERVED growing negatively.
*
* Example implementation specific status codes:
* @code
* #define AESCCMXYZ_STATUS_ERROR0 AESCCM_STATUS_RESERVED - 0
* #define AESCCMXYZ_STATUS_ERROR1 AESCCM_STATUS_RESERVED - 1
* #define AESCCMXYZ_STATUS_ERROR2 AESCCM_STATUS_RESERVED - 2
* @endcode
*/
#define AESCCM_STATUS_RESERVED AES_STATUS_RESERVED
/*!
* @brief Successful status code.
*
* Functions return AESCCM_STATUS_SUCCESS if the function was executed
* successfully.
*/
#define AESCCM_STATUS_SUCCESS AES_STATUS_SUCCESS
/*!
* @brief Generic error status code.
*
* Functions return AESCCM_STATUS_ERROR if the function was not executed
* successfully and no more pertinent error code could be returned.
*/
#define AESCCM_STATUS_ERROR AES_STATUS_ERROR
/*!
* @brief An error status code returned if the hardware or software resource
* is currently unavailable.
*
* AESCCM 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 AESCCM_STATUS_RESOURCE_UNAVAILABLE AES_STATUS_RESOURCE_UNAVAILABLE
/*!
* @brief The ongoing operation was canceled.
*/
#define AESCCM_STATUS_CANCELED AES_STATUS_CANCELED
/*!
* @brief An error status code returned if the MAC provided by the application for
* a decryption operation does not match the one calculated during the operation.
*
* This code is returned by AESCCM_oneStepDecrypt() or AESCCM_finalizeDecrypt()
* if the verification of the MAC fails.
*/
#define AESCCM_STATUS_MAC_INVALID AES_STATUS_MAC_INVALID
/*!
* @brief The operation requested is not supported either by the target hardware
* or the driver implementation.
*/
#define AESCCM_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 AESCCM_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 AESCCM_STATUS_KEYSTORE_GENERIC_ERROR AES_STATUS_KEYSTORE_GENERIC_ERROR
/*!
* @brief The operation does not support non-word-aligned input and/or output.
*
* AESCCM driver implementations may have restrictions on the alignment of
* input/output data due to performance limitations of the hardware.
*/
#define AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED AES_STATUS_UNALIGNED_IO_NOT_SUPPORTED
/*!
* @brief AESCCM Global configuration
*
* The AESCCM_Config structure contains a set of pointers used to characterize
* the AESCCM driver implementation.
*
* This structure needs to be defined before calling AESCCM_init() and it must
* not be changed thereafter.
*
* @sa AESCCM_init()
*/
typedef AESCommon_Config AESCCM_Config;
/*!
* @brief A handle that is returned from an AESCCM_open() call.
*/
typedef AESCCM_Config *AESCCM_Handle;
/*!
* @brief The way in which CCM function calls return after performing an
* encryption + authentication or decryption + verification operation.
*
* Not all CCM 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.
*
* AESCCM functions exhibiting the specified return behavior have restrictions on the
* context from which they may be called.
*
* | | Task | Hwi | Swi |
* |--------------------------------|-------|-------|-------|
* |AESCCM_RETURN_BEHAVIOR_CALLBACK | X | X | X |
* |AESCCM_RETURN_BEHAVIOR_BLOCKING | X | | |
* |AESCCM_RETURN_BEHAVIOR_POLLING | X | X | X |
*
*/
typedef enum
{
AESCCM_RETURN_BEHAVIOR_CALLBACK = AES_RETURN_BEHAVIOR_CALLBACK,
/*!< The function call will return immediately while the
* CCM 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.
*/
AESCCM_RETURN_BEHAVIOR_BLOCKING = AES_RETURN_BEHAVIOR_BLOCKING,
/*!< The function call will block while the CCM operation goes
* on in the background. CCM operation results are available
* after the function returns.
*/
AESCCM_RETURN_BEHAVIOR_POLLING = AES_RETURN_BEHAVIOR_POLLING,
/*!< The function call will continuously poll a flag while CCM
* operation goes on in the background. CCM operation results
* are available after the function returns.
*/
} AESCCM_ReturnBehavior;
/*!
* @brief Enum for the direction of the CCM operation.
*/
typedef enum
{
AESCCM_MODE_ENCRYPT = 1,
AESCCM_MODE_DECRYPT = 2,
} AESCCM_Mode;
/*!
* @brief Struct containing the parameters required for encrypting/decrypting
* and authenticating/verifying a message for one-step operations.
*/
typedef struct
{
CryptoKey *key; /*!< A previously initialized CryptoKey */
uint8_t *aad; /*!< A buffer of length \c aadLength containing additional
* authentication data to be authenticated/verified but not
* encrypted/decrypted.
*/
uint8_t *input; /*!<
* - Encryption: The plaintext buffer to be encrypted and authenticated
* in the CCM operation.
* - Decryption: The ciphertext to be decrypted and verified.
*/
uint8_t *output; /*!<
* - Encryption: The output ciphertext buffer that the encrypted plaintext
* is copied to.
* - Decryption: The plaintext derived from the decrypted and verified
* ciphertext is copied here.
*/
uint8_t *nonce; /*!< A buffer containing a nonce. Nonces must be unique to
* each CCM operation and may not be reused. If
* nonceInternallyGenerated is set, the nonce will be
* generated by #AESCCM_oneStepEncrypt() and copied to this buffer.
*/
uint8_t *mac; /*!<
* - Encryption: The buffer where the message authentication
* code is copied.
* - Decryption: The buffer containing the received message
* authentication code.
*/
size_t aadLength; /*!< Length of the total \c aad in bytes. Either \c aadLength or
* \c inputLength must be non-zero. Unlike this field in
* AESCCM_SegmentedAADOperation, the length doesn't need to be
* block-aligned.
*/
size_t inputLength; /*!< Length of the input/output data in bytes. Either \c aadLength or
* \c inputLength must be non-zero. Unlike this field in
* AESCCM_SegmentedDataOperation, the length doesn't need to be
* block-aligned.
* Max length supported may be limited depending on the return behavior.
*/
uint8_t nonceLength; /*!< Length of \c nonce in bytes.
* Valid nonce lengths are [7, 8, ... 13].
*/
uint8_t macLength; /*!< Length of \c mac in bytes.
* Valid MAC lengths are [0, 4, 6, 8, 10, 12, 14, 16].
* A length of 0 disables authentication and verification. This is
* only permitted when using CCM*.
*/
bool nonceInternallyGenerated; /*!< When true, the nonce buffer passed into #AESCCM_oneStepEncrypt()
* will be overwritten with a randomly generated nonce.
* Not supported by all implementations.
*/
} AESCCM_OneStepOperation;
/*!
* @brief Struct containing the parameters required for
* authenticating/verifying additional data in a segmented operation.
* Must be updated for each add AAD step of a segmented operation.
*/
typedef struct
{
uint8_t *aad; /*!< A buffer of length \c aadLength containing additional
* authentication data to be authenticated/verified but not
* encrypted/decrypted.
*/
size_t aadLength; /*!< Length of the \c aad in bytes. Must be non-zero, multiple
* of the AES block size (16 bytes) unless the last chunk of
* AAD is being passed in. In that case, this value doesn't
* need to be an AES block-sized multiple.
*/
} AESCCM_SegmentedAADOperation;
/*!
* @brief Struct containing the parameters required for encrypting/decrypting
* a message in a segmented operation. Must be updated between each
* add data step of a segmented operation.
*/
typedef struct
{
uint8_t *input; /*!<
* - Encryption: The plaintext buffer to be encrypted and authenticated
* in the CCM operation.
* - Decryption: The ciphertext to be decrypted and verified.
*/
uint8_t *output; /*!<
* - Encryption: The output ciphertext buffer that the encrypted plaintext
* is copied to.
* - Decryption: The plaintext derived from the decrypted and verified
* ciphertext is copied here.
*/
size_t inputLength; /*!< Length of the input/output data in bytes. Must be non-zero, multiple
* of the AES block size (16 bytes) unless the last chunk of data is being
* passed in. In that case, this value doesn't need to a block size multiple.
* Max length supported may be limited depending on the return behavior.
*/
} AESCCM_SegmentedDataOperation;
/*!
* @brief Struct containing the parameters required for finalizing an
* encryption/decryption and authentication/verification of a message
* in a segmented operation.
*/
typedef struct
{
uint8_t *input; /*!<
* - Encryption: The plaintext buffer to be encrypted and authenticated
* in the CCM operation.
* - Decryption: The ciphertext to be decrypted and verified.
*/
uint8_t *output; /*!<
* - Encryption: The output ciphertext buffer that the encrypted plaintext
* is copied to.
* - Decryption: The plaintext derived from the decrypted and verified
* ciphertext is copied here.
*/
uint8_t *mac; /*!<
* - Encryption: The buffer where the message authentication
* code is copied.
* - Decryption: The buffer containing the received message
* authentication code.
*/
size_t inputLength; /*!< Length of the input/output data in bytes. Can be 0 if finalizing
* without new payload data. Unlike this field in
* AESCCM_SegmentedDataOperation, the length doesn't need to be
* block-aligned.
* Max length supported may be limited depending on the return behavior.
*/
uint8_t macLength; /*!< Length of \c mac in bytes.
* Valid MAC lengths are [0, 4, 6, 8, 10, 12, 14, 16].
* A length of 0 disables authentication and verification. This is
* only permitted when using CCM*.
*/
} AESCCM_SegmentedFinalizeOperation;
/**
* @deprecated
* Define a typedef for deprecated operation AESCCM_Operation.
* Existing code should be refactored to use AESCCM_OneStepOperation.
* This reference may be removed at some point in the future
*
*/
typedef AESCCM_OneStepOperation AESCCM_Operation;
/*!
* @brief Union containing a reference to a one step,
* segmented AAD, segmented data, or segmented finalize operation.
*/
typedef union AESCCM_OperationUnion
{
AESCCM_OneStepOperation oneStepOperation; /* One-step operation element of the operation union */
AESCCM_SegmentedAADOperation segmentedAADOperation; /* Segmented AAD operation element of the operation union */
AESCCM_SegmentedDataOperation segmentedDataOperation; /* Segmented data operation element of the operation union */
AESCCM_SegmentedFinalizeOperation segmentedFinalizeOperation; /* Segmented finalize operation element of the
operation union */
} AESCCM_OperationUnion;
/*!
* @brief Enum for the operation types supported by the driver.
*/
typedef enum
{
AESCCM_OPERATION_TYPE_ENCRYPT = 1, /* Fields 1 and 2 are for backward compatibility */
AESCCM_OPERATION_TYPE_DECRYPT = 2,
AESCCM_OP_TYPE_ONESTEP_ENCRYPT = 1, /* Names changed to _OP_TYPE_ to avoid MISRA deviation from first 31 chars not
being unique */
AESCCM_OP_TYPE_ONESTEP_DECRYPT = 2,
AESCCM_OP_TYPE_AAD_ENCRYPT = 3,
AESCCM_OP_TYPE_AAD_DECRYPT = 4,
AESCCM_OP_TYPE_DATA_ENCRYPT = 5,
AESCCM_OP_TYPE_DATA_DECRYPT = 6,
AESCCM_OP_TYPE_FINALIZE_ENCRYPT = 7,
AESCCM_OP_TYPE_FINALIZE_DECRYPT = 8,
} AESCCM_OperationType;
/*!
* @brief The definition of a callback function used by the AESCCM driver
* when used in ::AESCCM_RETURN_BEHAVIOR_CALLBACK
*
* @param handle Handle of the client that started the CCM operation.
*
* @param returnValue The result of the CCM operation. May contain an error code.
* Informs the application of why the callback function was
* called.
*
* @param operationUnion A pointer to an operation union.
*
* @param operationType This parameter determines which operation the
* callback refers to.
*/
typedef void (*AESCCM_CallbackFxn)(AESCCM_Handle handle,
int_fast16_t returnValue,
AESCCM_OperationUnion *operation,
AESCCM_OperationType operationType);
/*!
* @brief CCM Parameters
*
* CCM Parameters used with the AESCCM_open() call. Default values for
* these parameters are set using AESCCM_Params_init().
*
* @sa AESCCM_Params_init()
*/
typedef struct
{
AESCCM_ReturnBehavior returnBehavior; /*!< Blocking, callback, or polling return behavior */
AESCCM_CallbackFxn callbackFxn; /*!< Callback function pointer */
uint32_t timeout; /*!< Timeout before the driver returns an error in
* ::AESCCM_RETURN_BEHAVIOR_BLOCKING
*/
void *custom; /*!< Custom argument used by driver
* implementation
*/
} AESCCM_Params;
/*!
* @brief Default AESCCM_Params structure
*
* @sa #AESCCM_Params_init()
*/
extern const AESCCM_Params AESCCM_defaultParams;
/*!
* @brief This function initializes the CCM module.
*
* @pre The AESCCM_config structure must exist and be persistent before this
* function can be called. This function must also be called before
* any other CCM driver APIs. This function call does not modify any
* peripheral registers.
*/
void AESCCM_init(void);
/*!
* @brief Function to initialize the #AESCCM_Params struct to its defaults
*
* @param params An pointer to #AESCCM_Params structure for
* initialization
*
* Defaults values are:
* returnBehavior = AESCCM_RETURN_BEHAVIOR_BLOCKING
* callbackFxn = NULL
* timeout = SemaphoreP_WAIT_FOREVER
* custom = NULL
*/
void AESCCM_Params_init(AESCCM_Params *params);
/*!
* @brief This function opens a given CCM peripheral.
*
* @pre CCM controller has been initialized using #AESCCM_init()
*
* @param [in] index Logical peripheral number for the CCM indexed into
* the AESCCM_config table
*
* @param [in] params Pointer to an parameter block, if NULL it will use
* default values.
*
* @return An AESCCM_Handle on success or a NULL on an error or if it has been
* opened already.
*
* @sa #AESCCM_init()
* @sa #AESCCM_close()
*/
AESCCM_Handle AESCCM_open(uint_least8_t index, const AESCCM_Params *params);
/*!
* @brief Function to close a CCM peripheral specified by the CCM handle
*
* @pre #AESCCM_open() or #AESCCM_construct()
*
* @param [in] handle A CCM handle
*
* @sa #AESCCM_open()
*/
void AESCCM_close(AESCCM_Handle handle);
/*!
* @brief Function to prepare a segmented AESCCM encryption operation.
*
* This function sets up a segmented AESCCM encryption operation.
*
* @pre #AESCCM_open() or #AESCCM_construct()
*
* @param [in] handle A CCM handle returned from #AESCCM_open()
* or #AESCCM_construct()
*
* @param [in] key Pointer to a previously initialized CryptoKey.
*
* @param [in] totalAADLength Total size of the AAD in bytes.
* This value can be 0 and later provided
* by #AESCCM_setLengths().
*
* @param [in] totalPlaintextLength Total size of the plaintext in bytes.
* This value can be 0 and later provided
* by #AESCCM_setLengths().
*
* @param [in] macLength Size of the MAC in bytes. This value
* can be 0 and later provided by
* #AESCCM_setLengths().
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not supported in this device.
*
* @post #AESCCM_addAAD()
* @post #AESCCM_addData()
*/
int_fast16_t AESCCM_setupEncrypt(AESCCM_Handle handle,
const CryptoKey *key,
size_t totalAADLength,
size_t totalPlaintextLength,
size_t macLength);
/*!
* @brief Function to prepare a segmented AESCCM decryption operation.
*
* This function sets up a segmented AESCCM decryption operation.
*
* @pre #AESCCM_open() or #AESCCM_construct()
*
* @param [in] handle A CCM handle returned from #AESCCM_open()
* or #AESCCM_construct()
*
* @param [in] key Pointer to a previously initialized CryptoKey.
*
* @param [in] totalAADLength Total size of the AAD in bytes.
* This value can be 0 and later provided
* by #AESCCM_setLengths().
*
* @param [in] totalPlaintextLength Total size of the plaintext in bytes
* This value can be 0 and later provided
* by #AESCCM_setLengths().
*
* @param [in] macLength Size of the MAC in bytes. This value
* can be 0 and later provided by
* #AESCCM_setLengths().
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not supported in this device.
*
* @post #AESCCM_addAAD()
* @post #AESCCM_addData()
*/
int_fast16_t AESCCM_setupDecrypt(AESCCM_Handle handle,
const CryptoKey *key,
size_t totalAADLength,
size_t totalPlaintextLength,
size_t macLength);
/*!
* @brief Function to set the lengths of the message, additional data, and MAC.
*
* This function declares the lengths of the message,
* additional authenticated data (AAD), and MAC.
*
* @note This function doesn't have to be called if the lengths above were
* specified in #AESCCM_setupEncrypt() or #AESCCM_setupDecrypt().
*
* @pre #AESCCM_setupEncrypt() or #AESCCM_setupDecrypt()
*
* @param [in] handle A CCM handle returned from #AESCCM_open()
* or #AESCCM_construct()
*
* @param [in] aadLength Size of the non-encrypted AAD in bytes
*
* @param [in] plaintextLength Size of the plaintext or ciphertext to encrypt or decrypt in bytes
*
* @param [in] macLength Size of the MAC in bytes
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not supported in this device.
*
* @post #AESCCM_setNonce()
* @post #AESCCM_generateNonce()
*/
int_fast16_t AESCCM_setLengths(AESCCM_Handle handle, size_t aadLength, size_t plaintextLength, size_t macLength);
/*!
* @brief Function to set the nonce for an AES CCM segmented operation.
*
* @pre #AESCCM_setupEncrypt(), #AESCCM_setupDecrypt(), or #AESCCM_setLengths()
*
* @param [in] handle A CCM handle returned from #AESCCM_open()
* or #AESCCM_construct()
*
* @param [in] nonce Pointer to the buffer containing the nonce
*
* @param [in] nonceLength The length of the nonce in bytes
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not
* supported in this device.
*
* @post #AESCCM_addAAD()
* @post #AESCCM_addData()
*/
int_fast16_t AESCCM_setNonce(AESCCM_Handle handle, const uint8_t *nonce, size_t nonceLength);
/*!
* @brief Function to generate a nonce for an AES CCM segmented encryption operation.
*
* @pre #AESCCM_setupEncrypt() or #AESCCM_setLengths()
*
* @param [in] handle A CCM handle returned from #AESCCM_open()
* or #AESCCM_construct()
*
* @param [in] nonce Pointer to the buffer where the generated nonce
* is to be written to
*
* @param [in] nonceSize The length of the nonce buffer in bytes
*
* @param [out] nonceLength The length of the nonce actually written if the
* operation was successful
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not
* supported in this device.
*
* @post #AESCCM_addAAD()
* @post #AESCCM_addData()
*/
int_fast16_t AESCCM_generateNonce(AESCCM_Handle handle, uint8_t *nonce, size_t nonceSize, size_t *nonceLength);
/*!
* @brief Adds a segment of @a aad with a @a length in bytes to the generated MAC.
* The length must be a multiple of a block size, 16 bytes, unless passing in the last
* chunk of AAD.
*
* #AESCCM_addAAD() may be called an arbitrary number of times before continuing the operation with
* #AESCCM_addData(), #AESCCM_finalizeEncrypt() or #AESCCM_finalizeDecrypt().
*
* This function returns according to the return behavior set when opening the driver.
*
* @note This function must not be called after passing data to encrypt or
* decrypt with #AESCCM_addData().
*
* @warning When decrypting, do not use the output until
* #AESCCM_finalizeDecrypt() succeeds.
*
* @pre #AESCCM_setNonce() or #AESCCM_generateNonce()
*
* @param [in] handle A CCM handle returned from #AESCCM_open() or #AESCCM_construct()
*
* @param [in] operation Pointer to segmented AAD CCM operation structure
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_RESOURCE_UNAVAILABLE The required hardware resource was not available.
* Try again later.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not supported in this device.
* @retval #AESCCM_STATUS_CANCELED The operation was canceled.
*
* @post #AESCCM_addAAD()
* @post #AESCCM_addData()
* @post #AESCCM_finalizeEncrypt()
* @post #AESCCM_finalizeDecrypt()
*/
int_fast16_t AESCCM_addAAD(AESCCM_Handle handle, AESCCM_SegmentedAADOperation *operation);
/*!
* @brief Adds a segment of @a data with a @a length in bytes to the plaintext/ciphertext
* output and generated MAC. The length must be a multiple of a block size, 16 bytes, unless
* passing in the last chunk of payload data.
*
* #AESCCM_addData() may be called an arbitrary number of times before finishing the operation
* with #AESCCM_finalizeEncrypt() or #AESCCM_finalizeDecrypt().
*
* This function returns according to the return behavior set when opening the driver.
*
* @warning When decrypting, do not use the output until
* #AESCCM_finalizeDecrypt() succeeds.
*
* @pre #AESCCM_setNonce() or #AESCCM_generateNonce()
*
* @param [in] handle A CCM handle returned from #AESCCM_open() or #AESCCM_construct()
*
* @param [in] operation Pointer to segmented data CCM operation structure
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_RESOURCE_UNAVAILABLE The required hardware resource was not available.
* Try again later.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not supported in this device.
* @retval #AESCCM_STATUS_CANCELED The operation was canceled.
* @retval #AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned.
*
* @post #AESCCM_addData()
* @post #AESCCM_finalizeEncrypt()
* @post #AESCCM_finalizeDecrypt()
*/
int_fast16_t AESCCM_addData(AESCCM_Handle handle, AESCCM_SegmentedDataOperation *operation);
/*!
* @brief Finalize the MAC and ciphertext.
*
* This function finalizes the encryption of a dataset earlier provided
* by calls to #AESCCM_addAAD() and #AESCCM_addData() and creates a message
* authentication code. If additional data needs to be encrypted and verified
* as part of this call, set the operation structure @a inputLength accordingly.
*
* The resulting output is a message authentication code and ciphertext.
*
* @pre #AESCCM_addAAD() or #AESCCM_addData()
*
* @param [in] handle A CCM handle returned from #AESCCM_open() or #AESCCM_construct()
*
* @param [in] operation Pointer to segmented finalize CCM operation structure
*
* @retval #AESCCM_STATUS_SUCCESS In ::AESCCM_RETURN_BEHAVIOR_BLOCKING and
* ::AESCCM_RETURN_BEHAVIOR_POLLING, this means the MAC
* was generated successfully. In ::AESCCM_RETURN_BEHAVIOR_CALLBACK,
* this means the operation started successfully.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_CANCELED The operation was canceled.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not supported in this device.
* @retval #AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned.
*/
int_fast16_t AESCCM_finalizeEncrypt(AESCCM_Handle handle, AESCCM_SegmentedFinalizeOperation *operation);
/*!
* @brief Finalize the MAC and plaintext and verify it.
*
* This function finalizes the decryption of a dataset earlier provided
* by calls to AESCCM_addAAD() and AESCCM_addData() and verifies a provided message
* authentication code. If additional data needs to be decrypted and verified
* as part of this call, set the operation structure @a inputLength accordingly.
*
* @note None of the buffers provided as arguments may be altered by the application during an ongoing operation.
* Doing so can yield a corrupted MAC comparison.
*
* The resulting output is a verification return code and plaintext.
*
* @pre #AESCCM_addAAD() or #AESCCM_addData()
*
* @param [in] handle A CCM handle returned from #AESCCM_open() or #AESCCM_construct()
*
* @param [in] operation Pointer to segmented finalize CCM operation structure
*
* @retval #AESCCM_STATUS_SUCCESS In ::AESCCM_RETURN_BEHAVIOR_BLOCKING and
* ::AESCCM_RETURN_BEHAVIOR_POLLING, this means the MAC
* was verified successfully. In ::AESCCM_RETURN_BEHAVIOR_CALLBACK,
* this means the operation started successfully.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_MAC_INVALID The provided MAC did not match the recomputed one.
* @retval #AESCCM_STATUS_CANCELED The operation was canceled.
* @retval #AESCCM_STATUS_FEATURE_NOT_SUPPORTED The operation is not supported in this device.
* @retval #AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned.
*/
int_fast16_t AESCCM_finalizeDecrypt(AESCCM_Handle handle, AESCCM_SegmentedFinalizeOperation *operation);
/*!
* @brief Function to initialize an #AESCCM_Operation struct to its defaults
*
* @deprecated This function should be replaced by calls to operation-specific
* init functions.
*
* @param [in] operationStruct A pointer to an #AESCCM_Operation structure for
* initialization
*
* Defaults values are all zeros.
*/
void AESCCM_Operation_init(AESCCM_Operation *operationStruct);
/*!
* @brief Function to initialize an #AESCCM_OneStepOperation struct to its defaults
*
* @param [in] operationStruct A pointer to an #AESCCM_OneStepOperation structure for
* initialization
*
* Defaults values are all zeros.
*/
void AESCCM_OneStepOperation_init(AESCCM_OneStepOperation *operationStruct);
/*!
* @brief Function to initialize an #AESCCM_SegmentedAADOperation struct to its defaults
*
* @param [in] operationStruct A pointer to an #AESCCM_SegmentedAADOperation structure
* for initialization
*
* Defaults values are all zeros.
*/
void AESCCM_SegmentedAADOperation_init(AESCCM_SegmentedAADOperation *operationStruct);
/*!
* @brief Function to initialize an #AESCCM_SegmentedDataOperation struct to its defaults
*
* @param [in] operationStruct A pointer to an #AESCCM_SegmentedDataOperation structure
* for initialization
*
* Defaults values are all zeros.
*/
void AESCCM_SegmentedDataOperation_init(AESCCM_SegmentedDataOperation *operationStruct);
/*!
* @brief Function to initialize an #AESCCM_SegmentedFinalizeOperation struct to its defaults
*
* @param [in] operationStruct A pointer to an #AESCCM_SegmentedFinalizeOperation structure
* for initialization
*
* Defaults values are all zeros.
*/
void AESCCM_SegmentedFinalizeOperation_init(AESCCM_SegmentedFinalizeOperation *operationStruct);
/*!
* @brief Function to perform an AESCCM encryption + authentication 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 or incorrect authentication.
*
* @pre #AESCCM_open() or #AESCCM_construct() and #AESCCM_Operation_init() have to be called first.
*
* @param [in] handle A CCM handle returned from #AESCCM_open() or #AESCCM_construct()
*
* @param [in] operationStruct A pointer to a struct containing the parameters required to perform the
* operation.
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_RESOURCE_UNAVAILABLE The required hardware resource was not available. Try again later.
* @retval #AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned.
*
* @sa AESCCM_oneStepDecrypt()
*/
int_fast16_t AESCCM_oneStepEncrypt(AESCCM_Handle handle, AESCCM_OneStepOperation *operationStruct);
/*!
* @brief Function to perform an AESCCM decryption + verification 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 or incorrectly failed verification.
*
* @pre #AESCCM_open() or #AESCCM_construct() and #AESCCM_Operation_init() have to be called first.
*
* @param [in] handle A CCM handle returned from #AESCCM_open() or #AESCCM_construct()
*
* @param [in] operationStruct A pointer to a struct containing the parameters required to perform the
* operation.
*
* @retval #AESCCM_STATUS_SUCCESS The operation succeeded.
* @retval #AESCCM_STATUS_ERROR The operation failed.
* @retval #AESCCM_STATUS_RESOURCE_UNAVAILABLE The required hardware resource was not available. Try again later.
* @retval #AESCCM_STATUS_MAC_INVALID The provided MAC did not match the recomputed one.
* @retval #AESCCM_STATUS_UNALIGNED_IO_NOT_SUPPORTED The input and/or output buffer were not word-aligned.
*
* @sa AESCCM_oneStepEncrypt()
*/
int_fast16_t AESCCM_oneStepDecrypt(AESCCM_Handle handle, AESCCM_OneStepOperation *operationStruct);
/*!
* @brief Cancels an ongoing AESCCM operation.
*
* Asynchronously cancels an AESCCM operation. Only available when using
* AESCCM_RETURN_BEHAVIOR_CALLBACK.
* The operation will terminate as though an error occurred. The
* return status code of the operation will be AESCCM_STATUS_CANCELED.
*
* @param [in] handle Handle of the operation to cancel
*
* @retval #AESCCM_STATUS_SUCCESS The operation was canceled, or the operation had already completed.
* @retval #AESCCM_STATUS_ERROR The driver was not in callback mode, or the operation's output
* and generated MAC weren't properly cleared.
*/
int_fast16_t AESCCM_cancelOperation(AESCCM_Handle handle);
/**
* @brief Constructs a new AESCCM object
*
* Unlike #AESCCM_open(), #AESCCM_construct() does not require the hwAttrs and
* object to be allocated in a #AESCCM_Config array that is indexed into.
* Instead, the #AESCCM_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.
*
* @param config #AESCCM_Config describing the location of the object and hwAttrs.
*
* @param params #AESCCM_Params to configure the driver instance.
*
* @return Returns a #AESCCM_Handle on success or NULL on failure.
*
* @pre The object struct @c config points to must be zeroed out prior to
* calling this function. Otherwise, unexpected behavior may ensue.
*/
AESCCM_Handle AESCCM_construct(AESCCM_Config *config, const AESCCM_Params *params);
#ifdef __cplusplus
}
#endif
#endif /* ti_drivers_AESCCM__include */