Skip to content

Commit 8a58d6c

Browse files
authored
docs: Document MLDSA pk hash calculation (#3616)
Adds additional vendor and owner PK hash computations for MLDSA
1 parent 15fa4d3 commit 8a58d6c

1 file changed

Lines changed: 99 additions & 0 deletions

File tree

rom/dev/README.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
13741473
The owner PK hash is SHA2-384 over the serialized `ImageOwnerPubKeys` struct, which contains:

0 commit comments

Comments
 (0)