Skip to content

Introduce HKDF to PKCS11 TA - #7837

Open
Hussainity wants to merge 3 commits into
OP-TEE:masterfrom
Hussainity:hm/hkdf-001
Open

Introduce HKDF to PKCS11 TA#7837
Hussainity wants to merge 3 commits into
OP-TEE:masterfrom
Hussainity:hm/hkdf-001

Conversation

@Hussainity

@Hussainity Hussainity commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

This PR implements CKM_HKDF_DERIVE (PKCS#11 v3.0, RFC 5869) in the PKCS#11 TA so that clients can perform HKDF Extract, Expand, or Extract-then-Expand against a generic-secret parent key.

Summary

  • New ta/pkcs11/src/processing_hkdf.c: HKDF Extract / Expand built directly on TEE_ALG_HMAC_* rather than the GP TEE_ALG_HKDF so all three modes (extract-only, expand-only, both) and any HMAC-supported PRF hash (MD5, SHA-1, SHA-224/256/384/512) can be supported. Short keys are zero-padded to the GP HMAC type minimum (equivalent under RFC 2104) so RFC 5869 test vectors with sub-minimum salts work.

  • Mechanism plumbing:

    • ta/pkcs11/include/pkcs11_ta.h: add PKCS11_CKM_HKDF_DERIVE and the pkcs11_hkdf_salt_type enum mirroring CKF_HKDF_SALT_{NULL,DATA,KEY}.
    • ta/pkcs11/src/pkcs11_attributes.c: allow the new mechanism through created-attribute and parent-key checks (parent must be CKO_SECRET_KEY / CKK_GENERIC_SECRET).
    • ta/pkcs11/src/processing.{c,h}: dispatch PKCS11_FUNCTION_DERIVE to derive_key_by_hkdf().
    • ta/pkcs11/src/token_capabilities.c: advertise the mechanism with CKFM_DERIVE.
  • Wire format matches libckteec's serialize_mecha_hkdf_derive_param().

  • Unrelated supporting fix: core/tee/tee_svc_cryp.c and lib/libutee/tee_api_operations.c — TEE_ALG_HKDF (consolidated form, no hash bits in the algo ID) now defaults to SHA-256 in get_hkdf_params() and is accepted by TEE_AllocateOperation(). Without this, an operation for TEE_ALG_HKDF returns TEE_ERROR_NOT_SUPPORTED.

RFC 5869 conformance

  • Extract: PRK = HMAC-Hash(salt, IKM); empty salt → HashLen zero bytes.
  • Expand: T(i) = HMAC-Hash(PRK, T(i-1) || info || i), N = ceil(L / HashLen) ≤ 255.
  • Mode-specific length checks: extract-only output must equal HashLen; expand-only requires IKM ≥ HashLen; expand caps L ≤ 255 · HashLen.

Related PRs

Testing

  • xtest ran on QEMUv8

@jenswikl

Copy link
Copy Markdown
Contributor

Please provide a proper commit message.

The consolidated TEE_ALG_HKDF carries no hash bits in its algorithm
ID. tee_cryp_hkdf() runs the value through TEE_ALG_HASH_ALGO(), so
seed hash_id with TEE_ALG_GET_DIGEST_HASH(TEE_ALG_HKDF_SHA256_DERIVE_KEY)
rather than TEE_ALG_SHA256 to match that form.

Signed-off-by: Hussain Miyaziwala <hussain_miya@hotmail.com>
…tion

The consolidated TEE_ALG_HKDF identifier was missing from the switch
in TEE_AllocateOperation(), so allocating an operation for it returned
TEE_ERROR_NOT_SUPPORTED. Add it alongside the per-hash HKDF variants.

Signed-off-by: Hussain Miyaziwala <hussain_miya@hotmail.com>
Comment thread ta/pkcs11/include/pkcs11_ta.h Outdated
PKCS11_CKM_SHA512_RSA_PKCS_PSS = 0x00045,
PKCS11_CKM_SHA224_RSA_PKCS = 0x00046,
PKCS11_CKM_SHA224_RSA_PKCS_PSS = 0x00047,
PKCS11_CKM_HKDF_DERIVE = 0x0402a,

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.

I'd prefer we keep on sorting enum labels per value. Could you move PKCS11_CKM_HKDF_DERIVE down to the end of the enum list?

Comment thread ta/pkcs11/include/pkcs11_ta.h Outdated
PKCS11_CKM_UNDEFINED_ID = PKCS11_UNDEFINED_ID,
};

/* HKDF salt source selectors (mirror libckteec CKF_HKDF_SALT_*) */

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.

