
  /*
   *  Object %name    : %
   *  State           :  %state%
   *  Creation date   :  Wed Nov 17 17:25:55 2004
   *  Last modified   :  %modify_time%
   */
  /** @file
   *  \brief A brief description of this module
   *
   *  \version DX_CRYPTO_AES.c#1:csrc:6
   *  \author adams
   *  \remarks Copyright (C) 2004 by Discretix Technologies Ltd.
   *           All Rights reserved
   */



/************* Include Files ****************/

/* .............. CRYS level includes ................. */
#include <crypto/algapi.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/crypto.h>

#include "BaseTypes.h"
#include "error.h"
#include "CRYS_HASH_error.h"
#include "CRYS_HASH.h"

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

#define SHA1_BLOCK_SIZE     64
#define SHA224_BLOCK_SIZE   64
#define SHA256_BLOCK_SIZE   64

#define MD5_DIGEST_SIZE     16
#define SHA1_DIGEST_SIZE    20
#define SHA224_DIGEST_SIZE  28
#define SHA256_DIGEST_SIZE  32

#define CRYPT_S390_PRIORITY 300
#define CRYPT_S390_COMPOSITE_PRIORITY 400
/************************ Global Data ******************************/

/************* Private function prototype ****************/


/************************ Public Functions ******************************/
int dx_hash_init(void);
void dx_hash_finish(void);

static void dx_sha1_init(struct crypto_tfm *tfm);
static void dx_sha1_update(struct crypto_tfm *tfm, const uint8_t*data, uint len);
static void dx_sha1_final(struct crypto_tfm *tfm, uint8_t *out);
    
static void dx_md5_init(struct crypto_tfm *tfm);
static void dx_md5_update(struct crypto_tfm *tfm, const uint8_t*data, uint len);
static void dx_md5_final(struct crypto_tfm *tfm, uint8_t *out);
    
static void dx_sha224_init(struct crypto_tfm *tfm);
static void dx_sha224_update(struct crypto_tfm *tfm, const uint8_t*data, uint len);
static void dx_sha224_final(struct crypto_tfm *tfm, uint8_t *out);
    
static void dx_sha256_init(struct crypto_tfm *tfm);
static void dx_sha256_update(struct crypto_tfm *tfm, const uint8_t*data, uint len);
static void dx_sha256_final(struct crypto_tfm *tfm, uint8_t *out);

/************************ Structures ******************************/


/* initializing the sha1 structure */
/* ------------------------------ */
static struct crypto_alg alg_sha1 = {
	.cra_name        = "sha1",
	.cra_driver_name = "sha1-s390",
	.cra_priority    = CRYPT_S390_PRIORITY,
	.cra_flags       = CRYPTO_ALG_TYPE_DIGEST,
	.cra_blocksize   = SHA1_BLOCK_SIZE,
	.cra_ctxsize     = sizeof(struct CRYS_HASHUserContext_t),
	.cra_module      = THIS_MODULE,
	.cra_list        = LIST_HEAD_INIT(alg_sha1.cra_list),
	.cra_u           = { 
		.digest = {
			.dia_digestsize = SHA1_DIGEST_SIZE,
                 	.dia_init       = dx_sha1_init,
                 	.dia_update     = dx_sha1_update,
                 	.dia_final      = dx_sha1_final
		} 
	}
};

 
/* initializing the md5 structure */
/* ------------------------------ */
static struct crypto_alg alg_md5 = {
	.cra_name        = "md5",
	.cra_driver_name = "md5-s390",
	.cra_priority    = CRYPT_S390_PRIORITY,
	.cra_flags       = CRYPTO_ALG_TYPE_DIGEST,
	.cra_blocksize   = SHA1_BLOCK_SIZE,
	.cra_ctxsize     = sizeof(struct CRYS_HASHUserContext_t),
	.cra_module      = THIS_MODULE,
	.cra_list        = LIST_HEAD_INIT(alg_md5.cra_list),
	.cra_u           = { 
		.digest  = {
			.dia_digestsize = SHA1_DIGEST_SIZE,
                 	.dia_init       = dx_md5_init,
                 	.dia_update     = dx_md5_update,
                 	.dia_final      = dx_md5_final 
		} 
	}
};
 
    
/* initializing the sha224 structure */
/* ------------------------------ */

