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 |
RSIP-E51A | RA8M1, RA8D1, RA8T1 |
RSIP-E50D | T.B.D |
RSIP-E31A | T.B.D |
SCE9 | RA6M4, RA4M3, RA4M2, RA6M5 |
SCE7 | RA6M3, RA6M2, RA6M1, RA6T1 |
SCE5 | RA4W1, RA4M1 |
SCE5B | RA6T2 |
AES Engine | RA2A1, RA2E1, RA2E2, RA2L1 |
- 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
- SHA256 calculation
- SHA224 calculation
- MAC Operations
- HMAC with SHA224
- HMAC with SHA256
- AES
- Keybits - 128, 192, 256
- Encryption and Decryption.
- Chaining Modes: CBC, CTR, GCM mode
AES Chaining Mode | HW Acceleration |
CBC | Fully accelerated |
CTR | Fully accelerated |
GCM | Encrypt - Fully accelerated; Decrypt - Only GHASH and block cipher unit is HW accelerated |
CCM | Only block cipher unit is HW accelerated |
- Random number generation
- ECC
- ECDSA: Supported Curves - SECP384R1, SECP256R1.
- ECDH: Supported Curves - SECP384R1, SECP256R1.
- RSA
- Signature Generation - RSA 2048 (Plain or Wrapped private) key. (This can be used for decryption)
- Signature Verification - RSA 2048, RSA 3072 and RSA 4096 keys. (This can be used for encryption)
- Supported encoding scheme: PKCS1V15
This module provides SCE7, SCE9, RSIP-E51A, and RSIP-E50D hardware support for the following NetX Crypto operations:
- SHA256 calculation
- SHA224 calculation
- AES
- Keybits - 128, 192, 256
- Encryption and Decryption.
- Chaining Modes: CBC, CTR, GCM mode
AES Chaining Mode | HW Acceleration |
CBC | Fully accelerated |
CTR | Fully accelerated |
GCM | Only block cipher unit is HW accelerated |
CCM | Only block cipher unit is HW accelerated |
- ECC
- ECDSA: Supported Curves - SECP384R1, SECP256R1.
- ECDH: Supported Curves - SECP384R1, SECP256R1.
- RSA
- Signature Generation - RSA 2048 (Plain or Wrapped private) key. (This can be used for decryption)
- Signature Verification - RSA 2048. (This can be used for encryption)
- Supported encoding scheme: PKCS1V15
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:
Configuration | Options | Default | Description |
Standalone Usage |
-
Use Standalone Crypto Only
-
Use with TLS
| Use Standalone Crypto Only | Defines NX_CRYPTO_STANDALONE_ENABLE. |
Maximum RSA Modulus size (bits) |
| 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:
Configuration | Options | Default | Description |
Hardware Acceleration |
Hardware Acceleration > Hash |
SHA256/224 | MCU Specific Options | | Enables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_SHA256_ALT. |
Hardware Acceleration > Cipher |
AES | MCU Specific Options | | Enables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_AES_ALT |
Hardware Acceleration > Public Key Cryptography (PKC) |
Hardware Acceleration > Public Key Cryptography (PKC) > ECC |
ECC | MCU Specific Options | | Enables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_ECC_ALT |
ECDSA Scratch Buffer Size (Bytes) | Value must be an integer | 3016 | Sets value of NX_CRYPTO_ECDSA_SCRATCH_BUFFER_SIZE |
ECDH Scratch Buffer Size (Bytes) | Value must be an integer | 2464 | Sets value of NX_CRYPTO_ECDH_SCRATCH_BUFFER_SIZE |
Hardware Acceleration > Public Key Cryptography (PKC) > RSA |
RSA | MCU Specific Options | | Enables/Disables RSA HW support |
RSA 1024 (HW) | MCU Specific Options | | Enables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_1024_ALT to allow HW support |
RSA 2048 (HW) | MCU Specific Options | | Enables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_2048_ALT to allow HW support |
RSA 3072 Verify/Encryption (HW) | MCU Specific Options | | Enables NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_3072_ALT to allow HW support |
RSA 4096 Verify/Encryption (HW) | MCU Specific Options | | Enables RSA NETX_SECURE_CRYPTO_NX_CRYPTO_METHODS_RSA_4096_ALT to allow HW support |
RSA Scratch Buffer Size (Bytes) | MCU Specific Options | | Sets value of NX_CRYPTO_RSA_SCRATCH_BUFFER_SIZE |
TRNG |
| 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_1024_ALT | Signature Generation / Signature Verification (Encryption / Decryption) |
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:
- Uncompressed public key is of the form (0x04 || Qx || Qy). Refer Section 2.2. Subject Public Key under RFC5480
- Formatted public key is of the form (Key Info (4 bytes) || Qx || Qy || Key Info (16 bytes)). This is the key which is used internally by SCE peripheral.
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
- Only little endian mode is supported.
- RSA CRT keys are not supported.
- ECJPAKE related operations are unsupported for NIST 224, 256 and 384 bit curves when HW ECC is eanbled.
Examples
Initialization Example
This example shows how to initialize the HW crypto engine. This step must be performed before any crypto algorithm is used.
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;
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
err = _nx_crypto_method_sha256_init(&crypto_method_sha256, NX_CRYPTO_NULL, 0, &handler, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
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);
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);
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);
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;
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
};
const uint8_t NIST_AES256_CBC_iv[] =
{
0xbd, 0x41, 0x6c, 0xb3, 0xb9, 0x89, 0x22, 0x28, 0xd8, 0xf1, 0xdf, 0x57, 0x56, 0x92, 0xe4, 0xd0
};
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
};
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;
uint8_t generated_ciphertext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
uint8_t generated_plaintext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
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);
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);
err = (uint32_t) memcmp(generated_ciphertext, NIST_AES256_CBC_ciphertext, sizeof(generated_ciphertext));
assert(0 == err);
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);
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;
static const uint8_t key_gcm_128[] =
{
0x83, 0xF9, 0xD9, 0x7D, 0x4A, 0xB7, 0x59, 0xFD, 0xDC, 0xC3, 0xEF, 0x54, 0xA0, 0xE2, 0xA8, 0xEC
};
static const uint8_t iv_gcm_128[] =
{
0x01, 0xCF
};
static const uint8_t plain_gcm_128[] =
{
0x77, 0xE6, 0x32, 0x9C, 0xF9, 0x42, 0x4F, 0x71, 0xC8, 0x08, 0xDF, 0x91, 0x70, 0xBF, 0xD2, 0x98
};
static const uint8_t aad_gcm_128[] =
{
0x6D, 0xD4, 0x9E, 0xAE, 0xB4, 0x10, 0x3D, 0xAC, 0x8F, 0x97, 0xE3, 0x23, 0x49, 0x46, 0xDD, 0x2D
};
static const uint8_t secret_gcm_128[] =
{
0x50, 0xDE, 0x86, 0xA7, 0xA9, 0x2A, 0x8A, 0x5E, 0xA3, 0x3D, 0xB5, 0x69, 0x6B, 0x96, 0xCD, 0x77,
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;
uint8_t generated_ciphertext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
uint8_t generated_plaintext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
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);
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);
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);
err = (uint32_t) memcmp(&generated_ciphertext[sizeof(plain_gcm_128)], &secret_gcm_128[sizeof(plain_gcm_128)], 16U);
assert(0 == err);
err = (uint32_t) memcmp(generated_ciphertext, secret_gcm_128, sizeof(secret_gcm_128));
assert(0 == err);
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);
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),
(uint8_t *) iv_gcm_128,
generated_plaintext,
sizeof(generated_plaintext),
metadata,
metadata_size,
NX_CRYPTO_NULL,
NX_CRYPTO_NULL);
assert(NX_CRYPTO_SUCCESS == err);
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,
NX_CRYPTO_AES_256_KEY_LEN_IN_BITS,
NX_CRYPTO_AES_IV_LEN_IN_BITS,
0,
(NX_CRYPTO_AES_BLOCK_SIZE_IN_BITS >> 3),
sizeof(NX_CRYPTO_AES),
_nx_crypto_method_aes_init,
_nx_crypto_method_aes_cleanup,
_nx_crypto_method_aes_ctr_operation
};
const uint8_t key_ctr_256[] =
{
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,
0x3B, 0xF0, 0xD1, 0x58,
};
const uint8_t iv_ctr_256[] =
{
0xA1, 0xA3, 0x17, 0x04, 0xC8, 0xB7, 0xE1, 0x6C,
};
const uint8_t plain_ctr_256[] =
{
0x98, 0x1F, 0xA3, 0x32, 0x22, 0xC5, 0x45, 0x10, 0x17, 0x53, 0x01, 0x55, 0xA4, 0xBF, 0x7F, 0x29,
};
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;
uint8_t generated_ciphertext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
uint8_t generated_plaintext[3U * NX_CRYPTO_AES_BLOCK_SIZE] = {0};
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);
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);
err = (uint32_t) memcmp(generated_ciphertext, secret_ctr_256, sizeof(secret_ctr_256));
assert(0 == err);
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);
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,
0x07, 0x54, 0x0d, 0xb9, 0xa8, 0x8a, 0x8b, 0xc2, 0xd5, 0xe9, 0x38, 0x4b, 0xf9, 0xe5, 0x43, 0x5a
};
const uint8_t ECC_SECP256R1PublicKeydata[] =
{
0x04,
0x5b, 0xba, 0xd4, 0x2e, 0xb5, 0xc1, 0x07, 0xf2, 0x0e, 0x01, 0x95, 0x42, 0x6e, 0x90, 0xb8, 0x4e,
0xe9, 0x5a, 0xa1, 0xe8, 0x4c, 0x6c, 0xa5, 0x32, 0x3c, 0xf3, 0x09, 0xf5, 0xff, 0x8b, 0x3d, 0x26,
0xb6, 0x88, 0xc1, 0xdb, 0x02, 0xaf, 0x4d, 0xa5, 0x0e, 0x73, 0x61, 0x96, 0xb3, 0x59, 0x95, 0x6f,
0x5e, 0xc9, 0xa1, 0xf9, 0xb7, 0xb3, 0xb6, 0xdf, 0x54, 0x82, 0x79, 0xe3, 0xb6, 0x4e, 0xac, 0xb6
};
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};
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
err = _nx_crypto_method_ecdsa_init(&crypto_method_ecdsa, NX_CRYPTO_NULL, 0, &handler, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
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);
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);
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;
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;
const uint8_t ECC_SECP256R1Keydata_ecdh[] =
{
0x59, 0x13, 0x7e, 0x38, 0x15, 0x23, 0x50, 0xb1, 0x95, 0xc9, 0x71, 0x8d, 0x39, 0x67, 0x3d, 0x51,
0x98, 0x38, 0x05, 0x5a, 0xd9, 0x08, 0xdd, 0x47, 0x57, 0x15, 0x2f, 0xd8, 0x25, 0x5c, 0x09, 0xbf,
};
const uint8_t ECC_SECP256R1PublicKeydata_ecdh[] =
{
0x04,
0xa8,0xc5, 0xfd, 0xce, 0x8b, 0x62, 0xc5, 0xad, 0xa5, 0x98, 0xf1, 0x41, 0xad, 0xb3, 0xb2, 0x6c,
0xf2,0x54, 0xc2, 0x80, 0xb2, 0x85, 0x7a, 0x63, 0xd2, 0xad, 0x78, 0x3a, 0x73, 0x11, 0x5f, 0x6b,
0x80,0x6e, 0x1a, 0xaf, 0xec, 0x4a, 0xf8, 0x0a, 0x0d, 0x78, 0x6b, 0x3d, 0xe4, 0x53, 0x75, 0xb5,
0x17,0xa7, 0xe5, 0xb5, 0x1f, 0xfb, 0x2c, 0x35, 0x65, 0x37, 0xc9, 0xe6, 0xef, 0x22, 0x7d, 0x4a,
};
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;
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
err = _nx_crypto_method_ecdh_init(&crypto_method_ecdh, NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
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);
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;
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);
err = _nx_crypto_method_ecdh_init(&crypto_method_ecdh, NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, metadata, metadata_size);
assert(NX_CRYPTO_SUCCESS == err);
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);
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);
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);
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;
const uint8_t public_e[] =
{
0x00, 0x01, 0x00, 0x01,
};
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,
};
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,
};
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,
};
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};
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
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);
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;
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,
};
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,
};
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;
err = nx_crypto_initialize();
assert(NX_CRYPTO_SUCCESS == err);
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);
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);
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);
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);
err = (uint32_t) memcmp(output, secret_256, sizeof(secret_256));
assert(0 == err);
}