AES128 Hardware acceleration for TinyCrypt on the RA2 family.
Overview
- Note
- The TinyCrypt port module does not provide any interfaces to the user. Consult the documentation at https://github.com/intel/tinycrypt/blob/master/documentation/tinycrypt.rst for further information.
TinyCrypt is designed as a small footprint software crypto implementation to be used on resource constrained devices. The software only module is available in FSP on all RA devices. Hardware acceleration for AES-128 is provided only for the RA2 family. This release uses TinyCrypt v0.2.8.
Hardware Overview
Crypto Peripheral version | Devices |
AES Engine | RA2A1, RA2E1, RA2L1 |
Features
For features supported by the software-only version, refer to the TinyCrypt documentation.
The TinyCrypt port module provides hardware support for the following operations
- AES
- Keybits - 128, 192, 256
- ECB, CBC, CTR, CCM, GCM and CMAC modes -TRNG
Configuration
Build Time Configurations for TinyCrypt_Acceleration
The following build time configurations are defined in fsp_cfg/rm_tinycrypt_port_cfg.h:
Configuration | Options | Default | Description |
Parameter Checking |
-
Default (BSP)
-
Enabled
-
Disabled
| Default (BSP) | If selected code for parameter checking is included in the build. |
AES Configuration
To enable hardware acceleration for the AES128 operation, choose TinyCrypt (H/W Accelerated) from the stack options . This feature is only supported on the RA2 family.
Usage Notes
Hardware Initialization
Invoke RM_TINCYRYPT_PORT_Init () to initialize the hardware before using Tinycrypt if either hardware acceleration or the TRNG is to be used.
Random Number Generation
There are two Pseudo-random Number Generators (PRNG) provided in TinyCrypt
- CTR-PRNG which uses AES128 internally in its implementation. Enabling AES128 hardware acceleration will improve the performance of this module.
- HMAC-PRNG which uses SHA256 internally in its implementation.
Both these implementations will only be able to provide a random pseudo-random number sequence if they are seeded with truly random data. The TRNG module that is present in hardware and available in rm_tinycrypt_port must be used to seed these modules. When using CTR-PRNG or HMAC-PRNG, use the RM_TINCYRYPT_PORT_TRNG_Read() function to obtain random data from the TRNG hardware and use that to seed the PRNG modules before invoking the pseudo-random number generation. If purely random data is sufficient for the application, then RM_TINCYRYPT_PORT_TRNG_Read() can be used directly instead. The hardware TRNG implements the CTR_DRBG spec.
Default CSPRNG
The TinyCrypt ECC implementation requires a platform specific implementation of the default_CSPRNG() function. This function has been implemented using the hardware TRNG in the port to support software ECC usage. When using TinyCrypt in S/W mode, it is necessary to implement default_CSPRNG() if using ECC signature generation (ECDSA) or key derivation (ECDH).
AES-128 Usage
The AES ECB mode implementation is provided in aes_encrypt.decrypt.c. All the other modes of AES operation including CBC, CCN, CMAC and CTR use the ECB mode for the block operation. On the RA2, the ECB mode has been hardware accelerated which improves performance of the other modes as well. Additionally the CBC and CTR modes are also accelerated.
To use the different AES modes, first initialize the hardware (on the RA2) and then use the functions defined in the header file of each AES mode. Note that TinyCrypt does not provide any type of padding or buffering so the data provided to these modes should be multiples of AES block size.
Usage with RA2A2
On the RA2A2, the TinyCrypt API has been expanded to support GCM mode operation. Key lengths of 128, 192 and 256 are supported. GCM mode operation is not supported on other MCUs in hardware or software in the TinyCrypt API.
Memory Usage
TinyCrypt does not use dynamic allocation so there is no heap requirement.
Limitations
Usage with RA4 and RA6 devices
TinyCrypt (S/W Only) can be used on RA4 and RA6 devices. However, since ECC signature generation (ECDSA) and key derivation (ECDH) requires a random number source, that operation is currently not supported on these devices when using TinyCrypt (S/W Only). In order to support those operations the function default_CSPRNG() must be implemented in the user code.
TinyCrypt
- No padding is supported; the user is expected to provide adequately padded data depending on the algorithm used.
- AES Key generation is not supported.
- Key encoding/decoding is not supported.
Using TinyCrypt with TrustZone
Unlike FSP drivers, TinyCrypt cannot be configured as Non-secure callable in the RA Configurator for a secure project. The reason for this is that in order to achieve the security objective of controlling access to protected keys, both the crypto code as well as the keys must be placed in the secure region. Since the tinyCrypt API requires access to the keys directly during initialization and later via a key handle, allowing non-secure code to use the API by making it Non-secure callable will require the keys to be stored in non-secure memory.
This limitation is identical to that for PSA Crypto. Refer to the documentation of that module on how to create a crypto Non-Secure Callable layer to be used in such situations.
Examples
AES-CBC Example
This is an example on using TinyCrypt to encrypt and decrypt data using an AES-128 key in CBC mode.
#define TC_INPUT_PLAINTEXT_SIZE 64U
#define TF_AES_IV_SIZE TC_AES_BLOCK_SIZE
#define TC_OUTPUT_CIPHERTEXT_SIZE (TC_INPUT_PLAINTEXT_SIZE + TF_AES_IV_SIZE)
const uint8_t cbc_key[TC_AES_KEY_SIZE] =
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
uint8_t cbc_iv[TC_AES_BLOCK_SIZE] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
const uint8_t cbc_plaintext[TC_INPUT_PLAINTEXT_SIZE] =
{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
};
uint8_t cbc_expected_ciphertext[TC_OUTPUT_CIPHERTEXT_SIZE] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7
};
void tinycrypt_aes128cbc_example (void)
{
struct tc_aes_key_sched_struct aes_keyschedule;
uint8_t cbc_encrypted[TC_OUTPUT_CIPHERTEXT_SIZE] = {0U};
uint8_t cbc_decrypted[TC_OUTPUT_CIPHERTEXT_SIZE] = {0U};
if (TC_CRYPTO_SUCCESS != tc_aes128_set_encrypt_key(&aes_keyschedule, cbc_key))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS !=
tc_cbc_mode_encrypt(cbc_encrypted, sizeof(cbc_plaintext) + TC_AES_BLOCK_SIZE, cbc_plaintext,
sizeof(cbc_plaintext), cbc_iv, &aes_keyschedule))
{
debugger_break();
}
else if (0 != memcmp(&cbc_encrypted[0], &cbc_expected_ciphertext[0], sizeof(cbc_encrypted)))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS !=
tc_cbc_mode_decrypt(cbc_decrypted, sizeof(cbc_encrypted), &cbc_encrypted[TC_AES_BLOCK_SIZE],
sizeof(cbc_encrypted), cbc_encrypted, &aes_keyschedule))
{
debugger_break();
}
else if (0 != memcmp(&cbc_plaintext[0], &cbc_decrypted[0], sizeof(cbc_plaintext)))
{
debugger_break();
}
else
{
while (1)
{
;
}
}
}
AES-CTR Example
This is an example on using TinyCrypt to encrypt and decrypt data using an AES-128 key in CTR mode.
#define TC_CTR_INPUT_PLAINTEXT_SIZE 64U
#define TF_AES_IV_SIZE TC_AES_BLOCK_SIZE
#define TC_CTR_OUTPUT_CIPHERTEXT_SIZE (TC_CTR_INPUT_PLAINTEXT_SIZE + TF_AES_IV_SIZE)
const uint8_t ctr_key[TC_AES_KEY_SIZE] =
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
uint8_t ctr_iv[TC_AES_KEY_SIZE] =
{
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
const uint8_t ctr_plaintext[64] =
{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
};
const uint8_t ctr_expected_ciphertext[TC_CTR_OUTPUT_CIPHERTEXT_SIZE] =
{
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce,
0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff,
0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab,
0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee
};
void tinycrypt_aes128ctr_example (void)
{
struct tc_aes_key_sched_struct aes_keyschedule;
uint8_t ctr_encrypted[TC_CTR_OUTPUT_CIPHERTEXT_SIZE] = {0U};
uint8_t ctr_decrypted[TC_CTR_OUTPUT_CIPHERTEXT_SIZE] = {0U};
if (0 != memcpy(ctr_encrypted, ctr_iv, sizeof(ctr_iv)))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != tc_aes128_set_encrypt_key(&aes_keyschedule, ctr_key))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS !=
tc_ctr_mode(&ctr_encrypted[TC_AES_BLOCK_SIZE], sizeof(ctr_plaintext), ctr_plaintext, sizeof(ctr_plaintext),
ctr_iv, &aes_keyschedule))
{
debugger_break();
}
else if (0 != memcmp(&ctr_encrypted[0], &ctr_expected_ciphertext[0], sizeof(ctr_encrypted)))
{
debugger_break();
}
else if (0 != memcpy(ctr_iv, ctr_encrypted, sizeof(ctr_iv)))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS !=
tc_ctr_mode(ctr_decrypted, sizeof(ctr_decrypted), &ctr_encrypted[TC_AES_BLOCK_SIZE], sizeof(ctr_decrypted),
ctr_iv, &aes_keyschedule))
{
debugger_break();
}
else if (0 != memcmp(&ctr_plaintext[0], &ctr_decrypted[0], sizeof(ctr_plaintext)))
{
debugger_break();
}
else
{
while (1)
{
;
}
}
}
CTR-PRNG Example
This is an example on using the CTR_PRNG module in TinyCrypt to obtain random data.
#define TC_ENTROPY_SIZE 64U
#define TC_CTRPRNG_OUTPUT_SIZE 32U
void tinycrypt_ctr_prng_example (void)
{
TCCtrPrng_t cprng_ctx;
uint8_t seed[TC_ENTROPY_SIZE];
uint8_t ctr_prng_output_1[TC_CTRPRNG_OUTPUT_SIZE] = {0};
uint8_t ctr_prng_output_2[TC_CTRPRNG_OUTPUT_SIZE] = {0};
{
debugger_break();
}
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != tc_ctr_prng_init(&cprng_ctx, seed, sizeof(seed), 0, 0))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS !=
tc_ctr_prng_generate(&cprng_ctx, 0, 0, ctr_prng_output_1, sizeof(ctr_prng_output_1)))
{
debugger_break();
}
else if (0 == memcmp(&ctr_prng_output_1[0], &ctr_prng_output_2[0], sizeof(ctr_prng_output_1)))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS !=
tc_ctr_prng_generate(&cprng_ctx, 0, 0, ctr_prng_output_2, sizeof(ctr_prng_output_2)))
{
debugger_break();
}
else if (0 == memcmp(&ctr_prng_output_1[0], &ctr_prng_output_2[0], sizeof(ctr_prng_output_1)))
{
debugger_break();
}
else
{
while (1)
{
;
}
}
}
AES-CMAC Example
This is an example on using AES Circuit (Hardware support) to encrypt data using an AES-128 key in CMAC mode. This is also an example on use tc_cmac_setup and tc_cmac_setup_extended.
#define MLEN4 64
#define BUF_LEN 16
const uint8_t cmac_key_128[TC_AES_KEY_SIZE] =
{
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
};
const uint8_t msg[MLEN4] =
{
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10,
};
const uint8_t tag[BUF_LEN] =
{
0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe,
};
void tinycrypt_aes128cmac_example (void)
{
struct tc_cmac_struct state;
struct tc_aes_key_sched_struct sched;
uint8_t Tag[BUF_LEN];
if (TC_CRYPTO_SUCCESS != tc_cmac_setup(&state, cmac_key_128, &sched))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != tc_cmac_init(&state))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != tc_cmac_update(&state, msg, sizeof(msg)))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != tc_cmac_final(Tag, &state))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != memcmp(Tag, tag, BUF_LEN))
{
debugger_break();
}
else
{
while (1)
{
;
}
}
}
void tinycrypt_aes128cmac_example_setup_extended (void)
{
struct tc_cmac_struct state;
struct tc_aes_key_sched_struct sched;
uint8_t Tag[BUF_LEN];
if (TC_CRYPTO_SUCCESS != tc_cmac_setup_extended(&state, cmac_key_128, &sched, sizeof(cmac_key_128)))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != tc_cmac_init(&state))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != tc_cmac_update(&state, msg, sizeof(msg)))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != tc_cmac_final(Tag, &state))
{
debugger_break();
}
else if (TC_CRYPTO_SUCCESS != memcmp(Tag, tag, BUF_LEN))
{
debugger_break();
}
else
{
while (1)
{
;
}
}
}
◆ RM_TINCYRYPT_PORT_Init()
◆ RM_TINCYRYPT_PORT_TRNG_Read()
fsp_err_t RM_TINCYRYPT_PORT_TRNG_Read |
( |
uint8_t *const |
p_rngbuf, |
|
|
uint32_t |
num_req_bytes |
|
) |
| |
Reads requested length of random data from the TRNG. Generate num_req_bytes
of random bytes and store them in p_rngbuf
buffer.
- Return values
-
FSP_SUCCESS | Random number generation successful |
FSP_ERR_ASSERTION | NULL input parameter(s). |
FSP_ERR_CRYPTO_UNKNOWN | An unknown error occurred. |
- Returns
- See Common Error Codes or functions called by this function for other possible return codes.
◆ default_CSPRNG()
int default_CSPRNG |
( |
uint8_t * |
dest, |
|
|
unsigned int |
size |
|
) |
| |
Implements the Cryptographically Secure Pseudo-Random Number Generator function required byt TinyCrypt.
- Return values
-
TC_CRYPTO_SUCCESS | Random number generation successful |
TC_CRYPTO_FAIL | Random number generation failed. |
- Returns
- See Common Error Codes or functions called by this function for other possible return codes. This function calls:
- RM_TINCYRYPT_PORT_TRNG_Read