#ifndef LLF_DH_H
#define LLF_DH_H

/*
* All the includes that are needed for code using this module to
* compile correctly should be #included here.
*/

#include "CE2_public.h"
#include "CE2_DH.h"
#include "CE2_HASH.h"

#ifdef __cplusplus
extern "C"
{
#endif

/*
*  Object name     :  LLF_DH.h
*  State           :  %state%
*  Creation date   :  20.03.2007
*  Last modified   :  %modify_time%
*/
/** @file
* \brief contains declarations of low level functions for 
*              DH (Diffie-Hellman key exchange).
*
*  \version LLF_AES.h#1:cinc:1
* \author Yermalayeu Ihar
* \remarks Copyright (C) 2007 by Discretix Technologies Ltd. All rights reserved.
*/

/************************ Defines *****************************/
/************************ Enums *******************************/
/************************ Typedefs ****************************/
/************************ Structs *****************************/
/************************ Public Variables ********************/
/************************ Public Functions ********************/

/**
****************************************************************
* Function Name: 
*  LLF_DH_GeneratePubPrv
*
*  @param Generator_ptr [in] - Pointer to the Generator octet string
*  @param GeneratorSize [in] - Size of the Generator String (in bytes)
*  @param Prime_ptr [in] - Pointer to the Prime octet string
*  @param PrimeSize [in] - Size of the Prime string (in bytes)
*  @param L [in] - Relevant only for PKCS#3, the private value length in bits
*                 If L != 0 then - force the private key to be 2^(L-1) <= Prv < 2^l
*                 if L 0 then: 0< Prv < P-1
*                 In ANSI X9.42 L is irrelevant  
*  @param Q_ptr [in] - Relevant only for ANSI X9.42 - Pointer to the Q octet string
*                     1 <= Prv <= q-1   or   1 < Prv < q-1
*  @param QSize	[in] - Relevant only for ANSI X9.42 - Size of the Q string (in bytes)  				 				  
*  @param DH_mode [in] - enum declaring weather this is PKCS#3 or ANSI X9.42
*  @param ClientPrvKey_ptr [out] - Pointer to the Private key octet string - 
*                                 In PKCS#3 This buffer should be at least the 
*                                 following size:
*                                 2^L - 1 - if L is provided
*                                 P-1	- if L is DX_NULL
*  @param ClientPrvKeySize_ptr [in/out] - The user should provide the size of the 
*                                        buffer indicated by ClientPrvKey_ptr
*                                        The function returns the actual size 
*                                        in bytes of the Private key Size
*  @param ClientPub_ptr [out] - Pointer to the Public key octet string
*                              This Buffer should be at least PrimeSize bytes
*  @param ClientPubSize_ptr [in/out] - The user should provide the size of the buffer 
*                                     indicated by ClientPub_ptr
*                                     The function returns the actual size in bytes 
*                                     of the client public buffer
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code defined in CE2_DH_error.h:
*
* \brief \b 
* Description:
*  LLF_DH_GeneratePubPrv has 2 functionalities:
*  -# randomly generates the Client private key 
*  -# compute the Client public key which is 
*     ClientPub = Generator ^ Prv mod Prime 
*
*  \b 
* Algorithm:
*  -# Call corresponding subfunction for this mode;
***************************************************************/
CE2Error_t LLF_DH_GeneratePubPrv(
  DxUint8_t *Generator_ptr,
  DxUint16_t GeneratorSize,
  DxUint8_t *Prime_ptr,
  DxUint16_t PrimeSize,
  DxUint16_t L,
  DxUint8_t *Q_ptr,
  DxUint16_t QSize,
  CE2_DH_OpMode_t DH_mode,
  DxUint8_t *ClientPrvKey_ptr,
  DxUint16_t *ClientPrvKeySize_ptr,
  DxUint8_t *ClientPub_ptr,
  DxUint16_t *ClientPubSize_ptr);

/**
****************************************************************
* Function Name: 
*  LLF_DH_KeyDerivationFunc
*
*  @param ZZSecret_ptr [in] - A pointer to shared secret key octet string 
*  @param ZZSecretSize [in] - The shared secret key Size, in bytes
*  @param hashFunc [in] - The hash function to be used. The hash function 
*                        output must be at least 160 bits.
*  @param KeyLenInBits [in] - The size in Bits of the keying data to be generated - 
*                             KeyLenInBits < hashlen*(2^32-1) - in our implementation 
*                             the size should not be larger than the maximum input 
*                             size to the Hash function
*  @param derivation_mode [in] - Specifies whether we use an ASN.1-based derivation 
*                               function or a derivation based on concatenation.
*  @param KeyingData_ptr [out] - A pointer to the keying data derived from the secret 
*                               key, of length KeyLenInBits
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code defined in CE2_DH_error.h:
*
* \brief \b 
* Description:
*  LLF_DH_KeyDerivationFunc specifies the key derivation function, 
*  either based on ASN.1 DER encoding or based on the concatanation of fields as 
*  specified in ANSI X9.42-2001. The purpose of this function is to derive a key 
*  data from the shared secret value.
*
*  \b 
* Algorithm:
*  -# Init variables
*  -# Derivate key data
***************************************************************/
CE2Error_t LLF_DH_KeyDerivationFunc(
  DxUint8_t *ZZSecret_ptr,
  DxUint16_t ZZSecretSize,
  CE2_DH_HASH_OpMode_t hashFunc,				                    
  DxUint32_t KeyLenInBits,				                    
  DxUint8_t *KeyingData_ptr,
  CE2_DH_DerivationFunc_Mode derivation_mode);

/**
****************************************************************
* Function Name: 
*  LLF_DH_X942_GetSecretData
*
*  @param hashFunc [in] - The hash function to be used
*  @param ClientPrvKey_ptr [in] - A pointer to the Private key octet string 
*  @param ClientPrvKeySize [in] - The Private key size, in bytes
*  @param ServerPubKey_ptr [in] - A pointer to the Server public key octet string - 
*  @param ServerPubKeySize [in] - The Server Public key size, in bytes
*  @param Prime_ptr [in] - A pointer to the Prime octet string
*  @param PrimeSize [in] - The size of the Prime string
*  @param DerFunc_mode [in] - The type of function to derive the secret key to 
*                            the key data. We use ASN.1-based function or Hash 
*                            concatenation function mode.
*  @param SecretKeyData_ptr [out] - A pointer to the secret key octet string. 
*                                  This buffer should be at least PrimeSize bytes.
*  @param SecretKeyDataSizeBitsNeeded [in] - Specifies the derived Secret Key data 
*                                           size needed in Bits. This value converted 
*                                           to bytes cannot be larger than PrimeSize
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code defined in CE2_DH_error.h:
*
* \brief \b 
* Description:
*  LLF_DH_X942_GetSecretData computes the shared secret key as follows:
*   -# OPTIONAL - validate the correctness of the argument keys
*   -# SecretKey = ServerPubKey ^ ClientPrvKey mod Prime
*   -# Use of Derivation function to derive a data key from the secret key 
*
*  \b 
* Algorithm:
*  -# Initialize LibTomCrypt primitives
*  -# Calculate SecretKey
*  -# Derivate secret key data from shared secret
***************************************************************/

CE2Error_t LLF_DH_X942_GetSecretData(
  CE2_DH_HASH_OpMode_t hashFunc,		
  DxUint8_t *ClientPrvKey_ptr,
  DxUint16_t ClientPrvKeySize,
  DxUint8_t *ServerPubKey_ptr,
  DxUint16_t ServerPubKeySize,				                    
  DxUint8_t *Prime_ptr,
  DxUint16_t PrimeSize,
  CE2_DH_DerivationFunc_Mode DerFunc_mode,
  DxUint8_t *SecretKeyData_ptr,
  DxUint16_t SecretKeyDataSizeBitsNeeded);

/**
****************************************************************
* Function Name: 
*  LLF_DH_X942_Hybrid_GetSecretData
*
*  @param hashFunc [in] - The hash function to be used
*  @param ClientPrvKey_ptr1 [in] - A pointer to the First Private key octet string 
*                                 number 
*  @param ClientPrvKeySize1 [in] - The First Private key Size, in bytes
*  @param ClientPrvKey_ptr2 [in] - A pointer to the Second Private key octet string
*  @param ClientPrvKeySize2 [in] - The Second Private key Size, in bytes
*  @param ServerPubKey_ptr1 [in] - A pointer to the First Server public key octet string
*  @param ServerPubKeySize1 [in] - The First Server Public key Size, in bytes
*  @param ServerPubKey_ptr2 [in] - A pointer to the Second Server public key octet string
*  @param ServerPubKeySize2 [in] - The Second Server Public key Size, in bytes
*  @param Prime_ptr [in] - A pointer to the Prime octet string
*  @param PrimeSize [in] - The size of the Prime string
*  @param DerFunc_mode [in] - The type of function to derive the secret key to the key 
*                            data. We use an ASN.1-based function or a Hash 
*                            concatenation function mode.
*  @param SecretKeyData_ptr [out] - A pointer to the secret key octet string.
*                                  This buffer should be at least 2*PrimeSize bytes.
*  @param SecretKeyDataSizeBitsNeeded [in] - Specifies the derived Secret Key data size 
*                                           needed in Bits. This value converted to bytes 
*                                           cannot be larger than PrimeSize
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code defined in CE2_DH_error.h:
*
* \brief \b 
* Description:
*  LLF_DH_X942_Hybrid_GetSecretData computes the shared secret key as follows:
*   -# OPTIONAL - validate the correctness of the argument keys
*   -# SecretKey1 = ServerPubKey1 ^ ClientPrvKey1 mod Prime
*   -# SecretKey2 = ServerPubKey2 ^ ClientPrvKey2 mod Prime
*   -# Use of Derivation function to derive a data key from the 2 secret keys 
*
*  \b 
* Algorithm:
*  -# Initialize LibTomCrypt primitives
*  -# SecretKey1 = ServerPubKey1 ^ ClientPrvKey1 mod Prime
*  -# SecretKey2 = ServerPubKey2 ^ ClientPrvKey2 mod Prime
*  -# SecretKey = SecretKey1 || SecretKey2
*  -# Use of Derivation function to derive a data key from SecretKey
***************************************************************/
CE2Error_t LLF_DH_X942_Hybrid_GetSecretData(
  CE2_DH_HASH_OpMode_t hashFunc,		
  DxUint8_t *ClientPrvKey_ptr1,
  DxUint16_t ClientPrvKeySize1,
  DxUint8_t *ClientPrvKey_ptr2,
  DxUint16_t ClientPrvKeySize2,				                    
  DxUint8_t *ServerPubKey_ptr1,
  DxUint16_t ServerPubKeySize1,
  DxUint8_t *ServerPubKey_ptr2,
  DxUint16_t ServerPubKeySize2,				                    				                    
  DxUint8_t *Prime_ptr,
  DxUint16_t PrimeSize,
  CE2_DH_DerivationFunc_Mode DerFunc_mode,
  DxUint8_t *SecretKeyData_ptr,
  DxUint16_t SecretKeyDataSizeBitsNeeded);

/**
****************************************************************
* Function Name: 
*  LLF_DH_PKCS3_GetSecretKey
*
*  @param ClientPrvKey_ptr [in] - Pointer to the Private key octet string.
*  @param ClientPrvKeySize [in] - The Private key Size (in bytes)
*  @param ServerPubKey_ptr [in] - Pointer to the Server public key octet string.
*  @param ServerPubKeySize [in] - The Server Public key Size (in bytes)
*  @param Prime_ptr [in] - Pointer to the Prime octet string
*  @param PrimeSize [in] - Size of the Prime string
*  @param SecretKey_ptr [out] - Pointer to the secret key octet string.
*                              This buffer should be at least PrimeSize Bytes
*  @param SecretKeySize_ptr [out] - Size of secret key octet string
*
* @returns \b
*  CE2Error_t 
*  - CE2_OK - on success
*  - Otherwise - error code defined in CE2_DH_error.h:
*
* \brief \b 
* Description:
*  LLF_DH_PKCS3_GetSecretKey computes the shared secret key in the 
*  following computation: SecretKey = ServerPubKey ^ ClientPrvKey mod Prime
*
*  \b 
* Algorithm:
*  -# Initialize LibTomCrypt primitives
*  -# Calculate SecretKey
*  -# Convert SecretKey to output big-endian SecretKey_ptr
***************************************************************/
CE2Error_t LLF_DH_PKCS3_GetSecretKey(
  DxUint8_t *ClientPrvKey_ptr,
  DxUint16_t ClientPrvKeySize,
  DxUint8_t *ServerPubKey_ptr,
  DxUint16_t ServerPubKeySize,				                    
  DxUint8_t *Prime_ptr,
  DxUint16_t PrimeSize,
  DxUint8_t *SecretKey_ptr,
  DxUint16_t *SecretKeySize_ptr);

#ifdef __cplusplus
}
#endif

#endif
