RA Flexible Software Package Documentation  Release v5.2.0

 
Azure RTOS NetX Crypto HW Acceleration (rm_netx_secure_crypto)

Detailed Description

Hardware acceleration for the Netx Crypto implementation of the Microsoft Azure RTOS NetX Crypto API.

Overview

Please refer to the NetXDuo - NetX Crypto documentation for further details.

HW Overview

Crypto Peripheral version Devices
SCE9 RA6M4, RA4M3, RA4M2, RA6M5
SCE7 RA6M3, RA6M2, RA6M1, RA6T1
SCE5 RA4W1, RA4M1
SCE5B RA6T2
AES Engine RA2A1, RA2E1, RA2E2, RA2L1
RSIP7 RA8M1
Note
NetX Crypto hardware acceleration is unsupported on 'SCE5' and 'AES Engine' crypto peripherals listed above.

Features

This module provides SCE9 hardware support for the following NetX Crypto operations

This module provides SCE7 hardware support for the following NetX Crypto operations

Configuration

Build Time Configurations for rm_netx_secure_crypto_sw_port

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

ConfigurationOptionsDefaultDescription
Standalone Usage
  • Use Standalone Crypto Only
  • Use with TLS
Use Standalone Crypto Only Defines NX_CRYPTO_STANDALONE_ENABLE.
Maximum RSA Modulus size (bits)
  • 1024
  • 2048
  • 3072
  • 4096
4096

Build Time Configurations for rm_netx_secure_crypto

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

ConfigurationOptionsDefaultDescription
Hardware Acceleration
Hardware Acceleration > Hash
SHA256/224MCU Specific OptionsEnables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_SHA256_ALT.
Hardware Acceleration > Cipher
AESMCU Specific OptionsEnables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_AES_ALT
Hardware Acceleration > Public Key Cryptography (PKC)
Hardware Acceleration > Public Key Cryptography (PKC) > ECC
ECCMCU Specific OptionsEnables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_ECC_ALT
ECDSA Scratch Buffer Size (Bytes)Value must be an integer3016 Sets value of NX_CRYPTO_ECDSA_SCRATCH_BUFFER_SIZE
ECDH Scratch Buffer Size (Bytes)Value must be an integer2464 Sets value of NX_CRYPTO_ECDH_SCRATCH_BUFFER_SIZE
Hardware Acceleration > Public Key Cryptography (PKC) > RSA
RSAMCU Specific OptionsEnables/Disables RSA HW support
RSA 2048 (HW)MCU Specific OptionsEnables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_2048_ALT to allow HW support
RSA 3072 Verify/Encryption (HW)MCU Specific OptionsEnables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_3072_ALT to allow HW support
RSA 4096 Verify/Encryption (HW)MCU Specific OptionsEnables RSA NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_4096_ALT to allow HW support
RSA Scratch Buffer Size (Bytes)MCU Specific OptionsSets value of NX_CRYPTO_RSA_SCRATCH_BUFFER_SIZE
TRNG
  • Enabled
  • Disabled
Enabled Enables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_TRNG_ALT.
Standalone Usage
  • Use Standalone Crypto Only
  • Use with TLS
Use Standalone Crypto Only Defines NX_CRYPTO_STANDALONE_ENABLE.

Random Number Generator Configuration

To enable hardware acceleration for the TRNG, the macro NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_TRNG_ALT must be defined in the configuration file. By default TRNG is enabled which can be disabled using the RA Configuration editor.

Once enabled 'rand' function will be mapped to HW TRNG; the 'srand' function is not supported, any calls to this function will have no effect. Functionality to re-seed the HW TRNG is not supported by the existing implementation.

If disabled, both 'rand' and 'srand' will be mapped to the C Standard Library. This would require setting up the heap as 'rand' implementation calls 'malloc'.

SHA256 Configuration

To enable hardware acceleration for the SHA256/224 calculation, the macro NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_SHA256_ALT must be defined in the configuration file. By default SHA256 is enabled which can be disabled using the RA Configuration editor.

AES Configuration

To enable hardware acceleration for the AES128/192/256 operation, the macro NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_AES_ALT must be defined in the configuration file. By default AES is enabled which can be disabled using the RA Configuration editor.

ECC Configuration

To enable hardware acceleration for the ECDSA and ECDH for curves SECP384R1 and SECP256R1, the macro NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_ECC_ALT must be defined in the configuration file. By default ECC operations are enabled which can be disabled using the RA Configuration editor.

RSA Configuration

To enable hardware acceleration for the RSA Encrypt/Decrypt (or Sign/Verify) operation(s), the macro(s) below must be must be defined in the configuration file:

Configuration Macro Feature / Operation
NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_2048_ALT Signature Generation / Signature Verification (Encryption / Decryption)
NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_3072_ALT Signature Verification (Encryption Only)
NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_4096_ALT Signature Verification (Encryption Only)

By default RSA 2048 is enabled which can be disabled using the RA Configuration editor.

RSA software implementation is completely disabled when any of the above macros are enabled.

Usage Notes

Memory Alignment

Use 32bit aligned buffer pointers as arguments to APIs for best performance.

Hardware Initialization

_nx_crypto_initialize() must be invoked before using the NetX Crypto APIs to ensure that the SCE peripheral is initialized.

Memory Usage

Sufficient memory must be allocated to be used as 'crypto_metadata' for the chosen crypto operation(s). Refer Azure RTOS NetX Crypto API description for recommended 'crypto_metadata_size' based on selected crypto operations. Sufficient amount of memory must be allocated for the thread stack to support low level crypto operations when using this module in the standalone mode or through NetX Secure (TLS). A minimum stack of 0x1000 is required to use ECC and RSA. This is either the main stack in a bare metal application or the specific thread stack for an RTOS based application.

AES Usage

GCM mode

The first byte of the IV must indicate the length of the subsequent IV. For example if the IV is {0x00, 0x00, 0x00}, then the IV pointer passed to the _nx_crypto_method_aes_operation must store the IV as {0x03, 0x00, 0x00, 0x00}. Refer to the example code for actual usage.

CTR mode

For CTR mode the IV pointer must be as defined in Using Advanced Encryption Standard (AES) Counter Mode With IPsec Encapsulating Security Payload (ESP) under 'Figure 2. Counter Block Format'. The IV must be 8 bytes in length. The Nonce field in the reference above must be 4 bytes and should be passed to _nx_crypto_method_aes_operation through the key pointer stored after the actual AES key. For Example, if the AES 128-bit Plain Key is {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} and the Nonce is {0x01, 0x07, 0xBD, 0xFD}, the key passed to the _nx_crypto_method_aes_operation during Encryption/Decryption should be set as {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0xBD, 0xFD}. This format would also be valid for Wrapped keys where the Nonce is appended at the end of the actual Wrapped key. Refer to the example code for actual usage.

The 'Block Counter' field in the above reference is fixed to {0x00, 0x00, 0x00, 0x01} at the beginning and increments internally after every subsequent AES block is processed. Test vectors that have the initial Block Counter not set to {0x00, 0x00, 0x00, 0x01} cannnot be used in this implementation.

ECC Usage

ECC operations include ECDH and ECDSA. As a part of ECDSA operation the input message can be hashed before signing or verification, or the message digest can be provided directly. ECC Scratch buffer size can be optionally reduced as supported ECC computations are now done by the HW. This is controlled by NX_CRYPTO_ECDSA_SCRATCH_BUFFER_SIZE and NX_CRYPTO_ECDH_SCRATCH_BUFFER_SIZE macros for ECDSA and ECDH respectively.

Operation Key Format
ECDSA Signature Plain private key; Wrapped private key
ECDSA Signature-Verify Uncompressed public key
Key Generation using ECDSA operation API Wrapped private key; Uncompressed public key
ECDH private key import Plain private key; Wrapped private key (Allows for Uncompressed and Formatted public key)
ECDH public key export Uncompressed public key
ECDH setup Uncompressed public key
ECDH shared secret calculate Uncompressed public key
Key Generation using ECDH operation API Wrapped private key; Uncompressed public key

