/*
 * Copyright (c) 2017, 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
 *
 * @warning     This is a beta API. It may change in future releases.
 *
 *  # Overview #
 *  The Counter with CBC-MAC (CCM) mode of operation is a generic
 *  authenticated encryption block cipher mode.  It can be used with
 *  any 128-bit 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.
 *
 *  AESCCM encryption has the following inputs and outputs:
 *
 * <table>
 * <caption id="AESCCM_multi_row">AES-CCM input and output parameters</caption>
 * <tr><th>Encryption</th><th>Decryption</th></tr>
 * <tr><th colspan=2>Input</th></tr>
 * <tr><td>Shared AES key</td><td> Shared AES key</td></tr>
 * <tr><td>Nonce</td><td>Nonce</td></tr>
 * <tr><td>Cleartext</td><td>Ciphertext (encrypted plaintext + MAC)</td></tr>
 * <tr><td>AAD (optional)</td><td>AAD (optional)</td></tr>
 * <tr><th colspan=2>Output</th></tr>
 * <tr><td>Ciphertext (encrypted plaintext + MAC)</td><td>Cleartext</td></tr>
 * </table>
 *
 *  The AES key is a shared secret between the two parties and has a length
 *  between 128 and 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 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 and the message authentication code (MAC). The MAC can be seen as an
 *  encrypted fingerprint of the message header and content.
 *
 *  # 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 datastructures are representations
 *        of keying material and its storage. Depending on how the keying material
 *        is stored (RAM or flash, key store, key blob), the CryptoKey must be
 *        initialized differently. The AESCCM API can handle all types of CryptoKey.
 *        However, not all device-specific implementions 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.
 *
 *  ## Starting a CCM operation #
 *
 *  There are two general ways to execute a CCM operation. In one call or multiple.
 *
 *  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. When trying to operate on
 *  data that is too large to fit into available memory, partial processing would be
 *  more advisable.
 *  All devices support single call operations.
 *  When performing a decryption operation with AESCCM_oneStepDecrypt(), the MAC is
 *  automatically verified when using AESCCM_RETURN_BEHAVIOR_BLOCKING or AESCCM_RETURN_BEHAVIOR_POLLING.
 *  When using AESCCM_RETURN_BEHAVIOR_CALLBACK however, the application's registered
 *  callback function must call AESCCM_verifyMac() itself to ensure that the computed
 *  and transmitted MACs match.
 *
 *  The partial processing functions split the setup, processing of the AAD, processing
 *  of the plaintext or ciphertext, and computation or verification of the MAC into
 *  multiple calls. The AAD and payload processing functions may be called on buffers
 *  smaller than the total AAD and payload sizes.
 *  Not all devices support partial processing. The hardware or software implementations
 *  of the CCM mode of operation available on a specific device may not be designed to
 *  support partial processing.
 *
 *  ## 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()
 *
 *  ## AESCCM Driver Configuration #
 *
 *  In order to use the AESCCM APIs, the application is required
 *  to provide device-specific AESCCM configuration in the Board.c file.
 *  The AESCCM driver interface defines a configuration data structure:
 *
 *  @code
 *  typedef struct AESCCM_Config_ {
 *      void                   *object;
 *      void          const    *hwAttrs;
 *  } AESCCM_Config;
 *  @endcode
 *
 *  The application must declare an array of AESCCM_Config elements, named
 *  AESCCM_config[].  Each element of AESCCM_config[] must be populated with
 *  pointers to a device specific AESCCM driver implementation's driver object and
 *  hardware attributes.  The hardware attributes define properties such
 *  as the AESCCM peripheral's base address.
 *  Each element in AESCCM_config[] corresponds to an AESCCM instance
 *  and none of the elements should have NULL pointers.
 *  There is no correlation between the index and the
 *  peripheral designation (such as AESCCM0 or AESCCM1).  For example, it is
 *  possible to use AESCCM_config[0] for AESCCM1. Multiple drivers and driver
 *  instances may all access the same underlying hardware. This is transparent
 *  to the application. Mutual exclusion is performed automatically by the
 *  drivers as necessary.
 *
 *  Because the AESCCM configuration is very device dependent, you will need to
 *  check the doxygen for the device specific AESCCM implementation.  There you
 *  will find a description of the AESCCM hardware attributes.  Please also
 *  refer to the Board.c file of any of your examples to see the AESCCM
 *  configuration.
 *
 *  ## AESCCM Parameters
 *
 *  The #AESCCM_Params structure is passed to the AESCCM_open() call.  If NULL
 *  is passed for the parameters, AESCCM_open() uses default parameters.
 *  A #AESCCM_Params structure is initialized with default values by passing
 *  it to AESCCM_Params_init().
 *  Some of the AESCCM parameters are described below.  To see brief descriptions
 *  of all the parameters, see #AESCCM_Params.
 *
 *  ## AESCCM Return Behavior
 *  The AESCCM driver supports three return behaviors when processing data: blocking, polling, and
 *  callback. The return behavior is determined by the returnBehavior parameter
 *  in the AESCCM_Params data structure. The AESCCM driver
 *  defaults to blocking mode, if the application does not set it.
 *  Once an AESCCM driver is opened, the only way to change the return behavior
 *  is to close and re-open the AESCCM instance with the new return behavior.
 *
 *  In blocking mode, a task's code execution is blocked until an AESCCM
 *  operation has completed. This ensures that only one AESCCM operation
 *  operates at a given time. Other tasks requesting AESCCM operations while
 *  a operation is currently taking place are also placed into a blocked
 *  state. AESCCM operations are executed in the order in which they were
 *  received.  In blocking mode, you cannot perform AESCCM operations
 *  in the context of a software or hardware ISR.
 *
 *  In callback mode, an AESCCM operation functions asynchronously, which
 *  means that it does not block code execution. After an AESCCM operation
 *  has been completed, the AESCCM driver calls a user-provided hook function.
 *  Callback mode is supported in the task, SWI, and HWI execution context,
 *  However, if an AESCCM operation is requested while a operation is taking place,
 *  the call returns an error code.
 *
 *  In polling mode, an AESCCM operation behaves the almost the same way as
 *  in blocking mode. Instead of pending on a semaphore and letting other
 *  scheduled tasks run, the application task, SWI, or HWI continuously polls
 *  a flag until the operation completes. If an AESCCM operation is
 *  requested while a operation is taking place, the call returns an error code.
 *  When starting an AESCCM operation in polling mode from HWI or SWI context,
 *  the AESCCM HWI and SWI must be configured to have a higher priority to pre-empt
 *  the polling context.
 *
 *  ## Examples
 *
 *  ### Single call CCM encryption + authentication with plaintext CryptoKey in blocking return mode #
 *  @code
 *
 *  #include <ti/drivers/AESCCM.h>
 *  #include <ti/drivers/types/cryptoKey/CryptoKey_Plaintext.h>
 *
 *  ...
 *
 *  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));
 *
 *  encryptionResult = AESCCM_oneStepEncrypt(handle,
 *                                           &cryptoKey,
 *                                           aad, sizeof(aad),
 *                                           plaintext, sizeof(plaintext),
 *                                           nonce, sizeof(nonce),
 *                                           mac, sizeof(mac),
 *                                           ciphertext);
 *
 *  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 <ti/drivers/AESCCM.h>
 *  #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
 *
 *  ...
 *
 *  // 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, CryptoKey *processedKey) {
 *      int_fast16_t verificationResult;
 *
 *      verificationResult = AESCCM_verifyMac(handle, &mac);
 *
 *      if (verificationResult != AESCCM_STATUS_SUCCESS) {
 *          // handle error
 *      }
 *  }
 *
 *  void ccmStartFunction(void) {
 *      AESCCM_Handle handle;
 *      AESCCM_Params params;
 *      CryptoKey cryptoKey;
 *      int_fast16_t decryptionResult;
 *
 *      AESCCM_Params_init(&params);
 *      params.returnBehavior = AESCCM_RETURN_BEHAVIOR_CALLBACK;
 *      params.callbackFxn = ccmCallback;
 *
 *      handle = AESCCM_open(0, &params);
 *
 *      if (handle == NULL) {
 *          // handle error
 *      }
 *
 *      CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
 *
 *      decryptionResult = AESCCM_oneStepEncrypt(handle,
 *                                               &cryptoKey,
 *                                               aad, sizeof(aad),
 *                                               ciphertext, sizeof(ciphertext),
 *                                               nonce, sizeof(nonce),
 *                                               mac, sizeof(mac),
 *                                               plaintext);
 *
 *      if (encryptionResult != 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

#ifdef __cplusplus
extern "C" {
#endif

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>

/**
 *  @defgroup AESCCM_CONTROL AESCCM_control command and status codes
 *  These AESCCM macros are reservations for AESCCM.h
 *  @{
 */

