一、伽罗瓦计数器模式(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);
四、自测
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");
终、其他
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
非易失性存储器,即使关闭电源也能够保存已保存数据的存储器