Note:

RSA Usage

Wrapped Key Usage

To use the NetX Crypto stack with wrapped private keys (for signature generation/decryption), a dummy pointer (non-NULL) should be passed to the 'key' parameter during _nx_crypto_method_rsa_init API call. However, the 'key_size_in_bits' parameter should be equal to the intended RSA modulus length in bits. The actual wrapped key must be passed as the 'key' parameter to the _nx_crypto_method_rsa_operation API call with its length in bits passed through the 'key_size_in_bits' parameter.

For PKCS1V15 operation 'key' and 'key_size_in_bits' parameters of _nx_crypto_method_pkcs1_v1_5_init are unused. These can be passed as NULL and 0 respectively. The actual wrapped key must be passed as the 'key' parameter to the _nx_crypto_method_pkcs1_v1_5_operation API call and the intended modulus length in bits must be passed through the 'key_size_in_bits' parameter.

Software Implementation

The plaintext data passed in to the RSA encryption API must be 4-byte aligned. If it is not aligned then when the resultant encrypted data is decrypted using the decryption API, the unaligned data will be endian-swapped. For instance, if {0x01, 0x02,0x03, 0x04, 0x05} is passed as input data for encryption, when decrypted, the result will be {0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x05}. Note that this alignment of input data need not be taken care while using Hardware accelerated RSA.

Limitations

Examples

Initialization Example

This example shows how to initialize the HW crypto engine. This step must be performed before any crypto algorithm is used.

/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);

Hash Example

This is an example on calculating the SHA256 hash using the NetX Crypto API.