/*!
 * Common AESCCM_control command code reservation offset.
 * AESCCM driver implementations should offset command codes with AESCCM_CMD_RESERVED
 * growing positively
 *
 * Example implementation specific command codes:
 * @code
 * #define AESCCMXYZ_CMD_COMMAND0     AESCCM_CMD_RESERVED + 0
 * #define AESCCMXYZ_CMD_COMMAND1     AESCCM_CMD_RESERVED + 1
 * @endcode
 */
#define AESCCM_CMD_RESERVED           (32)

/*!
 * Common AESCCM_control 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        (-32)

/**
 *  @defgroup AESCCM_STATUS Status Codes
 *  AESCCM_STATUS_* macros are general status codes returned by AESCCM functions
 *  @{
 *  @ingroup AESCCM_CONTROL
 */

/*!
 * @brief   Successful status code.
 *
 * Function return AESCCM_STATUS_SUCCESS if the control code was executed
 * successfully.
 */
#define AESCCM_STATUS_SUCCESS         (0)

/*!
 * @brief   Generic error status code.
 *
 * Functions return AESCCM_STATUS_ERROR if the control code was not executed
 * successfully.
 */
#define AESCCM_STATUS_ERROR           (-1)

/*!
 * @brief   An error status code returned by AESCCM_control() for undefined
 * command codes.
 *
 * AESCCM_control() returns AESCCM_STATUS_UNDEFINEDCMD if the control code is not
 * recognized by the driver implementation.
 */
