nRF5 SDK v15.0.0
Infineon OPTIGA™ Trust X Command Library

The Infineon OPTIGA™ Trust X Command Library provides a high-level API to access cryptographic and security-related functions of a discrete Infineon OPTIGA™ Trust X ("Trust X") hardware security module connected via I2C. The command library utilizes the Infineon I2C Protocol Stack Library to interface via I2C to the Trust X hardware module.

Note
The Infineon OPTIGA™ Trust X hardware security module must be acquired separately. For more information, visit Infineon.com - OPTIGA™ Trust X SLS 32AIA.
Warning
This module implements a preliminary high-level API to access a subset of Infineon OPTIGA™ Trust X features. This high-level API is an early evaluation version and subject to major changes in future releases.

Configuration

Device-specific configuration related to the Infineon I2C Protocol Stack can be configured in ifx_i2c_config.h.

Initialization of host library and device

To initialize the Trust X host library and hardware device, you must call two functions: optiga_init() and optiga_open_application().

The following code snippet shows how to initialize the Trust X host library and hardware device:

#include "optiga_command_library.h"
ret_code_t err_code;
uint16_t err_code = optiga_init();
if (err_code != IFX_I2C_STACK_SUCCESS)
{
// Handle error
}
uint16_t err_code = optiga_open_application();
if (err_code != IFX_I2C_STACK_SUCCESS)
{
// Handle error
}

Trust X commands

This section explains the most relevant command groups and commands supported by the command library.

Note
This documentation and the command library implementation cover only a subset of the functions supported by the device.

Random number generation

The random number generation (RNG) function optiga_get_random() retrieves a cryptographic-quality random number from a Trust X device. This function can be used as entropy source for various security schemes. The buffer to store the random number must be allocated by the application. The length of the random number ranges from 8 to 256 bytes.

The following code snippet shows how to retrieve 16 random bytes from Trust X:

#include "optiga_command_library.h"
ret_code_t err_code;
uint8_t rnd[16];
err_code = optiga_get_random(rnd, sizeof(rnd));
if (err_code != IFX_I2C_STACK_SUCCESS)
{
// Handle error
}

Reading data objects

The function optiga_get_data_object() allows to retrieve data objects from Trust X, for example, the public X.509 certificate stored in the Trust X device. The certificate and the contained public key can be used to verify a signature computed by the Trust X device. In addition, the receiver of the certificate can verify the chain of trust by validating the issuer of the certificate and the issuer's signature on the certificate. The buffer to hold the certificate is allocated inside the command library, and is only valid until the next call to the command library.

The following code snippet shows how to retrieve the Infineon device certificate pre-personalized on a Trust X device:

#include "optiga_command_library.h"
ret_code_t err_code;
uint8_t *p_cert;
uint16_t cert_len;
err_code = optiga_get_data_object(OID_INFINEON_CERTIFICATE, &p_cert, &cert_len);
if (err_code != IFX_I2C_STACK_SUCCESS)
{
// Handle error
}
if (p_cert[0] == 0xC0) // 0x30 = TLS identity tag
{
// Strip TLS certificate chain header from certificate chain
// Please refer to the official documentation for detailed information on public-key certificate data structures).
// Example TLS certificate header
// C0 01 CA 00 01 C7 00 01 C4 30 82 01 C0 30 82 ... end
// <- t1 -> <- va -> <- v1 -> <- X.509 cert --------->
p_cert += 9;
cert_len -= 9;
}
else if (p_cert[0] == 0x30) // 0xC0 = one-way authentication identity
{
// Pure ASN.1-coded certificate, no need to strip anything
}
else
{
// Not supported case, handle error
}
// Copy certificate into application memory to make it persistent
if (cert_len > PUBLIC_KEY_CERT_MAX_LEN)
{
// Not supported case, handle error
}
uint8_t cert[PUBLIC_KEY_CERT_MAX_LEN];
memcpy(cert, p_cert, cert_len);

ECDSA signature calculation and verification

The Trust X can calculate and verify ECDSA-based digital signatures using the optiga_calc_sign() and optiga_verify_signature() functions. Furthermore, the Trust X can conduct the hashing operation needed to compute or verify digital signatures, using optiga_calc_hash().

The following code snippet shows how to hash, sign, and verify a message using Trust X:

#include "optiga_command_library.h"
ret_code_t err_code;
// Calculate message digest (SHA-256) with Trust X:
uint8_t digest[OPTIGA_HASH_LEN_SHA256];
uint8_t msg[] = {'m', 'e', 's', 's', 'a', 'g', 'e'};
err_code = optiga_calc_hash(HASH_SHA256, msg, sizeof(msg), digest);
if (err_code != IFX_I2C_STACK_SUCCESS)
{
// Handle error and abort
}
// Sign (ECDSA) the digest with generated private key OID_DEVICE_PRIVATE_KEY_1 inside Trust X:
uint8_t *p_sig2;
uint8_t sig2_len;
err_code = optiga_calc_sign(OID_DEVICE_PRIVATE_KEY_1, digest, digest_len, &p_sig2, &sig2_len);
if (err_code != IFX_I2C_STACK_SUCCESS)
{
// Handle error and abort
}
// Copy Signature into application memory
uint8_t sig2[SIGNATURE_ECDSA_ECC_NIST_P256_MAX_LEN];
memcpy(sig2, p_sig2, sig2_len);
// Verify signature with Trust X using the generated public key:
err_code = optiga_verify_signature(ECC_NIST_P256, digest, digest_len, sig2, sig2_len, public_key, public_key_len);
if (err_code == IFX_I2C_STACK_SUCCESS)
{
// Signature successfully verified
}

Elliptic Curve (EC) private/public key generation

The Trust X can generate an EC key pair using optiga_generate_key_pair().

The following code snippet shows how to generate a private/public key pair and export the public key. The private key is stored in the data object slot for OID_DEVICE_PRIVATE_KEY_2. The public key is exported and returned to the application.

#include "optiga_command_library.h"
ret_code_t err_code;
uint8_t *p_public_key;
uint8_t public_key_len;
err_code = optiga_generate_key_pair(ECC_NIST_P256, OID_DEVICE_PRIVATE_KEY_2, &p_public_key, &public_key_len);
if (err_code != IFX_I2C_STACK_SUCCESS)
{
// Handle error and abort
}
// Copy public key into application memory
uint8_t public_key[public_key_len];
memcpy(public_key, p_public_key, public_key_len);

Documentation feedback | Developer Zone | Subscribe | Updated