SSU_cipher使用参考

uboot

代码框架

img

cipher API接口解析

aes加解密接口

函数原型:

@pConfigthe config of configurating aes hardware
void MDrv_AESDMA_Run(aesdmaConfig* pConfig);

aesdmaConfig结构体字段解释:

typedef struct
{
    MS_U64               u64SrcAddr;                    //the address of source data
    U32                  u32Size;                       //the size of data that needs to be encrypted
    MS_U64               u64DstAddr;                    //the address of destination data
    enumAESDMA_KeyType   eKeyType;
    //the type of aeskey,ep:    E_AESDMA_KEY_CIPHER,    E_AESDMA_KEY_OTP_EFUSE_KEY1~8,
    U16 *                pu16Key;                       //the address of cipherkey
    BOOL                 bSetIV;                        //set iv or not
    BOOL                 bDecrypt;                      //0:encrypt,1:decrypt
    U16 *                pu16IV;                        //the address of iv(16byte)
    enumAESDMA_ChainMode eChainMode;
    //three mode: E_AESDMA_CHAINMODE_ECB, E_AESDMA_CHAINMODE_CTR, E_AESDMA_CHAINMODE_CBC
    U32                  keylen;                        // 16->aes128,32->aes256
} __attribute__((aligned(16))) aesdmaConfig;

demo路径:cmd/sstar/aes.c

以cbc加密为例:

  1. 配置加解密数据源数据,目标数据地址和长度,aeskey类型和长度,aeskey地址(cipherkey need),是否设置iv和iv地址(cbc/ctr mode need),加密模式(ecb/cbc/ctr)。
  2. 使用MDrv_AESDMA_Run接口将配置写入寄存器并触发。
  3. 加密完成的数据可以在地址config.u64DstAddr中读取到,长度为config.u32Size。
char __attribute__((aligned(64))) out_buf[128] = {0};
char __attribute__((aligned(16))) aes_cbc_plaintext[] = {
    "\x00\x01\x02\x03\x04\x05\x06\x07"
    "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
    "\x10\x11\x12\x13\x14\x15\x16\x17"
    "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"};
char __attribute__((aligned(16))) aes_cbc_key[] = {
    "\xc2\x86\x69\x6d\x88\x7c\x9a\xa0"
    "\x61\x1b\xbb\x3e\x20\x25\xa4\x5a"};
char __attribute__((aligned(16))) aes_cbc_iv[] = {
    "\x56\x2e\x17\x99\x6d\x09\x3d\x28"
    "\xdd\xb3\xba\x69\x5a\x2e\x6f\x58"};
char __attribute__((aligned(16))) aes_cbc_result[] = {
    "\xd2\x96\xcd\x94\xc2\xcc\xcf\x8a"
    "\x3a\x86\x30\x28\xb5\xe1\xdc\x0a"
    "\x75\x86\x60\x2d\x25\x3c\xff\xf9"
    "\x1b\x82\x66\xbe\xa6\xd6\x1a\xb1"};

void verify_cbc_aes_encrypt(void)
{
    aesdmaConfig config = {0};

    int in_size;

    printf("\nTest AES-CBC encryption ");

    in_size = aes_cbc_ilen;
    memcpy(in_buf, aes_cbc_plaintext, in_size);

    //config struct aesdmaConfig
    config.u64SrcAddr = (unsigned long)in_buf;
    config.u64DstAddr = (unsigned long)out_buf;
    config.u32Size    = in_size;
    config.eKeyType   = E_AESDMA_KEY_CIPHER;
    config.pu16Key    = (U16 *)aes_cbc_key;
    config.pu16IV     = (U16 *)aes_cbc_iv;
    config.bSetIV     = 1;
    config.eChainMode = E_AESDMA_CHAINMODE_CBC;

    //trig aesdma hardware
    MDrv_AESDMA_Run(&config);

    //compare result
    if (Compare_data(out_buf, aes_cbc_result, config.u32Size))
    {
        printf("Failed\n");
        Dump_data(out_buf, config.u32Size);
    }
    else
    {
        printf("passed!!\n");
    }
}

注意:ECB模式的加密资料的长度必须是16byte对齐。

otpkey作为密钥

