cipher User Guide¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.00 | 06/12/2024 |
1. Overview¶
cipher module, which can be used for AES encryption and decryption, SHA calculation, RSA encryption and decryption, and digital signature verification.
2. Keyword description¶
-
AESDMA
Hardware module for encryption and decryption calculations.
3. Function description¶
-
aes
Supports AES128/AES192/AES256 encryption and decryption algorithms; modes include ECB/CBC/CTR modes; supports hardware key and software key usage.
-
hash
Supports SHA1/SHA256 algorithms, input data length is unlimited.
-
rsa
Supports RSA2048/RSA4096 encryption and decryption, signing and verification; supports the use of hardware keys and software keys.
4. Uboot¶
4.1. Code Framework¶

4.2. Cipher API Interface Description¶
4.2.1 AES Encryption and Decryption Interface¶
Function prototype:
@pConfig: the config of configurating aes hardware
void MDrv_AESDMA_Run(aesdmaConfig* pConfig);
Description of the aesdmaConfig structure fields:
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;
A demo code is placed under the path: cmd/sstar/aes.c
Take cbc encryption as an example:
- Configure encryption and decryption source data, target data address and length, aeskey type and length, aeskey address (required by cipherkey), whether to set IV and IV address (required in cbc/ctr mode), and encryption mode (ecb/cbc/ctr).
- Use the MDrv_AESDMA_Run interface to write the configuration to the register and trigger.
- The encrypted data can be read at the address config.u64DstAddr, and the length is 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");
}
}
Note: The length of the encrypted data in ECB mode must be aligned to 16 bytes.
otpkey as a key
If you need to use otpkey as a key, you need to burn OTP_AES128_KEY in advance.
AESKEY256 in OTP is actually composed of two AES128 keys in OTP. The combination and setting method are as follows.
Want to set:
KEY256_1:000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
Need to set:
key128_1:000102030405060708090A0B0C0D0E0F
key128_2:101112131415161718191A1B1C1D1E1F
The configuration methods and corresponding relationships are as follows:
| 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) |
4.2.2 Hash Operation Interface¶
@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)
A demo code is placed under the path: cmd/sstar/aes.c
Take sha256 as an example:
- Configure encryption and decryption source data, target data address and length, and encryption mode (sha1/sha256).
- Use the MDrv_SHA_Run interface to write the configuration to the register and trigger.
- The encrypted data can be read at the address pu16Output. The length of sha1 is 10-byte and the length of sha256 is 16-byte.
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");
}
}
Note: The u64SrcAddr of sha must be 16-byte aligned. Please use the __attribute__((aligned(16))) keyword to define the source data.
4.2.3 RSA Encryption and Decryption Interface¶
@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;
Note: RSA only loads the hw key once when it is powered on, which is used for signature verification in the rom code stage. After that, the hw key cannot be used.
A demo code is placed under the path: cmd/sstar/aes.c
Take rsa2048 as an example:
- Configure encryption and decryption source data, target data address and length, KeyN, KeyE, KeyLen, and type (public key, private key), etc.
- Use the MDrv_RSA_Run interface to write the configuration to the register and trigger.
- The encrypted data can be read at the address pu16Output. The length of rsa2048 is 256-byte and the length of rsa4096 is 512-byte.
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");
}
}
Note: There are two keys in an asymmetric encryption algorithm: public key and private key. They are a pair. If a public key is used to encrypt, only only the corresponding private key can be used to decrypt; if a private key is used to encrypt, only the corresponding public key can be used to decrypt.
5. Kernel¶
5.1 Config Setting¶

5.2 Code Framework¶

