CIPHER USER GUIDE
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 04/18/2024 | |
| 1.1 | 04/11/2025 |
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.
-
sm⅔/4
Support SM⅔/4 algorithm
4. UBOOT¶
4.1 Code Framework and Config¶
4.1.1 Code Framework¶

4.1.2 Uboot Config¶
Open the following configuration under uboot:
[*] SigmaStar drivers --->
[*] SigmaStar AESDMA
4.2. Cipher API Interface Analysis¶
4.2.1 AES Encryption and Decryption Interface¶
Function prototype:
@pConfig: the config of configurating aes hardware void MDrv_AESDMA_Run(aesdmaConfig* pConfig);
AESDMAConfig structure field explanation:
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 path: cmd/sstar/aes.c.
Take cbc encryption as an example:
- Configure the encryption and decryption data source data, target data address and length, aeskey type and length, aeskey address (cipherkey need), whether to set iv and iv address (cbc/ctr mode need), encryption mode (ecb/cbc/ctr).
- Use the MDrv_AESDMA_Run interface to write the configuration to the register and trigger it.
- 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. For the specific generation and burning methods of otpkey, please refer to Chapter 2 of the Secureboot User Manual: Security_Boot_zh.md, for inquiries about the Security_Boot_zh.md document, please consult the FAE window.
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 shown in the following table:
| 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_KEY1 | 32 | key256_1(key128_1+key128_2) |
| E_AESDMA_KEY_OTP_EFUSE_KEY2 | 32 | key256_2(key128_3+key128_4) |
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)
Demo path: cmd/sstar/aes.c.
Take sha256 as an example:
- Configure the encryption and decryption data source data, target data address and length, encryption mode (sha1/sha256).
- Use the MDrv_SHA_Run interface to write the configuration to the register and trigger it.
- The encrypted data can be read at the address pu16Output. The length of sha1 is 10 bytes and the length of sha256 is 16 bytes.
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: sha's u64SrcAddr 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 hw key once when powered on, which is used for signature verification in the rom code stage. After that, hw key cannot be used.
Demo path: cmd/sstar/aes.c.
Take rsa2048 as an example:
- Configure the encryption and decryption data source data, target data address and length, KeyN, KeyE, KeyLen, type (public key, private key), etc.
- Use the MDrv_RSA_Run interface to write the configuration to the register and trigger it.
- The encrypted data can be read at the address pu16Output. The length of rsa2048 is 256 bytes, and the length of rsa4096 is 512 bytes.
char __attribute__((aligned(16))) 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 __attribute__((aligned(16))) 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 __attribute__((aligned(16))) 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 __attribute__((aligned(16))) 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 __attribute__((aligned(16))) rsa_encrypt_out[256]; U8 __attribute__((aligned(16))) 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: In an asymmetric encryption algorithm, there are two keys: a public key and a private key. They are a pair. If you encrypt with a public key, you can only decrypt with the corresponding private key; if you encrypt with a private key, you can only decrypt with the corresponding public key.
4.2.4 SM⅔/4 Encryption and Decryption Interface¶
uboot currently does not support sm⅔/4 encryption and decryption.
5. KERNEL¶
5.1. Code Framework and Kernel Config¶
5.1.1 Code Framework¶