如果需要以otpkey作为密钥,需要提前烧录OTP_AES128_KEY ,OTP中AESKEY256实际上是由OTP中两把AES128组合而成,组合和设置方式举例如下。

欲设置

KEY256_1:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F

需设置

key128_1:000102030405060708090A0B0C0D0E0F key128_2:101112131415161718191A1B1C1D1E1F

配置方法和对应关系如下表:

eKeyType keylen corresponding otpkey
E_AESDMA_KEY_OTP_EFUSE_KEY1 16 key128_1
E_AESDMA_KEY_OTP_EFUSE_KEY2 16 key128_2
E_AESDMA_KEY_OTP_EFUSE_KEY3 16 key128_3
E_AESDMA_KEY_OTP_EFUSE_KEY4 16 key128_4
E_AESDMA_KEY_OTP_EFUSE_KEY5 16 key128_5
E_AESDMA_KEY_OTP_EFUSE_KEY6 16 key128_6
E_AESDMA_KEY_OTP_EFUSE_KEY7 16 key128_7
E_AESDMA_KEY_OTP_EFUSE_KEY8 16 key128_8
E_AESDMA_KEY_OTP_EFUSE_KEY1 32 key256_1(key128_1+key128_2)
E_AESDMA_KEY_OTP_EFUSE_KEY2 32 key256_2(key128_3+key128_4)
E_AESDMA_KEY_OTP_EFUSE_KEY3 32 key256_3(key128_5+key128_6)
E_AESDMA_KEY_OTP_EFUSE_KEY4 32 key256_4(key128_7+key128_8)

hash运算接口

@u64SrcAddr:        //the address of source data
@u32Size:           //the size of data that needs to be hashed
@eMode:             //E_SHA_MODE_1 or E_SHA_MODE_256
@pu16Output:        //the address of destination data
void MDrv_SHA_Run(MS_U64 u64SrcAddr, U32 u32Size, enumShaMode eMode, U16* pu16Output)

demo路径:cmd/sstar/aes.c

以sha256为例:

  1. 配置加解密数据源数据,目标数据地址和长度,加密模式(sha1/sha256)。
  2. 使用MDrv_SHA_Run接口将配置写入寄存器并触发。
  3. 加密完成的数据可以在地址pu16Output中读取到,sha1长度为10byte,sha256长度为16byte。
char __attribute__((aligned(16))) sha_plaintext[] = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
int  sha_psize                                    = 56;
char sha_digest[] =
    "\x24\x8d\x6a\x61\xd2\x06\x38\xb8"
    "\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
    "\xa3\x3c\xe4\x59\x64\xff\x21\x67"
    "\xf6\xec\xed\xd4\x19\xdb\x06\xc1";

void verify_sha(void)
{
    char __attribute__((aligned(16))) out_buf[128] = {0};

    printf("\nTest %s ", __FUNCTION__);

    MDrv_SHA_Run((unsigned long)sha_plaintext, sha_psize, E_SHA_MODE_256, (U16 *)out_buf);

    if (Compare_data(out_buf, sha_digest, 32))
    {
        printf("Failed\n");
        Dump_data(out_buf, 32);
    }
    else
    {
        printf("passed!!\n");
    }
}

注意:sha的u64SrcAddr必须是十六byte对齐的,源数据请用 __attribute__((aligned(16)))关键字进行定义。

rsa加解密接口

@pConfig:the config of configurating rsa hardware
void MDrv_RSA_Run(rsaConfig* pConfig)
typedef struct
{
    U32 *pu32Sig;               //the address of source data
    U32 *pu32KeyN;              //the address of KeyN
    U32 *pu32KeyE;              //the address of KeyE
    U32 *pu32Output;            //the address of destination data
    BOOL bHwKey;                //Invalid parameter
    BOOL bPublicKey;            //0:pvivate key,1:public key
    U32  u32KeyLen;             //256->2048,512->4096
    U32  u32SigLen;             //256->2048,512->4096
    U32  u32OutputLen;          //0,256->2048,512->4096
} __attribute__((aligned(16))) rsaConfig;

注:rsa只在上电的时候load一次hw key,用于rom code阶段的验签,之后都无法使用hw key。

demo路径:cmd/sstar/aes.c