Suggestion, for consistency with other inlie descriptions

Suggested change
/* HKDF salt source selectors (mirror libckteec CKF_HKDF_SALT_*) */
/*
* Valid values for HKDF source selectors
* PKCS11_CKF_HKDF_SALT_<x> reflects CryptoKi client API IDs CKF_HKDF_SALT_<x>.
*/

if (key_class != PKCS11_CKO_SECRET_KEY ||
key_type != PKCS11_CKK_GENERIC_SECRET)
return PKCS11_CKR_KEY_FUNCTION_NOT_PERMITTED;
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 you add an empty line below, for conssitency.

} else if (processing_is_tee_hkdf(proc_params->id)) {
if (function != PKCS11_FUNCTION_DERIVE) {
rc = PKCS11_CKR_MECHANISM_INVALID;
goto out;

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.

If function != PKCS11_FUNCTION_DERIVE I think we should not have reached this point.
TEE_Panic(function) could apply.
IMHO ASSERT(function != PKCS11_FUNCTION_DERIVE) could be enough.

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.

I picked TEE_Panic(function) for consistency

}

/* Mirrors the strict GP HMAC type ranges from core/tee/tee_svc_cryp.c */
struct hkdf_prf {

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.

Prefer have struct defined before any fucntion: here, before processing_is_tee_hkdf() definition.

Comment thread ta/pkcs11/src/token_capabilities.c Outdated
TA_MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE),
TA_MECHANISM(PKCS11_CKM_AES_CBC_ENCRYPT_DATA, PKCS11_CKFM_DERIVE),
TA_MECHANISM(PKCS11_CKM_ECDH1_DERIVE, PKCS11_CKFM_DERIVE),
TA_MECHANISM(PKCS11_CKM_HKDF_DERIVE, PKCS11_CKFM_DERIVE),

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.

Prefer adding this line at the end of the array, for consistency with pkcs11_modes[].

Comment thread ta/pkcs11/src/processing_hkdf.c Outdated
if (rc)
return rc;
} else {
*salt = NULL;

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 remove *salt = NULL (also *info = NULL below) since we known these are already zero initialiaze.

Comment thread ta/pkcs11/src/processing_hkdf.c Outdated
Comment on lines +310 to +311
salt = NULL;
salt_len = 0;

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.

IMO it would be worth be strict on expected parameters provided by the client:

Suggested change
salt = NULL;
salt_len = 0;
if (salt || salt_len)
rc = PKCS11_CKR_MECHANISM_PARAM_INVALID;

if (!salt_obj) {
rc = PKCS11_CKR_KEY_HANDLE_INVALID;
goto out;
}

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.

Should check access to salt key handle.

rc = check_access_attrs_against_token(session, salt_obj->attributes);
if (rc)
	goto out;

Comment thread ta/pkcs11/src/processing_hkdf.c Outdated
res = TEE_ERROR_GENERIC;

out:
memset(padded_key, 0, sizeof(padded_key));

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.

memzero_explicit()

@etienne-lms

Copy link
Copy Markdown
Contributor

I forgot to thank you for these additions. I'll need to take a few other looks, for the details, but the overall LGTM.

@Hussainity

Copy link
Copy Markdown
Contributor Author

I forgot to thank you for these additions. I'll need to take a few other looks, for the details, but the overall LGTM.

@etienne-lms , happy to contribute, thank you for the review, I have updated the branch.

@github-actions

Copy link
Copy Markdown

This pull request has been marked as a stale pull request because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this pull request will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.

@github-actions github-actions Bot added the Stale label Jul 27, 2026
@etienne-lms

Copy link
Copy Markdown
Contributor

Keep alive.

@etienne-lms etienne-lms 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.

For commit "core: tee: tee_svc_cryp: default TEE_ALG_HKDF hash to SHA-256" and
commit "libutee: tee_api_operations: accept TEE_ALG_HKDF in TEE_AllocateOperation":
Look consistent to me.
Reviewed-by: Etienne Carriere <etienne.carriere@st.com>

For commit "ta: pkcs11: Introduce HKDF_DERIVE support", some minor comments. The overall looks good to me but I need another review.

My apologies for this late feedback on your P-R. Thanks for your patience.

Comment thread ta/pkcs11/src/processing.c Outdated
Comment on lines +999 to +1001
if (function != PKCS11_FUNCTION_DERIVE) {
TEE_Panic(function);
}

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.

For consistency, prefer without braces for single line conditioned instructions:

Suggested change
if (function != PKCS11_FUNCTION_DERIVE) {
TEE_Panic(function);
}
if (function != PKCS11_FUNCTION_DERIVE)
TEE_Panic(function);

Comment thread ta/pkcs11/src/processing_hkdf.c Outdated
memzero_explicit(okm, out_byte_size);
TEE_Free(okm);
}
release_active_processing(session);

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.

