← 首页 PQC-LMS微码开发

一、伽罗瓦计数器模式(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)部分测试记录
//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.95‬ms/次
次/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) 其他修改

函数名称

  1. XCBC MAC统一改为AES XCBC MAC 96,RFC《3566》里已规定是128bit密钥,算法参数可以去掉
  2. 测试例子中的随机向量测试可以删除了
//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);