Figure 2-1: Cipher_02
5.1.2 Kernel Config¶
Open the following configuration under kernel to use aesdma normally.
Device Drivers --->
[*] Sstar SoC platform drivers --->
<*> SigmaStar Crypto driver
[*] HW_RANDOM Random Number Generator support
<*> Support cryptodev
5.2. Access Interface in Userspace¶
Access the kernel through user-level ioctl.
- aes, sha, sm3, sm4: With the help of the module cryptodev, it provides a general encryption API that enables applications to take advantage of hardware-accelerated encryption functions. Encryption functions can be accessed by opening the
/dev/cryptodevice file. Applications can use common encryption algorithms (such as AES, DES, etc.) and modes (such as CBC, ECB, CTR, etc.) to perform encryption and decryption operations.
rsa, sm2
- rsa, sm2: RSA/SM2 algorithms are not supported in the kernel native interface, so RSA/SM2 uses the Linux standard interface to register misc class devices, generating
/dev/rsaand/dev/sm2nodes, and User Space can use Hardware RSA/SM2 algorithms through nodes.
5.2.1 aes/sm4 Encryption and Decryption Interface¶
Demo path: drivers/sstar/cryptodev/examples/aes.c drivers/sstar/cryptodev/examples/sm4.c.
use otpkey demo path:drivers/sstar/cryptodev/examples/aes-sstar-unique.c.
-
Open notes
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 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; // use CRYPTO_SM4_CBC for SM4 CBC mode 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, the generation method and burning method of otpkey please refer to Section 4.2.1.
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\x01" 32 key256_1(key128_1+key128_2) "SStarU\x02" 32 key256_2(key128_3+key128_4) 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 examples
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 session
void aes_ctx_deinit(struct cryptodev_ctx* ctx) { if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { perror("ioctl(CIOCFSESSION)"); } } -
Close nodes
/* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; }Note that currently hardware acceleration only supports aes (ecb/cbc/ctr) and sm4 (ecb/cbc/ctr). If other algorithms are required, software decryption will be used. The aes/sm4 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, and hardware accelerated SM4 supports key sizes of 128 bits.
5.2.2 Hash Operation Interface¶
Demo path: drivers/sstar/cryptodev/examples/sha.c drivers/sstar/cryptodev/examples/sm3.c
-
Open nodes
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 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; // use CRYPTO_SM3 for sm3 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 operation
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 examples
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 session
void sha_ctx_deinit(struct cryptodev_ctx* ctx) { if (ioctl(ctx->cfd, CIOCFSESSION, &ctx->sess.ses)) { perror("ioctl(CIOCFSESSION)"); } } -
Close nodes
/* Close the original descriptor */ if (close(cfd)) { perror("close(cfd)"); return 1; }Note that currently hardware acceleration only supports sha256/sm3 algorithms. If other algorithms (such as sha1, md5) are used, the software algorithm will be called.
5.2.3 RSA Encryption and Decryption Interface¶
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).
demo path: drivers/sstar/cryptodev/examples/cipher/cipher_rsa_sync.c.
-
Open nodes
int fd = -1; /* Open the crypto device */ fd = open("/dev/rsa", O_RDWR, 0); if (fd < 0) { perror("open(/dev/rsa)"); return 1; } -
Perform operation
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 examples
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 nodes
/* Close the original descriptor */ if (close(fd)) { perror("close(fd)"); return 1; }Among them, RSA has the following requirements for the size of input data (pu32RSA_Sig), KeyN (pu32RSA_KeyN), and 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
5.2.4 SM2 Encryption and Decryption Interface¶
SM2 encryption and decryption demo path: drivers/sstar/cryptodev/examples/sm2.c.
-
Open nodes
int fd = -1; /* Open the crypto device */ fd = open("/dev/sm2", O_RDWR, 0); if (fd < 0) { perror("open(/dev/sm2)"); return 1; } -
Perform operation
Structure description
typedef struct DRV_Sm2Config_s { unsigned char *pu8PrivKey; // private key unsigned char *pu8PubKeyX; // public key in X coordinate unsigned char *pu8PubKeyY; // public key in Y coordinate unsigned int u32KeyLen; // key length (unit: byte) unsigned char bDecrypt; // decryption flag (set 1 for decryption, 0 for encryption) unsigned char *pu8Input; // input data unsigned int u32InputLen; // input data length (unit: byte) unsigned char *pu8Output; // output data } DRV_Sm2Config_t;Encryption and decryption examples
int UtSm2Encrypt(int s32Fd, void* pInput, void* pOutput, unsigned int u32Len) { DRV_Sm2Config_t stCfg; stCfg.bDecrypt = 0; stCfg.pu8PubKeyX = g_u8PubKeyX; stCfg.pu8PubKeyY = g_u8PubKeyY; stCfg.u32KeyLen = UT_SM2_PRECISION * 4; stCfg.pu8Input = pInput; stCfg.u32InputLen = u32Len; stCfg.pu8Output = pOutput; if (ioctl(s32Fd, SM2_IOCTL_CRYPT, &stCfg)) { fprintf(stderr, "ioctl(SM2_IOCTL_CRYPT) failed\n"); return -1; } return 0; } -
Close nodes
/* Close the original descriptor */ if (close(fd)) { perror("close(fd)"); return 1; }Among them, SM2 encryption and decryption requires a key length of 32 bytes and supports a maximum input data length of 1MB.