
  /*
   *  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/module.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
#include <linux/init.h>

#include "BaseTypes.h"
#include "error.h"
#include "CRYS_AES_error.h"
#include "CRYS_AES.h"

/************************ Defines for AES ******************************/
#define AES_MIN_KEY_SIZE   16
#define AES_MAX_KEY_SIZE   32
#define AES_BLOCK_SIZE     16
#define AES_KEYLEN_16_BYTES 16
#define AES_KEYLEN_24_BYTES 24
#define AES_KEYLEN_32_BYTES 32


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

/************************ Public Functions ******************************/
int dx_aes_init(void);
void dx_aes_finish(void);
static int dx_ecb_aes_setkey(struct crypto_tfm *tfm, const uint8_t *in_key, uint_t key_len);
static int dx_ecb_aes_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                                            struct scatterlist *src, uint_t nbytes);
static int dx_ecb_aes_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                                        struct scatterlist *src, uint_t nbytes);
static int dx_cbc_aes_setkey(struct crypto_tfm *tfm, const uint8_t  *in_key, uint_t key_len);
static int dx_cbc_aes_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                                        struct scatterlist *src, uint_t nbytes);
static int dx_cbc_aes_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                                        struct scatterlist *src, uint_t nbytes);


/************************ Global Structures ******************************/
/* Global structure for discretix aes context */
struct dx_aes_ctx {
	uint8_t iv[AES_BLOCK_SIZE];
	uint8_t key[AES_MAX_KEY_SIZE];
	uint32_t enc;
	uint32_t dec;
	uint16_t key_len;
};

/* initializing the ecb structure */
/* ------------------------------ */
static struct crypto_alg ecb_aes_alg = {
	.cra_name               =       "ecb(aes)",
	.cra_driver_name        =       "ecb-aes-s390",
	.cra_priority           =       CRYPT_S390_COMPOSITE_PRIORITY,
	.cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER |CRYPTO_ALG_NEED_FALLBACK,
	.cra_blocksize          =       AES_BLOCK_SIZE,
	.cra_ctxsize            =       sizeof(struct dx_aes_ctx),
	.cra_type               =       &crypto_blkcipher_type,
	.cra_module             =       THIS_MODULE,
	.cra_list               =       LIST_HEAD_INIT(ecb_aes_alg.cra_list),
	.cra_u                  = {
	.blkcipher = {
		.min_keysize = AES_MIN_KEY_SIZE,
		.max_keysize = AES_MAX_KEY_SIZE,
		.setkey      = dx_ecb_aes_setkey,
		.encrypt     = dx_ecb_aes_encrypt,
		.decrypt     = dx_ecb_aes_decrypt,
		}
	}
 };
 
    /* initializing the cbc structure */
    /* ------------------------------ */
	static struct crypto_alg cbc_aes_alg = {
	.cra_name               =       "cbc(aes)",
	.cra_driver_name        =       "cbc-aes-s390",
	.cra_priority           =       CRYPT_S390_COMPOSITE_PRIORITY,
	.cra_flags              =       CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK,
	.cra_blocksize          =       AES_BLOCK_SIZE,
	.cra_ctxsize            =       sizeof(struct dx_aes_ctx),
	.cra_type               =       &crypto_blkcipher_type,
	.cra_module             =       THIS_MODULE,
	.cra_list               =       LIST_HEAD_INIT(cbc_aes_alg.cra_list),
	.cra_u                  =       {
	.blkcipher = {
		.min_keysize = AES_MIN_KEY_SIZE,
		.max_keysize = AES_MAX_KEY_SIZE,
		.ivsize      = AES_BLOCK_SIZE,
		.setkey      = dx_cbc_aes_setkey,
		.encrypt     = dx_cbc_aes_encrypt,
		.decrypt     = dx_cbc_aes_decrypt,
		}
	}
 };

/****************************************************************************************************/
/**
 * @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_aes_init(void)
{

/* The return error identifier */
uint32_t error;

