|
40 | 40 | #include "hal/armv8m_tz.h" |
41 | 41 | #endif |
42 | 42 |
|
| 43 | +#if defined(WOLFCRYPT_TZ_PSA) && defined(WOLFBOOT_DICE_HW) |
| 44 | +#include "mcuxClEls.h" |
| 45 | +#include "mcuxClEls_Kdf.h" |
| 46 | +#include "mcuxClEls_Ecc.h" |
| 47 | +#include "mcuxClEls_KeyManagement.h" |
| 48 | +#endif |
| 49 | + |
43 | 50 | #ifdef WOLFCRYPT_SECURE_MODE |
44 | 51 | void hal_trng_init(void); |
45 | 52 | int hal_trng_get_entropy(unsigned char *out, unsigned int len); |
@@ -212,7 +219,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) |
212 | 219 | return 0; |
213 | 220 | } |
214 | 221 |
|
215 | | -#ifdef WOLFCRYPT_SECURE_MODE |
| 222 | +#if defined(WOLFCRYPT_SECURE_MODE) && !defined(NONSECURE_APP) |
216 | 223 | #define ELS_CMD_RND_REQ 24U |
217 | 224 |
|
218 | 225 | void hal_trng_init(void) |
@@ -383,3 +390,172 @@ void uart_write(const char *buf, unsigned int sz) |
383 | 390 | sz -= line_sz + 1U; |
384 | 391 | } |
385 | 392 | } |
| 393 | + |
| 394 | +#if defined(WOLFCRYPT_TZ_PSA) && defined(WOLFBOOT_DICE_HW) |
| 395 | + |
| 396 | +/* Key slot holding the UDS (pre-loaded by ROM before DICE). |
| 397 | + * TODO: Verify slot number from MCXN947 RM / ROM source. */ |
| 398 | +#define MCXN_ELS_DICE_UDS_KEYSLOT 0U /* TODO: verify */ |
| 399 | + |
| 400 | +/* Key slot pre-loaded by ROM DICE: HKDF(UDS, wolfBoot_hash) -> initial CDI. |
| 401 | + * TODO: Verify slot number from MCXN947 RM / ROM source. */ |
| 402 | +#define MCXN_ELS_DICE_CDI_INITIAL_KEYSLOT 0U /* TODO: verify */ |
| 403 | + |
| 404 | +/* wolfBoot stores the boot-measurement-derived CDI here. |
| 405 | + * TODO: Confirm this slot is free at runtime (not reserved by ROM or PSA). */ |
| 406 | +#define MCXN_ELS_DICE_CDI_DERIVED_KEYSLOT 20U /* example — verify availability */ |
| 407 | + |
| 408 | +/* wolfBoot stores the per-boot IAK (P-256) here. |
| 409 | + * TODO: Confirm this slot is free at runtime (not reserved by ROM or PSA). */ |
| 410 | +#define MCXN_ELS_DICE_IAK_KEYSLOT 21U /* example — verify availability */ |
| 411 | + |
| 412 | +int hal_attestation_get_ueid(uint8_t *buf, size_t *len) |
| 413 | +{ |
| 414 | + /* |
| 415 | + * Derive 32-byte UEID from UDS via ELS HKDF SP800-56C. |
| 416 | + * Using the UDS key slot matches the software path hash(UDS) -> UEID. |
| 417 | + * Output goes to system memory (not a keystore slot). |
| 418 | + * |
| 419 | + * buf[0] = WOLFBOOT_UEID_TYPE_RANDOM (0x01) |
| 420 | + * buf[1..32] = 32 bytes from ELS HKDF SP800-56C |
| 421 | + * *len = 33 (= WOLFBOOT_DICE_UEID_LEN) |
| 422 | + * |
| 423 | + * TODO: Implement using mcuxClEls_Hkdf_Sp80056c_Async: |
| 424 | + * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(..., |
| 425 | + * mcuxClEls_Hkdf_Sp80056c_Async( |
| 426 | + * MCXN_ELS_DICE_UDS_KEYSLOT, |
| 427 | + * &buf[1], |
| 428 | + * (uint8_t*)"WOLFBOOT-UEID", 13)); |
| 429 | + * mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR); |
| 430 | + * buf[0] = 0x01; |
| 431 | + * *len = 33; |
| 432 | + */ |
| 433 | + (void)buf; |
| 434 | + (void)len; |
| 435 | + return -1; /* placeholder */ |
| 436 | +} |
| 437 | + |
| 438 | +int hal_attestation_get_lifecycle(uint32_t *lifecycle) |
| 439 | +{ |
| 440 | + if (lifecycle == NULL) |
| 441 | + return -1; |
| 442 | + *lifecycle = 0x3000u; /* PSA_LIFECYCLE_SECURED */ |
| 443 | + return 0; |
| 444 | +} |
| 445 | + |
| 446 | +int hal_dice_update_cdi(const uint8_t *measurement, size_t meas_len) |
| 447 | +{ |
| 448 | + static int cdi_step = 0; |
| 449 | + |
| 450 | + if (cdi_step == 0) { |
| 451 | + /* |
| 452 | + * Component [0] is the wolfBoot hash. The ROM already incorporated |
| 453 | + * it as: HKDF(UDS, wolfBoot_hash) -> initial_CDI. |
| 454 | + * Skip re-applying it — doing so would produce the wrong CDI chain. |
| 455 | + */ |
| 456 | + cdi_step++; |
| 457 | + return 0; |
| 458 | + } |
| 459 | + |
| 460 | + /* |
| 461 | + * Component [1+]: mix this measurement into the CDI chain via ELS HKDF RFC5869. |
| 462 | + * |
| 463 | + * The 32-byte derivation data buffer must be composed as: |
| 464 | + * deriv[0..30] = info/label (31 bytes, zero-padded) |
| 465 | + * deriv[31] = 0x01 (RFC5869 counter byte for single-block expansion) |
| 466 | + * The SDK does NOT add this formatting automatically. |
| 467 | + * |
| 468 | + * NOTE: The exact label policy (truncate SHA-384 to 31 bytes, or pre-hash |
| 469 | + * to SHA-256 then take first 31 bytes) and alignment with the ROM's approach |
| 470 | + * for component[0] must be confirmed before finalizing this implementation. |
| 471 | + * See also: whether a separate RFC5869 Extract step is needed before Expand. |
| 472 | + * |
| 473 | + * TODO: Implement using mcuxClEls_KeyDelete_Async + mcuxClEls_Hkdf_Rfc5869_Async: |
| 474 | + * |
| 475 | + * // Step 1: Free target slot (KDELETE, cmd 0xB) |
| 476 | + * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(..., |
| 477 | + * mcuxClEls_KeyDelete_Async(MCXN_ELS_DICE_CDI_DERIVED_KEYSLOT)); |
| 478 | + * mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR); |
| 479 | + * |
| 480 | + * // Step 2: Compose derivation data {label[31 bytes], counter[1 byte]} |
| 481 | + * uint8_t deriv[MCUXCLELS_HKDF_RFC5869_DERIVATIONDATA_SIZE] = {0}; |
| 482 | + * size_t label_len = (meas_len < 31u) ? meas_len : 31u; |
| 483 | + * memcpy(deriv, measurement, label_len); |
| 484 | + * deriv[31] = 0x01u; |
| 485 | + * |
| 486 | + * // Step 3: Derive new CDI into freed slot |
| 487 | + * mcuxClEls_HkdfOption_t opts = {0}; |
| 488 | + * opts.bits.rtfdrvdat = MCUXCLELS_HKDF_VALUE_RTF_DERIV_DISABLE; |
| 489 | + * mcuxClEls_KeyProp_t props = {.word.value = |
| 490 | + * MCUXCLELS_KEYPROPERTY_VALUE_HKDF | MCUXCLELS_KEYPROPERTY_VALUE_ACTIVE}; |
| 491 | + * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(..., |
| 492 | + * mcuxClEls_Hkdf_Rfc5869_Async(opts, |
| 493 | + * MCXN_ELS_DICE_CDI_INITIAL_KEYSLOT, |
| 494 | + * MCXN_ELS_DICE_CDI_DERIVED_KEYSLOT, |
| 495 | + * props, deriv)); |
| 496 | + * mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR); |
| 497 | + */ |
| 498 | + cdi_step++; |
| 499 | + (void)measurement; |
| 500 | + (void)meas_len; |
| 501 | + return -1; /* placeholder */ |
| 502 | +} |
| 503 | + |
| 504 | +int hal_dice_create_attest_key(void) |
| 505 | +{ |
| 506 | + /* |
| 507 | + * Generate P-256 IAK from derived CDI using ELS KEYGEN. |
| 508 | + * Private key stays in ELS keystore. Public key written to system memory. |
| 509 | + * |
| 510 | + * TODO: Implement using mcuxClEls_KeyDelete_Async + mcuxClEls_EccKeyGen_Async: |
| 511 | + * |
| 512 | + * // Step 1: Free target slot (KDELETE, cmd 0xB) |
| 513 | + * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(..., |
| 514 | + * mcuxClEls_KeyDelete_Async(MCXN_ELS_DICE_IAK_KEYSLOT)); |
| 515 | + * mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR); |
| 516 | + * |
| 517 | + * // Step 2: Generate IAK into freed slot from derived CDI |
| 518 | + * static uint8_t pub_key[64] __attribute__((aligned(4))); |
| 519 | + * mcuxClEls_EccKeyGenOption_t opts = {0}; |
| 520 | + * opts.bits.kgsrc = 0; // deterministic from CDI key material |
| 521 | + * opts.bits.kgtypedh = 0; // signing key (not DH) |
| 522 | + * mcuxClEls_KeyProp_t props = {.word.value = |
| 523 | + * MCUXCLELS_KEYPROPERTY_VALUE_ECSGN | MCUXCLELS_KEYPROPERTY_VALUE_ACTIVE}; |
| 524 | + * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(..., |
| 525 | + * mcuxClEls_EccKeyGen_Async(opts, |
| 526 | + * MCXN_ELS_DICE_CDI_DERIVED_KEYSLOT, |
| 527 | + * MCXN_ELS_DICE_IAK_KEYSLOT, |
| 528 | + * props, NULL, pub_key)); |
| 529 | + * mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR); |
| 530 | + */ |
| 531 | + return -1; /* placeholder */ |
| 532 | +} |
| 533 | + |
| 534 | +int hal_dice_sign_hash(const uint8_t *hash, size_t hash_len, |
| 535 | + uint8_t *sig, size_t *sig_len) |
| 536 | +{ |
| 537 | + /* |
| 538 | + * Sign pre-hashed TBS using ELS ECSIGN with the IAK slot. |
| 539 | + * Output MUST be 64-byte raw R||S (big-endian), NOT DER-encoded. |
| 540 | + * This matches WOLFBOOT_DICE_SIG_LEN and is used directly in COSE_Sign1. |
| 541 | + * |
| 542 | + * TODO: Implement using mcuxClEls_EccSign_Async: |
| 543 | + * static uint8_t sig_buf[64] __attribute__((aligned(4))); |
| 544 | + * mcuxClEls_EccSignOption_t opts = {0}; |
| 545 | + * opts.bits.echashchl = 0; // pre-hashed input (not plain message) |
| 546 | + * MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(..., |
| 547 | + * mcuxClEls_EccSign_Async(opts, |
| 548 | + * MCXN_ELS_DICE_IAK_KEYSLOT, |
| 549 | + * hash, NULL, 0, sig_buf)); |
| 550 | + * mcuxClEls_WaitForOperation(MCUXCLELS_ERROR_FLAGS_CLEAR); |
| 551 | + * memcpy(sig, sig_buf, 64); |
| 552 | + * *sig_len = 64; |
| 553 | + */ |
| 554 | + (void)hash; |
| 555 | + (void)hash_len; |
| 556 | + (void)sig; |
| 557 | + (void)sig_len; |
| 558 | + return -1; /* placeholder */ |
| 559 | +} |
| 560 | + |
| 561 | +#endif /* WOLFCRYPT_TZ_PSA && WOLFBOOT_DICE_HW */ |
0 commit comments