/*
 * (C) Copyright 2007 Andre McCurdy, NXP Semiconductors
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <aes.h>

#if 0
#define ENABLE_CTR_MODE 		/* does Mitch still need this.. ?!? */
#endif

/*****************************************************************************
*****************************************************************************/

#ifndef SGDX_REGS_BASE
#define SGDX_REGS_BASE				0xB7E1C000
#endif

#define REG_AES_CONFIG                  	0x430		/* AES config register */
  #define AES_CONFIG_SKEY_SELECT        	(1 << 9)
  #define AES_CONFIG_CTR_MODE           	(1 << 8)
  #define AES_CONFIG_DO_NOT_EXECUTE     	(1 << 7)
  #define AES_CONFIG_INIT_KEY           	(1 << 5)
  #define AES_CONFIG_PROCESS_ONE_WORD   	(2 << 5)
  #define AES_CONFIG_INIT_IV            	(3 << 5)
  #define AES_CONFIG_ECB                	(0 << 4)
  #define AES_CONFIG_CBC                	(1 << 4)
  #define AES_CONFIG_BYPASS             	(1 << 3)
  #define AES_CONFIG_DECRYPT            	(0 << 2)
  #define AES_CONFIG_ENCRYPT            	(1 << 2)
  #define AES_CONFIG_WORD_SWAP_A        	(0 << 0)
  #define AES_CONFIG_WORD_SWAP_B        	(1 << 0)
  #define AES_CONFIG_WORD_SWAP_C        	(2 << 0)
  #define AES_CONFIG_WORD_SWAP_D        	(3 << 0)
  #define AES_CONFIG_DEFAULT            	(0)

#define REG_AES_CMD                     	0x434		/* AES command register */
  #define AES_CMD_ABORT                 	(1 << 3)
  #define AES_CMD_SOFT_RESET            	(1 << 2)
  #define AES_CMD_PROCESS_BLOCK         	(1 << 1)
  #define AES_CMD_PROCESS_CONFIG        	(1 << 0)

#define REG_AES_BLOCK_COUNT             	0x438		/* 16Byte block count (max 1024) */

#define REG_AES_STATUS                  	0x43C		/* AES status */
  #define AES_STATUS_SKEY_VALID         	(1 << 16)
  #define AES_STATUS_STATE_MASK         	(0x07)
  #define AES_STATUS_STATE_SHIFT        	(13)
  #define AES_STATUS_READ_FREEZE        	(1 << 12)
  #define AES_STATUS_ZERO               	(1 << 11)
  #define AES_STATUS_CURRENT_WORD_MASK  	(0x7FF)
  #define AES_STATUS_CURRENT_WORD_SHIFT 	(0)

#define REG_AES_DATA_IN0                	0x440		/* AES data in [127:96] */
#define REG_AES_DATA_IN1                	0x444		/* AES data in [95:64] */
#define REG_AES_DATA_IN2                	0x448		/* AES data in [63:32] */
#define REG_AES_DATA_IN3                	0x44C		/* AES data in [31:0] */
#define REG_AES_DATA_OUT0               	0x450		/* AES data out [127:96] */
#define REG_AES_DATA_OUT1               	0x454		/* AES data out [95:64] */
#define REG_AES_DATA_OUT2               	0x458		/* AES data out [63:32] */
#define REG_AES_DATA_OUT3               	0x45C		/* AES data out [31:0] */

#define REG_AES_PKT_CFG                 	0x460		/* AES packet configuration */
  #define AES_PKT_CFG_HEADER_MASK       	(0xFF)
  #define AES_PKT_CFG_HEADER_SHIFT      	(16)
  #define AES_PKT_CFG_DATA_MASK         	(0xFFFF)
  #define AES_PKT_CFG_DATA_SHIFT        	(0)
  #define AES_PKT_CFG_DEFAULT           	(0x0000FFFF)

#define REG_AES_INCR_CTR                	0x464		/* AES value for counter increment */
#define REG_AES_CTR_PKT                 	0x468		/* AES packet size in CTR_MODE */


/*****************************************************************************
*****************************************************************************/

#ifndef KC_REGS_BASE
#define KC_REGS_BASE				0xB7E04000
#endif

#define REG_KC_UID_LSB				0x000		/* 31:0 : R- : UNIQUE_ID bits (31:0) */
#define REG_KC_UID_MSB				0x004		/* 31:0 : R- : UNIQUE_ID bits (63:32) */

#define REG_KC_STATUS				0x008		/* 15:0 : R- : Status register */

  #define KC_STATUS_FB1_KEY_VALID		(1 << 9)	/* Feedback key for SGdesc path validity */
  #define KC_STATUS_OUT1_KEY_VALID		(1 << 8)	/* Output key for SGDesc path validity */
  #define KC_STATUS_SESSION1_KEY_VALID		(1 << 7)	/* Session key for SGDesc path validity */
  #define KC_STATUS_CHAINING1_KEY_VALID		(1 << 6)	/* Chaining key for SGDesc path validity */
  #define KC_STATUS_PRIVATE1_KEY_VALID		(1 << 5)	/* Private key for SGDesc path validity */
  #define KC_STATUS_OTP1_KEY_VALID		(1 << 4)	/* OTP secret key for SGDesc path validity */
  #define KC_STATUS_KL_MODE_2_LEVEL		(0 << 2)	/* */
  #define KC_STATUS_KL_MODE_3_LEVEL		(1 << 2)	/* */
  #define KC_STATUS_KL_MODE_2_LEVEL_ALT 	(2 << 2)	/* */
  #define KC_STATUS_KL_MODE_RESERVED		(3 << 2)	/* */
  #define KC_STATUS_KL_MODE_MASK		(3 << 2)	/* */
  #define KC_STATUS_DISABLE_KEYS_OUT		(1 << 1)	/* Value of DISABLE_KEYS_OUT input. If 1, OTP secret key can not be output to SGDesc */
  #define KC_STATUS_DISABLE_CA_MODULE		(1 << 0)	/* Value of DISABLE_CA_MODULE input. If 1, the Keycontrol module is de-activated */