/* initializing the error to O.K */
error=DX_OK; 
 
	/* call the registration function with the ecb struct */
	error = crypto_register_alg(&ecb_aes_alg);
	if (error!=DX_OK)
		goto ecb_aes_err;
 
	/* call the registration function with the cbc struct */
	error = crypto_register_alg(&cbc_aes_alg);
	if (error!=DX_OK)
		goto cbc_aes_err;

	return DX_OK;

cbc_aes_err:
	crypto_unregister_alg(&ecb_aes_alg);
ecb_aes_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_aes_finish(void)
 {
	crypto_unregister_alg(&cbc_aes_alg);
	crypto_unregister_alg(&ecb_aes_alg);
 }
/****************************************************************************************************/
/**
 * @brief This function is used to unregistreate the AES algorithm.
 * 
 * @param[in] tfm - pointer to the high level structure crypto_tfm.
 * @param[in] in_key - A pointer to the user's key buffer.
 * @param[in] key_len - The size of the KEY used by the AES: 128, 192 or 256 bits.
 *								The size in bytes.
 *
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static int dx_ecb_aes_setkey(struct crypto_tfm *tfm, const uint8_t  *in_key, uint_t key_len)
{                                                                              
/* The return error identifier */
uint32_t error;

int i;
   
struct dx_aes_ctx *ctx_ptr = crypto_tfm_ctx(tfm);

/* initializing the error to O.K */
error=DX_OK; 
    
	printk(KERN_INFO "\n DX_CRYTP --- start: dx_ecb_aes_setkey \n"); 
	printk(KERN_INFO "\n DX_CRYTP --- dx_ecb_aes_setkey: key_len = %d\n",key_len);
	printk(KERN_INFO "\n DX_CRYTP --- dx_ecb_aes_setkey: key = \n");

	for (i=0;i<key_len;i++)
		printk(KERN_INFO "%c",in_key[i]);
    
	printk(KERN_INFO "\n DX_CRYPTO --- dx_ecb_aes_setkey: step 1");
    
	if ((key_len !=AES_KEYLEN_16_BYTES) && 
	    (key_len !=AES_KEYLEN_24_BYTES) &&
	    (key_len !=AES_KEYLEN_32_BYTES)) {
		error = CRYS_AES_ILLEGAL_KEY_SIZE_ERROR;
		goto End;
	}
	
	printk(KERN_INFO "\n DX_CRYPTO --- dx_ecb_aes_setkey: step 2");	 
	ctx_ptr->key_len = key_len;
	memcpy(ctx_ptr->key, in_key, key_len);
    
	printk(KERN_INFO "\n DX_CRYTP --- dx_ecb_aes_setkey: key_len = %d\n",ctx_ptr->key_len);
	printk(KERN_INFO "\n DX_CRYTP --- dx_ecb_aes_setkey: key = \n");

	for (i=0;i<key_len;i++)
		printk(KERN_INFO "%c",ctx_ptr->key[i]);
	
	printk(KERN_INFO "\n DX_CRYTP --- finish: dx_ecb_aes_setkey \n"); 
    
	return DX_OK;
      
End:
	return error;
};

/****************************************************************************************************/
/**
 * @brief This function is used to unregistreate the AES algorithm.
 *   
 * @param[in] desc - pointer to the high level structure blkcipher_desc.
 * @param[in] Dst - pointer to the destination structure scatterlist.
 * @param[in] Src - pointer to the source structure scatterlist.
 * @param[in] nbytes - number of bytes to encrypt
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static int dx_ecb_aes_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
						struct scatterlist *src, uint nbytes)
{
/* The return error identifier */
uint32_t error;

int i;

CRYS_AES_KeySize_t keysize=0;
    
struct dx_aes_ctx *ctx_ptr = crypto_blkcipher_ctx(desc->tfm);
  