#define AESCCM_STATUS_UNDEFINEDCMD    (-2)

/*!
 * @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 (-3)

/*!
 * @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() and AESCCM_verifyMAC() if the
 * verification of the MAC fails.
 */
#define AESCCM_STATUS_MAC_INVALID (-4)


/** @}*/

/**
 *  @defgroup AESCCM_CMD Command Codes
 *  AESCCM_CMD_* macros are general command codes for AESCCM_control(). Not all AESCCM
 *  driver implementations support these command codes.
 *  @{
 *  @ingroup AESCCM_CONTROL
 */

/* Add AESCCM_CMD_<commands> here */

/** @}*/

/** @}*/

/*!
 *  @brief  A handle that is returned from an AESCCM_open() call.
 */
typedef struct AESCCM_Config_    *AESCCM_Handle;

/*!
 *  @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  processedKey The CryptoKey that the CCM operation was performed with.
 */
typedef void (*AESCCM_CallbackFxn) (AESCCM_Handle handle, CryptoKey *processedKey);

/*!
 * @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 behavor. Functions that do not
 * require significant computation and cannot offload that computation to a background thread
 * behave like regular functions. Which functions exhibit the specfied 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_ReturnBehavior_ {
    AESCCM_RETURN_BEHAVIOR_CALLBACK = 1,    /*!< 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 = 2,    /*!< The function call will block while CCM operation goes
                                             *   on in the background. CCM operation results are available
                                             *   after the function returns.
                                             */
    AESCCM_RETURN_BEHAVIOR_POLLING  = 4,    /*!< 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_ {
    AESCCM_MODE_ENCRYPT = 1,
    AESCCM_MODE_DECRYPT = 2,
} AESCCM_Mode;

/*!
 *  @brief  CCM Parameters
 *
 *  CCM Parameters are used to with the AESCCM_open() call. Default values for
 *  these parameters are set using AESCCM_Params_init().
 *
 *  @sa     AESCCM_Params_init()
 */
