1+ from test .penetrationtests .sca .host_scripts .sca_sha3_functions import *
2+ from communication .sca_sha3_commands import OTSHA3
3+ from python .runfiles import Runfiles
4+ from communication .chip import *
5+ from test .penetrationtests .util .utils import *
6+ import os
7+ import json
8+ import random
9+ from Crypto .Hash import SHA3_256
10+
11+
12+ ignored_keys_set = set ([])
13+
14+ def reset_test (opentitantool , target ):
15+ reset_target (opentitantool )
16+ while True :
17+ read_line = str (target .readline ().decode ().strip ())
18+ if len (read_line ) > 0 :
19+ if "firmware_sca.c" in read_line :
20+ return True
21+ else :
22+ return False
23+
24+
25+ def init_test (opentitantool , target ):
26+ sha3sca = OTSHA3 (target , "ujson" )
27+ device_id , owner_page , boot_log , boot_measurements , version = sha3sca .init (0 )
28+ device_id_json = json .loads (device_id )
29+ owner_page_json = json .loads (owner_page )
30+ boot_log_json = json .loads (boot_log )
31+ boot_measurements_json = json .loads (boot_measurements )
32+
33+ expected_device_id_keys = {
34+ "device_id" ,
35+ "rom_digest" ,
36+ "icache_en" ,
37+ "dummy_instr_en" ,
38+ "clock_jitter_locked" ,
39+ "clock_jitter_en" ,
40+ "sram_main_readback_locked" ,
41+ "sram_main_readback_en" ,
42+ "sram_ret_readback_locked" ,
43+ "sram_ret_readback_en"
44+ }
45+ actual_device_id_keys = set (device_id_json .keys ())
46+
47+ if not actual_device_id_keys == expected_device_id_keys :
48+ print ("device_id keys do not match the expected set." )
49+ print (f"Expected: { expected_device_id_keys } " )
50+ print (f"Actual: { actual_device_id_keys } " )
51+ return False
52+
53+ expected_owner_page_keys = {
54+ "config_version" ,
55+ "sram_exec_mode" ,
56+ "ownership_key_alg" ,
57+ "update_mode" ,
58+ "min_security_version_bl0" ,
59+ "lock_constraint"
60+ }
61+ actual_owner_page_keys = set (owner_page_json .keys ())
62+ if not expected_owner_page_keys == actual_owner_page_keys :
63+ print ("owner_page keys do not match the expected set." )
64+ print (f"Expected: { expected_owner_page_keys } " )
65+ print (f"Actual: { actual_owner_page_keys } " )
66+ return False
67+
68+ expected_boot_log_keys = {
69+ "digest" ,
70+ "identifier" ,
71+ "scm_revision_low" ,
72+ "scm_revision_high" ,
73+ "rom_ext_slot" ,
74+ "rom_ext_major" ,
75+ "rom_ext_minor" ,
76+ "rom_ext_size" ,
77+ "bl0_slot" ,
78+ "ownership_state" ,
79+ "ownership_transfers" ,
80+ "rom_ext_min_sec_ver" ,
81+ "bl0_min_sec_ver" ,
82+ "primary_bl0_slot" ,
83+ "retention_ram_initialized"
84+ }
85+ actual_boot_log_keys = set (boot_log_json .keys ())
86+ if not expected_boot_log_keys == actual_boot_log_keys :
87+ print ("boot_log keys do not match the expected set." )
88+ print (f"Expected: { expected_boot_log_keys } " )
89+ print (f"Actual: { actual_boot_log_keys } " )
90+ return False
91+
92+ expected_boot_measurements_keys = {
93+ "bl0" ,
94+ "rom_ext"
95+ }
96+ actual_boot_measurements_keys = set (boot_measurements_json .keys ())
97+ if not expected_boot_measurements_keys == actual_boot_measurements_keys :
98+ print ("boot_measurements keys do not match the expected set." )
99+ print (f"Expected: { expected_boot_measurements_keys } " )
100+ print (f"Actual: { actual_boot_measurements_keys } " )
101+ return False
102+
103+ if "PENTEST" not in version :
104+ print ("Did not receive a PENTEST version." )
105+ print (f"Actual: { version } " )
106+ return False
107+
108+ return True
109+
110+ def char_sha3_single_absorb_test (opentitantool_path , iterations ):
111+ text = [0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ]
112+ masking = True
113+ actual_result = char_sha3_single_absorb (opentitantool_path , iterations , masking , text )
114+ try :
115+ actual_result_json = json .loads (actual_result )
116+ except :
117+ print ("char_sha3_single_absorb gave an unexpected result" )
118+ print (f"Actual: { actual_result } " )
119+ return False
120+
121+ mac = SHA3_256 .new ()
122+ mac .update (bytes (text ))
123+ tag = bytearray (mac .digest ())
124+ expected_result = [x for x in tag ]
125+
126+ expected_result_json = {
127+ "batch_digest" : expected_result ,
128+ }
129+ if not compare_json_data (actual_result_json , expected_result_json , ignored_keys_set ):
130+ print ("char_sha3_single_absorb failed" )
131+ print (f"Expected: { expected_result_json } " )
132+ print (f"Actual: { actual_result_json } " )
133+ print ("" )
134+ return False
135+ return True
136+
137+ def char_sha3_batch_absorb_test (opentitantool_path , iterations , num_segments ):
138+ text = [0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ]
139+ masking = True
140+ actual_result = char_sha3_batch_absorb (opentitantool_path , iterations , num_segments , masking , text )
141+ try :
142+ actual_result_json = json .loads (actual_result )
143+ except :
144+ print ("char_sha3_batch_absorb gave an unexpected result" )
145+ print (f"Actual: { actual_result } " )
146+ return False
147+
148+ # Seed the synchronized randomness with the same seed as in the chip which is 1
149+ random .seed (1 )
150+
151+ # Generate the batch data
152+ sample_fixed = 0
153+ for _ in range (iterations ):
154+ xor_tag = [0 for _ in range (32 )]
155+ for __ in range (num_segments ):
156+ if sample_fixed == 1 :
157+ batch_data = text
158+ else :
159+ batch_data = [random .randint (0 , 255 ) for _ in range (16 )]
160+ dummy = [random .randint (0 , 255 ) for _ in range (16 )]
161+ sample_fixed = dummy [0 ] & 0x1
162+ mac = SHA3_256 .new ()
163+ mac .update (bytes (batch_data ))
164+ tag = [x for x in bytearray (mac .digest ())]
165+ xor_tag = [xor_tag [i ] ^ tag [i ] for i in range (32 )]
166+
167+ expected_result_json = {
168+ "batch_digest" : xor_tag ,
169+ }
170+ if not compare_json_data (actual_result_json , expected_result_json , ignored_keys_set ):
171+ print ("char_sha3_batch_absorb failed" )
172+ print (f"Expected: { expected_result_json } " )
173+ print (f"Actual: { actual_result_json } " )
174+ print ("" )
175+ return False
176+ return True
177+
178+ def main ():
179+ r = Runfiles .Create ()
180+ opentitantool_path = r .Rlocation ("lowrisc_opentitan/sw/host/opentitantool/opentitantool" )
181+
182+ firmware_target_name = os .environ .get ("SELECTED_FIRMWARE_TARGET" , "pen_test_sca_silicon_owner_gb_rom_ext" )
183+ firmware_path = r .Rlocation (f"lowrisc_opentitan/sw/device/tests/penetrationtests/firmware/{ firmware_target_name } .img" )
184+
185+ target = DUT ()
186+
187+ flash_target (opentitantool_path , firmware_path )
188+ target .dump_all ()
189+
190+ if not reset_test (opentitantool_path , target ):
191+ print ("Reset test failure" )
192+ return False
193+
194+ if not init_test (opentitantool_path , target ):
195+ print ("Init test failure" )
196+ return False
197+
198+ iterations = 10
199+ num_segments_list = [1 , 2 , 5 , 10 , 12 , 50 ]
200+
201+ char_sha3_single_absorb_test (opentitantool_path , iterations )
202+ for num_segments in num_segments_list :
203+ char_sha3_batch_absorb_test (opentitantool_path , iterations , num_segments )
204+
205+ print ("Testing finished" )
206+ return True
207+
208+ if __name__ == "__main__" :
209+ main ()
0 commit comments