static struct crypto_alg alg_sha224 = {
	.cra_name        = "sha224",
	.cra_driver_name = "sha224-s390",
	.cra_priority    = CRYPT_S390_PRIORITY,
	.cra_flags       = CRYPTO_ALG_TYPE_DIGEST,
	.cra_blocksize   = SHA224_BLOCK_SIZE,
	.cra_ctxsize     = sizeof(struct CRYS_HASHUserContext_t),
	.cra_module      = THIS_MODULE,
	.cra_list        = LIST_HEAD_INIT(alg_sha224.cra_list),
	.cra_u           = {
		.digest  = {
			.dia_digestsize = SHA224_DIGEST_SIZE,
             		.dia_init       = dx_sha224_init,
             		.dia_update     = dx_sha224_update,
             		.dia_final      = dx_sha224_final 
		} 
	}
};

/* initializing the sha256 structure */
/* ------------------------------ */
static struct crypto_alg alg_sha256 = {
	.cra_name        = "sha256",
	.cra_driver_name = "sha256-s390",
	.cra_priority    = CRYPT_S390_PRIORITY,
	.cra_flags       = CRYPTO_ALG_TYPE_DIGEST,
	.cra_blocksize   = SHA256_BLOCK_SIZE,
	.cra_ctxsize     = sizeof(struct CRYS_HASHUserContext_t),
	.cra_module      = THIS_MODULE,
	.cra_list        = LIST_HEAD_INIT(alg_sha256.cra_list),
	.cra_u           = {
		.digest  = {
			.dia_digestsize = SHA256_DIGEST_SIZE,
			.dia_init       = dx_sha256_init,
			.dia_update     = dx_sha256_update,
             		.dia_final      = dx_sha256_final 
		} 
	}
};

 
   
/****************************************************************************************************/
/**
 * @brief This function is used to registreate the AES algorithm.
 *			 It initilize the crypto_alg structure for ecb and cbc,
 *			 and call the registration function
 *   
 *
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

int dx_hash_init(void)
{

/* The return error identifier */
uint32_t error;

/* initializing the error to O.K */
error = DX_OK; 

	/* call the registration function with the sha1 struct */
	error = crypto_register_alg(&alg_sha1);
	if (error!=DX_OK)
		goto alg_sha1_err;
    
	/* call the registration function with the sha1 struct */
	error = crypto_register_alg(&alg_md5);
	if (error!=DX_OK)
		goto alg_md5_err;

	/* call the registration function with the sha1 struct */
	error = crypto_register_alg(&alg_sha224);
	if (error!=DX_OK)
		goto alg_sha224_err;
         
	/* call the registration function with the sha1 struct */
	error = crypto_register_alg(&alg_sha256);
	if (error!=DX_OK)
		goto alg_sha256_err;

alg_sha256_err:         
	crypto_unregister_alg(&alg_sha224);
	crypto_unregister_alg(&alg_md5);
	crypto_unregister_alg(&alg_sha1);
alg_sha224_err:         
	crypto_unregister_alg(&alg_md5);
	crypto_unregister_alg(&alg_sha1);
alg_md5_err:
	crypto_unregister_alg(&alg_sha1);
alg_sha1_err:
	return error;
}