typedef struct AESCCM_Params_ {
    AESCCM_ReturnBehavior   returnBehavior;             /*!< Blocking, callback, or polling return behavior */
    AESCCM_CallbackFxn      callbackFxn;                /*!< Callback function pointer */
    bool                    nonceInternallyGenerated;   /*!< When true, the nonce buffer passed into the AESCCM_setupEncrypt()
                                                         *   and AESCCM_oneStepEncrypt() functions will be overwritten with a
                                                         *   randomly generated nonce.
                                                         */
    uint32_t                timeout;
    void                   *custom;                     /*!< Custom argument used by driver
                                                         *   implementation
                                                         */
} AESCCM_Params;



/*!
 *  @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 struct AESCCM_Config_ {
    /*! Pointer to a driver specific data object */
    void               *object;

    /*! Pointer to a driver specific hardware attributes structure */
    void         const *hwAttrs;
} AESCCM_Config;

/*!
 *  @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
 *      nonceInternallyGenerated    = false
 *      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  index         Logical peripheral number for the CCM indexed into
 *                        the AESCCM_config table
 *
 *  @param  params        Pointer to an parameter block, if NULL it will use
 *                        default values.
 *
 *  @return A 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, AESCCM_Params *params);

/*!
 *  @brief  Function to close a CCM peripheral specified by the CCM handle
 *
 *  @pre    AESCCM_open() has to be called first.
 *
 *  @param  handle A CCM handle returned from AESCCM_open()
 *
 *  @sa     AESCCM_open()
 */
void AESCCM_close(AESCCM_Handle handle);

/*!
 *  @brief  Function performs implementation specific features on a given
 *          AESCCM_Handle.
 *
 *  Commands for AESCCM_control can originate from AESCCM.h or from implementation
 *  specific AESCCM*.h (_AESCCMCC26XX.h_, _AESCCMMSP432.h_, etc.. ) files.
 *  While commands from AESCCM.h are API portable across driver implementations,
 *  not all implementations may support all these commands.
 *  Conversely, commands from driver implementation specific AESCCM*.h files add
 *  unique driver capabilities but are not API portable across all AESCCM driver
 *  implementations.
 *
 *  Commands supported by AESCCM.h follow an AESCCM_CMD_\<cmd\> naming
 *  convention.<br>
 *  Commands supported by AESCCM*.h follow an AESCCM*_CMD_\<cmd\> naming
 *  convention.<br>
 *  Each control command defines @b arg differently. The types of @b arg are
 *  documented with each command.
 *
 *  See @ref AESCCM_CMD "AESCCM_control command codes" for command codes.
 *
 *  See @ref AESCCM_STATUS "AESCCM_control return status codes" for status codes.
 *
 *  @pre    AESCCM_open() has to be called first.
 *
 *  @param  handle      A AESCCM handle returned from AESCCM_open()
 *
 *  @param  cmd         AESCCM.h or AESCCM*.h commands.
 *
 *  @param  args        An optional R/W (read/write) command argument
 *                      accompanied with cmd
 *
 *  @return Implementation specific return codes. Negative values indicate
 *          unsuccessful operations.
 *
 *  @sa     AESCCM_open()
 */
int_fast16_t AESCCM_control(AESCCM_Handle handle, uint32_t cmd, void *args);



/*!
 *  @brief  Function to set up an AESCCM encryption + authentication operation in multiple calls.
 *
 *  @pre    AESCCM_open() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [in] key                    A previously initialized CryptoKey
 *
 *  @param  [in] aadTotalLength         Total length of the additional authentication data in bytes.
 *                                      Either \c aadTotalLength or \c plaintextTotalLength must be non-zero.
 *
 *  @param  [in] plaintextTotalLength   Total length of the plaintext in bytes.
 *                                      Either \c aadTotalLength or \c plaintextTotalLength must be non-zero.
 *
 *  @param  [in,out] nonce              A buffer containing a nonce. Nonces must be unique to each CCM operation and
 *                                      may not be reused. If nonceInternallyGenerated was set in the AESCCM_Params,
 *                                      the nonce will be generated by this function call and copied to this buffer.
 *
 *  @param  [in] nonceLength            Length of \c nonce in bytes.
 *                                      Valid nonce lengths are {7, 8, 9, 10, 11, 12, 13}.
 *
 *  @param  [in] macLength              Length of the message authentication code in bytes.
 *                                      Valid MAC lengths are [0, 1, ... 16].
 *
 *  @return A status code
 *
 *  @post   AESCCM_processAAD() must be called next.
 *
 *  @sa     AESCCM_setupDecrypt()
 */