#define REG_KC_DATA1_LSB			0x00C		/* 31:0 : RW : Data1(31:0) input value */
#define REG_KC_DATA1_MSB			0x010		/* 31:0 : RW : Data1(63:32) input value */
#define REG_KC_CFG 				0x014		/*  7:0 : RW : Configuration register */

  #define KC_CFG_OUT_KEY_FROM_MEM		(1 << 7)	/* */
  #define KC_CFG_ALG_SELECT_ENC			(0 << 6)	/* */
  #define KC_CFG_ALG_SELECT_DEC			(1 << 6)	/* */
  #define KC_CFG_ALG_SELECT_MASK		(0x01 << 6)	/* */
  #define KC_CFG_RESULT_SEL_OUTPUT		(0 << 5)	/* */
  #define KC_CFG_RESULT_SEL_FB			(1 << 5)	/* */
  #define KC_CFG_RESULT_SEL_MASK		(0x01 << 5)	/* */
  #define KC_CFG_INPUT_SEL_DATAIN		(0 << 3)	/* */
  #define KC_CFG_INPUT_SEL_DATAIN_XOR_FB	(1 << 3)	/* */
  #define KC_CFG_INPUT_SEL_FB			(2 << 3)	/* */
  #define KC_CFG_INPUT_SEL_MASK			(0x03 << 3)	/* */
  #define KC_CFG_COMMAND_GEN_CHAIN1		(0 << 0)	/* */
  #define KC_CFG_COMMAND_GEN_SESSION1		(1 << 0)	/* */
  #define KC_CFG_COMMAND_GEN_CW1		(2 << 0)	/* */
  #define KC_CFG_COMMAND_GEN_MASK		(0x07 << 0)	/* */

#define REG_KC_START				0x018		/*    0 : RW : Write 1 to cause start execution */
#define REG_KC_DATA2_LSB			0x020		/* 31:0 : RW : Data2(31:0) input value */
#define REG_KC_DATA2_MSB			0x024		/* 31:0 : RW : Data2(63:32) input value */
#define REG_KC_DATA3_LSB			0x028		/* 31:0 : RW : Data3(31:0) input value */
#define REG_KC_DATA3_MSB			0x02C		/* 31:0 : RW : Data3(63:32) input value */
#define REG_KC_INT_STATUS			0xFE0		/*  1:0 : R- : Interrupt status */
#define REG_KC_INT_ENABLE			0xFE4		/*  1:0 : RW : Interrupt enable */
#define REG_KC_INT_CLEAR			0xFE8		/*  1:0 : RW : Interrupt clear */
#define REG_KC_INT_SET				0xFEC		/*  1:0 : RW : Interrupt set */

  #define KC_INT_OK				(1 << 0)
  #define KC_INT_ERROR				(1 << 1)
  #define KC_INT_ALL				(0x03)

#define REG_KC_POWERDOWN			0xFF4		/*    0 : RW : To put the Keycontrol module in power down mode */
#define REG_KC_MODULE_ID			0xFFC		/* 31:0 : R- : Module Identification and revision information */


/*****************************************************************************
*****************************************************************************/

static unsigned int aes_reg_read (unsigned int reg_offset)
{
	return *((volatile unsigned int *) (SGDX_REGS_BASE + reg_offset));
}

static void aes_reg_write (unsigned int reg_offset, unsigned int value)
{
	*((volatile unsigned int *) (SGDX_REGS_BASE + reg_offset)) = value;
}

static unsigned int kc_reg_read (unsigned int reg_offset)
{
	return *((volatile unsigned int *) (KC_REGS_BASE + reg_offset));
}

static void kc_reg_write (unsigned int reg_offset, unsigned int value)
{
	*((volatile unsigned int *) (KC_REGS_BASE + reg_offset)) = value;
}


/*****************************************************************************
*****************************************************************************/

static unsigned int unaligned_read32_be (const unsigned char *src)
{
	unsigned int value;

	value = src[0];
	value = (value << 8) | src[1];
	value = (value << 8) | src[2];
	value = (value << 8) | src[3];

	return value;
}

static void unaligned_write32_be (unsigned char *dst, unsigned int value)
{
	dst[0] = (unsigned char) (value >> 24);
	dst[1] = (unsigned char) (value >> 16);
	dst[2] = (unsigned char) (value >> 8);
	dst[3] = (unsigned char) (value >> 0);
}

#if 0
static void kc_reg_read64 (unsigned char *dst, unsigned int reg_offset)
{
	unaligned_write32_be (dst + 4, kc_reg_read (reg_offset + 0));
	unaligned_write32_be (dst + 0, kc_reg_read (reg_offset + 4));
}
#endif

static void kc_reg_write64 (unsigned int reg_offset, const unsigned char *src)
{
	kc_reg_write (reg_offset + 0, unaligned_read32_be (src + 4));
	kc_reg_write (reg_offset + 4, unaligned_read32_be (src + 0));
}

static void kc_data_write192 (const unsigned char *src)
{
	kc_reg_write64 (REG_KC_DATA1_LSB, src + 0);
	kc_reg_write64 (REG_KC_DATA2_LSB, src + 8);
	kc_reg_write64 (REG_KC_DATA3_LSB, src + 16);
}

