一、伽罗瓦计数器模式(GCM)
计算消息验证码的加密模式
1、SKE_GCM_TEST_VECTOR结构解析
//GCM模式测试容器结构
//uint32_t aes_128_gcm_test()
typedef struct {
//SKE_ALG_AES_128 5,定义在ske_basic.h
SKE_ALG alg;
//std_gcm_plain
//常量明文数组,256字节数据
//const uint8_t std_gcm_plain[256] = {
0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a, 0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55,
0xB4,0xD1,0x4B,0x82,0xE0,0x03,0xCA,0x48,0x4C,0x28,0x1B,0x5D,0x4D,0x9B,0xBC,0x29,
0xF3,0x61,0xD1,0x61,0x79,0x36,0xF5,0x3E,0x37,0xEF,0x97,0x73,0xB3,0x31,0x8C,0x8C,
0x4E,0xCB,0x31,0x9E,0x26,0x4D,0xF6,0x29,0xBE,0x8C,0x41,0x1B,0xF5,0xC4,0xBE,0x45,
0x03,0x62,0x56,0xE4,0xD8,0x2F,0x64,0x5A,0x4D,0x0A,0xDF,0x44,0x55,0xB1,0x31,0xA1,
0x7B,0xC6,0x74,0x21,0x86,0xC4,0x2E,0x28,0x3A,0xA5,0xBA,0xD5,0x4A,0x18,0xEC,0x14,
0x3B,0xAF,0x1E,0x6C,0x85,0x7F,0x32,0xEC,0x5D,0x92,0xB1,0x96,0xCF,0x7E,0x31,0x13,
0x71,0xBD,0xA2,0xEA,0xE8,0xDF,0xD0,0x82,0xCF,0xEB,0x58,0x3A,0x41,0xCF,0xCE,0xAA,
0x78,0x0F,0xD1,0x7F,0xBA,0xE9,0x31,0xDE,0xF7,0x17,0xB4,0x5B,0xB8,0x6F,0x15,0xD6,
0x01,0xF5,0x44,0xFB,0xCC,0xB2,0x43,0x5F,0x80,0xE8,0x9D,0x6F,0x21,0x87,0x06,0x37,
0x86,0x01,0xEA,0x99,0x15,0x6E,0x8A,0x88,0xAA,0xED,0x8C,0xE6,0x14,0x2F,0xB6,0x65,
0xB6,0xEE,0xEB,0x6F,0x06,0xEA,0x9D,0x45,0xB0,0x14,0x04,0x00,0x59,0xB4,0x26,0x77,
0x32,0xD7,0x33,0xB2,0xF0,0x92,0xE8,0x5E,0x40,0xF2,0x21,0x04,0xC4,0xF0,0x9C,0x80,};
const uint8_t *std_plain;
//明文长度0-256
uint32_t c_bytes; //byte length of plaintext or ciphertext
//std_gcm_key,32字节
//const uint8_t std_gcm_key[32]= {
0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08,
0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08};
const uint8_t *key;
//0
uint16_t keyid;
//std_gcm_iv,可为任意长度(包括0)
//const uint8_t std_gcm_iv[12] = {
0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88};
const uint8_t *iv;
//IV值长度,由上可知12字节
uint32_t iv_bytes;
//std_aad-additional authentication data 额外的认证消息,可为任意长度(包括0)
//aad在GCM模式中仍然明文形式,实际上add可能包含网络协议中的地址和参数
//const uint8_t std_aad[33] = {
0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
0xab,0xad,0xda,0xd2,0x7C,0xA4,0x8E,0x82,0x99,0xFC,0x5A,0xD3,0xE9,0x08,0xB7,0x65,
0x1B,};
const uint8_t *aad;
//aad长度,长度可以自己拓展
uint32_t aad_bytes;
//std_aes128_gcm_cipher
//const uint8_t std_aes128_gcm_cipher[256] = {
0x42,0x83,0x1E,0xC2,0x21,0x77,0x74,0x24,0x4B,0x72,0x21,0xB7,0x84,0xD0,0xD4,0x9C,
0xE3,0xAA,0x21,0x2F,0x2C,0x02,0xA4,0xE0,0x35,0xC1,0x7E,0x23,0x29,0xAC,0xA1,0x2E,
0x21,0xD5,0x14,0xB2,0x54,0x66,0x93,0x1C,0x7D,0x8F,0x6A,0x5A,0xAC,0x84,0xAA,0x05,
0x1B,0xA3,0x0B,0x39,0x6A,0x0A,0xAC,0x97,0x3D,0x58,0xE0,0x91,0x47,0x3F,0x59,0x85,
0x69,0x79,0x2C,0x46,0x2E,0xF1,0x7B,0xB9,0xF4,0x81,0xE4,0x14,0x87,0xBB,0x37,0x48,
0xE5,0xB9,0x25,0x90,0xBA,0xFF,0xD2,0x01,0x14,0x38,0xCF,0x6F,0x70,0x42,0x68,0xED,
0xBE,0xD5,0x6D,0x21,0x83,0x62,0xB6,0xDB,0xEE,0x80,0x46,0xDF,0xEA,0xF3,0xCF,0x34,
0xC2,0xDF,0xA2,0x51,0xB8,0x49,0xE7,0x2A,0xC9,0x80,0x75,0x72,0x53,0xAB,0xA6,0xF9,
0x85,0x10,0x89,0x90,0x6E,0xFF,0x8A,0x37,0x19,0xDC,0x8C,0x7E,0x0C,0x78,0xC9,0xD4,
0xFB,0x19,0xC2,0xEA,0xA7,0x3A,0xBA,0xD6,0xCF,0x41,0x49,0x42,0xF4,0x47,0x97,0x38,
0x03,0xD0,0xE4,0xFC,0x45,0x76,0x34,0x33,0xCE,0xAC,0xC6,0xBB,0x75,0xCD,0xE8,0x15,
0xF9,0xB3,0xAA,0xBE,0x1F,0x20,0x06,0xF7,0x84,0xFB,0x0A,0xD9,0x22,0x90,0x42,0xF6,
0xA5,0x46,0x40,0x05,0x56,0x23,0xEA,0xF1,0x2F,0x2C,0x59,0xCE,0x8E,0xD9,0xA8,0x85,
0xA8,0x93,0x54,0xBA,0x6F,0x1D,0x39,0x9F,0xE1,0x0F,0x69,0xDE,0x94,0xB6,0x13,0x5F,
0x06,0x73,0x95,0x9E,0x8F,0xFC,0x47,0xE3,0x47,0x95,0x79,0x33,0x1C,0xF7,0x0C,0xE4,
0x83,0x47,0x09,0x6B,0x67,0xF5,0x1E,0x4E,0x86,0x63,0x31,0x2E,0xCE,0xD5,0x38,0xEC,};
const uint8_t *std_cipher;
//标准消息认证码,pX对于明文长度X
const uint8_t std_aes128_gcm_mac_aad0_p256[] = {0x97,0x5A,0x7B,0x3E,0x2E,0x76,0x19,0x59,0x4E,0xFB,0x4A,0x12,0xB3,0x88,0xB3,0xD0};
const uint8_t std_aes128_gcm_mac_aad3_p201[] = {0xF0,0x0A,0x05,0xCF,0xD8,0x11,0x2B,0x6C,0x08,0x4B,0xAA,0xAC,0x06,0xEB,0xDB,0xAF};
const uint8_t std_aes128_gcm_mac_aad16_p120[] = {0x97,0x79,0x9F,0xA3,0xFC,0x35,0x41,0x33,0x41,0xA6,0x09,0xBC,0xCF,0x42,0x89,0xAF};
const uint8_t std_aes128_gcm_mac_aad17_p65[] = {0xD9,0x89,0xF7,0xFF,0xD8,0xED,0xD4,0x99,0x4B,0x1D,0x1D,0x54,0x00,0x7F,0x3F,0x7B};
const uint8_t std_aes128_gcm_mac_aad20_p32[] = {0xE1,0x3E,0x14,0x34,0x28,0x5A,0x94,0x26,0xAD,0xDF,0xBF,0xC2,0x70,0xD2,0x7F,0x16};
const uint8_t std_aes128_gcm_mac_aad32_p15[] = {0x09,0x24,0xCA,0x52,0xC7,0x81,0x92,0x2E,0xC5,0x3B,0x9F,0x55,0x8F,0xDB,0x6C,0x80};
const uint8_t std_aes128_gcm_mac_aad33_p0[] = {0x3C,0xBA,0x19,0x87,0x0D,0xFD,0x4D,0xDD,0x35,0x0F,0x6D,0xFB,0xF1,0x90,0xD7,0x4E};
const uint8_t *std_mac;
//消息认证码长度
std_aes128_gcm_mac_aad0_p256, 16
std_aes128_gcm_mac_aad3_p201, 13
std_aes128_gcm_mac_aad16_p120, 10
std_aes128_gcm_mac_aad17_p65, 9
std_aes128_gcm_mac_aad20_p32, 7
std_aes128_gcm_mac_aad32_p15, 4
std_aes128_gcm_mac_aad33_p0, 1
//测试发现Mac输出X均为16字节的前X字节
uint32_t mac_bytes;
}SKE_GCM_TEST_VECTOR;
uint32_t aes_128_gcm_test()
{
SKE_GCM_TEST_VECTOR vector[7] = {
{SKE_ALG_AES_128, std_gcm_plain, 256, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 0, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad0_p256, 16},
{SKE_ALG_AES_128, std_gcm_plain, 201, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 3, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad3_p201, 13},
{SKE_ALG_AES_128, std_gcm_plain, 120, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 16, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad16_p120, 10},
{SKE_ALG_AES_128, std_gcm_plain, 65, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 17, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad17_p65, 9},
{SKE_ALG_AES_128, std_gcm_plain, 32, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 20, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad20_p32, 7},
{SKE_ALG_AES_128, std_gcm_plain, 15, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 32, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad32_p15, 4},
{SKE_ALG_AES_128, std_gcm_plain, 0, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 33, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad33_p0, 1},
};
return ske_gcm_test_internal(vector, 7);
}
2、SKE_CCM_TEST_VECTOR结构解析
CCM(Counter-CBC-MAC)
typedef struct {
SKE_ALG alg;
//明文
const uint8_t *std_plain;
//明文的长度
uint32_t c_bytes; //byte length of plaintext or ciphertext
//std_CCM_Key,32字节,应该是子密钥
//《rfc4309》:AES必须支持128、可支持192、256bit密钥,AES-CCM使用CBC-MAC,并使用计数器模式
const uint8_t *key;
//0
uint16_t keyid;
//std_CCM_nonce,在指定上下文中只使用一次的值,字节长度是15-L
//const uint8_t std_ccm_nonce[]= {0xC7,0x2B,0x65,0x91,0xA0,0xD7,0xDE,0x8F,0x6B,0x40,0x72,0x33,0xAD,0x35,0x81,0xD6};
//《rfc4309》:该参数长度取决于L,数据长度为15-L字节,实现必须支持11字节
const uint8_t *nonce;
//从ske_lp.sdk代码上看,为最终需要的Mac的长度
//定义完整性检查值的大小-《rfc4309》,{4,6,8,10,12,14,16},为保证对齐并保证足够的安全性,只有是4的倍数且为8的值允许
//认证域的字节长度,即认证tag,有效值是在{4,6,8,10,12,14,16}中选取
//4-16分别对应最后std_mac数据长度
uint32_t M;
//表示长度字段的大小,CCM定义L在2-8,实现必须支持4字节的L值,可容纳一个完整的Jumbogram,长度包括ESP Padding、Pad Length、下一个头部字段,这规范仅支持L=4?-《rfc4309》
//长度域的长度,即消息字节长度占用的字节数,有效值在2-8(1个字节是保留值)
//代码截取Nonce的前15-L字节做Nonce
uint32_t L;
//std_aad-additional authentication data 额外的认证消息
//在CCM模式中,aad长度只能是7-13字节
const uint8_t *aad;
//验证数据长度
uint32_t aad_bytes;
//标准密钥
//在代码中这个参数长度对应原明文长度
const uint8_t *std_cipher;
//mac值
//std_aes128_ccm_mac_MX_L8_aad33_p0中的X代表该参数为X字节数据
//测试发现不同的X长度,输出的值完全不同,也不是16字节的前X部分
const uint8_t *std_mac;
}SKE_CCM_TEST_VECTOR;
二、分组密码链接-消息认证码-模式(CCM)
分组密码链接-消息认证码-CCM
//CCM模式测试容器结构
typedef struct {
//SKE_ALG_AES_128 5 定义在ske_basic.h
SKE_ALG alg;
//明文数据std_ccm_plain
const uint8_t std_ccm_plain[]= {0x81,0x70,0x99,0x44,0xE0,0xCB,0x2E,0x1D,0xB5,0xB0,0xA4,0x77,0xD1,0xA8,0x53,0x9B,
0x0A,0x87,0x86,0xE3,0x4E,0xAA,0xED,0x99,0x30,0x3E,0xA6,0x97,0x55,0x95,0xB2,0x45,
0x4D,0x5D,0x7F,0x91,0xEB,0xBD,0x4A,0xCD,0x72,0x6C,0x0E,0x0E,0x5E,0x3E,0xB5,0x5E,
0xF6,0xB1,0x5A,0x13,0x8E,0x22,0x6E,0xCD,0x1B,0x23,0x5A,0xB5,0xBB,0x52,0x51,0xC1,
0x33,0x76,0xB2,0x64,0x48,0xA9,0xAC,0x1D,0xE8,0xBD,0x52,0x64,0x8C,0x0B,0x5F,0xFA,
0x94,0x44,0x86,0x82,0xE3,0xCB,0x4D,0xE9,0xCB,0x8A,0xE7,0xF4,0xBD,0x41,0x0E,0xD5,
0x02,0xB1,0x25,0x3A,0xD0,0x8B,0xB2,0x79,0x69,0xB5,0xF0,0x2B,0x10,0x02,0x9D,0x67,
0xD0,0x7E,0x18,0x64,0xD9,0x4D,0x4F,0xCA,0x20,0x81,0x51,0xE2,0x6F,0x5F,0xEE,0x26,
0x7B,0xC6,0x74,0x21,0x86,0xC4,0x2E,0x28,0x3A,0xA5,0xBA,0xD5,0x4A,0x18,0xEC,0x14,
0x3B,0xAF,0x1E,0x6C,0x85,0x7F,0x32,0xEC,0x5D,0x92,0xB1,0x96,0xCF,0x7E,0x31,0x13,
0x71,0xBD,0xA2,0xEA,0xE8,0xDF,0xD0,0x82,0xCF,0xEB,0x58,0x3A,0x41,0xCF,0xCE,0xAA,
0x78,0x0F,0xD1,0x7F,0xBA,0xE9,0x31,0xDE,0xF7,0x17,0xB4,0x5B,0xB8,0x6F,0x15,0xD6,
0x01,0xF5,0x44,0xFB,0xCC,0xB2,0x43,0x5F,0x80,0xE8,0x9D,0x6F,0x21,0x87,0x06,0x37,
0x86,0x01,0xEA,0x99,0x15,0x6E,0x8A,0x88,0xAA,0xED,0x8C,0xE6,0x14,0x2F,0xB6,0x65,
0xB6,0xEE,0xEB,0x6F,0x06,0xEA,0x9D,0x45,0xB0,0x14,0x04,0x00,0x59,0xB4,0x26,0x77,
0x32,0xD7,0x33,0xB2,0xF0,0x92,0xE8,0x5E,0x40,0xF2,0x21,0x04,0xC4,0xF0,0x9C,0x80,};
const uint8_t *std_plain;
//明文长度,0-256
uint32_t c_bytes; //byte length of plaintext or ciphertext
//std_ccm_key
//const uint8_t std_ccm_key[32]= {0xE0,0x70,0x99,0xF1,0xBF,0xAF,0xFD,0x7F,0x24,0x0C,0xD7,0x90,0xCA,0x4F,0xE1,0x34,
0xB4,0x42,0x60,0xE1,0x56,0x8D,0x9E,0x85,0x0A,0x0C,0x95,0x37,0x44,0x02,0xDE,0x28};
const uint8_t *key;
//0
uint16_t keyid;
//std_ccm_nonce
//const uint8_t std_ccm_nonce[]= {0xC7,0x2B,0x65,0x91,0xA0,0xD7,0xDE,0x8F,0x6B,0x40,0x72,0x33,0xAD,0x35,0x81,0xD6};
const uint8_t *nonce;
//256-16,201-14,120-12,65-10,32-8,15-6,0-4
uint32_t M;
//256-2,201-3,120-4,65-5,32-6,15-7,0-8
uint32_t L;
//std_aad-additional authentication data 额外的验证数据
//33个元素,const uint8_t std_ccm_aad[] = {0xAE,0x30,0x14,0xAA,0x4E,0x58,0xBD,0xF9,0x03,0x23,0x87,0xED,0xBB,0x2C,0xF8,0xA3,
0xB6,0xD8,0x39,0x87,0x0D,0x89,0x54,0x7F,0xF7,0x68,0xFD,0x87,0x70,0x79,0x37,0x7E,
0x1B,};
const uint8_t *aad;
//认证数据长度0-33
uint32_t aad_bytes;
//数组长度要等于明文长度c_bytes
//c_bytes == 0时,此参数NULL
const uint8_t *std_cipher;
//消息认证码
const uint8_t std_aes128_ccm_mac_M16_L2_aad0_p256[] = {0x55,0xEA,0x2A,0x8F,0x0A,0x72,0x1F,0x7D,0xFA,0xD4,0xB9,0x77,0xC1,0x0D,0xB3,0x8A};
const uint8_t std_aes128_ccm_mac_M14_L3_aad3_p201[] = {0x8D,0x8D,0x3D,0xBC,0xF9,0x71,0xB4,0xDE,0x3B,0xE1,0x13,0xB1,0xAD,0x21};
const uint8_t std_aes128_ccm_mac_M12_L4_aad15_p120[] = {0xAD,0xF4,0xF9,0x42,0x9C,0x32,0xCA,0x51,0xE2,0xCD,0x9D,0xCB};
const uint8_t std_aes128_ccm_mac_M10_L5_aad16_p65[] = {0xEF,0x67,0xD8,0xE8,0x7C,0x4B,0xA5,0x72,0x7A,0x96};
const uint8_t std_aes128_ccm_mac_M8_L6_aad17_p32[] = {0x02,0xED,0x46,0xC9,0xF9,0xF0,0xF1,0x47};
const uint8_t std_aes128_ccm_mac_M6_L7_aad32_p15[] = {0xCF,0x8D,0x20,0x41,0x87,0x32,};
const uint8_t std_aes128_ccm_mac_M4_L8_aad33_p0[] = {0x72,0xF4,0xA8,0x70};
const uint8_t *std_mac;
}SKE_CCM_TEST_VECTOR;
uint32_t aes_128_ccm_test()
{
SKE_CCM_TEST_VECTOR vector[7] = {
{SKE_ALG_AES_128, std_ccm_plain, 256, std_ccm_key, 0, std_ccm_nonce, 16, 2, std_ccm_aad, 0, std_aes128_ccm_L2_cipher, std_aes128_ccm_mac_M16_L2_aad0_p256},
{SKE_ALG_AES_128, std_ccm_plain, 201, std_ccm_key, 0, std_ccm_nonce, 14, 3, std_ccm_aad, 3, std_aes128_ccm_L3_cipher, std_aes128_ccm_mac_M14_L3_aad3_p201},
{SKE_ALG_AES_128, std_ccm_plain, 120, std_ccm_key, 0, std_ccm_nonce, 12, 4, std_ccm_aad, 15, std_aes128_ccm_L4_cipher, std_aes128_ccm_mac_M12_L4_aad15_p120},
{SKE_ALG_AES_128, std_ccm_plain, 65, std_ccm_key, 0, std_ccm_nonce, 10, 5, std_ccm_aad, 16, std_aes128_ccm_L5_cipher, std_aes128_ccm_mac_M10_L5_aad16_p65},
{SKE_ALG_AES_128, std_ccm_plain, 32, std_ccm_key, 0, std_ccm_nonce, 8, 6, std_ccm_aad, 17, std_aes128_ccm_L6_cipher, std_aes128_ccm_mac_M8_L6_aad17_p32},
{SKE_ALG_AES_128, std_ccm_plain, 15, std_ccm_key, 0, std_ccm_nonce, 6, 7, std_ccm_aad, 32, std_aes128_ccm_L7_cipher, std_aes128_ccm_mac_M6_L7_aad32_p15},
{SKE_ALG_AES_128, std_ccm_plain, 0, std_ccm_key, 0, std_ccm_nonce, 4, 8, std_ccm_aad, 33, NULL, std_aes128_ccm_mac_M4_L8_aad33_p0},
};
return ske_ccm_test_internal(vector, 7);
}
三、任务
1、telink性能测试
1)部分测试记录
//RSA1024 密钥生成,e=65537
[14:57:13.839]收←◆ Test Begin Number = 100
[14:59:55.748]收←◆
non-CRT 100
Test End
ms/次:161.909/100 = 1.61909 * 1000 = 1619.09ms/次
次/s:100/161.909 = 0.6176308914266656次/s
//RSA1024 密钥生成,d,即指数1024比特,1000次
[18:32:04.382]收←◆
RSA_ModExp end
RSA_ModExp e begin
[18:32:09.556]收←◆
RSA_ModExp e end
ms/次:5.17/1000 = 1.61909 * 1000 = 5.17ms/次
次/s:1000/5.17 = 193.42359767891682785299806576402次/s
//RSA1024 加密验签,含H参数
//RSA1024 加密验签,指数1024bit,含H参数
xil_printf("\r\n RSA_ModExp begin "); fflush(stdout);
for(int j=0;j<500;j++){
ret = RSA_ModExp(in, d, n, out, get_valid_bits(d, nWordLen, nBitLen), nBitLen);
}xil_printf("\r\n RSA_ModExp end ");fflush(stdout);
[15:21:45.130]收←◆
RSA_ModExp begin
[15:24:30.227]收←◆
RSA_ModExp end
RSA encrypt & decrypt success
ms/次:169.332/500 = 0.338664 * 1000 = 338.664ms/次
次/s:500/169.332 = 2.952779155741384次/s
//RSA1024-CRT 模幂,解密/签名
xil_printf("\r\n begin2 "); fflush(stdout);
for(int j=0;j<1000;j++){
ret = RSA_CRTModExp(out, p, q, dp, dq, u, out2, nBitLen);
}
xil_printf("\r\n end2 ");fflush(stdout);
[15:43:56.045]收←◆
begin2
[15:44:54.524]收←◆
end2
ms/次:58.479/1000 * 1000 = 58.479ms/次
次/s:1000/58.479 = 17.10015561141606次/s
//RSA1024-CRT 密钥生成,e=65537
ret = RSA_GetCRTKey(e, p, q, dp, dq, u, n, eBitLen, nBitLen);
[15:58:34.621]收←◆
begin3
[16:01:09.512]收←◆
CRT 100
end3
ms/次:154.891/100 * 1000 = 1548.91ms/次
次/s:100/154.891 = 0.6456153036651581次/s
//ECC384,200次
[16:34:54.339]收←◆
---secp384r1
get key pair begin
[16:35:38.215]收←◆
finished
sign begin
[16:36:22.774]收←◆
finished
verify begin
[16:37:51.334]收←◆
finished
ECDSA verify success
//随机密钥对生成
ms/次:43.876/200 * 1000 = 219.38ms/次
次/s:200/43.876 = 4.5583006655118971647369860516次/s
//ECDSA签名
ms/次:44.559/200 * 1000 = 222.795ms/次
次/s:200/44.559 = 4.4884310689198590632644359164254次/s
//ECDSA验签
ms/次:88.56/200 * 1000 = 442.8ms/次
次/s:200/88.56 = 2.2583559168925022583559168925023次/s
//ECC brainpoolp512r1 200次
[16:41:51.145]收←◆
---brainpoolp512r1
get key pair begin
[16:43:16.041]收←◆
finished
sign begin
[16:44:42.233]收←◆
finished
verify begin
[16:47:36.009]收←◆
finished
ECDSA verify success
//随机密钥对生成
次/s:200/84.896 = 2.3558235959291368262344515642669次/s
//ECDSA签名
次/s:200/86.192 = 2.3204009652868015593094486727306次/s
//ECDSA验签
次/s:200/173.776 = 1.1509069146487432096492035724151次/s
//ECC secp521r1 200次
[16:50:15.159]收←◆
---secp521r1
get key pair begin
[16:51:49.126]收←◆
finished
sign begin
[16:53:24.326]收←◆
finished
verify begin
[16:56:36.639]收←◆
finished
ECDSA verify success
//随机密钥对生成
次/s:200/94.057 = 2.1263701797845987007878201516102次/s
//ECDSA签名
次/s:200/95.11 = 2.1028283040689727683734623068026次/s
//ECDSA验签
次/s:200/192.313 = 1.0399712967922085350444327736554次/s
//ecdh_rand_test(secp384r1, "secp384r1")
//*****************有问题*********************
//ECDH密钥协商,100次
------------- secp384r1 ECDH rand data test -------------
[17:20:18.686]收←◆
secp384r1 Begin4
[17:21:02.315]收←◆
secp384r1 End4
//ECDH密钥协商
次/s:100/43.629 = 2.2920534506864700084805977675399次/s
------------- brainpoolp512r1 ECDH rand data test -------------
[17:21:03.154]收←◆
brainpoolp512r1 Begin4
[17:22:26.918]收←◆
brainpoolp512r1 End4
//ECDH密钥协商
次/s:100/83.764 = 1.1938302850866720786972923929134次/s
------------- secp521r1 ECDH rand data test -------------
[17:22:27.876]收←◆
secp521r1 Begin4
[17:24:03.394]收←◆
secp521r1 End4
//ECDH密钥协商
次/s:100/96.476 = 1.0365272192047763174260956092707次/s
//ecdh_speed_test
//brainpoolp512r1,60次
[17:51:40.987]收←◆
=================== ECDH test ===================
[17:51:41.836]收←◆
begin6
[17:52:07.138]收←◆
finished
//ECDH密钥协商
次/s:60/25.302 = 2.3713540431586435854873132558691次/s
//secp384r1,100次
=================== ECDH test ===================
[17:58:26.667]收←◆
begin6
[17:58:48.434]收←◆
finished
//ECDH密钥协商
次/s:100/21.767 = 4.5941103505306197454862865806037次/s
//secp521r1,100次
=================== ECDH test ===================
[18:01:01.947]收←◆
begin6
[18:01:48.993]收←◆
finished
//ECDH密钥协商
次/s:100/47.046 = 2.1255792203375419801896016664541次/s
//Ed25519, 1000次
//uint8_t Ed25519_all_test(void)
[17:43:12.606]收←◆
=================== EdDSA(Ed25519) test ===================
begin
[17:44:17.427]收←◆
finished
begin
[17:45:22.988]收←◆
finished
begin
[17:46:50.456]收←◆
finished
//ECDH随机密钥生成,1000次
次/s:1000/64.821 = 15.427099242529427191805124882368次/s
//ECDH签名,1000次
次/s:1000/65.561 = 15.2529705160079925565503881881次/s
//ECDH验签,600次
次/s:600/87.468 = 6.8596515297022911236109205652353次/s
//点乘,Ed25519
[18:39:17.609]收←◆
=================== EdDSA(Ed25519) test ===================
begin
CZH,diancheng,begin
[18:39:49.737]收←◆
CZH,diancheng,end
//
次/s:500/32.128 = 15.562749003984063745019920318725次/s
//ECDH
//secp521r1,100次
[18:49:26.509]收←◆
=================== ECDH test ===================
[18:49:26.980]收←◆
ECC,diancheng begin
[18:50:13.963]收←◆
ECC,diancheng end
次/s:100/46.983 = 2.1284294319221846199689249302939次/s
//brainpoolp512r1,100次
[18:52:40.569]收←◆
ECC,diancheng begin
[18:53:22.676]收←◆
ECC,diancheng end
次/s:100/42.107 = 2.3749020352910442444249174721543次/s
//secp384r1,100次
[18:50:54.054]收←◆
ECC,diancheng begin
[18:51:15.762]收←◆
ECC,diancheng end
次/s:100/21.708 = 4.6065966463976414225170444075917次/s
2)性能测试时间计算代码
//性能测试时间计算代码
void calc_time()
{
while (1)
{
int a, b, c, d;
std::cin >> a >> b >> c >> d;
int e, f, g, h;
std::cin >> e >> f >> g >> h;
double num1 = 3600 * a + 60 * b + c + d*0.001;
double num2 = 3600 * e + 60 * f + g + h*0.001;
std::cout << num2 - num1 << std::endl;
std::cout << std::endl;
std::cout << std::endl;
}
return;
}
3)复测
//RSA1024 密钥生成
[13:56:09.068]收←◆ RSA_GetKey Test Begin Number = 1
[13:58:50.991]收←◆
ms/次:333.916/200 = X * 1000 = 1669.58ms/次
次/s:200/333.916 = 0.59895303010337929299584326597108次/s
ms/次:511.185/300 = 1.70395 * 1000 = 1703.95ms/次
次/s:300/511.185 = 0.5868716805070571319580973620118次/s
//RSA1024 模幂
//加密
xil_printf("\r\n RSA_ModExp begin "); fflush(stdout);
for(int j=0;j<1000;j++){
ret = RSA_ModExp(in, d, n, out, get_valid_bits(d, nWordLen, nBitLen), nBitLen);
}xil_printf("\r\n RSA_ModExp end ");fflush(stdout);
if(ret)
{
printf("\r\n RSA_ModExp error, ret = %d", ret);fflush(stdout);
return 1;
}
//解密
xil_printf("\r\n RSA_ModExp e begin "); fflush(stdout);
for(int j=0;j<1000;j++){
ret = RSA_ModExp(out, e, n, out2, eBitLen, nBitLen);
}xil_printf("\r\n RSA_ModExp e end ");fflush(stdout);
//加密
ms/次:165.111/1000 = 0.165111 * 1000 = 165.111ms/次
次/s:1000/165.111 = 6.0565316665758186916680293862916次/s
//解密
ms/次:5.152/1000 = X * 1000 = 5.152ms/次
次/s:1000/5.152 = 194.09937888198757763975155279503次/s
//RSA1024 CRT-模幂
[14:36:37.113]收←◆
begin2
[14:37:36.380]收←◆
end2
ms/次:59.267/1000 = X * 1000 = 59.267ms/次
次/s:1000/59.267 = 16.872795991023672532775406212563次/s
//RSA1024 CRT-密钥生成
[14:41:20.259]收←◆ RSA_GetKey Test Begin Number = 1
begin3
[14:43:52.855]收←◆ CRT 100
ms/次:152.596/100 = X * 1000 = 1525.96ms/次
次/s:100/152.596 = 0.65532517235052032818684631314058次/s
2、AES-XCBC-AMC-96
1)init
//计算k1\k2\k3,用结构体保存
uint32_t ske_lp_aes_xcbc_mac_96_init(SKE_AES_XCBC_MAC_96_CTX *ctx, SKE_MAC mac_action, uint8_t *key, uint16_t sp_key_idx);
//DMA模式,做法与CPU一致
uint32_t ske_lp_dma_aes_xcbc_mac_96_init(SKE_AES_XCBC_MAC_96_DMA_CTX *ctx, uint8_t *key, uint16_t sp_key_idx);
2)update
//参考cmac,分段计算,用结构体记录当前分组后的剩余明文
uint32_t ske_lp_aes_xcbc_mac_96_update(SKE_AES_XCBC_MAC_96_CTX *ctx, uint8_t *msg, uint32_t msg_bytes);
//DMA模式,参考hp版本的cmac模式,该过程简单,要求传进来block分组的倍数的明文,ske_lp_dma_update_blocks
uint32_t ske_lp_dma_aes_xcbc_mac_96_update_blocks_excluding_last_block(SKE_AES_XCBC_MAC_96_DMA_CTX *ctx, uint32_t *msg,
uint32_t msg_words, uint32_t *tmp_out, SKE_CALLBACK callback);
3)final
//根据最后一组明文是否满分组,满分组跟k2异或再CBC加密、不满分组跟k3异或再CBC加密
uint32_t ske_lp_aes_xcbc_mac_96_final(SKE_AES_XCBC_MAC_96_CTX *ctx, uint8_t mac[12]);
//DMA模式,参考hp版本的cmac模式
uint32_t ske_lp_dma_aes_xcbc_mac_96_update_including_last_block(SKE_AES_XCBC_MAC_96_DMA_CTX *ctx, uint32_t *msg, uint32_t msg_bytes,
uint32_t *tmp_out, uint32_t *mac, SKE_CALLBACK callback);
5)RFC3566标准测试数据参考
=================== test0 plain_len=0====================
AES128-XCBC-MAC-96: 75f0251d528ac01c4573dfd5
=================== test3 plain_len=3====================
AES128-XCBC-MAC-96: 5b376580ae2f19afe7219cee
=================== test16 plain_len=16====================
XCBC-MAC-96: d2a246fa349b68a79998a439
=================== test32 plain_len=32====================
AES128-XCBC-MAC-96: f54f0ec8d2b9f3d36807734b
=================== test34 plain_len=34====================
AES128-XCBC-MAC-96: becbb3bccdb518a30677d548
6) 其他修改
函数名称
- XCBC MAC统一改为AES XCBC MAC 96,RFC《3566》里已规定是128bit密钥,算法参数可以去掉
- 测试例子中的随机向量测试可以删除了
//XCBC MAC simple test
#if 0
//test rand vector
rand = ske_get_rand_number(vector_num);
printf("\r\n\r\n =================== test rand vector plain_len=%d==================== \r\n",rand);
ret = ske_lp_aes_xcbc_mac_96_init(ctx, SKE_ALG_AES_128, SKE_GENERATE_MAC, std_aes_128_xcbc_mac_key, sp_key_idx, 0x0C);
ret |= ske_lp_aes_xcbc_mac_96_update(ctx, std_aes_128_xcbc_mac_plain, rand);
ret |= ske_lp_aes_xcbc_mac_96_final(ctx, mac);
if(SKE_SUCCESS != ret)
{
return ret;
}
else
{;}
print_buf_U8(mac, ctx->mac_bytes, "AES128-XCBC-MAC-96");
#endif
7)性能测试
单位MBytes/s,例如测试数据4K,重复10000次,时间25.24s,那么性能为:4K*10000/1024/1024/25.24 Mbytes/s
8)接口文档增加编写
//OSR_SKE_LP_v1.2_API_UG_CB_v1.0.docx
1)1.3符号和缩略语
2)1.4算法库整体文件结构
3)1.5.3支持的SKE算法及模式定义
4)2.15AES-XCBC-MAC-96
5)3.2参考空间资源占用(未修改)
//OSR_SKE_LP_v1.2_API_FPGA_TR_CN v1.0.docx
1)2.8AES-XCBC-MAC-96测试
//OSR_SKE_LP_v1.2_DR_SA_CN_v1.0.docx
1)Cppcheck扫描有ske.c有一处错误
9)CppCheck
//此接口里的ret没有初始化,从代码逻辑看,最后END直接判断ret存在问题。
uint32_t ske_tdes_update_blocks(uint8_t *in, uint8_t *out, uint32_t bytes)
10)资源占用测试
Xilinx修改重新编译后,Console会有相关数据
(1)text指的是代码段(含全局常量,即const修饰的全局变量定义)。
(2)data指的是定义时就被初始化非零值的全局变量,不使用,为0,故不列出。
(3)bss指的是定义时没有被初始化或初始化为零的全局变量。
(4)stack是栈内存占用。
(5)heap是堆内存占用,不使用,为0,故不列出。
//bss
//45, ske.c
static SKE_ALG g_ske_alg; //1
static SKE_MODE g_ske_mode; //1
static SKE_CRYPTO g_ske_crypto_action; //1
static uint32_t g_ske_key_buf[6]; //24
static uint32_t g_ske_iv_buf[4]; //16
static SKE_CTX g_ske_ctx[1]; //2
//4,ske_basic.c //data是定义时就被初始化为0的全局变量
volatile static ske_lp_reg_t * const g_ske_lp_reg = (ske_lp_reg_t *)(SKE_LP_BASE_ADDR); //4
//8,trng.c
static uint32_t error_counter = 0; //4
static uint32_t trng_cfg_flag = 0;//4
//最终占用45B,g_ske_lp_reg是data,trng.c相关的是属于定义为0,不属于bss
//stack
ske_lp_dma_aes_xcbc_mac_96 //1+2+6*4+1*12=39
-ske_lp_dma_aes_xcbc_mac_96_update //4*2+4+4*2+4+4*2+1*2=34
--ske_lp_dma_update_blocks //4*4=16
---ske_lp_dma_operate //6*4=24
----ske_lp_dma_calc_wait_till_done //4*3=12
12+24+16+34+39=125
ske_lp_dma_aes_xcbc_mac_96 //1+2+6*4+1*12=39
-ske_lp_dma_aes_xcbc_mac_96_init //4+1+4+2+4*5=31
--ske_lp_init_internal //4+1+1+1+4+2+8+4=25
---ske_lp_set_key //1+4+2+2+4*8=41
----ske_lp_set_key_uint32 //4*3+4*2=20
20+41+25+31+39=156
//text
//标准版(去掉测试代码)
text data bss dec hex filename
97160 2584 23456 123200 1e140 hello.elf
//含aes-xcbc-mac-96(去掉测试代码)
text data bss dec hex filename
99464 2584 23456 125504 1ea40 hello.elf
//最新-20220616,去掉测试代码
text data bss dec hex filename
100552 2584 23456 126592 1ee80 hello.elf
//最新-20220616,只留下crypto_common
text data bss dec hex filename
74624 2584 23328 100536 188b8 hello.elf
11)DMA模式下的一些问题
a) words字
uint32_t std_in_;
std_in_ = std_buf_ + 16;//16不是代表16个字、是16字节,因为定义不是指针,上次排查花了好多时间没注意到定义
uint32_t *std_in_;
std_in_ = std_buf_ + 16;//16代表16个字
//10111213 80000000 00000000 00000000
uint32_clear((uint32_t *)(block_buf+2), 2); //后面置为0
b)update_blocks
ske_lp_dma_aes_xcbc_mac_96_update_blocks里面封装了一个函数ske_lp_dma_operate(可以指定out输出的个数,lp目前似乎必须要输出)
//以下两个函数等价
//out_words设置为0或者blocks_bytes/4-1都会卡死,其他情况未测试,应该得同长度输入输出,(后续了解lp必须要有输出,hp可以没有)
ret = ske_lp_dma_operate(ctx->ske_xcbc_mac_ctx, msg, msg+1000, blocks_bytes/4, blocks_bytes/4, callback);
ret = ske_lp_dma_update_blocks(msg, msg+1000, blocks_bytes/4, callback);
c)其他数据
/*uint32_t ske_lp_dma_aes_xcbc_mac_96_update_including_last_block(SKE_AES_XCBC_MAC_96_CTX *ctx, uint32_t *msg, uint32_t msg_words,
uint32_t *buf, SKE_CALLBACK callback);*/
3、增加测试向量
1)GCM向量结构
//GCM模式
//以AES_128为例,aad为65,plaintext为0
SKE_GCM_TEST_VECTOR vector[8] = {
...
{SKE_ALG_AES_128, std_gcm_plain, 0, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 65, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad65_p0, 16},
};
//以上std_aes128_gcm_mac_aad65_p0可知,参与消息认证码的计算参数为:
//1)AES_128_GCM_Key,为16字节
//2)IV值:可以为空,有64bits的填充
//3)plaintext:明文,可以为NULL
//4)aad附加认证消息:可以为空,没有填充
//可以利用MyBlockCipher20220126.exe计算出Tag值,
//原本33字节,增加到65字节
const uint8_t std_aad[65] = {
0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
0xab,0xad,0xda,0xd2,0x7C,0xA4,0x8E,0x82,0x99,0xFC,0x5A,0xD3,0xE9,0x08,0xB7,0x65,
0x1B,
0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
0xab,0xad,0xda,0xd2,0x7C,0xA4,0x8E,0x82,0x99,0xFC,0x5A,0xD3,0xE9,0x08,0xB7,0x65,};
const uint8_t std_gcm_iv[12] = {
0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88};
//通过MyBlockCipher20220126.exe计算带入
const uint8_t std_aes128_gcm_mac_aad65_p0[] = {0x68,0x4D,0x42,0xF7,0xE7,0xDF,0x3D,0xEB,0xB7,0xD6,0x93,0x6D,0x54,0x42,0x18,0x8E};
//测试向量
{SKE_ALG_AES_128, std_gcm_plain, 0, std_gcm_key, 0, std_gcm_iv, 12, std_aad, 65, std_aes128_gcm_cipher, std_aes128_gcm_mac_aad65_p0, 8},
//AES-GCM-Key-128 16字节子密钥
feffe9928665731c6d6a8f9467308308
//AES-GCM-Key-192 24字节子密钥
feffe9928665731c6d6a8f9467308308feffe9928665731c
//AES-GCM-Key-256 32字节子密钥
feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
//SM4,IV和密钥长度为16字节,GCM模式下IV例外,甚至可以为NULL,密钥为
feffe9928665731c6d6a8f9467308308
2)GCM-测试数据
Key:
FEFFE9928665731C6D6A8F9467308308
IV:
CAFEBABEFACEDBADDECAF888
aad:
FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD27CA48E8299FC5AD3E908B7651BFEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD27CA48E8299FC5AD3E908B765
plaintext:
D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B391AAFD255B4D14B82E003CA484C281B5D4D9BBC29F361D1617936F53E37EF9773B3318C8C4ECB319E264DF629BE8C411BF5C4BE45036256E4D82F645A4D0ADF4455B131A17BC6742186C42E283AA5BAD54A18EC143BAF1E6C857F32EC5D92B196CF7E311371BDA2EAE8DFD082CFEB583A41CFCEAA780FD17FBAE931DEF717B45BB86F15D601F544FBCCB2435F80E89D6F218706378601EA99156E8A88AAED8CE6142FB665B6EEEB6F06EA9D45B014040059B4267732D733B2F092E85E40F22104C4F09C80
Tag:自选输出长度,1-16字节
4)CCM-测试数据
std_ccm_Key
16:
E07099F1BFAFFD7F240CD790CA4FE134
24:
E07099F1BFAFFD7F240CD790CA4FE134B44260E1568D9E85
32:
E07099F1BFAFFD7F240CD790CA4FE134B44260E1568D9E850A0C95374402DE28
Nonce:
16:
C72B6591A0D7DE8F6B407233AD3581D6
13:
C72B6591A0D7DE8F6B407233AD
aad:
65:AE3014AA4E58BDF9032387EDBB2CF8A3B6D839870D89547FF768FD877079377E1BAE3014AA4E58BDF9032387EDBB2CF8A3B6D839870D89547FF768FD877079377E
33:
AE3014AA4E58BDF9032387EDBB2CF8A3B6D839870D89547FF768FD877079377E1B
plaintext:
81709944E0CB2E1DB5B0A477D1A8539B0A8786E34EAAED99303EA6975595B2454D5D7F91EBBD4ACD726C0E0E5E3EB55EF6B15A138E226ECD1B235AB5BB5251C13376B26448A9AC1DE8BD52648C0B5FFA94448682E3CB4DE9CB8AE7F4BD410ED502B1253AD08BB27969B5F02B10029D67D07E1864D94D4FCA208151E26F5FEE267BC6742186C42E283AA5BAD54A18EC143BAF1E6C857F32EC5D92B196CF7E311371BDA2EAE8DFD082CFEB583A41CFCEAA780FD17FBAE931DEF717B45BB86F15D601F544FBCCB2435F80E89D6F218706378601EA99156E8A88AAED8CE6142FB665B6EEEB6F06EA9D45B014040059B4267732D733B2F092E85E40F22104C4F09C80
4、CMAC-DMA
1)分布计算函数
update和final参考AES-XCBC-MAC-96,直接移植过来,final需要更换密钥,init照搬CPU模式的init
//分步计算代码
#if 0
ret = ske_lp_dma_cmac(alg, std_key, sp_key_idx, msg, 3, mac, mac_bytes, tmp_out_, ske_call_manage);
#else
ret = ske_lp_dma_cmac_init(ctx, alg, std_key, sp_key_idx, mac_bytes);
ret |= ske_lp_dma_cmac_update_blocks_excluding_last_block(ctx, msg, 0, tmp_out_, ske_call_manage);
ret |= ske_lp_dma_cmac_update_including_last_block(ctx, msg, 3, mac, tmp_out_, ske_call_manage);
#endif
//初步跑通
ret = ske_lp_dma_cmac_init(ctx, alg, std_key, sp_key_idx, mac_bytes);
ret |= ske_lp_dma_cmac_update_blocks_excluding_last_block(ctx, msg, 0, tmp_out_, ske_call_manage);
ret |= ske_lp_dma_cmac_update_including_last_block(ctx, msg, 3, mac, tmp_out_, ske_call_manage);
//DMA初始化
ret = ske_lp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k_buf, sp_key_idx, iv);
//ske_lp_dma_init包含了ske_lp_init_internal操作,调用ske_lp_dma_init即可
ret = ske_lp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k_buf, sp_key_idx, iv);
/* ret = ske_lp_init_internal(ctx->ske_xcbc_mac_ctx, SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, key, sp_key_idx, NULL,SKE_LP_DMA_ENABLE);*/
2)TDES
除了AES系列、SM4、DES,DMA不支持TDES、TDES(CPU模式)是软件基于DES做,新增部分接口如tdes_update_blocks。
简单验证了下TDES的加密,跟密码学工具计算的不符合,表明不支持
uint8_t tdes128_plain[8] = {0x8F,0x34,0xFE,0x51,0x4C,0xFE,0x31,0x47,};
uint8_t tdes128_key[16] = {0xE0,0x70,0x99,0xF1,0xBF,0xAF,0xFD,0x7F,0x24,0x0C,0xD7,0x90,0xCA,0x4F,0xE1,0x34,};
uint32_t *msg_test = (uint32_t *)(DMA_RAM_BASE);
memcpy_(msg_test, tdes128_plain, 8);
print_buf_U8(msg_test, 8, "msg_test1");
ret = ske_lp_dma_cmac_init_internal(ctx, SKE_ALG_TDES_128, tdes128_key, 0, 8); //
ret |= ske_lp_dma_update_blocks(msg_test, msg_test, 2, callback);
printf("\nret=%d\n",ret);
print_buf_U8(msg_test, 8, "msg_test2");
5、CBC-MAC-DMA
//调用示例
#if 1
ret = ske_lp_dma_cbc_mac(alg, SKE_ZERO_PADDING, std_key, sp_key_idx, msg, 3, mac, mac_bytes, tmp_out_, ske_call_manage);
#else
ret = ske_lp_dma_cbc_mac_init(ctx, alg, SKE_ZERO_PADDING, std_key, sp_key_idx, mac_bytes);
ret |= ske_lp_dma_cbc_mac_update_blocks_excluding_last_block(ctx, msg, 0, tmp_out_, ske_call_manage);
ret |= ske_lp_dma_cbc_mac_update_blocks_including_last_block(ctx, mac,msg, 3, tmp_out_, ske_call_manage);
#endif
6、ske_hp移植
将aes-xcbc-mac-96、ccm/gcm测试向量移植到ske_hp上
7、性能测试(内部计算)
//方式1
//头文件
#include "xtime_l.h"
//用例
XTime tmp_time=0; //类型
XTime_SetTime(0);//开始计算crycle
ret = RSA_CRTModExp_with_pub(vector->std_in, p, q, dp, dq, u, vector->e, out, eBitLen, nBitLen);
XTime_GetTime(&tmp_time);//统计执行一遍的周期数,这个地方很重要
//打印测试结果,COUNTS_PER_SECOND为1s,执行的crycle数量
printf("\n***************%llu***************\n",tmp_time);
printf("speed(n/s)=%f\n",COUNTS_PER_SECOND/tmp_time);
printf("speed(ms/n)=%f\n\n",tmp_time/COUNTS_PER_SECOND*1000); //CZH
//方式2
uint32_t startP()
{
//SysTick_Config应该是工程内置函数
SysTick_Config(0xFFFFFF);
//SysTick->VAL应该是工程内置变量,看环境,目前看到的是1600W,开始递减
g_starl = SysTick->VAL;
}
uint32_t endP(uint8_t mode, uint32_t mlen, uint32_t cnt, char *info)
{
g_endl = SysTick->VAL;//看环境,该值会递减,目前看到的是1600W
calcP(mode,mlen,cnt,info);
}
//计算周期,注意g_endl==0时,会重新最高值递减
counterL = g_starl - g_endl;
printf("\r\n startL = %u cycle, endL = %u cycle, counterL = %u cycle", g_starl, g_endl, counterL);fflush(stdout);
//计算本轮计算的时间,当前单位是us
ts = counterL/(float)CPU_Hz;
//换算成秒,10^6
printf("\r\n ts = %.3f s", ts / (float)1000 / (float)1000);fflush(stdout);
//计算Mbps=Mb/s
msg_bits = msg_bytes*cnt*8;//计算本轮计算的数据量=单次数据*循环次数
printf("\r\n meslen = %u bit", msg_bits);fflush(stdout);
//res = res /1024 /1024 / ts * 10^6
res = msg_bits/ts;
res = res*1000/1024;
res = res*1000/1024;
//计算 次/s
res = cnt*STDCNT/ts;//STDCNT=1000000u
printf("\r\nres = %.6f/s;CPU_Hz = %uMhz", res,CPU_Hz);fflush(stdout);
res = res*DEFAULT_CPU_Hz/CPU_Hz;//200u / 10u
printf("\r\nexres = %.3f/s;exCPU_Hz = %uMhz", res,DEFAULT_CPU_Hz);fflush(stdout);
8.PUF
...
9.HFE/HASH_LP
//hash_lp (hash&hmac)
hmac_dma ⇒ 1+4+2+4+4+4+4+4+8+4+220=259
hmac_dma_init ⇒ 4+1+4+2+4+4+4+348=371
hmac_init ⇒ 4+1+4+2+4+8+8=31
hash_update ⇒ 4+4+4+4+2=18
hash_calc_blocks ⇒ 4+4+4+4=32
hash_input_msg ⇒ 4+4+8=16
memcpy_ 12+8=20
259+371+31+18+32+16=727
//HFE (hash&hmac)
hmac ⇒ 1+4+2+4+4+4+4+524+4=551
hmac_update ⇒ 16+1+1=18
hash_calc_blocks ⇒ 4+4+4+4=16
hash_get_iterator ⇒ 4+4+4+4=16
memcpy_ 12+8=20
551+18+16+16+20=621
//hash_lp (hash)
hash ⇒
hash_update ⇒
hash_calc_blocks ⇒
hash_input_msg ⇒
memcpy_ 20
//HFE (hash)
hash ⇒
hash_update ⇒
hash_calc_blocks ⇒
hash_get_iterator ⇒
memcpy_ 20
10.XHSC_SKE_HP
//DMA测试获取CBC_MAC和CMAC中间值
//结果:CPU模式下CMAC和CBC_MAC都可以在DOUT寄存器获取最后一组,DMA模式下CBC_MAC可以配置out输出到非DMA_TEST_ADDR上,每一段用完整的CBC_MAC获取结果,CMAC无法获取中间值。
uint32_t xxx_cmac_test(void)
{
uint8_t key[32] = {0xE0,0x70,0x99,0xF1,0xBF,0xAF,0xFD,0x7F,0x24,0x0C,0xD7,0x90,0xCA,0x4F,0xE1,0x34,
0xB4,0x42,0x60,0xE1,0x56,0x8D,0x9E,0x85,0x0A,0x0C,0x95,0x37,0x44,0x02,0xDE,0x28,};
uint8_t message[500] = {0};
uint8_t mid_iv[16];
uint8_t mac[500];
SKE_CMAC_CTX cmac_ctx[1];
SKE_CBC_MAC_CTX cbc_mac_ctx[1];
SKE_ALG alg = SKE_ALG_AES_128;//SKE_ALG_SM4;
uint32_t i,j, ret;
//K1:7051501D5233E9D2E1F43857DC30888C
ske_hp_set_payload_stage(SKE_PAYLOARD_STREAM);
for(i=0;i<500;i++)
{
message[i] = 0;
}
//get CBC_MAC mid iv(CPU mode),success
memset_(mac, 0, 16);
ret = ske_hp_cbc_mac(alg, SKE_GENERATE_MAC, SKE_NO_PADDING, (uint8_t *)key, 0, (uint8_t *)message, 48, mac, 16);
print_buf_U8(mac, 16, "cbc mac1");
memset_(mac, 0, 16);
ret = ske_hp_cbc_mac_init(cbc_mac_ctx, alg, SKE_GENERATE_MAC, SKE_NO_PADDING, (uint8_t *)key, 0, 16);
ret |= ske_hp_cbc_mac_update_blocks(cbc_mac_ctx, (uint8_t *)message, 16);
ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
print_buf_U8(mid_iv, 16, "cbc mid_iv");
ret |= ske_hp_cbc_mac_update_blocks(cbc_mac_ctx, (uint8_t *)message, 16);
ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
print_buf_U8(mid_iv, 16, "cbc mid_iv");
ret |= ske_hp_cbc_mac_update_blocks(cbc_mac_ctx, (uint8_t *)message, 16);
ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
print_buf_U8(mid_iv, 16, "cbc mid_iv");
ret |= ske_hp_cbc_mac_final(cbc_mac_ctx, mac);
print_buf_U8(mac, 16, "cbc mac2");
//get CMAC mid iv(CPU mode),success
memset_(mac, 0, 16);
ret = ske_hp_cmac(alg, SKE_GENERATE_MAC, (uint8_t *)key, 0, (uint8_t *)message, 48, mac, 16);
print_buf_U8(mac, 16, "cmac1");
memset_(mac, 0, 16);
ret = ske_hp_cmac_init(cmac_ctx, alg, SKE_GENERATE_MAC, (uint8_t *)key, 0, 16);
ret |= ske_hp_cmac_update_blocks(cmac_ctx, (uint8_t *)message, 16);
ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
print_buf_U8(mid_iv, 16, "cmac mid_iv");
ret |= ske_hp_cmac_update_blocks(cmac_ctx, (uint8_t *)message, 16);
ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
print_buf_U8(mid_iv, 16, "cmac mid_iv");
ret |= ske_hp_cmac_update_blocks(cmac_ctx, (uint8_t *)message, 16);
ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
print_buf_U8(mid_iv, 16, "cmac mid_iv");
ret |= ske_hp_cmac_final(cmac_ctx, mac);
print_buf_U8(mac, 16, "cmac2");
//get CBC_MAC mid iv(DMA mode),success
SKE_CMAC_DMA_CTX cmac_ctx2[1];
SKE_CBC_MAC_DMA_CTX cbc_mac_ctx2[1];
uint32_t *msg_buf = (uint32_t *)(DMA_RAM_BASE);
uint32_t *mac_buf = msg_buf + 256;
memcpy_(msg_buf, message, 48);
memset_(mac, 0, 16);
ret = ske_hp_dma_cbc_mac(alg, (uint8_t *)key, 0, msg_buf, 48, (uint32_t *)mac, 16, NULL);
print_buf_U8(mac, 16, "cbc dma mac1");
memset_(mac, 0, 16);
ret = ske_hp_dma_cbc_mac_init(cbc_mac_ctx2, alg, key, 0, 16);
ret |= ske_hp_dma_cbc_mac_update_blocks_excluding_last_block(cbc_mac_ctx2, msg_buf, 16, NULL);
// ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
// print_buf_U8(mid_iv, 16, "cbc dma mid_iv");
ret |= ske_hp_dma_cbc_mac_update_blocks_excluding_last_block(cbc_mac_ctx2, msg_buf, 16, NULL);
// ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
// print_buf_U8(mid_iv, 16, "cbc dma mid_iv");
ret |= ske_hp_dma_cbc_mac_update_including_last_block(cbc_mac_ctx2, msg_buf, 16, (uint32_t *)mac, NULL);
// ske_hp_simple_get_output_block((uint32_t *)mid_iv, 4);
// print_buf_U8(mid_iv, 16, "cbc dma mid_iv");
print_buf_U8(mac, 16, "cbc dma mac2");
memset_(mac, 0, 16);
ret = ske_hp_dma_cmac(alg, key, 0, msg_buf, 48, (uint32_t *)mac, 16, NULL);
print_buf_U8(mac, 16, "dma cmac1");
memset_(mac, 0, 16);
ret = ske_hp_dma_cmac_init(cmac_ctx2, alg, (uint8_t *)key, 0, 16);
ret |= ske_hp_dma_cmac_update_blocks_excluding_last_block(cmac_ctx2, msg_buf, 32, NULL);
// ret |= ske_hp_dma_cmac_update_blocks_excluding_last_block(cmac_ctx2, msg_buf, 16, NULL);
ret |= ske_hp_dma_cmac_update_including_last_block(cmac_ctx2, msg_buf, 16, (uint32_t *)mac, NULL);
print_buf_U8(mac, 16, "dma cmac2");
}
11、ChaCha20在NucleiStudio性能测试
N205
1.用最新版本的IDE,202204
2.每次launch后,可以在执行性能测试前,Registers中mstatus寄存器把第4位(0bit开始)bit改为0
3.接调试器(另一个)
12、sm2-kmu sign
//set mgmr:curve->eccp_p, curve->eccp_p_h
pke_load_operand((uint32_t *)(rPKE_A(0u,0x20)), modulus, 8); //A0 p //0x0400U+(0*0x20)
pke_load_operand((uint32_t *)(rPKE_B(0u,0x20)), modulus_h, 8); //B0 h //0x01000U+(0*0x20)
pke_pre_calc_mont_N0();
//get rand k
//[k](Gx,Gy), r=Px
pke_load_operand((uint32_t *)(rPKE_B(1u,0x20)), Px, 8); //B1 Px //0x01000U+(1*0x20)
pke_load_operand((uint32_t *)(rPKE_B(2u,0x20)), Py, 8); //B2 Py
pke_set_operand_uint32_value((uint32_t *)(rPKE_A(3u,0x20)), 8, 1u); //A3 Pz
pke_load_operand((uint32_t *)(rPKE_B(3u,step_bytes)), curve->eccp_b, 8); //B3 b ---- corrupted after calculating
pke_load_operand((uint32_t *)(rPKE_B(4u,step_bytes)), curve->eccp_a, 8); //B4 a---- if a is not 0, B4 is corrupted after calculating.
pke_load_operand((uint32_t *)(rPKE_B(5u,step_bytes)), curve->eccp_n, 8); //B5 order---- corrupted after calculating
pke_load_operand((uint32_t *)(rPKE_A(4u,step_bytes)), k, nWordLen); //A4 k---- corrupted after calculating
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_PMUL_SEC);
pke_read_operand((uint32_t *)(rPKE_A(1u,step_bytes)), Qx, pWordLen); //A1 Qx
pke_read_operand((uint32_t *)(rPKE_A(2u,step_bytes)), Qy, pWordLen); //A2 Qy
//r=r+e mod n
pke_load_operand((uint32_t *)(rPKE_A(0u,32u)), modulus, 8u); //A0 modulus--curve->eccp_n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 a--e
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 b--r
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODADD);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 out--r
//get rand t1
//set mgmr:curve->eccp_n, curve->eccp_n_h
rPKE_CFG &= (~(0x0007FFFFU));
rPKE_CFG |= 0x00020100u;
pke_load_operand_256bits((uint32_t *)(rPKE_A(0u,32u)), modulus); //A0 p--eccp_n //0x0400U+(0*0x20)
pke_load_operand_256bits((uint32_t *)(rPKE_B(0u,32u)), modulus_h); //B0 h--eccp_n_h //0x01000U+(0*0x20)
pke_pre_calc_mont_N0();
//out = (dA - t1) mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 a--dA
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 b--t1
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODSUB);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 --out
//out = (out + 1) mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 --out
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 --1
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODADD);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 --out
//get rand t2
//out = (out)*t2 mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 a--out
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 b--t2
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODMUL);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 --out
//tmp = t1*t2 mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 a--t1
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 b--t2
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODMUL);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 --tmp
//out = (out+tmp) mod n = ((dA+1)*rand2) mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 --out
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 --tmp
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODADD);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 --out
//out = (out)^(-1) mod n = ((dA+1)*rand2)^(-1) mod n
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), a); //B1 a --out
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODINV);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), ainv); //A1 ainv --(out)^(-1)
//tmp = (k+r) mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 a --k
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 b --r
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODADD);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 out--tmp
//tmp = tmp*(t2) mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 a--tmp
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 b--t2
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODMUL);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 out--tmp
//tmp = (out)*(tmp) mod n = (((dA+1)*t2)^(-1))*((k+r)*(t2)) mod n = ((dA+1)^(-1))*(k+r) mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 a--out
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 b--tmp
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODMUL);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 out--tmp
//s = (tmp - r) mod n = (((dA+1)^(-1))*(k+r) - r) mod n = ((dA+1)^(-1))*(k+r-(dA+1)r) mod n = ((dA+1)^(-1))*(k-r*dA) mod n
pke_load_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), a); //A1 a--tmp
pke_load_operand_256bits((uint32_t *)(rPKE_B(1u,32u)), b); //B1 b--r
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODSUB);
pke_read_operand_256bits((uint32_t *)(rPKE_A(1u,32u)), out); //A1 out--s
//使用情况统计
busy:A0-A4, B0-B5
//所需缓存max
1.tmp:32B 1*32
2.曲线参数:p p_h Gx Gy a b n 7*32
3.随机数:k,t1,t2 3*32
4.pz:1*32
//hp pke ram
ramA:0x400-0x0DFC+4 = 0x400-0x0E00
ramB:0x1000-0x19FC+4 = 0x1000-0x1A00
init
0x1820:p
0x1820+1*32:p_h
0x1820+2*32:Gx
0x1820+3*32:Gy
0x1820+4*32:a
0x1820+5*32:b
0x1820+6*32:n
0x1820+7*32:n_h
0x1820+8*32:k
0x1820+9*32:t1
0x1820+10*32:t2
0x1820+11*32:pz
//B
0x80000000+0x1000U+(1*32)
//A
0x80000000+0x0400U+(1*32)
eccp_p = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 0*SM2_BYTE_LEN);//1700
eccp_p_h = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 1*SM2_BYTE_LEN);//1720
eccp_Gx = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 2*SM2_BYTE_LEN);//1740
eccp_Gy = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 3*SM2_BYTE_LEN);//1760
eccp_a = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 4*SM2_BYTE_LEN);//1780
eccp_b = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 5*SM2_BYTE_LEN);//17A0
eccp_n = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 6*SM2_BYTE_LEN);//17C0
eccp_n_h = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 7*SM2_BYTE_LEN);//17E0
rand_k = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 8*SM2_BYTE_LEN);//1800
rand1 = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 9*SM2_BYTE_LEN);//1820
rand2 = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 10*SM2_BYTE_LEN);//1840
pz = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 11*SM2_BYTE_LEN);//1860
dA = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 12*SM2_BYTE_LEN);//1880
r = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 13*SM2_BYTE_LEN);//18A0
out = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 14*SM2_BYTE_LEN);//18C0
tmp = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 15*SM2_BYTE_LEN);//18E0
value_one = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 16*SM2_BYTE_LEN);//1900
e = (uint32_t *)(PKE_RAM_SIGN_BUFFER_OFFSET + 16*SM2_BYTE_LEN);//1920
debug_out //1980
//get rand k, t1, t2
//k
B6D481A1F3689D9A4177591CDDB71DEECA181B960712B0D973DDB3B38D0C2644
//t1
1111111111111111111111111111111111111111111111111111111111111111
//t2
1111111111111111111111111111111111111111111111111111111111111111
//[k](Gx,Gy), r=Px
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), eccp_Gx); //B1 Px
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(2u,32u)), eccp_Gy); //B2 Py
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(3u,32u)), pz); //A3 Pz
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(3u,32u)), eccp_b); //B3 b ---- corrupted after calculating
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(4u,32u)), eccp_a); //B4 a---- if a is not 0, B4 is corrupted after calculating.
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(5u,32u)), eccp_n); //B5 order---- corrupted after calculating
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(4u,32u)), rand_k); //A4 k---- corrupted after calculating
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_PMUL_SEC);
pke_dma_ram_move_sm2(r, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 Qx, save r
//r
//set mgmr pre value of n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(0u,32u)), eccp_n); //A0 p--eccp_n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(0u,32u)), eccp_n_h); //B0 h--eccp_n_h
pke_pre_calc_mont_N0();
//out = (dA - t1) mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), dA); //A1 a--dA
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), rand1); //B1 b--t1
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODSUB);
pke_dma_ram_move_sm2(out, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 --out
//out = (out + 1) mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), out); //A1 --out
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), value_one); //B1 --1
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODADD);
pke_dma_ram_move_sm2(out, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 --out
//out = (out)*t2 mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), out); //A1 a--out
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), rand2); //B1 b--t2
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODMUL);
pke_dma_ram_move_sm2(out, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 --out
//tmp = t1*t2 mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), rand1); //A1 a--t1
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), rand2); //B1 b--t2
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODMUL);
pke_dma_ram_move_sm2(tmp, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 --tmp
//out = (out+tmp) mod n = ((dA+1)*rand2) mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), out); //A1 --out
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), tmp); //B1 --tmp
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODADD);
pke_dma_ram_move_sm2(out, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 --out
//out = (out)^(-1) mod n = ((dA+1)*rand2)^(-1) mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), out); //B1 a --out
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODINV);
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), out); //A1 out = ainv --(out)^(-1)
//tmp = (k+r) mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), rand_k); //A1 a --k
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), r); //B1 b --r
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODADD);
pke_dma_ram_move_sm2(tmp, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 out--tmp
//tmp = tmp*(t2) mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), tmp); //A1 a--tmp
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), rand2); //B1 b--t2
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODMUL);
pke_dma_ram_move_sm2(out, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 out--tmp
//tmp = (out)*(tmp) mod n = (((dA+1)*t2)^(-1))*((k+r)*(t2)) mod n = ((dA+1)^(-1))*(k+r) mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), out); //A1 a--out
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), tmp); //B1 b--tmp
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODMUL);
pke_dma_ram_move_sm2(out, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 out--tmp
//s = (tmp - r) mod n = (((dA+1)^(-1))*(k+r) - r) mod n = ((dA+1)^(-1))*(k+r-(dA+1)r) mod n = ((dA+1)^(-1))*(k-r*dA) mod n
pke_dma_ram_move_sm2((uint32_t *)(rPKE_A_OFFSET(1u,32u)), tmp); //A1 a--tmp
pke_dma_ram_move_sm2((uint32_t *)(rPKE_B_OFFSET(1u,32u)), r); //B1 b--r
ret = pke_set_micro_code_start_wait_return_code(MICROCODE_MODSUB);
pke_dma_ram_move_sm2(out, (uint32_t *)(rPKE_A_OFFSET(1u,32u))); //A1 out--s
//output r and s and clear pke ram
pke_dma_ram_move_sm2(output, r);
pke_dma_ram_move_sm2(&output[(32/4)], out);
pke_dma_claer();
//step 2: prepare [k]G
memcpy_(signature_r, output, 32);
memcpy_(signature_s, &output[32/4], 32);
//t1
1111111111111111111111111111111111111111111111111111111111111111
//t2
1111111111111111111111111111111111111111111111111111111111111111
//dA
B6D481A1F3689D9A4177591CDDB71DEECA181B960712B0D973DDB3B38D0C2644
//k
11223344F3689D9A4177591CDDB71DEECA181B960712B0D973DDB3B38D0C2644
//r
3FE74EFD87D75CA2C4A776D860B869089A5662F3B2A395DDFB785B7BB600BFB7
//out = (dA - t1) mod n
A5C37090E2578C893066480BCCA60CDDB9070A84F6019FC862CCA2A27BFB1533
//out = (out + 1) mod n
A5C37090E2578C893066480BCCA60CDDB9070A84F6019FC862CCA2A27BFB1534
//out = (out)*t2 mod n
8C6195EE1C552CE4922869B5E14D751E8CAEFD73D9E4C3969326D2286D1CD3D6
//tmp = t1*t2 mod n
7D4AC3925BBE3378DE4D7064769752EB0C9D1C83078F70862EDF57FE8BB42F91
//out = (out+tmp) mod n = ((dA+1)*rand2) mod n
9AC59817813605D7075DA1A57E4C80A27483A8BBFAE2EF16E4A361DBEFBC244
//out = (out)^(-1) mod n = ((dA+1)*rand2)^(-1) mod n
E56142D0C399D14892B029BCB84BB36127451B4737994562F738CBDF07F903C3
//tmp = (k+r) mod n
510982427B3FFA3D061ECFF53E6F86F7646E7E89B9B646B76F560F2F430CE5FB
//tmp = tmp*(t2) mod n
4DC6059642214E556CA785C16B60370C1EAADE304ACE1DAE0795E7B41B70B357
//tmp = (out)*(tmp) mod n = (((dA+1)*t2)^(-1))*((k+r)*(t2)) mod n = ((dA+1)^(-1))*(k+r) mod n
8FE4DE0A7E70218347494381EB2D6EBB3726099694E960FB546227F4780ECC6A
//s = (tmp - r) mod n = (((dA+1)^(-1))*(k+r) - r) mod n = ((dA+1)^(-1))*(k+r-(dA+1)r) mod n = ((dA+1)
4FFD8F0CF698C4E082A1CCA98A7505B29CCFA6A2E245CB1D58E9CC78C20E0CB3
四、自测
1、变量内存占用
uint8_t value_8;
printf("value_8 = %d\n",sizeof(value_8)); //1bytes
uint16_t value_16;
printf("value_16 = %d\n",sizeof(value_16)); //2bytes
uint32_t value_32;
printf("value_32 = %d\n",sizeof(value_32)); //4bytes
uint32_t *p_32;
printf("p_32 = %d\n",sizeof(p_32)); //4bytes
uint8_t *p_8;
printf("p_8 = %d\n",sizeof(p_8)); //4bytes
uint32_t tmp[5];
printf("tmp[5] = %d\n",sizeof(tmp)); //20bytes
typedef void (*SKE_CALLBACK)(void);
SKE_CALLBACK call;
printf("call=%d",sizeof(call)); //4Bytes
typedef struct{
uint32_t block_bytes;
uint32_t block_words;
} SSS;
SSS S;
SSS *pS = &S;
//S=8 pS=4
printf("S=%d pS=%d",sizeof(S),sizeof(pS));
typedef enum {
SKE_GENERATE_MAC = 0,
SKE_VERIFY_MAC = 1,
A = 2,
B = 3,
C = 4,
} SKE_MAC;
SKE_MAC S;
SKE_MAC *p = &S;
//S=1 pS=4
printf("S=%d pS=%d",sizeof(S),sizeof(p));
2、words与bytes
bytes转words
//大端:数据高位放在低地址
uint8_t message[16] = {0};
uint32_t des[4] = {0};
//数组
//00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
print_buf_U8(message,16, "message");
//00000000 00000000 00000000 00000000
print_buf_U32(des,4, "des");
//61 62 63 64 00 00 00 00 00 00 00 00 00 00 00 00
//地址从左到右递增,“大端模式”
memcpy_(message, "abcd", 4);
//64636261 00000000 00000000 00000000
//地址从左到右递增,“大端模式”(可以用u8输出查看)
uint32_copy(des, (uint32_t *)message, 1);
//61 62 63 64 00 00 00 00 00 00 00 00 00 00 00 00
print_buf_U8(message,16, "message");
//64636261 00000000 00000000 00000000
print_buf_U32(des,4, "des");
//61 62 63 64 00 00 00 00 00 00 00 00 00 00 00 00
print_buf_U8(des,16, "des");
uint32_t k_buf[4];
uint8_t *p = k_buf;
//函数里面数组赋值,还是小端模式,地位放在低地址
uint32_set(k_buf, 0x01020304, 4);
//0x4 0x3 0x2 0x1
printf("0x%x 0x%x 0x%x 0x%x\n\n",*p, *(p+1),*(p+2), *(p+3));
k_buf[0] = 0x05060708;
//0x8 0x7 0x6 0x5
printf("0x%x 0x%x 0x%x 0x%x\n\n",*p, *(p+1),*(p+2), *(p+3));
//数值
uint32_t num_32 = 0x12345678;
uint32_t *p = &num_32;
//pnum_32 = 0x12345678 p_num_32=0x001343a4 p=0x001343a4 *p=0x12345678
printf("pnum_32 = 0x%08x p_num_32=0x%08x p=0x%08x *p=0x%08x",num_32, &num_32, p, *p);
uint32_t num_32 = 0x12345678; //小端存储,Xilinx,FPGA
uint8_t *p8 = &num_32;
//0x78 0x56 0x34 0x12 小端存储
printf("0x%x 0x%x 0x%x 0x%x",*p8, *(p8+1),*(p8+2), *(p8+3));
//VS环境
//adress:0x0064FEA0 0x0064FEA1 0x0064FEA2 0x0064FEA3
//value : 78 56 34 12
uint32_t num_32 = 0x12345678;
uint32_t *p = &num_32;
//pnum_32 = 0x12345678 p_num_32=0x0064fea0 p=0x0064fea0 *p=0x12345678 &p=0x0064fea0
printf("pnum_32 = 0x%08x p_num_32=0x%08x p=0x%08x *p=0x%08x", num_32, &num_32, p, *p);
3、常用函数
//8位输出
print_buf_U8(ctx->block_buf, 0x10, "ctx->block_buf");
//32位输出
print_buf_U32(buf,8, "all_32");
void uint32_XOR(uint32_t *A, uint32_t *B, uint32_t *C, uint32_t wordLen)
//复制
memcpy_(message, "abc", 3);
memcpy_(mac, (uint8_t*)msg + msg_bytes, 0x0C);
//清零
uint32_clear((uint32_t *)ctx->block_buf, 4);
//DMA宏定义
#ifdef SKE_LP_DMA_FUNCTION
//...
#endif
//memset函数
memset_((uint8_t*)msg + msg_bytes, 0x80, 1);
memset_((uint8_t*)msg + msg_bytes + 1, 0, ctx->ske_xcbc_mac_ctx->block_bytes - 1 - remainder_bytes);
//32位异或
uint32_XOR(msg + block_num * ctx->ske_cmac_ctx->block_words, (uint32_t *) ctx->k2, tmp_out, ctx->ske_cmac_ctx->block_words);
DMA与CPU
//DMA初始化
ret = ske_lp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k_buf, sp_key_idx, iv);
//ske_lp_dma_init包含了ske_lp_init_internal操作
ret = ske_lp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k_buf, sp_key_idx, iv);
/* ret = ske_lp_init_internal(ctx->ske_xcbc_mac_ctx, SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, key, sp_key_idx, NULL,SKE_LP_DMA_ENABLE);*/
4、常见问题
1)debug找不到文件。Xilinx工程只能开一个debug,开了其他会存在问题
5、自写函数
1)异或
//异或函数
void xor_U8(uint8_t *p_m1, uint8_t *p_m2, uint8_t *p_buf, uint8_t len)
{
uint32_t i;
for (i = 0;i < len;i++)
{
*p_buf = (*p_m1)^(*p_m2);
p_m1++;
p_m2++;
p_buf++;
}
return ;
}
void xor_U32(uint32_t *p_m1, uint32_t *p_m2, uint32_t *p_buf, uint32_t wordLen)
{
uint32_t i;
for (i = 0;i < wordLen;i++)
{
*p_buf = (*p_m1)^(*p_m2);
p_m1++;
p_m2++;
p_buf++;
}
return ;
}
void ToUpper(string &str)
{
for (int i = 0; i < str.length(); i++)
if (str[i] >= 'a' && str[i] <= 'z')
str[i] = str[i] - ('a' - 'A');
return;
}
void XOR(string &str1, string &str2, string &res)
{
for (int i = 0; i < str1.length(); i++)
{
int x = str1[i];
int y = str2[i];
if (x > '9') x = x - 65 + 10;
else
x = x - '0';
if (y > '9') y = y - 65 + 10;
else
y = y - '0';
int res1 = x^y;
if (res1 <= 9)
res[i] = res1 + '0';
else
res[i] = res1 - 10 + 'A';
}
}
int main()
{
string str1 = "6C72951F4A79A729665278DE4C7D57BE";
string str2 = "308259D26E875DDCE7F371D723B6ADCE";
string res = "00000000000000000000000000000000";
ToUpper(str1);
ToUpper(str2);
XOR(str1, str2, res);
std::cout << res;
return 0;
}
//XOR
string XOR(string &str1, string &str2)
{
string res;
int x, y;
for (int i = 0; i < str1.length(); i++)
{
if (str1[i] >= '0' && str1[i] <= '9')
x = str1[i] - '0';
else
x = str1[i] - 'A' + 10;
if (str2[i] >= '0' && str2[i] <= '9')
y = str2[i] - '0';
else
y = str2[i] - 'A' + 10;
x = x^y;
if (x < 10)
res = res + (char)(x + '0');
else
res = res + (char)(x + 'A' - 10);
}
return res;
}
2)打印输出
//打印输出
void AES_XCBC_MAC_Print(uint32_t *pHexText, uint32_t HexTextLen, char *pStrExplain)
{
printf("\r\n\r\n");
while( *pStrExplain != '\0')
printf("%c",*pStrExplain++);
printf("\r\n");
for(int i=0; i<HexTextLen; i++)
printf("%02x ",*pHexText++);
return ;
}
AES_XCBC_MAC_Print(out, len/4, "out");
AES_XCBC_MAC_Print(std_out_, len/4, "std_out_");
3)计算串口时间
//串口计算中间时间函数
void calc_time()
{
while (1)
{
int a, b, c, d;
std::cin >> a >> b >> c >> d;
int e, f, g, h;
std::cin >> e >> f >> g >> h;
double num1 = 3600 * a + 60 * b + c + d*0.001;
double num2 = 3600 * e + 60 * f + g + h*0.001;
std::cout << num2 - num1 << std::endl;
std::cout << std::endl;
std::cout << std::endl;
}
return;
}
4)判断是否整数倍(含0)
//位运算
//不是block整数倍就返回错误
if(bytes & (g_ske_ctx->block_bytes - 1))
{
return SKE_INPUT_INVALID;
}
5)大小端转换
uint32_t swap_endian(uint32_t val)
{
val = ((val << 8) & 0xFF00FF00 | ((val>>8) & 0xFF00FF));
return (val << 16) | (val >>16);
}
6)&|~运算
//~取反
uint8_t a = 0xFFFF;
//1111 1111 11111 1111
printf("%u\n",a);
a = ~a; //取反
//0000 0000 0000 0000
printf("%u",a);
//对4-5位清零,[31,0],对区间bit与0做&运算
uint32_t a = 0xFFFF;
uint32_t mask = ~(3<<(4-1));
//11111 1111 11111 1111
printf("%u\n",a);
a &= mask;
//11111 1111 1110 0111
printf("%u",a);
//接上,对4-5赋值10,[31,0],对区间bit与1做|运算
uint32_t flag = 2<<(4-1);
a |= flag;
//11111 1111 1111 0111
printf("%u",a);
6、10位补足
bit位补足至一个block,XXXX10000...
//不初始化会有脏数据
uint32_t msg[4] = {0};
uint32_t msg_bytes = 13, remainder_bytes;
uint8_t *p = msg;
//00000000000000000000000000000000
print_buf_U8((uint8_t *)msg, 16, "msg");
if(msg_bytes & 0x0F)
{
//msg_bytes=0无效
msg[msg_bytes/4] |= 0x80<<((msg_bytes&3)*8);
remainder_bytes = msg_bytes & 0x0F;
}
else
{
remainder_bytes = 16;
}
printf("remainder_bytes=%d\n",remainder_bytes); //13
//00000000000000000000000000800000
print_buf_U8((uint8_t *)msg, 16, "msg");
7、Keil5 统计占用
//stack最大占用 & 最深栈链
1.设置-output-勾选Debug Infomation & Create HEX File & Browse Infomation
2.在Objects\hello_word路径下打开.htm文件
//code占用
1.设置-listing-linker Listing 全勾选
2.编译后,查看map文件(双击Debug目录)-Image component sizes
3.注意编译优化级别
8、运行时栈使用统计
//keil5工程中,stack size在启动文件startup_CM3DS.s,栈的起始结束地址在.lst文件中,__initial_sp
//init-栈空间全赋值0xFF
uint32_t i = 0;
uint8_t *p = (uint8_t *)0x20004d50;
for(i=0; i<17408/*栈空间*/; i++)
{
*(p+i) = 0xFF;
}
i=1;
p = (uint8_t *)0x20004d50;
//middle-统计前的开始地址,栈地址使用从高地址往低地址
for(i=0; i<17408/*栈空间*/; i++)
{
if(*(p+i) != 0xFF)
{
printf("begin=0x%08x ", p+i);
break;
};
}
//final-统计后的结束地址
for(i=0; i<17408/*栈空间*/; i++)
{
if(*(p+i) != 0xFF)
{
printf("end=0x%08x ", p+i);
break;
};
}
最后相减得到middle-final阶段的栈最大使用空间
注:优化级别会影响实际栈空间使用
9、keil5生成静态库
1.创建工程
2.设置-output-生成静态库
注:应该跟设备类型无关,不需要启动文件
10、keil5使用静态库
1.创建工程,添加启动文件
2.添加测试代码,lib直接添加进来
11、keil5使用问题
1)添加启动工程:新建项目时选择设备-勾选启动文件
2)提示找不到“core_cm3.h”:点击魔法棒-添加路径E:\CZHSoftware\keil5\Keil_v5\ARM\PACK\ARM\CMSIS\5.3.0\CMSIS\Include
3)屏蔽警告:魔法棒-C/C++
12、Xilinx
1)命令
objdump.exe -D hello.elf > seip.asm
2)统计代码占用
1.copy一份旧工程
2.main函数加上printf,使得空白工程占用约71368B
3.从顶层逐步加入代码编译,得到差值即为code大小
3)反汇编查看
project -> C/C++ Build -> Settings -> Build Steps ->
//xilinx把elf反汇编成asm操作,结果是能保证完整性和正确性,工具链实现
arm-none-eabi-objdump -D ${ProjName}.elf > ${ProjName}.asm
//示例
//调整优化级别,汇编代码可能会有变化
//00112bcc函数地址,每次转换可能不一样
00112bcc <hash_wait_till_done>:
112bcc: e3a02000 mov r2, #0
112bd0: e34423c0 movt r2, #17344 ; 0x43c0
112bd4: e5923000 ldr r3, [r2]
112bd8: e3130001 tst r3, #1
112bdc: 1afffffc bne 112bd4 <hash_wait_till_done+0x8>
112be0: e12fff1e bx lr
4)加快代码编译速度
project -> C/C++ Build -> Behavior -> Enable parallel build(勾选)
13、查看keil5编译器版本
//E:\CZHSoftware\keil5\Keil_v5\ARM\ARMCC\bin
./armcc.exe -h
//output
Product: MDK Plus 5.25
Component: ARM Compiler 5.06 update 6 (build 750)
14、使用芯莱工具链查看.o文件大小
//windows-cmd
E:\NucleiStudio_IDE_202204-win64\NucleiStudio\toolchain\gcc\bin>E:\NucleiStudio_IDE_202204-win64\NucleiStudio\toolchain\gcc\bin\riscv-nuclei-elf-size.exe D:\2023.02_PKE_HP\IAR_SA\fpga_pke-hp\Objects\aes.o
//查看程序的代码段(只包含链接进去的函数?)
E:\NucleiStudio_IDE_202204-win64\NucleiStudio\toolchain\gcc\bin>riscv-nuclei-elf-size.exe D:\2023.02_PKE_HP\IAR_SA\fpga_pke-hp\Objects\hello_world.axf
//批量输出当前目录所有.o文件的信息
find ./ -name "*.o" | xargs /e/NucleiStudio_IDE_202204-win64/NucleiStudio/toolchain/gcc/bin/riscv-nuclei-elf-size.exe
15、统计SM9 h和l计算耗时
//sm9.c
printf("sm9_sign_with_r h+l begin\r\n");
startP();
//get h = H2(msg||w, N)
ret = sm9_h1_h2(2, msg, msg_bytes, h2rf_para, 32*12, el);
if(PKE_SUCCESS != ret)
{
return ret;
}
else
{;}
u32little_to_u8big(h, el);
//el = (r-h) mod n
ret = pke_modsub((uint32_t *)sm9p256v1_n, r, el, el, SM9_BASE_WORD_LEN);
if(PKE_SUCCESS != ret)
{
return ret;
}
else
{;}
endP(0,1,1);
printf("sm9_sign_with_r h+l end\r\n");
16、keil5统计code size
code size=code+RO-data+RW-data
例:预统计sm2 code size
1.记录main.c初始大小(空白工程),记录C1=code size
2.添加想要统计的算法库代码(可多不可少)
3.调用sm2.c中某个函数,重新全部编译,记录C2=code size
4.sm2_code_size=C2-C1
注:以上统计是以文件为单位,若只统计链接的函数,设置-C/C++-One ELF Section per Function
五、算法调试自测函数
1、cmac
#include "../driver/crypto_include/ske/ske_cmac.h"
uint32_t ske_sec_cmac(SKE_ALG alg, SKE_MAC mac_action, uint8_t *key, uint16_t sp_key_idx, uint8_t *msg, uint32_t msg_bytes,
uint8_t *mac, uint8_t mac_bytes);
void CZH_CMAC()
{
uint32_t ret;
uint8_t key[8] = {0xe0,0x70,0x99,0xf1,0xbf,0xaf,0xfd,0x7f};
uint8_t msg[] = {0x61,0x62,0x63};
uint8_t msg_bytes = 3;
uint8_t mac[16];
uint8_t mac_bytes = 8;
ret = ske_sec_cmac(SKE_ALG_DES, SKE_GENERATE_MAC, key, 0, msg, msg_bytes, mac, mac_bytes);
printf("ret = %d\r\n", ret);
//std mac:EE3F707F2C11D297
print_buf_U8(mac, mac_bytes, "mac");
}
2、ccm
void CZH_AES128_CCM()
{
uint32_t ret;
uint8_t key[16] = {0x27,0xF8,0x67,0x57,0xEE,0x3A,0x22,0xCF,0x32,0x1E,0x2C,0x04,0x93,0x1D,0xD9,0x5F};
uint8_t nonce[7] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77};
uint8_t msg[] = {0x3A,0x1A,0x07,0x58,0x2F,0xEE,0xCD,0x2F,0x6C,0x42,0xD1,0x8A,0x04,0x18,0x90,0x82};
uint8_t msg_bytes = 16;
uint8_t mac[16];
uint8_t mac_bytes = 6;
uint32_t aad_bytes = 0;
uint8_t cipher[16];
ret = ske_sec_ccm_crypto(SKE_ALG_AES_128, SKE_CRYPTO_ENCRYPT, key, 0, nonce,
6, 8, NULL, aad_bytes, msg, cipher, msg_bytes, mac);
printf("ret = %d\r\n", ret);
//std cipher:B82F54D9D7AE4D0E739BA821416A4C46
print_buf_U8(cipher, msg_bytes, "cipher");
//std mac:F6049BE2C785
print_buf_U8(mac, mac_bytes, "mac");
}
3、xts
void CZH_AES128_XTS()
{
uint32_t ret;
uint8_t key[32] = {0x27,0xF8,0x67,0x57,0xEE,0x3A,0x22,0xCF,0x32,0x1E,0x2C,0x04,0x93,0x1D,0xD9,0x5F,0x9D,0xAD,0x1F,0xD7,0x2D,0x56,0x81,0x7C,0x4E,0x3E,0x0A,0x49,0xAA,0x46,0x23,0x78};
uint8_t i[16] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88};
uint8_t msg[33] = {0x27,0xC0,0x66,0xD4,0xF4,0x6C,0x71,0x6C,0x9C,0x7F,0x7E,0xD0,0x1F,0x4B,0x68,0x12,0xCA,0xE8,0xE5,0x54,0x9F,0x27,0x6F,0x70,0x3D,0x7A,0xEB,0xFA,0x39,0x7A,0x74,0xD3,0x11};
uint8_t msg_bytes = 33;
uint8_t cipher[33] = {0};
ret = ske_sec_xts_crypto(SKE_ALG_AES_128, SKE_CRYPTO_ENCRYPT, key, 0, i,
msg, cipher, msg_bytes);
printf("ret = %d\r\n", ret);
print_buf_U8(cipher, msg_bytes, "cipher");
}
六、项目
1、ske_hp
用ske_hp_dma_operate分段输入CBC加密过程中,不输出密文,仅最后block加密后获取一分组结果,发现是CBC结果的第一组密文。
//std_cipher=5B376580AE2F19AFE7219CEEF172756F||BDD3589AF928AC0FCA575BA9EE865651
uint8_t k1[16] = {0xC3,0x52,0x80,0x57,0x54,0x23,0x7F,0x31,0x1A,0xC0,0xFF,0xF4,0xE3,0xE0,0x3E,0x78};
uint8_t plain[32] = {0xC1,0xA6,0xA9,0x21,0xA2,0x3A,0x94,0x06,0x58,0x07,0xA0,0x8C,0xC8,0xEE,0xD0,0x6E,
0xC1,0xA6,0xA9,0x21,0xA2,0x3A,0x94,0x06,0x58,0x07,0xA0,0x8C,0xC8,0xEE,0xD0,0x6E,};
uint32_t iv[4];
uint32_clear(iv,4);
uint32_t *msg2 = (uint32_t *)DMA_RAM_BASE;
memcpy_(msg2 , plain, 32);
uint32_clear(iv,4);
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, NULL, 0, 0, callback);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, ctx->ske_xcbc_mac_ctx->block_words, 4, callback);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756f
memcpy_(msg2 , plain, 16);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, ctx->ske_xcbc_mac_ctx->block_words, 4, callback);
printf("ret=%d\n",ret);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//bdd3589af928ac0fca575ba9ee865651
ske_hp_dma_final();
//std_cipher=5B376580AE2F19AFE7219CEEF172756F||BDD3589AF928AC0FCA575BA9EE865651
uint8_t k1[16] = {0xC3,0x52,0x80,0x57,0x54,0x23,0x7F,0x31,0x1A,0xC0,0xFF,0xF4,0xE3,0xE0,0x3E,0x78};
uint8_t plain[32] = {0xC1,0xA6,0xA9,0x21,0xA2,0x3A,0x94,0x06,0x58,0x07,0xA0,0x8C,0xC8,0xEE,0xD0,0x6E,
0xC1,0xA6,0xA9,0x21,0xA2,0x3A,0x94,0x06,0x58,0x07,0xA0,0x8C,0xC8,0xEE,0xD0,0x6E,};
uint32_t iv[4];
uint32_clear(iv,4);
uint32_t *msg2 = (uint32_t *)DMA_RAM_BASE;
memcpy_(msg2 , plain, 32);
uint32_clear(iv,4);
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, NULL, 0, 0, callback);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, ctx->ske_xcbc_mac_ctx->block_words, 4, callback);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756f
memcpy_(msg2 , plain, 16);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, NULL, ctx->ske_xcbc_mac_ctx->block_words, 0, callback);
printf("ret=%d\n",ret);
print_buf_U8((uint8_t *)msg2, 16, "msg2");//第二分组密文不输出
memcpy_(msg2 , plain, 16);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, ctx->ske_xcbc_mac_ctx->block_words, 4, callback);
//获取的是第二分组的密文,现在是传了三个分组,
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//bdd3589af928ac0fca575ba9ee865651
ske_hp_dma_final();
//std_cipher=5B376580AE2F19AFE7219CEEF172756F||BDD3589AF928AC0FCA575BA9EE865651
uint8_t k1[16] = {0xC3,0x52,0x80,0x57,0x54,0x23,0x7F,0x31,0x1A,0xC0,0xFF,0xF4,0xE3,0xE0,0x3E,0x78};
uint8_t plain[32] = {0xC1,0xA6,0xA9,0x21,0xA2,0x3A,0x94,0x06,0x58,0x07,0xA0,0x8C,0xC8,0xEE,0xD0,0x6E,
0xC1,0xA6,0xA9,0x21,0xA2,0x3A,0x94,0x06,0x58,0x07,0xA0,0x8C,0xC8,0xEE,0xD0,0x6E,};
uint32_t iv[4];
uint32_clear(iv,4);
uint32_t *msg2 = (uint32_t *)DMA_RAM_BASE;
memcpy_(msg2 , plain, 32);
uint32_clear(iv,4);
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, NULL, 0, 0, callback);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, ctx->ske_xcbc_mac_ctx->block_words, 4, callback);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756f
memcpy_(msg2 , plain, 16);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, NULL, ctx->ske_xcbc_mac_ctx->block_words, 0, callback);
printf("ret=%d\n",ret);
print_buf_U8((uint8_t *)msg2, 16, "msg2");//第二分组密文不输出
memcpy_(msg2 , plain, 16);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, ctx->ske_xcbc_mac_ctx->block_words, 8, callback);
//获取的是第2、3分组的密文 //bdd3589af928ac0fca575ba9ee865651 || a6b4bde77c4c3d2fa383a7aa135c863c
print_buf_U8((uint8_t *)msg2, 32, "msg_cbc_res");,
//密文获取完,不影响后续加密,否则影响
ske_hp_dma_final();
//std_cipher=5B376580AE2F19AFE7219CEEF172756F||BDD3589AF928AC0FCA575BA9EE865651
uint8_t k1[16] = {0xC3,0x52,0x80,0x57,0x54,0x23,0x7F,0x31,0x1A,0xC0,0xFF,0xF4,0xE3,0xE0,0x3E,0x78};
uint8_t plain[32] = {0xC1,0xA6,0xA9,0x21,0xA2,0x3A,0x94,0x06,0x58,0x07,0xA0,0x8C,0xC8,0xEE,0xD0,0x6E,
0xC1,0xA6,0xA9,0x21,0xA2,0x3A,0x94,0x06,0x58,0x07,0xA0,0x8C,0xC8,0xEE,0xD0,0x6E,};
uint32_t iv[4];
uint32_clear(iv,4);
uint32_t *msg2 = (uint32_t *)DMA_RAM_BASE;
memcpy_(msg2 , plain, 32);
uint32_clear(iv,4);
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, NULL, 0, 0, callback);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, ctx->ske_xcbc_mac_ctx->block_words, 4, callback);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756f
memcpy_(msg2 , plain, 16);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, NULL, ctx->ske_xcbc_mac_ctx->block_words, 0, callback);
printf("ret=%d\n",ret);
print_buf_U8((uint8_t *)msg2, 16, "msg2");//第二分组密文不输出
memcpy_(msg2 , plain, 16);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, ctx->ske_xcbc_mac_ctx->block_words, 4, callback);
print_buf_U8((uint8_t *)msg2, 32, "msg_cbc_res");//获取的是第2分组的密文,bdd3589af928ac0fca575ba9ee865651 || c1a6a921a23a94065807a08cc8eed06e
ske_hp_dma_final();//密文没有获取完,还有第三分组密文没获取,影响下面的加密,坑?
memcpy_(msg2 , plain, 32);
print_buf_U8((uint8_t *)iv, 16, "iv");
print_buf_U8((uint8_t *)msg2, 32, "msg2");
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, 2 * ctx->ske_xcbc_mac_ctx->block_words, 8, callback);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//上面密文没有获取完,得308259d26e875ddce7f371d723b6adce //原文00000000000000000000000000000000
print_buf_U8((uint8_t *)msg2, 32, "msg_cbc_res");//上面密文没有获取完,得308259d26e875ddce7f371d723b6adce5b376580ae2f19afe7219ceef172756f,//原文00000000000000000000000000000000F124F0F3CCBDC9DABFF4D15BEB587DA0
printf("ret=%d\n",ret);
ske_hp_dma_final();
从下面示例结果看,硬件的输出应该类似队列,软件获取的是先进先出的结果。
memcpy_(msg2 , plain, 32);
print_buf_U8((uint8_t *)iv, 16, "iv");
print_buf_U8((uint8_t *)msg2, 32, "msg2");
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, 2 * ctx->ske_xcbc_mac_ctx->block_words, 8, callback);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756f
print_buf_U8((uint8_t *)msg2, 32, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756fbdd3589af928ac0fca575ba9ee865651
printf("ret=%d\n",ret);
ske_hp_dma_final();
memcpy_(msg2 , plain, 32);
print_buf_U8((uint8_t *)iv, 16, "iv");
print_buf_U8((uint8_t *)msg2, 32, "msg2");
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, 2 * ctx->ske_xcbc_mac_ctx->block_words, 8, callback);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756f
print_buf_U8((uint8_t *)msg2, 32, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756fbdd3589af928ac0fca575ba9ee865651
printf("ret=%d\n",ret);
ske_hp_dma_final();
memcpy_(msg2 , plain, 32);
print_buf_U8((uint8_t *)iv, 16, "iv");
print_buf_U8((uint8_t *)msg2, 32, "msg2");
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, 2 * ctx->ske_xcbc_mac_ctx->block_words, 4, callback);
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756f
print_buf_U8((uint8_t *)msg2, 32, "msg_cbc_res");//5b376580ae2f19afe7219ceef172756f || c1a6a921a23a94065807a08cc8eed06e
printf("ret=%d\n",ret);
ske_hp_dma_final();
#if 0
memcpy_(msg2 , plain, 32);
print_buf_U8((uint8_t *)iv, 16, "iv");
print_buf_U8((uint8_t *)msg2, 32, "msg2");
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, 2 * ctx->ske_xcbc_mac_ctx->block_words, 8, callback);//8
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//bdd3589af928ac0fca575ba9ee865651,这是上面没有获取的密文
print_buf_U8((uint8_t *)msg2, 32, "msg_cbc_res");//dd3589af928ac0fca575ba9ee865651 || 5b376580ae2f19afe7219ceef172756f
printf("ret=%d\n",ret);
ske_hp_dma_final();
#else
memcpy_(msg2 , plain, 32);
print_buf_U8((uint8_t *)iv, 16, "iv");
print_buf_U8((uint8_t *)msg2, 32, "msg2");
ret = ske_hp_dma_init(SKE_ALG_AES_128, SKE_MODE_CBC, SKE_CRYPTO_ENCRYPT, (uint8_t *)k1, 0, (uint8_t *)iv);
ret |= ske_hp_dma_operate(ctx->ske_xcbc_mac_ctx, msg2, msg2, 2 * ctx->ske_xcbc_mac_ctx->block_words, 12, callback);//12
print_buf_U8((uint8_t *)msg2, 16, "msg_cbc_res");//bdd3589af928ac0fca575ba9ee865651,这是上面没有获取的密文
print_buf_U8((uint8_t *)msg2, 32+16, "msg_cbc_res");//dd3589af928ac0fca575ba9ee865651 || 5b376580ae2f19afe7219ceef172756f || bdd3589af928ac0fca575ba9ee865651
printf("ret=%d\n",ret);
ske_hp_dma_final();
#endif
2、芯驰
//下载工具
D:\202203_semidrive\E3 Early Access Release\SDToolBox_R2.22.0301
//ospi
D:\202206_semidrive\ssdk\boards\e3_gateway\build\ref\gcc\ospi_e3_gateway.pac
//emmc
D:\202206_semidrive\ssdk\boards\e3_gateway\build\ref\gcc\emmc_e3_gateway.pac
//工程的main文件在如下目录。
D:\202206_semidrive\ssdk\boards\e3_gateway\sf\projects\ref
//编译打包(好几分钟)windows cmd,路径为当前ssdk
//启动GCC编译,其中 -b 指示BOARD, -p 指示PROJECT
cd D:\202206_semidrive
cd ssdk
sh build.sh -b e3_gateway -p ref
//更新配置
sh tools\menuconfig.sh -b e3_gateway -p ref -c sf
//test code
D:\202206_semidrive\ssdk\test\crypto
//驱动(含通信)
D:\202206_semidrive\ssdk\drivers\crypto\osr_crypto\mailbox
//测试代码和驱动库路径
D:\202206_semidrive\ssdk\drivers\crypto
D:\202206_semidrive\ssdk\test\crypto
//mailbox
依次三个Key:生成、解密、签名
uint32_t cmd_rsa_crt_test_internal(
uint16_t ebitlen,
uint16_t nbitlen,
uint32_t idx,
cmd_key_type_e generate_key_type,
uint16_t generate_key_id,
cmd_key_type_e decrypt_key_type,
uint16_t decrypt_key_id,
cmd_key_type_e sign_key_type,
uint16_t sign_key_id
)
if (CMD_KEY_EXTERNAL_CIPHERTEXT == generate_key_type) {
//输入密文Key d,输出明文key d
KEK_decrypt(d, nByteLen, generate_key_id, d, mac_buf);
}
uint32_t cmd_rsa_decrypt(
uint8_t *msg,
uint8_t *d,
uint8_t *e,
uint8_t *n,
uint32_t nbitlen,
uint8_t *out,
cmd_key_type_e decrypt_key_type,
uint16_t decrypt_key_id,
uint8_t *mac_buf
)
uint32_t cmd_rsa_generate_signature(
uint8_t *msg, //被签名消息
uint8_t *d, //私钥
uint8_t *e, //公钥
uint8_t *n, //大整数
uint32_t nbitlen, //密钥位数
uint8_t *out, //签名值
cmd_key_type_e sign_key_type, //签名密钥类型:内部/外部明文/外部密文
uint16_t sign_key_id, //key序号
uint8_t *mac_buf
)
typedef enum {
CMD_KEY_INTERNAL = 0,
CMD_KEY_EXTERNAL_PLAINTEXT,
CMD_KEY_EXTERNAL_CIPHERTEXT,
CMD_KEY_MAX,
} cmd_key_type_e;
1)RSA
a)RSA测试
//RSA测试
uint32_t cmd_rsa_test_internal(
uint16_t ebitlen, //公钥模幂,65537,统一为17?
uint16_t nbitlen,//(p-1)(q-1),RSA1024/2048/4096
uint32_t idx, //序号,统一为1
cmd_key_type_e generate_key_type, //生成key类型:内部/外部明文/外部密文(外部理解为可导/获取)
uint16_t generate_key_id,//生成Key序号
cmd_key_type_e decrypt_key_type,//解密key类型:内部/外部明文/外部密文
uint16_t decrypt_key_id, //解密key序号
cmd_key_type_e sign_key_type, //签名key类型:内部/外部明文/外部密文
uint16_t sign_key_id //签名key序号
)
//获取RSA密钥对 私钥(d,n),公钥(e,n),密钥属性为generate_key_type
cmd_rsa_generate_key(ebitlen, nbitlen, generate_key_type, generate_key_id, n, e, d, mac_buf)
if (generate_key_type == cmd_key_external_ciphertext)
//私钥解密到Key原地址,【解密密钥不清楚是什么】
KEK_decrypt(d, nByteLen, generate_key_id, d, mac_buf)
//循环测试-加密&解密&签名&验签
//获取随机数,小于n
//enc
cmd_trng_get_rand(in, nByteLen)
((uint32_t *)in)[0] = 0
cmd_rsa_encrypt(in, e, n, nbitlen, out)
//dec
if (decrypt_key_type == cmd_key_external_plaintext)
cmd_rsa_decrypt(out, d, e, n, nbitlen, out, decrypt_key_type, decrypt_key_id, mac_buf)
else if(decrypt_key_type == cmd_key_external_ciphertext)
//【加密输出到d+0x200暂不清楚原因】
KEK_decrypt(d, nByteLen, generate_key_id, d+0x200, mac_buf)
cmd_rsa_decrypt(out, (d + 0x200), e, n, nbitlen, out, decrypt_key_type, decrypt_key_id, mac_buf)
else return -1 //RSA解密时,解密密钥类型不能是internal?
//sign
if (sign_key_type == cmd_key_external_plaintext)
cmd_rsa_generate_signatrue(in,d,e,n,nbitlen,out,sign_key_type,sign_key_id,mac_buf)
else if(sign_key_type == cmd_key_external_ciphertext)
EKE_encrypt(d,nBytelen,sign_key_id,d+0x200,mac_buf)
cmd_rsa_generate_signatrue(in,d+0x200,e,n,nbitlen,out,sign_key_type,sign_key_id,mac_buf)\
else return -1////RSA签名时,解密密钥类型不能是internal?
//verify
cmd_rsa_verify_signature(in, e, n, nbitlen, out)
//无效签名验签
//签名值第1个words自增1,不通过则成功
cmd_rsa_verify_signature
b)RSA-CRT测试
//RSA-CRT测试
cmd_rsa_generate_crt_key(ebitlen, nbitlen, generate_key_type, generate_key_id, n, e, rsa_crt_pri_key, mac_buf)
//----------
typedef struct {
uint8_t p_ptr[4];
uint8_t q_ptr[4];
uint8_t dp_ptr[4];
uint8_t dq_ptr[4];
uint8_t u_ptr[4];
} rsa_crt_pri_key_ptr_t; //RSA-CRT五元组结构体
//----------
if (generate_key_type == cmd_key_external_ciphertext)
//依次对p,q,dp,dq,u加密
KEK_decrypt(p,pByteLen,generate_key_id,p,mac_buf)
...
KEK_decrypt(u,pByteLen,generate_key_id,u,mac_buf)
//循环测试
//获取随机数,小于n
//enc
cmd_trng_get_rand(in, nByteLen)
((uint32_t *)in)[0] = 0
cmd_rsa_encrypt(in, e, n, nbitlen, out)
//dec
if (decrypt_key_type == cmd_key_external_plaintext)
//设置私钥
cmd_rsa_set_crt_prikey_ptr(p, q, dp, dq, u, rsa_crt_pri_key)
else if(decrypt_key_type == cmd_key_external_ciphertext)
//依次对p,q,dp,dq,u加密到X+0x100位置,然后再设置私钥
KEK_decrypt(p,pByteLen,generate_key_id,p,mac_buf)
...
cmd_rsa_set_crt_prikey_ptr(p, q, dp, dq, u, rsa_crt_pri_key)
else return -1 //RSA解密时,解密密钥类型不能是internal?
//解密,相比常规少了d,增加rsa_crt_pri_key
cmd_rsa_crt_decrypt(out, e, n, nbitlen, out, decrypt_key_type, decrypt_key_id, rsa_crt_pri_key, mac_buf);
//sign
if (sign_key_type == cmd_key_external_plaintext)
cmd_rsa_set_crt_prikey_ptr(p, q, dp, dq, u, rsa_crt_pri_key);
else if(sign_key_type == cmd_key_external_ciphertext)
//依次对p,q,dp,dq,u加密到X+0x100位置,然后再设置私钥
KEK_decrypt(p,pByteLen,generate_key_id,p,mac_buf)
...
cmd_rsa_set_crt_prikey_ptr(p, q, dp, dq, u, rsa_crt_pri_key)
else return 1////RSA签名时,签名密钥类型不能是internal?
//开始签名
cmd_rsa_crt_generate_signature(in, e, n, nbitlen, out, sign_key_type, sign_key_id, rsa_crt_pri_key, mac_buf);
//【下面步骤感觉多余?】
if (CMD_KEY_EXTERNAL_CIPHERTEXT == sign_key_id)
KEK_decrypt(p + 0x100, pByteLen, sign_key_id, p, mac_buf);
//verify
cmd_rsa_verify_signature(in, e, n, nbitlen, out)
//无效签名验签
//签名值第1个words自增1,不通过则成功
cmd_rsa_verify_signature
c)自测
//RSA-enc/dec
uint8_t *n = (uint8_t *)(CMD_TEST_DMA_RAM_BASE);
uint8_t *e = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x200);
uint8_t *d = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x400);
uint8_t *in = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x800);
uint8_t *out = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0xA00);
uint8_t *mac_buf = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0xC00);
/*********** generate key pair ***********/
cmd_rsa_generate_key(ebitlen, nbitlen, CMD_KEY_EXTERNAL_PLAINTEXT, 0, n, e, d, mac_buf);
print_buf_U8(n,nByteLen,"n");
print_buf_U8(e,nByteLen,"e");
print_buf_U8(d,nByteLen,"d");
printf("***enc***");
/*get random message less than n*/
cmd_trng_get_rand(in, nByteLen);
((uint32_t *)in)[0] = 0;
print_buf_U8(in,nByteLen,"rand");
cmd_rsa_encrypt(in, e, n, nbitlen, out);
print_buf_U8(out,nByteLen,"enc_rand_out");
cmd_rsa_decrypt(out, d, e, n, nbitlen, out, CMD_KEY_EXTERNAL_PLAINTEXT, 0, mac_buf);
print_buf_U8(out,nByteLen,"dec_rand_out");
/*********** sign ***********/
cmd_rsa_generate_signature(out, d, e, n, nbitlen, out, CMD_KEY_EXTERNAL_PLAINTEXT, 0, mac_buf);
print_buf_U8(out,nByteLen,"rsa_signature");//pass
/*********** verify ***********/
cmd_rsa_verify_signature(in, e, n, nbitlen, out);
print_buf_U8(out,nByteLen,"rsa_verify");//pass
/*********** verify ***********/
cmd_rsa_verify_signature(in, e, n, nbitlen, out+1);
print_buf_U8(out+1,nByteLen,"rsa_verify");//fail
//注意密文形式
cmd_rsa_generate_key(ebitlen, nbitlen, CMD_KEY_EXTERNAL_CIPHERTEXT, 5,n, e, d, mac_buf);
print_buf_U8(n,nByteLen,"n");
print_buf_U8(e,nByteLen,"e");
print_buf_U8(d,nByteLen,"d");//密文key,测试既不是生成的公钥加密,也不是生成的私钥加密
printf("***kek dec***");
KEK_decrypt(d, nByteLen, 5, d, mac_buf);//得到d,enc(d,d)得不到上述密文key
print_buf_U8(d,nByteLen,"d");
printf("***kek enc***");
KEK_encrypt(d, nByteLen, 5, d, mac_buf);//kek-keyid=0 加密失败,d为全0
print_buf_U8(d,nByteLen,"d");//同生成的加密形式一样
//RSA-CRT
//CRT
uint8_t *p = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0xE00);
uint8_t *q = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x1000);
uint8_t *dp = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x1200);
uint8_t *dq = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x1400);
uint8_t *u = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x1600);
/*********** generate crt key pair ***********/
rsa_crt_pri_key_ptr_t *rsa_crt_pri_key = (rsa_crt_pri_key_ptr_t *)(CMD_TEST_DMA_RAM_BASE + 0x1800);
cmd_rsa_set_crt_prikey_ptr(p, q, dp, dq, u, rsa_crt_pri_key); cmd_rsa_generate_crt_key(ebitlen, nbitlen, CMD_KEY_EXTERNAL_PLAINTEXT, 1,
n, e, rsa_crt_pri_key, mac_buf);
/*********** encrypt ***********/
/*get random message less than n*/
cmd_trng_get_rand(in, nByteLen);
((uint32_t *)in)[0] = 0;
print_buf_U8(in,nByteLen,"rand");
cmd_rsa_encrypt(in, e, n, nbitlen, out);
print_buf_U8(out,nByteLen,"enc_rand_out");
/*********** decrypt ***********/ //解密形式是密文则要对密钥crt参数加密
cmd_rsa_crt_decrypt(out, e, n, nbitlen, out, CMD_KEY_EXTERNAL_PLAINTEXT, 1, rsa_crt_pri_key, mac_buf);
print_buf_U8(out,nByteLen,"dec_rand_out");
/*********** sign ***********/
cmd_rsa_crt_generate_signature(in, e, n, nbitlen, out, CMD_KEY_EXTERNAL_PLAINTEXT, 1, rsa_crt_pri_key, mac_buf);
/*********** verify ***********/
cmd_rsa_verify_signature(in, e, n, nbitlen, out);
2)SM2测试
a)SM2-Sign
//SM2签名测试流程
uint32_t cmd_sm2_sign_test_internal(
uint32_t idx,
cmd_key_type_e generate_key_type,
uint16_t generate_key_id,
cmd_key_type_e generate_sign_type,
uint16_t generate_sign_key_id
)
//生成64字节公钥、32字节私钥
cmd_sm2_generatekey(generate_key_type, generate_key_id, prikey, pubkey, mac_buf)
if(generatekey_key_type == cmd_key_external_cipher)
KEK_decrypt//如果生成Key密文,解密到key地址
//签名
while 循环测试i
cmd_trng_get_rand//随机取32字节e,原本e=SM3(Z||M),这里测试取随机值
while 循环测试j
if (generate_sign_type == cmd_key_external_plaintext)
//generate_sign_key_id=0
cmd_sm2_sign(e, prikey, generate_sign_type, 0, signature, mac_buf)
else if (generate_sign_type == cmd_key_external_ciphertext)
KEK_encrypt//加密key到prikey+32地址
cmd_sm2_sign//同上,key用prikey+32
else if (generate_sign_type == cmd_key_internal)
cmd_sm2_sign //prikey为空
//验证签名值
if(generate_sign_type == cmd_key_internal)
//复制私钥前半部分
prikey <- get_key_from_key_id(keyid_half_mask | generate_sign_key_id, 16)
//复制私钥后半部分
prikey+16 <- get_key_from_key_id(generate_sign_key_id, 16)
//从私钥获取公钥,内部应该是直接椭圆曲线计算
pubkey <- cmd_sm2_get_pubkey_from_prikey(prikey);
cmd_sm2_verify(e,pubkey,signature)
//无效签名验证
//修改签名值第1words自增数值1,不通过就成功
(uint32_t *)signature[0] += 1;
cmd_sm2_verify
b)SM2-Enc
//SM2加密测试流程
uint32_t cmd_sm2_enc_test_internal(
uint32_t idx,
cmd_key_type_e decrypt_key_type,
uint16_t decrypt_key_id
)
if(decrypt_key_type != cmd_key_internal)
//生成64字节公钥、32字节私钥,generate_key_id=0
cmd_sm2_generatekey(decrypt_key_type, 0, prikey, pubkey, mac_buf)
else
//复制私钥前半部分,【什么值暂不清楚,反正会计算对应公钥】
prikey <- get_key_from_key_id(keyid_half_mask | decrypt_key_id, 16)
//复制私钥后半部分
prikey+16 <- get_key_from_key_id(decrypt_key_id, 16)
//从私钥获取公钥,内部应该是直接椭圆曲线计算
pubkey <- cmd_sm2_get_pubkey_from_prikey(prikey); //64字节
//加密
while 循环测试i
...//获取随机长度随机内容msg
cmd_sm2_enc(msg, msg_len, pubkey, cipher)
//解密
if(decrypt_key_type == cmd_key_external_plaintext)
//密文长度+97,decrypt_key_id=0
cmd_sm2_dec(prikey, msg2, cipher, (msg_len + 97), decrypt_key_type, 0, mac_buf)
else if (decrypt_key_type == cmd_key_external_ciphertext)
//内部密钥对私钥加密,相当于外部密文私钥输入,到prikey+32位置
KEK_encrypt(prikey, 32, decrypt_key_id, prikey + 32, mac_buf)
cmd_sm2_dec(prikey+32, msg2, cipher, (msg_len + 97), decrypt_key_type, decrypt_key_id, mac_buf)
else if (decrypt_key_type == cmd_key_internal)
//内部otp私钥做加密,prikey = 0
cmd_sm2_dec(0, msg2, cipher, (msg_len + 97), decrypt_key_type, decrypt_key_id, mac_buf)
c)SM2-Exchange
//协商流程
//A方:公私钥对(Da,Pa)、Pb、临时公私钥对(ra,Ra),B方ID
//B方:公私钥(Db,Pb)、Pa、临时公私钥对(rb,Rb),A方ID
//ID用来生成各自的Z值��_�� 和��_��,Z值生成同SM2签名的预计算1
//x1是Ra的x坐标
x1' = 2^w+(x1 & (2^w - 1)) //w=127
if ra_and_Da_not_on_ECC() return fail
Ta = (Da + x1' * ra) mod n
if (Rb_not_on_ECC) return fail
//x2来自Rb的x坐标
x2' = 2^w + (x2 & (2^w - 1))
t2 = (Ta*x2') mod n
U = [Ta]Pb + [t2]Rb
//将上述结果转换为字节串形式(Xu,Yu)
发起方:K = KDF(Xu || Yu || Za || Zb)
响应方:K = KDF(Xu || Yu || Zb || Za)
若本方是发起方,计算��_1=ℎ����ℎ(〖0��02||��〗_�� ||ℎ����ℎ(��_�� ||��_�� | 〖|��〗_�� ||��_1 ||��_1 ||��_2 ||��_2) ) , ��_��=ℎ����ℎ(〖0��03||��〗_�� ||ℎ����ℎ(��_�� ||��_�� | 〖|��〗_�� ||��_1 ||��_1 ||��_2 ||��_2) )
否则若本方是响应方,计算��_��=ℎ����ℎ(〖0��02||��〗_�� ||ℎ����ℎ(��_�� ||��_�� | 〖|��〗_�� ||��_2 ||��_2 ||��_1 ||��_1) ) ,��_2=ℎ����ℎ(〖0��03||��〗_�� ||ℎ����ℎ(��_�� ||��_�� | 〖|��〗_�� ||��_2 ||��_2 ||��_1 ||��_1) )
//SM2密钥交换/协商
cmd_sm2_exckey_test_internal(
uint32_t idx, //1
cmd_key_type_e dA_key_type, //A方公私密钥对类型
uint16_t dA_key_id, //id
cmd_key_type_e rA_key_type, //A方临时密钥对类型
uint16_t rA_key_id, //id
uint16_t enc_key_id,//加密密钥id
cmd_key_type_e output_key_type, //输出的协商密钥类型
uint16_t output_key_id//id
)
//模拟双方生成公私钥对、临时公私钥对,一共4对
cmd_sm2_generatekey(dA_key_type, 0, dA, PA, mac_buf);//0 代表明文key
cmd_sm2_generatekey(rA_key_type, 0, rA, RA, mac_buf);
cmd_sm2_generatekey(dA_key_type, 0, dB, PB, mac_buf);
cmd_sm2_generatekey(dA_key_type, 0, rB, RB, mac_buf);
//循环测试begin
cmd_trng_get_rand(ZA, 32)
cmd_trng_get_rand(ZB, 32)
kBytelen = get_rand from [1,sm2_exchange_test_key_max_len]
//A side exchange key-处理dA、pA
if(dA_key_type == cmd_key_external_ciphertext)
//enc_key_id外部传入,此时密钥还是明文状态,需要做加密
KEK_encrypt(dA,32,enc_key_id,dA+32,mac_buf)
else if (dA_key_type == cmd_key_internal)
dA <- get_key_from_key_id(KEY_HALF_MASK | dA_key_id)//前16字节,内部对应密钥
dA+16 <- get_key_from_key_id(dA_key_id)//后16字节
pA <- cmd_sm2_get_pubkey_from_prikey(dA)//直接椭圆曲线计算公钥
//A side exchange key-处理rA、RA
if(rA_key_type == cmd_key_external_ciphertext)
//enc_key_id外部传入
KEK_encrypt(rA,32,enc_key_id,rA+32,mac_buf)
else if (rA_key_type == cmd_key_internal)
rA <- get_key_from_key_id(KEY_HALF_MASK | rA_key_id)//rA_key_id外部传入
rA+16 <- get_key_from_key_id(rA_key_id)
RA <- cmd_sm2_get_pubkey_from_prikey(rA)
//如果dA和rA是密文key,临时dA_tmp和rA_tmp为对应X+32位置,否则为dA、rA
...
//设置密钥协商参数,把前面参数赋值到cmd_sm2_exc_key_input
cmd_sm2_set_exckey_input_ptr(dA_temp, RA, rA_temp, RB, PB, ZA, ZB, cmd_sm2_exc_key_input)
//设置密钥信息
//-------------------
typedef struct {
cmd_key_type_e dA_key_type;
uint16_t dA_key_id;
cmd_key_type_e rA_key_type;
uint16_t rA_key_id;
uint16_t enc_key_id;
cmd_key_type_e output_key_type;
uint16_t output_key_id;
} cmd_sm2_exchangekey_keyinfo_t;
//--------------------
//密钥协商A方
cmd_sm2_exchange_key(CMD_SM2_ROLE_SPONSOR, (cmd_sm2_exchangekey_keyinfo_t *)&cmd_sm2_exckey_keyinfo,
cmd_sm2_exc_key_input, kbytelen,S1, SA, KA, mac_buf)//KA协商密钥
//如果输出密钥是密文,解密
if (output_key_type == cmd_key_external_ciphertext)
KEK_decrypt(KA, kbytelen, output_key_id, KA, mac_buf)
//B side exchange key
cmd_sm2_set_exckey_input_ptr(dB, RB, rB, RA, PA, ZB, ZA, cmd_sm2_exc_key_input)
...//设置cmd_sm2_exckey_keyinfo
//密钥协商B方
cmd_sm2_exchange_key(CMD_SM2_ROLE_RESPONSOR, (cmd_sm2_exchangekey_keyinfo_t*)&cmd_sm2_exckey_keyinfo,
cmd_sm2_exc_key_input, kbytelen,S2, SB, KB, mac_buf);
//判断双方密钥是否协商成功
1. KA == KB
2. SA == S2
3. SB == S1
//循环测试end
//probleam
//当generate_key_type为密文时,是什么加密Key?临时密钥?————下面生成的密钥是密文状态
ret = cmd_rsa_generate_key(ebitlen, nbitlen, generate_key_type, generate_key_id,
n, e, d, mac_buf);
if (CMD_KEY_EXTERNAL_CIPHERTEXT == decrypt_key_type) {
//私钥解密? 原解密的密文Key是由公钥做加密?————要求解密的时候密钥是密文状态
KEK_encrypt(d, nByteLen, decrypt_key_id, d + 0x200, mac_buf);
ret = cmd_rsa_decrypt(out, (d + 0x200), e, n, nbitlen, out, decrypt_key_type, decrypt_key_id, mac_buf);
//SM2生成密钥对,generate_key_type只作用在key_id_array[0]取值是否为0 或者 generate_key_id。
//1. 如果generate_key_type = Ciphertext,generate_key_id=0,生成的Key是密文 or 明文?
//2. mailbox里面key_id_array[0]最大数是?
cmd_sm2_generatekey(generate_key_type, generate_key_id, prikey, pubkey, mac_buf)
d)自测
uint8_t *prikey = (uint8_t *)(CMD_TEST_DMA_RAM_BASE);
uint8_t *pubkey = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x40);
uint8_t *msg = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x100);
uint8_t *cipher = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x200);
uint8_t *mac_buf = (uint8_t *)(CMD_TEST_DMA_RAM_BASE + 0x800);
/*********** generate crt key pair ***********/
cmd_sm2_generatekey(CMD_KEY_EXTERNAL_PLAINTEXT, 0, prikey, pubkey, mac_buf);
print_buf_U8(prikey, 32, "prikey");
print_buf_U8(pubkey,64,"public");
cmd_trng_get_rand((uint8_t *)msg, 32);
print_buf_U8(msg,32,"msg");
/*********** encrypt ***********/
cmd_sm2_enc(msg, 32, pubkey, cipher);
print_buf_U8(cipher,32+97,"msg_enc");
/*********** decrypt ***********/
cmd_sm2_dec(prikey, msg, cipher, 32+97, CMD_KEY_EXTERNAL_PLAINTEXT, 0, mac_buf);
print_buf_U8(msg,32,"msg_dec");
/*********** sign ***********/
cmd_trng_get_rand(e, 32);
cmd_sm2_sign(e, prikey, CMD_KEY_EXTERNAL_PLAINTEXT, 0, signature, mac_buf);
/*********** verify ***********/
cmd_sm2_verify(e, pubkey, signature);
//generate RSA key pair nbitlen = 2048 ebitlen = 17
cmd_rsa_generate_key(ebitlen, nbitlen, CMD_KEY_EXTERNAL_PLAINTEXT, 0, n, e, d, mac_buf);
//模数
print_buf_U8(n,nByteLen,"n");
//e=10001,17位,当ebitlen=17
print_buf_U8(e,nByteLen,"e");
//【怎么知道私钥的长度?】
print_buf_U8(d,nByteLen,"d");
//【ebitlen = 17?】,2^16=65536
3)添加编译
每个源文件目录下都有rules.mk
//D:\202206_semidrive\ssdk\test\crypto\rules.mk
ifeq ($(CONFIG_OSR_CRYPTO_TEST), y)
MODULE_SRCS += \
$(LOCAL_DIR)/test.c \
$(LOCAL_DIR)/gm_uart.c \
//注意回车,否则提示缺少endif
endif
4)密钥管理
//用内部keyid
KEK_encrypt(prikey, 32, key_id, prikey + 32, mac_buf);
5)其他
//下位机固件代码路径
F:seip_tc_new\seip_tc_new
//匹配的上位机测试工程
\\192.168.3.2\OSR-FileSharing\USERS\liufeng\芯驰项目\bak20210914\fpga_demo\Application\crypto\soc_seip\soc_otp_key.c
//芯驰修改波特率
D:\202206_semidrive\ssdk\boards\d3_disp\sf\configs\uart_cfg.c
//模糊查找,当前目录使用git bash here
grep "*sm2*" * -nR
//波特率,以下uart.c文件中baud是9600
D:\202206_semidrive\ssdk\boards\taishan_haps\sf\configs
//获取otp密钥属性
get_otp_key_attribute(i);
//修改mpu配置
//ssdk\test\crypto\mailbox\cmd_test.c
//默认的0x4000到0x4000
mpu_add_region(index, CMD_TEST_DMA_RAM_BASE, 0x40000, MPU_REGION_STRONGORDERED);
3、Momenta
//初始化petalinux环境
source /opt/petalinux/17/settings.sh
//配置kernel
petalinux-config -c kernel
///获取硬件随机数1024B,输出在random.bin
dd if=/dev/hwrng of=random.bin bs=1 count=1024
//打印random
hexdump random.bin
//kernel source的路径
~/linux/Momenta/sadrv/build/tmp/work-shared/plnx_arm/kernel-source
//testmgr 路径
~/linux/Momenta/sadrv/project-spec/meta-user/recipes-kernel/linux/linux-xlnx
file://libs/crypto_lib/pke/ed25519.c \
file://libs/crypto_lib/pke/x25519.c \
file://libs/crypto_addons/soft_sha384_sha512.h \
file://libs/crypto_addons/soft_sha384_sha512.c \
//打包
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/top.bit --u-boot --force
//patch添加路径
~/linux/Momenta/sadrv/project-spec/meta-user/recipes-kernel/linux/linux-xlnx_%.bbappend
SRC_URI += "file://user_2024-05-11-10-43-00.cfg \
file://user_2024-05-11-16-16-00.cfg \
file://testmgr.patch \
file://user_2024-05-13-13-41-00.cfg \
//备份路径
~/Desktop/bak-up/git
//patch路径
~/linux/Momenta/sadrv/project-spec/meta-user/recipes-kernel/linux/linux-xlnx/testmgr.patch
root@sadrv:/run/media/mmcblk0p1# cat /proc/version
Linux version 4.9.0-xilinx-v2017.4 (osr@ubuntu) (gcc version 6.2.1 20161016 (Linaro GCC 6.2-2016.11) ) #1 SMP PREEMPT Wed Jul 10 18:47:40 CST 2024
root@sadrv:/run/media/mmcblk0p1#
//linux-xlnx_%.bbappend文件添加testmgr.patch(取自git仓库)
~/linux/Momenta/sadrv/project-spec/meta-user/recipes-kernel/linux/linux-xlnx_%.bbappend
SRC_URI += "file://user_2024-05-13-13-41-00.cfg
file://testmgr.patch \
//编译ok
cd ~/linux/Momenta/sadrv/
petalinux-build
//拷贝项目kernel-source文件
cp ~/linux/Momenta/sadrv/build/tmp/work-shared/plnx_arm/kernel-source ~/Desktop/bak-up/git/ -r -f
//建立git管理
cd ~/Desktop/bak-up/git/kernel-source
rm .git -r -f
git init
git add .
git commit -m "XXX"
//获取外部修改的文件(比如增加secp521测试向量),拷贝到~/Desktop/bak-up/git/kernel-source
cp /mnt/hgfs/share/patch/crypto/testmgr.h ~/Desktop/bak-up/git/kernel-source/crypto/ -r -f
cp /mnt/hgfs/share/patch/crypto/testmgr.c ~/Desktop/bak-up/git/kernel-source/crypto/ -r -f
git diff > testmgr2.patch
mv testmgr2.patch ~/linux/Momenta/sadrv/project-spec/meta-user/recipes-kernel/linux/linux-xlnx
//linux-xlnx_%.bbappend文件添加testmgr2.patch(取自git仓库)
~/linux/Momenta/sadrv/project-spec/meta-user/recipes-kernel/linux/linux-xlnx_%.bbappend
SRC_URI += "file://user_2024-05-13-13-41-00.cfg \
file://testmgr.patch \
file://testmgr2.patch \
file://user_2024-07-09-11-48-00.cfg \
"
//编译ok
cd ~/linux/Momenta/sadrv/
petalinux-build
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/top.bit --u-boot --force
petalinux-build
//使用xlinx编译器编译mydemo
petalinux-build -c my-demo
//修改mydemo代码
vim ~/linux/Momenta/sadrv/project-spec/meta-user/recipes-apps/my-demo/files/my-demo.c
//copy出去
cp ~/linux/Momenta/sadrv/build/tmp/work/cortexa9hf-neon-xilinx-linux-gnueabi/my-demo/1.0-r0/my-demo /mnt/hgfs/share/
~/linux/Momenta/sadrv/build/tmp/sysroots/x86_64-linux/usr/bin/arm-xilinx-linux-gnueabi/arm-xilinx-linux-gnueabi-gcc ~/linux/get-and-print-dev-hwrng.c
~/linux/Momenta/sadrv/build/tmp/work/cortexa9hf-neon-xilinx-linux-gnueabi/my-demo/1.0-r0/my-demo.c
CSR_TRNG_VERSION=0x000d0010
CSR_TRNG_SR=0x0000011a
CSR_TRNG_RO_CLK_EN=0x0000000f
cat /proc/crypto | grep "osr"
cat /proc/cpuinfo | grep "osr"
终、其他
1、文档资料
1)《rfc4309》
Using AES CCM Mode with IPsec ESP
CCM原始过程的4个输入参数
//单个密钥被用于计算ICV,通过CBC-MAC和计数器模式执行有效负荷加密
//实现AES必须支持128、可支持192、256bit密钥,AES-CCM使用CBC-MAC,并使用计数器模式
Key
//上下文被用于一次的数,长度却决于L,为15-L
//实现必须支持11字节
Nonce
//有效负荷,长度不超过2^32-1字节,ESP Padding、Pad Length、Net Header Fields是其中的一部分
payload
//附加的认证数据(additional auhenticated data)在符合之外,CCM提供数据完整性和认证性
//CCM不允许aad长度大于2^64-1字节
//ICV计算依赖:ESP header,有效负荷Payload,ESP尾部字段ESP trailer fields
AAD
000102030405060708090a0b0c0d0e0f
原本代码有输出函数
//utility.c
void print_buf_U8(uint8_t buf[], uint32_t byteLen, char name[])
{
uint32_t i;
printf("\r\n %s: ",name); fflush(stdout);
for(i=0; i<byteLen; i++)
{
printf("%02x", buf[i]);
}
printf("\r\n");
}
void print_buf_U32(uint32_t buf[], uint32_t wordLen, char name[])
{
uint32_t i;
printf("\r\n %s: %08x\r\n",name, (uint32_t)buf);fflush(stdout);
for(i=0; i<wordLen; i++)
{
printf("%08x", buf[i]);fflush(stdout);
}
printf("\r\n");fflush(stdout);
}
2)、OSR_SKE_LP_UG
//使用流程
reset(复位)
while 1
if update cfg
write SKE_CFG寄存器,input cfg
AHB写SKE_KEY1
写SKE_CTRL,触发运算
while 1:
if SKE_SR2 == 1
write SKE_SR2,清除标志
清除SKE_CFG.UP_CFG
break
else
AHB写SKE_DIN
写SKE_CTRL,触发运算
while 1:
if SKE_SR2 == 1
write SKE_SR2,清除标志
读取SKE_DOUT
//状态说明
//SKE配置寄存器(SKE_CFG)
//SKE状态寄存器1(SKE_SR1)
大小:32bit
[31:1] Reserved保留位
[0 :0] BUSY位
SKE_SR1.BUSY
1:SKE_LP开始运算(CPU)
0:SKE_LP结束运算(CPU)
//SKE状态寄存器2(SKE_SR2)
大小:32bit
[31:1] Reserved保留位
[0 :0] CORE_DONE
SKE_SR2.CORE_DONE
1:SKE_LP运算结束(CPU),中断产生
0:无中断
//SKE密钥寄存器1(SKE_KEY1)
大小:32bit
[31:0]AES-256,密钥空间为8word(1 word == 4 Bytes == 32 bit)
[31:0]AES-192,密钥空间为6word
[31:0]AES-128,密钥空间为4word
[31:0]SM4, 密钥空间为4word
[31:0]DES, 密钥空间为2word
//SKE_ADD长度寄存器(SKE_AAD)
大小:32bit
A_LEN(AAD比特长度,该寄存器GCM有效)
//SKE数据长度寄存器(SKE_CLEN)
大小:32bit
[31:0]C_LEN(密文比特长度,该寄存器GCM有效)
//SKE数据标志寄存器(SKE_DIN_CR)
大小:32bit
[31:17] Reserved保留位
[16:16] LAST数据末尾标志
[15: 0] Reserved保留位
SKE_DIN_CR.LAST
1:当前数据包含数据末尾
0:当前数据不包含数据末尾,该标志对所有GCM模式有效
//SKE数据输入寄存器(SKE_DIN)
[31: 0] DATA_IN 数据输入
//SKEIV寄存器(SKE_IV)
大小:32bit
[31: 0] IV
//SKE数据输出寄存器(SKE_DOUT)
大小:32bit
[31: 0] DATA_OUT 数据输出,当SKE_SR2.CORE_DONE为1时,可以读取本寄存器的值作为运算结果
//DMA源地址寄存器(DMA_SADDR)
大小:32bit
[31: 0] DMA源地址
//DMA目的地址寄存器(DMA_SADDR)
大小:32bit
[31: 0] DMA目的地址
//DMA读数据长度寄存器(DMA_RLEN)
[31: 0] DMA读Byte长度
//DMA写数据长度寄存器(DMA_RLEN)
大小:32bit
[31: 0] DMA写Byte长度
//版本寄存器(VERSION)
大小:32bit
2、bit处理
1)清空(置零)CFG的bit位[0:3]
清零思想:与0与运算
volatile uint32_t mask = ~(0x0F);
CFG = CFG & mask
2)设置CFG的bit位[0:3]为A
设置思想:与0或运算(先对对应位置清零)
CFG = CFG & mask
3、Xilinx背景颜色
//右键属性-General-Editors-TextEditors
RGB = 204 232 207
//白色默认 255 255 255
4、可用代码
#include "./osr_crypto/crypto_include/utility.h"//CZH
5、Keil5使用
1)返回上一步:CRTL + -
2)背景豆沙色:菜单栏右边-扳手-colors & fonts-C/C++ Editor,最好全部选上,背景色同Xilinx
3)选择设备:菜单栏-锤子-debug-use
6、CppCheck
目录分析不能含有中文路径,全英文。
7、硬件知识
1、寄存器可以有多少个
无规定,多个
2、硬件中断是指?
一般是由中断控制器提供中断码类型,处理机自动转向中断处理程序。
3、硬件复位是指?
使系统恢复到已知状态的一项操作,用于上电初始状态进入,异常后回复系统的一项操作。
主要有上电/手动/硬件/软件/部分复位,
4、硬件时钟、时钟域是指?
时钟电路:所有数字系统在处理信号都是按节拍一步一步进行,产生时钟信号的电路就是时钟电路。
如果时钟周期=0.1s,f=1/T=10Hz
5、TRL是指?
寄存器级转换电路(Register Transfer Level)
6、NVM
非易失性存储器,即使关闭电源也能够保存已保存数据的存储器
8、Hash分组长度
| 算法 | 分组长度Byte | 摘要长度Byte |
|---|---|---|
| SM3 | 64 | 32 |
| MD5 | 64 | 16 |
| SHA1 | 64 | 20 |
| SHA256 | 64 | 32 |
| SHA224 | 64 | 32 |
| SHA384 | 128 | 64 |
| SHA512 | 128 | 64 |
| SHA512_224 | 128 | 28 |
| SHA512_256 | 128 | 32 |
| SHA3_224 | 36*4=144 | 28 |
| SHA3_256 | 34*4=136 | 32 |
| SHA3_384 | 26*4=104 | 48 |
| SHA3_512 | 18*4=72 | 64 |
uint32_t hash_dma_test(HASH_ALG hash_alg, uint8_t *std_digest1, uint8_t *std_digest2, uint8_t *std_digest3)
{
HASH_DMA_CTX ctx[1];
uint8_t tmp_buf[500];
uint8_t message[500];
uint32_t iterator[HASH_ITERATOR_MAX_WORD_LEN];
uint32_t block_word_len, block_byte_len, output_word_len, digest_byte_len, iterator_word_len;
char *name[] = {"SM3","MD5","SHA_256","SHA_384","SHA_512","SHA_1","SHA_224","SHA_512_224","SHA_512_256"};
uint32_t *msg = (uint32_t *)(DMA_RAM_BASE+0x00000010);
uint32_t *digest = msg+512;
uint32_t msg_bytes = 500;
uint32_t i,j,total;
uint32_t ret;
#ifdef SUPPORT_HASH_DMA_NODE
HASH_DMA_NODE hash_dma_node[4];
#endif
memset_(message, 0, sizeof(message));
memcpy_(message, "abc", 3); //to avoid some bad compiler's error(memset not found)
printf("\r\n ------------ %s DMA test ------------ ", name[hash_alg]);
block_word_len = hash_get_block_word_len(hash_alg);
block_byte_len = block_word_len<<2;
digest_byte_len = hash_get_digest_word_len(hash_alg)<<2;
output_word_len = ((digest_byte_len+15)/16)*4; //must be a multiple of 4(namely 128bits)
iterator_word_len = hash_get_iterator_word_len(hash_alg);
#ifdef SUPPORT_HASH_DMA_NODE
//test 2-final
uint32_clear(digest, 64/4);
hash_dma_node[0].msg_addr = msg;
hash_dma_node[0].msg_bytes = block_byte_len;
hash_dma_node[1].msg_addr = hash_dma_node[0].msg_addr + hash_dma_node[0].msg_bytes/4;
hash_dma_node[1].msg_bytes = block_byte_len;
hash_dma_node[2].msg_addr = hash_dma_node[1].msg_addr + hash_dma_node[1].msg_bytes/4;
hash_dma_node[2].msg_bytes = msg_bytes - 2*block_byte_len;
ret = hash_dma_node_steps(hash_alg, hash_dma_node, 3, digest, hash_call_manage);
if(HASH_SUCCESS != ret || memcmp_(std_digest2, digest, digest_byte_len))
{
printf("\r\n %s DMA test 2-final(hash dma node style) failure, ret=%x \r\n", name[hash_alg], ret);//fflush(stdout);
print_buf_U8(message, msg_bytes, "message");
print_buf_U8((uint8_t *)digest, output_word_len<<2, "digest");
print_buf_U8(std_digest1, digest_byte_len, "std digest");
return 1;
}
else
{
printf("\r\n %s DMA test 2-final(hash dma node style)", name[hash_alg]);//fflush(stdout);
}
#endif
return 0;
}
xhsc ske hp已修改:
1.trng utility sm3以xhsc sm9最新替换,并完成静态代码修改
2.trng 增加宏TRNG_GENERATE_BY_HARDWARE 控制IP获取随机数或从软件生成随机数
3.算法库修改部分低风险代码,剩余1条中风险,剩余333低风险(绝大部分警告为数值与指针相互转换)
________________________________
hfe已修改:
1.trng utility sm3以xhsc sm9最新替换,并完成静态代码修改
2.trng 增加宏TRNG_GENERATE_BY_HARDWARE 控制IP获取随机数或从软件生成随机数
3.测试增加corner case(msg=NULL), 覆盖DMA和CPU模式
3.算法库修改部分低风险代码,剩余2条中风险,剩余232低风险(绝大部分警告为数值与指针相互转换)
________________________________
已修改:
1./*hfe*/和xhsc ske hp同步sm3 //并根据SA修改(取自xhsc sm9)
2.hfe和xhsc ske hp trng 增加宏TRNG_BY_HTRNG_HARDWARE 控制
________________________________
已修改:
1.解决if else if警告,指针偏移操作警告
2.hfe和xhsc ske hp同步utility并根据SA修改(取自xhsc sm9)
________________________________
已修改:
1.hfe和xhsc ske hp同步trng并根据SA修改(取自xhsc sm9)
2.hfe和xhsc ske hp同步utility并根据SA修改(取自xhsc sm9)
遗留待修改:
1.memcmp_警告
________________________________
已修改:
1.部分低风险
遗留待修改:
1.memcmp_警告
9、项目本地管理方法
project
--1_branch(if new requirement, open new branch)
----0_backups
------date
--------files+readme.txt
----1_source_master
----2_source_dev
----3_keil5
------project
----4_xilinx
----5_nucleStudio
----6_commit
----7_doc
----8_other
----project_获取sw_dev最新doc到7_doc.bat
----roject_获取sw_dev最新driver到1_source_master.bat
----修改说明.txt
10、code size统计
例:统计rsa code size
1.新建keil5工程,全量编译记录code size=T0
2.在main函数调用所有rsa相关函数,全量编译记录code size=T1
3.rsa code size = T1-T0
根据测试,模块A调用模块B,程序code size=模块A+模块B+模块B调用的其他模块(模块所有调用到的函数link进来,包括模块A没有调用到的函数也会统计进来)
编译器:ARM Compiler 5.06 update 6 (build 750)
代码优化:-O2
【1】LP国密安全版的code size,包括
SM2(单验签)/3(单hash不带hmac)/4(基本加解密)
TRNG-SM4
code size=14.13K
【2】LP国密安全版的全功能code size,包括
SM2/3(带HMAC)/4
TRNG-SM4
code size=21.35K
【3】客户要求的全部算法的code size
code size=32.07K
例:Xilinx SDK
project -> setting -> Tool Settings -> ARM v7 gcc linker -> Miscellaneous -> Other options
project -> setting -> Tool Settings -> ARM v7 gcc compiler -> Miscellaneous -> Other flags
//编译时按函数划分section
-ffunction-sections
project -> setting -> Tool Settings -> ARM v7 gcc linker -> Miscellaneous -> Other options
//去掉不需要的链接
--gc-section
//打印不需要的链接
--print-gc-sections
//生成map
-Map,"xilinxSDK.map"
//
94780
82684-71364
11、timer计时正确性校验
配合串口时间戳打印对比校验,校验硬件时钟频率是否正确,如10Mhz
void SysTick_Handler(void)
{
// SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; //disable SysTick, this could be ignored
g_irq_timer_counter ++;
// SysTick->LOAD = TIMER_MAX_COUNTER - 1; //real time works
// SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; //enable SysTick, this could be ignored
}
uint32_t startP(void)
{
g_irq_timer_counter = 0;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //disable SysTick, and this could be ignored. please don't use SysTick->CTRL = 0;
g_starl = (TIMER_MAX_COUNTER - 1);
SysTick_Config(TIMER_MAX_COUNTER);//config and start SysTick
return 0;
}
uint32_t endP(uint8_t mode, uint32_t once_bytes, uint32_t round)
{
g_endl = SysTick->VAL;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //disable SysTick, and this could be ignored. please don't use SysTick->CTRL = 0;
calcP(mode,once_bytes,round);
return 0;
}
#endif
void CZH_TIMER_TEST(void)
{
g_irq_timer_counter = 0;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //disable SysTick, and this could be ignored. please don't use SysTick->CTRL = 0;
SysTick_Config(1000);
g_starl = SysTick->VAL;
uint32_t i = 1;
while(1)
{
if(0 == (g_irq_timer_counter % 10000))
{
printf("i = %us\r\n", i);
i++;
}
}
}
12、Nuclei Timer计时
//如果使用下述的timer配置,还有个地方也要改,在demosoc.h:
//#define RTC_FREQ (625000u)//(10000000u)
//core_feature_timer.h里增加#include "demosoc.h"
#if 1
#include "../../../../nuclei_sdk/NMSIS/Core/Include/core_feature_timer.h"
#define TIMER_MAX_COUNTER 0xFFFFFF
#define DEFAULT_CPU_Hz 200u //MHz
#define CPU_Hz 10u //MHz
#define STDCNT 1000000u
#define RTC_FREQ (625000u)//(10000000u)
// The TIMER frequency is just the RTC frequency
#define SOC_TIMER_FREQ RTC_FREQ
// uint32_t volatile g_irq_timer_counter = 0;
uint64_t g_starl = 0;
uint64_t g_endl = 0;
uint32_t calcP(uint8_t mode, uint32_t once_bytes, uint32_t round)
{
uint32_t counterH,counterL;
uint32_t msg_bits;
double ts;
double res;
uint64_t _1s = (SOC_TIMER_FREQ * (uint64_t)1000) / 1000;
ts = (double)(g_endl - g_starl) / (double)_1s;
printf("\r\n ts = %.6lf s", ts);fflush(stdout);
switch(mode)
{
case 0:// test mbps/s
msg_bits = once_bytes*round*8;
printf("\r\n meslen = %u bit", msg_bits);fflush(stdout);
res = msg_bits/ts;
res = res*1000/1024;
res = res*1000/1024;
printf("\r\n res = %.6lfMBps = %.3fMbps;CPU_Hz = %uMhz", res/8,res,CPU_Hz);fflush(stdout);
res = res*DEFAULT_CPU_Hz/CPU_Hz;
printf("\r\n exres = %.3lfMBps = %.3fMbps;exCPU_Hz = %uMhz", res/8,res,DEFAULT_CPU_Hz);fflush(stdout);
break;
case 1:// test cnt/s
res = (double)round/ts;
printf("\r\nres = %.3lfcnt/s;CPU_Hz = %uMhz", res,CPU_Hz);fflush(stdout);
res = res*DEFAULT_CPU_Hz/CPU_Hz;
printf("\r\nexres = %.3lf/s;exCPU_Hz = %uMhz", res,DEFAULT_CPU_Hz);fflush(stdout);
break;
default:
break;
}
return 0;
}
uint64_t SysTimer_GetLoadValue_EX(void)
{
return SysTimer->MTIMER;
}
void SysTick_Handler(void)
{
return ;
}
void startP(void)
{
g_starl = SysTimer_GetLoadValue_EX();
return ;
}
void endP(uint8_t mode, uint32_t once_bytes, uint32_t round)
{
g_endl = SysTimer_GetLoadValue_EX();
calcP(mode,once_bytes,round);
return ;
}
#endif
void CZH_TIMER_TEST(void)
{
uint32_t i = 1;
double ts;
uint64_t _1s = (SOC_TIMER_FREQ * (uint64_t)1000) / 1000;
g_starl = SysTimer_GetLoadValue_EX();
while(1)
{
if((SysTimer_GetLoadValue_EX() - g_starl) >= _1s)
{
g_endl = SysTimer_GetLoadValue_EX();
ts = (double)(g_endl - g_starl) / (double)_1s;
g_starl = g_endl;
printf("i=%d, \r\n\r\n", i);fflush(stdout);
printf("ts=%.6lf, \r\n\r\n", ts);fflush(stdout);
i++;
}
}
}
//注:当输出浮点数失败时,可能Nucle IDE配置影响,RV-Tools->SDK Configuration Tools->Select Runtime library -> optimized for size, full feature
13、TRNG性能测试
uint32_t trng_speed_test2()
{
uint32_t counter = 100;
uint32_t once_bytes = 4096;
uint32_t rand[4096/4];
uint32_t i, j, ret = 0;
trng_set_freq(0);
uint32_sleep(0x1FFFF, 1);
printf("\r\n===================== TRNG begin =====================");fflush(stdout);
#ifdef TRNG_CONFIG_SPEED_TEST_BY_TIMER
startP();
#endif
for(i=0;i<counter;i++)
{
ret = get_rand_internal((uint8_t *)rand, once_bytes);
if(TRNG_SUCCESS != ret)
{
printf("\r\n update error ret=%d", ret);
return 1;
}
}
#ifdef TRNG_CONFIG_SPEED_TEST_BY_TIMER
endP(0,once_bytes,counter);
#else
printf("\r\n finished");
#endif
uint32_sleep(0x1FFFF, 1);
printf("\r\n===================== DBRG begin =====================");fflush(stdout);
#ifdef TRNG_CONFIG_SPEED_TEST_BY_TIMER
startP();
#endif
for(i=0;i<counter;i++)
{
ret = get_rand_fast((uint8_t *)rand, once_bytes);
if(TRNG_SUCCESS != ret)
{
printf("\r\n update error ret=%d", ret);
return 1;
}
}
#ifdef TRNG_CONFIG_SPEED_TEST_BY_TIMER
endP(0,once_bytes,counter);
#else
printf("\r\n finished");
#endif
uint32_sleep(0x1FFFF, 1);
printf("\r\n===================== DBRG GM begin =====================");fflush(stdout);
#ifdef TRNG_CONFIG_SPEED_TEST_BY_TIMER
startP();
#endif
for(i=0;i<counter;i++)
{
ret = get_rand((uint8_t *)rand, once_bytes);
if(TRNG_SUCCESS != ret)
{
printf("\r\n update error ret=%d", ret);
return 1;
}
}
#ifdef TRNG_CONFIG_SPEED_TEST_BY_TIMER
endP(0,once_bytes,counter);
#else
printf("\r\n finished");
#endif
return 0;
}
14、uhp算子测试
//CZH_DEBUG
void CZH_point_Mul_Shamir_hal_256_test()
{
uint32_t k1[8] = {0};
uint32_t k2[8] = {0};
uint32_t Qx[8], Qy[8];
uint32_t Px[8] = {0x804b6121,0x0f099990,0x8806af17,0xe1fb945f,0x964bdb08,0xd99e9b0b,0x128e18d9,0x223284f6};//U32little
uint32_t Py[8] = {0x92a014ff,0xdefb4225,0x62be16c0,0x5eec0be8,0x8ed51e33,0x956d18f3,0xda31b79a,0x248ad941};//U32little
// uint32_t P2x[8] = {0x5C709EE5,0xABAC09B9,0x8CEF3CA7,0x5C778E4B,0x95C07CD8,0x3045406E,0x41ED7D6D,0xC6047F94};//U32little
// uint32_t P2y[8] = {0x50CFE52A,0x236431A9,0x3266D0E1,0xF7F63265,0x466CEAEE,0xA3C58419,0xA63DC339,0x1AE168FE};//U32little
uint32_t P2x[8] = {0x16F81798,0x59F2815B,0x2DCE28D9,0x029BFCDB,0xCE870B07,0x55A06295,0xF9DCBBAC,0x79BE667E};//U32little
uint32_t P2y[8] = {0xFB10D4B8,0x9C47D08F,0xA6855419,0xFD17B448,0x0E1108A8,0x5DA4FBFC,0x26A3C465,0x483ADA77};//U32little
uint32_t step_bytes, pWordLen = 256/32, nWordLen = 256/32;
uint32_t ret;
k1[0] = 0x02;
k2[0] = 0x03;
// memset_((uint8_t *)k1, 2, 32);
// memset_((uint8_t *)k2, 3, 32);
step_bytes = pke_get_operand_bytes();
ret = pke_set_modulus_and_pre_monts(secp256k1->eccp_p, secp256k1->eccp_p_h, secp256k1->eccp_p_bitLen);
pke_set_curve_k1(1);
//(Qx,Qy) = [k1]P +[k2]P
pke_load_operand((uint32_t *)(rPKE_B(0,1,step_bytes)), Px, pWordLen); //B1 P1x U32little
pke_load_operand((uint32_t *)(rPKE_B(0,2,step_bytes)), Py, pWordLen); //B2 P1y U32little
pke_set_operand_uint32_value((uint32_t *)(rPKE_A(0,3,step_bytes)), step_bytes>>2, 1); //A3 P1z U32little
pke_load_operand((uint32_t *)(rPKE_B(0,5,step_bytes)), P2x, pWordLen); //B5 P2x U32little
pke_load_operand((uint32_t *)(rPKE_B(0,6,step_bytes)), P2y, pWordLen); //B6 P2y U32little
pke_load_operand((uint32_t *)(rPKE_B(0,4,step_bytes)), secp256k1->eccp_a, pWordLen); //B4 a U32little 0x80041000+4*0x20
pke_load_operand((uint32_t *)(rPKE_A(0,4,step_bytes)), k1, nWordLen); //A4 k1 U32little 0x80040400+4*0x20
pke_load_operand((uint32_t *)(rPKE_A(0,5,step_bytes)), k2, nWordLen); //A5 k2 U32little 0x80040400+5*0x20
if((step_bytes>>2) > pWordLen)
{
uint32_clear((uint32_t *)(rPKE_B(g_pke_core_id,1,step_bytes))+pWordLen, step_bytes>>2-pWordLen);
uint32_clear((uint32_t *)(rPKE_B(g_pke_core_id,2,step_bytes))+pWordLen, step_bytes>>2-pWordLen);
uint32_clear((uint32_t *)(rPKE_B(g_pke_core_id,4,step_bytes))+pWordLen, step_bytes>>2-pWordLen);
uint32_clear((uint32_t *)(rPKE_B(g_pke_core_id,5,step_bytes))+pWordLen, step_bytes>>2-pWordLen);
uint32_clear((uint32_t *)(rPKE_B(g_pke_core_id,6,step_bytes))+pWordLen, step_bytes>>2-pWordLen);
}
else
{;}
if((step_bytes>>2) > nWordLen)
{
uint32_clear((uint32_t *)(rPKE_A(g_pke_core_id,4,step_bytes))+nWordLen, step_bytes>>2-nWordLen);
uint32_clear((uint32_t *)(rPKE_A(g_pke_core_id,5,step_bytes))+nWordLen, step_bytes>>2-nWordLen);
}
else
{;}
ret |= pke_set_micro_code_start_wait_return_code(MICROCODE_PMULF);
pke_read_operand((uint32_t *)(rPKE_A(g_pke_core_id,1,step_bytes)), Qx, pWordLen); //A1 Qx U32little
pke_read_operand((uint32_t *)(rPKE_A(g_pke_core_id,2,step_bytes)), Qy, pWordLen); //A2 Ay U32little
uint32_t tmp_Q1x[8],tmp_Q1y[8];
uint32_t tmp_Q2x[8],tmp_Q2y[8];
uint32_t tmp_Q3x[8],tmp_Q3y[8];
eccp_pointMul((eccp_curve_t *)secp256k1, k1, Px, Py, tmp_Q1x, tmp_Q1y);
eccp_pointMul((eccp_curve_t *)secp256k1, k2, P2x, P2y, tmp_Q2x, tmp_Q2y);
eccp_pointAdd((eccp_curve_t *)secp256k1, tmp_Q1x, tmp_Q1y, tmp_Q2x, tmp_Q2y, tmp_Q3x, tmp_Q3y);
//conver to u8big
reverse_byte_array((uint8_t *)k1, (uint8_t *)k1, 256/8);
reverse_byte_array((uint8_t *)k2, (uint8_t *)k2, 256/8);
reverse_byte_array((uint8_t *)Px, (uint8_t *)Px, 256/8);
reverse_byte_array((uint8_t *)Py, (uint8_t *)Py, 256/8);
reverse_byte_array((uint8_t *)P2x, (uint8_t *)P2x, 256/8);
reverse_byte_array((uint8_t *)P2y, (uint8_t *)P2y, 256/8);
reverse_byte_array((uint8_t *)Qx, (uint8_t *)Qx, 256/8);
reverse_byte_array((uint8_t *)Qy, (uint8_t *)Qy, 256/8);
reverse_byte_array((uint8_t *)tmp_Q1x, (uint8_t *)tmp_Q1x, 256/8);
reverse_byte_array((uint8_t *)tmp_Q1y, (uint8_t *)tmp_Q1y, 256/8);
reverse_byte_array((uint8_t *)tmp_Q2x, (uint8_t *)tmp_Q2x, 256/8);
reverse_byte_array((uint8_t *)tmp_Q2y, (uint8_t *)tmp_Q2y, 256/8);
reverse_byte_array((uint8_t *)tmp_Q3x, (uint8_t *)tmp_Q3x, 256/8);
reverse_byte_array((uint8_t *)tmp_Q3y, (uint8_t *)tmp_Q3y, 256/8);
print_buf_U8((uint8_t *)k1, 256/8, "k1");
print_buf_U8((uint8_t *)k2, 256/8, "k2");
print_buf_U8((uint8_t *)Px, 256/8, "Px");
print_buf_U8((uint8_t *)Py, 256/8, "Py");
print_buf_U8((uint8_t *)P2x, 256/8, "P2x");
print_buf_U8((uint8_t *)P2y, 256/8, "P2y");
print_buf_U8((uint8_t *)Qx, 256/8, "Qx");
print_buf_U8((uint8_t *)Qy, 256/8, "Qy");
print_buf_U8((uint8_t *)tmp_Q1x, 256/8, "tmp_Q1x");
print_buf_U8((uint8_t *)tmp_Q1y, 256/8, "tmp_Q1y");
print_buf_U8((uint8_t *)tmp_Q2x, 256/8, "tmp_Q2x");
print_buf_U8((uint8_t *)tmp_Q2y, 256/8, "tmp_Q2y");
print_buf_U8((uint8_t *)tmp_Q3x, 256/8, "tmp_Q3x");
print_buf_U8((uint8_t *)tmp_Q3y, 256/8, "tmp_Q3y");
//test [2]P + [3]P, here k1 and k2 have the same bit length.
}
15、正则匹配
(if) \({1}.*\){1}[\w\W]+?\}{1}[\w\W]+?\r
16、eHSM lib更新
//按项目来定
ehsm_mem_remap.h//D:\Git\osr_ehsm_fw\ehsm_fw\source\include\driver
eHSM_Types_Ip.h//D:\Git\osr_ehsm_fw\ehsm_host\include\common
eHSM_Config_Ip.h//D:\Git\osr_ehsm_fw_config\1002
eHSM_IntCfg_Ip.h//D:\Git\osr_ehsm_fw_config\1002
17、timer修改
1.timer :res = (float)round*(float)STDCNT/ts;
2.之前在跑pke modadd modsub性能时,round=5000次,总耗时0.4s,计算结果不到2000,明显不对,后面发现这个计算没有强转float下,数值大的就会导致计算错误,百度和请教了其他同事还没有合理解释这个错误值怎么来的-已改
3.hash-ske、pke消除ehsm warning
//the following is for speed test by using Timer(on ARM-CM3/Keil5), if you don't need, you can disable this part.
//and if you need, you may need to rewrite this on your platform.
#if 1
#include "CM3DS_MPS2.h"
#define TIMER_MAX_COUNTER 0xFFFFFF
#define DEFAULT_CPU_Hz 200u //MHz
#define CPU_Hz 10u //MHz
#define STDCNT 1000000u
uint32_t volatile g_irq_timer_counter = 0;
uint32_t volatile g_starl = 0;
uint32_t volatile g_endl = 0;
uint32_t calcP(uint8_t mode, uint32_t once_bytes, uint32_t round)
{
//uint32_t counterH;
uint32_t counterL;
uint32_t msg_bytes;
float ts;
float res;
counterL = g_irq_timer_counter*TIMER_MAX_COUNTER;
if(g_starl > g_endl)
{
counterL += g_starl - g_endl;
}
else
{
counterL -= g_endl - g_starl;
}
printf("\r\n startL = %u cycle, endL = %u cycle, counterL = %u cycle", g_starl, g_endl, counterL);fflush(stdout);
ts = counterL/(float)CPU_Hz;
printf("\r\n ts = %.6f s", ts / (float)1000 / (float)1000);fflush(stdout);
switch(mode)
{
case 0:// test mbps/s
msg_bytes = once_bytes*round;
printf("\r\n meslen = %u bytes", msg_bytes);fflush(stdout);
res = msg_bytes/(ts/8);
res = res*1000/1024;
res = res*1000/1024;
printf("\r\n res = %.6fMBps = %.3fMbps;CPU_Hz = %uMhz", res/8,res,CPU_Hz);fflush(stdout);
res = res*DEFAULT_CPU_Hz/CPU_Hz;
printf("\r\n exres = %.3fMBps = %.3fMbps;exCPU_Hz = %uMhz", res/8,res,DEFAULT_CPU_Hz);fflush(stdout);
break;
case 1:// test cnt/s
res = round*(STDCNT/ts);
printf("\r\nres = %.6f/s,%.4fms/time;CPU_Hz = %uMhz", res,1000/res,CPU_Hz);fflush(stdout);
res = res*DEFAULT_CPU_Hz/CPU_Hz;
printf("\r\nexres = %.3f/s;exCPU_Hz = %uMhz", res,DEFAULT_CPU_Hz);fflush(stdout);
break;
default:
break;
}
return 0;
}
void SysTick_Handler(void)
{
// SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; //disable SysTick, this could be ignored
g_irq_timer_counter ++;
// SysTick->LOAD = TIMER_MAX_COUNTER - 1; //real time works
// SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; //enable SysTick, this could be ignored
}
uint32_t startP(void)
{
g_irq_timer_counter = 0;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //disable SysTick, and this could be ignored. please don't use SysTick->CTRL = 0;
g_starl = TIMER_MAX_COUNTER;
SysTick_Config(TIMER_MAX_COUNTER);
//g_starl = SysTick->VAL; //avoid optimize make val is 0
return 0;
}
uint32_t endP(uint8_t mode, uint32_t once_bytes, uint32_t round)
{
g_endl = SysTick->VAL;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //disable SysTick, and this could be ignored. please don't use SysTick->CTRL = 0;
calcP(mode,once_bytes,round);
return 0;
}
#endif
18、keil compiler5 to compiler6
//setting
C/C++
FPGA_IMAGE
19、代码format
1. vscode安装插件:\\192.168.110.100\publics\USERS\hul\vscode\xaver.clang-format-1.9.0.vsix
2. 将这个文件\\192.168.110.100\publics\USERS\hul\vscode\clang-format.exe 复制到你系统上PATH环境变量指定的目录下
3. 在vscode里打开源代码,按 SHIFT-ALT-F,会自动格式化当前代码
20、xilinx elf文件转bin
./armr5-none-eabi-objcopy.exe helloworld.elf -O binary helloworld.bin
//C:\Xilinx\SDK\2017.4\gnu\armr5\nt\gcc-arm-none-eabi\bin
21、双keil5工程跑
划分不同rom段,烧写工程1,再烧写工程2,执行工程二需要把PC设置为0x000101e5,对应工程2反汇编文件hello-world.lst如下
** Section #1 'ER_IROM1' (SHT_PROGBITS) [SHF_ALLOC + SHF_EXECINSTR]
Size : 4588 bytes (alignment 4)
Address: 0x00010000
$d.realdata
RESET
__Vectors
0x00010000: 2000cd70 p.. DCD 536923504
0x00010004: 000101e5 .... DCD 66021
22、suspend
//现有软件方案支持suspend,在现有测试代码中,使用计时器随机触发中断,中断函数执行cmac一次性计算,整个测试过程通过
SKE—HP(SKE5种基本模式/CBCMAC/CMAC/CCM/GCM DMA均已测试通过)
保存现场:B任务打断A任务(A任务处于DMA模式)
1.软件使能suspend,等待硬件中断完成
2.软件保存硬件相关寄存器值 RW RO
3.软件清除中断信息
4.软件执行任务B
恢复现场:
1.软件解析保存的硬件寄存器信息,比如何种算法何种模式、中断是否有效,中间值多少
2.软件对于RW寄存器,读取保存的信息回写进硬件(中间值根据suspend有效是否有效,决定写入硬件suspend返回的中间值,还是A任务写入的中间值,此情况需要全局变量来记录A写入的中间值)
3.软件触发硬件CFG配置更新,并拉低更新配置的比特
4.1软件根据保存的硬件信息判断suspend如果发生在idle,把全局变量suspend标记拉高
4.2软件根据保存的硬件信息判断suspend如果发生在task,把全局变量suspend标记拉低,对算法模式进行接力计算
保存现场:B任务打断A任务(A任务处于CPU模式)
1.每个分组备份,如果检测到全局suspend标记被拉高,重新计算,(缺点:性能降低至少一半)
libs改造:
1.增加保存、恢复现场两个接口
2.增加一个全局变量suspend标记
3.对DMA接口,如果检测到全局suspend标记被拉高,重新执行一遍计算
方案:
1.对于suspend后不会擦写的RW寄存器值,恢复现场可由软件进行保存回写
2.待补充
23、STIP学习
//假设mask
static inline void io_mask32(uintptr_t addr, uint32_t val, uint32_t mask)
{
io_write32(addr, (io_read32(addr) & ~mask) | (val & mask));
}
七、算法小Demo
1)CBCMAC
void CZH_CBCMAC_TEST()
{
uint8_t key[16] = {0x8D,0x05,0x3D,0x8E,0xD2,0x72,0x0C,0x4E,0xDE,0x2A,0x5B,0x7F,0x32,0x97,0xEE,0x8B};
uint8_t msg[32+16] = {0x8B,0x01,0xA3,0x69,0xCC,0x77,0x59,0x4D,0x4F,0x35,0x17,0x44,0x0A,0x48,0x7D,0x97,
0x2E,0xB6,0xBE,0xCB,0xE8,0x67,0x2A,0xC3,0xD8,0xE5,0xC0,0x69,0x0C,0x1B,0x87,0xE4,
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t mac[16] = {0};
uint8_t std_mac_msg32[16] = {0x17,0xAE,0x0E,0x02,0xF0,0xCD,0x1F,0xA8,0x69,0xD8,0x06,0x83,0x10,0x5A,0xB8,0x04};
uint8_t std_mac_msg16[16] = {0xD1,0xF5,0xC0,0xBD,0xDE,0x7A,0xAC,0x50,0xF9,0xBC,0x6B,0xF0,0x6C,0x95,0x5F,0x47};
uint8_t std_mac_msg33[16] = {0x11,0x81,0x11,0xbc,0x47,0xd3,0xe4,0x7d,0x17,0xf8,0xe6,0x12,0x7a,0x2e,0x72,0xa7};
uint32_t ret;
uint32_t i;
SKE_CBC_MAC_CTX ctx1[1];
SKE_CBC_MAC_DMA_CTX ctx[1];
uint32_t mac_bytes = 15U;
uint32_t *std_in_, *std_out_;
std_in_ = (uint32_t *)SKE_DMA_RAM_BASE;
std_out_ = std_in_+64;
uint32_copy(std_in_, (uint32_t *)msg, 48/4);
uint32_copy(std_out_, (uint32_t *)std_mac_msg32, 16/4);
// //CPU mode
// ret = ske_hp_cbc_mac(SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, key, 0, msg, 32, mac, 16);
// if((SKE_SUCCESS == ret) && (0u == memcmp_(mac, std_mac_msg32, 16)))
// {
// printf("ske_hp_cbc_mac test success(cpu mode)\n");
// }
// else
// {
// printf("ske_hp_cbc_mac test error (cpu mode)!!!! ret=%d\n", ret);
// print_buf_U8(mac, 16, "mac");
// }
//#if 0
// ret = ske_hp_cbc_mac(SKE_ALG_SM4, SKE_CRYPTO_DECRYPT, SKE_ZERO_PADDING, key, 0, msg, 32, std_mac_msg32, 16);
//#else
// ret = ske_hp_cbc_mac_init(ctx1, SKE_ALG_SM4, SKE_VERIFY_MAC, SKE_ZERO_PADDING, key, 0, mac_bytes);
// ret |= ske_hp_cbc_mac_update(ctx1, msg, 0x10);
// ret |= ske_hp_cbc_mac_update(ctx1, msg+0x10, 0x10);
// ret |= ske_hp_cbc_mac_final(ctx1, std_mac_msg32);
//#endif
// if(SKE_SUCCESS == ret)
// {
// printf("ske_hp_cbc_mac test success 2 (cpu mode)\n");
// }
// else
// {
// printf("ske_hp_cbc_mac test error (cpu mode)!!!! ret=%d\n", ret);
// print_buf_U8(mac, 16, "mac");
// }
//DMA mode //OK
#if 0
ret = ske_hp_dma_cbc_mac(SKE_ALG_SM4, key, 0, std_in_, 32, std_out_, 16, NULL);
#else
mac_bytes = 15;
ret = ske_hp_dma_cbc_mac_init(ctx, SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, key, 0, mac_bytes);
ret |= ske_hp_dma_cbc_mac_update_blocks_excluding_last_block(ctx, std_in_, 16, NULL);
ret |= ske_hp_dma_cbc_mac_update_including_last_block(ctx, std_in_+4, 16, std_out_, NULL);
#endif
if((SKE_SUCCESS == ret) && (0u == memcmp_((uint8_t *)std_out_, std_mac_msg32, mac_bytes)))
{
printf("ske_hp_cbc_mac test success 2 (DMA mode)\n");
}
else
{
printf("ske_hp_cbc_mac test error (DMA mode)!!!! ret=%d\n", ret);
print_buf_U8(std_mac_msg32, 16, "std_mac_msg32");
print_buf_U8((uint8_t *)std_out_, mac_bytes, "mac");
}
mac_bytes = 16u;
ret = ske_hp_dma_cbc_mac(SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, key, 0, std_in_, 16, std_out_, mac_bytes, NULL);
if((SKE_SUCCESS == ret) && (0u == memcmp_((uint8_t *)std_out_, std_mac_msg16, mac_bytes)))
{
printf("ske_hp_cbc_mac test success 3 (DMA mode)\n");
}
else
{
printf("ske_hp_cbc_mac test error 3 (DMA mode)!!!! ret=%d\n", ret);
print_buf_U8(std_mac_msg32, 16, "std_mac_msg32");
print_buf_U8((uint8_t *)std_out_, 16, "mac");
}
mac_bytes = 16u;
ret = ske_hp_dma_cbc_mac(SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, key, 0, std_in_, 32+1, std_out_, mac_bytes, NULL);
if((SKE_SUCCESS == ret) && (0u == memcmp_((uint8_t *)std_out_, std_mac_msg33, mac_bytes)))
{
printf("ske_hp_cbc_mac test success 4 (DMA mode)\n");
}
else
{
printf("ske_hp_cbc_mac test error 4 (DMA mode)!!!! ret=%d\n", ret);
print_buf_U8(std_mac_msg32, 16, "std_mac_msg32");
print_buf_U8((uint8_t *)std_out_, 16, "mac");
}
}
void CZH_CBCMAC_TEST2()
{
uint8_t key[16] = {0xE0,0x70,0x99,0xF1,0xBF,0xAF,0xFD,0x7F,0x24,0x0C,0xD7,0x90,0xCA,0x4F,0xE1,0x34};
uint8_t msg[256] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF};
uint32_t ret;
uint32_t mac_bytes = 16;
uint32_t *std_in_, *std_out_;
std_in_ = (uint32_t *)SKE_DMA_RAM_BASE;
std_out_ = std_in_+256;
SKE_CBC_MAC_DMA_CTX ctx[1];
uint32_copy(std_in_, (uint32_t *)msg, 256/4);
ret = ske_hp_dma_cbc_mac_init(ctx, SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, key, 0, mac_bytes);
// print_buf_U8((uint8_t *)std_in_, 256-16, "smg1");
ret |= ske_hp_dma_cbc_mac_update_blocks_excluding_last_block(ctx, std_in_, 0x80, NULL);
ret |= ske_hp_dma_cbc_mac_update_blocks_excluding_last_block(ctx, std_in_+0x80/4, 0x70, NULL);
ret |= ske_hp_dma_cbc_mac_update_including_last_block(ctx, std_in_+(256-16)/4, 16, std_out_, NULL);
//print_buf_U8((uint8_t *)(std_in_+(256-16)/4), 16, "smg2");
print_buf_U8((uint8_t *)std_out_, mac_bytes, "mac");
}
void CZH_CBCMAC_TEST3()
{
uint32_t kmu_base_addr = 0xA0000000;
uint32_t kmu_key_addr = kmu_base_addr;
uint32_t kmu_key_mask_addr = kmu_base_addr+0x800;
uint8_t key[16] = {0x8D,0x05,0x3D,0x8E,0xD2,0x72,0x0C,0x4E,0xDE,0x2A,0x5B,0x7F,0x32,0x97,0xEE,0x8B};
uint8_t msg[32+16] = {0x8B,0x01,0xA3,0x69,0xCC,0x77,0x59,0x4D,0x4F,0x35,0x17,0x44,0x0A,0x48,0x7D,0x97,
0x2E,0xB6,0xBE,0xCB,0xE8,0x67,0x2A,0xC3,0xD8,0xE5,0xC0,0x69,0x0C,0x1B,0x87,0xE4,
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t mac[16] = {0};
uint8_t std_mac_msg32[16] = {0x17,0xAE,0x0E,0x02,0xF0,0xCD,0x1F,0xA8,0x69,0xD8,0x06,0x83,0x10,0x5A,0xB8,0x04};
uint8_t std_mac_msg16[16] = {0xD1,0xF5,0xC0,0xBD,0xDE,0x7A,0xAC,0x50,0xF9,0xBC,0x6B,0xF0,0x6C,0x95,0x5F,0x47};
uint8_t std_mac_msg33[16] = {0x11,0x81,0x11,0xbc,0x47,0xd3,0xe4,0x7d,0x17,0xf8,0xe6,0x12,0x7a,0x2e,0x72,0xa7};
uint32_t ret;
uint32_t i;
SKE_CBC_MAC_CTX ctx1[1];
SKE_CBC_MAC_DMA_CTX ctx[1];
uint32_t mac_bytes = 15U;
uint32_t *std_in_, *std_out_;
std_in_ = (uint32_t *)SKE_DMA_RAM_BASE;
std_out_ = std_in_+64;
uint32_copy(std_in_, (uint32_t *)msg, 48/4);
uint32_copy(std_out_, (uint32_t *)std_mac_msg32, 16/4);
memcpy_((void *)kmu_base_addr, key, 16);
memset_((void *)kmu_key_mask_addr,0xFF, 16);
//memcpy_((void *)kmu_key_mask_addr, key, 16);
//CPU mode
ret = ske_hp_cbc_mac(SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, NULL, 0, msg, 32, mac, 16);
//ret = ske_hp_cbc_mac(SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, NULL, 0, msg, 32, mac, 16);
if((SKE_SUCCESS == ret) && (0u == memcmp_(mac, std_mac_msg32, 16)))
{
printf("ske_hp_cbc_mac test success(cpu mode)\n");
}
else
{
printf("ske_hp_cbc_mac test error (cpu mode)!!!! ret=%d\n", ret);
print_buf_U8(mac, 16, "mac");
}
#if 0
ret = ske_hp_cbc_mac(SKE_ALG_SM4, SKE_CRYPTO_DECRYPT, SKE_ZERO_PADDING, key, 0, msg, 32, std_mac_msg32, 16);
#else
ret = ske_hp_cbc_mac_init(ctx1, SKE_ALG_SM4, SKE_VERIFY_MAC, SKE_ZERO_PADDING, NULL, 0, mac_bytes);
ret |= ske_hp_cbc_mac_update(ctx1, msg, 0x10);
ret |= ske_hp_cbc_mac_update(ctx1, msg+0x10, 0x10);
ret |= ske_hp_cbc_mac_final(ctx1, std_mac_msg32);
#endif
if(SKE_SUCCESS == ret)
{
printf("ske_hp_cbc_mac test success 2 (cpu mode)\n");
}
else
{
printf("ske_hp_cbc_mac test error (cpu mode)!!!! ret=%d\n", ret);
print_buf_U8(mac, 16, "mac");
}
//DMA mode //OK
#if 0
ret = ske_hp_dma_cbc_mac(SKE_ALG_SM4, key, 0, std_in_, 32, std_out_, 16, NULL);
#else
mac_bytes = 15;
ret = ske_hp_dma_cbc_mac_init(ctx, SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, NULL, 0, mac_bytes);
ret |= ske_hp_dma_cbc_mac_update_blocks_excluding_last_block(ctx, std_in_, 16, NULL);
ret |= ske_hp_dma_cbc_mac_update_including_last_block(ctx, std_in_+4, 16, std_out_, NULL);
#endif
if((SKE_SUCCESS == ret) && (0u == memcmp_((uint8_t *)std_out_, std_mac_msg32, mac_bytes)))
{
printf("ske_hp_cbc_mac test success 2 (DMA mode)\n");
}
else
{
printf("ske_hp_cbc_mac test error (DMA mode)!!!! ret=%d\n", ret);
print_buf_U8(std_mac_msg32, 16, "std_mac_msg32");
print_buf_U8((uint8_t *)std_out_, mac_bytes, "mac");
}
mac_bytes = 16u;
ret = ske_hp_dma_cbc_mac(SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, NULL, 0, std_in_, 16, std_out_, mac_bytes, NULL);
if((SKE_SUCCESS == ret) && (0u == memcmp_((uint8_t *)std_out_, std_mac_msg16, mac_bytes)))
{
printf("ske_hp_cbc_mac test success 3 (DMA mode)\n");
}
else
{
printf("ske_hp_cbc_mac test error 3 (DMA mode)!!!! ret=%d\n", ret);
print_buf_U8(std_mac_msg32, 16, "std_mac_msg32");
print_buf_U8((uint8_t *)std_out_, 16, "mac");
}
mac_bytes = 16u;
ret = ske_hp_dma_cbc_mac(SKE_ALG_SM4, SKE_GENERATE_MAC, SKE_ZERO_PADDING, NULL, 0, std_in_, 32+1, std_out_, mac_bytes, NULL);
if((SKE_SUCCESS == ret) && (0u == memcmp_((uint8_t *)std_out_, std_mac_msg33, mac_bytes)))
{
printf("ske_hp_cbc_mac test success 4 (DMA mode)\n");
}
else
{
printf("ske_hp_cbc_mac test error 4 (DMA mode)!!!! ret=%d\n", ret);
print_buf_U8(std_mac_msg32, 16, "std_mac_msg32");
print_buf_U8((uint8_t *)std_out_, 16, "mac");
}
}
2)CMAC
void CZH_CMAC_TEST()
{
uint8_t key[16] = {0xE0,0x70,0x99,0xF1,0xBF,0xAF,0xFD,0x7F,0x24,0x0C,0xD7,0x90,0xCA,0x4F,0xE1,0x34};
uint8_t msg[4*16+1] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x40};
uint8_t mac[16] = {0};
uint8_t std_cmac_msg65[16] = {0x09,0xD7,0xF1,0x24,0x96,0xD4,0xE8,0x4C,0x39,0xC0,0x5F,0x29,0x8F,0xD3,0x9D,0xC5};
uint8_t std_cmac_msg0[16] = {0xEA,0xC1,0x01,0xA7,0x62,0xFD,0xB0,0x9F,0xEF,0xB2,0xAE,0xD6,0x5F,0x15,0x2F,0x13};
uint32_t ret;
uint32_t i;
uint32_t *std_in_, *std_out_;
std_in_ = (uint32_t *)SKE_DMA_RAM_BASE;
std_out_ = std_in_+64;
uint32_copy(std_in_, (uint32_t *)msg, (65+3)/4);
uint32_copy(std_out_, (uint32_t *)std_cmac_msg65, 16/4);
//CPU mode
// ret = ske_hp_cmac(SKE_ALG_SM4, SKE_GENERATE_MAC, key, 0, msg, 65, mac, 16);
// if((SKE_SUCCESS == ret) && (0u == memcmp_(mac, std_cmac_msg65, 16)))
// {
// printf("ske_hp_cmac test success(cpu mode)\n");
// }
// else
// {
// printf("ske_hp_cmac test error (cpu mode)!!!! ret=%d\n", ret);
// print_buf_U8(mac, 16, "mac");
// }
// ret = ske_hp_cmac(SKE_ALG_SM4, SKE_CRYPTO_DECRYPT, key, 0, msg, 65, std_cmac_msg65, 16);
// if((SKE_SUCCESS == ret) && (0u == memcmp_(mac, std_cmac_msg65, 16)))
// {
// printf("ske_hp_cmac test success 2 (cpu mode)\n");
// }
// else
// {
// printf("ske_hp_cmac test error (cpu mode)!!!! ret=%d\n", ret);
// print_buf_U8(mac, 16, "mac");
// }
ret = ske_hp_cmac(SKE_ALG_SM4, SKE_GENERATE_MAC, key, 0, msg, 0, mac, 16);
if((SKE_SUCCESS == ret) && (0u == memcmp_(mac, std_cmac_msg0, 16)))
{
printf("ske_hp_cmac test success 3 (cpu mode)\n");
}
else
{
printf("ske_hp_cmac test error (cpu mode)!!!! ret=%d\n", ret);
print_buf_U8(mac, 16, "mac");
}
//DMA mode //OK
#if 0
ret = ske_hp_dma_cmac(SKE_ALG_SM4, key, 0, std_in_, 32, std_out_, 16, NULL);
#else
SKE_CMAC_DMA_CTX ctx[1];
uint32_t mac_bytes = 15;
ret = ske_hp_dma_cmac_init(ctx, SKE_ALG_SM4, SKE_GENERATE_MAC, key, 0, mac_bytes);
ret |= ske_hp_dma_cmac_update_blocks_excluding_last_block(ctx, std_in_, 64, NULL);
ret |= ske_hp_dma_cmac_update_including_last_block(ctx, std_in_+(64/4), 1, std_out_, NULL);
#endif
if((SKE_SUCCESS == ret) && (0u == memcmp_((uint8_t *)std_out_, std_cmac_msg65, mac_bytes)))
{
printf("ske_hp_dma_cmac test success 2 (DMA mode)\n");
}
else
{
printf("ske_hp_dma_cmac test error (DMA mode)!!!! ret=%d\n", ret);
print_buf_U8(std_cmac_msg65, 16, "std_mac_msg32");
print_buf_U8((uint8_t *)std_out_, mac_bytes, "mac");
}
mac_bytes = 16u;
ske_hp_dma_cmac(SKE_ALG_SM4, SKE_GENERATE_MAC, key, 0, std_in_, 0, std_out_, 16, NULL);
if((SKE_SUCCESS == ret) && (0u == memcmp_((uint8_t *)std_out_, std_cmac_msg0, mac_bytes)))
{
printf("ske_hp_dma_cmac test success 3 (DMA mode)\n");
}
else
{
printf("ske_hp_dma_cmac test error 3 (DMA mode)!!!! ret=%d\n", ret);
print_buf_U8(std_cmac_msg0, 16, "std_mac_msg32");
print_buf_U8((uint8_t *)std_out_, 16, "mac");
}
}
PQC-LMS微码开发
//固定参数
csr_hash_mode = 0x02; // sha256
csr_out_len = 32;//摘要输出长度
//变动参数
csr_in_len = 3;//msg 长度
csr_byte_slot_size = 32;//每个槽的长度
csr_byte_slot_offset = 0; //槽的偏移
//一次性计算示例demo
or = 0, //0(input is from PQC RAM), 1(input is from DMA RAM),DMA RAM是指用户侧存储空间
rs1 = 0, //输入的slot的index
rs2 = 2;//输出的slot的index
mem_to_pqc_ram((uint8_t *)&(ram[csr_byte_slot_offset + csr_byte_slot_size * rs1]), std_msg, 3u);//数据搬运到pqc ram
op_osr_hash_onepass(or, rs1, rs2);
pqc_ram_to_mem(buf, (uint8_t *)&(ram[csr_byte_slot_offset + csr_byte_slot_size * rs2]), csr_out_len);
//分段计算示例demo
// completely init,0(completely init), 1(init with iterator input),rs1: input hash iv(iterator) index in pqc ram
op_osr_hash_init(0, 0);
rs1 = 0, //输入的slot的index
mem_to_pqc_ram((uint8_t *)&(ram[csr_byte_slot_offset + csr_byte_slot_size * rs1]), std_msg, 3u);
op_osr_hash_update(or, rs1); // or = 0, data is from pqc ram
rs2 = 2; //输出的slot的index
op_osr_hash_final(0, rs2); // get digest -> rs2
pqc_ram_to_mem(buf, (uint8_t *)&(ram[csr_byte_slot_offset + csr_byte_slot_size * rs2]), csr_out_len);//mem <- rs2
//pqc ram
uint32_t pqc_ram[4096];//word wr&rd
uint8_t pqc_ram_byte[4096];//byte wr&rd
//lm ots offset
#define LM_OTS_ERROR_OFFSET (0)
#define LM_OTS_TYPE_OFFSET (LM_OTS_ERROR_OFFSET + 1)
#define LM_OTS_W_OFFSET (LM_OTS_TYPE_OFFSET + 1)
#define LM_OTS_P_OFFSET (LM_OTS_W_OFFSET + 1)
#define LM_OTS_LS_OFFSET (LM_OTS_P_OFFSET + 1)
uint32_t* p_lm_ots_error = ((uint32_t *)(&pqc_ram[LM_OTS_ERROR_OFFSET]));
uint32_t* p_lm_ots_type = ((uint32_t *)(&pqc_ram[LM_OTS_TYPE_OFFSET]));
uint32_t* p_lm_ots_w = ((uint32_t *)(&pqc_ram[LM_OTS_W_OFFSET]));
uint32_t* p_lm_ots_p = ((uint32_t *)(&pqc_ram[LM_OTS_P_OFFSET]));
uint32_t* p_lm_ots_ls = ((uint32_t *)(&pqc_ram[LM_OTS_LS_OFFSET]));
#define LM_OTS_MSG_HASH_CKSUM_OFFSET (0)
uint8_t* p_lm_ots_msg_hash_cksum = ((uint8_t *)(&pqc_ram_byte[LM_OTS_MSG_HASH_CKSUM_OFFSET]));
#define LM_OTS_COEF_F_S_OFFSET (LM_OTS_LS_OFFSET + 1)
#define LM_OTS_COEF_F_I_OFFSET (LM_OTS_COEF_F_S_OFFSET + 1)
#define LM_OTS_COEF_F_INDEX_OFFSET (LM_OTS_COEF_F_I_OFFSET + 1)
#define LM_OTS_COEF_F_SHIFT_OFFSET (LM_OTS_COEF_F_INDEX_OFFSET + 1)
#define LM_OTS_COEF_F_MASK_OFFSET (LM_OTS_COEF_F_SHIFT_OFFSET + 1)
#define LM_OTS_COEF_F_RETURN_OFFSET (LM_OTS_COEF_F_MASK_OFFSET + 1)
uint32_t* p_lm_ots_coef_f_S = ((uint32_t*)(&pqc_ram[LM_OTS_COEF_F_S_OFFSET]));
uint32_t* p_lm_ots_coef_f_i = ((uint32_t*)(&pqc_ram[LM_OTS_COEF_F_I_OFFSET]));
uint32_t* p_lm_ots_coef_f_index = ((uint32_t*)(&pqc_ram[LM_OTS_COEF_F_INDEX_OFFSET]));
uint32_t* p_lm_ots_coef_f_shift = ((uint32_t*)(&pqc_ram[LM_OTS_COEF_F_SHIFT_OFFSET]));
uint32_t* p_lm_ots_coef_f_mask = ((uint32_t*)(&pqc_ram[LM_OTS_COEF_F_MASK_OFFSET]));
uint32_t* p_lm_ots_coef_f_return = ((uint32_t*)(&pqc_ram[LM_OTS_COEF_F_RETURN_OFFSET]));
// csr_hash_mode = 0x02; //sha256
set_csr_value(uin32_t idx, uint32 value) //idx = csr_alu_mode_idx
{
op_osr_cfgi(idx, value & 0xff, 0);
op_osr_cfgi(idx, (value>>8)&0xff, 1);
op_osr_cfgi(idx, (value>>16)&0xff, 2);
op_osr_cfgi(idx, (value>>24)&0xff, 3);
}
op_osr_cfgi(18, 0x02, 0);
op_osr_cfgi(18, 0x00, 1);
op_osr_cfgi(18, 0x00, 2);
op_osr_cfgi(18, 0x00, 3);
// csr_in_len = 3;
op_osr_cfgi(0, 0x03, 0);
op_osr_cfgi(0, 0x00, 1);
op_osr_cfgi(0, 0x00, 2);
op_osr_cfgi(0, 0x00, 3);
// csr_out_len = 20;
op_osr_cfgi(1, 0x14, 0);
op_osr_cfgi(1, 0x00, 1);
op_osr_cfgi(1, 0x00, 2);
op_osr_cfgi(1, 0x00, 3);
// csr_byte_slot_offset = 4;
op_osr_cfgi(11, 0x04, 0);
op_osr_cfgi(11, 0x00, 1);
op_osr_cfgi(11, 0x00, 2);
op_osr_cfgi(11, 0x00, 3);
// csr_byte_slot_size = 32;
op_osr_cfgi(10, 0x20, 0);
op_osr_cfgi(10, 0x00, 1);
op_osr_cfgi(10, 0x00, 2);
op_osr_cfgi(10, 0x00, 3);