nrf_security: Add CCM* support to CRACEN - #30789
Conversation
Devices would crash when `input_length` is larger than the output size. This also account for when `tag_size` is smaller than `operation->tag_size`. Signed-off-by: Sigvart Hovland <sigvart.hovland@nordicsemi.no>
|
The following west manifest projects have changed revision in this Pull Request:
⛔ DNM label due to: 1 project with PR revision Note: This message is automatically posted and updated by the Manifest GitHub Action. |
Add PSA_NEED_CRACEN_CCM_STAR_NO_TAG_AES so the CRACEN cipher driver is built when PSA_WANT_ALG_CCM_STAR_NO_TAG is requested, and expose it in the generated psa_crypto_config.h. AES-192 acceleration is only selected when the CRACEN HW is not the lite variant. Signed-off-by: Sigvart Hovland <sigvart.hovland@nordicsemi.no>
Accept tagsz == 0 in the AES-CCM create functions to support CCM* (IEEE P802.15-4/0537r2), which has no authentication field. With Tlen = 0 the engine emits no tag block, so sx_aead_produce_tag() adds no output descriptor and sx_aead_verify_tag() neither feeds an expected tag nor verifies one. Document the accepted tag size in aead.h and aes.h, including that the caller's B_0 flags octet must encode the same M value. Signed-off-by: Sigvart Hovland <sigvart.hovland@nordicsemi.no>
Implement PSA_ALG_CCM_STAR_NO_TAG in the CRACEN cipher driver. With a zero-length authentication field CCM* reduces to AES-CTR over the counter blocks A_i = Flags || Nonce || i starting at i = 1, so cracen_cipher_set_iv() builds A_1 from the 13-octet nonce (L is fixed at 2) and the operation then runs on the existing AES-CTR primitive. Also keep create_aead_ccmheader() from underflowing the M field when the tag size is zero. Signed-off-by: Sigvart Hovland <sigvart.hovland@nordicsemi.no>
Enable CONFIG_PSA_WANT_ALG_CCM_STAR_NO_TAG so the PSA arch test suite covers the CCM* cipher path in the CRACEN driver, and update the psa-arch-tests revision to pick up the CCM* test cases. Signed-off-by: Sigvart Hovland <sigvart.hovland@nordicsemi.no>
Record CCM* no tag as supported in the nRF54L Series CRACEN tables: Supported for the devices that already list the other CRACEN cipher modes, and CONFIG_PSA_WANT_ALG_CCM_STAR_NO_TAG added to the cipher modes covered by CONFIG_PSA_USE_CRACEN_CIPHER_DRIVER. Signed-off-by: Sigvart Hovland <sigvart.hovland@nordicsemi.no>
ade40a2 to
69947b3
Compare
CI InformationTo view the history of this post, click the 'edited' button above Inputs:Sources:sdk-nrf: PR head: 69947b39a0002bd28996d833f27130a61f8da5aa more detailssdk-nrf:
Github labels
List of changed files detected by CI (12)Outputs:ToolchainVersion: e214c2a47c Test Spec & Results: ✅ Success; ❌ Failure; 🟠 Queued; 🟡 Progress; ◻️ Skipped;
|
|
You can find the documentation preview for this PR here. Preview links for modified nRF Connect SDK documents: |
| if (output_size < input_length) { | ||
| return PSA_ERROR_BUFFER_TOO_SMALL; | ||
| } |
There was a problem hiding this comment.
Please consider moving this check to cracen_aead_update() instead.
| if (tag_size < operation->tag_size) { | ||
| return PSA_ERROR_BUFFER_TOO_SMALL; | ||
| } |
There was a problem hiding this comment.
Hm, it looks like a duplicate to
| depends on PSA_WANT_AES_KEY_SIZE_128 || \ | ||
| PSA_WANT_AES_KEY_SIZE_192 || \ | ||
| PSA_WANT_AES_KEY_SIZE_256 |
There was a problem hiding this comment.
| depends on PSA_WANT_AES_KEY_SIZE_128 || \ | |
| PSA_WANT_AES_KEY_SIZE_192 || \ | |
| PSA_WANT_AES_KEY_SIZE_256 | |
| depends on \ | |
| PSA_WANT_AES_KEY_SIZE_128 || \ | |
| PSA_WANT_AES_KEY_SIZE_192 || \ | |
| PSA_WANT_AES_KEY_SIZE_256 |
or
| depends on PSA_WANT_AES_KEY_SIZE_128 || \ | |
| PSA_WANT_AES_KEY_SIZE_192 || \ | |
| PSA_WANT_AES_KEY_SIZE_256 | |
| depends on PSA_WANT_AES_KEY_SIZE_128 || PSA_WANT_AES_KEY_SIZE_192 || PSA_WANT_AES_KEY_SIZE_256 |
| depends on PSA_NEED_CRACEN_CTR_AES || \ | ||
| PSA_NEED_CRACEN_CCM_STAR_NO_TAG_AES || \ | ||
| PSA_NEED_CRACEN_CBC_PKCS7_AES || \ | ||
| PSA_NEED_CRACEN_CBC_NO_PADDING_AES || \ | ||
| PSA_NEED_CRACEN_ECB_NO_PADDING_AES || \ | ||
| PSA_NEED_CRACEN_STREAM_CIPHER_CHACHA20 |
There was a problem hiding this comment.
| depends on PSA_NEED_CRACEN_CTR_AES || \ | |
| PSA_NEED_CRACEN_CCM_STAR_NO_TAG_AES || \ | |
| PSA_NEED_CRACEN_CBC_PKCS7_AES || \ | |
| PSA_NEED_CRACEN_CBC_NO_PADDING_AES || \ | |
| PSA_NEED_CRACEN_ECB_NO_PADDING_AES || \ | |
| PSA_NEED_CRACEN_STREAM_CIPHER_CHACHA20 | |
| depends on \ | |
| PSA_NEED_CRACEN_CTR_AES || \ | |
| PSA_NEED_CRACEN_CCM_STAR_NO_TAG_AES || \ | |
| PSA_NEED_CRACEN_CBC_PKCS7_AES || \ | |
| PSA_NEED_CRACEN_CBC_NO_PADDING_AES || \ | |
| PSA_NEED_CRACEN_ECB_NO_PADDING_AES || \ | |
| PSA_NEED_CRACEN_STREAM_CIPHER_CHACHA20 |
There was a problem hiding this comment.
and bring back alignment of || \
|
|
||
| static size_t single_part_iv_size(psa_algorithm_t alg) | ||
| { | ||
| if (alg == PSA_ALG_STREAM_CIPHER) { |
There was a problem hiding this comment.
Possibly return a removed comment stating the following?
"ChaCha20 only supports 12 bytes IV in the single part decryption function"
Or how do you feel about moving this value to some macro? There are also other places in this file where it is used (e.g. in cracen_cipher_set_iv() ).
There was a problem hiding this comment.
That makes sense.
There was a problem hiding this comment.
Pull request overview
Adds CRACEN support for PSA CCM* without authentication using the AES-CTR hardware primitive.
Changes:
- Implements CCM* cipher encryption/decryption and configuration.
- Extends CCM internals to support zero-length tags.
- Enables PSA tests and documents device support.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
west.yml |
References dependent PSA tests. |
tests/tfm/tfm_psa_test/prj.conf |
Enables CCM* tests. |
subsys/nrf_security/src/drivers/cracen/sxsymcrypt/src/aead.c |
Supports zero-length CCM tags. |
subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/aes.h |
Documents tagless CCM*. |
subsys/nrf_security/src/drivers/cracen/sxsymcrypt/include/sxsymcrypt/aead.h |
Updates tag-size documentation. |
subsys/nrf_security/src/drivers/cracen/psa_driver.Kconfig |
Adds CRACEN CCM* configuration. |
subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen_psa_cipher.c |
Implements CCM* through AES-CTR. |
subsys/nrf_security/src/drivers/cracen/cracenpsa/src/cracen_psa_aead.c |
Handles zero-tag CCM headers. |
subsys/nrf_security/src/drivers/cracen/cracen_sw/src/cracen_sw_aes_ccm.c |
Adds output-buffer validation. |
subsys/nrf_security/configs/psa_crypto_config.h.template |
Exposes the configuration macro. |
subsys/nrf_security/cmake/psa_crypto_config.cmake |
Propagates CCM* configuration. |
doc/nrf/security/crypto/crypto_supported_features.rst |
Documents CRACEN device support. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| #define CCM_STAR_L 2 | ||
| #define CCM_STAR_NONCE_LENGTH (SX_BLKCIPHER_IV_SZ - 1 - CCM_STAR_L) |
| } | ||
| } | ||
| if ((tagsz & 1) || (tagsz < 4) || (tagsz > 16)) { | ||
| if ((tagsz != 0) && ((tagsz & 1) || (tagsz < 4) || (tagsz > 16))) { |
| sx_status = operation->dir == CRACEN_DECRYPT | ||
| ? sx_blkcipher_create_aesctr_dec(&operation->cipher, | ||
| &operation->keyref, | ||
| operation->iv) |
| depends on PSA_NEED_CRACEN_CTR_AES || \ | ||
| PSA_NEED_CRACEN_CCM_STAR_NO_TAG_AES || \ | ||
| PSA_NEED_CRACEN_CBC_PKCS7_AES || \ | ||
| PSA_NEED_CRACEN_CBC_NO_PADDING_AES || \ | ||
| PSA_NEED_CRACEN_ECB_NO_PADDING_AES || \ | ||
| PSA_NEED_CRACEN_STREAM_CIPHER_CHACHA20 |
There was a problem hiding this comment.
and bring back alignment of || \
There was a problem hiding this comment.
commit title: would make sense to have craecen in it IMO
| /* CCM* has a 13-octet nonce because L is fixed at 2; everything else prepends a full cipher | ||
| * block. |
There was a problem hiding this comment.
Would it make more sense to have this comment where CCM_STAR_NONCE_LENGTH is defined as here we are just using it without knowing anything about its value?
| case PSA_ALG_CCM_STAR_NO_TAG: | ||
| if (IS_ENABLED(PSA_NEED_CRACEN_CCM_STAR_NO_TAG_AES)) { | ||
| sx_status = operation->dir == CRACEN_DECRYPT | ||
| ? sx_blkcipher_create_aesctr_dec(&operation->cipher, | ||
| &operation->keyref, | ||
| operation->iv) | ||
| : sx_blkcipher_create_aesctr_enc(&operation->cipher, | ||
| &operation->keyref, | ||
| operation->iv); | ||
| } | ||
| break; |
There was a problem hiding this comment.
could just reuse the PSA_ALG_CTR case? what we could have is IF_DEFINED(PSA_NEED_X, (case PSA_ALG_Y:))
| operation->iv[0] = CCM_STAR_L - 1; | ||
| memcpy(&operation->iv[1], iv, CCM_STAR_NONCE_LENGTH); | ||
| operation->iv[14] = 0; | ||
| operation->iv[15] = 1; |
There was a problem hiding this comment.
Using a mix of define (CCM_STAR_NONCE_LENGTH) and magic values is not great, rather error-prone. Either use only one, or use a local variable to move the pointer every time too?
Adds
PSA_ALG_CCM_STAR_NO_TAG(CCM* with a zero-length authenticationfield, IEEE P802.15-4/0537r2) as a cipher algorithm on the CRACEN driver.
With Tlen = 0, CCM* reduces to AES-CTR over the counter blocks
A_i = Flags || Nonce || i starting at i = 1, so the implementation builds
A_1 from the 13-octet nonce (L is fixed at 2) and runs on the existing
AES-CTR hardware primitive. sxsymcrypt is extended to accept tagsz == 0 so
no tag block is produced or verified.
Tested with the PSA arch test suite (c037/c050 cipher tests) on nRF54L.
Depends on nrfconnect/sdk-psa-arch-tests#12, which adds the CCM* test
cases.