static void aes_datain_write128 (const unsigned char *src)
{
	aes_reg_write (REG_AES_DATA_IN0, unaligned_read32_be (src + 0));
	aes_reg_write (REG_AES_DATA_IN1, unaligned_read32_be (src + 4));
	aes_reg_write (REG_AES_DATA_IN2, unaligned_read32_be (src + 8));
	aes_reg_write (REG_AES_DATA_IN3, unaligned_read32_be (src + 12));
}

static void aes_dataout_read128 (unsigned char *dst)
{
	unaligned_write32_be (dst + 0, aes_reg_read (REG_AES_DATA_OUT0));
	unaligned_write32_be (dst + 4, aes_reg_read (REG_AES_DATA_OUT1));
	unaligned_write32_be (dst + 8, aes_reg_read (REG_AES_DATA_OUT2));
	unaligned_write32_be (dst + 12, aes_reg_read (REG_AES_DATA_OUT3));
}


/*****************************************************************************
*****************************************************************************/

static int kc_process (const unsigned char *data, unsigned int cmd)
{
	int intstat;

	kc_reg_write (REG_KC_INT_CLEAR, KC_INT_ALL);
	kc_reg_write (REG_KC_CFG, cmd);
	kc_data_write192 (data);
	kc_reg_write (REG_KC_START, 1);

	while ((intstat = kc_reg_read (REG_KC_INT_STATUS)) == 0)
		;

	kc_reg_write (REG_KC_INT_CLEAR, KC_INT_ALL);

	return (intstat == KC_INT_OK) ? 0 : -1;
}

static int kc_setup (const unsigned char *ck_ct, const unsigned char *sk_ct, const unsigned char *cw_ct)
{
	static const unsigned char keydata[24] = {
		0xC1,0xEE,0xE4,0xF2,0xE5,0xA0,0xCD,0xE3,
		0xC3,0xF5,0xF2,0xE4,0xF9,0xA0,0xB2,0xEB,
		0xB7,0xA0,0xC7,0xD0,0xCC,0xA0,0xA0,0x80
	};

	int result;
	int hw_bypass_disabled;
	int hw_levels_supported;
	unsigned int cmd1, cmd2, cmd3;
	unsigned int status = kc_reg_read (REG_KC_STATUS);

	printf ("%s: KC_STATUS 0x%08x\n", __FUNCTION__, status);

	if (status & KC_STATUS_DISABLE_CA_MODULE)
		return -1;

	if ((status & KC_STATUS_OTP1_KEY_VALID) != KC_STATUS_OTP1_KEY_VALID)
		return -1;

	switch (status & KC_STATUS_KL_MODE_MASK)
	{
		case KC_STATUS_KL_MODE_2_LEVEL:
		case KC_STATUS_KL_MODE_2_LEVEL_ALT:
			hw_levels_supported = 2;
			break;

		case KC_STATUS_KL_MODE_3_LEVEL:
			hw_levels_supported = 3;
			break;

		default:
			return -1;
	}

	hw_bypass_disabled = (status & KC_STATUS_DISABLE_KEYS_OUT) ? 1 : 0;

	cmd1 = (KC_CFG_ALG_SELECT_DEC | KC_CFG_COMMAND_GEN_CHAIN1);
	cmd2 = (KC_CFG_ALG_SELECT_DEC | KC_CFG_COMMAND_GEN_SESSION1);
	cmd3 = (KC_CFG_ALG_SELECT_DEC | KC_CFG_COMMAND_GEN_CW1);

	if ((ck_ct == NULL) && (sk_ct == NULL) && (cw_ct == NULL)) {
		if (hw_bypass_disabled)
			return -1;
		ck_ct = keydata;
		sk_ct = keydata;
		cw_ct = keydata;
	}
	else {
		if (((ck_ct == NULL) && (hw_levels_supported != 2)) ||
		    ((ck_ct != NULL) && (hw_levels_supported != 3)))
			return -1;
		cmd3 |= KC_CFG_OUT_KEY_FROM_MEM;
	}

	if (hw_levels_supported == 3) {
		if ((result = kc_process (ck_ct, cmd1)) != 0)
			return result;
	}

	if ((result = kc_process (sk_ct, cmd2)) != 0)
		return result;

	return kc_process (cw_ct, cmd3);
}


/*****************************************************************************
*****************************************************************************/

static int aes_issue_cmd (unsigned int cmd)
{
	int i;

	aes_reg_write (REG_AES_CMD, cmd);

	for (i = 0; i < 10; i++) {
		unsigned int state = aes_reg_read (REG_AES_CMD);
		if (state == 0)
			break;
		printf ("%s: waiting for cmd to complete... 0x%08x\n", __FUNCTION__, state);
		udelay (10);
	}

	return 0;
}

static void aes_hw_init (void)
{
	aes_issue_cmd (AES_CMD_ABORT);		/* is this necessary ?? */
	aes_issue_cmd (AES_CMD_SOFT_RESET);	/* reset internal state (but not externally visible registers !?!) */

	aes_reg_write (REG_AES_PKT_CFG, AES_PKT_CFG_DEFAULT);
	aes_reg_write (REG_AES_BLOCK_COUNT, 0);
}

static int aes_set_key (const unsigned char *keydata, AES_KEY *key, int encdec, int skey)
{
	key->cfg = (encdec == AES_DECRYPT) ? AES_CONFIG_DECRYPT : AES_CONFIG_ENCRYPT;

	aes_hw_init();

	if (skey) {
		if ((aes_reg_read (REG_AES_STATUS) & AES_STATUS_SKEY_VALID) == 0)
			return -1;
		key->cfg |= AES_CONFIG_SKEY_SELECT;
	}
	else {
		aes_datain_write128 (keydata);
	}

	aes_reg_write (REG_AES_CONFIG, (key->cfg | AES_CONFIG_INIT_KEY));

	return aes_issue_cmd (AES_CMD_PROCESS_CONFIG);
}