release_active_processing() is already called from entry_processing_key(). For consistency I'd prefer you remove this line.

Comment thread ta/pkcs11/src/processing.c Outdated
Comment on lines +1003 to +1005
if (!rc)
goto done;
goto out;

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.

For consistency with the other cases in this function, prefer the other way round:

Suggested change
if (!rc)
goto done;
goto out;
if (rc)
goto out;
goto done;

Comment thread ta/pkcs11/src/processing_hkdf.c Outdated
Comment on lines +153 to +156
if (key_obj != TEE_HANDLE_NULL)
TEE_FreeTransientObject(key_obj);
if (op != TEE_HANDLE_NULL)
TEE_FreeOperation(op);

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 remove the tests:

Suggested change
if (key_obj != TEE_HANDLE_NULL)
TEE_FreeTransientObject(key_obj);
if (op != TEE_HANDLE_NULL)
TEE_FreeOperation(op);
TEE_FreeTransientObject(key_obj);
TEE_FreeOperation(op);

Comment thread ta/pkcs11/src/processing_hkdf.c Outdated
Comment on lines +311 to +314
case PKCS11_CKF_HKDF_SALT_KEY: {
struct pkcs11_object *salt_obj = NULL;
void *salt_value = NULL;
uint32_t salt_value_size = 0;

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.

The braces added here make indentation a bit strange. I'd prefer you move the local variable at function entry or use a local helper function for the salt key case.

@Hussainity

Copy link
Copy Markdown
Contributor Author

@etienne-lms , I appreciate your review, I have updated the branch with your suggestions.

@etienne-lms etienne-lms 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.

Still LGTM. See the remaining comments.

Comment on lines +343 to +345
rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &out_byte_size);
if (rc)
goto out;

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.

The specs says generated object template may not specify CKA_VALUE_LEN when bExpand is false, in which case the length is defined by the algo.
Suggestion:

Suggested change
rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &out_byte_size);
if (rc)
goto out;
rc = get_u32_attribute(*head, PKCS11_CKA_VALUE_LEN, &out_byte_size);
if (rc) {
/* When bExpand is false, default default lengh is the hash length */
if (rc != PKCS11_RV_NOT_FOUND)
goto out;
if (expand == PKCS11_TRUE) {
rc = PKCS11_CKR_MECHANISM_PARAM_INVALID;
goto out;
}
out_byte_size = prf.hash_len;
}

Comment thread ta/pkcs11/src/processing_hkdf.c Outdated
if (rc)
goto out;

switch (salt_type) {

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.

Nitpicking: thee spec says the slat should be ignored when bExtract is false. I wonder if a strict implementation should avoid error cases when salt parameters are invalid, like skipping this switch/case sequence when so. What do you think?

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.

Agreed, always supportive of removing vendor specific failure modes that aren't reflected in the spec!

@Hussainity

Copy link
Copy Markdown
Contributor Author

@etienne-lms , addressed comments and tested against OP-TEE/optee_test#819

Add the PKCS#11 v3.0 CKM_HKDF_DERIVE mechanism. The implementation
runs HKDF (RFC 5869) directly on top of TEE_ALG_HMAC_* so that
extract-only, expand-only and combined modes are all supported, for
any HMAC PRF the GP API offers (MD5, SHA-1, SHA-224/256/384/512).

The mechanism parameters follow the wire format produced by libckteec
(bExtract, bExpand, prfHashMechanism, salt source/length/data,
hSaltKey, info length/data) and the parent key must be a
CKO_SECRET_KEY of CKK_GENERIC_SECRET that supplies the IKM.

Signed-off-by: Hussain Miyaziwala <hussain_miya@hotmail.com>
@Hussainity

Copy link
Copy Markdown
Contributor Author

Will add review tags for all commits once I get the thumbs up

@Hussainity

Copy link
Copy Markdown
Contributor Author

@etienne-lms @jenswikl I fixed the workflow errors, still need a maintainer rerun and reviewer tag for the final commit!

@jforissier

Copy link
Copy Markdown
Contributor

For "core: tee: tee_svc_cryp: default TEE_ALG_HKDF hash to SHA-256" and "libutee: tee_api_operations: accept TEE_ALG_HKDF in TEE_AllocateOperation": Reviewed-by: Jerome Forissier <jerome.forissier@arm.com>

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.

4 participants