/* initializing the error to O.K */
error=DX_OK; 
      
	printk(KERN_INFO "\n DX_CRYTP --- start: dx_ecb_aes_encrypt \n");  
	printk(KERN_INFO "\n DX_CRYTP --- dx_ecb_aes_encrypt: nbytes = %d\n",nbytes);
	printk(KERN_NOTICE "\n DX_CRYTP --- dx_ecb_aes_encrypt: key_len = %d\n",ctx_ptr->key_len);
	printk(KERN_NOTICE "\n DX_CRYTP --- dx_ecb_aes_encrypt: key = \n");

	for (i=0;i<ctx_ptr->key_len;i++) 
		printk(KERN_NOTICE "%c",ctx_ptr->key[i]);
    
	switch(ctx_ptr->key_len) {
	case AES_KEYLEN_16_BYTES:
		keysize = CRYS_AES_Key128BitSize;
		break;
	case AES_KEYLEN_24_BYTES:
		keysize = CRYS_AES_Key192BitSize;
		break;
	case AES_KEYLEN_32_BYTES:
		keysize = CRYS_AES_Key256BitSize;
		break;
	default:
		return CRYS_AES_ILLEGAL_KEY_SIZE_ERROR;
	}
	
	printk(KERN_INFO "\n DX_CRYPTO --- dx_ecb_aes_encrypt: step 1");
	printk(KERN_INFO "\n DX_CRYTP --- dx_ecb_aes_encrypt: keysize = %d\n",keysize);    
	
	/* Locking data in memory */
	
	printk(KERN_INFO "\n DX_CRYPTO --- dx_ecb_aes_encrypt: step 2");
       
	/* call the AES function with the rlevant parameters for encrypt ecb mode */
	error = CRYS_AES(DX_NULL, ctx_ptr->key, keysize, CRYS_AES_Encrypt, 
		CRYS_AES_ECB_mode, 0, (uint8_t*)src,nbytes,(uint8_t*)dst );
	if (error != DX_OK)
		return error;
	
	printk(KERN_INFO "\n DX_CRYPTO --- dx_ecb_aes_encrypt: step 3");
	printk(KERN_INFO "\n DX_CRYTP --- finish: dx_ecb_aes_encrypt \n"); 
	 
	/* releasing the out buffer in the memory */

	return DX_OK;	
};
/****************************************************************************************************/
/**
 * @brief This function is used to unregistreate the AES algorithm.
 *
 * @param[in] desc - pointer to the high level structure blkcipher_desc.
 * @param[in] Dst - pointer to the destination structure scatterlist.
 * @param[in] Src - pointer to the source structure scatterlist.
 * @param[in] nbytes - number of bytes to encrypt
 *
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static int dx_ecb_aes_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
					struct scatterlist *src, unsigned int nbytes)
{
/* The return error identifier */
uint32_t error;

CRYS_AES_KeySize_t keysize=0;
    
struct dx_aes_ctx *ctx_ptr = crypto_blkcipher_ctx(desc->tfm);
	
/* initializing the error to O.K */
error=DX_OK; 
    
	/* find the size of the key */
	switch(ctx_ptr->key_len) {
	case AES_KEYLEN_16_BYTES:
		keysize = CRYS_AES_Key128BitSize;
		break;
	case AES_KEYLEN_24_BYTES:
		keysize = CRYS_AES_Key192BitSize;
		break;
	case AES_KEYLEN_32_BYTES:
		keysize = CRYS_AES_Key256BitSize;
		break;
	default:
	    	return CRYS_AES_ILLEGAL_KEY_SIZE_ERROR;
	}
   
	/* call the AES function with the rlevant parameters for encrypt ecb mode */
	error = CRYS_AES(DX_NULL, ctx_ptr->key, keysize, CRYS_AES_Decrypt,
		CRYS_AES_ECB_mode, 0, (uint8_t*)src, nbytes, (uint8_t*)dst );
	if (error != DX_OK)
		return error;
	
	return DX_OK;	  	
};



