#include "sr_sunrise.h"

/**********CRC 示例*************************/
static uint8_t data[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f};
static void _CrcCheckTest(SR_CRC_TYPE_E type)
{
	uint32_t result = 0;
	SR_CrcCheck(type, data, sizeof(data), &result);
	SR_LOG(INFO, "[CRC] type: %d result: 0x%X \r\n", type, result);
}
static int CrcExample(int argc, char *argv[])
{

	_CrcCheckTest(CRC4_ITU);
	_CrcCheckTest(CRC5_EPC);
	_CrcCheckTest(CRC5_ITU);
	_CrcCheckTest(CRC5_USB);
	_CrcCheckTest(CRC6_ITU);
	_CrcCheckTest(CRC7_MMC);
	_CrcCheckTest(CRC8);
	_CrcCheckTest(CRC8_ITU);
	_CrcCheckTest(CRC8_ROHC);
	_CrcCheckTest(CRC8_MAXIM);
	_CrcCheckTest(CRC16_IBM);
	_CrcCheckTest(CRC16_MAXIM);
	_CrcCheckTest(CRC16_USB);
	_CrcCheckTest(CRC16_MODBUS);
	_CrcCheckTest(CRC16_CCITT);
	_CrcCheckTest(CRC16_CCITT_FALSE);
	_CrcCheckTest(CRC16_X25);
	_CrcCheckTest(CRC16_XMODEM);
	_CrcCheckTest(CRC16_DNP);
	_CrcCheckTest(CRC32);
	_CrcCheckTest(CRC32_MPEG2);

	return 0;
}
SR_SHELL_CMD_EXPORT(crc_exmp, CrcExample);

/**********AES 示例*************************/
static char plainTxt[64] = "73AF9252.DEV0001_DF66664C20EC44DE9B7377E2A2A58EC5";
static uint8_t deviceKey[16] = {0xB8, 0xC4, 0xF7, 0x46, 0x5A, 0xD2, 0x6C, 0xE3, 0xBC, 0x77, 0xE8, 0x98, 0xD9, 0x6E, 0xA7, 0x5C};

static unsigned char iv[16] = // 128-bit AES IV
	{
		0x3b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
		0xeb, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};

static int _AesTest(SR_AES_TYPE_E type, uint8_t *key, uint16_t keyBit, uint8_t *iv)
{
	uint8_t encText[128];
	uint8_t decText[128];
	int oLen = 0;
	int i;

	// AES 加密
	SR_LOG(INFO, "AES type: %d", type);
	oLen = SR_AesEncrypt(type, key, keyBit, iv, plainTxt, strlen(plainTxt), encText);
	SR_LOG(INFO, "加密，oLen=%d:", oLen);
	if (oLen > 0)
	{
		for (int i = 0; i < oLen; i++)
		{
			SR_LOG(INFO,"%02x ", encText[i]);
		}
		SR_LOG(INFO, "\r\n");
	}

	// AES 解密
	oLen = SR_AesDecrypt(type, key, keyBit, iv, encText, oLen, decText);
	SR_LOG(INFO, "解密，oLen=%d:", oLen);
	if (oLen > 0)
	{
		for (int i = 0; i < oLen; i++)
		{
			SR_LOG(INFO,"%c ", decText[i]);
		}
		SR_LOG(INFO, "\r\n");
	}

	return 0;
}

static int AesExample(int argc, char *argv[])
{
	int i = 0;
	SR_LOG(INFO, "原始明文 len(%d): %s\r\n", strlen(plainTxt), plainTxt);

	_AesTest(SR_AES_ECB128, deviceKey, 128, 0); // AES_ECB不需要iv
	_AesTest(SR_AES_CBC128, deviceKey, 128, iv);
	_AesTest(SR_AES_CTR128, deviceKey, 128, iv);

	return 0;
}
SR_SHELL_CMD_EXPORT(aes_exmp, AesExample);

/**********MD5 示例*************************/
// 少量数据场景
static void _HashTest(SR_HASH_TYPE_E type)
{
	uint8_t out[64] = {0};
	int ret, i, oLen = 0;
	SR_HASH_CTX_T hashCtx;

	SR_LOG(INFO, "Hash type: %d:", type);

	// 启动
	ret = SR_HashStart(&hashCtx, type);
	if (ret != 0)
	{
		SR_LOG(INFO, "HashStart err");
		return;
	}

	// 更新
	ret = SR_HashUpdate(&hashCtx, plainTxt, strlen(plainTxt));
	if (ret != 0)
	{
		SR_LOG(INFO, "HashUpdate err");
		return;
	}

	// 完成
	oLen = SR_HashFinish(&hashCtx, out);
	if (oLen > 0)
	{
		for (int i = 0; i < oLen; i++)
		{
			SR_LOG(INFO,"%02x ", out[i]);
		}
		SR_LOG(INFO, "\r\n");
	}
	else
	{
		SR_LOG(INFO, "HashFinish err");
		return;
	}
}

// 大量数据场景，如文件、flash
static void _HashTest2(SR_HASH_TYPE_E type)
{
	uint8_t out[64] = {0};
	int ret, i, oLen = 0, k, r;
	SR_HASH_CTX_T hashCtx;

	SR_LOG(INFO, "Hash type: %d:", type);

	// 启动
	ret = SR_HashStart(&hashCtx, type);
	if (ret != 0)
	{
		SR_LOG(INFO, "HashStart err");
		return;
	}

	// 更新。每次最多输入16字节
	k = strlen(plainTxt) / 16;
	r = strlen(plainTxt) % 16;
	for (i = 0; i < k; i++)
	{
		ret = SR_HashUpdate(&hashCtx, &plainTxt[i * 16], 16);
		if (ret != 0)
		{
			SR_LOG(INFO, "HashUpdate err");
			return;
		}
	}
	ret = SR_HashUpdate(&hashCtx, &plainTxt[k * 16], r); // 输入剩余数据
	if (ret != 0)
	{
		SR_LOG(INFO, "HashUpdate last err");
		return;
	}

	// 完成
	oLen = SR_HashFinish(&hashCtx, out);

	if (oLen > 0)
	{
		for (int i = 0; i < oLen; i++)
		{
			SR_LOG(INFO,"%02x ", out[i]);
		}
		SR_LOG(INFO, "\r\n");
	}
	else
	{
		SR_LOG(INFO, "HashFinish err");
		return;
	}
}

static int HashExample(int argc, char *argv[])
{
	SR_LOG(INFO, "原始明文: %s\r\n", plainTxt);

	_HashTest(SR_MD5);
	_HashTest2(SR_MD5);
	_HashTest(SR_SHA256);
	_HashTest2(SR_SHA256);
	_HashTest(SR_SHA224);
	_HashTest2(SR_SHA224);

	_HashTest(SR_SHA512);
	_HashTest2(SR_SHA512);
	_HashTest(SR_SHA384);
	_HashTest2(SR_SHA384);
}
SR_SHELL_CMD_EXPORT(hash_exmp, HashExample);
