#ifndef LLF_RSA_COMMON_H
#define LLF_RSA_COMMON_H

/*
* All the includes that are needed for code using this module to
* Compile correctly should be #included here.
*/
#include "CE2_public.h"
#include "tomcrypt.h"

#ifdef __cplusplus
extern "C"
{
#endif

/*
* Creation date : Tew Mar 13 12:42:39 2007
* Last modified : %modify_time%
*/
/** @file
* \brief This file contains declaration of low level
* common functions for RSA cryptography,
* which worked with LibTomCrypt.
* 
* \version LLF_RSA_Common.h#1:csrc:1
* \author Pavel Sasunkevich
* \remarks Copyright (C) 2007 by Discretix Technologies Ltd.
* All Rights reserved
*/

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

/* Converts bits to bytes. */
#define BITS2BYTES(cb) ((cb >> 3) + ((cb & 7) ? (1) : (0)))

/************************ Enums *******************************/
/************************ Typedefs ****************************/
/************************ Structs *****************************/
/************************ Public Variables ********************/

extern const struct ltc_hash_descriptor sha1_descDx;
extern const struct ltc_hash_descriptor md5_descDx;
extern const struct ltc_hash_descriptor sha512_descDx;
extern const struct ltc_hash_descriptor sha384_descDx;
extern const struct ltc_hash_descriptor sha256_descDx;
extern const struct ltc_hash_descriptor sha224_descDx;

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

/**
****************************************************************
* Function Name: 
*  LLF_RSA_UserPubKey_TO_rsakey
*
* Inputs:
*  @param UserPubKey_ptr [in] - A pointer to the user public key structure;
*  @param key [out] - A pointer to the public key structure.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_UserPubKey_TO_rsakey exports public key data from
*  UserPubKey_ptr to rsa_key.
*
* \b
* Algorithm:
*  -# Convert from unsigned bin variables of user public key to
*     mp_int variables into the public rsa_key.
***************************************************************/
CE2Error_t LLF_RSA_UserPubKey_TO_rsakey(
                        CE2_RSAUserPubKey_t * UserPubKey_ptr,	/* in */
                        rsa_key *key);							/* out */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_UserPrivKey_TO_rsakey
*
* Inputs:
*  @param UserPrivKey_ptr [in] - A pointer to the user private key structure;
*  @param key [out] - A pointer to the public key structure.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_UserPrivKey_TO_rsakey exports private key data from
*  UserPubKey_ptr to rsa_key.
*
* \b
* Algorithm:
*  -# Convert from unsigned bin variables of user private key to
*     mp_int variables into the private rsa_key.
***************************************************************/
CE2Error_t LLF_RSA_UserPrivKey_TO_rsakey(
                        CE2_RSAUserPrivKey_t * UserPrivKey_ptr,	/* in */
                        rsa_key *key);							/* out */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_rsakey_TO_UserPubKey
*
* Inputs:
*  @param key [in] - A pointer to the public key structure;
*  @param UserPubKey_ptr [out] - A pointer to the user public key structure.

* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_rsakey_TO_UserPubKey exports private key data from
*  UserPubKey_ptr to rsa_key.
*
* \b
* Algorithm:
*  -# Convert from mp_int variables into the public rsa_key to 
*     unsigned bin variables of user public key.
***************************************************************/
CE2Error_t LLF_RSA_rsakey_TO_UserPubKey(
                        rsa_key *key,							/* in */
                        CE2_RSAUserPubKey_t * UserPubKey_ptr);	/* out */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_rsakey_TO_UserPrivKey
*
* Inputs:
*  @param key [in] - A pointer to the private key structure;
*  @param UserPrivKey_ptr [out] - A pointer to the user private key structure;
*  @param mode [in] - defines if CRT parameters should be transfered.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_rsakey_TO_UserPrivKey exports private key data
*  with/without CRT parameters from rsa_key to UserPrivKey_ptr.
*
* \b
* Algorithm:
*  -# Convert from mp_int variables into the private rsa_key to 
*     unsigned bin variables of user private key with/without
*     CRT parameters.
***************************************************************/
CE2Error_t LLF_RSA_rsakey_TO_UserPrivKey(
                        rsa_key *key,							/* in */
                        CE2_RSAUserPrivKey_t * UserPrivKey_ptr, /* out */
                        DxUint16_t mode);						/* in */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_EXPTMOD
*
* Inputs:
*  @param in    [in] - A pointer to the input data (Big-Endian format);
*  @param inlen [in] - The size of the input data, in bytes;
*  @param out   [out] - A pointer to the output data (Big-Endian format);
*  @param outlen[out] - The size of the Output_buffer ptr [bytes].
*         This value is updated with the actual number 
*         of bytes that are loaded to out buffer;
*  @param key [in] - Private user key;
*  @param PKCS1_ver [in] - Ver 1.5 or 2.1, according to the functionality required;
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_EXPTMOD loads the bignum from “in”, raises it to either
*  “e” or “d” and stores the result in “out” and the size of the result
*  in “outlen”.
*  If private key mode is set to CE2_RSA_PRIVATE_KEY_NON_CRT_MODE
*  to use “d” as the exponent (i.e. for decrypting/signing), and 
*  If private key mode is set to CE2_RSA_PRIVATE_KEY_CRT_MODE
*  to use CRT parameters of private user key to calculate exponent.
*
* \b
* Algorithm:
*  -# If we are not using CRT mode: calculate out = in**d mod N;
*  -# If we are using CRT mode: calculate out using rsa_exptmod or 
*     ltc_mp.rsa_me depending on PKCS1_ver.
***************************************************************/
CE2Error_t LLF_RSA_EXPTMOD(
                        DxUint8_t * in,		/* in */
                        DxUint32_t inlen,	/* in */
                        DxUint8_t * out,	/* out */
                        DxUint32_t * outlen,/* in,out */
                        rsa_key * key,		/* in */
                        CE2_PKCS1_version PKCS1_ver); /* in */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_register_available_hash_modes
*
* Inputs:
*  None
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_register_available_hash_modes function register hash
*  modes that used in LLF_RSA_pkcs_v15_sa_get_sig_hash_mode to
*  determine hash idx
*
* \b
* Algorithm:
*  -# Register following modes: SHA1, SHA224, SHA256, SHA384,
*     SHA512, MD5;
***************************************************************/
CE2Error_t LLF_RSA_register_available_hash_modes(void);

/**
****************************************************************
* Function Name: 
*  LLF_RSA_pkcs_v15_sa_get_sig_hash_mode
*
* Inputs:
*  @param sig [in] - A pointer to the signature;
*  @param siglen [in] - Length of signature (usually == modulus_bytelen);
*  @param modulus_bytelen [in] - Size of modulus in bytes;
*  @param hash_idx [out] - Founded hash idx or -1 if unknown.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_pkcs_v15_sa_get_sig_hash_mode determines the hash
*  functions that was used when sign was created.
*
* \b
* Algorithm:
*  -# Register used hashes using LLF_RSA_register_available_hash_modes;
*  -# Validate sign structure;
*  -# Seek at the begining of the ASN.1 OID;
*  -# Compare OID in sign with the available OIDs and their len
*     to find equal OID.
***************************************************************/
CE2Error_t LLF_RSA_pkcs_v15_sa_get_sig_hash_mode(
                        DxUint8_t * sig,		/* in */
						DxUint32_t siglen,		/* in */
                        DxUint32_t modulus_bytelen,	/* in */
						DxInt_t *hash_idx);		/* out */

/**
*************************************************************
* Function Name: 
*  LLF_RSA_pkcs_1_v15_sa_decode
*
* Inputs:
*  @param msghash    [in] - The hash that was signed;
*  @param msghashlen [in] - The length of the hash;
*  @param sig        [in] - The signature [padded data];
*  @param siglen     [in] - The length of the signature;
*  @param hash_idx   [in] - The index of the hash used;
*  @param modulus_bitlen [in] - The bit length of the RSA modulus;
*  @param res        [out] - Result of comparison, 1==valid, 0==invalid.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK, CRYPT_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_pkcs_1_v15_sa_decode perform PKCS #1 v1.5 Signature Decoding.
*
* \b
* Algorithm:
*  -# Identical pkcs_1_v15_sa_decode but used typecast on IOD
*     validation;
*  -# Validate hash;
*  -# Validate sizes;
*  -# Validate OID;
*  -# Compare sign hashes.
***************************************************************/
CE2Error_t LLF_RSA_pkcs_1_v15_sa_decode(
                        const unsigned char *msghash,	/* in */
                        unsigned long        msghashlen,/* in */
                        const unsigned char *sig,		/* in */
                        unsigned long        siglen,	/* in */
                        int                  hash_idx,	/* in */
                        unsigned long        modulus_bitlen, /* in */
                        int                 *res);		/* out */

/**
*************************************************************
* Function Name: 
*  LLF_RSA_pkcs_1_oaep_encode
*
* Inputs:
* @param msg       [in]  - The data to encode;
* @param msglen    [in]  - The length of the data to encode (octets);
* @param lparam    [in]  - A session or system parameter (can be NULL);
* @param lparamlen [in]  - The length of the lparam data;
* @param modulus_bitlen [in] - The bit length of the RSA modulus;
* @param prng      [in]  - An active PRNG state;
* @param prng_idx  [in]  - The index of the PRNG desired;
* @param hash_idx  [in]  - The index of the hash desired;
* @param out       [out] - The destination for the encoded data;
* @param outlen    [in/out] - The max size and resulting size of the encoded data.
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK, CRYPT_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_pkcs_1_oaep_encode perform PKCS #1 v2.1 Encoding.
*
* \b
* Algorithm:
*  -# Identical pkcs_1_oaep_encode but null pointer is valid
*     entire data;
*  -# Validate hash;
*  -# Validate sizes;
*  -# Validate OID;
*  -# Compare sign hashes.
***************************************************************/
CE2Error_t LLF_RSA_pkcs_1_oaep_encode(
						const unsigned char	*msg,		/* in */
						unsigned long		msglen,		/* in */
						const unsigned char	*lparam,	/* in */
						unsigned long		lparamlen,	/* in */
						unsigned long		modulus_bitlen,	/* in */
						prng_state			*prng,		/* in */
						int					prng_idx,	/* in */
						int					hash_idx,	/* in */
						unsigned char		*out,		/* out */
						unsigned long		*outlen);	/* in/out */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_pss_get_sig_salt_len
*
* Inputs:
*  @param sig [in] - A pointer to the signature;
*  @param siglen [in] - Length of signature (usually == modulus_bytelen);
*  @param modulus_bytelen [in] - Size of modulus in bytes;
*  @param hash_idx [int] - hash idx;
*  @param saltlen [out] - Founded saltlen;
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_pss_get_sig_salt_len determines the salt len
*  parameter that was used when sign was created.
*
* \b
* Algorithm:
*  -# Register used hashes using LLF_RSA_register_available_hash_modes;
*  -# Validate sign structure;
*  -# Seek at the begining of the ASN.1 OID;
*  -# Calculate salt len of the sign.
***************************************************************/
CE2Error_t LLF_RSA_pss_get_sig_salt_len(
                        DxUint8_t * sig,		/* in */
						DxUint32_t siglen,		/* in */
                        DxUint32_t modulus_bytelen,	/* in */
						DxInt_t hash_idx,		/* in */
						DxUint16_t* saltlen);	/* out */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_Encrypt
*
* Inputs:
*  @param in    [in] - A pointer to the input data (Big-Endian format);
*  @param inlen [in] - The size of the input data, in bytes;
*  @param out   [out] - A pointer to the output data (Big-Endian format);
*  @param outlen[out] - The size of the Output_buffer ptr [bytes].
*         This value is updated with the actual number 
*         of bytes that are loaded to out buffer;
*  @param UserPublKey [in] - User public RSA key;
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_Encrypt - Make RSA encryption (modular exponentiation).
*
* \b
* Algorithm:
*  -# Initialize LibTomCrypt variables.
*  -# Verify if in < modulus.
*  -# Encrypt input message with using exptmod() function;
*  -# Convert encrypted message in output big-endian format;
***************************************************************/
CE2Error_t LLF_RSA_Encrypt( DxUint8_t * in,		/* in */
                           DxUint32_t inlen,	/* in */
                           DxUint8_t * out,	/* out */
                           DxUint32_t * outlen,/* in,out */
                           CE2_RSAUserPubKey_t *UserPublKey); /* in */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_Decrypt
*
* Inputs:
*  @param in    [in] - A pointer to the input data (Big-Endian format);
*  @param inlen [in] - The size of the input data, in bytes;
*  @param out   [out] - A pointer to the output data (Big-Endian format);
*  @param outlen[out] - The size of the Output_buffer ptr [bytes].
*         This value is updated with the actual number 
*         of bytes that are loaded to out buffer;
*  @param UserPrivKey [in] - User private RSA key;
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_Decrypt - Make RSA decryption (modular exponentiation).
*
* \b
* Algorithm:
*  -# Initialize LibTomCrypt variables.
*  -# Decrypt input message 
*    a) with using exptmod() function (in NON_CRT_MODE);
*    b) with using rsa_me() function (in CRT_MODE);
*  -# Convert decrypted message in output big-endian format;
***************************************************************/
CE2Error_t LLF_RSA_Decrypt(DxUint8_t * in,		/* in */
                           DxUint32_t inlen,	/* in */
                           DxUint8_t * out,	/* out */
                           DxUint32_t * outlen,/* in,out */
                           CE2_RSAUserPrivKey_t *UserPrivKey); /* in */