/****************************************************************************************************/
/**
 * @brief This function is used to unregistreate the AES algorithm.
 * 
 * @param[in] tfm - pointer to the high level structure crypto_tfm.
 * @param[in] in_key - A pointer to the user's key buffer.
 * @param[in] key_len - The size of the KEY used by the AES: 128, 192 or 256 bits.
 *								The size in bytes.
 *
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static int dx_cbc_aes_setkey(struct crypto_tfm *tfm, const unsigned char  *in_key,
			 					unsigned int key_len)
{
/* The return error identifier */
uint32_t error;

struct dx_aes_ctx *ctx_ptr = crypto_tfm_ctx(tfm);

/* initializing the error to O.K */
error=DX_OK; 
    
	printk(KERN_INFO "\n start: DX_CRYTP --- dx_cbc_aes_setkey \n"); 
  
	if ((key_len !=AES_KEYLEN_16_BYTES) &&
		(key_len !=AES_KEYLEN_24_BYTES) &&
		(key_len !=AES_KEYLEN_32_BYTES)) {
			error = CRYS_AES_ILLEGAL_KEY_SIZE_ERROR;
			goto End;
	}
		 
	ctx_ptr->key_len = key_len;
	memcpy(ctx_ptr->key, in_key, key_len);
    
	printk(KERN_INFO "\n finish: DX_CRYTP --- dx_cbc_aes_setkey \n"); 
    
	return DX_OK;
      
End:
	return error;
};

/****************************************************************************************************/
/**
 * @brief This function is used to unregistreate the AES algorithm.
 *   
 * @param[in] desc - pointer to the high level structure blkcipher_desc.
 * @param[in] Dst - pointer to the destination structure scatterlist.
 * @param[in] Src - pointer to the source structure scatterlist.
 * @param[in] nbytes - number of bytes to encrypt
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static int dx_cbc_aes_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
					struct scatterlist *src, unsigned int nbytes)
{
/* The return error identifier */
uint32_t error;
   
CRYS_AES_KeySize_t keysize=0;
    
uint8_t *iv_ptr;
   
struct dx_aes_ctx *ctx_ptr = crypto_blkcipher_ctx(desc->tfm);
	
/* initializing the error to O.K */
error=DX_OK; 

	switch(ctx_ptr->key_len) {
	case AES_KEYLEN_16_BYTES:
		keysize = CRYS_AES_Key128BitSize;
		break;
	case AES_KEYLEN_24_BYTES:
	      keysize = CRYS_AES_Key192BitSize;
	      break;
	case AES_KEYLEN_32_BYTES:
	keysize = CRYS_AES_Key256BitSize;
	      break;
	default:
		return CRYS_AES_ILLEGAL_KEY_SIZE_ERROR;  
	}
	   
	/* extract the iv information */
	iv_ptr = crypto_blkcipher_crt(desc->tfm)->iv;

	/* call the AES function with the rlevant parameters for encrypt ecb mode */
	error = CRYS_AES(iv_ptr, ctx_ptr->key, keysize, CRYS_AES_Encrypt, CRYS_AES_CBC_mode,      
						0, (uint8_t*)src, nbytes, (uint8_t*)dst );
	if (error != DX_OK)
		return error;
	  
	return DX_OK;	
};
/****************************************************************************************************/
/**
 * @brief This function is used to unregistreate the AES algorithm.
 *
 * @param[in] desc - pointer to the high level structure blkcipher_desc.
 * @param[in] Dst - pointer to the destination structure scatterlist.
 * @param[in] Src - pointer to the source structure scatterlist.
 * @param[in] nbytes - number of bytes to encrypt
 *
 * @return value - On success DX_OK is returned, on failure a
 *                        value MODULE_* CRYS_AES_error.h
 */
static int dx_cbc_aes_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
					struct scatterlist *src, unsigned int nbytes)
{
/* The return error identifier */
uint32_t error;
   
CRYS_AES_KeySize_t keysize=0;
    
uint8_t *iv_ptr;
   
struct dx_aes_ctx *ctx_ptr = crypto_blkcipher_ctx(desc->tfm);
	
/* initializing the error to O.K */
error=DX_OK; 

