RA Flexible Software Package Documentation  Release v5.2.0

 
TinyCrypt H/W Acceleration (rm_tinycrypt_port)

Functions

fsp_err_t RM_TINCYRYPT_PORT_Init ()
 
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. More...
 
int default_CSPRNG (uint8_t *dest, unsigned int size)
 Implements the Cryptographically Secure Pseudo-Random Number Generator function required byt TinyCrypt. More...
 

Detailed Description

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

Configuration

Build Time Configurations for TinyCrypt_Acceleration

The following build time configurations are defined in fsp_cfg/rm_tinycrypt_port_cfg.h:

ConfigurationOptionsDefaultDescription
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

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

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)
/*
* NIST test vectors from SP 800-38a:
*
* Block #1
* Plaintext 6bc1bee22e409f96e93d7e117393172a
* Input Block 6bc0bce12a459991e134741a7f9e1925
* Output Block 7649abac8119b246cee98e9b12e9197d
* Ciphertext 7649abac8119b246cee98e9b12e9197d
* Block #2
* Plaintext ae2d8a571e03ac9c9eb76fac45af8e51
* Input Block d86421fb9f1a1eda505ee1375746972c
* Output Block 5086cb9b507219ee95db113a917678b2
* Ciphertext 5086cb9b507219ee95db113a917678b2
* Block #3
* Plaintext 30c81c46a35ce411e5fbc1191a0a52ef
* Input Block 604ed7ddf32efdff7020d0238b7c2a5d
* Output Block 73bed6b8e3c1743b7116e69e22229516
* Ciphertext 73bed6b8e3c1743b7116e69e22229516
* Block #4
* Plaintext f69f2445df4f9b17ad2b417be66c3710
* Input Block 8521f2fd3c8eef2cdc3da7e5c44ea206
* Output Block 3ff1caa1681fac09120eca307586e1a7
* Ciphertext 3ff1caa1681fac09120eca307586e1a7
*/
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, // NOLINT(readability-magic-numbers)
0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, // NOLINT(readability-magic-numbers)
0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, // NOLINT(readability-magic-numbers)
0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, // NOLINT(readability-magic-numbers)
0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 // NOLINT(readability-magic-numbers)
};
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
{
/* Operation successful. */
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)
/*
* NIST SP 800-38a CTR Test for encryption and decryption.
*/
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 // NOLINT(readability-magic-numbers)
};
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
{
/* Operation successful. */
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};
/* Setup the platform; initialize the crypto engine. */
{
debugger_break();
}
/* Read random data from the TRNG to use as seed for the CTR_PRNG. */
else if (FSP_SUCCESS != RM_TINCYRYPT_PORT_TRNG_Read(seed, sizeof(seed)))
{
debugger_break();
}
/* Initialize and seed the CTR_PRNG with the random data from the TRNG. */
else if (TC_CRYPTO_SUCCESS != tc_ctr_prng_init(&cprng_ctx, seed, sizeof(seed), 0, 0))
{
debugger_break();
}
/* Read random data from the CTR_PRNG. */
else if (TC_CRYPTO_SUCCESS !=
tc_ctr_prng_generate(&cprng_ctx, 0, 0, ctr_prng_output_1, sizeof(ctr_prng_output_1)))
{
debugger_break();
}
/* Check that the generated value is not 0. */
else if (0 == memcmp(&ctr_prng_output_1[0], &ctr_prng_output_2[0], sizeof(ctr_prng_output_1)))
{
debugger_break();
}
/* Read random data again from the TRNG. */
else if (TC_CRYPTO_SUCCESS !=
tc_ctr_prng_generate(&cprng_ctx, 0, 0, ctr_prng_output_2, sizeof(ctr_prng_output_2)))
{
debugger_break();
}
/* Check that the generated value is different than the previous call. */
else if (0 == memcmp(&ctr_prng_output_1[0], &ctr_prng_output_2[0], sizeof(ctr_prng_output_1)))
{
debugger_break();
}
else
{
/* Operation successful. */
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
{
/* Operation successful. */
while (1)
{
;
}
}
}
/* Below is a example of using tc_cmac_setup_extended instead of tc_cmac_setup*/
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
{
/* Operation successful. */
while (1)
{
;
}
}
}

Function Documentation

◆ RM_TINCYRYPT_PORT_Init()

fsp_err_t RM_TINCYRYPT_PORT_Init ( )

Initialize the SCE.

◆ 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_SUCCESSRandom number generation successful
FSP_ERR_ASSERTIONNULL input parameter(s).
FSP_ERR_CRYPTO_UNKNOWNAn 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_SUCCESSRandom number generation successful
TC_CRYPTO_FAILRandom 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