/*
 * Copyright (c) 2018-2019, 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       AESGCM.h
 *
 * @brief      AESGCM driver header
 *
 * @warning     This is a beta API. It may change in future releases.
 *
 * @anchor ti_drivers_AESGCM_Overview
 * ### Overview #
 *
 * The Galois Counter Mode (GCM) mode of operation is a generic
 * authenticated encryption with associated data (AEAD) block cipher mode.
 * It can be implemented with any block cipher.
 * AESGCM combines GHASH with the AES block cipher in CTR mode of operation.
 *
 * This combination of block cipher modes enables GCM to encrypt messages of any
 * length and not only multiples of the block cipher block size.
 *
 * CTR provides confidentiality. The using GHASH and encrypting the result provides
 * message integrity and authentication.
 *
 * The AES key is a shared secret between the two parties and has a length
 * of 128, 192, or 256 bits.
 *
 * The IV is generated by the party performing the authenticated
 * encryption operation.  Within the scope of any authenticated
 * encryption key, the IV value must be unique.  That is, the set of
 * IV values used with any given key must not contain any duplicate
 * values.  Using the same IV for two different messages encrypted
 * with the same key destroys the security properties of GCM.
 *
 * The optional additional authentication data (AAD) is authenticated
 * but not encrypted. Thus, the AAD is not included in the AES-GCM output.
 * It can be used to authenticate packet headers, timestamps and other
 * metadata.
 *
 * After the encryption operation, the ciphertext contains the encrypted
 * data and the message authentication code (MAC).
 *
 * GCM is highly performant for an AEAD mode. Counter with CBC-MAC requires
 * one invocation per block of AAD and two invocations of the block cipher
 * per proccessed block of input; one to compute the CBC-MAC and one to
 * perform CTR. GCM substitutes the block cipher invocation during CBC-MAC
 * computation with computing GHASH over the same input. GHASH is significantly
 * faster per block than AES. In turn, this gives GCM a performance edge
 * over CCM.
 *
 * ### Security Considerations
 *
 * In each operation, GCM limits the length of the input and AAD to guarantee
 * its security properties:
 *     - inputLength <= 2^36 - 32 bytes
 *     - aadLength <= 2^61 - 1 bytes
 *
 * The security properties of GCM rely on the MAC size. While MAC lengths of
 * [4, 8, 12, 13, 14, 15, 16] bytes are permitted, it is recommended to
 * use the full 16-byte MAC.
 *
 * See NIST SP 800-38D for more a more detailed discussion of security
 * considerations.
 *
 * @anchor ti_drivers_AESGCM_Usage
 * ### Usage #
 *
 * #### Before starting a GCM operation #
 *
 * Before starting a GCM operation, the application must do the following:
 *     - Call AESGCM_init() to initialize the driver
 *     - Call AESGCM_Params_init() to initialize the #AESGCM_Params to default values.
 *     - Modify the #AESGCM_Params as desired
 *     - Call AESGCM_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 AESGCM 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.
 *     - Initialise the #AESGCM_Operation using AESGCM_Operation_init() and set all
 *       length, key, and buffer fields.
 *
 * #### Starting a GCM operation #
 *
 * The AESGCM_oneStepEncrypt() and AESGCM_oneStepDecrypt() functions perform a GCM operation in a single call.
 *
 * When performing a decryption operation with AESGCM_oneStepDecrypt(), the MAC is
 * automatically verified.
 *
 * #### After the GCM operation completes #
 *
 * After the GCM operation completes, the application should either start another operation
 * or close the driver by calling AESGCM_close()
 *
 * @anchor ti_drivers_AESGCM_Synopsis
 * ## Synopsis
 *
 * @anchor ti_drivers_AESGCM_Synopsis_Code
 * @code
 *
 * // Import AESGCM Driver definitions
 * #include <ti/drivers/AESGCM.h>
 *
 * // Define name for AESGCM channel index
 * #define AESGCM_INSTANCE 0
 *
 * AESGCM_init();
 *
 * handle = AESGCM_open(AESGCM_INSTANCE, NULL);
 *
 * // Initialize symmetric key
 * CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
 *
 * // Set up AESGCM_Operation
 * AESGCM_Operation_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 = AESGCM_oneStepEncrypt(handle, &operation);
 *
 * AESGCM_close(handle);
 * @endcode
 *
 * @anchor ti_drivers_AESGCM_Examples
 * #### Examples
 *
 * ##### Single call GCM encryption + authentication with plaintext CryptoKey in blocking return mode #
 *
 * @code
 *
 * #include <ti/drivers/AESGCM.h>
 * #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
 *
 * ...
 *
 * AESGCM_Handle handle;
 * CryptoKey cryptoKey;
 * int_fast16_t encryptionResult;
 * uint8_t iv[12] = "12-byte IV  ";
 * 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 = AESGCM_open(0, NULL);
 *
 * if (handle == NULL) {
 *     // handle error
 * }
 *
 * CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
 *
 * AESGCM_Operation operation;
 * AESGCM_Operation_init(&operation);
 *
 * operation.key               = &cryptoKey;
 * operation.aad               = aad;
 * operation.aadLength         = sizeof(aad);
 * operation.input             = plaintext;
 * operation.output            = ciphertext;
 * operation.inputLength       = sizeof(plaintext);
 * operation.iv                = iv;
 * operation.ivLength          = 12;
 * operation.mac               = mac;
 * operation.macLength         = sizeof(mac);
 *
 * encryptionResult = AESGCM_oneStepEncrypt(handle, &operation);
 *
 * if (encryptionResult != AESGCM_STATUS_SUCCESS) {
 *     // handle error
 * }
 *
 * AESGCM_close(handle);
 *
 * @endcode
 *
 * ##### Single call GCM decryption + verification with plaintext CryptoKey in callback return mode #
 *
 * @code
 *
 * #include <ti/drivers/AESGCM.h>
 * #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
 *
 * ...
 *
 * // The following test vector is Packet Vector 1 from RFC 3610 of the IETF.
 *
 * uint8_t iv[]                            = {0x1f, 0x80, 0x3c, 0x52, 0xca, 0xc4, 0x97, 0xe1,
 *                                            0x55, 0xaa, 0x55, 0x2d};
 * uint8_t aad[]                           = {0x3b, 0xba, 0x31, 0x28, 0x9d, 0x05, 0xf5, 0x0f,
 *                                            0xed, 0x6c, 0x53, 0x35, 0x3c, 0x1f, 0x74, 0xd8,
 *                                            0x28, 0xa9, 0x96, 0xb8, 0xd6, 0x84, 0xfe, 0x64,
 *                                            0x7f, 0x7c, 0x40, 0xc0, 0xd5, 0x68, 0x8c, 0x89,
 *                                            0x68, 0x1a, 0x33, 0xb1, 0x0c, 0xb7, 0x14, 0xb6,
 *                                            0x49, 0x0b, 0xdf, 0x1f, 0x16, 0x60, 0x60, 0xa7};
 * uint8_t mac[]                           = {0x39, 0x03, 0xe4, 0xdc, 0xa4, 0xe7, 0xc8, 0x21,
 *                                            0x62, 0x1a, 0xbb, 0xb2, 0x37, 0x2c, 0x97};
 * uint8_t ciphertext[]                    = {0xf8, 0x7e, 0xf7, 0x99, 0x4a, 0x86, 0xf3, 0xe9,
 *                                            0xa3, 0xab, 0x6a, 0x6f, 0x2d, 0x34, 0x3b, 0xbd};
 * uint8_t keyingMaterial[]                = {0x4f, 0xd7, 0xf2, 0x09, 0xdf, 0xb0, 0xdf, 0xbd,
 *                                            0xd9, 0x8d, 0x2d, 0xb4, 0x98, 0x66, 0x4c, 0x88};
 * uint8_t plaintext[sizeof(ciphertext)];
 *
 * // The plaintext should be the following after the decryption operation:
 * // 0x17, 0x9d, 0xcb, 0x79, 0x5c, 0x09, 0x8f, 0xc5, 0x31, 0x4b, 0xde, 0x0d, 0x39, 0x9d, 0x7a, 0x10
 *
 *
 * void gcmCallback(AESGCM_Handle handle,
 *                  int_fast16_t returnValue,
 *                  AESGCM_Operation *operation,
 *                  AESGCM_OperationType operationType) {
 *
 *     if (returnValue != AESGCM_STATUS_SUCCESS) {
 *         // handle error
 *     }
 * }
 *
 * AESGCM_Operation operation;
 * CryptoKey cryptoKey;
 *
 * void gcmStartFunction(void) {
 *     AESGCM_Handle handle;
 *     AESGCM_Params params;
 *     int_fast16_t decryptionResult;
 *
 *     AESGCM_Params_init(&params);
 *     params.returnBehavior = AESGCM_RETURN_BEHAVIOR_CALLBACK;
 *     params.callbackFxn = gcmCallback;
 *
 *     handle = AESGCM_open(0, &params);
 *
 *     if (handle == NULL) {
 *         // handle error
 *     }
 *
 *     CryptoKeyPlaintext_initKey(&cryptoKey, keyingMaterial, sizeof(keyingMaterial));
 *
 *     AESGCM_Operation_init(&operation);
 *
 *     operation.key               = &cryptoKey;
 *     operation.aad               = aad;
 *     operation.aadLength         = sizeof(aad);
 *     operation.input             = ciphertext;
 *     operation.output            = plaintext;
 *     operation.inputLength       = sizeof(ciphertext);
 *     operation.iv                = iv;
 *     operation.mac               = mac;
 *     operation.macLength         = sizeof(mac);
 *
 *     decryptionResult = AESGCM_oneStepDecrypt(handle, &operation);
 *
 *     if (decryptionResult != AESGCM_STATUS_SUCCESS) {
 *         // handle error
 *     }
 *
 *     // do other things while GCM operation completes in the background
 *
 * }
 * @endcode
 */