以rsa2048为例:

  1. 配置加解密数据源数据,目标数据地址和长度,KeyN,KeyE,KeyLen,类型(公钥,私钥)等。
  2. 使用MDrv_RSA_Run接口将配置写入寄存器并触发。
  3. 加密完成的数据可以在地址pu16Output中读取到,rsa2048长度为256byte,rsa4096长度为512byte。
char RSA_plaintext[] = {
    0x31, 0x5d, 0xfa, 0x52, 0xa4, 0x93, 0x52, 0xf8, 0xf5, 0xed, 0x39, 0xf4, 0xf8, 0x23, 0x4b, 0x30, 0x11, 0xa2, 0x2c,
    0x5b, 0xa9, 0x8c, 0xcf, 0xdf, 0x19, 0x66, 0xf5, 0xf5, 0x1a, 0x6d, 0xf6, 0x25, 0x89, 0xaf, 0x06, 0x13, 0xdc, 0xa4,
    0xd4, 0x0b, 0x3c, 0x1c, 0x4f, 0xb9, 0xd3, 0xd0, 0x63, 0x29, 0x2a, 0x5d, 0xfe, 0xb6, 0x99, 0x20, 0x58, 0x36, 0x2b,
    0x1d, 0x57, 0xf4, 0x71, 0x38, 0xa7, 0x8b, 0xad, 0x8c, 0xef, 0x1f, 0x2f, 0xea, 0x4c, 0x87, 0x2b, 0xd7, 0xb8, 0xc8,
    0xb8, 0x09, 0xcb, 0xb9, 0x05, 0xab, 0x43, 0x41, 0xd9, 0x75, 0x36, 0x4d, 0xb6, 0x8a, 0xd3, 0x45, 0x96, 0xfd, 0x9c,
    0xe8, 0x6e, 0xc8, 0x37, 0x5e, 0x4f, 0x63, 0xf4, 0x1c, 0x18, 0x2c, 0x38, 0x79, 0xe2, 0x5a, 0xe5, 0x1d, 0x48, 0xf6,
    0xb2, 0x79, 0x57, 0x12, 0xab, 0xae, 0xc1, 0xb1, 0x9d, 0x11, 0x4f, 0xa1, 0x4d, 0x1b, 0x4c, 0x8c, 0x3a, 0x2d, 0x7b,
    0x98, 0xb9, 0x89, 0x7b, 0x38, 0x84, 0x13, 0x8e, 0x3f, 0x3c, 0xe8, 0x59, 0x26, 0x90, 0x77, 0xe7, 0xca, 0x52, 0xbf,
    0x3a, 0x5e, 0xe2, 0x58, 0x54, 0xd5, 0x9b, 0x2a, 0x0d, 0x33, 0x31, 0xf4, 0x4d, 0x68, 0x68, 0xf3, 0xe9, 0xb2, 0xbe,
    0x28, 0xeb, 0xce, 0xdb, 0x36, 0x1e, 0xae, 0xb7, 0x37, 0xca, 0xaa, 0xf0, 0x9c, 0x6e, 0x27, 0x93, 0xc9, 0x61, 0x76,
    0x99, 0x1a, 0x0a, 0x99, 0x57, 0xa8, 0xea, 0x71, 0x96, 0x63, 0xbc, 0x76, 0x11, 0x5c, 0x0c, 0xd4, 0x70, 0x0b, 0xd8,
    0x1c, 0x4e, 0x95, 0x89, 0x5b, 0x09, 0x17, 0x08, 0x44, 0x70, 0xec, 0x60, 0x7c, 0xc9, 0x8a, 0xa0, 0xe8, 0x98, 0x64,
    0xfa, 0xe7, 0x52, 0x73, 0xb0, 0x04, 0x9d, 0x78, 0xee, 0x09, 0xa1, 0xb9, 0x79, 0xd5, 0x52, 0x4f, 0xf2, 0x39, 0x1c,
    0xf7, 0xb9, 0x73, 0xe0, 0x3d, 0x6b, 0x54, 0x64, 0x86};

