/**
\code

 / _____)             _              | |
( (____  _____ ____ _| |_ _____  ____| |__
 \____ \| ___ |    (_   _) ___ |/ ___)  _ \
 _____) ) ____| | | || |_| ____( (___| | | |
(______/|_____)_|_|_| \__)_____)\____)_| |_|
    (C)2013 Semtech
 ___ _____ _   ___ _  _____ ___  ___  ___ ___
/ __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
\__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
embedded.connectivity.solutions===============

\endcode

Description: LoRa MAC Crypto implementation

License: Revised BSD License, see LICENSE.TXT file include in the project

Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )


Copyright (c) 2017, Arm Limited and affiliates.

SPDX-License-Identifier: BSD-3-Clause
*/

#ifndef MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__
#define MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__

#include "mbedtls/aes.h"
#include "mbedtls/cmac.h"


class LoRaMacCrypto
{
public:
    /**
     * Constructor
     */
    LoRaMacCrypto();

    /**
     * Computes the LoRaMAC frame MIC field
     *
     * @param [in]  buffer          - Data buffer
     * @param [in]  size            - Data buffer size
     * @param [in]  key             - AES key to be used
     * @param [in]  key_length      - Length of the key (bits)
     * @param [in]  address         - Frame address
     * @param [in]  dir             - Frame direction [0: uplink, 1: downlink]
     * @param [in]  seq_counter     - Frame sequence counter
     * @param [out] mic             - Computed MIC field
     *
     * @return                        0 if successful, or a cipher specific error code
     */
    int compute_mic(const uint8_t *buffer, uint16_t size,
                    const uint8_t *key, uint32_t key_length,
                    uint32_t address, uint8_t dir, uint32_t seq_counter,
                    uint32_t *mic);

    /**
     * Performs payload encryption
     *
     * @param [in]  buffer          - Data buffer
     * @param [in]  size            - Data buffer size
     * @param [in]  key             - AES key to be used
     * @param [in]  key_length      - Length of the key (bits)
     * @param [in]  address         - Frame address
     * @param [in]  dir             - Frame direction [0: uplink, 1: downlink]
     * @param [in]  seq_counter     - Frame sequence counter
     * @param [out] enc_buffer      - Encrypted buffer
     *
     * @return                        0 if successful, or a cipher specific error code
     */
    int encrypt_payload(const uint8_t *buffer, uint16_t size,
                        const uint8_t *key, uint32_t key_length,
                        uint32_t address, uint8_t dir, uint32_t seq_counter,
                        uint8_t *enc_buffer);

    /**
     * Performs payload decryption
     *
     * @param [in]  buffer          - Data buffer
     * @param [in]  size            - Data buffer size
     * @param [in]  key             - AES key to be used
     * @param [in]  key_length      - Length of the key (bits)
     * @param [in]  address         - Frame address
     * @param [in]  dir             - Frame direction [0: uplink, 1: downlink]
     * @param [in]  seq_counter     - Frame sequence counter
     * @param [out] dec_buffer      - Decrypted buffer
     *
     * @return                        0 if successful, or a cipher specific error code
     */
    int decrypt_payload(const uint8_t *buffer, uint16_t size,
                        const uint8_t *key, uint32_t key_length,
                        uint32_t address, uint8_t dir, uint32_t seq_counter,
                        uint8_t *dec_buffer);

    /**
     * Computes the LoRaMAC Join Request frame MIC field
     *
     * @param [in]  buffer          - Data buffer
     * @param [in]  size            - Data buffer size
     * @param [in]  key             - AES key to be used
     * @param [in]  key_length      - Length of the key (bits)
     * @param [out] mic             - Computed MIC field
     *
     * @return                        0 if successful, or a cipher specific error code
     *
     */
    int compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
                               const uint8_t *key, uint32_t key_length,
                               uint32_t *mic);

    /**
     * Computes the LoRaMAC join frame decryption
     *
     * @param [in]  buffer          - Data buffer
     * @param [in]  size            - Data buffer size
     * @param [in]  key             - AES key to be used
     * @param [in]  key_length      - Length of the key (bits)
     * @param [out] dec_buffer      - Decrypted buffer
     *
     * @return                        0 if successful, or a cipher specific error code
     */
    int decrypt_join_frame(const uint8_t *buffer, uint16_t size,
                           const uint8_t *key, uint32_t key_length,
                           uint8_t *dec_buffer);

    /**
     * Computes the LoRaMAC join frame decryption
     *
     * @param [in]  key              - AES key to be used
     * @param [in]  key_length       - Length of the key (bits)
     * @param [in]  app_nonce        - Application nonce
     * @param [in]  dev_nonce        - Device nonce
     * @param [out] nwk_skey         - Network session key
     * @param [out] app_skey         - Application session key
     *
     * @return                        0 if successful, or a cipher specific error code
     */
    int compute_skeys_for_join_frame(const uint8_t *key, uint32_t key_length,
                                     const uint8_t *app_nonce, uint16_t dev_nonce,
                                     uint8_t *nwk_skey, uint8_t *app_skey);

private:
    /**
     * AES computation context variable
     */
    mbedtls_aes_context aes_ctx;

    /**
     * CMAC computation context variable
     */
    mbedtls_cipher_context_t aes_cmac_ctx[1];
};

#endif // MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__
