/**************************************************************************************
* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved         *
*                                                                                     *
* This file and the related binary are licensed under the following license:          *
*                                                                                     *
* ARM Object Code and Header Files License, v1.0 Redistribution.                      *
*                                                                                     *
* Redistribution and use of object code, header files, and documentation, without     *
* modification, are permitted provided that the following conditions are met:         *
*                                                                                     *
* 1) Redistributions must reproduce the above copyright notice and the                *
*    following disclaimer in the documentation and/or other materials                 *
*    provided with the distribution.                                                  *
*                                                                                     *
* 2) Unless to the extent explicitly permitted by law, no reverse                     *
*    engineering, decompilation, or disassembly of is permitted.                      *
*                                                                                     *
* 3) Redistribution and use is permitted solely for the purpose of                    *
*    developing or executing applications that are targeted for use                   *
*    on an ARM-based product.                                                         *
*                                                                                     *
* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND                  *
* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT             *
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT,        *
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          *
* COPYRIGHT HOLDERS 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.                        *
**************************************************************************************/




#ifndef CRYS_RND_H
#define CRYS_RND_H

#include "crys_error.h"
#include "ssi_aes.h"

#ifdef __cplusplus
extern "C"
{
#endif

/*!
@file
@brief This file contains the CRYS APIs used for random number generation.
The random-number generation module implements referenced standard [SP800-90].
@defgroup crys_rnd CryptoCell Random Generator APIs
@{
@ingroup cryptocell_api
*/

/************************ Defines ******************************/

/*!  Maximal reseed counter - indicates maximal number of
requests allowed between reseeds; according to NIST 800-90
it is (2^48 - 1), our restriction is :  (0xFFFFFFFF - 0xF).*/
#define CRYS_RND_MAX_RESEED_COUNTER 	(0xFFFFFFFF - 0xF)

/* Max size for one RNG generation (in bits) =
  max_num_of_bits_per_request = 2^19 (FIPS 800-90 Tab.3) */
/*! Maximal size of generated vector in bits. */
#define CRYS_RND_MAX_GEN_VECTOR_SIZE_BITS       0x7FFFF
/*! Maximal size of generated vector in bytes. */
#define CRYS_RND_MAX_GEN_VECTOR_SIZE_BYTES      0xFFFF

/*! AES output block size in words. */
#define CRYS_RND_AES_BLOCK_SIZE_IN_WORDS  SASI_AES_BLOCK_SIZE_IN_WORDS


/* RND seed and additional input sizes */
/*! Maximal size of random seed in words. */
#define CRYS_RND_SEED_MAX_SIZE_WORDS                  12

#ifndef CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS
/*! Maximal size of additional input data in words. */
#define CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS	CRYS_RND_SEED_MAX_SIZE_WORDS
#endif

/* allowed sizes of AES Key, in words */
/*! AES key size (128 bits) in words. */
#define CRYS_RND_AES_KEY_128_SIZE_WORDS  4
/*! AES key size (192 bits) in words. */
#define CRYS_RND_AES_KEY_192_SIZE_WORDS  6
/*! AES key size (256 bits) in words. */
#define CRYS_RND_AES_KEY_256_SIZE_WORDS  8

/*   Definitions of temp buffer for RND_DMA version of CRYS_RND   */
/*******************************************************************/
/*   Definitions of temp buffer for DMA version of CRYS_RND   */

/*! Temporary buffer size in words. */
#define CRYS_RND_WORK_BUFFER_SIZE_WORDS 1528

/*! A definition for RAM buffer to be internally used in instantiation (or reseeding) operation. */
typedef struct
{
	/*! Internal buffer*/
	uint32_t crysRndWorkBuff[CRYS_RND_WORK_BUFFER_SIZE_WORDS];
}CRYS_RND_WorkBuff_t;

/*! A definition for entropy estimation data type. */
#define CRYS_RND_EntropyEstimatData_t  CRYS_RND_WorkBuff_t
/*! A definition for entropy estimation buffer. */
#define crysRndEntrIntBuff  crysRndWorkBuff


/* RND source buffer inner (entrpopy) offset       */
/*! An internal offset definition. */
#define CRYS_RND_TRNG_SRC_INNER_OFFSET_WORDS    2
/*! An internal offset definition. */
#define CRYS_RND_TRNG_SRC_INNER_OFFSET_BYTES    (CRYS_RND_TRNG_SRC_INNER_OFFSET_WORDS*sizeof(uint32_t))




/* Size of the expected output buffer used by FIPS KAT */
/*! FIPS Known answer test output size. */
#define CRYS_PRNG_FIPS_KAT_OUT_DATA_SIZE      64

/************************ Enumerators  ****************************/

/*! Definition of random operation modes. */
typedef  enum
{
	/*! SW entropy estimation mode. */
	CRYS_RND_Fast  = 0,
	/*! Full entropy mode. */
	CRYS_RND_Slow  = 1,
	/*! Reserved. */
	CRYS_RND_ModeLast = 0x7FFFFFFF,
} CRYS_RND_mode_t;



/************************ Structs  *****************************/


/* The internal state of DRBG mechanism based on AES CTR and CBC-MAC
   algorithms. It is set as global data defined by the following
   structure  */
/*! RND state structure. Includes internal data that needs to be saved between boots by the user.*/
typedef  struct
{
	/* Seed buffer, consists from concatenated Key||V: max size 12 words */
	/*! Random Seed buffer */
	uint32_t  Seed[CRYS_RND_SEED_MAX_SIZE_WORDS];
	/* Previous value for continuous test */
	/*! Previous random data (used for continuous test). */
	uint32_t  PreviousRandValue[SASI_AES_BLOCK_SIZE_IN_WORDS];

	/* AdditionalInput buffer max size = seed max size words + 4w for padding*/
	/*! Previous additional input buffer. */
	uint32_t  PreviousAdditionalInput[CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS+5];
	/*! Additional input buffer. */
	uint32_t  AdditionalInput[CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS+4];
	/*! Additional input size in words. */
	uint32_t  AddInputSizeWords; /* size of additional data set by user, words   */

	/*! Entropy source size in words */
	uint32_t  EntropySourceSizeWords;

	/*! Reseed counter (32 bits active) - indicates number of requests for entropy
	since instantiation or reseeding */
	uint32_t  ReseedCounter;

	/*! Key size: 4 or 8 words according to security strength 128 bits or 256 bits*/
	uint32_t KeySizeWords;

	/* State flag (see definition of StateFlag above), containing bit-fields, defining:
	- b'0: instantiation steps:   0 - not done, 1 - done;
	- 2b'9,8: working or testing mode: 0 - working, 1 - KAT DRBG test, 2 -
	  KAT TRNG test;
	b'16: flag defining is Previous random valid or not:
	        0 - not valid, 1 - valid */
	/*! State flag used internally in the code.*/
	uint32_t StateFlag;

	/* Trng processing flag - indicates which ROSC lengths are:
	-  allowed (bits 0-3);
	-  total started (bits 8-11);
	-  processed (bits 16-19);
	-  started, but not processed (bits24-27)              */
	/*! TRNG process state used internally in the code */
	uint32_t TrngProcesState;

	/* validation tag */
	/*! Validation tag used internally in the code */
	uint32_t ValidTag;

	/*! Rnd source entropy size in bits */
	uint32_t  EntropySizeBits;

} CRYS_RND_State_t;


/*! The RND Generate vector function pointer type definition.
   The prototype intendent for External and CRYS internal RND functions
   pointers definitions.
   Full description can be found in ::CRYS_RND_GenerateVector function API. */
typedef uint32_t (*SaSiRndGenerateVectWorkFunc_t)(        \
				void  *rndState_ptr, /*context*/   \
				uint16_t          outSizeBytes,   /*in*/      \
				uint8_t          *out_ptr         /*out*/);



/*! Data structure required for internal FIPS verification for PRNG KAT. */
typedef  struct
{
       /*! Internal working buffer. */
       CRYS_RND_WorkBuff_t      rndWorkBuff;
       /*! Output buffer. */
       uint8_t                  rndOutputBuff[CRYS_PRNG_FIPS_KAT_OUT_DATA_SIZE];
} CRYS_PrngFipsKatCtx_t;


/*****************************************************************************/
/**********************        Public Functions      *************************/
/*****************************************************************************/

/*!
@brief This function initializes the RND context.
It must be called at least once prior to using this context with any API that requires it as a parameter (e.g., other RND APIs, asymmetric
cryptography key generation and signatures).
It is called as part of ARM TrustZone CryptoCell library initialization, which initializes and returns the primary RND context.
This primary context can be used as a single global context for all RND needs.
Alternatively, other contexts may be initialized and used with a more limited scope (for specific applications or specific threads).
The call to this function must be followed by a call to ::CRYS_RND_SetGenerateVectorFunc API to set the generate vector function.
It implements referenced standard [SP800-90] - 10.2.1.3.2 - CTR-DRBG Instantiate algorithm using AES (FIPS-PUB 197) and Derivation Function (DF).
\note Additional data can be mixed with the random seed (personalization data or nonce). If required, this data should be provided by calling ::CRYS_RND_AddAdditionalInput prior to using this API.

@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_Instantiation(
                        void   *rndState_ptr,       /*!< [in/out]  Pointer to the RND state buffer allocated by the user, which is used to
										   maintain the RND state. This context state must be saved and provided as a
										   parameter to any API that uses the RND module.
										   \note the context must be cleared before sent to the function. */
                        CRYS_RND_WorkBuff_t  *rndWorkBuff_ptr       /*!< [in/out] Scratchpad for the RND module's work. */
);