/****************************************************************************************************/
/**
 * @brief This function is used to unregistreate the AES algorithm.
 *   
 *
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
void dx_hash_finish(void)
{
	crypto_unregister_alg(&alg_sha1);
	crypto_unregister_alg(&alg_md5);
	crypto_unregister_alg(&alg_sha224);
	crypto_unregister_alg(&alg_sha256);
}

/****************************************************************************************************/
/**
 * @brief This function initializes the HASH machine.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static void dx_sha1_init(struct crypto_tfm *tfm)
{
struct dx_sha1_ctx *ctx = crypto_tfm_ctx(tfm);
 
	CRYS_HASH_Init((CRYS_HASHUserContext_t*)ctx, CRYS_HASH_SHA1_mode);
 }

/****************************************************************************************************/
/**
 * @brief This function process a block of data via the HASH Hardware.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

static void dx_sha1_update(struct crypto_tfm *tfm, const uint8_t *data, unsigned int len)
{
struct dx_sha1_ctx *ctx = crypto_tfm_ctx(tfm);

	CRYS_HASH_Update((CRYS_HASHUserContext_t*)ctx ,(uint8_t *)data,len );
}
/****************************************************************************************************/
/**
 * @brief This function finalize the hashing process of data block.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

static void dx_sha1_final(struct crypto_tfm *tfm, uint8_t *out)
{
struct dx_sha1_ctx *ctx = crypto_tfm_ctx(tfm);

	CRYS_HASH_Finish((CRYS_HASHUserContext_t*)ctx, (uint32_t*)out);
}

/******************************************************************************************************
********************************************** MD5 ****************************************************
*******************************************************************************************************/
/****************************************************************************************************/
/**
 * @brief This function initializes the HASH machine.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static void dx_md5_init(struct crypto_tfm *tfm)
{
struct dx_md5_ctx *ctx = crypto_tfm_ctx(tfm);
 
	CRYS_HASH_Init((CRYS_HASHUserContext_t*)ctx ,CRYS_HASH_MD5_mode);
}

/****************************************************************************************************/
/**
 * @brief This function process a block of data via the HASH Hardware.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

static void dx_md5_update(struct crypto_tfm *tfm, const uint8_t* data, unsigned int len)
{
struct dx_md5_ctx *ctx = crypto_tfm_ctx(tfm);

	CRYS_HASH_Update((CRYS_HASHUserContext_t*)ctx ,(uint8_t*) data,len );
}
/****************************************************************************************************/
/**
 * @brief This function finalize the hashing process of data block.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

static void dx_md5_final(struct crypto_tfm *tfm, uint8_t *out)
{
struct dx_md5_ctx *ctx = crypto_tfm_ctx(tfm);

	CRYS_HASH_Finish((CRYS_HASHUserContext_t*)ctx, (uint32_t*)out);
}

/******************************************************************************************************
********************************************** SHA224 ****************************************************
*******************************************************************************************************/
/****************************************************************************************************/
/**
 * @brief This function initializes the HASH machine.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static void dx_sha224_init(struct crypto_tfm *tfm)
{
struct dx_sha224_ctx *ctx = crypto_tfm_ctx(tfm);
 
	CRYS_HASH_Init((CRYS_HASHUserContext_t*)ctx ,CRYS_HASH_SHA224_mode);
}

/****************************************************************************************************/
/**
 * @brief This function process a block of data via the HASH Hardware.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

static void dx_sha224_update(struct crypto_tfm *tfm, const uint8_t* data, unsigned int len)
{
struct dx_sha224_ctx *ctx = crypto_tfm_ctx(tfm);

	CRYS_HASH_Update((CRYS_HASHUserContext_t*)ctx ,(uint8_t*) data,len );
}
/****************************************************************************************************/
/**
 * @brief This function finalize the hashing process of data block.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

static void dx_sha224_final(struct crypto_tfm *tfm, uint8_t *out)
{
struct dx_sha224_ctx *ctx = crypto_tfm_ctx(tfm);

	CRYS_HASH_Finish((CRYS_HASHUserContext_t*)ctx, (uint32_t*)out);
}

/******************************************************************************************************
********************************************** SHA256 ****************************************************
*******************************************************************************************************/
/****************************************************************************************************/
/**
 * @brief This function initializes the HASH machine.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static void dx_sha256_init(struct crypto_tfm *tfm)
{
struct dx_sha256_ctx *ctx = crypto_tfm_ctx(tfm);
 
	CRYS_HASH_Init((CRYS_HASHUserContext_t*)ctx ,CRYS_HASH_SHA256_mode);
}

/****************************************************************************************************/
/**
 * @brief This function process a block of data via the HASH Hardware.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

static void dx_sha256_update(struct crypto_tfm *tfm, const uint8_t* data, unsigned int len)
{
struct dx_sha256_ctx *ctx = crypto_tfm_ctx(tfm);

	CRYS_HASH_Update((CRYS_HASHUserContext_t*)ctx ,(uint8_t*) data,len );

}
/****************************************************************************************************/
/**
 * @brief This function finalize the hashing process of data block.
 *   
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */

static void dx_sha256_final(struct crypto_tfm *tfm, uint8_t *out)
{
struct dx_sha256_ctx *ctx = crypto_tfm_ctx(tfm);

	CRYS_HASH_Finish((CRYS_HASHUserContext_t*)ctx, (uint32_t*)out);
}


/******************************* Dummy function ***************************/
 uint32_t CRYS_HASH_Init(CRYS_HASHUserContext_t*    ContextID_ptr,
                                     CRYS_HASH_OperationMode_t  OperationMode)
{
    printk(KERN_ALERT "\n HELLO: CRYS_HASH_Init - DUMMY FUNCTION\n"); 
    return DX_OK;
}

uint32_t CRYS_HASH_Update(CRYS_HASHUserContext_t*    ContextID_ptr,
                                       uint8_t*                 DataIn_ptr,
                                       uint32_t                 DataInSize )
{ 
    printk(KERN_ALERT "\n HELLO: CRYS_HASH_Update - DUMMY FUNCTION\n"); 
    return DX_OK;
}

uint32_t CRYS_HASH_Finish( CRYS_HASHUserContext_t*   ContextID_ptr ,
                              CRYS_HASH_Result_t        HashResultBuff )
{
    printk(KERN_ALERT "\n HELLO: CRYS_HASH_Finish - DUMMY FUNCTION\n"); 
    return DX_OK;
}