extern NX_CRYPTO_METHOD crypto_method_sha256;
const uint8_t NIST_SHA256ShortMsgLen200[] =
{
0x2e, 0x7e, 0xa8, 0x4d, 0xa4, 0xbc, 0x4d, 0x7c, 0xfb, 0x46, 0x3e, 0x3f, 0x2c, 0x86, 0x47, 0x05,
0x7a, 0xff, 0xf3, 0xfb, 0xec, 0xec, 0xa1, 0xd2, 00
};
const uint8_t NIST_SHA256ShortMsgLen200_expected[] =
{
0x76, 0xe3, 0xac, 0xbc, 0x71, 0x88, 0x36, 0xf2, 0xdf, 0x8a, 0xd2, 0xd0, 0xd2, 0xd7, 0x6f, 0x0c,
0xfa, 0x5f, 0xea, 0x09, 0x86, 0xbe, 0x91, 0x8f, 0x10, 0xbc, 0xee, 0x73, 0x0d, 0xf4, 0x41, 0xb9
};
void netx_secure_crypto_sha256_example (void)
{
size_t actual_hash_len = RM_NETX_SECURE_CRYPTO_EXAMPLE_SHA256_HASH_SIZE_BYTES;
uint8_t actual_hash[RM_NETX_SECURE_CRYPTO_EXAMPLE_SHA256_HASH_SIZE_BYTES];
uint8_t metadata[sizeof(NX_CRYPTO_SHA256)];
uint32_t metadata_size = sizeof(NX_CRYPTO_SHA256);
void * handler = NX_CRYPTO_NULL;
uint32_t err = NX_CRYPTO_SUCCESS;
/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
/* Nx Crypto SHA256 init */
err = _nx_crypto_method_sha256_init(&crypto_method_sha256, NX_CRYPTO_NULL, 0, &handler, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
/* Nx Crypto SHA256 operation - NX_CRYPTO_HASH_INITIALIZE */
err = _nx_crypto_method_sha256_operation(NX_CRYPTO_HASH_INITIALIZE,
handler,
&crypto_method_sha256,
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Nx Crypto SHA256 operation - NX_CRYPTO_HASH_UPDATE,
* call this multiple times if needed to hash multiple data batches */
err =
_nx_crypto_method_sha256_operation(NX_CRYPTO_HASH_UPDATE,
handler,
&crypto_method_sha256,
NX_CRYPTO_NULL,
0,
(uint8_t *) NIST_SHA256ShortMsgLen200,
sizeof(NIST_SHA256ShortMsgLen200),
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Nx Crypto SHA256 operation - NX_CRYPTO_HASH_CALCULATE */
err = _nx_crypto_method_sha256_operation(NX_CRYPTO_HASH_CALCULATE,
handler,
&crypto_method_sha256,
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
(uint8_t *) actual_hash,
actual_hash_len,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Ensure generated SHA256 hash matches the expected digest */
err = (uint32_t) memcmp(&actual_hash[0], &NIST_SHA256ShortMsgLen200_expected[0], actual_hash_len);
assert(0 == err);
}

AES Example

This is an example on using the NetX Crypto API to encrypt and decrypt multi-block data.

AES CBC Example

extern NX_CRYPTO_METHOD crypto_method_aes_cbc_256;
/* fe8901fecd3ccd2ec5fdc7c7a0b50519c245b42d611a5ef9e90268d59f3edf33 */
const uint8_t NIST_AES256_CBC_key[] =
{
0xfe, 0x89, 0x01, 0xfe, 0xcd, 0x3c, 0xcd, 0x2e, 0xc5, 0xfd, 0xc7, 0xc7, 0xa0, 0xb5, 0x05, 0x19,
0xc2, 0x45, 0xb4, 0x2d, 0x61, 0x1a, 0x5e, 0xf9, 0xe9, 0x02, 0x68, 0xd5, 0x9f, 0x3e, 0xdf, 0x33
};
/* 851e8764776e6796aab722dbb644ace8 */
const uint8_t NIST_AES256_CBC_iv[] =
{
0xbd, 0x41, 0x6c, 0xb3, 0xb9, 0x89, 0x22, 0x28, 0xd8, 0xf1, 0xdf, 0x57, 0x56, 0x92, 0xe4, 0xd0
};
/* 6282b8c05c5c1530b97d4816ca434762 */
const uint8_t NIST_AES256_CBC_plaintext[] =
{
0x8d, 0x3a, 0xa1, 0x96, 0xec, 0x3d, 0x7c, 0x9b, 0x5b, 0xb1, 0x22, 0xe7, 0xfe, 0x77, 0xfb, 0x12,
0x95, 0xa6, 0xda, 0x75, 0xab, 0xe5, 0xd3, 0xa5, 0x10, 0x19, 0x4d, 0x3a, 0x8a, 0x41, 0x57, 0xd5,
0xc8, 0x9d, 0x40, 0x61, 0x97, 0x16, 0x61, 0x98, 0x59, 0xda, 0x3e, 0xc9, 0xb2, 0x47, 0xce, 0xd9
};
/* 6acc04142e100a65f51b97adf5172c41 */
const uint8_t NIST_AES256_CBC_ciphertext[] =
{
0x60, 0x8e, 0x82, 0xc7, 0xab, 0x04, 0x00, 0x7a, 0xdb, 0x22, 0xe3, 0x89, 0xa4, 0x47, 0x97, 0xfe,
0xd7, 0xde, 0x09, 0x0c, 0x8c, 0x03, 0xca, 0x8a, 0x2c, 0x5a, 0xcd, 0x9e, 0x84, 0xdf, 0x37, 0xfb,
0xc5, 0x8c, 0xe8, 0xed, 0xb2, 0x93, 0xe9, 0x8f, 0x02, 0xb6, 0x40, 0xd6, 0xd1, 0xd7, 0x24, 0x64
};
void netx_secure_crypto_aes256cbc_multipart_example (void)
{
uint8_t metadata[sizeof(NX_CRYPTO_AES)];
uint32_t metadata_size = sizeof(NX_CRYPTO_AES);
void * handler = NX_CRYPTO_NULL;
uint32_t err = NX_CRYPTO_SUCCESS;
/* 3 AES Blocks */
uint8_t generated_ciphertext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
uint8_t generated_plaintext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
err =
_nx_crypto_method_aes_init(&crypto_method_aes_cbc_256, (uint8_t *) NIST_AES256_CBC_key,
sizeof(NIST_AES256_CBC_key) << 3U, &handler, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
/* Encryption. */
err = _nx_crypto_method_aes_operation(NX_CRYPTO_ENCRYPT,
handler,
&crypto_method_aes_cbc_256,
NULL,
0,
(uint8_t *) NIST_AES256_CBC_plaintext,
sizeof(NIST_AES256_CBC_plaintext),
(uint8_t *) NIST_AES256_CBC_iv,
generated_ciphertext,
sizeof(generated_ciphertext),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Verify generated ciphertext matches the expected ciphertext */
err = (uint32_t) memcmp(generated_ciphertext, NIST_AES256_CBC_ciphertext, sizeof(generated_ciphertext));
assert(0 == err);
/* Decryption. */
err = _nx_crypto_method_aes_operation(NX_CRYPTO_DECRYPT,
handler,
&crypto_method_aes_cbc_256,
NULL,
0,
(uint8_t *) NIST_AES256_CBC_ciphertext,
sizeof(NIST_AES256_CBC_ciphertext),
(uint8_t *) NIST_AES256_CBC_iv,
generated_plaintext,
sizeof(generated_plaintext),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Verify generated plaintext matches the input plaintext */
err = (uint32_t) memcmp(generated_plaintext, NIST_AES256_CBC_plaintext, sizeof(generated_ciphertext));
assert(0 == err);
}

AES GCM Example

extern NX_CRYPTO_METHOD crypto_method_aes_128_gcm_16;
/* 83F9D97D4AB759FDDCC3EF54A0E2A8EC */
static const uint8_t key_gcm_128[] =
{
0x83, 0xF9, 0xD9, 0x7D, 0x4A, 0xB7, 0x59, 0xFD, 0xDC, 0xC3, 0xEF, 0x54, 0xA0, 0xE2, 0xA8, 0xEC
};
/* In case of IV the IV length must be the first byte followed by the actual IV.
* In this example the IV length is 0x01 and the actual IV is 0xCF
*/
/* 01CF */
static const uint8_t iv_gcm_128[] =
{
0x01, 0xCF
};
/* 77E6329CF9424F71C808DF9170BFD298 */
static const uint8_t plain_gcm_128[] =
{
0x77, 0xE6, 0x32, 0x9C, 0xF9, 0x42, 0x4F, 0x71, 0xC8, 0x08, 0xDF, 0x91, 0x70, 0xBF, 0xD2, 0x98
};
/* 6DD49EAEB4103DAC8F97E3234946DD2D */
static const uint8_t aad_gcm_128[] =
{
0x6D, 0xD4, 0x9E, 0xAE, 0xB4, 0x10, 0x3D, 0xAC, 0x8F, 0x97, 0xE3, 0x23, 0x49, 0x46, 0xDD, 0x2D
};
/* 50DE86A7A92A8A5EA33DB5696B96CD77AA181E84BC8B4BF5A68927C409D422CB */
static const uint8_t secret_gcm_128[] =
{
/* Ciphertext */
0x50, 0xDE, 0x86, 0xA7, 0xA9, 0x2A, 0x8A, 0x5E, 0xA3, 0x3D, 0xB5, 0x69, 0x6B, 0x96, 0xCD, 0x77,
/* Tag */
0xAA, 0x18, 0x1E, 0x84, 0xBC, 0x8B, 0x4B, 0xF5, 0xA6, 0x89, 0x27, 0xC4, 0x09, 0xD4, 0x22, 0xCB
};
void netx_secure_crypto_aes128gcm_multipart_example (void)
{
uint8_t metadata[sizeof(NX_CRYPTO_AES)];
uint32_t metadata_size = sizeof(NX_CRYPTO_AES);
void * handler = NX_CRYPTO_NULL;
uint32_t err = NX_CRYPTO_SUCCESS;
/* 3 AES Blocks */
uint8_t generated_ciphertext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
uint8_t generated_plaintext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
err =
_nx_crypto_method_aes_init(&crypto_method_aes_128_gcm_16,
(uint8_t *) key_gcm_128,
sizeof(key_gcm_128) << 3U,
&handler,
metadata,
metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
/* Setup Additional Authentication Data */
err = _nx_crypto_method_aes_operation(NX_CRYPTO_SET_ADDITIONAL_DATA,
handler,
&crypto_method_aes_128_gcm_16,
NULL,
0,
(uint8_t *) aad_gcm_128,
sizeof(aad_gcm_128),
NULL,
NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Encryption. */
err = _nx_crypto_method_aes_operation(NX_CRYPTO_ENCRYPT,
handler,
&crypto_method_aes_128_gcm_16,
NULL,
0,
(uint8_t *) plain_gcm_128,
sizeof(plain_gcm_128),
(uint8_t *) iv_gcm_128,
generated_ciphertext,
sizeof(generated_ciphertext),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* The 16 byte tag is appended to the generated ciphertext */
/* Verify generated tag matches the expected tag */
err = (uint32_t) memcmp(&generated_ciphertext[sizeof(plain_gcm_128)], &secret_gcm_128[sizeof(plain_gcm_128)], 16U);
assert(0 == err);
/* Verify generated ciphertext matches the expected ciphertext */
err = (uint32_t) memcmp(generated_ciphertext, secret_gcm_128, sizeof(secret_gcm_128));
assert(0 == err);
/* Setup Additional Authentication Data */
err = _nx_crypto_method_aes_operation(NX_CRYPTO_SET_ADDITIONAL_DATA,
handler,
&crypto_method_aes_128_gcm_16,
NULL,
0,
(uint8_t *) aad_gcm_128,
sizeof(aad_gcm_128),
NULL,
NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Decryption. */
err = _nx_crypto_method_aes_operation(NX_CRYPTO_DECRYPT,
handler,
&crypto_method_aes_128_gcm_16,
NULL,
0,
(uint8_t *) generated_ciphertext,
sizeof(secret_gcm_128), /* ciphertext size + tag size */
(uint8_t *) iv_gcm_128,
generated_plaintext,
sizeof(generated_plaintext),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Verify generated plaintext matches the input plaintext */
err = (uint32_t) memcmp(generated_plaintext, plain_gcm_128, sizeof(plain_gcm_128));
assert(0 == err);
}

AES CTR Example

NX_CRYPTO_METHOD crypto_method_aes_ctr_256 =
{
NX_CRYPTO_ENCRYPTION_AES_CTR, /* AES crypto algorithm */
NX_CRYPTO_AES_256_KEY_LEN_IN_BITS, /* Key size in bits */
NX_CRYPTO_AES_IV_LEN_IN_BITS, /* IV size in bits */
0, /* ICV size in bits, not used */
(NX_CRYPTO_AES_BLOCK_SIZE_IN_BITS >> 3), /* Block size in bytes */
sizeof(NX_CRYPTO_AES), /* Metadata size in bytes */
_nx_crypto_method_aes_init, /* AES-CBC initialization routine */
_nx_crypto_method_aes_cleanup, /* AES-CBC cleanup routine */
_nx_crypto_method_aes_ctr_operation /* AES-CBC operation */
};
/*Note: For CTR, the key_ctr is the conjunction of key and nonce. */
/* D0E78C4D0B30D33F5BF4A132B2F94A4A38963511A3904B117E35A37B5AAC8A193BF0D158 */
const uint8_t key_ctr_256[] =
{
/* AES Key */
0xD0, 0xE7, 0x8C, 0x4D, 0x0B, 0x30, 0xD3, 0x3F, 0x5B, 0xF4, 0xA1, 0x32, 0xB2, 0xF9, 0x4A, 0x4A,
0x38, 0x96, 0x35, 0x11, 0xA3, 0x90, 0x4B, 0x11, 0x7E, 0x35, 0xA3, 0x7B, 0x5A, 0xAC, 0x8A, 0x19,
/* Nonce */
0x3B, 0xF0, 0xD1, 0x58,
};
/* A1A31704C8B7E16C */
const uint8_t iv_ctr_256[] =
{
0xA1, 0xA3, 0x17, 0x04, 0xC8, 0xB7, 0xE1, 0x6C,
};
/* 981FA33222C5451017530155A4BF7F29 */
const uint8_t plain_ctr_256[] =
{
0x98, 0x1F, 0xA3, 0x32, 0x22, 0xC5, 0x45, 0x10, 0x17, 0x53, 0x01, 0x55, 0xA4, 0xBF, 0x7F, 0x29,
};
/* 643B91B4E541B20AAAEAB77F2D328566 */
const uint8_t secret_ctr_256[] =
{
0x64, 0x3B, 0x91, 0xB4, 0xE5, 0x41, 0xB2, 0x0A, 0xAA, 0xEA, 0xB7, 0x7F, 0x2D, 0x32, 0x85, 0x66,
};
void netx_secure_crypto_aes256ctr_multipart_example (void)
{
uint8_t metadata[sizeof(NX_CRYPTO_AES)];
uint32_t metadata_size = sizeof(NX_CRYPTO_AES);
void * handler = NX_CRYPTO_NULL;
uint32_t err = NX_CRYPTO_SUCCESS;
/* 3 AES Blocks */
uint8_t generated_ciphertext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
uint8_t generated_plaintext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
err =
_nx_crypto_method_aes_init(&crypto_method_aes_ctr_256,
(uint8_t *) key_ctr_256,
crypto_method_aes_ctr_256.nx_crypto_key_size_in_bits,
&handler,
metadata,
metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
/* Encryption. */
err = _nx_crypto_method_aes_operation(NX_CRYPTO_ENCRYPT,
handler,
&crypto_method_aes_ctr_256,
(uint8_t *) key_ctr_256,
crypto_method_aes_ctr_256.nx_crypto_key_size_in_bits,
(uint8_t *) plain_ctr_256,
sizeof(plain_ctr_256),
(uint8_t *) iv_ctr_256,
generated_ciphertext,
sizeof(generated_ciphertext),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Verify generated ciphertext matches the expected ciphertext */
err = (uint32_t) memcmp(generated_ciphertext, secret_ctr_256, sizeof(secret_ctr_256));
assert(0 == err);
/* Decryption. */
err = _nx_crypto_method_aes_operation(NX_CRYPTO_DECRYPT,
handler,
&crypto_method_aes_ctr_256,
(uint8_t *) key_ctr_256,
crypto_method_aes_ctr_256.nx_crypto_key_size_in_bits,
(uint8_t *) secret_ctr_256,
sizeof(secret_ctr_256),
(uint8_t *) iv_ctr_256,
generated_plaintext,
sizeof(generated_plaintext),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Verify generated plaintext matches the input plaintext */
err = (uint32_t) memcmp(generated_plaintext, plain_ctr_256, sizeof(plain_ctr_256));
assert(0 == err);
}

ECDSA Example

This is an example on using the NetX Crypto API to sign and verify input message data. Based on the hash algorithm selected a digest is computed of the plain input message before sign/verify.

extern NX_CRYPTO_METHOD crypto_method_ecdsa;
extern NX_CRYPTO_METHOD crypto_method_ec_secp256;
extern NX_CRYPTO_METHOD crypto_method_sha256;
const uint8_t ECC_SECP256R1Keydata[] =
{
0xf9, 0xa7, 0x68, 0x71, 0x24, 0x68, 0x9d, 0x32, 0x92, 0x6f, 0x1d, 0xfb, 0xbe, 0xf2, 0x61, 0x41, // NOLINT(readability-magic-numbers)
0x07, 0x54, 0x0d, 0xb9, 0xa8, 0x8a, 0x8b, 0xc2, 0xd5, 0xe9, 0x38, 0x4b, 0xf9, 0xe5, 0x43, 0x5a // NOLINT(readability-magic-numbers)
};
const uint8_t ECC_SECP256R1PublicKeydata[] =
{
0x04, /* ASN1 Constant */
0x5b, 0xba, 0xd4, 0x2e, 0xb5, 0xc1, 0x07, 0xf2, 0x0e, 0x01, 0x95, 0x42, 0x6e, 0x90, 0xb8, 0x4e, // NOLINT(readability-magic-numbers)
0xe9, 0x5a, 0xa1, 0xe8, 0x4c, 0x6c, 0xa5, 0x32, 0x3c, 0xf3, 0x09, 0xf5, 0xff, 0x8b, 0x3d, 0x26, // NOLINT(readability-magic-numbers)
0xb6, 0x88, 0xc1, 0xdb, 0x02, 0xaf, 0x4d, 0xa5, 0x0e, 0x73, 0x61, 0x96, 0xb3, 0x59, 0x95, 0x6f, // NOLINT(readability-magic-numbers)
0x5e, 0xc9, 0xa1, 0xf9, 0xb7, 0xb3, 0xb6, 0xdf, 0x54, 0x82, 0x79, 0xe3, 0xb6, 0x4e, 0xac, 0xb6 // NOLINT(readability-magic-numbers)
};
const uint8_t ECC_SECP256R1Message[] = "ASYMMETRIC_INPUT_FOR_SIGN......";
void netx_secure_crypto_ecdsa_example (void)
{
uint8_t metadata[sizeof(NX_CRYPTO_ECDSA)];
uint32_t metadata_size = sizeof(NX_CRYPTO_ECDSA);
void * handler = NX_CRYPTO_NULL;
uint32_t err = NX_CRYPTO_SUCCESS;
ULONG sig_length;
NX_CRYPTO_EXTENDED_OUTPUT extended_output;
uint8_t output[RM_NETX_SECURE_CRYPTO_EXAMPLE_OUTPUT_BUFFER_SIZE] = {0};
/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
/* Call the crypto initialization function. */
err = _nx_crypto_method_ecdsa_init(&crypto_method_ecdsa, NX_CRYPTO_NULL, 0, &handler, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
/* Set hash method. */
err = _nx_crypto_method_ecdsa_operation(NX_CRYPTO_HASH_METHOD_SET,
handler,
&crypto_method_ecdsa,
NX_CRYPTO_NULL,
0,
(uint8_t *) &crypto_method_sha256,
sizeof(NX_CRYPTO_METHOD *),
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Set EC curve. */
err =
_nx_crypto_method_ecdsa_operation(NX_CRYPTO_EC_CURVE_SET,
handler,
&crypto_method_ecdsa,
NX_CRYPTO_NULL,
0,
(uint8_t *) &crypto_method_ec_secp256,
sizeof(NX_CRYPTO_METHOD *),
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
extended_output.nx_crypto_extended_output_data = output;
extended_output.nx_crypto_extended_output_length_in_byte = sizeof(output);
/* Sign the hash data using ECDSA. */
err = _nx_crypto_method_ecdsa_operation(NX_CRYPTO_SIGNATURE_GENERATE,
handler,
&crypto_method_ec_secp256,
(uint8_t *) ECC_SECP256R1Keydata,
sizeof(ECC_SECP256R1Keydata) << 3,
(uint8_t *) ECC_SECP256R1Message,
sizeof(ECC_SECP256R1Message),
NX_CRYPTO_NULL,
(uint8_t *) &extended_output,
sizeof(extended_output),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
sig_length = extended_output.nx_crypto_extended_output_actual_size;
/* Verify the generated signature. */
err = _nx_crypto_method_ecdsa_operation(NX_CRYPTO_SIGNATURE_VERIFY,
handler,
&crypto_method_ec_secp256,
(uint8_t *) ECC_SECP256R1PublicKeydata,
sizeof(ECC_SECP256R1PublicKeydata) << 3,
(uint8_t *) ECC_SECP256R1Message,
sizeof(ECC_SECP256R1Message),
NX_CRYPTO_NULL,
output,
sig_length,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
}

ECDH Example

This is an example on using the NetX Crypto API to generate a shared secret using ECDH. A shared secret is computed using known public key (from peer) and generated private key. Another shared secret is computed using the generated public key and known private key (imported to mimic peer). Both the shared secrets are checked to be the same.

extern NX_CRYPTO_METHOD crypto_method_ecdh;
/*Private key 59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf */
const uint8_t ECC_SECP256R1Keydata_ecdh[] =
{
0x59, 0x13, 0x7e, 0x38, 0x15, 0x23, 0x50, 0xb1, 0x95, 0xc9, 0x71, 0x8d, 0x39, 0x67, 0x3d, 0x51, // NOLINT(readability-magic-numbers)
0x98, 0x38, 0x05, 0x5a, 0xd9, 0x08, 0xdd, 0x47, 0x57, 0x15, 0x2f, 0xd8, 0x25, 0x5c, 0x09, 0xbf, // NOLINT(readability-magic-numbers)
};
/*Public key 4, a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b, 806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a*/
const uint8_t ECC_SECP256R1PublicKeydata_ecdh[] =
{
0x04,
0xa8,0xc5, 0xfd, 0xce, 0x8b, 0x62, 0xc5, 0xad, 0xa5, 0x98, 0xf1, 0x41, 0xad, 0xb3, 0xb2, 0x6c, // NOLINT(readability-magic-numbers)
0xf2,0x54, 0xc2, 0x80, 0xb2, 0x85, 0x7a, 0x63, 0xd2, 0xad, 0x78, 0x3a, 0x73, 0x11, 0x5f, 0x6b, // NOLINT(readability-magic-numbers)
0x80,0x6e, 0x1a, 0xaf, 0xec, 0x4a, 0xf8, 0x0a, 0x0d, 0x78, 0x6b, 0x3d, 0xe4, 0x53, 0x75, 0xb5, // NOLINT(readability-magic-numbers)
0x17,0xa7, 0xe5, 0xb5, 0x1f, 0xfb, 0x2c, 0x35, 0x65, 0x37, 0xc9, 0xe6, 0xef, 0x22, 0x7d, 0x4a, // NOLINT(readability-magic-numbers)
};
void netx_secure_crypto_ecdh_example (void)
{
uint8_t metadata[sizeof(NX_CRYPTO_ECDH)];
uint32_t metadata_size = sizeof(NX_CRYPTO_ECDH);
uint32_t err = NX_CRYPTO_SUCCESS;
uint8_t local_public_key[RM_NETX_SECURE_CRYPTO_EXAMPLE_OUTPUT_BUFFER_SIZE] = {0};
uint32_t local_public_key_len = 0;
uint8_t shared_secret[RM_NETX_SECURE_CRYPTO_EXAMPLE_OUTPUT_BUFFER_SIZE] = {0};
uint32_t shared_secret_len = 0;
uint8_t output[RM_NETX_SECURE_CRYPTO_EXAMPLE_OUTPUT_BUFFER_SIZE] = {0};
NX_CRYPTO_EXTENDED_OUTPUT extended_output;
/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
/* Call the crypto initialization function. */
err = _nx_crypto_method_ecdh_init(&crypto_method_ecdh, NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
/* Set EC curve. */
err = _nx_crypto_method_ecdh_operation(NX_CRYPTO_EC_CURVE_SET,
NX_CRYPTO_NULL,
&crypto_method_ecdh,
NX_CRYPTO_NULL,
0,
(uint8_t *) &crypto_method_ec_secp256,
sizeof(NX_CRYPTO_METHOD *),
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Generate local public key. This will generate a key pair.
* The private wrapped key will be held by the ecdh context and the public key (local_public_key)
* will be returned for sharing with the peer.
*/
extended_output.nx_crypto_extended_output_data = local_public_key;
extended_output.nx_crypto_extended_output_length_in_byte = sizeof(local_public_key);
err = _nx_crypto_method_ecdh_operation(NX_CRYPTO_DH_SETUP,
NX_CRYPTO_NULL,
&crypto_method_ecdh,
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
(uint8_t *) &extended_output,
sizeof(extended_output),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
local_public_key_len = extended_output.nx_crypto_extended_output_actual_size;
/* Calculate shared secret using the test (peer's) public key. */
extended_output.nx_crypto_extended_output_data = shared_secret;
extended_output.nx_crypto_extended_output_length_in_byte = sizeof(shared_secret);
err = _nx_crypto_method_ecdh_operation(NX_CRYPTO_DH_CALCULATE,
NX_CRYPTO_NULL,
&crypto_method_ecdh,
NX_CRYPTO_NULL,
0,
(uint8_t *) ECC_SECP256R1PublicKeydata_ecdh,
sizeof(ECC_SECP256R1PublicKeydata_ecdh),
NX_CRYPTO_NULL,
(uint8_t *) &extended_output,
sizeof(extended_output),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
shared_secret_len = extended_output.nx_crypto_extended_output_actual_size;
err = _nx_crypto_method_ecdh_cleanup(metadata);
assert(NX_CRYPTO_SUCCESS == err);
/* Verify. The below operations will be carried out by the peer. */
/* Call the crypto initialization function. */
err = _nx_crypto_method_ecdh_init(&crypto_method_ecdh, NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
/* Set EC curve. */
err = _nx_crypto_method_ecdh_operation(NX_CRYPTO_EC_CURVE_SET,
NX_CRYPTO_NULL,
&crypto_method_ecdh,
NX_CRYPTO_NULL,
0,
(uint8_t *) &crypto_method_ec_secp256,
sizeof(NX_CRYPTO_METHOD *),
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Import the test private key. The peer could generate its own key pair,
* in this example a test private key is used for simplicity. */
err =
_nx_crypto_method_ecdh_operation(NX_CRYPTO_DH_KEY_PAIR_IMPORT,
NX_CRYPTO_NULL,
&crypto_method_ecdh,
(uint8_t *) ECC_SECP256R1Keydata_ecdh,
(NX_CRYPTO_KEY_SIZE) (sizeof(ECC_SECP256R1Keydata_ecdh) << 3),
(uint8_t *) ECC_SECP256R1PublicKeydata_ecdh,
sizeof(ECC_SECP256R1PublicKeydata_ecdh),
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Calculate the shared secret using the local public key generated above and shared with the peer. */
extended_output.nx_crypto_extended_output_data = output;
extended_output.nx_crypto_extended_output_length_in_byte = sizeof(output);
err = _nx_crypto_method_ecdh_operation(NX_CRYPTO_DH_CALCULATE,
NX_CRYPTO_NULL,
&crypto_method_ecdh,
NX_CRYPTO_NULL,
0,
local_public_key,
local_public_key_len,
NX_CRYPTO_NULL,
(uint8_t *) &extended_output,
sizeof(extended_output),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Validate the output. Both the parties must generate the same shared secret */
err = (extended_output.nx_crypto_extended_output_actual_size != shared_secret_len);
assert(NX_CRYPTO_SUCCESS == err);
err = (uint32_t) memcmp(output, shared_secret, extended_output.nx_crypto_extended_output_actual_size);
assert(NX_CRYPTO_SUCCESS == err);
}

RSA Example

This is an example on using the NetX Crypto API to encrypt and decrypt input message data.

extern NX_CRYPTO_METHOD crypto_method_rsa;
/* 00010001 */
const uint8_t public_e[] =
{
0x00, 0x01, 0x00, 0x01,
};
/* 13FF7429F8E851F1079CCFCE3B3CD8606ABA8607AD85CBB3057501EBD58811F3C04823171F192C048E1E883AF8CF958810151D3874AEDC8EC4F88D2065C581569F1E200852DD40B6DFD1652659085A9DD1D3B869EA3617D904D209DE156A60BA5929D02F16430273D10720C2F28D2B95684DCAA6B9F6A508EA2CBBC11B9F3F30D6201EA6CFFBBF1C44255CEC58EE70DBC872442BCCF115D8F743557B5DE5F42DDDA6CEAE7977793CC9D90ADFE65E520F5520B615CF3B8C2DC82D7AC75EDB1297CF38AB23A37EED18D4DD45D9AD051B26401BE86E8C8E53F9585A702D02F1B5BD65F6739DFA6BFFE560CA130B6F1D4779C556C06D9CD29FB72D8851904F9CDEE9 */
const uint8_t private_e_2048[] =
{
0x13, 0xFF, 0x74, 0x29, 0xF8, 0xE8, 0x51, 0xF1, 0x07, 0x9C, 0xCF, 0xCE, 0x3B, 0x3C, 0xD8, 0x60,
0x6A, 0xBA, 0x86, 0x07, 0xAD, 0x85, 0xCB, 0xB3, 0x05, 0x75, 0x01, 0xEB, 0xD5, 0x88, 0x11, 0xF3,
0xC0, 0x48, 0x23, 0x17, 0x1F, 0x19, 0x2C, 0x04, 0x8E, 0x1E, 0x88, 0x3A, 0xF8, 0xCF, 0x95, 0x88,
0x10, 0x15, 0x1D, 0x38, 0x74, 0xAE, 0xDC, 0x8E, 0xC4, 0xF8, 0x8D, 0x20, 0x65, 0xC5, 0x81, 0x56,
0x9F, 0x1E, 0x20, 0x08, 0x52, 0xDD, 0x40, 0xB6, 0xDF, 0xD1, 0x65, 0x26, 0x59, 0x08, 0x5A, 0x9D,
0xD1, 0xD3, 0xB8, 0x69, 0xEA, 0x36, 0x17, 0xD9, 0x04, 0xD2, 0x09, 0xDE, 0x15, 0x6A, 0x60, 0xBA,
0x59, 0x29, 0xD0, 0x2F, 0x16, 0x43, 0x02, 0x73, 0xD1, 0x07, 0x20, 0xC2, 0xF2, 0x8D, 0x2B, 0x95,
0x68, 0x4D, 0xCA, 0xA6, 0xB9, 0xF6, 0xA5, 0x08, 0xEA, 0x2C, 0xBB, 0xC1, 0x1B, 0x9F, 0x3F, 0x30,
0xD6, 0x20, 0x1E, 0xA6, 0xCF, 0xFB, 0xBF, 0x1C, 0x44, 0x25, 0x5C, 0xEC, 0x58, 0xEE, 0x70, 0xDB,
0xC8, 0x72, 0x44, 0x2B, 0xCC, 0xF1, 0x15, 0xD8, 0xF7, 0x43, 0x55, 0x7B, 0x5D, 0xE5, 0xF4, 0x2D,
0xDD, 0xA6, 0xCE, 0xAE, 0x79, 0x77, 0x79, 0x3C, 0xC9, 0xD9, 0x0A, 0xDF, 0xE6, 0x5E, 0x52, 0x0F,
0x55, 0x20, 0xB6, 0x15, 0xCF, 0x3B, 0x8C, 0x2D, 0xC8, 0x2D, 0x7A, 0xC7, 0x5E, 0xDB, 0x12, 0x97,
0xCF, 0x38, 0xAB, 0x23, 0xA3, 0x7E, 0xED, 0x18, 0xD4, 0xDD, 0x45, 0xD9, 0xAD, 0x05, 0x1B, 0x26,
0x40, 0x1B, 0xE8, 0x6E, 0x8C, 0x8E, 0x53, 0xF9, 0x58, 0x5A, 0x70, 0x2D, 0x02, 0xF1, 0xB5, 0xBD,
0x65, 0xF6, 0x73, 0x9D, 0xFA, 0x6B, 0xFF, 0xE5, 0x60, 0xCA, 0x13, 0x0B, 0x6F, 0x1D, 0x47, 0x79,
0xC5, 0x56, 0xC0, 0x6D, 0x9C, 0xD2, 0x9F, 0xB7, 0x2D, 0x88, 0x51, 0x90, 0x4F, 0x9C, 0xDE, 0xE9,
};
/* E0F5059966A8AEC4BF7CDAC8AE2430BDF61C54D09CAB9963CBF9A52AC641E384B6431D3B6A9D1811519A2904E1170A44446C80E7638A4AF2720A7654AB740D8A151FDD216F3D6933422FD9AC14AEDE9CCD021EA79E46925F4B18FD1AF2C0073CFC3A69AC71A2B3673D08136CDB01C379892601C7C857D68018DAE924CB8CD29377A14C752B92BAFF14C3A49725AE2FEFAAD4686D8A7D9F94EB11BF81E05BD5D2586526FB129E73539F9223D496B2ACA23CCACC34D5B18533BD0F5815A76F94F4F55D965FE61599B44BD8FBAD35F42B612A4C4F2765B2097A5C0090EA8166D9C6DA1E03B6119736B794600491C48433132D0F15D5DE3BB4270DF6BC9012B74931 */
const uint8_t m_2048[] =
{
0xE0, 0xF5, 0x05, 0x99, 0x66, 0xA8, 0xAE, 0xC4, 0xBF, 0x7C, 0xDA, 0xC8, 0xAE, 0x24, 0x30, 0xBD,
0xF6, 0x1C, 0x54, 0xD0, 0x9C, 0xAB, 0x99, 0x63, 0xCB, 0xF9, 0xA5, 0x2A, 0xC6, 0x41, 0xE3, 0x84,
0xB6, 0x43, 0x1D, 0x3B, 0x6A, 0x9D, 0x18, 0x11, 0x51, 0x9A, 0x29, 0x04, 0xE1, 0x17, 0x0A, 0x44,
0x44, 0x6C, 0x80, 0xE7, 0x63, 0x8A, 0x4A, 0xF2, 0x72, 0x0A, 0x76, 0x54, 0xAB, 0x74, 0x0D, 0x8A,
0x15, 0x1F, 0xDD, 0x21, 0x6F, 0x3D, 0x69, 0x33, 0x42, 0x2F, 0xD9, 0xAC, 0x14, 0xAE, 0xDE, 0x9C,
0xCD, 0x02, 0x1E, 0xA7, 0x9E, 0x46, 0x92, 0x5F, 0x4B, 0x18, 0xFD, 0x1A, 0xF2, 0xC0, 0x07, 0x3C,
0xFC, 0x3A, 0x69, 0xAC, 0x71, 0xA2, 0xB3, 0x67, 0x3D, 0x08, 0x13, 0x6C, 0xDB, 0x01, 0xC3, 0x79,
0x89, 0x26, 0x01, 0xC7, 0xC8, 0x57, 0xD6, 0x80, 0x18, 0xDA, 0xE9, 0x24, 0xCB, 0x8C, 0xD2, 0x93,
0x77, 0xA1, 0x4C, 0x75, 0x2B, 0x92, 0xBA, 0xFF, 0x14, 0xC3, 0xA4, 0x97, 0x25, 0xAE, 0x2F, 0xEF,
0xAA, 0xD4, 0x68, 0x6D, 0x8A, 0x7D, 0x9F, 0x94, 0xEB, 0x11, 0xBF, 0x81, 0xE0, 0x5B, 0xD5, 0xD2,
0x58, 0x65, 0x26, 0xFB, 0x12, 0x9E, 0x73, 0x53, 0x9F, 0x92, 0x23, 0xD4, 0x96, 0xB2, 0xAC, 0xA2,
0x3C, 0xCA, 0xCC, 0x34, 0xD5, 0xB1, 0x85, 0x33, 0xBD, 0x0F, 0x58, 0x15, 0xA7, 0x6F, 0x94, 0xF4,
0xF5, 0x5D, 0x96, 0x5F, 0xE6, 0x15, 0x99, 0xB4, 0x4B, 0xD8, 0xFB, 0xAD, 0x35, 0xF4, 0x2B, 0x61,
0x2A, 0x4C, 0x4F, 0x27, 0x65, 0xB2, 0x09, 0x7A, 0x5C, 0x00, 0x90, 0xEA, 0x81, 0x66, 0xD9, 0xC6,
0xDA, 0x1E, 0x03, 0xB6, 0x11, 0x97, 0x36, 0xB7, 0x94, 0x60, 0x04, 0x91, 0xC4, 0x84, 0x33, 0x13,
0x2D, 0x0F, 0x15, 0xD5, 0xDE, 0x3B, 0xB4, 0x27, 0x0D, 0xF6, 0xBC, 0x90, 0x12, 0xB7, 0x49, 0x31,
};
/* 551C2E268F7ED44D0E8B063F5B2B510CB809F53BD54E9956971E243B2363DA123C29AB4A009EDE1FCEC54625971A4E3490F3EA398BF7386AAC34720E43FB0C795445B520AEE4D7694EE1474F60F77E1B5F09FE2ED004333658D212122F040322D1564512A1540400F27E18049A762A5EDC9F072CA4F49F408252D42B31BC35523373740E90DDDA6A8CE7865EEB7C694A662C74412406AB190FE0435DA2551F0C24A48939DDA58A0239706D40B4977473689DC36CE5A4DF4EF892816CBDE2780D9389B7384674C93B1DDAF728F292B5671679FC7175AC0A3B2197B809E7CF410417010F3B1316D10D82466C62F3A01667B70A714E0499400E255D4C39EA7DE55C */
const uint8_t plain_2048[] =
{
0x55, 0x1C, 0x2E, 0x26, 0x8F, 0x7E, 0xD4, 0x4D, 0x0E, 0x8B, 0x06, 0x3F, 0x5B, 0x2B, 0x51, 0x0C,
0xB8, 0x09, 0xF5, 0x3B, 0xD5, 0x4E, 0x99, 0x56, 0x97, 0x1E, 0x24, 0x3B, 0x23, 0x63, 0xDA, 0x12,
0x3C, 0x29, 0xAB, 0x4A, 0x00, 0x9E, 0xDE, 0x1F, 0xCE, 0xC5, 0x46, 0x25, 0x97, 0x1A, 0x4E, 0x34,
0x90, 0xF3, 0xEA, 0x39, 0x8B, 0xF7, 0x38, 0x6A, 0xAC, 0x34, 0x72, 0x0E, 0x43, 0xFB, 0x0C, 0x79,
0x54, 0x45, 0xB5, 0x20, 0xAE, 0xE4, 0xD7, 0x69, 0x4E, 0xE1, 0x47, 0x4F, 0x60, 0xF7, 0x7E, 0x1B,
0x5F, 0x09, 0xFE, 0x2E, 0xD0, 0x04, 0x33, 0x36, 0x58, 0xD2, 0x12, 0x12, 0x2F, 0x04, 0x03, 0x22,
0xD1, 0x56, 0x45, 0x12, 0xA1, 0x54, 0x04, 0x00, 0xF2, 0x7E, 0x18, 0x04, 0x9A, 0x76, 0x2A, 0x5E,
0xDC, 0x9F, 0x07, 0x2C, 0xA4, 0xF4, 0x9F, 0x40, 0x82, 0x52, 0xD4, 0x2B, 0x31, 0xBC, 0x35, 0x52,
0x33, 0x73, 0x74, 0x0E, 0x90, 0xDD, 0xDA, 0x6A, 0x8C, 0xE7, 0x86, 0x5E, 0xEB, 0x7C, 0x69, 0x4A,
0x66, 0x2C, 0x74, 0x41, 0x24, 0x06, 0xAB, 0x19, 0x0F, 0xE0, 0x43, 0x5D, 0xA2, 0x55, 0x1F, 0x0C,
0x24, 0xA4, 0x89, 0x39, 0xDD, 0xA5, 0x8A, 0x02, 0x39, 0x70, 0x6D, 0x40, 0xB4, 0x97, 0x74, 0x73,
0x68, 0x9D, 0xC3, 0x6C, 0xE5, 0xA4, 0xDF, 0x4E, 0xF8, 0x92, 0x81, 0x6C, 0xBD, 0xE2, 0x78, 0x0D,
0x93, 0x89, 0xB7, 0x38, 0x46, 0x74, 0xC9, 0x3B, 0x1D, 0xDA, 0xF7, 0x28, 0xF2, 0x92, 0xB5, 0x67,
0x16, 0x79, 0xFC, 0x71, 0x75, 0xAC, 0x0A, 0x3B, 0x21, 0x97, 0xB8, 0x09, 0xE7, 0xCF, 0x41, 0x04,
0x17, 0x01, 0x0F, 0x3B, 0x13, 0x16, 0xD1, 0x0D, 0x82, 0x46, 0x6C, 0x62, 0xF3, 0xA0, 0x16, 0x67,
0xB7, 0x0A, 0x71, 0x4E, 0x04, 0x99, 0x40, 0x0E, 0x25, 0x5D, 0x4C, 0x39, 0xEA, 0x7D, 0xE5, 0x5C,
};
/* 10F904E071338569EC131401A7869F42F3BCAE252B5D3C8755FD24D47997A9CD4221D992B2871E05283B98841FC5C379C5D0E35B3938279B344299C3CF1566E0C994D0A9013AF64174F1379A4B5E4E9DE57491F3078F6D10011EA55535D0763E538662C9996F4FCF8B64A768685AA417ADB6978743D3D1F513CF143DD6D383AD6357728A88928D39E27EA4D0B2AF92FC7F63875F9D6A70FAE7993C1FF04DF9A2F99216874BC123D4B7DA7E7E8974CFC10ACF0C7BC8747526A8D16791F969082EA9B0C36D77B67C37B325682D74178E4234D52D5635273301A6CC35E315AE74D659B1433576DAAE6780FA39E0550D971F2CB5817CAAFC24B5220E21C8CEEE85DD */
const uint8_t secret_2048[] =
{
0x10, 0xF9, 0x04, 0xE0, 0x71, 0x33, 0x85, 0x69, 0xEC, 0x13, 0x14, 0x01, 0xA7, 0x86, 0x9F, 0x42,
0xF3, 0xBC, 0xAE, 0x25, 0x2B, 0x5D, 0x3C, 0x87, 0x55, 0xFD, 0x24, 0xD4, 0x79, 0x97, 0xA9, 0xCD,
0x42, 0x21, 0xD9, 0x92, 0xB2, 0x87, 0x1E, 0x05, 0x28, 0x3B, 0x98, 0x84, 0x1F, 0xC5, 0xC3, 0x79,
0xC5, 0xD0, 0xE3, 0x5B, 0x39, 0x38, 0x27, 0x9B, 0x34, 0x42, 0x99, 0xC3, 0xCF, 0x15, 0x66, 0xE0,
0xC9, 0x94, 0xD0, 0xA9, 0x01, 0x3A, 0xF6, 0x41, 0x74, 0xF1, 0x37, 0x9A, 0x4B, 0x5E, 0x4E, 0x9D,
0xE5, 0x74, 0x91, 0xF3, 0x07, 0x8F, 0x6D, 0x10, 0x01, 0x1E, 0xA5, 0x55, 0x35, 0xD0, 0x76, 0x3E,
0x53, 0x86, 0x62, 0xC9, 0x99, 0x6F, 0x4F, 0xCF, 0x8B, 0x64, 0xA7, 0x68, 0x68, 0x5A, 0xA4, 0x17,
0xAD, 0xB6, 0x97, 0x87, 0x43, 0xD3, 0xD1, 0xF5, 0x13, 0xCF, 0x14, 0x3D, 0xD6, 0xD3, 0x83, 0xAD,
0x63, 0x57, 0x72, 0x8A, 0x88, 0x92, 0x8D, 0x39, 0xE2, 0x7E, 0xA4, 0xD0, 0xB2, 0xAF, 0x92, 0xFC,
0x7F, 0x63, 0x87, 0x5F, 0x9D, 0x6A, 0x70, 0xFA, 0xE7, 0x99, 0x3C, 0x1F, 0xF0, 0x4D, 0xF9, 0xA2,
0xF9, 0x92, 0x16, 0x87, 0x4B, 0xC1, 0x23, 0xD4, 0xB7, 0xDA, 0x7E, 0x7E, 0x89, 0x74, 0xCF, 0xC1,
0x0A, 0xCF, 0x0C, 0x7B, 0xC8, 0x74, 0x75, 0x26, 0xA8, 0xD1, 0x67, 0x91, 0xF9, 0x69, 0x08, 0x2E,
0xA9, 0xB0, 0xC3, 0x6D, 0x77, 0xB6, 0x7C, 0x37, 0xB3, 0x25, 0x68, 0x2D, 0x74, 0x17, 0x8E, 0x42,
0x34, 0xD5, 0x2D, 0x56, 0x35, 0x27, 0x33, 0x01, 0xA6, 0xCC, 0x35, 0xE3, 0x15, 0xAE, 0x74, 0xD6,
0x59, 0xB1, 0x43, 0x35, 0x76, 0xDA, 0xAE, 0x67, 0x80, 0xFA, 0x39, 0xE0, 0x55, 0x0D, 0x97, 0x1F,
0x2C, 0xB5, 0x81, 0x7C, 0xAA, 0xFC, 0x24, 0xB5, 0x22, 0x0E, 0x21, 0xC8, 0xCE, 0xEE, 0x85, 0xDD,
};
void netx_secure_crypto_rsa_example (void)
{
uint8_t metadata[sizeof(NX_CRYPTO_RSA)];
uint32_t metadata_size = sizeof(NX_CRYPTO_RSA);
uint32_t err = NX_CRYPTO_SUCCESS;
void * handler = NX_CRYPTO_NULL;
uint8_t output[RM_NETX_SECURE_CRYPTO_EXAMPLE_OUTPUT_BUFFER_SIZE] = {0};
/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
/* Encryption. */
err =
_nx_crypto_method_rsa_init(&crypto_method_rsa,
(uint8_t *) m_2048,
RM_NETX_SECURE_CRYPTO_BYTES_TO_BITS(sizeof(m_2048)),
&handler,
metadata,
metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
err = _nx_crypto_method_rsa_operation(NX_CRYPTO_ENCRYPT,
handler,
&crypto_method_rsa,
(uint8_t *) public_e,
RM_NETX_SECURE_CRYPTO_BYTES_TO_BITS(sizeof(public_e)),
(uint8_t *) plain_2048,
sizeof(m_2048),
NX_CRYPTO_NULL,
output,
sizeof(m_2048),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
err = (uint32_t) memcmp(output, secret_2048, sizeof(m_2048));
assert(0 == err);
err = _nx_crypto_method_rsa_cleanup(metadata);
assert(NX_CRYPTO_SUCCESS == err);
/* Decryption. */
memset(output, 0, sizeof(output));
err =
_nx_crypto_method_rsa_init(&crypto_method_rsa,
(uint8_t *) m_2048,
RM_NETX_SECURE_CRYPTO_BYTES_TO_BITS(sizeof(m_2048)),
&handler,
metadata,
metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
err = _nx_crypto_method_rsa_operation(NX_CRYPTO_DECRYPT,
handler,
&crypto_method_rsa,
(uint8_t *) private_e_2048,
RM_NETX_SECURE_CRYPTO_BYTES_TO_BITS(sizeof(private_e_2048)),
(uint8_t *) secret_2048,
sizeof(m_2048),
NX_CRYPTO_NULL,
output,
sizeof(m_2048),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
err = (uint32_t) memcmp(output, plain_2048, sizeof(m_2048));
assert(0 == err);
}

RSA PKCS1V1.5 Example

This is an example on using the NetX Crypto API to sign and verify input message data. The plain input message is PKCS1V1.5 encoded before signature generation.

PKCS1V15 Example

HMAC SHA256 Example

This is an example on using the HMAC with SHA256 hash using the NetX Crypto API.

extern NX_CRYPTO_METHOD crypto_method_hmac_sha256;
/* C4DA057B81EA740B697FFE1B6EB8591356BA6D5EA7F1B96E4F048030449ACD64E4BB271CB4DCF94937E6 */
const uint8_t key_256[] =
{
0xC4, 0xDA, 0x05, 0x7B, 0x81, 0xEA, 0x74, 0x0B, 0x69, 0x7F, 0xFE, 0x1B, 0x6E, 0xB8, 0x59, 0x13,
0x56, 0xBA, 0x6D, 0x5E, 0xA7, 0xF1, 0xB9, 0x6E, 0x4F, 0x04, 0x80, 0x30, 0x44, 0x9A, 0xCD, 0x64,
0xE4, 0xBB, 0x27, 0x1C, 0xB4, 0xDC, 0xF9, 0x49, 0x37, 0xE6,
};
/* BDACB6555D294D3AFFC245520116062D98F88D64276BDA593492AE71CFE16E46CABC287CB00DF21D96066D5856C2224EEF609D4896302540078F3A0EE325F5337E */
const uint8_t plain_256[] =
{
0xBD, 0xAC, 0xB6, 0x55, 0x5D, 0x29, 0x4D, 0x3A, 0xFF, 0xC2, 0x45, 0x52, 0x01, 0x16, 0x06, 0x2D,
0x98, 0xF8, 0x8D, 0x64, 0x27, 0x6B, 0xDA, 0x59, 0x34, 0x92, 0xAE, 0x71, 0xCF, 0xE1, 0x6E, 0x46,
0xCA, 0xBC, 0x28, 0x7C, 0xB0, 0x0D, 0xF2, 0x1D, 0x96, 0x06, 0x6D, 0x58, 0x56, 0xC2, 0x22, 0x4E,
0xEF, 0x60, 0x9D, 0x48, 0x96, 0x30, 0x25, 0x40, 0x07, 0x8F, 0x3A, 0x0E, 0xE3, 0x25, 0xF5, 0x33,
0x7E,
};
/* 940F986AC891C9000B72EF0CEC69AB66AF002E3A34EB8A3A5F94484E45C0396C */
const uint8_t secret_256[] =
{
0x94, 0x0F, 0x98, 0x6A, 0xC8, 0x91, 0xC9, 0x00, 0x0B, 0x72, 0xEF, 0x0C, 0xEC, 0x69, 0xAB, 0x66,
0xAF, 0x00, 0x2E, 0x3A, 0x34, 0xEB, 0x8A, 0x3A, 0x5F, 0x94, 0x48, 0x4E, 0x45, 0xC0, 0x39, 0x6C,
};
void netx_secure_crypto_hmac_sha256_example (void)
{
uint8_t output[RM_NETX_SECURE_CRYPTO_EXAMPLE_SHA256_HASH_SIZE_BYTES] = {0};
uint8_t metadata[sizeof(NX_CRYPTO_SHA256_HMAC)] = {0};
uint32_t metadata_size = sizeof(NX_CRYPTO_SHA256_HMAC);
void * handler = NX_CRYPTO_NULL;
uint32_t err = NX_CRYPTO_SUCCESS;
/* Setup the platform; initialize the SCE and the TRNG */
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
/* Nx Crypto HMAC-SHA256 init */
err = _nx_crypto_method_hmac_sha256_init(&crypto_method_hmac_sha256,
(UCHAR *) key_256,
RM_NETX_SECURE_CRYPTO_BYTES_TO_BITS(sizeof(key_256)),
&handler,
metadata,
metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
/* Nx Crypto HMAC-SHA256 operation - NX_CRYPTO_HASH_INITIALIZE */
err =
_nx_crypto_method_hmac_sha256_operation(NX_CRYPTO_HASH_INITIALIZE,
handler,
&crypto_method_hmac_sha256,
(UCHAR *) key_256,
RM_NETX_SECURE_CRYPTO_BYTES_TO_BITS(sizeof(key_256)),
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Nx Crypto HMAC-SHA256 operation - NX_CRYPTO_HASH_UPDATE */
err = _nx_crypto_method_hmac_sha256_operation(NX_CRYPTO_HASH_UPDATE,
handler,
&crypto_method_hmac_sha256,
NX_CRYPTO_NULL,
0,
(UCHAR *) plain_256,
sizeof(plain_256),
NX_CRYPTO_NULL,
NX_CRYPTO_NULL,
0,
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Nx Crypto HMAC-SHA256 operation - NX_CRYPTO_HASH_CALCULATE */
err = _nx_crypto_method_hmac_sha256_operation(NX_CRYPTO_HASH_CALCULATE,
handler,
&crypto_method_hmac_sha256,
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
0,
NX_CRYPTO_NULL,
(UCHAR *) output,
sizeof(output),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
/* Ensure generated HMAC-SHA256 mac matches the expected mac */
err = (uint32_t) memcmp(output, secret_256, sizeof(secret_256));
assert(0 == err);
}