/*!
@brief Clears existing RNG instantiation state.

@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_UnInstantiation(
                        void *rndState_ptr       /*!< [in/out] Pointer to the RND context state buffer. */
);


/*!
@brief This function is used for reseeding the RNG with additional entropy and additional user-provided input.
(additional data should be provided by calling ::CRYS_RND_AddAdditionalInput prior to using this API).
It implements referenced standard [SP800-90] - 10.2.1.4.2 - CTR-DRBG Reseeding algorithm, using AES (FIPS-PUB 197) and Derivation Function (DF).

@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_Reseeding(
                        void   *rndState_ptr,          /*!< [in/out] Pointer to the RND context buffer. */
                        CRYS_RND_WorkBuff_t  *rndWorkBuff_ptr      /*!< [in/out] Scratchpad for the RND module's work. */
);


/****************************************************************************************/
/*!
@brief Generates a random vector according to the algorithm defined in referenced standard [SP800-90] - 10.2.1.5.2 - CTR-DRBG.
The generation algorithm uses AES (FIPS-PUB 197) and Derivation Function (DF).

\note
<ul id="noteb"><li> The RND module must be instantiated prior to invocation of this API.</li>
<li> In the following cases, Reseeding operation must be performed prior to vector generation:</li>
    <ul><li> Prediction resistance is required.</li>
    <li> The function returns CRYS_RND_RESEED_COUNTER_OVERFLOW_ERROR, stating that the Reseed Counter has passed its upper-limit (2^32-2).</li></ul></ul>

@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_GenerateVector(
                            void *rndState_ptr,     /*!< [in/out] Pointer to the RND state structure, which is part of the RND context structure.
								     Use rndContext->rndState field of the context for this parameter. */
                            uint16_t   outSizeBytes,            /*!< [in]  The size in bytes of the random vector required. The maximal size is 2^16 -1 bytes. */
                            uint8_t   *out_ptr                  /*!< [out] The pointer to output buffer. */
);