/**
****************************************************************
* Function Name: 
*  LLF_RSA_PKCS1_V15_Encode
*
* Inputs:
*  @param DataIn_ptr [in] - A pointer to input data.
*  @param DataInSize [in] - Size of input data.
*                           Note: DataInSize <=  ModulusSize - 11; 
*  @param ModulusSizeInBits [in] - Size of modulus (in bits). 
*  @param DataOut_ptr [out] - A pointer to output data.    
*  @param DataOutSize_ptr [in/out] - A pointer to actual size of output data.
*                                    Note: *DataOutSize_ptr >= ModulusSize; 
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_PKCS1_V15_Encode - Make pkcs1 v15 encoding.
*
* \b
* Algorithm:
*  -# 
***************************************************************/
CE2Error_t LLF_RSA_PKCS1_V15_Encode(DxUint8_t *DataIn_ptr,    
																		DxUint32_t DataInSize,
																		DxUint32_t ModulusSizeInBits, 
																		DxUint8_t *DataOut_ptr,    
																		DxUint32_t *DataOutSize_ptr);

/**
****************************************************************
* Function Name: 
*  LLF_RSA_PKCS1_V15_Decode
*
* Inputs:
*  @param DataIn_ptr [in] - A pointer to input data.
*  @param DataInSize [in] - Size of input data.
*                           Note: DataInSize == ModulusSize; 
*  @param ModulusSizeInBits [in] - Size of modulus (in bits). 
*  @param DataOut_ptr [out] - A pointer to output data.    
*  @param DataOutSize_ptr [in/out] - A pointer to actual size of output data.
*                                    Note: *DataOutSize_ptr >= ModulusSize - 11; 
*
* Outputs: @returns \b
*  CE2Error_t  
*  - CE2_OK - On success
*  - Otherwise - error code.
*
* \brief \b
* Description:
*  LLF_RSA_PKCS1_V15_Decode - Make pkcs1 v15 decoding.
*
* \b
* Algorithm:
*  -# 
***************************************************************/
CE2Error_t LLF_RSA_PKCS1_V15_Decode(DxUint8_t *DataIn_ptr,    
																		DxUint32_t DataInSize,
																		DxUint32_t ModulusSizeInBits, 
																		DxUint8_t *DataOut_ptr,    
																		DxUint32_t *DataOutSize_ptr);

#ifdef __cplusplus
}
#endif

#endif /* LLF_RSA_COMMON_H */
