[util] implement flash scrambling key derivation
The address and data flash scrambling keys are computed from seeds
stored in the OTP, and netlist constants embedded in the RTL. This
implements the same flash scrambling key derivation scheme implemented
in the RTL so flash VMEM images can be pre-scrabled for backdoor loading
in DV.
Signed-off-by: Timothy Trippel <ttrippel@google.com>
diff --git a/util/design/gen-flash-img.py b/util/design/gen-flash-img.py
index 90b580a..754dbac 100755
--- a/util/design/gen-flash-img.py
+++ b/util/design/gen-flash-img.py
@@ -15,6 +15,7 @@
import re
import sys
from dataclasses import dataclass
+from enum import Enum
from pathlib import Path
from typing import List
@@ -74,6 +75,24 @@
# ------------------------------------------------------------------------------
+class FlashScramblingKeyType(Enum):
+ ADDRESS = 1
+ DATA = 2
+
+
+# Flash scrambling key computation parameters.
+KEY_TYPE_2_IV = {
+ FlashScramblingKeyType.ADDRESS: 0x97883548F536F544,
+ FlashScramblingKeyType.DATA: 0xC5F5C1D8AEF35040,
+}
+KEY_TYPE_2_FINALIZATION_CONST = {
+ FlashScramblingKeyType.ADDRESS: 0x39AED01B4B2277312E9480868216A281,
+ FlashScramblingKeyType.DATA: 0x1D888AC88259C44AAB06CB4A4C65A7EA,
+}
+FLASH_KEY_COMPUTATION_KEY_SIZE = OTP_FLASH_ADDR_KEY_SEED_SIZE // 2
+FLASH_KEY_COMPUTATION_KEY_MASK = (2**FLASH_KEY_COMPUTATION_KEY_SIZE) - 1
+
+
@dataclass
class FlashScramblingConfigs:
scrambling_enabled: bool = False
@@ -150,11 +169,36 @@
OTP_SECRET1_BLOCK_SIZE)
+def _compute_flash_scrambling_key(scrambling_configs: FlashScramblingConfigs,
+ key_type: FlashScramblingKeyType) -> int:
+ if key_type == FlashScramblingKeyType.ADDRESS:
+ key_seed = scrambling_configs.addr_key_seed
+ else:
+ key_seed = scrambling_configs.data_key_seed
+ full_key = 0
+ for i in range(2):
+ round_1_present_key = (key_seed >>
+ (FLASH_KEY_COMPUTATION_KEY_SIZE *
+ i)) & FLASH_KEY_COMPUTATION_KEY_MASK
+ key_half = 0
+ for j in range(2):
+ if j == 0:
+ cipher = Present(round_1_present_key)
+ key_half = cipher.encrypt(
+ KEY_TYPE_2_IV[key_type]) ^ KEY_TYPE_2_IV[key_type]
+ else:
+ cipher = Present(KEY_TYPE_2_FINALIZATION_CONST[key_type])
+ key_half = cipher.encrypt(key_half) ^ key_half
+ full_key |= key_half << (64 * i)
+ return full_key
+
+
def _compute_flash_scrambling_keys(
scrambling_configs: FlashScramblingConfigs) -> None:
- # TODO: implement key computation
- scrambling_configs.addr_key = 0
- scrambling_configs.data_key = 0
+ scrambling_configs.addr_key = _compute_flash_scrambling_key(
+ scrambling_configs, FlashScramblingKeyType.ADDRESS)
+ scrambling_configs.data_key = _compute_flash_scrambling_key(
+ scrambling_configs, FlashScramblingKeyType.DATA)
def _reformat_flash_vmem(