char RSA_KEYN[] = {
    0x82, 0x78, 0xA0, 0xC5, 0x39, 0xE6, 0xF6, 0xA1, 0x5E, 0xD1, 0xC6, 0x8B, 0x9C, 0xF9, 0xC4, 0x3F, 0xEA, 0x19, 0x16,
    0xB0, 0x96, 0x3A, 0xB0, 0x5A, 0x94, 0xED, 0x6A, 0xD3, 0x83, 0xE8, 0xA0, 0xFD, 0x01, 0x5E, 0x92, 0x2A, 0x7D, 0x0D,
    0xF9, 0x72, 0x1E, 0x03, 0x8A, 0x68, 0x8B, 0x4D, 0x57, 0x55, 0xF5, 0x2F, 0x9A, 0xC9, 0x45, 0xCF, 0x9B, 0xB7, 0xF5,
    0x11, 0x94, 0x7A, 0x16, 0x0B, 0xED, 0xD9, 0xA3, 0xF0, 0x63, 0x8A, 0xEC, 0xD3, 0x21, 0xAB, 0xCF, 0x74, 0xFC, 0x6B,
    0xCE, 0x06, 0x4A, 0x51, 0xC9, 0x7C, 0x7C, 0xA3, 0xC4, 0x10, 0x63, 0x7B, 0x00, 0xEC, 0x2D, 0x02, 0x18, 0xD5, 0xF1,
    0x8E, 0x19, 0x7F, 0xBE, 0xE2, 0x45, 0x5E, 0xD7, 0xA8, 0x95, 0x90, 0x88, 0xB0, 0x73, 0x35, 0x89, 0x66, 0x1C, 0x23,
    0xB9, 0x6E, 0x88, 0xE0, 0x7A, 0x57, 0xB0, 0x55, 0x8B, 0x81, 0x9B, 0x9C, 0x34, 0x9F, 0x86, 0x0E, 0x15, 0x94, 0x2C,
    0x6B, 0x12, 0xC3, 0xB9, 0x56, 0x60, 0x25, 0x59, 0x3E, 0x50, 0x7B, 0x62, 0x4A, 0xD0, 0xF0, 0xB6, 0xB1, 0x94, 0x83,
    0x51, 0x66, 0x6F, 0x60, 0x4D, 0xEF, 0x8F, 0x94, 0xA6, 0xD1, 0xA2, 0x80, 0x06, 0x24, 0xF2, 0x6E, 0xD2, 0xC7, 0x01,
    0x34, 0x8D, 0x2B, 0x6B, 0x03, 0xF7, 0x05, 0xA3, 0x99, 0xCC, 0xC5, 0x16, 0x75, 0x1A, 0x81, 0xC1, 0x67, 0xA0, 0x88,
    0xE6, 0xE9, 0x00, 0xFA, 0x62, 0xAF, 0x2D, 0xA9, 0xFA, 0xC3, 0x30, 0x34, 0x98, 0x05, 0x4C, 0x1A, 0x81, 0x0C, 0x52,
    0xCE, 0xBA, 0xD6, 0xEB, 0x9C, 0x1E, 0x76, 0x01, 0x41, 0x6C, 0x34, 0xFB, 0xC0, 0x83, 0xC5, 0x4E, 0xB3, 0xF2, 0x5B,
    0x4F, 0x94, 0x08, 0x33, 0x87, 0x5E, 0xF8, 0x39, 0xEF, 0x7F, 0x72, 0x94, 0xFF, 0xD7, 0x51, 0xE8, 0xA2, 0x5E, 0x26,
    0x25, 0x5F, 0xE9, 0xCC, 0x2A, 0x7D, 0xAC, 0x5B, 0x35};

