@@ -1369,6 +1369,105 @@ As [u32; 12] fuse register value:
13691369 0xdee1ff41, 0x5adfc187, 0xe1e4edb4, 0xd3b2d909]
13701370```
13711371
1372+ ### Computing public key hashes: MLDSA step-by-step example
1373+
1374+ The following example walks through the same computation as the LMS example above, but
1375+ using PQC key type **MLDSA (type 1)** with the test keys from `image/fake-keys/src/lib.rs`.
1376+
1377+ #### MLDSA Step 1: Hash each vendor ECC public key
1378+
1379+ The ECC keys and their hashes are identical to the LMS example — see
1380+ [Step 1 above](#step-1-hash-each-vendor-ecc-public-key). The ECC key descriptor is
1381+ independent of the PQC key type.
1382+
1383+ #### MLDSA Step 2: Hash each vendor MLDSA public key
1384+
1385+ Each MLDSA-87 public key is a 2592-byte array (`[u32; 648]`). When serialized via
1386+ `as_bytes()`, each `u32` word is written in little-endian byte order — for example, the
1387+ Rust value `0x3bf1c072` becomes bytes `72 c0 f1 3b` in memory. Unlike LMS keys, MLDSA
1388+ keys are not subject to any additional encoding — these raw bytes are hashed directly
1389+ with SHA2-384.
1390+
1391+ **MLDSA Key 0:**
1392+ ```
1393+ Size: 2592 bytes (648 u32 words)
1394+ First 24 bytes: 72c0f13b 7d937e22 69b6988d 6daadc3a e78acd11 940cfc0d ...
1395+
1396+ SHA384 (standard): f1097978 0adae470 dcd4eeb8 5749a2e4 2e70c055 ebac46e4
1397+ 07c2c404 b46473d8 189117ed 8c83dde4 9f941e6a 1b6c6d4c
1398+ SHA384 (reversed-dword): 787909f1 70e4da0a b8eed4dc e4a24957 55c0702e e446aceb
1399+ 04c4c207 d87364b4 ed179118 e4dd838c 6a1e949f 4c6d6c1b
1400+ ```
1401+
1402+ **MLDSA Key 1:**
1403+ ```
1404+ Size: 2592 bytes (648 u32 words)
1405+ First 24 bytes: f432346c 096d0ec9 04f8d925 1512236b e3fd1ccb bda9ed3a ...
1406+
1407+ SHA384 (standard): a57b6f71 ffab9844 de49e9f7 ad61476b 7446e140 517d07b1
1408+ 81447acb a6d7166f 7b89f199 b6e36174 2d0ab01c 540d26de
1409+ SHA384 (reversed-dword): 716f7ba5 4498abff f7e949de 6b4761ad 40e14674 b1077d51
1410+ cb7a4481 6f16d7a6 99f1897b 7461e3b6 1cb00a2d de260d54
1411+ ```
1412+
1413+ **MLDSA Key 2:**
1414+ ```
1415+ Size: 2592 bytes (648 u32 words)
1416+ First 24 bytes: 2bc91a00 7d3e5a4f e6b3f2ec cb1aaa0d 278d9786 44b25fed ...
1417+
1418+ SHA384 (standard): 7f2f3c55 e8dd2481 bbee17c1 5d5773a8 01a9c0a6 84b30e47
1419+ 0ae67ecd 1ec3e7ac 19273c71 feb6bb99 10d26dd0 4ace4298
1420+ SHA384 (reversed-dword): 553c2f7f 8124dde8 c117eebb a873575d a6c0a901 470eb384
1421+ cd7ee60a ace7c31e 713c2719 99bbb6fe d06dd210 9842ce4a
1422+ ```
1423+
1424+ **MLDSA Key 3:**
1425+ ```
1426+ Size: 2592 bytes (648 u32 words)
1427+ First 24 bytes: 378dcb02 a6db3481 d51e9913 14da1567 a211290e f4c3d02f ...
1428+
1429+ SHA384 (standard): 79fbeb0a 6ebc354b ccf48dd1 5b6c9142 a62af0c5 198c0de1
1430+ 365fbcb0 b2463ee5 103ccae3 4504ab83 04b37886 5c9a28ae
1431+ SHA384 (reversed-dword): 0aebfb79 4b35bc6e d18df4cc 42916c5b c5f02aa6 e10d8c19
1432+ b0bc5f36 e53e46b2 e3ca3c10 83ab0445 8678b304 ae289a5c
1433+ ```
1434+
1435+ #### MLDSA Step 3: Build the ECC key descriptor (196 bytes)
1436+
1437+ Same as the LMS example — the ECC descriptor is independent of PQC key type. See
1438+ [Step 3 above](#step-3-build-the-ecc-key-descriptor-196-bytes).
1439+
1440+ #### MLDSA Step 4: Build the PQC (MLDSA) key descriptor (1540 bytes)
1441+
1442+ The PQC key descriptor struct always has 32 hash slots (`VENDOR_PQC_MAX_KEY_COUNT`).
1443+ For MLDSA, only 4 keys are populated; the remaining 28 slots are zero-filled.
1444+
1445+ ```
1446+ Header (4 bytes): 01 00 01 04 (version=1, key_type=1=MLDSA, key_hash_count=4)
1447+ MLDSA key 0 hash (48 bytes, reversed-dword): 787909f1 70e4da0a ... 4c6d6c1b
1448+ MLDSA key 1 hash (48 bytes, reversed-dword): 716f7ba5 4498abff ... de260d54
1449+ MLDSA key 2 hash (48 bytes, reversed-dword): 553c2f7f 8124dde8 ... 9842ce4a
1450+ MLDSA key 3 hash (48 bytes, reversed-dword): 0aebfb79 4b35bc6e ... ae289a5c
1451+ ... (keys 4-31 are zero-filled)
1452+
1453+ Total: 4 + (32 × 48) = 1540 bytes
1454+ ```
1455+
1456+ #### MLDSA Step 5: Compute the vendor PK descriptor hash
1457+
1458+ ```
1459+ Input = ECC descriptor (196 bytes) || PQC descriptor (1540 bytes) = 1736 bytes
1460+
1461+ SHA384 (standard byte order):
1462+ 30399676 a17e3e97 3677b3ff 862f4bf2 d1932d88 4778453c
1463+ 376fe00d c93fb8aa 0770f3eb f3411a08 53e9c57e ce8a2980
1464+
1465+ As [ u32; 12] fuse register value:
1466+ [ 0x30399676, 0xa17e3e97, 0x3677b3ff, 0x862f4bf2,
1467+ 0xd1932d88, 0x4778453c, 0x376fe00d, 0xc93fb8aa,
1468+ 0x0770f3eb, 0xf3411a08, 0x53e9c57e, 0xce8a2980]
1469+ ```
1470+
13721471#### Owner PK hash
13731472
13741473The owner PK hash is SHA2-384 over the serialized `ImageOwnerPubKeys` struct, which contains:
0 commit comments