
/**
 *  \file cry.h
 *
 *  Platform header file for cryptographic functions that will be used from
 *  other IP modules.
 */

/*
 *  Copyright (C) 2016. Mindtree Limited.
 *  All rights reserved.
 */

/* --------------------------------------------- Header File Inclusion */
#include "EM_os.h"

//#define CRY_ECDH_TIMESLICE

#define PHYPLUS_ECDH_ENABLE            

/* --------------------------------------------- Global Definitions */
/* Size definitions */
#define CRY_AES128_DATALEN              16
#define CRY_AES128_KEYLEN               16
#define CRY_AES128CCM_DATALEN_MAX       150
#define CRY_AES128CMAC_DATALEN_MAX      150
#define CRY_AES128CMAC_MACLEN           16
#define CRY_ECDH_PUBKEY_SIZE            64
#define CRY_ECDH_PVTKEY_SIZE            32
#define CRY_ECDH_SECRET_SIZE            32

/* AES-CMAC operations */
#define CRY_AES_128_CMAC_SIGN           0x00
#define CRY_AES_128_CMAC_VERIFY         0x01

/* --------------------------------------------- Structures/Data Types */

/* --------------------------------------------- Macros */
#define CRY_LE2BE(s,d,l)    cry_reverse_bytestream_endianness((s),(d),(l))
#define CRY_BE2LE(s,d,l)    cry_reverse_bytestream_endianness((s),(d),(l))

/* --------------------------------------------- Internal Functions */

/* --------------------------------------------- API Declarations */
#define cry_aes_128_encrypt_be(p, k, c, r) \
    (r) = cry_aes_128_encrypt((p), (k), (c))

#define cry_aes_128_decrypt_be(c, k, p, r) \
    (r) = cry_aes_128_decrypt((c), (k), (p))

#define cry_aes_128_ccm_encrypt_be(k, n, nl, p, pl, a, al, c, m, ml, r) \
    (r) = cry_aes_128_ccm_encrypt((k), (n), (nl), (p), (pl), (a), (al), (c), (m), (ml))

#define cry_aes_128_ccm_decrypt_be(k, n, nl, c, cl, a, al, p, m, ml, r) \
    (r) = cry_aes_128_ccm_decrypt((k), (n), (nl), (c), (cl), (a), (al), (p), (m), (ml))

#define cry_aes_128_cmac_sign_be(p, pl, k, m, ml, r) \
    (r) = cry_aes_128_cmac(CRY_AES_128_CMAC_SIGN, (p), (pl), (k), (m), (ml))

#define cry_aes_128_cmac_verify_be(p, pl, k, m, ml, r) \
    (r) = cry_aes_128_cmac(CRY_AES_128_CMAC_VERIFY, (p), (pl), (k), (m), (ml))

#define cry_ecdh_get_public_key_be(p, r) \
    (r) = cry_ecdh_get_public_key((p))

#define cry_ecdh_generate_secret_be(p, s, sl, r, cb) \
    (r) = cry_ecdh_generate_secret((p), (s), (sl), (cb)); \


#define cry_aes_128_encrypt_le(p, k, c, r) \
{ \
    UCHAR cry_plain[CRY_AES128_DATALEN]; \
    UCHAR cry_key[CRY_AES128_KEYLEN]; \
    UCHAR cry_cipher[CRY_AES128_DATALEN]; \
 \
    CRY_LE2BE((p), cry_plain, CRY_AES128_DATALEN); \
    CRY_LE2BE((k), cry_key, CRY_AES128_KEYLEN); \
 \
    (r) = cry_aes_128_encrypt(cry_plain, cry_key, cry_cipher); \
 \
    CRY_BE2LE(cry_cipher, (c), CRY_AES128_DATALEN); \
}

#define cry_aes_128_decrypt_le(c, k, p, r) \
{ \
    UCHAR cry_plain[CRY_AES128_DATALEN]; \
    UCHAR cry_key[CRY_AES128_KEYLEN]; \
    UCHAR cry_cipher[CRY_AES128_DATALEN]; \
    \
    CRY_LE2BE((c), cry_cipher, CRY_AES128_DATALEN); \
    CRY_LE2BE((k), cry_key, CRY_AES128_KEYLEN); \
    \
    (r) = cry_aes_128_decrypt(cry_cipher, cry_key, cry_plain); \
    \
    CRY_BE2LE(cry_plain, (p), CRY_AES128_DATALEN); \
}

