RSE Cryptography
This document provides details of the cryptography performed by the Runtime Security Engine (RSE).
Its primary use is as a guide to a software developer who is porting the reference RSE software to an RSE platform which does not use the reference cryptographic accelerator. To facilitate this, it contains:
A list of algorithms required to be supported at each stage of RSE boot
A list of APIs which must be reimplemented if the cryptographic accelerator is replaced, and the required semantics of those implementations.
A list of functions which must be replaced if the cryptographic accelerator is replaced, and the required semantics of those replacements.
A guide to the required level of side-channel protection a replacement cryptographic accelerator and driver must provide in order to maintain RSE security.
Some basic information about how different cryptographic accelerators are integrated into the RSE hardware, to aid in the software integration
BL1
Currently, the BL1 bootloader calls into the RSE crypto accelerator via a combination of three separate APIs:
The BL1 crypto api (as defined in
bl1/bl1_1/shared_lib/interface/crypto.h),The cc3xx
low_level_driverAPI (as defined inplatform/ext/target/arm/drivers/cc3xx/low_level_driver/include/)
This makes it difficult to substitute the cc3xx in the RSE integration layer, requiring some rewriting of the ROM code. This is a known limitation, and is planned to be fixed by using the (thin) PSA crypto API in BL1 in the medium term.
BL1 Bootloader usage
BL1_1
BL1_1 uses a hash function to validate the BL1_2 bootloader image in OTP against a hash stored in OTP. This hash is then recorded as a boot measurement for use in attestation.
The hash algorithm used will be one of the following: [1]
SHA256
SHA384
BL1_2
BL1_2 MAY use a symmetric decryption function to decrypt the BL2 image. This decryption MAY happen in-place.
The decryption algorithm will be one of the following: [2]
AES CTR
BL1_2 uses an asymmetric algorithm to validate the image. This algorithm will be one of the following: [3]
LMS
ECDSA
If the algorithm used in LMS, it will use the LMS_SHA256_M32_H10 and
LMOTS_SHA256_N32_W8 parameter sets.
If the algorithm used is ECDSA, the curve/hash pair used will be one of the following:
NIST SECP-256-r1 with SHA256
NIST SECP-384-r1 with SHA384
Provisioning usage
If RSE_SYMMETRIC_PROVISIONING is enabled, BL1_1 uses a symmetric
AEAD algorithm to decrypt and verify the provisioning blob. This
algorithm will be one of the following:
The decryption algorithm will be one of the following: [4]
AES CCM
If RSE_SYMMETRIC_PROVISIONING is not enabled, BL1_1 uses an
asymmetric algorithm to verify the blob. This algorithm will be one of
the following: [5]
ECSDA
If the algorithm used is ECDSA, the curve/hash pair used will be one of the following:
NIST SECP-256-r1 with SHA256
NIST SECP-384-r1 with SHA384
If RSE_SYMMETRIC_PROVISIONING is not enabled, BL1_1 may use a
symmetric algorithm to decrypt the blob. This algorithm will be one of
the following: [6]
AES CCM
The decryption algorithm will be one of the following: [7]
AES CTR
Usage of the BL1 crypto API
All functions in the BL1 crypto API MUST be implemented. The semantics for the implementation must match the semantics described in the BL1 crypto API documentation. The implementations MUST include the required level of side-channel countermeasures
Usage of the cc3xx low_level_driver API
The following cc3xx functions are directly called. If the integration uses a different cryptographic accelerator, the functions MUST be replaced. The semantics for the replacement calls must match the semantics described in the cc3xx ``low_level_driver` API documentation <#cc3xx-low-level-driver-api>`__
boot_hal_bl1_1.c
cc3xx_lowlevel_initcc3xx_lowlevel_dma_remap_region_initcc3xx_lowlevel_dma_burst_restricted_region_init
boot_hal_bl1_2.c
cc3xx_lowlevel_uninit
rse_kmu_keys.c
cc3xx_lowlevel_kdf_cmac
rse_provisioning_blob_handler.c
cc3xx_lowlevel_aes_initcc3xx_lowlevel_aes_set_tag_lencc3xx_lowlevel_aes_set_data_lencc3xx_lowlevel_aes_update_authed_datacc3xx_lowlevel_aes_updatecc3xx_lowlevel_aes_set_output_buffercc3xx_lowlevel_aes_finish
BL2
The BL2 bootloader calls into the RSE crypto accelerator using only the RSE Cryptoprocessor Driver Interface (also referred to as the PSA driver API).
BL2 Bootloader usage
BL2 uses an asymmetric algorithm to validate each image. This algorithm will be one of the following: [8]
ECDSA
If the algorithm used is ECDSA, the curve/hash pair used will be one of the following:
NIST SECP-256-r1 with SHA256
NIST SECP-384-r1 with SHA384
BL2 may use a symmetric algorithm to decrypt each image. This algorithm will be one of the following: [9]
AES CTR
The key used in this symmetric decryption will be included in the image metadata. To secure the key in transport, a key wrapping algorithm will be used. This algorithm will be one of the following: [10]
AES KW
BL2 usage of the PSA driver API
The following PSA driver API functions are required. If the integration
uses a different cryptographic accelerator, it MUST have a PSA driver
API driver which implements the entry points required for these
functions. The semantics of the entry points MUST be as described in the
PSA driver API.
Entry points my be integrated either by patching the
psa_crypto_driver_wrappers.h, or by using the
.json description file.
Note that it is valid for the driver to return PSA_ERROR_NOT_SUPPORTED for
these entry points, as long as that function isn’t required for any RSE
usecases. The implementations MUST include the required level of side-channel
countermeasures
thin_psa_crypto_core.c
psa_driver_wrapper_initpsa_driver_wrapper_freepsa_driver_wrapper_hash_abortpsa_driver_wrapper_hash_computepsa_driver_wrapper_hash_finishpsa_driver_wrapper_hash_setuppsa_driver_wrapper_hash_updatepsa_driver_wrapper_verify_hash
Runtime Crypto partition
The Runtime Cryptography partition provides cryptographic services to other secure partitions within the RSE, and if configured callers outside the RSE. These services are provided via the PSA crypto api, and the services that RSE provides may vary depending on the usecase.
Default cc3xx driver support
The cc3xx driver supports the following algorithms:
Hash
PSA_ALG_SHA_256
MAC
PSA_KEY_TYPE_AESPSA_ALG_CMAC
Cipher
PSA_KEY_TYPE_AESPSA_ALG_ECBPSA_ALG_CTRPSA_ALG_CBC
AEAD
PSA_KEY_TYPE_AESPSA_ALG_CCM
Key derivation
PSA_KEY_TYPE_AESPSA_ALG_SP800_108_COUNTER_CMAC
Asymmetric Signature
PSA_ALG_ECDSAPSA_ECC_FAMILY_SECP
Key agreement
PSA_ALG_ECDHPSA_ECC_FAMILY_SECP
Additionally, PSA_ALG_SHA_384 is supported in a software
implementation, in order to support ECDSA signing with the
SECP_384_R1 curve.
Runtime usage of the PSA driver API
The following PSA driver API functions are required. If the integration
uses a different cryptographic accelerator, it MUST have a PSA driver
API driver which implements the entry points required for these
functions. The semantics of the entry points MUST be as described in the
PSA driver API.
Entry points my be integrated either by patching the
psa_crypto_driver_wrappers.h, or by using the
.json description file.
Note that it is valid for the driver to return PSA_ERROR_NOT_SUPPORTED for
these entry points, as long as that function isn’t required for any RSE
usecases. The implementations MUST include the required level of side-channel
countermeasures
psa_crypto_driver_wrappers.c
psa_driver_wrapper_initpsa_driver_wrapper_freepsa_driver_wrapper_sign_messagepsa_driver_wrapper_verify_messagepsa_driver_wrapper_sign_hashpsa_driver_wrapper_verify_hashpsa_driver_wrapper_generate_keypsa_driver_wrapper_cipher_encryptpsa_driver_wrapper_cipher_decryptpsa_driver_wrapper_cipher_encrypt_setuppsa_driver_wrapper_cipher_decrypt_setuppsa_driver_wrapper_cipher_set_ivpsa_driver_wrapper_cipher_updatepsa_driver_wrapper_cipher_finishpsa_driver_wrapper_cipher_abortpsa_driver_wrapper_hash_computepsa_driver_wrapper_hash_abortpsa_driver_wrapper_hash_finishpsa_driver_wrapper_hash_setuppsa_driver_wrapper_hash_updatepsa_driver_wrapper_hash_clonepsa_driver_wrapper_aead_encryptpsa_driver_wrapper_aead_decryptpsa_driver_wrapper_aead_encrypt_setuppsa_driver_wrapper_aead_decrypt_setuppsa_driver_wrapper_aead_set_noncepsa_driver_wrapper_aead_set_lengthspsa_driver_wrapper_aead_update_adpsa_driver_wrapper_aead_updatepsa_driver_wrapper_aead_finishpsa_driver_wrapper_aead_verifypsa_driver_wrapper_aead_abortpsa_driver_wrapper_mac_computepsa_driver_wrapper_mac_sign_setuppsa_driver_wrapper_mac_verify_setuppsa_driver_wrapper_mac_updatepsa_driver_wrapper_mac_updatepsa_driver_wrapper_mac_sign_finishpsa_driver_wrapper_mac_verify_finishpsa_driver_wrapper_mac_abortpsa_driver_wrapper_asymmetric_encryptpsa_driver_wrapper_asymmetric_decryptpsa_driver_wrapper_key_agreement
psa_crypto_driver_wrappers_no_static.c
psa_driver_wrapper_export_public_key
RSE Cryptographic hardware
Diagram
Figure 2: RSE hardware diagram, with the cryptographic components colorized
RSE Cryptographic accelerator
The RSE cryptographic accelerator is within the RSE integration layer, and therefore is not included with the base RSE subsystem. The integrator MUST integrate an RSE cryptographic accelerator into the RSE integration layer.
The RSE MUST contain a hardware cryptographic accelerator.
The cryptographic engine MUST support acceleration of AES-256-CTR. The AES acceleration MUST include one or more registers with both write-only and write-once semantics which are used to input the key.
The cryptographic accelerator MUST support acceleration of one of the following:
AES-256-CMAC
HKDF
SP800-108-CTR KDF with a PRF with security strength of at least 256 bits.
Whichever is chosen MUST include one or more registers with both write-only and write-once semantics which are used to input the input key for the operation.
The cryptographic accelerator SHOULD support acceleration of the following hash functions:
SHA256
SHA384
The cryptographic accelerator SHOULD support acceleration of one of the following:
SHA256 hash-chaining
LMS verification
The cryptographic accelerator MUST support acceleration of all of the following:
ECDSA with the NIST SECP_256_R1 curve
ECDSA with the NIST SECP_384_R1 curve
The ECDSA acceleration SHOULD include one or more registers with both write-only and write-once semantics which are used to input the input key for the operation.
The cryptographic accelerator SHOULD support acceleration ML-DSA. The ML-DSA acceleration SHOULD include one or more registers with both write-only and write-once semantics which are used to input the input key for the operation.
Key Management Unit (KMU)
The RSE KMU stores keys in protected hardware registers. These registers are initially write-once read/write, and can then be locked and then become neither readable nor writable.
The KMU locking operation requires that the following are configured before locking can occur:
The export address
The export configuration
The key size
The KMU supports 128, 192 and 256 bit keys. RSE symmetric keys MUST be 256 bits.
Once a KMU register is locked, it can be triggered to be exported. The KMU writes the key to the specified address. Depending on the export configuration, this can be:
Multiple writes to a single key register
Writes a set of contiguous key registers
The export register MUST be have both write-only and write-once semantics.
The KMU also has a set of “Hardware” keys which are input into the KMU from the LCM when the LCM is released from reset. Hardware keyslots are identical to locked software keyslots. The number of hardware keyslots, export address, configuration and key size are configured by RSE RTL parameters.
A keyslot can be “invalidated”, erasing the key material and unlocking the slot to be reused. Note that Hardware keyslots cannot be reused after being invalidated. Note that invalidation does not permanently destroy hardware keys, as they are still stored in the OTP; after a reset the LCM will once again export them to the KMU ready to be used.
The integrator MUST prevent bus transactions initiated by the KMU from being read by any other entity in the system. The recommended integration is a private bus between the KMU and the cryptographic accelerator.
The KMU supports masking transactions with a random mask to mitigate power analysis attacks in transit. Cryptographic accelerators MUST support unmasking the KMU transactions.
Life Cycle Manager (LCM)
The LCM performs two functions in the hardware cryptographic flows.
It performs access control on the OTP memory which contains the Hardware keys. The Hardware key memory is not readable except under the following circumstances.
LCS == LCM_LCS_CM && LCM_SP_ENABLE == true:
HUKis Read/WriteGUKis Read/WriteKCE_CMis Read/WriteKP_CMis Read/Write
LCS == LCM_LCS_DM && LCM_SP_ENABLE == true:
KCE_DMis Read/WriteKP_DMis Read/Write
LCS == LCM_LCS_RMA:
HUKis Write-onlyGUKis Write-onlyKCE_CMis Write-onlyKP_CMis Write-onlyKCE_DMis Write-onlyKP_DMis Write-only
The second function the LCM performs is to export the hardware keys into the KMU hardware keyslots. The mapping between the keys and keyslots is detailed below.
Key |
KMU slot ID |
|---|---|
|
0 |
|
1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
Keys in OTP memory are protected from tampering by a zero-count. The LCM hardware performs a chech between the key and the zero-count on every reset, and if the zero counts do not match the key is not exported to the KMU.
Security strength requirements
All keys used in RSE MUST have a 256-bit or greater security strength.
Side-channel countermeasures
Secret handling countermeasures
Any Bus parity or DCLS alarms MUST be connected to SAM alarms.
Fault Injection countermeasures
Secrets used for encryption or signing MUST be copied only by bus initiators protected by Dual-Core LockStep (DCLS).
Secrets used for encryption or signing MUST only be copied over busses protected by partity or other error-correction hardware.
Secrets used for decryption or verification MAY be protected in the same way.
Secret operations SHOULD use software fault injection countermeasures.
Power and EM side-channel countermeasures
Secrets MUST be copied in the largest block possible.
The order of the block copies in a secret copy MUST be randomized.
Secrets copies SHOULD NOT include intermediate copies.
Timing side-channel countermeasures
Secrets MUST be compared by constant-time functions.
Secrets MUST be copied by constant-time functions.
AES countermeasures
AES hardware MUST connect any hardware countermeasure alarms to the SAM.
Fault Injection countermeasures
AES implementations MUST implement one of the following (which can both either be on a per-round or a per-operation basis):
Double-encrypt and compare results
Encrypt-then-decrypt and compare to plaintext
AES implememtations SHOULD use software fault injection countermeasures within the driver.
Power and EM side-channel countermeasures
AES implementations must include dummy rounds, inserted at random into the encryption and decryption operations.
AES implementations must include masking of intermediate values.
If double-encrypt and compare is implemented, the two operations MUST use different masks.
Timing side-channel countermeasures
AES operations MUST be constant-time
KDF countermeasures
Key derivation hardware MUST connect any hardware countermeasure alarms to the SAM.
Fault Injection countermeasures
KDF implementations MUST implement Double-encrypt and compare results (which can both either be on a per-round or a per-operation basis)
KDF implememtations SHOULD use software fault injection countermeasures within the driver.
Power and EM side-channel countermeasures
KDF implementations must include dummy rounds, inserted at random into the encryption and decryption operations.
KDF implementations must include masking of intermediate values.
If double-encrypt and compare is implemented, the two operations MUST use different masks.
Timing side-channel countermeasures
KDF operations MUST be constant-time
ECDSA countermeasures
ECDSA hardware MUST connect any hardware countermeasure alarms to the SAM.
Fault Injection countermeasures
ECDSA implementations MUST include integrity checks on in-use curve parameters
ECDSA implementations MUST include checks that any input, output or intermediate points are valid curve points.
ECDSA implememtations SHOULD use software fault injection countermeasures within the driver.
Power and EM side-channel countermeasures
ECDSA sign implementations MUST use projective coordinates with randomized
zcoordinatesECDSA sign implementations MUST use lookup tables to perform windowed point multiplication.
ECDSA sign implementations MUST perform scalar splitting
ECDSA sign implementations MUST perform scalar blinding
Timing side-channel countermeasures
ECDSA sign operations MUST be constant-time
Software fault injection countermeasures
The following software fault injection countermeasures SHOULD be used in security-critical code which is vulnerable to fault injection, for example, branches into lower-security boot paths, setup of security hardware, or cryptographic accelerator drivers.
Critical variables SHOULD use high hamming-weights
Return values SHOULD use high hamming-weights
Critical checks SHOULD be performed multiple times
Random delays SHOULD be inserted before critical operations
These SHOULD be implemented using the fih.h header library: * Any
variables used for implementing branches SHOULD be of type fih_int
* Any branches should use fih_eq or fih_not_eq * Function
calls SHOULD use FIH_CALL. Any function called by FIH_CALL MUST
return using FIH_RET * Additional delays MAY be inserted using
fih_delay
The fih.h library MUST be configured with the following options:
TFM_FIH_PROFILE_ONFIH_ENABLE_DELAY
It MAY be configured with additional options.
BL1 crypto API
This section documents the semantics of various functions in the BL1 crypto API.
crypto.h
bl1_hash_compute
fih_int bl1_hash_compute(enum tfm_bl1_hash_alg_t alg,
const uint8_t *data,
size_t data_length,
uint8_t *hash,
size_t hash_length,
size_t *hash_size);
This function computes a hash in a single call. All data to be hashed must be in a contiguous buffer and be available when this function is called.
This function MUST compute a hash of the data at the data pointer of
size data_length.
The hash MUST be copied to the hash pointer, and must not exceed
hash_length in size. If the calculated hash is larger that
hash_length, and error MUST be returned. The value at the
hash_size pointer MUST be set to the size of the hash, except in the
pointer is NULL in which case it MUST NOT be set.
If the alg argument is TFM_BL1_HASH_ALG_SHA256 then the hash
MUST be computed using the SHA-256 hash
algorithm
If the alg argument is TFM_BL1_HASH_ALG_SHA384 then the hash
MUST be computed using the SHA-384 hash
algorithm
If the alg argument is any other value, an error MUST be returned.
The implementation MUST pass all NIST CAVP vectors for hashing byte-oriented messages
The implementation SHOULD pass all NIST CAVP vectors for hashing bit-oriented messages
The implementation MAY include side-channel protections. If side-channel protections are not included, secret data MUST NOT be input into this function and This function MUST NOT be used to implement HKDF.
bl1_hash_init
fih_int bl1_hash_init(enum tfm_bl1_hash_alg_t alg);
This function initializes a multi-part hashing operation, ready for other functions to be called to input the data.
Before this function is called, the bl1_hash_update function MUST
NOT be called.
If the alg argument is TFM_BL1_HASH_ALG_SHA256 then the hash
operation MUST use the SHA-256 hash
algorithm
If the alg argument is TFM_BL1_HASH_ALG_SHA384 then the hash
operation MUST use the SHA-384 hash
algorithm
If the alg argument is any other value, an error MUST be returned.
This function does not include any sort of state object, so hash
operations cannot be interleaved. If bl1_hash_init has already been
called, and bl1_hash_finish has not been called to finish the
operation, bl1_hash_init MUST NOT be called.
bl1_hash_update
fih_int bl1_hash_update(const uint8_t *data,
size_t data_length);
This function submits input data to be hashed. It processes the data according to the initialized hash configuration.
This function MUST input into the hash operation the data at the
data pointer of size data_length.
bl1_hash_finish
fih_int bl1_hash_finish(uint8_t *hash,
size_t hash_length,
size_t *hash_size);
This function finalizes the hash operation and outputs the hash value.
The hash MUST be copied to the hash pointer, and must not exceed
hash_length in size. If the calculated hash is larger that
hash_length, and error MUST be returned. The value at the
hash_size pointer MUST be set to the size of the hash, except in the
pointer is NULL in which case it MUST NOT be set.
This function MUST NOT be called if bl1_hash_init has not been
called.
bl1_aes_256_ctr_decrypt
fih_int bl1_aes_256_ctr_decrypt(enum tfm_bl1_key_id_t key_id,
const uint8_t *key_material,
uint8_t *counter,
const uint8_t *ciphertext,
size_t ciphertext_length,
uint8_t *plaintext);
This function computes an AES-CTR decryption with a 256 bit key in a single call. All data to be decrypted must be in a contiguous buffer and be available when this function is called.
This function MUST decrypt the data at the ciphertext pointer of
size ciphertext_length.
The decrypted data MUST be output to the plaintext pointer, and must
be exactly ciphertext_length in size.
If the key_id is TFM_BL1_KEY_HUK, then KMU_HW_SLOT_HUK MUST
be used in the operation, by the mechanism of being exported from the
KMU directly to the cryptographic accelerator. If this key slot in the
KMU is not valid, this operation MUST return an error. Any key material
passed in key_material MUST be ignored.
If the key_id is TFM_BL1_KEY_GUK, then KMU_HW_SLOT_GUK MUST
be used in the operation, by the mechanism of being exported from the
KMU directly to the cryptographic accelerator. If this key slot in the
KMU is not valid, this operation MUST return an error. Any key material
passed in key_material MUST be ignored.
If the key_id is TFM_BL1_KEY_BL2_ENCRYPTION, then
RSE_KMU_SLOT_CM_IMAGE_ENCRYPTION_KEY MUST be used in the operation,
by the mechanism of being exported from the KMU directly to the
cryptographic accelerator. If this key slot in the KMU is not valid,
this operation MUST return an error. Any key material passed in
key_material MUST be ignored.
If the key_id is TFM_BL1_KEY_USER, then the key passed in the
key_material argument MUST be used in the operation. The key_id
pointer MUST point to a buffer of at least 32 bytes (256 bits) in size.
The key input copying MUST implement the required side-channel
protections for Secret Handling.
If the key_id is any other value, an error MUST be returned.
The implementation MUST pass all NIST CAVP vectors for AES Known-Answer Tests where the key length is 256 bits and the mode is CTR.
This function MUST implement the required side-channel protections for AES.
bl1_derive_key
fih_int bl1_derive_key(enum tfm_bl1_key_id_t key_id, const uint8_t *label,
size_t label_length, const uint8_t *context,
size_t context_length, uint32_t *output_key,
size_t output_length);
This function derives an unstructured (symmetric) key from an unstructured input key.
This function MUST implement either:
HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as per RFC5869
If this is chosen, the underlying hash function and/or the hardware-accelerated HKDF implementation MUST implement the required side-channel protections for Key Derivation.
If this is chosen, the cryptographic accelerator MUST contain a key register with write-only and write-once semantics to which the KMU can export keys for use in the hardware-accelerated HKDF operation only.
Counter Mode key derivation with AES-CMAC as the chosen pseudorandom function (PRF) as per NIST SP800-108 This function MUST implement the required level of side-channel security
If this is chosen, the underlying AES implementation and/or the hardware-accelerated SP800-108-CTR-AES-CMAC implementation MUST implement the required side-channel protections for Key Derivation.
This function MUST use the data at the label pointer of size
label_length as the label in the derivation operation.
This function MUST use the data at the context pointer of size
context_length as the context in the derivation operation.
This function MUST derive at key using the chosen KDF of the size
output_size bytes, and output it to the buffer pointed to by
output_key. Key output copying MUST implement the required
side-channel protections for Secret
Handling.
This function MUST write the output key using exactly 4-byte sized
writes if the output_size is 4 byte aligned and the output_key
pointer is 4 byte aligned.
This function MUST support output_size == 32 and
output_size == 48. It SHOULD support output_size == 16. It MAY
support other output sizes.
If the key_id is TFM_BL1_KEY_HUK, then KMU_HW_SLOT_HUK MUST
be used in the operation, by the mechanism of being exported from the
KMU directly to the cryptographic accelerator. If this key slot in the
KMU is not valid, this operation MUST return an error.
If the key_id is TFM_BL1_KEY_GUK, then KMU_HW_SLOT_GUK MUST
be used in the operation, by the mechanism of being exported from the
KMU directly to the cryptographic accelerator. If this key slot in the
KMU is not valid, this operation MUST return an error.
If the key_id is TFM_BL1_KEY_BL2_ENCRYPTION, then
RSE_KMU_SLOT_CM_IMAGE_ENCRYPTION_KEY MUST be used in the operation,
by the mechanism of being exported from the KMU directly to the
cryptographic accelerator. If this key slot in the KMU is not valid,
this operation MUST return an error.
If the key_id is any other value, an error MUST be returned.
This function MUST produce identical results to any KDF algorithms used offline to generate keys, for example, the BL2 encryption key.
bl1_ecc_derive_key
fih_int bl1_ecc_derive_key(enum tfm_bl1_ecdsa_curve_t curve, enum tfm_bl1_key_id_t key_id,
const uint8_t *label, size_t label_length,
const uint8_t *context, size_t context_length,
uint32_t *output_key, size_t output_size);
This function derives a structured ECDSA private key from an unstructured key.
This function MUST implement either:
HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as per RFC5869 as the DRBG used to implement ECDSA key pair generation as per FIPS 168-5 (appendix A.2)
If this is chosen, the underlying hash function and/or the hardware-accelerated HKDF implementation MUST implement MUST implement the required side-channel protections for Key Derivation.
If this is chosen, the cryptographic accelerator MUST contain a key register with write-only and write-once semantics to which the KMU can export keys for use in the hardware-accelerated HKDF operation only.
Counter Mode key derivation with AES-CMAC as the chosen pseudorandom function (PRF) as per NIST SP800-108 as the DRBG used to implement ECDSA key pair generation as per FIPS 168-5 (appendix A.2) This function MUST implement the required level of side-channel security
If this is chosen, the underlying AES implementation and/or the hardware-accelerated SP800-108-CTR-AES-CMAC implementation MUST implement the required side-channel protections for Key Derivation.
Hardware-accelerated ECDSA key derivation compliant with FIPS 168-5
If this is chosen, the cryptographic accelerator MUST contain a key register with write-only and write-once semantics to which the KMU can export keys for use in the hardware-accelerated ECDSA derivation operation only.
This function MUST derive at key using the chosen KDF of the size
output_size bytes, and output it to the buffer pointed to by
output_key. Key output copying MUST implement the required
side-channel protections for Secret
Handling.
If the curve argument is TFM_BL1_CURVE_P256 then the value
output to output_key MUST be a valid private key for the NIST
SECP256R1
curve
If the curve argument is TFM_BL1_CURVE_P384 then the value
output to output_key MUST be a valid private key for the NIST
SECP384R1
curve
The private key output to output_key must be in [11] format
If the curve argument is any other value, an error MUST be returned.
This function MUST use the data at the label pointer of size
label_length as the label in the derivation operation.
This function MUST use the data at the context pointer of size
context_length as the context in the derivation operation.
This function MUST write the output key using exactly 4-byte sized
writes if the output_size is 4 byte aligned and the output_key
pointer is 4 byte aligned.
If the key_id is TFM_BL1_KEY_HUK, then KMU_HW_SLOT_HUK MUST
be used in the operation, by the mechanism of being exported from the
KMU directly to the cryptographic accelerator. If this key slot in the
KMU is not valid, this operation MUST return an error.
If the key_id is TFM_BL1_KEY_GUK, then KMU_HW_SLOT_GUK MUST
be used in the operation, by the mechanism of being exported from the
KMU directly to the cryptographic accelerator. If this key slot in the
KMU is not valid, this operation MUST return an error.
If the key_id is any other value, an error MUST be returned.
This function MUST produce identical results to any KDF algorithms used offline to generate keys, for example, the Attestation key.
bl1_ecdsa_verify
fih_int bl1_ecdsa_verify(enum tfm_bl1_ecdsa_curve_t curve,
uint8_t *key, size_t key_size,
const uint8_t *hash,
size_t hash_length,
const uint8_t *signature,
size_t signature_size);
This function verifies an ECDSA signature over a hash.
This function MUST use the data at the key pointer of size
key_size as the ECDSA key. If key_size is odd, then the first
byte must be 0x04 and must be discarded. The remaining key
buffer MUST be used as the public key point in the format x || y
where x and y are raw ECDSA coordinates. [12]
This function MUST use the data at the hash pointer of size
hash_len as the hash to be verified.
This function MUST use the data at the signature pointer of size
signature_len as the signature to be verified.
This function MUST return success only if the signature verification succeeds
This function MUST implement the required side-channel protections for ECDSA.
cc3xx low_level_driver API
This section documents the semantics of various functions in the cc3xx
low_level_driver API.
cc3xx_init.h
cc3xx_lowlevel_init
cc3xx_err_t cc3xx_lowlevel_init(void);
This function initializes the cryptographic accelerator. Before this function is called, the accelerator MUST NOT be used. After calling it, the accelerator is ready for use (or an error is returned).
It SHOULD be called in each boot stage, as the cryptographic accelerator’s state might be stored in data sections that are reinitialized between stages.
cc3xx_lowlevel_uninit
cc3xx_err_t cc3xx_lowlevel_uninit(void);
This function uninitializes the cryptographic accelerator. Once this is
called, the accelerator MUST NOT be used again until
cc3xx_lowlevel_init is called again.
It SHOULD be called at the end of each boot stage or before reset, to ensure that any retained state does not leak across stages. It MUST erase all secret data within the accelerator.
cc3xx_dma.h
cc3xx_lowlevel_dma_remap_region_init
void cc3xx_lowlevel_dma_remap_region_init(uint32_t remap_region_idx,
const cc3xx_dma_remap_region_t *region);
This function configures a memory remap region. Any DMA access to an address within the specified region is redirected to the calculated remap base, including an optional per-CPU offset.
It is used when the system requires address translation between CPU and accelerator access paths—for example, when remapping CPU TCM accesses for use by the cryptographic engine.
This function MUST be called before accessing memory that requires remapping by the DMA.
cc3xx_lowlevel_dma_burst_restricted_region_init
void cc3xx_lowlevel_dma_burst_restricted_region_init(uint32_t region_idx,
const cc3xx_dma_burst_restricted_region_t *region);
This function defines a region where the bus does not support burst transactions. Within this region, the cryptographic engine will use word-aligned accesses instead of bursts.
This is typically used when writing secret material directly into KMU or other hardware-protected areas that do not allow burst transfers.
It MUST be called before any DMA accesses to such regions occur.
cc3xx_aes.h
cc3xx_lowlevel_aes_init
cc3xx_err_t cc3xx_lowlevel_aes_init(
cc3xx_aes_direction_t direction,
cc3xx_aes_mode_t mode, cc3xx_aes_key_id_t key_id,
const uint32_t *key, cc3xx_aes_keysize_t key_size,
const uint32_t *iv, size_t iv_len);
This function initializes an AES operation with the specified parameters.
This function MUST be called before any other AES functions are called.
This function MUST implement the required side-channel protections for AES.
cc3xx_lowlevel_aes_get_state
void cc3xx_lowlevel_aes_get_state(struct cc3xx_aes_state_t *state);
This function retrieves the current internal state of the AES operation. It allows pausing and resuming of AES operations across execution stages.
This function is used in conjunction with
cc3xx_lowlevel_aes_set_state to resume an operation from a
previously saved state.
This function MUST implement the required side-channel protections for AES.
cc3xx_lowlevel_aes_set_state
cc3xx_err_t cc3xx_lowlevel_aes_set_state(const struct cc3xx_aes_state_t *state);
This function sets the internal state of the AES operation from a
previously saved state. It reinitializes the AES engine based on the
provided state and eliminates the need for a separate call to
cc3xx_lowlevel_aes_init.
This function MUST implement the required side-channel protections for AES.
cc3xx_lowlevel_aes_set_tag_len
void cc3xx_lowlevel_aes_set_tag_len(uint32_t tag_len);
This function sets the tag length for authenticated encryption modes (AEAD), such as GCM or CCM. If called in modes that are not AEAD, this function is a no-op.
It MAY be called before cc3xx_lowlevel_aes_finish when using AEAD
modes to ensure proper tag generation or verification. If the function
is not called, then the tag length will be the maximum allowed for that
mode.
cc3xx_lowlevel_aes_set_data_len
void cc3xx_lowlevel_aes_set_data_len(uint32_t to_crypt_len, uint32_t to_auth_len);
This function sets the expected data lengths for AES operations, specifically used for CCM mode. It configures how much data will be encrypted and how much will be authenticated but not encrypted.
This function MUST be called before any data input in CCM mode. It MAY be called in other modes.
cc3xx_lowlevel_aes_set_output_buffer
void cc3xx_lowlevel_aes_set_output_buffer(uint8_t *out, size_t out_len);
This function specifies the buffer where the AES engine should place its
output. It MUST be called before cc3xx_lowlevel_aes_update to ensure
that the output has a valid destination.
If the size of the buffer is smaller than the input data, the update operation will fail.
The output buffer MUST NOT be set when the amount of data input is not a multiple of 16 bytes.
cc3xx_lowlevel_aes_update
cc3xx_err_t cc3xx_lowlevel_aes_update(const uint8_t* in, size_t in_len);
This function submits input data to be encrypted or decrypted. It
processes the data according to the initialized AES configuration and
stores the result in the buffer configured via
cc3xx_lowlevel_aes_set_output_buffer.
This function MUST NOT be called before cc3xx_lowlevel_aes_init or
after cc3xx_lowlevel_aes_finish.
This function MUST implement the required side-channel protections for AES.
cc3xx_lowlevel_aes_update_authed_data
void cc3xx_lowlevel_aes_update_authed_data(const uint8_t* in, size_t in_len);
This function inputs additional authenticated data (AAD) for AEAD/MAC
modes, such as GCM and CCM. It MUST be called before any data is
processed using cc3xx_lowlevel_aes_update.
This function MUST NOT be called after starting data
encryption/decryption (via cc3xx_lowlevel_aes_update). AAD and other
input data cannot be interleaved.
This function MUST implement the required side-channel protections for AES.
cc3xx_lowlevel_aes_finish
cc3xx_err_t cc3xx_lowlevel_aes_finish(uint32_t *tag, size_t *size);
This function finalizes the AES operation and processes any remaining buffered data. In AEAD modes, it also produces or verifies the authentication tag.
If tag is non-NULL, it will either be written with the generated tag
(encryption) or compared against the provided tag (decryption). The size
of the tag defaults to 16 bytes if not explicitly set via
cc3xx_lowlevel_aes_set_tag_len.
This function implicitly uninitializes the AES engine on success. On
failure, the engine must be explicitly uninitialized using
cc3xx_lowlevel_aes_uninit.
This function MUST implement the required side-channel protections for AES.
cc3xx_lowlevel_aes_uninit
void cc3xx_lowlevel_aes_uninit(void);
This function uninitializes the AES engine. It MUST be called once the AES operation is complete, especially to clear any internal state and secret keying material.
This function DOES NOT get called implicitly on failure and must be manually invoked to clean up state even in the case of errors.
cc3xx_kdf.h
cc3xx_lowlevel_kdf_cmac
cc3xx_err_t cc3xx_lowlevel_kdf_cmac(
cc3xx_aes_key_id_t key_id, const uint32_t *key,
cc3xx_aes_keysize_t key_size,
const uint8_t *label, size_t label_length,
const uint8_t *context, size_t context_length,
uint32_t *output_key, size_t out_length);
This function implements a counter-mode KDF following NIST SP800-108 revision 1 update 1. It uses AES in CMAC mode as the pseudo-random function, according to SP800-38B.
This function MUST produce identical results to any KDF algorithms used offline to generate keys, for example, the CM and DM master keys.
This function MUST implement the required side-channel protections for Key Derivation.
SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors