cipher使用参考
REVISION HISTORY¶
Revision No. | Description |
Date |
---|---|---|
1.00 | 04/18/2024 |
1. uboot¶
1.1 代码框架¶
1.2 cipher API接口解析¶
1.2.1 aes加解密接口¶
函数原型:
@pConfig:the 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加密为例:
- 配置加解密数据源数据,目标数据地址和长度,aeskey类型和长度,aeskey地址(cipherkey need),是否设置iv和iv地址(cbc/ctr mode need),加密模式(ecb/cbc/ctr)。
- 使用MDrv_AESDMA_Run接口将配置写入寄存器并触发。
- 加密完成的数据可以在地址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) |
1.2.2 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为例:
- 配置加解密数据源数据,目标数据地址和长度,加密模式(sha1/sha256)。
- 使用MDrv_SHA_Run接口将配置写入寄存器并触发。
- 加密完成的数据可以在地址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)))关键字进行定义。
1.2.3 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为例:
- 配置加解密数据源数据,目标数据地址和长度,KeyN,KeyE,KeyLen,类型(公钥,私钥)等。
- 使用MDrv_RSA_Run接口将配置写入寄存器并触发。
- 加密完成的数据可以在地址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"); } }
注意:非对称加密算法中,有两个密钥:公钥和私钥。它们是一对,如果用公钥进行加密,只有用对应的私钥才能解密;如果用私钥进行加密,只有用对应的公钥才能解密。
2. kernel¶
2.1 config设定¶
2.2 代码框架¶
2.3 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算法。
2.3.1 aes加解密接口¶
demo路径:drivers/sstar/crypto/cryptodev/examples/aes.c
-
打开节点
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 needed here) */ if (fcntl(cfd, F_SETFD, 1) == -1) { perror("fcntl(F_SETFD)"); return 1; }
-
创建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; }
-
进行加解密
结构体说明
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; }
-
关闭session
void aes_ctx_deinit(struct cryptodev_ctx* ctx) { if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { perror("ioctl(CIOCFSESSION)"); } }
-
关闭节点
/* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; }
注意目前硬件加速只支持aes(ecb/cbc/ctr),如果需要使用其他算法,将使用软件解密。其中,硬件加速的aes对输入数据大小的对齐要求如下:
mode | size alignment |
---|---|
ecb | 16 bytes |
cbc | 1 bytes |
ctr | 1 bytes |
对输入数据的内存地址没有对齐要求,但使用aes的时候建议为16bytes对齐,可使得cryptodev开启zero copy功能,减少用户层与内核层之间的内存拷贝。 硬件加速AES支持key size为128 / 256 bit。
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) |
2.3.2 hash运算接口¶
demo路径:drivers/sstar/crypto/cryptodev/examples/sha.c
-
打开节点
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 needed here) */ if (fcntl(cfd, F_SETFD, 1) == -1) { perror("fcntl(F_SETFD)"); return 1; }
-
创建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; }
-
进行运算
结构体说明
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; }
-
关闭session
void sha_ctx_deinit(struct cryptodev_ctx* ctx) { if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { perror("ioctl(CIOCFSESSION)"); } }
-
关闭节点
/* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; }
注意目前硬件加速只支持sha256算法,如果使用其他算法(如sha1,md5)会调用软件算法。
2.3.3 rsa加解密接口¶
RSA加解密接口支持RSA512/1024/2048/4096(由于RSA512/1024的安全性较低,建议使用RSA2048/4096),demo路径:drivers/sstar/crypto/cryptodev/examples/cipher/cipher_rsa_sync.c
-
打开节点
int fd = -1; /* Open the crypto device */ fd = open("/dev/rsa", O_RDWR, 0); if (fd < 0) { perror("open(/dev/rsa)"); return 1; }
-
进行运算
结构体说明
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->512,128->1024,256->2048,512->4096 unsigned int u32RSA_KeyELen; //64->512,128->1024,256->2048,512->4096 unsigned int u32RSA_SigLen; //64->512,128->1024,256->2048,512->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 // RSA calculate if (ioctl(fd, MDrv_RSA_Calculate, prsa_config)) { perror("ioctl(MDrv_RSA_Calculate)"); return 1; } #endif return 0; }
-
关闭节点
/* Close the original descriptor */ if (close(fd)) { perror("close(fd)"); return 1; }
其中,RSA对输入数据(pu32RSA_Sig)、KeyN(pu32RSA_KeyN)、KeyE(pu32RSA_KeyE)的大小要求如下:
RSA | input size | KeyN size | KeyE size |
---|---|---|---|
512 | 64 bytes | 64 bytes | 64 bytes |
1024 | 128 bytes | 128 bytes | 128 bytes |
2048 | 256 bytes | 256 bytes | 256 bytes |
4096 | 512 bytes | 512 bytes | 512 bytes |