#ifndef ti_drivers_AESGCM__include
#define ti_drivers_AESGCM__include

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

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

#ifdef __cplusplus
extern "C" {
#endif

/*!
 * Common AESGCM status code reservation offset.
 * AESGCM driver implementations should offset status codes with
 * AESGCM_STATUS_RESERVED growing negatively.
 *
 * Example implementation specific status codes:
 * @code
 * #define AESGCMXYZ_STATUS_ERROR0    AESGCM_STATUS_RESERVED - 0
 * #define AESGCMXYZ_STATUS_ERROR1    AESGCM_STATUS_RESERVED - 1
 * #define AESGCMXYZ_STATUS_ERROR2    AESGCM_STATUS_RESERVED - 2
 * @endcode
 */
#define AESGCM_STATUS_RESERVED        (-32)

/*!
 * @brief   Successful status code.
 *
 * Functions return AESGCM_STATUS_SUCCESS if the function was executed
 * successfully.
 */
#define AESGCM_STATUS_SUCCESS         (0)

/*!
 * @brief   Generic error status code.
 *
 * Functions return AESGCM_STATUS_ERROR if the function was not executed
 * successfully and no more pertinent error code could be returned.
 */
#define AESGCM_STATUS_ERROR           (-1)

/*!
 * @brief   An error status code returned if the hardware or software resource
 * is currently unavailable.
 *
 * AESGCM 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 AESGCM_STATUS_RESOURCE_UNAVAILABLE (-2)

/*!
 * @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 AESGCM_oneStepDecrypt() if the verification of the
 * MAC fails.
 */
#define AESGCM_STATUS_MAC_INVALID (-3)

/*!
 *  @brief  The ongoing operation was canceled.
 */
#define AESGCM_STATUS_CANCELED (-4)

/*!
 *  @brief  A handle that is returned from an AESGCM_open() call.
 */
typedef struct AESGCM_Config    *AESGCM_Handle;

/*!
 * @brief   The way in which GCM function calls return after performing an
 * encryption + authentication or decryption + verification operation.
 *
 * Not all GCM 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.
 *
 * AESGCM functions exhibiting the specified return behavior have restrictions on the
 * context from which they may be called.
 *
 * |                                | Task  | Hwi   | Swi   |
 * |--------------------------------|-------|-------|-------|
 * |AESGCM_RETURN_BEHAVIOR_CALLBACK | X     | X     | X     |
 * |AESGCM_RETURN_BEHAVIOR_BLOCKING | X     |       |       |
 * |AESGCM_RETURN_BEHAVIOR_POLLING  | X     | X     | X     |
 *
 */
typedef enum {
    AESGCM_RETURN_BEHAVIOR_CALLBACK = 1,    /*!< The function call will return immediately while the
                                             *   GCM 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.
                                             */
    AESGCM_RETURN_BEHAVIOR_BLOCKING = 2,    /*!< The function call will block while the GCM operation goes
                                             *   on in the background. GCM operation results are available
                                             *   after the function returns.
                                             */
    AESGCM_RETURN_BEHAVIOR_POLLING  = 4,    /*!< The function call will continuously poll a flag while GCM
                                             *   operation goes on in the background. GCM operation results
                                             *   are available after the function returns.
                                             */
} AESGCM_ReturnBehavior;

/*!
 *  @brief  Enum for the direction of the GCM operation.
 */
typedef enum {
    AESGCM_MODE_ENCRYPT = 1,
    AESGCM_MODE_DECRYPT = 2,
} AESGCM_Mode;

/*!
 *  @brief  Struct containing the parameters required for encrypting/decrypting
 *          and authenticating/verifying a message.
 */
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 GCM 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                  *iv;                        /*!< A buffer containing an IV. IVs must be unique to
                                                         *   each GCM operation and may not be reused. If
                                                         *   ivInternallyGenerated is set, the IV will be
                                                         *   generated by this function call 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 \c aad in bytes. Either \c aadLength or
                                                         *   \c plaintextLength must benon-zero.
                                                         *   encrypted.
                                                         */
   size_t                   inputLength;                /*!< Length of the input and output in bytes. Either \c aadLength or
                                                         *   \c inputLength must be
                                                         *   non-zero.
                                                         */
   uint8_t                  ivLength;                   /*!< Length of \c IV in bytes.
                                                         *   The only currently supported IV length is 12 bytes.
                                                         */
   uint8_t                  macLength;                  /*!< Length of \c mac in bytes.
                                                         *   Valid MAC lengths are [4, 8, 12, 13, 14, 15, 16].
                                                         */
   bool                     ivInternallyGenerated;      /*!< When true, the IV buffer passed into the AESGCM_setupEncrypt()
                                                         *   and AESGCM_oneStepEncrypt() functions will be overwritten with a
                                                         *   randomly generated IV. Not supported by all implementations.
                                                         */
} AESGCM_Operation;

