Skip to content

Add CKM_CONCATENATE_* derive mechanisms - #279

Merged
LinuxJedi merged 1 commit into
wolfSSL:masterfrom
Frauschi:issue-264-concatenate-derive
Nov 3, 2026
Merged

LinuxJedi merged 1 commit into
wolfSSL:masterfrom
Frauschi:issue-264-concatenate-derive

Conversation

@Frauschi

@Frauschi Frauschi commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Implement CKM_CONCATENATE_BASE_AND_KEY, CKM_CONCATENATE_BASE_AND_DATA and CKM_CONCATENATE_DATA_AND_BASE, so a hybrid key agreement such as ETSI TS 103 744 can build PSK || Z_ECDH || Z_MLKEM as a sensitive key and feed it to HKDF without exporting the parts. Fixes #264.

Changes

  • Add the three mechanisms to C_DeriveKey, the mechanism list and pkcs11.h (with CK_KEY_DERIVATION_STRING_DATA).
  • A shorter CKA_VALUE_LEN keeps the leading bytes; without it the key takes the summed length, and AES keys need CKA_VALUE_LEN.
  • A shorter CKA_VALUE_LEN may not end inside a sensitive or non-extractable input key.
  • The result is sensitive or non-extractable when either input is, also under WOLFPKCS11_LEGACY_DERIVE_NO_INHERIT, and CKA_WRAP_WITH_TRUSTED follows either input.
  • A token key that is not decoded gives CKR_USER_NOT_LOGGED_IN; a DHUK-wrapped AES key gives CKR_KEY_FUNCTION_NOT_PERMITTED.
  • Drop WP11_DERIVE_SECRET_KEY so the secret-key derive path is always built.
  • An AES key derived without CKA_VALUE_LEN at an invalid length now gives CKR_TEMPLATE_INCOMPLETE instead of CKR_FUNCTION_FAILED.
  • WP11_MAX_SYM_KEY_SZ is 256 bytes in ML-KEM builds without DH, so a 96-byte hybrid input fits.

Testing

  • pkcs11test: test_concatenate_* cases for each mechanism, attribute inheritance, error paths, CKA_WRAP_WITH_TRUSTED and logged-out keys.
  • pkcs11test: test_concatenate_hybrid_hkdf checks HKDF output from fixed ECDH and ML-KEM secrets.
  • pkcs11v3test: test_concatenate_hybrid_agreement runs ECDH, ML-KEM and a PSK through concatenation and HKDF on both sides and compares the keys.
  • pkcs11test: test_ecdh_derive_aes_no_value_len and test_hkdf_derive_aes_no_value_len.
  • pkcs11str: concatenation with a stored key before login.

Copilot AI balanced review requested due to automatic review settings November 2, 2026 15:44

Copilot AI 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.

🟡 Changes recommended

The tests lack native end-to-end agreement and 96-byte capacity regression coverage, while an unconditional logout causes empty-PIN configurations to fail before derivation checks run.

2 open issues
What changed in this PR

Adds secret-key concatenation to support protected hybrid key-agreement inputs for HKDF, addressing #264 without exporting the component secrets.

Changes:

  • Registers three concatenation mechanisms with length validation and protection-attribute inheritance.
  • Expands ML-KEM key capacity in no-DH builds and improves AES derivation errors.
  • Adds concatenation, storage-access, and deterministic concatenation-to-HKDF tests.
File Description
wolfpkcs11/​pkcs11.h Defines concatenation mechanisms and their data parameter type.
wolfpkcs11/​internal.h Declares concatenation helpers and expands ML-KEM key capacity.
tests/​pkcs11test.c Tests concatenation, protection inheritance, errors, and HKDF use.
tests/​pkcs11str.c Tests stored-key concatenation before login.
src/​slot.c Advertises concatenation mechanisms and capabilities.
src/​internal.c Implements key-state validation and concatenation helpers.
src/​crypto.c Adds derivation dispatch, attribute inheritance, and error handling.

Review effort: Balanced

Comment thread tests/pkcs11test.c Resolved
Comment thread tests/pkcs11test.c Resolved
@Frauschi

Frauschi commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

@wolfSSL-Fenrir-bot review balanced

@Frauschi

Frauschi commented Nov 2, 2026

Copy link
Copy Markdown
Member Author

@claude review

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot 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.

Fenrir Automated Review — PR #279

Scan targets checked: wolfpkcs11-src, wolfpkcs11-bugs
Coverage: 2 of 8 in-scope changed file(s) opened by the reviewer; not opened: src/slot.c, tests/pkcs11str.c, tests/pkcs11test.c, tests/pkcs11v3test.c, wolfpkcs11/internal.h, wolfpkcs11/pkcs11.h

Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)

This review was generated automatically by Fenrir. Reported findings require changes before merge.

Review tier: Balanced

Comment thread src/crypto.c Resolved
Comment thread src/crypto.c Resolved
Implement the PKCS#11 miscellaneous concatenation derive mechanisms
(v3.1/v3.2 section 6.43.3 to 6.43.5). They let a hybrid key agreement
such as ETSI TS 103 744 build PSK || Z_ECDH || Z_MLKEM as a sensitive,
non-extractable secret and feed it to CKM_HKDF_DERIVE without exporting
the parts.

A CKA_VALUE_LEN shorter than the concatenation keeps the leading bytes,
matching NSS and SoftHSM, and the data may then be longer than the
largest key. The shorter length may not end inside the bytes of a
sensitive or non-extractable input key: a caller could otherwise derive
keys one byte longer at a time, use each to sign or encrypt, and find
every key byte in 256 tries. Dropping trailing data, or all of a key,
stays allowed. Without CKA_VALUE_LEN the key takes the summed length, as
in NSS softoken; NSS asks for a CKK_HKDF key this way when it combines
the secrets of its hybrid TLS groups. An AES key has no single
well-defined length, so it needs CKA_VALUE_LEN and otherwise gets
CKR_TEMPLATE_INCOMPLETE. CKA_KEY_TYPE stays required, as for the other
derive mechanisms.