char RSA_KEY_PrivateE[] = {
    0x49, 0x7E, 0x93, 0xE9, 0xA5, 0x7D, 0x42, 0x0E, 0x92, 0xB0, 0x0E, 0x6C, 0x94, 0xC7, 0x69, 0x52, 0x2B, 0x97, 0x68,
    0x5D, 0x9E, 0xB2, 0x7E, 0xA6, 0xF7, 0xDF, 0x69, 0x5E, 0xAE, 0x9E, 0x7B, 0x19, 0x2A, 0x0D, 0x50, 0xBE, 0xD8, 0x64,
    0xE7, 0xCF, 0xED, 0xB2, 0x46, 0xE4, 0x2F, 0x1C, 0x29, 0x07, 0x45, 0xAF, 0x44, 0x3C, 0xFE, 0xB3, 0x3C, 0xDF, 0x7A,
    0x10, 0x26, 0x18, 0x43, 0x95, 0x02, 0xAD, 0xA7, 0x98, 0x81, 0x2A, 0x3F, 0xCF, 0x8A, 0xD7, 0x12, 0x6C, 0xAE, 0xC8,
    0x37, 0x6C, 0xF9, 0xAE, 0x6A, 0x96, 0x52, 0x4B, 0x99, 0xE5, 0x35, 0x74, 0x93, 0x87, 0x76, 0xAF, 0x08, 0xB8, 0x73,
    0x72, 0x7D, 0x50, 0xA5, 0x81, 0x26, 0x5C, 0x8F, 0x94, 0xEA, 0x73, 0x59, 0x5C, 0x33, 0xF9, 0xC3, 0x65, 0x1E, 0x92,
    0xCD, 0x20, 0xC3, 0xBF, 0xD7, 0x8A, 0xCF, 0xCC, 0xD0, 0x61, 0xF8, 0xFB, 0x1B, 0xF4, 0xB6, 0x0F, 0xD4, 0xCF, 0x3E,
    0x55, 0x48, 0x4C, 0x99, 0x2D, 0x40, 0x44, 0x7C, 0xBA, 0x7B, 0x6F, 0xDB, 0x5D, 0x71, 0x91, 0x2D, 0x93, 0x80, 0x19,
    0xE3, 0x26, 0x5D, 0x59, 0xBE, 0x46, 0x6D, 0x90, 0x4B, 0xDF, 0x72, 0xCE, 0x6C, 0x69, 0x72, 0x8F, 0x5B, 0xA4, 0x74,
    0x50, 0x2A, 0x42, 0x95, 0xB2, 0x19, 0x04, 0x88, 0xD7, 0xDA, 0xBB, 0x17, 0x23, 0x69, 0xF4, 0x52, 0xEB, 0xC8, 0x55,
    0xBE, 0xBC, 0x2E, 0xA9, 0xD0, 0x57, 0x7D, 0xC6, 0xC8, 0x8B, 0x86, 0x7B, 0x73, 0xCD, 0xE4, 0x32, 0x79, 0xC0, 0x75,
    0x53, 0x53, 0xE7, 0x59, 0x38, 0x0A, 0x8C, 0xEC, 0x06, 0xA9, 0xFC, 0xA5, 0x15, 0x81, 0x61, 0x3E, 0x44, 0xCD, 0x05,
    0xF8, 0x54, 0x04, 0x00, 0x79, 0xB2, 0x0D, 0x69, 0x2A, 0x47, 0x60, 0x1A, 0x2B, 0x79, 0x3D, 0x4B, 0x50, 0x8A, 0x31,
    0x72, 0x48, 0xBB, 0x75, 0x78, 0xD6, 0x35, 0x90, 0xE1,
};

char RSA_KEY_PublicE[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01};

void verify_rsa(void)
{
    U8 rsa_encrypt_out[256];
    U8 rsa_decrypt_out[256];

    memset(rsa_encrypt_out, 0, sizeof(rsa_encrypt_out));
    memset(rsa_decrypt_out, 0, sizeof(rsa_decrypt_out));

    printf("\nTest %s encrypt\n", __FUNCTION__);
    {
        rsaConfig config  = {0};
        config.pu32KeyN   = (U32 *)RSA_KEYN;
        config.pu32KeyE   = (U32 *)RSA_KEY_PrivateE;
        config.u32KeyLen  = 256;
        config.pu32Sig    = (U32 *)(RSA_plaintext);
        config.u32SigLen  = sizeof(RSA_plaintext);
        config.bPublicKey = 0;
        config.pu32Output = (U32 *)rsa_encrypt_out;
        MDrv_RSA_Run(&config);
    }
    printf("Test %s decrypt\n", __FUNCTION__);
    {
        rsaConfig config  = {0};
        config.pu32KeyN   = (U32 *)RSA_KEYN;
        config.pu32KeyE   = (U32 *)RSA_KEY_PublicE;
        config.u32KeyLen  = 256;
        config.pu32Sig    = (U32 *)(rsa_encrypt_out);
        config.u32SigLen  = sizeof(rsa_encrypt_out);
        config.pu32Output = (U32 *)rsa_decrypt_out;

        config.bPublicKey = 1;
        MDrv_RSA_Run(&config);
    }

    if (Compare_data((char *)RSA_plaintext, (char *)rsa_decrypt_out, 256))
    {
        printf("Failed\n");
        printf("RSA_plaintext:\n");
        Dump_data(RSA_plaintext, 256);
        printf("rsa_encrypt_out:\n");
        Dump_data(rsa_encrypt_out, 256);
        printf("rsa_decrypt_out:\n");
        Dump_data(rsa_decrypt_out, 256);
    }
    else
    {
        printf("passed!!\n");
    }
}

注意:非对称加密算法中,有两个密钥:公钥和私钥。它们是一对,如果用公钥进行加密,只有用对应的私钥才能解密;如果用私钥进行加密,只有用对应的公钥才能解密。

kernel

代码框架

img

userspace下访问接口

通过用户层ioctl访问kernel。

  • aes,sha:借助原生提供的内核模块cryptodev,它提供了一种通用的加密API,使应用程序能够利用硬件加速的加密功能。可以通过打开 /dev/crypto 设备文件来访问加密功能。应用程序可以使用常见的加密算法(如AES、DES等)和模式(如CBC、ECB、CTR等)来执行加密和解密操作。

rsa

  • rsa:Kernel原生接口中不支持RSA算法,故RSA使用Linux标准接口注册misc类设备,产生/dev/rsa节点, User Space可通过节点使用Hardware RSA算法。

aes加解密接口

demo路径:drivers/sstar/crypto/cryptodev/examples/aes.c

  1. 打开节点

    int cfd = -1;
    
    /* Open the crypto device */
    cfd = open("/dev/crypto", O_RDWR, 0);
    if (cfd < 0)
    {
        perror("open(/dev/crypto)");
        return 1;
    }
    
    /* Set close-on-exec (not really neede here) */
    if (fcntl(cfd, F_SETFD, 1) == -1)
    {
        perror("fcntl(F_SETFD)");
        return 1;
    }
    
  2. 创建session

    int aes_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t* key, unsigned int key_size)
    {
    #ifdef CIOCGSESSINFO
        struct session_info_op siop;
    #endif
    
        memset(ctx, 0, sizeof(*ctx));
        ctx->cfd = cfd;
    
        ctx->sess.cipher = CRYPTO_AES_CBC;
        ctx->sess.keylen = key_size;
        ctx->sess.key    = (void*)key;
        if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess))
        {
            perror("ioctl(CIOCGSESSION)");
            return -1;
        }
    
    #ifdef CIOCGSESSINFO
        memset(&siop, 0, sizeof(siop));
    
        siop.ses = ctx->sess.ses;
        if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop))
        {
            perror("ioctl(CIOCGSESSINFO)");
            return -1;
        }
        printf("Got %s with driver %s\n", siop.cipher_info.cra_name, siop.cipher_info.cra_driver_name);
        if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
        {
            printf("Note: This is not an accelerated cipher\n");
        }
        /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask); */
        ctx->alignmask = siop.alignmask;
    #endif
        return 0;
    }
    
  3. 进行加解密

    结构体说明

    struct crypt_op
    {
        __u32        ses;   /* session identifier */
        __u16        op;    /* COP_ENCRYPT or COP_DECRYPT */
        __u16        flags; /* see COP_FLAG_* */
        __u32        len;   /* length of source data */
        __u8 __user *src;   /* source data */
        __u8 __user *dst;   /* pointer to output data */
        /* pointer to output data for hash/MAC operations */
        __u8 __user *mac;
        /* initialization vector for encryption operations */
        __u8 __user *iv;
    };
    

    加解密实例

    int aes_encrypt(struct cryptodev_ctx* ctx, const void* iv, const void* plaintext, void* ciphertext, size_t size)
    {
        struct crypt_op cryp;
        void*           p;
    
        /* check plaintext and ciphertext alignment */
        if (ctx->alignmask)
        {
            p = (void*)(((unsigned long)plaintext + ctx->alignmask) & ~ctx->alignmask);
            if (plaintext != p)
            {
                fprintf(stderr, "plaintext is not aligned\n");
                return -1;
            }
    
            p = (void*)(((unsigned long)ciphertext + ctx->alignmask) & ~ctx->alignmask);
            if (ciphertext != p)
            {
                fprintf(stderr, "ciphertext is not aligned\n");
                return -1;
            }
        }
    
        memset(&cryp, 0, sizeof(cryp));
    
        /* Encrypt data.in to data.encrypted */
        cryp.ses = ctx->sess.ses;
        cryp.len = size;
        cryp.src = (void*)plaintext;
        cryp.dst = ciphertext;
        cryp.iv  = (void*)iv;
        cryp.op  = COP_ENCRYPT;
        if (ioctl(ctx->cfd, CIOCCRYPT, &cryp))
        {
            perror("ioctl(CIOCCRYPT)");
            return -1;
        }
    
        return 0;
    }
    
  4. 关闭session

    void aes_ctx_deinit(struct cryptodev_ctx* ctx)
    {
        if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses))
        {
            perror("ioctl(CIOCFSESSION)");
        }
    }
    
  5. 关闭节点

    /* Close the original descriptor */
    if (close(cfd))
    {
        perror("close(cfd)");
        return 1;
    }
    