/*!
 *  @brief  Enum for the operation types supported by the driver.
 */
typedef enum {
    AESGCM_OPERATION_TYPE_ENCRYPT = 1,
    AESGCM_OPERATION_TYPE_DECRYPT = 2,
} AESGCM_OperationType;

/*!
 *  @brief AESGCM Global configuration
 *
 *  The AESGCM_Config structure contains a set of pointers used to characterize
 *  the AESGCM driver implementation.
 *
 *  This structure needs to be defined before calling AESGCM_init() and it must
 *  not be changed thereafter.
 *
 *  @sa     AESGCM_init()
 */
typedef struct AESGCM_Config {
    /*! Pointer to a driver specific data object */
    void               *object;

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

/*!
 *  @brief  The definition of a callback function used by the AESGCM driver
 *          when used in ::AESGCM_RETURN_BEHAVIOR_CALLBACK
 *
 *  @param  handle Handle of the client that started the GCM operation.
 *
 *  @param  returnValue  The result of the GCM operation. May contain an error code.
 *                       Informs the application of why the callback function was
 *                       called.
 *
 *  @param  operation A pointer to an operation struct.
 *
 *  @param  operationType This parameter determines which operation the
 *          callback refers to.
 */
typedef void (*AESGCM_CallbackFxn) (AESGCM_Handle handle,
                                    int_fast16_t returnValue,
                                    AESGCM_Operation *operation,
                                    AESGCM_OperationType operationType);

/*!
 *  @brief  GCM Parameters
 *
 *  GCM Parameters are used to with the AESGCM_open() call. Default values for
 *  these parameters are set using AESGCM_Params_init().
 *
 *  @sa     AESGCM_Params_init()
 */
typedef struct {
    AESGCM_ReturnBehavior   returnBehavior;             /*!< Blocking, callback, or polling return behavior */
    AESGCM_CallbackFxn      callbackFxn;                /*!< Callback function pointer */
    uint32_t                timeout;                    /*!< Timeout before the driver returns an error in
                                                         *   ::AESGCM_RETURN_BEHAVIOR_BLOCKING
                                                         */
    void                   *custom;                     /*!< Custom argument used by driver
                                                         *   implementation
                                                         */
} AESGCM_Params;

/*!
 *  @brief Default AESGCM_Params structure
 *
 *  @sa     AESGCM_Params_init()
 */
extern const AESGCM_Params AESGCM_defaultParams;

/*!
 *  @brief  This function initializes the GCM module.
 *
 *  @pre    The AESGCM_config structure must exist and be persistent before this
 *          function can be called. This function must also be called before
 *          any other GCM driver APIs. This function call does not modify any
 *          peripheral registers.
 */
void AESGCM_init(void);

/*!
 *  @brief  Function to initialize the AESGCM_Params struct to its defaults
 *
 *  @param  params      An pointer to AESGCM_Params structure for
 *                      initialization
 *
 *  Defaults values are:
 *      returnBehavior              = AESGCM_RETURN_BEHAVIOR_BLOCKING
 *      callbackFxn                 = NULL
 *      timeout                     = SemaphoreP_WAIT_FOREVER
 *      custom                      = NULL
 */
void AESGCM_Params_init(AESGCM_Params *params);

/*!
 *  @brief  This function opens a given GCM peripheral.
 *
 *  @pre    GCM controller has been initialized using AESGCM_init()
 *
 *  @param  index         Logical peripheral number for the GCM indexed into
 *                        the AESGCM_config table
 *
 *  @param  params        Pointer to an parameter block, if NULL it will use
 *                        default values.
 *
 *  @return An AESGCM_Handle on success or a NULL on an error or if it has been
 *          opened already.
 *
 *  @sa     AESGCM_init()
 *  @sa     AESGCM_close()
 */
AESGCM_Handle AESGCM_open(uint_least8_t index, AESGCM_Params *params);

/*!
 *  @brief  Function to close a GCM peripheral specified by the GCM handle
 *
 *  @pre    AESGCM_open() has to be called first.
 *
 *  @param  handle A GCM handle returned from AESGCM_open()
 *
 *  @sa     AESGCM_open()
 */
void AESGCM_close(AESGCM_Handle handle);

/*!
 *  @brief  Function to initialize an AESGCM_Operation struct to its defaults
 *
 *  @param  operationStruct     A pointer to an AESGCM_Operation structure for
 *                              initialization
 *
 *  Defaults values are all zeros.
 */
void AESGCM_Operation_init(AESGCM_Operation *operationStruct);

/*!
 *  @brief  Function to perform an AESGCM 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    AESGCM_open() and AESGCM_Operation_init() have to be called first.
 *
 *  @param  [in] handle                 A GCM handle returned from AESGCM_open()
 *
 *  @param  [in] operationStruct        A pointer to a struct containing the parameters required to perform the operation.
 *
 *  @retval #AESGCM_STATUS_SUCCESS               The operation succeeded.
 *  @retval #AESGCM_STATUS_ERROR                 The operation failed.
 *  @retval #AESGCM_STATUS_RESOURCE_UNAVAILABLE  The required hardware resource was not available. Try again later.
 *  @retval #AESGCM_STATUS_CANCELED              The operation was canceled.
 *
 *  @sa     AESGCM_oneStepDecrypt()
 */
int_fast16_t AESGCM_oneStepEncrypt(AESGCM_Handle handle, AESGCM_Operation *operationStruct);

/*!
 *  @brief  Function to perform an AESGCM 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    AESGCM_open() and AESGCM_Operation_init() have to be called first.
 *
 *  @param  [in] handle                 A GCM handle returned from AESGCM_open()
 *
 *  @param  [in] operationStruct        A pointer to a struct containing the parameters required to perform the operation.
 *
 *  @retval #AESGCM_STATUS_SUCCESS               The operation succeeded.
 *  @retval #AESGCM_STATUS_ERROR                 The operation failed.
 *  @retval #AESGCM_STATUS_RESOURCE_UNAVAILABLE  The required hardware resource was not available. Try again later.
 *  @retval #AESGCM_STATUS_CANCELED              The operation was canceled.
 *  @retval #AESGCM_STATUS_MAC_INVALID           The provided MAC did no match the recomputed one.
 *
 *  @sa     AESGCM_oneStepEncrypt()
 */
int_fast16_t AESGCM_oneStepDecrypt(AESGCM_Handle handle, AESGCM_Operation *operationStruct);

/*!
 *  @brief Cancels an ongoing AESGCM operation.
 *
 *  Asynchronously cancels an AESGCM operation. Only available when using
 *  AESGCM_RETURN_BEHAVIOR_CALLBACK or AESGCM_RETURN_BEHAVIOR_BLOCKING.
 *  The operation will terminate as though an error occured. The
 *  return status code of the operation will be AESGCM_STATUS_CANCELED.
 *
 *  @param  handle Handle of the operation to cancel
 *
 *  @retval #AESCBC_STATUS_SUCCESS               The operation was canceled.
 *  @retval #AESCBC_STATUS_ERROR                 The operation was not canceled.
 */
int_fast16_t AESGCM_cancelOperation(AESGCM_Handle handle);

#ifdef __cplusplus
}
#endif

#endif /* ti_drivers_AESGCM__include */
