TMC32_QJB/App/crypto.c
2026-04-30 16:23:12 +08:00

314 lines
8.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
******************************************************************************
* @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>&copy; 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************************************/