注意目前硬件加速只支持ecb(aes),cbc(aes),ctr(aes),如果需要使用其他算法,将使用软件解密。

otpkey作为密钥

由于kernel原生没有选择是否使用otpkey的接口,程序会根据key的头部是否是特殊的字符序列"SStarU*"判断是否使用otpkey。

如果需要以otpkey作为密钥,需要提前烧录OTP_AES128_KEY ,OTP中AESKEY256实际上是由OTP中两把AES128组合而成,组合和设置方式举例如下。

欲设置

KEY256_1:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F

需设置

key128_1:000102030405060708090A0B0C0D0E0F key128_2:101112131415161718191A1B1C1D1E1F

配置方法和对应关系如下表:

key keylen otpkey
"SStarU1" 16 key128_1
"SStarU2" 16 key128_2
"SStarU3" 16 key128_3
"SStarU4" 16 key128_4
"SStarU5" 16 key128_5
"SStarU6" 16 key128_6
"SStarU7" 16 key128_7
"SStarU8" 16 key128_8
"SStarU1" 32 key256_1(key128_1+key128_2)
"SStarU2" 32 key256_2(key128_3+key128_4)
"SStarU3" 32 key256_3(key128_5+key128_6)
"SStarU4" 32 key256_4(key128_7+key128_8)

hash运算接口