int_fast16_t AESCCM_setupEncrypt(AESCCM_Handle handle,
                                 CryptoKey *key,
                                 uint8_t *nonce, uint8_t nonceLength,
                                 size_t aadTotalLength,
                                 size_t plaintextTotalLength,
                                 uint8_t macLength);

/*!
 *  @brief  Function to set up an AESCCM decryption + verification operation in multiple calls.
 *
 *  @pre    AESCCM_open() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [in] key                    A previously initialized CryptoKey
 *
 *  @param  [in] aadTotalLength         Total length of the additional authentication data in bytes.
 *                                      Either \c aadTotalLength or \c plaintextTotalLength must be non-zero.
 *
 *  @param  [in] ciphertextTotalLength  Total length of the ciphertext in bytes.
 *                                      Either \c aadTotalLength or \c ciphertextTotalLength must be non-zero.
 *
 *  @param  [in] nonce                  A buffer containing the nonce transmitted with the ciphertext and AAD.
 *
 *  @param  [in] nonceLength            Length of \c nonce in bytes.
 *                                      Valid nonce lengths are {7, 8, 9, 10, 11, 12, 13}.
 *
 *  @param  [in] macLength              Length of the message authentication code in bytes.
 *                                      Valid MAC lengths are [0, 1, ... 16].
 *
 *  @return A status code
 *
 *  @post   AESCCM_processAAD() must be called next.
 *
 *  @sa     AESCCM_setupEncrypt()
 */
int_fast16_t AESCCM_setupDecrypt(AESCCM_Handle handle,
                                 CryptoKey *key,
                                 uint8_t *nonce, uint8_t nonceLength,
                                 size_t aadTotalLength,
                                 size_t ciphertextTotalLength,
                                 uint8_t macLength);

/*!
 *  @brief  Function to process the additional authentication data in one or more calls.
 *
 *  @pre    AESCCM_setupDecrypt(), AESCCM_setupEncrypt(), or AESCCM_processAAD() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [in] aad                    A buffer of length \c length containing additional authentication data
 *                                      to be authenticated but not encrypted.
 *
 *  @param  [in] length                 Length of \c aad in bytes. Must be non-zero. May be smaller than the
 *                                      total AAD length provided in the setup call. This enables partial processing
 *                                      of longer AAD.
 *
 *  @return A status code
 *
 *  @post   AESCCM_processPayload() or AESCCM_processAAD() must be called next.
 */
int_fast16_t AESCCM_processAAD(AESCCM_Handle handle, uint8_t *aad, size_t length);

/*!
 *  @brief  Function to process the input data in one or more calls.
 *
 *  @pre    AESCCM_processAAD() or AESCCM_processPayload() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [in] input                  A buffer of length \c length containing either plaintext or ciphertext depending
 *                                      on the AESCCM_Mode.
 *
 *  @param  [in] length                 Length of \c input and output in bytes. Must be non-zero. May be smaller than the
 *                                      total input length provided in the setup call. This enables partial processing
 *                                      of longer inputs.
 *
 *  @param  [out] output                A buffer of length \c length that is filled with either ciphertext or plaintext
 *                                      depending on the AESCCM_Mode after processing.
 *
 *  @return A status code
 *
 *  @post   AESCCM_processPayload(), AESCCM_computeMAC(), or AESCCM_verifyMAC() must be called next.
 */
int_fast16_t AESCCM_processPayload(AESCCM_Handle handle, uint8_t *input, size_t length, uint8_t *output);