5.3 Accessing Interface in Userspace¶
Accessing the kernel through user layer ioctl:
- aes, sha: With the natively provided kernel module cryptodev, it provides a universal encryption API that enables applications to utilize the hardware-accelerated encryption functions. The crypto functionality can be accessed by opening the
/dev/cryptodevice file. Applications can perform encryption and decryption operations using common encryption algorithms (such as AES, DES, etc.) and modes (such as CBC, ECB, CTR, etc.).
RSA
- rsa: The kernel's native interface does not support the RSA algorithm, so RSA uses the Linux standard interface to register misc-type devices and generate
/dev/rsanodes. User Space can use the Hardware RSA algorithm through the nodes.
5.3.1 AES Encryption and Decryption Interface¶
A demo code is placed under the path: drivers/sstar/crypto/cryptodev/examples/aes.c
-
Open the node.
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; } -
Create a 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; }Parameter key description:
1) If using a software key, you can directly pass in the key data
2) If hardware keys are used, refer to the following rules
First, you need to burn the key to the OTP.
Since the kernel native interface does not select whether to use otpkey, the program will determine whether to use otpkey based on whether the key header is a special character sequence "SStarU*".
The configuration methods and corresponding relationships are shown in the following table:
key keylen otpkey "SStarU\x01" 16 key128_1 "SStarU\x02" 16 key128_2 "SStarU\x03" 16 key128_3 "SStarU\x04" 16 key128_4 "SStarU\x05" 16 key128_5 "SStarU\x06" 16 key128_6 "SStarU\x07" 16 key128_7 "SStarU\x08" 16 key128_8 "SStarU\x01" 32 key256_1(key128_1+key128_2) "SStarU\x02" 32 key256_2(key128_3+key128_4) "SStarU\x03" 32 key256_3(key128_5+key128_6) "SStarU\x04" 32 key256_4(key128_7+key128_8) For example, if using the OTP key 128_1, then the key is set:
unsigned char key[16] = {'S', 'S', 't', 'a', 'r', 'U', 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};Note: The key length needs to meet 16 bytes/32 bytes, the first 7 bytes of data need to be set according to the above format, and the data in the remaining positions are not required.
-
Perform encryption and decryption.
Structure description:
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; };Encryption and decryption example:
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; } -
Close the session.
void aes_ctx_deinit(struct cryptodev_ctx* ctx) { if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { perror("ioctl(CIOCFSESSION)"); } } -
Close the node.
/* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; }Note that currently hardware acceleration only supports aes (ecb/cbc/ctr). If other algorithms are required, software decryption will be used. The aes of hardware accelerated has the following alignment requirements for the input data size:
mode size alignment ecb 16 bytes cbc 1 bytes ctr 1 bytes There is no alignment requirement for the memory address of the input data, but it is recommended to align to 16 bytes when using aes, which can enable the zero copy function of cryptodev to reduce the memory copy between the user layer and the kernel layer.
Hardware accelerated AES supports key sizes of 128/256 bits.
5.3.2 Hash Operation Interface¶
A demo code is placed under the path: drivers/sstar/crypto/cryptodev/examples/sha.c
-
Open the node.
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; } -
Create a 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; } -
Perform calculations.
Structure description:
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; };Encryption and decryption example:
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; } -
Close the session.
void sha_ctx_deinit(struct cryptodev_ctx* ctx) { if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { perror("ioctl(CIOCFSESSION)"); } } -
Close the node.
/* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; }Note that currently hardware acceleration only supports sha256 algorithm. If other algorithms (such as sha1 or md5) are employed, software decryption will be used.
5.3.3 RSA Encryption and Decryption Interface¶
The RSA encryption and decryption interface supports RSA512/1024/2048/4096 (Due to the low security of RSA512/1024, it is recommended to use RSA2048/4096). A demo code is placed under the path: drivers/sstar/crypto/cryptodev/examples/cipher/cipher_rsa_sync.c
-
Open the node.
int fd = -1; /* Open the crypto device */ fd = open("/dev/rsa", O_RDWR, 0); if (fd < 0) { perror("open(/dev/rsa)"); return 1; } -
Perform calculations.
Structure description:
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 };Encryption and decryption example:
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 node.
/* Close the original descriptor */ if (close(fd)) { perror("close(fd)"); return 1; }Among them, RSA requires the size of input data (pu32RSA_sig), KeyN (pu32RSA_KeyN), and KeyE (pu32RSA_KeyE) as follows:
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