/**********************************************************************************************************/
/*!
@brief Generates a random vector with specific limitations by testing candidates (described and used in FIPS 186-4: B.1.2, B.4.2 etc.).

This function draws a random vector, compare it to the range limits, and if within range - return it in rndVect_ptr.
If outside the range, the function continues retrying until a conforming vector is found, or the maximal retries limit is exceeded.
If maxVect_ptr is provided, rndSizeInBits specifies its size, and the output vector must conform to the range [1 < rndVect < maxVect].
If maxVect_ptr is NULL, rndSizeInBits specifies the exact required vector size, and the output vector must be the exact same
bit size (with its most significant bit = 1).
\note
The RND module must be instantiated prior to invocation of this API.

@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_GenerateVectorInRange(
                    void   *rndState_ptr,                 /*!< [in/out] Pointer to the RND state structure. */
                    SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc,   /*!< [in] Pointer to the random vector generation function. */
                    uint32_t  rndSizeInBits,                /*!< [in]  The size in bits of the random vector required. The allowed size in range  2 <= rndSizeInBits < 2^19-1, bits. */
                    uint8_t  *maxVect_ptr,                  /*!< [in]  Pointer to the vector defining the upper limit for the random vector output, Given as little-endian byte array.
                                                                       If not NULL, its actual size is treated as [(rndSizeInBits+7)/8] bytes and its value must be in range (3, 2^19) */
                    uint8_t  *rndVect_ptr                   /*!< [in/out] Pointer to the output buffer for the random vector. Must be at least [(rndSizeInBits+7)/8] bytes.
                                                                 Treated as little-endian byte array. */
);


