Skip to content

nrf_security: Add CCM* support to CRACEN - #30789

Open
sigvartmh wants to merge 6 commits into
nrfconnect:mainfrom
sigvartmh:feat/add-ccm-star-support-for-cracen
Open

nrf_security: Add CCM* support to CRACEN#30789
sigvartmh wants to merge 6 commits into
nrfconnect:mainfrom
sigvartmh:feat/add-ccm-star-support-for-cracen

Conversation

@sigvartmh

Copy link
Copy Markdown
Contributor

Adds PSA_ALG_CCM_STAR_NO_TAG (CCM* with a zero-length authentication
field, 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.

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>
@sigvartmh
sigvartmh requested review from a team and magnev as code owners August 19, 2026 12:51
@NordicBuilder NordicBuilder added doc-required PR must not be merged without tech writer approval. manifest labels Aug 19, 2026
@NordicBuilder

Copy link
Copy Markdown
Contributor

The following west manifest projects have changed revision in this Pull Request:

Name Old Revision New Revision Diff
psa-arch-tests nrfconnect/sdk-psa-arch-tests@2deff6b nrfconnect/sdk-psa-arch-tests#12 nrfconnect/sdk-psa-arch-tests#12/files

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>
@sigvartmh
sigvartmh force-pushed the feat/add-ccm-star-support-for-cracen branch from ade40a2 to 69947b3 Compare August 19, 2026 13:01
@NordicBuilder

NordicBuilder commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

CI Information

To view the history of this post, click the 'edited' button above
Build number: 2

Inputs:

Sources:

sdk-nrf: PR head: 69947b39a0002bd28996d833f27130a61f8da5aa

more details

sdk-nrf:

PR head: 69947b39a0002bd28996d833f27130a61f8da5aa
merge base: 06f69172b79ac57a893f28bfbb772ca7416e63fe
target head (main): 15b36cb022b160e024277df4fbd3bbe606051960
Diff

Github labels

Enabled Name Description
ci-disabled Disable the ci execution
ci-all-test Run all of ci, no test spec filtering will be done
ci-force-downstream Force execution of downstream even if twister fails
ci-run-twister Force run twister
ci-run-zephyr-twister Force run zephyr twister
ci-run-draft Run CI on draft pull requests
List of changed files detected by CI (12)
doc
│  ├── nrf
│  │  ├── security
│  │  │  ├── crypto
│  │  │  │  │ crypto_supported_features.rst
subsys
│  ├── nrf_security
│  │  ├── cmake
│  │  │  │ psa_crypto_config.cmake
│  │  ├── configs
│  │  │  │ psa_crypto_config.h.template
│  │  ├── src
│  │  │  ├── drivers
│  │  │  │  ├── cracen
│  │  │  │  │  ├── cracen_sw
│  │  │  │  │  │  ├── src
│  │  │  │  │  │  │  │ cracen_sw_aes_ccm.c
│  │  │  │  │  ├── cracenpsa
│  │  │  │  │  │  ├── src
│  │  │  │  │  │  │  ├── cracen_psa_aead.c
│  │  │  │  │  │  │  │ cracen_psa_cipher.c
│  │  │  │  │  ├── psa_driver.Kconfig
│  │  │  │  │  ├── sxsymcrypt
│  │  │  │  │  │  ├── include
│  │  │  │  │  │  │  ├── sxsymcrypt
│  │  │  │  │  │  │  │  ├── aead.h
│  │  │  │  │  │  │  │  │ aes.h
│  │  │  │  │  │  ├── src
│  │  │  │  │  │  │  │ aead.c
tests
│  ├── tfm
│  │  ├── tfm_psa_test
│  │  │  │ prj.conf
west.yml

Outputs:

Toolchain

Version: e214c2a47c
Build docker image: docker-dtr.nordicsemi.no/sw-production/ncs-build:e214c2a47c_a140d687bb

Test Spec & Results: ✅ Success; ❌ Failure; 🟠 Queued; 🟡 Progress; ◻️ Skipped; ⚠️ Quarantine

  • ◻️ Toolchain - Skipped: existing toolchain is used
  • ✅ Build twister
    • sdk-nrf test count: 2319
  • ❌ Integration tests
    • ✅ test_ble_nrf_config
    • ✅ test-fw-nrfconnect-nrf_crypto
    • ✅ test-fw-nrfconnect-rs
    • ❌ test-fw-nrfconnect-tfm
    • ✅ test-sdk-find-my
    • ✅ test-sdk-mcuboot
    • ✅ test-sdk-dfu
    • ⚠️ test-fw-nrfconnect-nrf-iot_cloud
Disabled integration tests
    • test-fw-nrfconnect-nrf_lrcs_mosh
    • test-fw-nrfconnect-nrf_lrcs_positioning
    • desktop52_verification
    • test-fw-nrfconnect-apps
    • test-fw-nrfconnect-apps_nrfdesktop
    • test-fw-nrfconnect-ble_mesh
    • test-fw-nrfconnect-ble_samples
    • test-fw-nrfconnect-fem
    • test-fw-nrfconnect-nfc
    • test-fw-nrfconnect-nrf-iot_libmodem-nrf
    • test-fw-nrfconnect-nrf-iot_lwm2m
    • test-fw-nrfconnect-nrf-iot_samples
    • test-fw-nrfconnect-nrf-iot_zephyr_lwm2m
    • test-fw-nrfconnect-rpc
    • test-fw-nrfconnect-thread-main
    • test-low-level
    • test-sdk-audio
    • test-sdk-wifi
    • test-sdk-wifi-net

Note: This message is automatically posted and updated by the CI

@github-actions

Copy link
Copy Markdown

You can find the documentation preview for this PR here.

Preview links for modified nRF Connect SDK documents:

https://ncsbmdoc.z6.web.core.windows.net/ncs/PR-30789/nrf/security/crypto/crypto_supported_features.html

@AntonZma AntonZma left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some nits

Comment on lines +395 to +397
if (output_size < input_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider moving this check to cracen_aead_update() instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oki

Comment on lines +468 to +470
if (tag_size < operation->tag_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, it looks like a duplicate to

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true

Comment on lines +65 to +67
depends on PSA_WANT_AES_KEY_SIZE_128 || \
PSA_WANT_AES_KEY_SIZE_192 || \
PSA_WANT_AES_KEY_SIZE_256

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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

Suggested change
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

Comment on lines +117 to +122
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and bring back alignment of || \


static size_t single_part_iv_size(psa_algorithm_t alg)
{
if (alg == PSA_ALG_STREAM_CIPHER) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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() ).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +42 to +43
#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))) {
Comment thread west.yml
Comment on lines +387 to +390
sx_status = operation->dir == CRACEN_DECRYPT
? sx_blkcipher_create_aesctr_dec(&operation->cipher,
&operation->keyref,
operation->iv)
Comment on lines +117 to +122
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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and bring back alignment of || \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commit title: would make sense to have craecen in it IMO

Comment on lines +263 to +264
/* CCM* has a 13-octet nonce because L is fixed at 2; everything else prepends a full cipher
* block.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Comment on lines +385 to +395
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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could just reuse the PSA_ALG_CTR case? what we could have is IF_DEFINED(PSA_NEED_X, (case PSA_ALG_Y:))

Comment on lines +495 to +498
operation->iv[0] = CCM_STAR_L - 1;
memcpy(&operation->iv[1], iv, CCM_STAR_NONCE_LENGTH);
operation->iv[14] = 0;
operation->iv[15] = 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DNM doc-required PR must not be merged without tech writer approval. manifest manifest-psa-arch-tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants