SMEC98SP加密晶片對Arduino Mega 2560方案的保護
Arduino Mega 2560操作SMEC98SP加密晶片的事例程式碼,如果需要完整程式碼(包括加密晶片程式碼),請到中巨偉業服務與支援下載
#include “smec98sp.h” #include “iic_smec98sp.h” void PrintHex(unsigned char *str,unsigned int len) { unsigned int i; for(i=0;i<len;i++) { Serial.print(*str++,HEX); } Serial.print("\r\n");
}
/* 1.獲取SMEC98SP的UID號, 獲取STM32的ID, 獲取STM32隨機數 2.驗證PIN 3.內外部認證 4.SHA1=>前置資料^隨機數 5.密文讀 6.讀資料 7.寫資料 8.構造演算法(PA口資料->密文送加密晶片, 密文返回)
如果直接引用,請將print的除錯資訊去除 */ void SMEC_Test(void) { /*各種金鑰,不會在I2C線路上傳輸,可以使用同一組.應該將金鑰分散儲存,防止主控晶片被破解後,被攻擊者在二進位制碼中找到金鑰 */ unsigned char InternalKey[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F };//內部認證金鑰,必須和SMEC98SP一致 unsigned char ExternalKey[16] = { 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F };//外部認證金鑰,必須和SMEC98SP一致 unsigned char SHA1_Key[16] = { 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F }; //雜湊演算法認證金鑰,必須和SMEC98SP一致 unsigned char MKey[16] = { 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F }; //主控金鑰,用於產生過程金鑰,必須和SMEC98SP一致
unsigned char Pin[8] = { 0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc }; //Pin認證金鑰,必須和SMEC98SP一致
unsigned char bSmec98spUid[12] = { 0 }; //存放SMEC98SP的UID unsigned short RandomSeek = 0; //隨機數種子 unsigned char bRandom[8] = { 0 }; //存放隨機數 unsigned char bSessionKey[8] = { 0 }; //存放過程金鑰,過程金鑰為臨時產生的金鑰 unsigned char bDataBuf[64] = { 0 }; unsigned char ret, bLen; unsigned short i, j;
/獲取SMEC98SP的UID/ ret = SMEC_GetUid(bSmec98spUid); if(ret) { Serial.print(“SMEC_GetUid -> Error !\r\n”); while(1); } Serial.print("SMEC_GetUid: "); PrintHex(bSmec98spUid,12);
/取加密晶片的隨機數,作為MCU的RandomSeek因子,也可以用其他外部因素,如按鍵等待時間等/ if(SMEC_GetRandom(bDataBuf))//獲取8位元組隨機數 { Serial.print(“SMEC_GetRandom -> Error !\r\n”); while(1); } for(i = 0; i < 4; i += 2) { /使RandomSeek與加密晶片隨機數有關/ j = (bDataBuf[i] << 8) + bDataBuf[i + 1]; RandomSeek ^= j; } for(i = 0; i < 6; i += 2) { /使RandomSeek與SMEC98SP的UID相關,使得即使相同狀況下,不同的加密晶片,RandomSeek值也不一樣/ j = (bSmec98spUid[i] << 8) + bSmec98spUid[i + 1]; RandomSeek ^= j; } srand(RandomSeek); Serial.print(“RandomSeek:”); PrintHex((unsigned char *)&RandomSeek, 2);
/PIN碼驗證/ ret = SMEC_CheckPin(Pin, (unsigned char)sizeof(Pin)); if(ret) { Serial.print(“SMEC_CheckPin -> Error !\r\n”); while(1); } Serial.print(“SMEC_CheckPin OK !\r\n”);
/內部認證, 主控晶片對SMEC98SP加密晶片合法性判斷/ for(i = 0; i < 8; i ++) { bRandom[i] = (unsigned char) rand(); } ret = SMEC_IntrAuth(InternalKey, bRandom); if(ret) { Serial.print(“SMEC_IntrAuth -> Error !\r\n”); while(1); } Serial.print(“SMEC_IntrAuth OK !\r\n”);
/外部認證, SMEC98SP加密晶片對主控晶片合法性判斷/ ret = SMEC_ExtrAuth(ExternalKey); if(ret) { Serial.print(“SMEC_ExtrAuth -> Error !\r\n”); while(1); } Serial.print(“SMEC_ExtrAuth OK !\r\n”);
/SHA1摘要演算法認證, 資料長度可自己設定/ for(i = 0; i < 16; i ++) { bDataBuf[i] = (unsigned char) rand(); } ret = SMEC_Sha1Auth(SHA1_Key, (unsigned char)sizeof(SHA1_Key), bDataBuf, 16); if(ret) { Serial.print(“SMEC_Sha1Auth -> Error !\r\n”); while(1); } Serial.print(“SMEC_Sha1Auth OK !\r\n”);
/呼叫加密晶片內部計算圓周長演算法/ bDataBuf[0] = 0x02; ret = SMEC_CircleAlg(bDataBuf, 1, bDataBuf, &bLen); if(ret) { Serial.print(“SMEC_CircleAlg -> Error !\r\n”); while(1); } Serial.print("SMEC_CircleAlg OK, C = "); PrintHex(bDataBuf, 1);
/產生過程金鑰,用於後續的Flash資料加密讀,及構造的"埠資料運算"/ for(i = 0; i < 8; i ++) { bRandom[i] = (unsigned char) rand(); } ret = SMEC_GenSessionKey(MKey, bRandom, bSessionKey); if(ret) { Serial.print(“SMEC_GenSessionKey -> Error !\r\n”); while(1); } Serial.print(“SMEC_GenSessionKey OK !\r\n”);
/密文讀取Flash資料/ ret = SMEC_CryptReadFlash(bSessionKey, 0x0000, bDataBuf, 16); if(ret) { Serial.print(“SMEC_CryptReadFlash -> Error !\r\n”); while(1); } Serial.print(“SMEC_CryptReadFlash OK:\r\n”); PrintHex(bDataBuf, 16);
/讀取Flash資料/ ret = SMEC_ReadFlash(0x0000, bDataBuf, 16); if(ret) { Serial.print(“SMEC_ReadFlash -> Error !\r\n”); while(1); } Serial.print(“SMEC_ReadFlash OK:\r\n”); PrintHex(bDataBuf, 16);
/寫Flash資料/ for(i = 0; i < 16; i ++) { bDataBuf[i] = (unsigned char) i; } ret = SMEC_WriteFlash(0x0000, bDataBuf, 16); if(ret) { Serial.print(“SMEC_WriteFlash -> Error !\r\n”); while(1); } Serial.print(“SMEC_WriteFlash OK!\r\n”);
/構造"埠資料運算", 可以用實際的PA~PC埠資料/ bDataBuf[0] = 0x00; bDataBuf[1] = 0x00; ret = SMEC_GpioAlg(bSessionKey, bDataBuf,2, bDataBuf); if(ret) { Serial.print(“SMEC_GpioAlg -> Error !\r\n”); while(1); } Serial.print(“SMEC_GpioAlg OK:\r\n”); PrintHex(bDataBuf, 2);
/呼叫加密晶片內部計算圓周長演算法,並密文線上路上傳輸/ bDataBuf[0] = 0x02; ret = SMEC_CircleAlgCrypt(bSessionKey, bDataBuf, 1, bDataBuf, &bLen); if(ret) { Serial.print(“SMEC_CircleAlgCrypt -> Error !\r\n”); while(1); } Serial.print("SMEC_CircleAlgCrypt OK, C = "); PrintHex(bDataBuf, 1); }
void setup() { Serial.begin(115200); SMEC_I2cInit(); }
void loop() { SMEC_Test(); delay(200); }