/*!
 *  @brief  Function to compute the message authentication code.
 *
 *  @pre    AESCCM_processPayload() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [out] mac                   A buffer that the computed MAC is copied to.
 *
 *  @return A status code
 *
 */
int_fast16_t AESCCM_computeMAC(AESCCM_Handle handle, uint8_t *mac);

/*!
 *  @brief  Function to verify the provided message authentication code.
 *
 *  @pre    AESCCM_processPayload() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [in] mac                    A buffer containing the MAC that the computed one will be verified against.
 *
 *  @return A status code
 *
 */
int_fast16_t AESCCM_verifyMAC(AESCCM_Handle handle, uint8_t *mac);

/*!
 *  @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() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [in] key                    A previously initialized CryptoKey
 *
 *  @param  [in] aad                    A buffer of length \c aadLength containing additional authentication data
 *                                      to be authenticated but not encrypted.
 *
 *  @param  [in] aadLength              Length of \c aad in bytes. Either \c aadLength or \c plaintextLength must be
 *                                      non-zero.
 *
 *  @param  [in] plaintext              The plaintext buffer to be encrypted and authenticated in the CCM operation.
 *
 *  @param  [in] plaintextLength        Length of \c plaintext in bytes. Either \c aadLength or \c plaintextLength must be
 *                                      non-zero.
 *
 *  @param  [in,out] nonce              A buffer containing a nonce. Nonces must be unique to each CCM operation and
 *                                      may not be reused. If nonceInternallyGenerated was set in the AESCCM_Params,
 *                                      the nonce will be generated by this function call and copied to this buffer.
 *
 *  @param  [in] nonceLength            Length of \c nonce in bytes.
 *                                      Valid nonce lengths are {7, 8, 9, 10, 11, 12, 13}.
 *
 *  @param  [out] mac                   The message authentication code buffer to store the encrypted authentication tag.
 *
 *  @param  [in] macLength              Length of \c mac in bytes.
 *                                      Valid MAC lengths are [0, 1, ... 16].
 *
 *  @param  [out] ciphertext            The output ciphertext buffer that the encrypted plaintext is copied to.
 *                                      It is of length \c plaintextLength.
 *
 *  @return A status code
 *
 *  @sa     AESCCM_oneStepDecrypt()
 */
int_fast16_t AESCCM_oneStepEncrypt(AESCCM_Handle handle,
                                   CryptoKey *key,
                                   uint8_t *aad, size_t aadLength,
                                   uint8_t *plaintext, size_t plaintextLength,
                                   uint8_t *nonce, uint8_t nonceLength,
                                   uint8_t *mac, uint8_t macLength,
                                   uint8_t *ciphertext);

/*!
 *  @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() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [in] key                    A previously initialized CryptoKey
 *
 *  @param  [in] aad                    A buffer of length \c aadLength containing additional authentication data
 *                                      to be verified but not decrypted.
 *
 *  @param  [in] aadLength              Length of \c aad in bytes. Either \c aadLength or \c plaintextLength must be
 *                                      non-zero.
 *
 *  @param  [in] ciphertext             The ciphertext buffer to be decrypted and verified in the CCM operation.
 *
 *  @param  [in] ciphertextLength       Length of \c plaintext in bytes. Either \c aadLength or \c plaintextLength must be
 *                                      non-zero.
 *
 *  @param  [in] nonce                  A buffer containing the nonce transmitted with the ciphertext and AAD.
 *
 *  @param  [in] nonceLength            Length of \c nonce in bytes.
 *                                      Valid nonce lengths are {7, 8, 9, 10, 11, 12, 13}.
 *
 *  @param  [in] mac                    The message authentication code buffer containing the encrypted authentication tag.
 *
 *  @param  [in] macLength              Length of \c mac in bytes.
 *                                      Valid MAC lengths are [0, 1, ... 16].
 *
 *  @param  [out] plaintext             The output plaintext buffer that the decrypted ciphertext is copied to.
 *                                      It is of length \c ciphertexttextLength.
 *
 *  @return A status code
 *
 *  @sa     AESCCM_oneStepEncrypt()
 */
