314 lines
8.7 KiB
C
314 lines
8.7 KiB
C
/**
|
||
******************************************************************************
|
||
* @file crypto.c
|
||
* @author TMS Scan Team
|
||
* @version
|
||
* @date 2020-04-17
|
||
* @brief
|
||
******************************************************************************
|
||
*
|
||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||
* TIME. AS A RESULT, TMC SHALL NOT BE HELD LIABLE FOR ANY
|
||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||
*
|
||
* <h2><center>© COPYRIGHT 2020 TMS</center></h2>
|
||
******************************************************************************
|
||
**/
|
||
|
||
/********************************End of Head************************************/
|
||
#include "global.h"
|
||
|
||
uint16_t CRC_Calculate(uint8_t * inputData,uint16_t len)
|
||
{
|
||
uint16_t result;
|
||
|
||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_CRC, ENABLE); //crc clock
|
||
|
||
CRC->CON1 = 0x08;
|
||
result = CRC->DAT;
|
||
result = CRC->DAT;
|
||
while(len)
|
||
{
|
||
CRC->DAT = *inputData;
|
||
inputData++;
|
||
len--;
|
||
}
|
||
result = CRC->DAT << 8;
|
||
result += CRC->DAT;
|
||
return result;
|
||
}
|
||
|
||
|
||
uint8_t initKey(void)
|
||
{
|
||
uint32_t i;
|
||
CIPHER_KEY *keyAddrPageA;
|
||
CIPHER_KEY *keyAddrPageB;
|
||
uint16_t crcA, crcB;
|
||
uint16_t snA, snB;
|
||
memset((uint8_t *)(&gKeyCache), 0, KEY_STEP_LEN);
|
||
|
||
for(i = 0; i < gCurrentSysCfg->keyNum; i++)
|
||
{
|
||
keyAddrPageA = (CIPHER_KEY *)(KEY_BASE_ADDR + KEY_STEP_LEN * i * 2);
|
||
keyAddrPageB = (CIPHER_KEY *)(KEY_BASE_ADDR + KEY_STEP_LEN * i * 2 + KEY_STEP_LEN);
|
||
crcA = CRC_Calculate((uint8_t *) keyAddrPageA + 2, KEY_CRC_LEN);
|
||
crcB = CRC_Calculate((uint8_t *) keyAddrPageB + 2, KEY_CRC_LEN);
|
||
snA = keyAddrPageA->keySN;
|
||
snB = keyAddrPageB->keySN;
|
||
|
||
if((crcA == keyAddrPageA->keyCRC) && (crcB == keyAddrPageB->keyCRC)) //检验都正确
|
||
{
|
||
//标记最新页
|
||
if(snA == snB + 1)
|
||
{
|
||
gKeyAddr[i] = (uint32_t)keyAddrPageA;
|
||
}
|
||
else if(snB == snA + 1)
|
||
{
|
||
gKeyAddr[i] = (uint32_t)keyAddrPageB;
|
||
}
|
||
else
|
||
{
|
||
// 异常流程,清除CRC和SN
|
||
if(FLASH_Update((uint32_t)keyAddrPageA, (uint8_t *)(&gKeyCache), FLASH_SECTOR_SIZE * 2) != 0)
|
||
{
|
||
return WRERROR;
|
||
}
|
||
|
||
if(FLASH_Update((uint32_t)keyAddrPageB, (uint8_t *)(&gKeyCache), FLASH_SECTOR_SIZE * 2) != 0)
|
||
{
|
||
return WRERROR;
|
||
}
|
||
|
||
gKeyAddr[i] = (uint32_t)keyAddrPageB;
|
||
}
|
||
}
|
||
else if(crcA == keyAddrPageA->keyCRC) //A备份正确
|
||
{
|
||
gKeyAddr[i] = (uint32_t)keyAddrPageA;
|
||
}
|
||
else if(crcB == keyAddrPageB->keyCRC)
|
||
{
|
||
gKeyAddr[i] = (uint32_t)keyAddrPageB;
|
||
}
|
||
else
|
||
{
|
||
// 异常流程,清除CRC和SN
|
||
if(FLASH_Update((uint32_t)keyAddrPageA, (uint8_t *)(&gKeyCache), FLASH_SECTOR_SIZE * 2) != 0)
|
||
{
|
||
return WRERROR;
|
||
}
|
||
|
||
if(FLASH_Update((uint32_t)keyAddrPageB, (uint8_t *)(&gKeyCache), FLASH_SECTOR_SIZE * 2) != 0)
|
||
{
|
||
return WRERROR;
|
||
}
|
||
|
||
gKeyAddr[i] = (uint32_t)keyAddrPageB;
|
||
}
|
||
}
|
||
|
||
return TMC_OK;
|
||
}
|
||
|
||
/**
|
||
* @function AppCryptoInit
|
||
* @brief 加解密模块初始化
|
||
* @param[in] 无
|
||
* @return 无
|
||
*/
|
||
void AppCryptoInit(void)
|
||
{
|
||
RCC_Security2PeriphClockCmd(RCC_SEC2Periph_FLASH,ENABLE);
|
||
RCC_Security1PeriphClockCmd(RCC_SEC1Periph_TRNG, ENABLE); //随机数函数存放在ROM内 使用前需要打开门控时钟
|
||
RCC_Security1PeriphClockCmd(RCC_SEC1Periph_PKE, ENABLE); //非对称算法库在ROM内掩摸 使用前需打开门控时钟
|
||
pkeConfig(0xFF,0x0F,0x01); //PKE初始化函数
|
||
initKey();
|
||
}
|
||
|
||
uint16_t encryptData(uint8_t *pInputData, uint8_t *pOutputData, uint16_t inLen)
|
||
{
|
||
BarData encrypt;
|
||
uint8_t *pTempData = (uint8_t *) MIDOUTBUF;
|
||
uint16_t dataLen = 0, offset = 0, i, remainder, pkcs, outoffset = 0, outoffs = 0, templen;
|
||
uint8_t *pData = (uint8_t *)pInputData;
|
||
|
||
outoffs = SETCODELEN_MODULE;
|
||
|
||
encrypt.bartype = QR_Id;
|
||
switch(gCurrentSysCfg->cryptoType)
|
||
{
|
||
case SM2_CRYPTO:
|
||
pTempData[outoffs++] = gCurrentSysCfg->keyId;
|
||
pTempData[outoffs++] = 0; //加密
|
||
pTempData[outoffs++] = (uint8_t) inLen;
|
||
pTempData[outoffs++] = (uint8_t) (inLen >> 8);
|
||
memcpy(&pTempData[outoffs], pInputData, inLen);
|
||
outoffs += inLen;
|
||
encrypt.datalen = outoffs;
|
||
encrypt.bardata = pTempData;
|
||
if(SM2_Oper(&encrypt) == TMC_OK)
|
||
{
|
||
memcpy(pOutputData, &encrypt.bardata[SETCODELEN_MODULE + CRYPTO_CMD_OFFS], encrypt.datalen);
|
||
return encrypt.datalen;
|
||
}
|
||
break;
|
||
|
||
case SM3_CRYPTO:
|
||
pTempData[outoffs++] = 0;
|
||
pTempData[outoffs++] = 0; //加密
|
||
pTempData[outoffs++] = (uint8_t) inLen;
|
||
pTempData[outoffs++] = (uint8_t) (inLen >> 8);
|
||
memcpy(&pTempData[outoffs], pInputData, inLen);
|
||
outoffs += inLen;
|
||
encrypt.datalen = outoffs;
|
||
encrypt.bardata = pTempData;
|
||
if(SM3_Oper(&encrypt) == TMC_OK)
|
||
{
|
||
memcpy(pOutputData, &encrypt.bardata[SETCODELEN_MODULE + CRYPTO_CMD_OFFS], encrypt.datalen);
|
||
return encrypt.datalen;
|
||
}
|
||
break;
|
||
|
||
case SM4_CRYPTO:
|
||
memcpy(&pData[dataLen], pInputData, inLen);
|
||
dataLen += inLen;
|
||
remainder = dataLen % SYM_GROUP_LEN;
|
||
pkcs = SYM_GROUP_LEN - remainder;
|
||
|
||
for(i = 0; i < (SYM_GROUP_LEN - remainder); i++)
|
||
{
|
||
pData[dataLen++] = pkcs;
|
||
}
|
||
|
||
while(dataLen > 0)
|
||
{
|
||
pTempData = (uint8_t *) MIDOUTBUF;
|
||
outoffs = SETCODELEN_MODULE;
|
||
pTempData[outoffs++] = gCurrentSysCfg->keyId;
|
||
pTempData[outoffs++] = 0; //加密
|
||
pTempData[outoffs++] = (uint8_t) SYM_GROUP_LEN;
|
||
pTempData[outoffs++] = (uint8_t) (SYM_GROUP_LEN >> 8);
|
||
memcpy(&pTempData[outoffs], pInputData + offset, SYM_GROUP_LEN);
|
||
outoffs += SYM_GROUP_LEN;
|
||
encrypt.datalen = outoffs;
|
||
encrypt.bardata = pTempData;
|
||
if(SM4_Oper(&encrypt) == TMC_OK)
|
||
{
|
||
memcpy(pOutputData + offset, &encrypt.bardata[SETCODELEN_MODULE + CRYPTO_CMD_OFFS], encrypt.datalen);
|
||
offset += SYM_GROUP_LEN;
|
||
dataLen -= SYM_GROUP_LEN;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
return offset;
|
||
|
||
case RSA_1024:
|
||
dataLen = inLen;
|
||
while(dataLen > 0)
|
||
{
|
||
templen = (dataLen > RSA1024_KEY_LEN) ? RSA1024_KEY_LEN : dataLen;
|
||
pTempData = (uint8_t *) MIDOUTBUF;
|
||
outoffs = SETCODELEN_MODULE;
|
||
pTempData[outoffs++] = gCurrentSysCfg->keyId;
|
||
pTempData[outoffs++] = 0; //加密
|
||
pTempData[outoffs++] = (uint8_t) templen;
|
||
pTempData[outoffs++] = (uint8_t) (templen >> 8);
|
||
memcpy(&pTempData[outoffs], pInputData + offset, templen);
|
||
outoffs += templen;
|
||
encrypt.datalen = outoffs;
|
||
encrypt.bardata = pTempData;
|
||
if(RSA_Oper(&encrypt) == TMC_OK)
|
||
{
|
||
memcpy(pOutputData + outoffset, &encrypt.bardata[SETCODELEN_MODULE + CRYPTO_CMD_OFFS], encrypt.datalen);
|
||
outoffset += encrypt.datalen;
|
||
offset += templen;
|
||
dataLen -= templen;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
return outoffset;
|
||
case RSA_2048:
|
||
dataLen = inLen;
|
||
while(dataLen > 0)
|
||
{
|
||
templen = (dataLen > RSA2048_KEY_LEN) ? RSA2048_KEY_LEN : dataLen;
|
||
pTempData = (uint8_t *) MIDOUTBUF;
|
||
outoffs = SETCODELEN_MODULE;
|
||
pTempData[outoffs++] = gCurrentSysCfg->keyId;
|
||
pTempData[outoffs++] = 0x80; //2048加密
|
||
pTempData[outoffs++] = (uint8_t) templen;
|
||
pTempData[outoffs++] = (uint8_t) (templen >> 8);
|
||
memcpy(&pTempData[outoffs], pInputData + offset, templen);
|
||
outoffs += templen;
|
||
encrypt.datalen = outoffs;
|
||
encrypt.bardata = pTempData;
|
||
if(RSA_Oper(&encrypt) == TMC_OK)
|
||
{
|
||
memcpy(pOutputData + outoffset, &encrypt.bardata[SETCODELEN_MODULE + CRYPTO_CMD_OFFS], encrypt.datalen);
|
||
outoffset += encrypt.datalen;
|
||
offset += templen;
|
||
dataLen -= templen;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
return outoffset;
|
||
|
||
case DES3:
|
||
memcpy(&pData[dataLen], pInputData, inLen);
|
||
dataLen += inLen;
|
||
remainder = dataLen % DES_GROUP_LEN;
|
||
pkcs = DES_GROUP_LEN - remainder;
|
||
|
||
for(i = 0; i < (DES_GROUP_LEN - remainder); i++)
|
||
{
|
||
pData[dataLen++] = pkcs;
|
||
}
|
||
|
||
while(dataLen > 0)
|
||
{
|
||
pTempData = (uint8_t *) MIDOUTBUF;
|
||
outoffs = SETCODELEN_MODULE;
|
||
pTempData[outoffs++] = gCurrentSysCfg->keyId;
|
||
pTempData[outoffs++] = 0x30; //加密
|
||
pTempData[outoffs++] = (uint8_t) DES_GROUP_LEN;
|
||
pTempData[outoffs++] = (uint8_t) (DES_GROUP_LEN >> 8);
|
||
memcpy(&pTempData[outoffs], pInputData + offset, DES_GROUP_LEN);
|
||
outoffs += DES_GROUP_LEN;
|
||
encrypt.datalen = outoffs;
|
||
encrypt.bardata = pTempData;
|
||
if(DES_Oper(&encrypt) == TMC_OK)
|
||
{
|
||
memcpy(pOutputData + offset, &encrypt.bardata[SETCODELEN_MODULE + CRYPTO_CMD_OFFS], encrypt.datalen);
|
||
offset += DES_GROUP_LEN;
|
||
dataLen -= DES_GROUP_LEN;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
return offset;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/********************************End of File************************************/
|