demo路径:drivers/sstar/crypto/cryptodev/examples/sha.c

  1. 打开节点

    int                  cfd = -1, i;
    
    /* Open the crypto device */
    cfd = open("/dev/crypto", O_RDWR, 0);
    if (cfd < 0)
    {
        perror("open(/dev/crypto)");
        return 1;
    }
    
    /* Set close-on-exec (not really neede here) */
    if (fcntl(cfd, F_SETFD, 1) == -1)
    {
        perror("fcntl(F_SETFD)");
        return 1;
    }
    
  2. 创建session

    int sha_ctx_init(struct cryptodev_ctx* ctx, int cfd, const uint8_t* key, unsigned int key_size)
    {
    #ifdef CIOCGSESSINFO
        struct session_info_op siop;
    #endif
    
        memset(ctx, 0, sizeof(*ctx));
        ctx->cfd = cfd;
    
        if (key == NULL)
            ctx->sess.mac = CRYPTO_SHA2_256;
        else
        {
            ctx->sess.mac       = CRYPTO_SHA2_256_HMAC;
            ctx->sess.mackeylen = key_size;
            ctx->sess.mackey    = (void*)key;
        }
        if (ioctl(ctx->cfd, CIOCGSESSION, &ctx->sess))
        {
            perror("ioctl(CIOCGSESSION)");
            return -1;
        }
    
    #ifdef CIOCGSESSINFO
        siop.ses = ctx->sess.ses;
        if (ioctl(ctx->cfd, CIOCGSESSINFO, &siop))
        {
            perror("ioctl(CIOCGSESSINFO)");
            return -1;
        }
        printf("Got %s with driver %s\n", siop.hash_info.cra_name, siop.hash_info.cra_driver_name);
        if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
        {
            printf("Note: This is not an accelerated cipher\n");
        }
        /*printf("Alignmask is %x\n", (unsigned int)siop.alignmask);*/
        ctx->alignmask = siop.alignmask;
    #endif
        return 0;
    }
    
  3. 进行运算

    结构体说明

    struct crypt_op
    {
        __u32        ses;   /* session identifier */
        __u16        op;    /* COP_ENCRYPT or COP_DECRYPT */
        __u16        flags; /* see COP_FLAG_* */
        __u32        len;   /* length of source data */
        __u8 __user *src;   /* source data */
        __u8 __user *dst;   /* pointer to output data */
        /* pointer to output data for hash/MAC operations */
        __u8 __user *mac;
        /* initialization vector for encryption operations */
        __u8 __user *iv;
    };
    

    加解密实例

    int sha_hash(struct cryptodev_ctx* ctx, const void* text, size_t size, void* digest)
    {
        struct crypt_op cryp;
        void*           p;
    
        /* check text and ciphertext alignment */
        if (ctx->alignmask)
        {
            p = (void*)(((unsigned long)text + ctx->alignmask) & ~ctx->alignmask);
            if (text != p)
            {
                fprintf(stderr, "text is not aligned\n");
                return -1;
            }
        }
    
        memset(&cryp, 0, sizeof(cryp));
    
        /* Encrypt data.in to data.encrypted */
        cryp.ses = ctx->sess.ses;
        cryp.len = size;
        cryp.src = (void*)text;
        cryp.mac = digest;
        if (ioctl(ctx->cfd, CIOCCRYPT, &cryp))
        {
            perror("ioctl(CIOCCRYPT)");
            return -1;
        }
    
        return 0;
    }
    
  4. 关闭session

    void sha_ctx_deinit(struct cryptodev_ctx* ctx)
    {
        if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses))
        {
            perror("ioctl(CIOCFSESSION)");
        }
    }
    
  5. 关闭节点

    /* Close the original descriptor */
    if (close(cfd))
    {
        perror("close(cfd)");
        return 1;
    }
    

注意目前硬件加速只支持sha256算法,如果使用其他算法(如sha1,md5)会调用软件算法。

rsa加解密接口

demo路径:drivers/sstar/crypto/cryptodev/examples/cipher/cipher_rsa_sync.c

  1. 打开节点

    int fd  = -1;
    
    /* Open the crypto device */
    fd = open("/dev/rsa", O_RDWR, 0);
    if (fd < 0)
    {
        perror("open(/dev/rsa)");
        return 1;
    }
    
  2. 进行运算

    结构体说明

    struct rsa_config
    {
        unsigned int *pu32RSA_Sig;          //the address of source data
        unsigned int *pu32RSA_KeyN;         //the address of KeyN
        unsigned int *pu32RSA_KeyE;         //the address of KeyE
        unsigned int *pu32RSA_Output;       //the address of destination data
        unsigned int  u32RSA_KeyNLen;       //64->2048,128->4096
        unsigned int  u32RSA_KeyELen;       //64->2048,128->4096
        unsigned int  u32RSA_SigLen;        //64->2048,128->4096
        unsigned char u8RSA_pub_ekey;       //0:pvivate key,1:public key
    };
    

    加解密实例

    static int test_rsa(int fd, struct rsa_config *prsa_config)
    {
        int i = 0;
    
    #if 1
        // reset RSA
        if (ioctl(fd, MDrv_RSA_Reset, NULL))
        {
            perror("ioctl(MDrv_RSA_Reset)");
            return 1;
        }
    
        // RSA calculate
        if (ioctl(fd, MDrv_RSA_Calculate, prsa_config))
        {
            perror("ioctl(MDrv_RSA_Calculate)");
            return 1;
        }
    #endif
    
        return 0;
    }
    
  3. 关闭节点

    /* Close the original descriptor */
    if (close(fd))
    {
        perror("close(fd)");
        return 1;
    }