static void aes_process_block (const unsigned char *in, unsigned char *out, const AES_KEY *key)
{
	aes_datain_write128 (in);
	aes_reg_write (REG_AES_CONFIG, (key->cfg | AES_CONFIG_PROCESS_ONE_WORD));
	aes_issue_cmd (AES_CMD_PROCESS_CONFIG);
	aes_dataout_read128 (out);
}


/*****************************************************************************
*****************************************************************************/

int AES_set_decrypt_key_kc (const unsigned char *ck_ct, const unsigned char *sk_ct, const unsigned char *cw_ct, AES_KEY *key)
{
	int result;

	if ((result = kc_setup (ck_ct, sk_ct, cw_ct)) != 0)
		return result;

	return aes_set_key (NULL, key, AES_DECRYPT, 1);
}

int AES_set_encrypt_key_kc (const unsigned char *ck_ct, const unsigned char *sk_ct, const unsigned char *cw_ct, AES_KEY *key)
{
	int result;

	if ((result = kc_setup (ck_ct, sk_ct, cw_ct)) != 0)
		return result;

	return aes_set_key (NULL, key, AES_ENCRYPT, 1);
}

int AES_set_decrypt_key (const unsigned char *keydata, const int bits, AES_KEY *key)
{
	return aes_set_key (keydata, key, AES_DECRYPT, 0);
}

int AES_set_encrypt_key (const unsigned char *keydata, const int bits, AES_KEY *key)
{
	return aes_set_key (keydata, key, AES_ENCRYPT, 0);
}

void AES_decrypt (const unsigned char *in, unsigned char *out, const AES_KEY *key)
{
	aes_process_block (in, out, key);
}

void AES_encrypt (const unsigned char *in, unsigned char *out, const AES_KEY *key)
{
	aes_process_block (in, out, key);
}

void AES_cbc_encrypt (const unsigned char *in, unsigned char *out,
		      const unsigned long length, const AES_KEY *key,
		      unsigned char *iv, const int enc)
{
	int i;
	unsigned char tmp[16];
	unsigned int blocks;

	if ((length % 16) != 0)
		printf ("%s: %d trailing bytes will not be processed !!\n", __FUNCTION__, (length % 16));

	blocks = (length / 16);
	if (blocks == 0)
		return;

	while (1) {
		if (enc == AES_DECRYPT) {
			memcpy (tmp, in, 16);
			AES_decrypt (in, out, key);
			for (i = 0; i < 16; i++)
				out[i] ^= iv[i];
			memcpy (iv, tmp, 16);
		}
		else {
			for (i = 0; i < 16; i++)
				tmp[i] = in[i] ^ iv[i];
			AES_encrypt (tmp, out, key);
			memcpy (iv, out, 16);
		}
		if (--blocks == 0)
			break;
		in += 16;
		out += 16;
	}
}


#if defined (ENABLE_CTR_MODE)

/*
   Fixme: Working with chars is endian independent... but very inefficient.
*/
static void abn_inc_128be (unsigned char *bn)
{
	unsigned char t1, t2, c1, c2 = 0, inc = 1;
	unsigned char *bnp = bn + 15;

	while (1) {
		t1 = *bnp;
		t2 = t1 + inc;
		inc = 0;
		c1 = (t2 < t1) ? 1 : 0;
		t1 = t2 + c2;
		c2 = (t1 < t2) ? 1 : c1;
		*bnp = t1;
		if (bnp == bn)
			break;
		bnp--;
	}
}

void AES_ctr128_encrypt (const unsigned char *in, unsigned char *out,
			 const unsigned long length, const AES_KEY *key,
			 unsigned char *iv, unsigned char *ecount_buf,
			 unsigned int *num)
{
	unsigned int l = length;
	unsigned int n = *num;

	while (l--) {
		if (n == 0) {
			AES_encrypt (iv, ecount_buf, key);
			abn_inc_128be (iv);
		}
		*out++ = *in++ ^ ecount_buf[n];
		n = (n + 1) % 16;
	}

	*num = n;
}

#endif


/*****************************************************************************
*****************************************************************************/
#if 1
/*****************************************************************************
*****************************************************************************/

#include <command.h>
#include <sha.h>

/*
   Rijndael test values : ECB decryption (Monte Carlo test... iterate 10000 times).
*/
static const unsigned char ecb_d_key[] = { 0xA7, 0xBC, 0x3B, 0xD0, 0xEA, 0xBD, 0x9E, 0xBA, 0x98, 0x1E, 0x23, 0xE6, 0xFF, 0xC9, 0xC9, 0xC2 };
static const unsigned char ecb_d_ct[]  = { 0xE3, 0xFD, 0x51, 0x12, 0x3B, 0x48, 0xA2, 0xE2, 0xAB, 0x1D, 0xB2, 0x98, 0x94, 0x20, 0x22, 0x22 };
static const unsigned char ecb_d_pt[]  = { 0x87, 0x7B, 0x88, 0xA7, 0x7A, 0xEF, 0x04, 0xF0, 0x55, 0x46, 0x53, 0x9E, 0x17, 0x25, 0x9F, 0x53 };

/*
   Rijndael test values : ECB encryption (Monte Carlo test... iterate 10000 times).
*/
static const unsigned char ecb_e_key[] = { 0xC9, 0x8D, 0x5F, 0xB6, 0x3B, 0x68, 0xC0, 0x27, 0xE8, 0x83, 0x17, 0xD8, 0x23, 0x3C, 0x5B, 0x9D };
static const unsigned char ecb_e_pt[]  = { 0x0A, 0xC1, 0x5A, 0x9A, 0xFB, 0xB2, 0x4D, 0x54, 0xAD, 0x99, 0xE9, 0x87, 0x20, 0x82, 0x72, 0xE2 };
static const unsigned char ecb_e_ct[]  = { 0xA3, 0xD4, 0x3B, 0xFF, 0xA6, 0x5D, 0x0E, 0x80, 0x09, 0x2F, 0x67, 0xA3, 0x14, 0x85, 0x78, 0x70 };