int_fast16_t AESCCM_oneStepDecrypt(AESCCM_Handle handle,
                                   CryptoKey *key,
                                   uint8_t *aad, size_t aadLength,
                                   uint8_t *ciphertext, size_t ciphertextLength,
                                   uint8_t *nonce, uint8_t nonceLength,
                                   uint8_t *mac, uint8_t macLength,
                                   uint8_t *plaintext);

/*!
 *  @brief  Returns the AESCCM_Mode of an AESCCM operation in progress.
 *
 *  @pre    AESCCM_setupEncrypt() or AESCCM_setupDecrypt() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [out] mode                  Whether the operation in progress is a decryption or encryption operation
 *
 *  @return A status code
 */
int_fast16_t AESCCM_getMode(AESCCM_Handle handle, AESCCM_Mode *mode);

/*!
 *  @brief  Returns a pointer to the CryptoKey used for an AESCCM operation in progress.
 *
 *  @pre    AESCCM_setupEncrypt() or AESCCM_setupDecrypt() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [out] key                   The CryptoKey used in the operation
 *
 *  @return A status code
 */
int_fast16_t AESCCM_getCryptoKey(AESCCM_Handle handle, CryptoKey **key);

/*!
 *  @brief  Returns a pointer to the nonce and the nonce length of an AESCCM operation in progress.
 *
 *  @pre    AESCCM_setupEncrypt() or AESCCM_setupDecrypt() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [out] nonce                 The nonce used in the operation
 *
 *  @param  [out] nonceLength           The length of the nonce used in the operation
 *
 *  @return A status code
 */
int_fast16_t AESCCM_getNonce(AESCCM_Handle handle, uint8_t **nonce, uint8_t *nonceLength);

/*!
 *  @brief  Returns a pointer to the AAD and the AAD length of an AESCCM operation in progress.
 *
 *  @pre    AESCCM_processAAD() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [out] aad                   The AAD used in the operation
 *
 *  @param  [out] aadLength             The length of the AAD used in the operation
 *
 *  @return A status code
 */
int_fast16_t AESCCM_getAAD(AESCCM_Handle handle, uint8_t **aad, size_t *aadLength);

/*!
 *  @brief  Returns a pointer to the input (plaintext or ciphertext) and the input length of an AESCCM operation in progress.
 *
 *  @pre    AESCCM_processPayload() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [out] input                 The last input buffer used in the operation
 *
 *  @param  [out] inputLength           The length of the last input buffer used in the operation
 *
 *  @param  [out] totalInputLength      The total length of the input specified in the setup call. It is the same as the total length of the input.
 *
 *  @return A status code
 */
int_fast16_t AESCCM_getInput(AESCCM_Handle handle, uint8_t **input, size_t *inputLength, size_t *totalInputLength);

/*!
 *  @brief  Returns a pointer to the output (plaintext or ciphertext) and the output length of an AESCCM operation in progress.
 *
 *  @pre    AESCCM_processPayload() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [out] output                The output buffer used in the operation
 *
 *  @param  [out] outputLength          The output of the input used in the operation
 *
 *  @param  [out] totalOutputLength     The total length of the output specified in the setup call. It is the same as the total length of the input.
 *
 *  @return A status code
 */
int_fast16_t AESCCM_getOutput(AESCCM_Handle handle, uint8_t **output, size_t *outputLength, size_t *totalOutputLength);

/*!
 *  @brief  Returns a pointer to the MAC and the MAC length of the last completed AESCCM operation.
 *
 *  @pre    AESCCM_verifyMAC() or AESCCM_calculateMAC() has to be called first.
 *
 *  @param  [in] handle                 A CCM handle returned from AESCCM_open()
 *
 *  @param  [out] mac                   The MAC verified or calculated in the operation
 *
 *  @param  [out] macLength             The length of the MAC
 *
 *  @return A status code
 */
int_fast16_t AESCCM_getMAC(AESCCM_Handle handle, uint8_t *mac, uint8_t *macLength);

int_fast16_t AESCCM_setMACReturnPointer(AESCCM_Handle handle, uint8_t *mac);

#ifdef __cplusplus
}
#endif

#endif /* ti_drivers_AESCCM__include */
