blob: d62569240ff8c13510d427965c87f92bcfbbfe02 [file] [log] [blame]
/*****************************************************************************
* © 2015 Microchip Technology Inc. and its subsidiaries.
* You may use this software and any derivatives exclusively with
* Microchip products.
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".
* NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
* AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP
* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
* INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
* WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS
* BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.
* TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
* CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF
* FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE
* OF THESE TERMS.
*****************************************************************************/
#ifndef INCLUDE_CEC1302_CRYPTO_API_H_
#define INCLUDE_CEC1302_CRYPTO_API_H_
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Misc. */
/* RNG */
/**
* \rng_power
*
* \param [in] pwr_on Power On?
* \return none
*
* \details Gate clocks on/off to NDRNG block
*/
extern void
rng_power(bool pwr_on);
/**
* \rng_reset
*
* \return Reset NDRNG block
*
* \details
*/
extern void
rng_reset(void);
/**
* \rng_mode
*
* \param [in] mode tmode_pseudo 0(asynchronous/true random mode),
* Non-zero(pseudo-random mode)
* \return None
*
* \details Set NDRNG random number generation mode
*/
extern void
rng_mode(uint8_t mode);
/**
* \rng_is_on
*
* \return is NDRNG Block powered on? True if yes, false otherwise
*
* \details Check if NDRNG block is powered on.
*/
extern bool
rng_is_on(void);
/**
* \rng_start
*
* \return None
*
* \details Start NDRNG engine
*/
extern void
rng_start(void);
/**
* \rng_stop
*
* \return Void
*
* \details Stop NDRNG engine
*/
extern void
rng_stop(void);
/**
* \rng_get_fifo_level
*
* \return actual number of 32-bit words in the NDRNG FIFO.
*
* \details return the number of 32-bit words of random data
* currently in the FIFO.
*/
extern uint32_t
rng_get_fifo_level(void);
/**
* \rng_get_bytes
*
* \param [in] pbuff Output Buffer
* \param [in] nbytes Number of bytes to be read
* \return Number of bytes retrieved
*
* \details read bytes from the NDRNG FIFO
*/
extern uint32_t
rng_get_bytes(uint8_t* pbuff, uint32_t nbytes);
/**
* \rng_get_words
*
* \param [in] pwords Pointer to output buffer
* \param [in] nwords Number of words to read
* \return actual number of words read
*
* \details Details
*/
extern uint32_t
rng_get_words(uint32_t* pwords, uint32_t nwords);
/* AES */
/**
* \aes_hash_power
*
* \param [in] pwr_on Gate/Ungate clocks to block
* \return None
*
* \details Enable/Disable AES and HASH H/W Block
*/
extern void
aes_hash_power(uint8_t pwr_on);
/**
* \aes_hash_reset
*
* \return None
*
* \details Stop AES and HASH
*/
extern void
aes_hash_reset(void);
/**
* \aes_busy
*
* \return Is AES Block Running? True if yes, false Otherwise.
*
* \details Is AES Block Running?
*/
extern bool
aes_busy(void);
/**
* \aes_status
*
* \return Status of AES Block
*
* \details Returns the Status of AES Block
*/
extern uint32_t
aes_status(void);
/**
* \aes_done_status
*
* \param [in] hw_status Pointer to where the status value will be updated
* \return True if done, false otherwise
*
* \details Returns the done status of AES block
*/
extern bool
aes_done_status(uint32_t* hw_status);
/**
* \aes_stop
*
* \return Return aes_busy() Status
*
* \details Stop AES Operations
*/
extern bool
aes_stop(void);
/**
* \aes_start
*
* \param [in] ien Enable interrupts?
* \return None
*
* \details Start AES block with or without interrupts
*/
extern void
aes_start(bool ien);
/**
* \aes_iclr
*
* \return Status of the AES Block
*
* \details Clears AES Hash Interrupts
*/
extern uint32_t
aes_iclr(void);
/**
* \brief Brief
*
* \param [in] pkey Aligned buffer with AES Key
* \param [in] piv Aligned buffer with AES initialization
* \param [in] key_len AES_KEYLEN_128, AES_KEYLEN_192, AES_KEYLEN_256
* \param [in] msbf Most Significant Byte order first?
* \return AES_ERR_BAD_POINTER, AES_ERR_BAD_KEY_LEN, AES_OK
*
* \details Load AES Accelerator with key and optional Initialization vector
*/
extern uint8_t
aes_set_key(const uint32_t* pkey,
const uint32_t* piv,
uint8_t key_len, bool msbf);
/**
* \aes_crypt
*
* \param [in] data_in Aligned input data Buffer
* \param [in] data_out Aligned output data buffer
* \param [in] num_128bit_blocks Size of input in 16-byte blocks
* \param [in] mode AES Encryption/Decryption Mode
* \return AES_OK, AES_ERR_BAD_POINTER,
*
* \details Program specified AES Operation using currently programmed key
*/
extern uint8_t
aes_crypt(const uint32_t* data_in,
uint32_t* data_out,
uint32_t num_128bit_blocks, uint8_t mode);
/* SHA */
#define SHA1_BLEN (20u)
#define SHA1_WLEN (5u)
#define SHA2_BLEN (32u)
#define SHA2_WLEN (8u)
#define SHA12_BLOCK_BLEN (64u)
#define SHA12_BLOCK_WLEN (16u)
#define SHA3_BLEN (48u)
#define SHA3_WLEN (12u)
#define SHA5_BLEN (64u)
#define SHA5_WLEN (16u)
/* return values */
#define SHA_RET_OK (0) /* OK */
#define SHA_RET_START (1) /* OK, SHA Engine started */
#define SHA_RET_ERROR (0x80) /* b[7]==1 indicates an error */
#define SHA_RET_ERR_BUSY (0x80)
#define SHA_RET_ERR_BAD_ADDR (0x81)
#define SHA_RET_ERR_TIMEOUT (0x82)
#define SHA_RET_ERR_MAX_LEN (0x83)
#define SHA_RET_ERR_UNSUPPORTED (0x84)
#define SHA_MODE_MD5 (0) // Not supported by HW
#define SHA_MODE_1 (1)
#define SHA_MODE_224 (2) // Not supported by HW
#define SHA_MODE_256 (3)
#define SHA_MODE_384 (4) // Not supported by HW
#define SHA_MODE_512 (5) // Not supported by HW
#define HASH_START_IEN (1u)
#define HASH_START_NOIEN (0u)
typedef union {
uint32_t w[SHA2_WLEN];
uint8_t b[SHA2_BLEN];
} SHA12_DIGEST_U;
/*
* !!! SHA-1 & SHA-256
* HW Engine requires alignment >= 4-byte boundary !!!
*/
typedef struct sha12_context_s SHA12_CONTEXT_T;
struct sha12_context_s {
SHA12_DIGEST_U hash;
union {
uint32_t w[(SHA12_BLOCK_WLEN) * 2];
uint8_t b[(SHA12_BLOCK_BLEN) * 2];
} block;
uint8_t mode;
uint8_t block_len;
uint8_t rsvd[2];
uint32_t total_msg_len;
};
/**
* \hash_busy
*
* \return is busy? True if yes, Flase other wise
*
* \details returns the busy status of Hash Block
*/
extern bool hash_busy(void);
/**
* \hash_start
*
* \param [in] ien enable/disable interrupts
* \return None
*
* \details start hash block
*/
extern void
hash_start(bool ien);
/**
* \hash_done_status
*
* \param [in] hw_status Hash Status Register Value
* \return true if done, false otherwise
*
* \details reflects the done status of HASH black and updates
* status regsiter value into the input variable
*/
extern bool
hash_done_status(uint32_t* hw_status);
/**
* \sha12_init
*
* \param [in] psha12_ctx Data Structure for Input data and Output Digest
* \param [in] mode SHA_MODE_1 or SHA_MODE_256
* \return SHA_RET_ERR_BAD_ADDR, SHA_RET_ERR_UNSPPORTED ,SHA_RET_OK
*
* \details Initializes the Data structure provided
*/
extern uint8_t
sha12_init(SHA12_CONTEXT_T* psha12_ctx, uint8_t mode);
/**
* \sha12_update
*
* \param [in] psha12_ctx Data Structure for Input data and Output Digest
* \param [in] pdata Input Data to Hash Block
* \param [in] num_bytes Byte length of input data
* \return SHA_RET_ERR_BAD_ADDR, SHA_RET_ERR_BUSY, SHA_RET_ERR_MAX_LEN, SHA_RET_OK
*
* \details Run hash block on data and if data greater than block size, put remaining bytes back into the data structure
*/
extern uint8_t
sha12_update(SHA12_CONTEXT_T* psha12_ctx,
const uint32_t* pdata, uint32_t num_bytes);
/**
* \sha12_finalize
*
* \param [in] psha12_ctx Data Structure for Input data and Output Digest
* \return SHA_RET_ERR_BAD_ADDR, SHA_RET_ERR_BUSY ,SHA_RET_START
*
* \details Apply FIPS padding to SHA256 and perform final hash calculation.
*/
extern uint8_t
sha12_finalize(SHA12_CONTEXT_T* psha12_ctx);
/**
* \sha256_pad_fill
*
* \param [in] pblock64 Aligned Memory buffer of atleast 64 bytes
* \param [in] msg_byte_len Length of Message in bytes
* \return None
*
* \details Zero and fill a 64-byte SHA256 pad block with FIP padding values
*/
extern void
sha256_pad_fill(uint32_t* pblock64, uint32_t msg_byte_len);
/**
* \sha256_raw
*
* \param [in] pdata Input Message
* \param [in] pdigest Pointer to biffer where digest will be written
* \param [in] num64byte_blocks size of input data in blocks
* \return SHA_RET_ERR_BAD_ADDR, SHA_RET_ERR_BUSY ,SHA_RET_START
*
* \details Calculate SHA256 on data
*/
extern uint8_t
sha256_raw(uint32_t* pdata, uint32_t* pdigest, uint32_t num64byte_blocks);
/**
* \sha256_raw_init
*
* \param [in] psha256_digest Pointer to buffer where digest will be written
* \return None
*
* \details Initialize the SHA256 Digest data block
*/
extern void
sha256_raw_init(uint32_t* psha256_digest);
/**
* \sha256_raw_update
*
* \param [in] pdata Message on which HASH block is to be called
* \param [in] pdigest Pointer to where the digest will be stored
* \param [in] num64byte_blocks size of input data in blocks
* \return SHA_RET_ERR_BAD_ADDR, SHA_RET_ERR_BUSY ,SHA_RET_START
*
* \details run Hash block on data
*/
extern uint8_t
sha256_raw_update(uint32_t* pdata,
uint32_t* pdigest, uint32_t num64byte_blocks);
/**
* \hash_iclr
*
* \return Hash Block status
*
* \details Clear Hash Interrupt
*/
extern uint32_t
hash_iclr(void);
/**
* \sha_init
*
* \param [in] mode SHA_MODE_1, SHA_MODE_256, SHA_MODE_512
* \param [in] pdigest Address where digest will be stored
* \return * 0 = Success
* 1 = Hash Engine busy
* 2 = Unsupported SHA operation
* 3 = Bad digest pointer, NULL or mis-aligned.
* \details Initialize Hash engine for SHA operation.
* Programs supported SHA operation's initial value, digest address,
* and operation
*/
extern uint8_t
sha_init(uint8_t mode, uint32_t* pdigest);
/**
* \sha_update
*
* \param [in] pdata Input Data
* \param [in] nblocks Size in blocks
* \param [in] flags bit(0) - Clear Status?, bit(1) - Enable Interrupts?, bit(2) - Start?
* \return 0 - OK, 1 - Hash Busy, 2 - bad address for data, 3 - Buffer not aligned
*
* \details Run Hash block on data
*/
extern uint8_t
sha_update(uint32_t* pdata, uint16_t nblocks, uint8_t flags);
/**
* \sha_final
*
* \param [in] padbuf Buffer for padding (Twice block size)
* \param [in] total_msg_len Message length in bytes
* \param [in] prem Parameter_Description
* \param [in] flags bit(0) - Clear Status?, bit(1) - Enable Interrupts?, bit(2) - Start?
* \return 0 - OK, 1 - Hash Busy, 2 - bad address for data, 3 - Buffer not aligned
*
* \details Run final SHA Calculations and add padding
*/
extern uint8_t
sha_final(uint32_t* padbuf, uint32_t total_msg_len,
const uint8_t* prem, uint8_t flags);
/* PKE Miscellaneous */
#define PKE_RET_STARTED (0)
#define PKE_RET_OK (0)
#define PKE_RET_ERR_BUSY (1)
#define PKE_RET_ERR_BAD_PARAM (2)
#define PKE_RET_ERR_BAD_ADDR (3)
#define PKE_RET_ERR_UNKNOWN_OP (4)
#define PKE_RET_ERR_INVALID_BIT_LENGTH (5)
#define PKE_RET_ERR_INVALID_MSG_LENGTH (6)
/**
* \pke_power
*
* \param [in] pwr_on power on?
* \return None
*
* \details Gate or Ungate power to PKE block
*/
extern void
pke_power(bool pwr_on);
/**
* \brief pke_reset
*
* \return None
*
* \details Reset PKE Block
*/
extern void
pke_reset(void);
/**
* \pke_status
*
* \return Return PKE Status register value
*
* \details Details
*/
extern uint32_t
pke_status(void);
/**
* \pke_done_status
*
* \param [in] hw_status POinter where PKE Status is updated
* \return True if done, false otherwise
*
* \details Returns the done status of PKE block
*/
extern bool
pke_done_status(uint32_t* hw_status);
/**
* \pke_start
*
* \param [in] ien Interrupt Enable?
* \return None
*
* \details Start PKE Block
*/
extern void
pke_start(bool ien);
/**
* \pke_busy
*
* \return Busy? True if busy, false otherwise
*
* \details Details
*/
extern bool
pke_busy(void);
/**
* \pke_clear_scm
*
* \return None
*
* \details Clear the Shared Crypto memory
*/
extern void
pke_clear_scm(void);
/**
* \pke_scm_clear_slot
*
* \param [in] slot_num Slot number in Shared Crypto Memory
* \return None
*
* \details Clear the specified slot in Shared Crypto Memory
*/
extern void
pke_scm_clear_slot(uint8_t slot_num);
/**
* \pke_read_scm
*
* \param [in] dest Pointer to where the data is to be read
* \param [in] nbytes Number of bytes to be read
* \param [in] slot_num Slot number from which data is to be read
* \param [in] reverse_byte_order Reverse Byte order? True if yes, false otherwise
* \return Number of bytes Read
*
* \details Read data from specified slot number in Shared Crypto memory
*/
extern uint16_t
pke_read_scm(uint8_t* dest, uint16_t nbytes,
uint8_t slot_num, bool reverse_byte_order);
/**
* \pke_write_scm
*
* \param [in] pdata Data to be written
* \param [in] num_bytes Number of bytes to be written
* \param [in] slot_num Slot number to which data ought to be written
* \param [in] reverse_byte_order Reverse Byte order? True if yes, false otherwise
* \return None
*
* \details Write data provided to specified slot in Shared Crypto Memory
*/
extern void
pke_write_scm(const void* pdata, uint16_t num_bytes,
uint8_t slot_num, uint8_t reverse_byte_order);
/* PKE RSA */
/**
* \ rsa_load_key
*
* \param [in] rsa_bit_len 1024, 2048
* \param [in] private_exponent Pointer to private exponent
* \param [in] public_modulus Pointer to Public modulus
* \param [in] public_exponent Pointer to Public Exponent
* \param [in] public_exponent_byte_len Length in bytes of Public Exponent
* \param [in] msbf Reverse Byte order? True if yes, false otherwise
* \return PKE_RET_ERR_BUSY, PKE_RET_ERR_INVALID_BIT_LENGTH, PKE_RET_OK
*
* \details Load RSA keys into Crypto memory
*/
extern uint8_t
rsa_load_key(uint16_t rsa_bit_len,
const uint8_t* private_exponent,
const uint8_t* public_modulus,
const uint8_t* public_exponent,
uint16_t public_exponent_byte_len,
bool msbf);
/**
* \ rsa_encrypt
*
* \param [in] rsa_bit_len 1024, 2048
* \param [in] mesg Message to be encrypted
* \param [in] mlen length of message
* \param [in] flags bit[0]=0(do not start), 1(start after programming), bit[4] = byte order: 0 = Least significant byte first, 1 = Most significant byte first, bit[1]=0(do not enable interrupt), 1(enable interrupt before starting)
* \return PKE_RET_ERR_BAD_ADDR, PKE_RET_ERR_BUSY, PKE_RET_ERR_INVALID_MSG_LENGTH, PKE_RET_ERR_INVALID_BIT_LENGTH, PKE_RET_OK
*
* \details Encrypt provided message. Load Keys before this function is called
*/
extern uint8_t
rsa_encrypt(uint16_t rsa_bit_len,
const uint8_t* mesg,
uint16_t mlen,
uint8_t flags);
/**
* \ rsa_decrypt
*
* \param [in] rsa_bit_len 1024, 2048
* \param [in] encrypted_mesg Encrypted data
* \param [in] mlen length of encrypted message
* \param [in] flags flags bit[0]=0(do not start), 1(start after programming), bit[4] = byte order: 0 = Least significant byte first, 1 = Most significant byte first, bit[1]=0(do not enable interrupt), 1(enable interrupt before starting)
* \return PKE_RET_ERR_BAD_ADDR, PKE_RET_ERR_BUSY, PKE_RET_ERR_INVALID_MSG_LENGTH, PKE_RET_ERR_INVALID_BIT_LENGTH, PKE_RET_OK
*
* \details Perform decryption on provided encrypted message. load keys before calling this function
*/
extern uint8_t
rsa_decrypt(uint16_t rsa_bit_len,
const uint8_t* encrypted_mesg,
uint16_t mlen,
uint8_t flags);
#ifdef __cplusplus
}
#endif
#endif /* INCLUDE_CEC1302_CRYPTO_API_H_ */