/*
   Rijndael test values : CBC decryption (Monte Carlo test... iterate 10000 times).
*/
static const unsigned char cbc_d_key[] = { 0x0F, 0xFD, 0x18, 0x77, 0x85, 0x0D, 0x3B, 0x2C, 0xC2, 0xD3, 0x0C, 0xDC, 0x99, 0x02, 0x86, 0xC6 };
static const unsigned char cbc_d_iv[]  = { 0xDD, 0x74, 0xBB, 0x1A, 0xC6, 0xF0, 0xF8, 0x66, 0xC7, 0x99, 0x2C, 0x61, 0xF5, 0x9D, 0x55, 0x94 };
static const unsigned char cbc_d_ct[]  = { 0xF5, 0x37, 0x2F, 0x97, 0x35, 0xC5, 0x68, 0x5F, 0x1D, 0xA3, 0x62, 0xAF, 0x6E, 0xCB, 0x29, 0x40 };
static const unsigned char cbc_d_pt[]  = { 0x54, 0x96, 0xA4, 0xC2, 0x9C, 0x76, 0x70, 0xF6, 0x1B, 0x5D, 0x5D, 0xF6, 0x18, 0x1F, 0x59, 0x47 };

/*
   Rijndael test values : CBC encryption (Monte Carlo test... iterate 10000 times).
*/
static const unsigned char cbc_e_key[] = { 0x93, 0x28, 0x67, 0x64, 0xA8, 0x51, 0x46, 0x73, 0x0E, 0x64, 0x18, 0x88, 0xDB, 0x34, 0xEB, 0x47 };
static const unsigned char cbc_e_iv[]  = { 0x19, 0x2D, 0x9B, 0x3A, 0xA1, 0x0B, 0xB2, 0xF7, 0x84, 0x6C, 0xCB, 0xA0, 0x08, 0x5C, 0x65, 0x7A };
static const unsigned char cbc_e_pt[]  = { 0x98, 0x3B, 0xF6, 0xF5, 0xA6, 0xDF, 0xBC, 0xDA, 0xA1, 0x93, 0x70, 0x66, 0x6E, 0x83, 0xA9, 0x9A };
static const unsigned char cbc_e_ct[]  = { 0x40, 0xD8, 0xDA, 0xF6, 0xD1, 0xFD, 0xA0, 0xA0, 0x73, 0xB3, 0xBD, 0x18, 0xB7, 0x69, 0x5D, 0x2E };


#if defined (ENABLE_CTR_MODE)

/*
   "Using AES Counter Mode with IPsec ESP" test vector #2: Encrypting 32 octets using AES-CTR with 128-bit key
*/
static const unsigned char ctr_key[] = { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 };
static const unsigned char ctr_iv[]  = { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 };
static const unsigned char ctr_pt[]  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
                                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
static const unsigned char ctr_ct[]  = { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88,
                                         0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 };

#endif

/*
   Fixme: these test vectors rely on fixed OTP keys...

      #define TDESKEY1_DEFAULT_STRING	"D35107FBB602BF37"
      #define TDESKEY2_DEFAULT_STRING	"13D01C089E8AF123"
      #define TDESKEY3_DEFAULT_STRING	"D35107FBB602BF37"
*/

static const unsigned char sk_ct_2l[24] = {
	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
	0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
	0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A
};

static const unsigned char cw_ct_2l[24] = {
	0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
	0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
	0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D
};

static const unsigned char ck_ct_3l[24] = {
	0x8c, 0xdc, 0xf2, 0xe9, 0xc4, 0xb1, 0x8a, 0x6f,
	0x9a, 0xe2, 0x19, 0xb0, 0xe9, 0x20, 0x58, 0xd8,
	0x88, 0x6b, 0xfb, 0x0b, 0x12, 0x90, 0xa8, 0x1f
};

static const unsigned char sk_ct_3l[24] = {
	0xa6, 0x7a, 0x5d, 0x90, 0x43, 0xb4, 0x00, 0x5f,
	0x0b, 0x9c, 0x41, 0xb3, 0x93, 0xde, 0x08, 0x01,
	0x8c, 0x31, 0xaa, 0xe7, 0xfc, 0x02, 0xf5, 0x3e
};

static const unsigned char cw_ct_3l[24] = {
	0xe2, 0x66, 0x64, 0xb3, 0x05, 0xbd, 0x47, 0xeb,
	0xb6, 0xf2, 0x4f, 0xb7, 0x47, 0xe1, 0xac, 0x29,
	0xc9, 0x11, 0x58, 0x22, 0x30, 0x8f, 0xf8, 0x0d
};

static const unsigned char ecb_ct_kcb[] = { 0xE3, 0xFD, 0x51, 0x12, 0x3B, 0x48, 0xA2, 0xE2, 0xAB, 0x1D, 0xB2, 0x98, 0x94, 0x20, 0x22, 0x22 };
static const unsigned char ecb_pt_kcb[] = { 0xf4, 0x71, 0x55, 0x71, 0x1d, 0xe5, 0x08, 0x9b, 0xf0, 0x3d, 0x5a, 0xf0, 0x49, 0x3e, 0x33, 0xae };

static const unsigned char ecb_ct[] = { 0xE3, 0xFD, 0x51, 0x12, 0x3B, 0x48, 0xA2, 0xE2, 0xAB, 0x1D, 0xB2, 0x98, 0x94, 0x20, 0x22, 0x22 };
static const unsigned char ecb_pt[] = { 0x88, 0x94, 0x44, 0xe4, 0x44, 0x8b, 0x51, 0x39, 0x54, 0x86, 0xef, 0xb9, 0x89, 0x31, 0x42, 0xfe };