#define cry_aes_128_ccm_encrypt_le(k, n, nl, p, pl, a, al, c, m, ml, r) \
{ \
    UCHAR cry_plain[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_nonce[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_addl[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_cipher[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_mac[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_key[CRY_AES128_KEYLEN]; \
 \
    CRY_LE2BE((p), cry_plain, (pl)); \
    CRY_LE2BE((n), cry_nonce, (nl)); \
    CRY_LE2BE((a), cry_addl, (al)); \
    CRY_LE2BE((k), cry_key, CRY_AES128_KEYLEN); \
 \
    (r) = cry_aes_128_ccm_encrypt(cry_key, cry_nonce, (nl), cry_plain, (pl), cry_addl, (al), cry_cipher, cry_mac, (ml)); \
 \
    CRY_BE2LE(cry_cipher, (c), (pl)); \
    CRY_BE2LE(cry_mac, (m), (ml)); \
}

#define cry_aes_128_ccm_decrypt_le(k, n, nl, c, cl, a, al, p, m, ml, r) \
{ \
    UCHAR cry_plain[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_nonce[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_addl[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_cipher[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_mac[CRY_AES128CCM_DATALEN_MAX]; \
    UCHAR cry_key[CRY_AES128_KEYLEN]; \
 \
    CRY_LE2BE((c), cry_cipher, (cl)); \
    CRY_LE2BE((n), cry_nonce, (nl)); \
    CRY_LE2BE((a), cry_addl, (al)); \
    CRY_LE2BE((m), cry_mac, (ml)); \
    CRY_LE2BE((k), cry_key, CRY_AES128_KEYLEN); \
 \
    (r) = cry_aes_128_ccm_decrypt(cry_key, cry_nonce, (nl), cry_cipher, (cl), cry_addl, (al), cry_plain, cry_mac, (ml)); \
 \
    CRY_BE2LE(cry_plain, (p), (cl)); \
}

#define cry_aes_128_cmac_sign_le(p, pl, k, m, ml, r) \
{ \
    UCHAR cry_plain[CRY_AES128CMAC_DATALEN_MAX]; \
    UCHAR cry_key[CRY_AES128_KEYLEN]; \
    UCHAR cry_mac[CRY_AES128CMAC_MACLEN]; \
 \
    CRY_LE2BE((p), cry_plain, (pl)); \
    CRY_LE2BE((k), cry_key, CRY_AES128_KEYLEN); \
 \
    (r) = cry_aes_128_cmac(CRY_AES_128_CMAC_SIGN, cry_plain, (pl), cry_key, cry_mac, (ml)); \
 \
     CRY_BE2LE(cry_mac, (m), (ml)); \
}

#define cry_aes_128_cmac_verify_le(p, pl, k, m, ml, r) \
{ \
    UCHAR cry_plain[CRY_AES128CMAC_DATALEN_MAX]; \
    UCHAR cry_key[CRY_AES128_KEYLEN]; \
    UCHAR cry_mac[CRY_AES128CMAC_MACLEN]; \
    \
    CRY_LE2BE((p), cry_plain, (pl)); \
    CRY_LE2BE((k), cry_key, CRY_AES128_KEYLEN); \
    CRY_LE2BE((m), cry_mac, (ml)); \
    \
    (r) = cry_aes_128_cmac(CRY_AES_128_CMAC_VERIFY, cry_plain, (pl), cry_key, cry_mac, (ml)); \
}

#define cry_ecdh_get_public_key_le(p, r) \
{ \
    UCHAR cry_pub[CRY_ECDH_PUBKEY_SIZE]; \
 \
    (r) = cry_ecdh_get_public_key(cry_pub); \
 \
    CRY_BE2LE(cry_pub, (p), CRY_ECDH_PUBKEY_SIZE); \
 \
}

#define cry_ecdh_generate_secret_le(p, s, sl, r, cb) \
{ \
    UCHAR cry_pub[CRY_ECDH_PUBKEY_SIZE]; \
    UCHAR cry_skey[CRY_ECDH_SECRET_SIZE]; \
 \
    CRY_LE2BE((p), cry_pub, CRY_ECDH_PUBKEY_SIZE); \
 \
    (r) = cry_ecdh_generate_secret(cry_pub, cry_skey, (sl), (cb)); \
 \
    CRY_BE2LE(cry_skey, (s), (sl)); \
 \
}


void cry_reverse_bytestream_endianness(UCHAR * src, UCHAR * dst, UINT16 len);
void cry_reverse_bytestream_in_place(UCHAR * src, UINT16 len);

INT32 cry_rand_generate(UCHAR * prand, UINT16 randlen);

INT32 cry_aes_128_encrypt
      (
          UCHAR * pdata,
          UCHAR * pkey,
          UCHAR * pencdata
      );

INT32 cry_aes_128_decrypt
      (
          UCHAR * pencdata,
          UCHAR * pkey,
          UCHAR * pdata
      );

INT32 cry_aes_128_ccm_encrypt
      (
          UCHAR * pkey,
          UCHAR * pnonce,
          UINT16  noncelen,
          UCHAR * pdata,
          UINT16  datalen,
          UCHAR * paddata,
          UINT16  addatalen,
          UCHAR * pencdata,
          UCHAR * pmac,
          UINT16  maclen
      );

INT32 cry_aes_128_ccm_decrypt
      (
          UCHAR * pkey,
          UCHAR * pnonce,
          UINT16  noncelen,
          UCHAR * pencdata,
          UINT16  encdatalen,
          UCHAR * paddata,
          UINT16  addatalen,
          UCHAR * pdata,
          UCHAR * pmac,
          UINT16  maclen
      );

INT32 cry_aes_128_cmac
      (
          UCHAR   op,
          UCHAR * pdata,
          UINT16  datalen,
          UCHAR * pkey,
          UCHAR * pmac,
          UINT16  maclen
      );

INT32 cry_ecdh_init(void);
INT32 cry_ecdh_get_public_key(UCHAR * pubkey);
INT32 cry_ecdh_generate_secret
      (
          UCHAR * peer_pubkey,
          UCHAR * secret,
          UINT16 secret_len,
          void (*ecdh_cb)(UCHAR *)
      );
INT32 cry_set_ecdh_debug_keypair(UCHAR * pvtkey, UCHAR * pubkey);

#ifdef CRY_ECDH_TIMESLICE
INT32 cry_ecdh_process_secret(void);
#endif /* CRY_ECDH_TIMESLICE */
 
typedef int(*uCrypto_RNG_Function)(uint8_t *dest, uint32_t size);
void uCrypto_set_rng(uCrypto_RNG_Function rng_function);
 
uCrypto_RNG_Function uCrypto_get_rng(void);
INT32 phyplus_ecdh_init(void);
INT32 phyplus_ecdh_generate_secret(UCHAR * peer_pubkey, UCHAR * secret, UINT16 secret_len);
INT32 phyplus_ecdh_get_public_key(UCHAR * pubkey);


void test_verify_phyplus_ecdh(void);