For CKM_CONCATENATE_BASE_AND_KEY the second key must be a secret key
with CKA_DERIVE set, the derived key is sensitive if either input is and
non-extractable if either input is, and CKA_ALWAYS_SENSITIVE /
CKA_NEVER_EXTRACTABLE need both inputs to have them. A
CKM_CONCATENATE_DATA_AND_BASE result truncated to the caller's data
holds no key bytes, so it gets neither flag. CKA_WRAP_WITH_TRUSTED is
set when either input has it, so a copy cannot be wrapped with an
untrusted key. A token key whose value is not decoded, before login or
after logout, gives CKR_USER_NOT_LOGGED_IN instead of being
concatenated as empty or zeroed bytes. An AES key wrapped by the
STM32U5 DHUK gives CKR_KEY_FUNCTION_NOT_PERMITTED, as its stored value
is not the key.

The concatenation output contains the input key bytes, so these three
mechanisms inherit CKA_SENSITIVE and CKA_EXTRACTABLE even in builds
with WOLFPKCS11_LEGACY_DERIVE_NO_INHERIT (enabled for NSS); otherwise
concatenating a sensitive key with empty data would give a readable
copy. Under WP11_NSS_PERMISSIVE_KEY_DEFAULTS the second key skips the
CKA_DERIVE check, as the base key does.

Related derive changes:
- Drop WP11_DERIVE_SECRET_KEY. Concatenation needs no crypto, so the
  secret-key derive path is always built.
- For the other mechanisms, an AES key derived without CKA_VALUE_LEN
  takes the whole derived length. When that is not 16, 24 or 32 bytes,
  return CKR_TEMPLATE_INCOMPLETE before creating the object instead of
  failing in the key setter with CKR_FUNCTION_FAILED. A template that
  has CKA_VALUE_LEN keeps the error object creation returns for it.
- Use a WP11_MAX_SYM_KEY_SZ of 256 bytes in ML-KEM builds without DH.
  The ECC-only value of 66 bytes could not hold a 96-byte
  PSK || ECDH || ML-KEM input.

Fixes wolfSSL#264.

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot 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.

Fenrir Automated Review — PR #279

Scan targets checked: wolfpkcs11-src, wolfpkcs11-bugs
Coverage: 1 of 2 in-scope changed file(s) opened by the reviewer; not opened: tests/pkcs11test.c

Fenrir result: Approved ✅

No new issues found in the changed files.

Advisory only — this automated result does not count as a GitHub approval.

Review tier: Lite

@wolfSSL-Fenrir-bot
wolfSSL-Fenrir-bot dismissed their stale review November 2, 2026 17:54

Fenrir's latest completed scan found no issues; clearing the prior automated change request.

@LinuxJedi

Copy link
Copy Markdown
Member

Thanks for this, the concatenation support and the protection handling around it look good. My concern is how it lands on embedded and size-constrained builds.

Concatenation has no build option

Every other derive mechanism can be compiled out: --enable-ecc, --enable-dh, --enable-aescbc and --enable-hkdf each have a configure option and a define. CKM_CONCATENATE_* is built unconditionally, so every build carries the new derive case, WP11_Concat_KeyLen / WP11_Concat_Derive and the mechanism list entries, with no way to remove them short of patching.

Size is only part of it. Concatenation mechanisms have a history of key extraction attacks on PKCS#11 tokens (combine a sensitive key with known data, truncate, recover it a byte at a time). This PR guards against that with ConcatCutsProtectedKey and inheritance from both inputs, but a locked-down device with no use for hybrid key agreement (wolfBoot, for example) would rather not expose the mechanism at all.

Secret key objects get larger in ML-KEM builds

The new WOLFPKCS11_MLKEM branch for WP11_MAX_SYM_KEY_SZ sits ahead of HAVE_ECC, so an ML-KEM + ECC + --disable-dh build goes from 66 to 256 bytes. That value sizes the fixed array in WP11_Data, which is allocated for every AES, HKDF and generic secret key, so each one costs about 190 more bytes of heap whether or not concatenation is ever used. ML-KEM with ECC and no DH is a likely profile for PQC on microcontrollers, so this lands on the builds least able to afford it. Also, unlike WP11_MAX_PIN_LEN just above it, WP11_MAX_SYM_KEY_SZ is not wrapped in #ifndef, so users can't tune it back down.

Suggestions

  • Put the mechanisms behind their own option, e.g. --enable-concatenate / WOLFPKCS11_CONCATENATE. Defaulting it to on is fine.
  • Keep WP11_DERIVE_SECRET_KEY and add the new define to its condition. It was added for F-10381 so there is one list of the mechanisms that build a secret key and the guards can't drift apart again.
  • Tie the larger WP11_MAX_SYM_KEY_SZ to concatenation being enabled rather than to ML-KEM, and wrap it in #ifndef so it can be overridden. That would also cover ECC-only builds: PSK || Z_ECDH on P-384 is 80 bytes, which doesn't fit in the current 66.
  • Ideally add a CI configuration with the guard off (ECC, DH, HKDF, AES-CBC and concatenation all disabled). No current job builds that combination, which is how the mismatched guards behind F-10381 went unnoticed.

@LinuxJedi
LinuxJedi merged commit f5370f6 into wolfSSL:master Nov 3, 2026
100 of 103 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support secret-key concatenation for hybrid ECDH/ML-KEM derivation

5 participants