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************************************/
|