/*************************************************************************************/
/*!
@brief Used for adding additional input/personalization data provided by the user,
to be later used by the ::CRYS_RND_Instantiation/::CRYS_RND_Reseeding/::CRYS_RND_GenerateVector functions.

@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_AddAdditionalInput(
                            void *rndState_ptr,         /*!< [in/out] Pointer to the RND context state buffer. */
                            uint8_t *additonalInput_ptr,            /*!< [in]  The Additional Input buffer. */
                            uint16_t additonalInputSize             /*!< [in]  The size of the Additional Input buffer. It must
                                                                               be <= CRYS_RND_ADDITINAL_INPUT_MAX_SIZE_WORDS and a multiple of 4. */
);

/*!
@brief The CRYS_RND_EnterKatMode function sets KAT mode bit into StateFlag of global CRYS_RND_WorkingState structure.

The user must call this function before calling functions performing KAT tests.

\note Total size of entropy and nonce must be not great than 126 words (maximal size of entropy and nonce).

@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C CRYSError_t CRYS_RND_EnterKatMode(
            void   *rndState_ptr,       /*!< [in/out] Pointer to the RND context state buffer. */
            uint8_t            *entrData_ptr,       /*!< [in] Entropy data. */
            uint32_t            entrSize,           /*!< [in] Entropy size in bytes. */
            uint8_t            *nonce_ptr,          /*!< [in] Nonce. */
            uint32_t            nonceSize,          /*!< [in] Entropy size in bytes. */
            CRYS_RND_WorkBuff_t  *workBuff_ptr      /*!< [out] RND working buffer, must be the same buffer, which should be passed into
							Instantiation/Reseeding functions. */
);

/**********************************************************************************************************/
/*!
@brief The CRYS_RND_DisableKatMode function disables KAT mode bit into StateFlag of global CRYS_RND_State_t structure.

The user must call this function after KAT tests before actual using RND module (Instantiation etc.).

@return CRYS_OK on success.
@return A non-zero value from crys_rnd_error.h on failure.
*/
CIMPORT_C void CRYS_RND_DisableKatMode(
                    void   *rndState_ptr     /*!< [in/out] Pointer to the RND state buffer. */
);


#ifdef __cplusplus
}
#endif
/**
@}
 */
#endif /* #ifndef CRYS_RND_H */

