4646#include "mcuxClEls_Ecc.h"
4747#include "mcuxClEls_KeyManagement.h"
4848#include "mcuxCsslFlowProtection.h"
49+ #include <wolfssl/wolfcrypt/sha256.h>
4950
5051/* Key slot holding the UDS (pre-loaded by ROM before DICE).
5152 * TODO: Replace with NXP_DIE_DICE_UDS_MK_SK */
@@ -420,13 +421,13 @@ int hal_attestation_get_ueid(uint8_t *buf, size_t *len)
420421 }
421422
422423 /* 32 bytes CUSTOM PAD */
423- memset (deriv , 0 , sizeof (deriv ));
424- memcpy (deriv , "WOLFBOOT-UEID" , 13 );
424+ XMEMSET (deriv , 0 , sizeof (deriv ));
425+ XMEMCPY (deriv , "WOLFBOOT-UEID" , 13 );
425426
426427 /* UEID Type RANDOM */
427428 buf [0 ] = 0x01 ;
428429
429- /* Trigger the HKDF operation .
430+ /* Trigger the HKDF command .
430431 * We just give the names of token and return value
431432 * since it's declared within the macro */
432433 MCUX_CSSL_FP_FUNCTION_CALL_BEGIN (res_hkdf , tok_hkdf ,
@@ -439,11 +440,11 @@ int hal_attestation_get_ueid(uint8_t *buf, size_t *len)
439440 MCUX_CSSL_FP_FUNCTION_CALL_END ();
440441
441442 /* Wait for hardware to finish */
442- MCUX_CSSL_FP_FUNCTION_CALL_BEGIN (res_w2 , tok_w2 ,
443+ MCUX_CSSL_FP_FUNCTION_CALL_BEGIN (res_w , tok_w ,
443444 mcuxClEls_WaitForOperation (MCUXCLELS_ERROR_FLAGS_CLEAR ));
444445
445- if ((MCUX_CSSL_FP_FUNCTION_CALLED (mcuxClEls_WaitForOperation ) != tok_w2 ) ||
446- (MCUXCLELS_STATUS_OK != res_w2 ))
446+ if ((MCUX_CSSL_FP_FUNCTION_CALLED (mcuxClEls_WaitForOperation ) != tok_w ) ||
447+ (MCUXCLELS_STATUS_OK != res_w ))
447448 return -1 ;
448449
449450 MCUX_CSSL_FP_FUNCTION_CALL_END ();
@@ -459,62 +460,112 @@ int hal_attestation_get_lifecycle(uint32_t *lifecycle)
459460 return 0 ;
460461}
461462
463+ /* Derive new CDI from measurement and previous CDI */
462464int hal_dice_update_cdi (const uint8_t * measurement , size_t meas_len )
463465{
464466 static int cdi_step = 0 ;
467+ uint8_t deriv [MCUXCLELS_HKDF_RFC5869_DERIVATIONDATA_SIZE ];
468+ wc_Sha256 sha ;
469+ mcuxClEls_HkdfOption_t opts ;
470+ mcuxClEls_KeyProp_t props ;
471+ int ret = 0 ;
465472
466473 if (cdi_step == 0 ) {
467474 /*
468- * Component [0] is the wolfBoot hash. The ROM already incorporated
475+ * Component [0] is the wolfBoot hash. The boot ROM already incorporated
469476 * it as: HKDF(UDS, wolfBoot_hash) -> initial_CDI.
470477 * Skip re-applying it — doing so would produce the wrong CDI chain.
471478 */
472479 cdi_step ++ ;
473- return 0 ;
480+ return ret ;
481+ }
482+ else if (cdi_step > 1 ) {
483+ /* Limit to 2 components (including wolfBoot) due to key slot constraints */
484+ ret = -1 ;
474485 }
475486
476- /*
477- * Component [1+]: mix this measurement into the CDI chain via ELS HKDF RFC5869.
478- *
479- * The 32-byte derivation data buffer must be composed as:
480- * deriv[0..30] = info/label (31 bytes, zero-padded)
481- * deriv[31] = 0x01 (RFC5869 counter byte for single-block expansion)
482- * The SDK does NOT add this formatting automatically.
483- *
484- * NOTE: The exact label policy (truncate SHA-384 to 31 bytes, or pre-hash
485- * to SHA-256 then take first 31 bytes) and alignment with the ROM's approach
486- * for component[0] must be confirmed before finalizing this implementation.
487- * See also: whether a separate RFC5869 Extract step is needed before Expand.
488- *
489- * TODO: Implement using mcuxClEls_KeyDelete_Async + mcuxClEls_Hkdf_Rfc5869_Async:
490- *
491- * // Step 1: Free target slot (KDELETE, cmd 0xB)
492- * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(...,
493- * mcuxClEls_KeyDelete_Async(MCXN_ELS_DICE_CDI_DERIVED_KEYSLOT));
494- * mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR);
495- *
496- * // Step 2: Compose derivation data {label[31 bytes], counter[1 byte]}
497- * uint8_t deriv[MCUXCLELS_HKDF_RFC5869_DERIVATIONDATA_SIZE] = {0};
498- * size_t label_len = (meas_len < 31u) ? meas_len : 31u;
499- * memcpy(deriv, measurement, label_len);
500- * deriv[31] = 0x01u;
501- *
502- * // Step 3: Derive new CDI into freed slot
503- * mcuxClEls_HkdfOption_t opts = {0};
504- * opts.bits.rtfdrvdat = MCUXCLELS_HKDF_VALUE_RTF_DERIV_DISABLE;
505- * mcuxClEls_KeyProp_t props = {.word.value =
506- * MCUXCLELS_KEYPROPERTY_VALUE_HKDF | MCUXCLELS_KEYPROPERTY_VALUE_ACTIVE};
507- * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(...,
508- * mcuxClEls_Hkdf_Rfc5869_Async(opts,
509- * MCXN_ELS_DICE_CDI_INITIAL_KEYSLOT,
510- * MCXN_ELS_DICE_CDI_DERIVED_KEYSLOT,
511- * props, deriv));
512- * mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR);
513- */
514- cdi_step ++ ;
515- (void )measurement ;
516- (void )meas_len ;
517- return -1 ; /* placeholder */
487+ XMEMSET (deriv , 0 , sizeof (deriv ));
488+
489+ if (measurement == NULL || meas_len == 0 ) {
490+ ret = -1 ;
491+ }
492+
493+ if (ret == 0 ) {
494+ if (meas_len > SHA256_DIGEST_SIZE ) {
495+ /* Pre-hash to SHA-256 digest */
496+ ret = wc_InitSha256 (& sha );
497+ if (ret == 0 ) {
498+ ret = wc_Sha256Update (& sha , measurement , (word32 )meas_len );
499+ if (ret == 0 ) {
500+ ret = wc_Sha256Final (& sha , deriv );
501+ }
502+ wc_Sha256Free (& sha );
503+ }
504+ }
505+ else {
506+ XMEMCPY (deriv , measurement , meas_len );
507+ }
508+ }
509+
510+ if (ret == 0 ) {
511+ /* Trigger the KDELETE command to free the key slot.
512+ * We just give the names of token and return value
513+ * since it's declared within the macro */
514+ MCUX_CSSL_FP_FUNCTION_CALL_BEGIN (res_kdel , tok_kdel ,
515+ mcuxClEls_KeyDelete_Async (MCXN_ELS_DICE_CDI_DERIVED_KEYSLOT ));
516+
517+ if ((MCUX_CSSL_FP_FUNCTION_CALLED (mcuxClEls_KeyDelete_Async ) != tok_kdel ) ||
518+ (MCUXCLELS_STATUS_OK_WAIT != res_kdel ))
519+ ret = -1 ;
520+
521+ MCUX_CSSL_FP_FUNCTION_CALL_END ();
522+
523+ /* Wait for hardware to finish */
524+ MCUX_CSSL_FP_FUNCTION_CALL_BEGIN (res_w , tok_w ,
525+ mcuxClEls_WaitForOperation (MCUXCLELS_ERROR_FLAGS_CLEAR ));
526+
527+ if ((MCUX_CSSL_FP_FUNCTION_CALLED (mcuxClEls_WaitForOperation ) != tok_w ) ||
528+ (MCUXCLELS_STATUS_OK != res_w ))
529+ ret = -1 ;
530+
531+ MCUX_CSSL_FP_FUNCTION_CALL_END ();
532+ }
533+
534+ if (ret == 0 ) {
535+ opts .word .value = MCUXCLELS_HKDF_ALGO_RFC5869 ;
536+ /* UPPROT|UKGSRC|UHKDF|FGP|KBASE|KACTV|KSIZE */
537+ props .word .value = 0x440200E1U ;
538+
539+ /* Trigger the HKDF command.
540+ * We just give the names of token and return value
541+ * since it's declared within the macro */
542+ MCUX_CSSL_FP_FUNCTION_CALL_BEGIN (res_hkdf , tok_hkdf ,
543+ mcuxClEls_Hkdf_Rfc5869_Async (opts ,
544+ MCXN_ELS_DICE_CDI_INITIAL_KEYSLOT ,
545+ MCXN_ELS_DICE_CDI_DERIVED_KEYSLOT ,
546+ props , deriv ));
547+
548+ if ((MCUX_CSSL_FP_FUNCTION_CALLED (mcuxClEls_Hkdf_Rfc5869_Async ) != tok_hkdf ) ||
549+ (MCUXCLELS_STATUS_OK_WAIT != res_hkdf ))
550+ ret = -1 ;
551+
552+ MCUX_CSSL_FP_FUNCTION_CALL_END ();
553+
554+ /* Wait for hardware to finish */
555+ MCUX_CSSL_FP_FUNCTION_CALL_BEGIN (res_w , tok_w ,
556+ mcuxClEls_WaitForOperation (MCUXCLELS_ERROR_FLAGS_CLEAR ));
557+
558+ if ((MCUX_CSSL_FP_FUNCTION_CALLED (mcuxClEls_WaitForOperation ) != tok_w ) ||
559+ (MCUXCLELS_STATUS_OK != res_w ))
560+ ret = -1 ;
561+
562+ MCUX_CSSL_FP_FUNCTION_CALL_END ();
563+ }
564+
565+ if (ret == 0 )
566+ cdi_step ++ ;
567+
568+ return ret ;
518569}
519570
520571int hal_dice_create_attest_key (void )
0 commit comments