	switch(ctx_ptr->key_len) {
	case AES_KEYLEN_16_BYTES:
		keysize = CRYS_AES_Key128BitSize;
		break;
	case AES_KEYLEN_24_BYTES:
		keysize = CRYS_AES_Key192BitSize;
		break;
	case AES_KEYLEN_32_BYTES:
		keysize = CRYS_AES_Key256BitSize;
		break;
	default:
		return CRYS_AES_ILLEGAL_KEY_SIZE_ERROR;  
	}
	   
	/* extract the iv information */
	iv_ptr = crypto_blkcipher_crt(desc->tfm)->iv;

	/* call the AES function with the rlevant parameters for encrypt ecb mode */
	error = CRYS_AES(iv_ptr, ctx_ptr->key, keysize, CRYS_AES_Decrypt, CRYS_AES_CBC_mode,
						0, (uint8_t*)src, nbytes, (uint8_t*)dst );
	if (error != DX_OK)
		return error;
	
	return DX_OK;		
};

/*******************************************************************************************************/
/************* Dummy function prototype ****************/
 uint32_t  CRYS_AES( CRYS_AES_IvCounter_t       IVCounter_ptr,       
					CRYS_AES_Key_t             Key_ptr,
				CRYS_AES_KeySize_t         KeySize,            
					CRYS_AES_EncryptMode_t     EncryptDecryptFlag, 
					CRYS_AES_OperationMode_t   OperationMode ,      
					uint8_t                  is_secret_key,       
					uint8_t                  *DataIn_ptr,        
					uint32_t                 DataInSize,         
					uint8_t                  *DataOut_ptr )
{
    int i;
    
    printk(KERN_ALERT "\n HELLO: CRYS_AES - DUMMY FUNCTION\n"); 
    printk(KERN_ALERT "\n**********************************\n"); 
    if (IVCounter_ptr == DX_NULL)
    {
        printk(KERN_ALERT "\n IVCounter_ptr = NULL "); 
    }
    else
    {
        printk(KERN_ALERT "\n IVCounter_ptr = "); 
        for (i=0;i<(CRYS_AES_IV_COUNTER_SIZE_IN_BYTES/4);i++)
            printk(KERN_ALERT "%x,", IVCounter_ptr[i]); 
    }

    if (Key_ptr ==DX_NULL)
    {
        printk(KERN_ALERT "\n Key_ptr = NULL "); 
    }
    else
    {
        printk(KERN_ALERT "\n Key_ptr = "); 
        for (i=0;i<(CRYS_AES_KEY_MAX_SIZE_IN_BYTES/4);i++)
            printk(KERN_ALERT "%x,", Key_ptr[i]); 
    }

    printk(KERN_ALERT "\n KeySize = %d",KeySize); 
    printk(KERN_ALERT "\n EncryptDecryptFlag = %d",EncryptDecryptFlag); 
    printk(KERN_ALERT "\n OperationMode = %d",OperationMode); 
    printk(KERN_ALERT "\n is_secret_key = %d",is_secret_key); 
    printk(KERN_ALERT "\n DataInSize = %d",DataInSize);

    printk(KERN_ALERT "\n DataIn_ptr = "); 
    for (i=0;i<DataInSize;i++)
        printk(KERN_ALERT "%x,", DataIn_ptr[i]); 
    
    printk(KERN_ALERT "\n DataOut_ptr = "); 
    for (i=0;i<DataInSize;i++)
        printk(KERN_ALERT "%x,", DataOut_ptr[i]); 
    
    printk(KERN_ALERT "\n FINISH: CRYS_AES - DUMMY FUNCTION\n"); 
    printk(KERN_ALERT "\n***********************************\n"); 
        
    
    
	
    return DX_OK;
}