static void print_data (char *lead, const unsigned char *data, char *trail)
{
	if (lead)
		printf ("%s", lead);

	printf ("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
		data[0], data[1], data[ 2], data[ 3], data[ 4], data[ 5], data[ 6], data[ 7],
		data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);

	if (trail)
		printf ("%s", trail);
}

static unsigned int ticks_delta_to_usec (unsigned int delta)
{
	return (unsigned int) ((((unsigned long long) delta) * 1000000) / get_tbclk());
}

static unsigned int ticks_delta_to_kbps (unsigned int delta, unsigned int bytes)
{
	return (unsigned int) ((((unsigned long long) bytes) * get_tbclk()) /
			       (((unsigned long long) delta) * 1024));
}

static int selftest_aes (void)
{
	int i;
	AES_KEY key;
	unsigned int len;
	unsigned int start, stop;
	unsigned char buf[256];
	unsigned char buf_prev[16];
	unsigned char buf_iv[16];
	unsigned char tmp[16];
	unsigned char *data;
#if defined (ENABLE_CTR_MODE)
	int n;
#endif

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB encryption\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	AES_set_encrypt_key (ecb_e_key, 128, &key);
	memcpy (buf, ecb_e_pt, 16);
	for (i = 0; i < 10000; i++) {
		AES_encrypt ((const unsigned char *) buf, buf, &key);
	}
	stop = get_ticks();
	print_data ("ecb_e_key: ", ecb_e_key, "\n");
	print_data ("ecb_e_pt : ", ecb_e_pt, "\n");
//	print_data ("ecb_e_ct : ", ecb_e_ct, " <- expected\n");
	print_data ("ecb_e_ct : ", buf, memcmp (buf, ecb_e_ct, 16) ? " <- FAILED !!!\n" : " <- pass\n");
//	printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
	printf ("\n");

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB decryption\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	AES_set_decrypt_key (ecb_d_key, 128, &key);
	memcpy (buf, ecb_d_ct, 16);
	for (i = 0; i < 10000; i++) {
		AES_decrypt ((const unsigned char *) buf, buf, &key);
	}
	stop = get_ticks();
	print_data ("ecb_d_key: ", ecb_d_key, "\n");
	print_data ("ecb_d_ct : ", ecb_d_ct, "\n");
//	print_data ("ecb_d_pt : ", ecb_d_pt, " <- expected\n");
	print_data ("ecb_d_pt : ", buf, memcmp (buf, ecb_d_pt, 16) ? " <- FAILED !!!\n" : " <- pass\n");
//	printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
	printf ("\n");

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES CBC encryption\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	AES_set_encrypt_key (cbc_e_key, 128, &key);
	memcpy (buf, cbc_e_pt, 16);
	memcpy (buf_iv, cbc_e_iv, 16);
	memset (buf_prev, 0, 16);
	for (i = 0; i < 10000; i++) {
		AES_cbc_encrypt ((const unsigned char *) buf, buf, 16, &key, buf_iv, AES_ENCRYPT);
		memcpy (tmp, i ? buf_prev : cbc_e_iv, 16);
		memcpy (buf_prev, buf, 16);
		memcpy (buf, tmp, 16);
	}
	memcpy (buf, buf_prev, 16);
	stop = get_ticks();
	print_data ("cbc_e_key: ", cbc_e_key, "\n");
	print_data ("cbc_e_iv : ", cbc_e_iv, " <- initial\n");
	print_data ("cbc_e_iv : ", buf_iv, " <- final\n");
	print_data ("cbc_e_pt : ", cbc_e_pt, "\n");
//	print_data ("cbc_e_ct : ", cbc_e_ct, " <- expected\n");
	print_data ("cbc_e_ct : ", buf, memcmp (buf, cbc_e_ct, 16) ? " <- FAILED !!!\n" : " <- pass\n");
//	printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
	printf ("\n");

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES CBC decryption\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	AES_set_decrypt_key (cbc_d_key, 128, &key);
	memcpy (buf, cbc_d_ct, 16);
	memcpy (buf_iv, cbc_d_iv, 16);
	for (i = 0; i < 10000; i++) {
		AES_cbc_encrypt ((const unsigned char *) buf, buf, 16, &key, buf_iv, AES_DECRYPT);
	}
	stop = get_ticks();
	print_data ("cbc_d_key: ", cbc_d_key, "\n");
	print_data ("cbc_d_iv : ", cbc_d_iv, " <- initial\n");
	print_data ("cbc_d_iv : ", buf_iv, " <- final\n");
	print_data ("cbc_d_ct : ", cbc_d_ct, "\n");
//	print_data ("cbc_d_pt : ", cbc_d_pt, " <- expected\n");
	print_data ("cbc_d_pt : ", buf, memcmp (buf, cbc_d_pt, 16) ? " <- FAILED !!!\n" : " <- pass\n");
//	printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
	printf ("\n");

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB decryption, KC bypass key\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	if (AES_set_decrypt_key_kc (NULL, NULL, NULL, &key) == 0) {
		memcpy (buf, ecb_ct_kcb, 16);
		AES_decrypt ((const unsigned char *) buf, buf, &key);
		stop = get_ticks();
		print_data ("ecb_ct_kcb: ", ecb_ct_kcb, "\n");
		print_data ("ecb_pt_kcb: ", ecb_pt_kcb, " <- expected\n");
		print_data ("ecb_pt_kcb: ", buf, memcmp (buf, ecb_pt_kcb, 16) ? " <- FAILED !!!\n" : " <- pass\n");
		printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
		printf ("\n");
	}
	else {
		printf ("Not supported\n");
	}

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB encryption, KC bypass key\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	if (AES_set_encrypt_key_kc (NULL, NULL, NULL, &key) == 0) {
		memcpy (buf, ecb_pt_kcb, 16);
		AES_encrypt ((const unsigned char *) buf, buf, &key);
		stop = get_ticks();
		print_data ("ecb_pt_kcb: ", ecb_pt_kcb, "\n");
		print_data ("ecb_ct_kcb: ", ecb_ct_kcb, " <- expected\n");
		print_data ("ecb_ct_kcb: ", buf, memcmp (buf, ecb_ct_kcb, 16) ? " <- FAILED !!!\n" : " <- pass\n");
		printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
		printf ("\n");
	}
	else {
		printf ("Not supported\n");
	}

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB decryption, KC 2 level generated key\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	if (AES_set_decrypt_key_kc (NULL, sk_ct_2l, cw_ct_2l, &key) == 0) {
		memcpy (buf, ecb_ct, 16);
		AES_decrypt ((const unsigned char *) buf, buf, &key);
		stop = get_ticks();
		print_data ("ecb_ct   : ", ecb_ct, "\n");
		print_data ("ecb_pt   : ", ecb_pt, " <- expected\n");
		print_data ("ecb_pt   : ", buf, memcmp (buf, ecb_pt, 16) ? " <- FAILED !!!\n" : " <- pass\n");
		printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
		printf ("\n");
	}
	else {
		printf ("Not supported\n");
	}

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB encryption, KC 2 level generated key\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	if (AES_set_encrypt_key_kc (NULL, sk_ct_2l, cw_ct_2l, &key) == 0) {
		memcpy (buf, ecb_pt, 16);
		AES_encrypt ((const unsigned char *) buf, buf, &key);
		stop = get_ticks();
		print_data ("ecb_pt   : ", ecb_pt, "\n");
		print_data ("ecb_ct   : ", ecb_ct, " <- expected\n");
		print_data ("ecb_ct   : ", buf, memcmp (buf, ecb_ct, 16) ? " <- FAILED !!!\n" : " <- pass\n");
		printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
		printf ("\n");
	}
	else {
		printf ("Not supported\n");
	}

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB decryption, KC 3 level generated key\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	if (AES_set_decrypt_key_kc (ck_ct_3l, sk_ct_3l, cw_ct_3l, &key) == 0) {
		memcpy (buf, ecb_ct, 16);
		AES_decrypt ((const unsigned char *) buf, buf, &key);
		stop = get_ticks();
		print_data ("ecb_ct   : ", ecb_ct, "\n");
		print_data ("ecb_pt   : ", ecb_pt, " <- expected\n");
		print_data ("ecb_pt   : ", buf, memcmp (buf, ecb_pt, 16) ? " <- FAILED !!!\n" : " <- pass\n");
		printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
		printf ("\n");
	}
	else {
		printf ("Not supported\n");
	}

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB encryption, KC 3 level generated key\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	if (AES_set_encrypt_key_kc (ck_ct_3l, sk_ct_3l, cw_ct_3l, &key) == 0) {
		memcpy (buf, ecb_pt, 16);
		AES_encrypt ((const unsigned char *) buf, buf, &key);
		stop = get_ticks();
		print_data ("ecb_pt   : ", ecb_pt, "\n");
		print_data ("ecb_ct   : ", ecb_ct, " <- expected\n");
		print_data ("ecb_ct   : ", buf, memcmp (buf, ecb_ct, 16) ? " <- FAILED !!!\n" : " <- pass\n");
		printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
		printf ("\n");
	}
	else {
		printf ("Not supported\n");
	}

	/*********************************************************************
	*********************************************************************/

#if defined (ENABLE_CTR_MODE)

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES CTR encryption\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	AES_set_encrypt_key (ctr_key, 128, &key);
	memcpy (buf_iv, ctr_iv, 16);
	memset (tmp, 0, 16);
	n = 0;
	AES_ctr128_encrypt ((const unsigned char *) ctr_pt, buf, sizeof(ctr_pt), &key, buf_iv, tmp, &n);
	stop = get_ticks();
	print_data ("ctr_key  : ", ctr_key, "\n");
	print_data ("ctr_iv   : ", ctr_iv, " <- initial\n");
	print_data ("ctr_iv   : ", buf_iv, " <- final\n");
	print_data ("ctr_pt   : ", ctr_pt, "\n");
	print_data ("         : ", ctr_pt + 16, "\n");
//	print_data ("ctr_ct   : ", ctr_ct, "\n");
//	print_data ("         : ", ctr_ct + 16, " <- expected\n");
	print_data ("ctr_ct   : ", buf, "\n");
	print_data ("         : ", buf + 16, memcmp (buf, ctr_ct, sizeof(ctr_ct)) ? " <- FAILED !!!\n" : " <- pass\n");
//	printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
	printf ("\n");

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES CTR decryption\n");
	printf ("--------------------------------------------------------------------\n");
	start = get_ticks();
	AES_set_encrypt_key (ctr_key, 128, &key);
	memcpy (buf_iv, ctr_iv, 16);
	memset (tmp, 0, 16);
	n = 0;
	AES_ctr128_encrypt ((const unsigned char *) ctr_ct, buf, sizeof(ctr_ct), &key, buf_iv, tmp, &n);
	stop = get_ticks();
	print_data ("ctr_key  : ", ctr_key, "\n");
	print_data ("ctr_iv   : ", ctr_iv, " <- initial\n");
	print_data ("ctr_iv   : ", buf_iv, " <- final\n");
	print_data ("ctr_ct   : ", ctr_ct, "\n");
	print_data ("         : ", ctr_ct + 16, "\n");
//	print_data ("ctr_pt   : ", ctr_pt, "\n");
//	print_data ("         : ", ctr_pt + 16, " <- expected\n");
	print_data ("ctr_pt   : ", buf, "\n");
	print_data ("         : ", buf + 16, memcmp (buf, ctr_pt, sizeof(ctr_pt)) ? " <- FAILED !!!\n" : " <- pass\n");
//	printf ("Runtime  : %d usec\n", ticks_delta_to_usec (stop - start));
	printf ("\n");

#endif

	/*********************************************************************
	*********************************************************************/

#if defined (CONFIG_STB225)

#if 0
#define SHA1SUM_SHOW(addr,len)	sha1sum_display ((addr),(len))
#else
#define SHA1SUM_SHOW(addr,len)	do { } while (0)
#endif

	/*
	   Encrypt + decrypt the beginning of SDRAM and hope nothing breaks...
	*/

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES ECB performance\n");
	printf ("--------------------------------------------------------------------\n");

	len = 1024 * 1024;
	data = (unsigned char *) CFG_SDRAM_BASE;

	SHA1SUM_SHOW(data, len);

	start = get_ticks();
	memset (buf, 0x11, 16);
	memset (buf_iv, 0x22, 16);
	AES_set_encrypt_key (buf, 128, &key);
	for (i = 0; i < len; i += 16)
		AES_encrypt ((const unsigned char *) (data + i), (data + i), &key);
	stop = get_ticks();

	printf ("Encrypt DRAM: %d bytes in %d usec (%d kbps)\n", len,
		ticks_delta_to_usec (stop - start), ticks_delta_to_kbps ((stop - start), len));

	SHA1SUM_SHOW(data, len);

	start = get_ticks();
	memset (buf, 0x11, 16);
	memset (buf_iv, 0x22, 16);
	AES_set_decrypt_key (buf, 128, &key);
	for (i = 0; i < len; i += 16)
		AES_decrypt ((const unsigned char *) (data + i), (data + i), &key);
	stop = get_ticks();

	printf ("Decrypt DRAM: %d bytes in %d usec (%d kbps)\n", len,
		ticks_delta_to_usec (stop - start), ticks_delta_to_kbps ((stop - start), len));

	SHA1SUM_SHOW(data, len);

	printf ("\n");

	/*********************************************************************
	*********************************************************************/

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES CBC performance\n");
	printf ("--------------------------------------------------------------------\n");

	len = 1024 * 1024;
	data = (unsigned char *) CFG_SDRAM_BASE;

	SHA1SUM_SHOW(data, len);

	start = get_ticks();
	memset (buf, 0x11, 16);
	memset (buf_iv, 0x22, 16);
	AES_set_encrypt_key (buf, 128, &key);
	AES_cbc_encrypt ((const unsigned char *) data, data, len, &key, buf_iv, AES_ENCRYPT);
	stop = get_ticks();

	printf ("Encrypt DRAM: %d bytes in %d usec (%d kbps)\n", len,
		ticks_delta_to_usec (stop - start), ticks_delta_to_kbps ((stop - start), len));

	SHA1SUM_SHOW(data, len);

	start = get_ticks();
	memset (buf, 0x11, 16);
	memset (buf_iv, 0x22, 16);
	AES_set_decrypt_key (buf, 128, &key);
	AES_cbc_encrypt ((const unsigned char *) data, data, len, &key, buf_iv, AES_DECRYPT);
	stop = get_ticks();

	printf ("Decrypt DRAM: %d bytes in %d usec (%d kbps)\n", len,
		ticks_delta_to_usec (stop - start), ticks_delta_to_kbps ((stop - start), len));

	SHA1SUM_SHOW(data, len);

	printf ("\n");

	/*********************************************************************
	*********************************************************************/

#if defined (ENABLE_CTR_MODE)

	printf ("--------------------------------------------------------------------\n");
	printf ("-- AES CTR performance\n");
	printf ("--------------------------------------------------------------------\n");

	len = 1024 * 1024;
	data = (unsigned char *) CFG_SDRAM_BASE;

	SHA1SUM_SHOW(data, len);

	start = get_ticks();
	memset (buf, 0x11, 16);
	memset (buf_iv, 0x00, 16);
	memset (buf_iv, 0x22, 12);
	AES_set_encrypt_key (buf, 128, &key);
	memset (tmp, 0, 16);
	n = 0;
	AES_ctr128_encrypt ((const unsigned char *) data, data, len, &key, buf_iv, tmp, &n);
	stop = get_ticks();

	printf ("Encrypt DRAM: %d bytes in %d usec (%d kbps)\n", len,
		ticks_delta_to_usec (stop - start), ticks_delta_to_kbps ((stop - start), len));

	SHA1SUM_SHOW(data, len);

	start = get_ticks();
	memset (buf, 0x11, 16);
	memset (buf_iv, 0x00, 16);
	memset (buf_iv, 0x22, 12);
	AES_set_encrypt_key (buf, 128, &key);
	memset (tmp, 0, 16);
	n = 0;
	AES_ctr128_encrypt ((const unsigned char *) data, data, len, &key, buf_iv, tmp, &n);
	stop = get_ticks();

	printf ("Decrypt DRAM: %d bytes in %d usec (%d kbps)\n", len,
		ticks_delta_to_usec (stop - start), ticks_delta_to_kbps ((stop - start), len));

	SHA1SUM_SHOW(data, len);

	printf ("\n");

#endif

#endif

	return 0;
}

U_BOOT_CMD(
	st_aes, 1, 1, (int (*)(struct cmd_tbl_s *, int, int, char *[])) selftest_aes,
	"st_aes  - run AES selftest\n",
	" - run AES selftest\n"
);

/*****************************************************************************
*****************************************************************************/
#endif
/*****************************************************************************
*****************************************************************************/

