|
25 | 25 | "BL_PUBKEY": [242, 244, 246], |
26 | 26 | "APP_PUBKEY": [202, 204, 206], |
27 | 27 | } |
28 | | -KEY_SLOT_METADATA: str = "0x10ba0030" |
29 | 28 | KMU_KEY_SLOT_DEST_ADDR: str = "0x20000000" |
30 | 29 | ALGORITHM: str = "ED25519" |
31 | 30 | POLICIES = ["revokable", "lock", "lock-last"] |
32 | 31 | NRF54L15_KEY_POLICIES: dict[str, str] = {"revokable": "REVOKED", "lock": "LOCKED"} |
33 | 32 |
|
| 33 | +METADATA_ALGORITHM_MAPPING: dict[str, int] = { |
| 34 | + "ED25519": 10, |
| 35 | +} |
| 36 | +METADATA_RPOLICY_MAPPING: dict[str, int] = { |
| 37 | + 'ROTATING': 1, |
| 38 | + 'LOCKED': 2, |
| 39 | + 'REVOKED': 3 |
| 40 | +} |
| 41 | + |
| 42 | + |
| 43 | +# Implemented based on |
| 44 | +# https://github.com/nrfconnect/sdk-nrf/blob/f3ac9cfb784d163f4c1af11209976fcd5c403d5a/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.c#L41 |
| 45 | +@dataclass |
| 46 | +class KmuMetadata: |
| 47 | + metadata_version: int = 0 |
| 48 | + key_usage_scheme: int = 0 |
| 49 | + reserved: int = 0 |
| 50 | + algorithm: int = 0 |
| 51 | + size: int = 0 |
| 52 | + rpolicy: int = 0 |
| 53 | + usage_flags: int = 0 |
| 54 | + |
| 55 | + @property |
| 56 | + def value(self) -> int: |
| 57 | + # Combine all fields into a single 32-bit integer |
| 58 | + value = 0 |
| 59 | + value |= (self.metadata_version & 0xF) << 0 # (4 bits) |
| 60 | + value |= (self.key_usage_scheme & 0x3) << 4 # (2 bits) |
| 61 | + value |= (self.reserved & 0x3FF) << 6 # (10 bits) |
| 62 | + value |= (self.algorithm & 0xF) << 16 # (4 bits) |
| 63 | + value |= (self.size & 0x7) << 20 # (3 bits) |
| 64 | + value |= (self.rpolicy & 0x3) << 23 # (2 bits) |
| 65 | + value |= (self.usage_flags & 0x7F) << 25 # (7 bits) |
| 66 | + |
| 67 | + return value |
| 68 | + |
| 69 | + @classmethod |
| 70 | + def from_value(cls, value: int): |
| 71 | + metadata_version = (value >> 0) & 0xF |
| 72 | + key_usage_scheme = (value >> 4) & 0x3 |
| 73 | + reserved = (value >> 6) & 0x3FF |
| 74 | + algorithm = (value >> 16) & 0xF |
| 75 | + size = (value >> 20) & 0x7 |
| 76 | + rpolicy = (value >> 23) & 0x3 |
| 77 | + usage_flags = (value >> 25) & 0x7F |
| 78 | + |
| 79 | + return cls( |
| 80 | + metadata_version, key_usage_scheme, reserved, |
| 81 | + algorithm, size, rpolicy, usage_flags |
| 82 | + ) |
| 83 | + |
| 84 | + def __str__(self) -> str: |
| 85 | + return f'0x{self.value:08x}' |
| 86 | + |
34 | 87 |
|
35 | 88 | @dataclass |
36 | 89 | class SlotParams: |
37 | 90 | id: int |
38 | 91 | value: str |
39 | 92 | rpolicy: str |
| 93 | + metadata: str |
40 | 94 | algorithm: str = ALGORITHM |
41 | 95 | dest: str = KMU_KEY_SLOT_DEST_ADDR |
42 | | - metadata: str = KEY_SLOT_METADATA |
43 | 96 |
|
44 | 97 | def asdict(self) -> dict[str, str]: |
45 | 98 | return asdict(self) |
@@ -232,14 +285,26 @@ def _generate_slots(self, keyname: str, keys: str, policy: str) -> list[SlotPara |
232 | 285 | else: |
233 | 286 | key_policy = NRF54L15_KEY_POLICIES[policy] |
234 | 287 | slot_id = KEY_SLOTS[keyname][slot_idx] |
235 | | - slot = SlotParams(id=slot_id, value=pub_key_hex, rpolicy=key_policy) |
| 288 | + |
| 289 | + metadata = KmuMetadata( |
| 290 | + metadata_version=0, |
| 291 | + key_usage_scheme=3, |
| 292 | + reserved=0, |
| 293 | + algorithm=METADATA_ALGORITHM_MAPPING[ALGORITHM], |
| 294 | + size=3, |
| 295 | + rpolicy=METADATA_RPOLICY_MAPPING[key_policy], |
| 296 | + usage_flags=8 |
| 297 | + ) |
| 298 | + slot = SlotParams( |
| 299 | + id=slot_id, value=pub_key_hex, rpolicy=key_policy, metadata=str(metadata) |
| 300 | + ) |
236 | 301 |
|
237 | 302 | slots.append(slot) |
238 | 303 |
|
239 | 304 | return slots |
240 | 305 |
|
241 | 306 | @staticmethod |
242 | | - def _get_public_key_hex(keyfile: str) -> str: |
| 307 | + def _get_public_key_hex(keyfile: str | Path) -> str: |
243 | 308 | """Return the public key hex from the given keyfile.""" |
244 | 309 | with open(keyfile, "rb") as f: |
245 | 310 | data = f.read() |
|
0 commit comments