blob: 50073146d5376291dd22ea5e9ba38caa7e4c3a4a [file] [log] [blame]
Karl Zhang3de5ab12021-05-31 11:45:48 +08001/*
Nik Dewally298a8042024-07-23 15:03:13 +01002 * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
Karl Zhang3de5ab12021-05-31 11:45:48 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "class_forwards.hpp"
9
10#include "boilerplate.hpp"
11#include "gibberish.hpp"
12#include "compute.hpp"
13#include "string_ops.hpp"
14#include "data_blocks.hpp"
15#include "psa_asset.hpp"
16#include "find_or_create_asset.hpp"
17#include "template_line.hpp"
18#include "tf_fuzz.hpp"
19#include "crypto_asset.hpp"
20#include "psa_call.hpp"
21#include "sst_call.hpp"
22#include "sst_asset.hpp"
23#include "crypto_asset.hpp"
24#include "variables.hpp"
25
26
27
28/**********************************************************************************
29 Methods of class sst_set_call follow:
30**********************************************************************************/
31
32sst_set_call::sst_set_call (tf_fuzz_info *test_state, // (constructor)
33 long &call_ser_no,
34 asset_search how_asset_found)
35 : sst_call(test_state, call_ser_no, how_asset_found)
36{
37 // Copy the boilerplate text into local buffers:
38 prep_code.assign (""); // will fill in, depending upon template line content
39 call_code.assign (test_state->bplate->bplate_string[set_sst_call]);
40 check_code.assign (test_state->bplate->bplate_string[set_sst_check]);
41 call_description = "SST-set call";
42}
43sst_set_call::~sst_set_call (void)
44{
45 return; // just to have something to pin a breakpoint onto
46}
47
48bool sst_set_call::copy_call_to_asset (void)
49{
50 vector<psa_asset*>::iterator found_asset;
51
52 found_asset = resolve_asset (yes_create_asset, psa_asset_usage::all);
53 // Copy over everything relevant:
54 if (asset_info.how_asset_found != asset_search::not_found) {
55 asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
56 /* Note: The vector is base-class, but the assets in this list
57 themselves *really are* sst_asset-type objects. */
58 int i = asset_info.the_asset->set_data.n_set_vars; // save this
Mate Toth-Palffba10e2021-09-22 21:38:03 +020059 asset_info.the_asset->set_data = set_data;
Karl Zhang3de5ab12021-05-31 11:45:48 +080060 asset_info.the_asset->set_data.n_set_vars = set_data.n_set_vars = ++i;
61 asset_info.the_asset->set_data.flags_string.assign (set_data.flags_string);
62 if (asset_info.how_asset_found == asset_search::created_new) {
63 asset_info.the_asset->asset_info.name_specified = asset_info.name_specified;
64 asset_info.the_asset->asset_info.set_name (asset_info.get_name());
65 asset_info.the_asset->asset_info.asset_ser_no = asset_info.asset_ser_no;
66 asset_info.the_asset->asset_info.id_n = asset_info.id_n;
67 }
68 }
69 return true;
70}
71
72bool sst_set_call::copy_asset_to_call (void)
73{
74 // Get updated asset info from the asset:
75 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
76 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
77 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
78 exp_data.data = asset_info.the_asset->exp_data.data;
79 return true;
80}
81
82void sst_set_call::fill_in_prep_code (void)
83{
84 string var_name, length_var_name, var_name_suffix, length_var_name_suffix,
85 temp_string;
86 vector<variable_info>::iterator assign_variable;
87
88 if (assign_data_var_specified) {
89 var_name.assign (assign_data_var + "_data");
90 length_var_name.assign (assign_data_var + "_length");
91 /* If actual-data variable doesn't already exist, create variable tracker,
92 and write declaration for it: */
93 assign_variable = test_state->find_var (assign_data_var);
94 if (assign_variable == test_state->variable.end()) {
95 // No such variable exists, so:
96 test_state->make_var (assign_data_var);
97 assign_variable = test_state->find_var (assign_data_var);
98 prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
99 find_replace_1st ("$var", var_name, prep_code);
100 temp_string = (char *) assign_variable->value;
101 find_replace_1st ("$init", temp_string, prep_code);
102 // Actual-data length:
103 prep_code.append (test_state->bplate->bplate_string[declare_size_t]);
104 find_replace_1st ("$var", length_var_name, prep_code);
105 find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
106 // Offset (always 0 for now):
107 find_replace_1st ("$offset", "0", prep_code);
108 }
109 } else {
110 // Single string of two lines declaring string data and its length:
111 var_name_suffix = "_set_data";
112 length_var_name_suffix = "_set_length";
113 if (set_data.n_set_vars > 0) {
114 var_name_suffix += "_" + to_string(set_data.n_set_vars);
115 length_var_name_suffix += "_" + to_string(set_data.n_set_vars);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800116 }
117 var_name.assign (asset_info.get_name() + var_name_suffix);
118 length_var_name.assign (asset_info.get_name() + length_var_name_suffix);
119 prep_code = test_state->bplate->bplate_string[declare_string];
120 find_replace_1st ("$var", var_name, prep_code);
121 find_replace_1st ("$init", set_data.get(), prep_code);
122 temp_string.assign (test_state->bplate->bplate_string[declare_int]);
123 find_replace_1st ("static int", "static uint32_t", temp_string);
124 prep_code.append (temp_string);
125 find_replace_1st ("$var", length_var_name, prep_code);
126 find_replace_1st ("$init", to_string(set_data.get().length()), prep_code);
127 }
128}
129
130void sst_set_call::fill_in_command (void)
131{
132 string var_name, length_var_name, var_name_suffix, length_var_name_suffix,
133 temp_string;
134
135 // Fill in preceding comment:
136 if (asset_info.how_asset_found == asset_search::created_new) {
137 find_replace_1st ("$op", "Creating", call_code);
138 } else {
139 find_replace_1st ("$op", "Resetting", call_code);
140 }
141 if (asset_info.name_specified) {
142 find_replace_1st ("$description", "\"" + asset_info.get_name() + ",\"",
143 call_code);
144 } else {
145 find_replace_1st ("$description",
146 "UID = " + to_string((long) asset_info.id_n), call_code);
147 }
148 if (set_data.string_specified) {
149 find_replace_1st ("$data_source",
150 "\"" + set_data.get().substr (0, 10) + "...\"",
151 call_code);
152 } else if (set_data.file_specified) {
153 find_replace_1st ("$data_source", "from file " + set_data.file_path,
154 call_code);
155 } else {
156 find_replace_1st (" $data_source", "", call_code);
157 }
158 // Fill in the PSA command itself:
159 if (assign_data_var_specified) {
160 var_name.assign (assign_data_var + "_data");
161 length_var_name.assign (assign_data_var + "_length");
162 } else {
163 var_name_suffix = "_set_data";
164 if (set_data.n_set_vars > 0) {
165 var_name_suffix += "_" + to_string(set_data.n_set_vars);
166 }
167 var_name.assign (asset_info.get_name() + var_name_suffix);
168 length_var_name_suffix = "_set_length";
169 if (set_data.n_set_vars > 0) {
170 length_var_name_suffix += "_" + to_string(set_data.n_set_vars);
171 }
172 length_var_name.assign (asset_info.get_name() + length_var_name_suffix);
173 }
174 find_replace_1st ("$data", var_name, call_code);
175 find_replace_1st ("$flags", set_data.flags_string, call_code);
176 string id_string = to_string((long) asset_info.id_n);
177 find_replace_1st ("$uid", id_string, call_code);
178 find_replace_1st ("$length", length_var_name, call_code);
179 // Figure out what expected results:
180 if ( set_data.flags_string == "PSA_STORAGE_FLAG_WRITE_ONCE"
181 && set_data.n_set_vars > 0) {
182 exp_data.pf_specified = true;
183 exp_data.pf_result_string = "PSA_ERROR_NOT_PERMITTED";
184 }
185 calc_result_code();
186}
187
188/**********************************************************************************
189 End of methods of class sst_set_call.
190**********************************************************************************/
191
192
193/**********************************************************************************
194 Methods of class sst_get_call follow:
195**********************************************************************************/
196
197sst_get_call::sst_get_call (tf_fuzz_info *test_state, // (constructor)
198 long &call_ser_no,
199 asset_search how_asset_found)
200 : sst_call(test_state, call_ser_no, how_asset_found)
201{
202 // Copy the boilerplate text into local buffers:
203 prep_code.assign ("");
204 call_code.assign (test_state->bplate->bplate_string[get_sst_call]);
205 check_code.assign ("");
206 // depends upon the particular usage; will get it in fill_in_command()
207 call_description = "SST-get call";
208}
209sst_get_call::~sst_get_call (void)
210{
211 return; // just to have something to pin a breakpoint onto
212}
213
214bool sst_get_call::copy_call_to_asset (void)
215{
216 vector<psa_asset*>::iterator found_asset;
217
218 found_asset = resolve_asset (dont_create_asset, psa_asset_usage::active);
219 if (asset_info.how_asset_found != asset_search::not_found) {
220 // will be found for set calls, but not necessarily others
221 asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
222 // Note: Vector is of base-class type, but the assets *are* sst_asset.
223 /* Locating the asset is all we need to do here; copy_asset_to_call() will
224 do the rest. */
225 }
226 return true;
227 // TODO: Shouldn't data be copied over?
228}
229
230bool sst_get_call::copy_asset_to_call (void)
231{
232 if (asset_info.the_asset != nullptr) {
233 // will be found for set calls, but not necessarily others
234 set_data.string_specified = asset_info.the_asset->set_data.string_specified;
235 set_data.file_specified = asset_info.the_asset->set_data.file_specified;
236 set_data.set (asset_info.the_asset->set_data.get());
237 set_data.flags_string = asset_info.the_asset->set_data.flags_string;
238 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
239 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
240 asset_info.name_specified = asset_info.the_asset->asset_info.name_specified;
241 asset_info.the_asset->exp_data.n_exp_vars++;
242 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
243 }
244 return true;
245}
246
247void sst_get_call::fill_in_prep_code (void)
248{
249 string var_base, var_name, length_var_name, temp_string, var_name_suffix,
250 expected;
251 vector<variable_info>::iterator act_variable, exp_variable;
252
253 if (!(print_data || hash_data)) {
254 // Checking asset data verbatim against expected, so:
255 if (exp_data.data_var_specified) {
256 // Template specified a variable name to "check" against; use that:
257 var_base.assign (exp_data.data_var);
258 exp_variable = test_state->find_var (var_base);
259 if (exp_variable == test_state->variable.end()) {
260 test_state->make_var (var_base);
261 exp_variable = test_state->find_var (var_base);
262 var_name = var_base + "_data";
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200263 length_var_name = var_base + "_length";
Karl Zhang3de5ab12021-05-31 11:45:48 +0800264 prep_code.append (test_state->bplate->bplate_string[declare_string]);
265 find_replace_1st ("$var", var_name, prep_code);
266 temp_string = (char *) exp_variable->value;
267 find_replace_1st ("$init", temp_string, prep_code);
268 // Expected-data length:
269 temp_string.assign (test_state->bplate->bplate_string[declare_int]);
270 find_replace_1st ("static int", "static size_t", temp_string);
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200271 prep_code.append (temp_string);
272 find_replace_1st ("$var", length_var_name, prep_code);
273 find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800274 }
275 } else {
276 if (exp_data.data_specified) {
277 // Checking against literal expected data:
278 expected.assign (exp_data.data);
279 } else {
280 // Check against what we believe the asset to contain:
281 expected.assign (set_data.get());
282 }
283 var_name_suffix = "_exp_data";
284 if (exp_data.n_exp_vars > 0) {
285 var_name_suffix =
286 var_name_suffix + "_" + to_string(exp_data.n_exp_vars);
287 }
288 var_name.assign (asset_info.get_name() + var_name_suffix);
289 prep_code.assign(test_state->bplate->bplate_string[declare_string]);
290 find_replace_1st("$var", var_name, prep_code);
291 find_replace_1st("$init", expected, prep_code);
292 }
293 }
294 // Actual data:
295 if (assign_data_var_specified) {
296 var_base.assign (assign_data_var);
297 } else {
298 var_base.assign (asset_info.get_name() + "_act");
299 }
300 var_name.assign (var_base + "_data");
301 length_var_name.assign (var_base + "_length");
302 /* If actual-data variable doesn't already exist, create variable tracker,
303 and write declaration for it: */
304 act_variable = test_state->find_var (var_base);
305 if (act_variable == test_state->variable.end()) {
306 test_state->make_var (var_base);
307 act_variable = test_state->find_var (var_base);
308 prep_code.append (test_state->bplate->bplate_string[declare_big_string]);
309 find_replace_1st ("$var", var_name, prep_code);
310 temp_string = (char *) act_variable->value;
311 find_replace_1st ("$init", temp_string, prep_code);
312 // Actual-data length:
313 temp_string.assign (test_state->bplate->bplate_string[declare_int]);
314 find_replace_1st ("static int", "static size_t", temp_string);
315 prep_code.append (temp_string);
316 find_replace_1st ("$var", length_var_name, prep_code);
317 find_replace_1st ("$init", to_string(temp_string.length()), prep_code);
318 // Offset (always 0 for now):
319 find_replace_1st ("$offset", "0", prep_code);
320 }
321 // If hashing the (actual) data, then create a variable for that:
322 if (hash_data && !act_variable->hash_declared) {
323 var_name = var_base + "_hash";
324 prep_code.append (test_state->bplate->bplate_string[declare_generic]);
325 // where to put the hash of the data
326 find_replace_1st ("$type", "uint32_t", prep_code);
327 find_replace_1st ("$var", var_name, prep_code);
328 find_replace_1st ("$init", "0", prep_code); // for now...
329 act_variable->hash_declared = true;
330 }
331}
332
333void sst_get_call::fill_in_command (void)
334{
Nik Dewally298a8042024-07-23 15:03:13 +0100335 string exp_var_name, act_var_name, length_var_name,act_data_length, hash_var_name,
Karl Zhang3de5ab12021-05-31 11:45:48 +0800336 id_string, var_name_suffix;
337
338/* TODO: Flesh-out/fix this (it was a good try/start, but not quite right):
339 // Fill in preceding comment:
340 if (asset_info.how_asset_found == asset_search::created_new) {
341 find_replace_1st ("$op", "Creating", call_code);
342 } else {
343 find_replace_1st ("$op", "Resetting", call_code);
344 }
345 if (asset_info.name_specified) {
346 find_replace_1st ("$description", "\"" + asset_info.get_name() + ",\"",
347 call_code);
348 } else {
349 find_replace_1st ("$description",
350 "UID = " + to_string((long) asset_info.id_n), call_code);
351 }
352 if (set_data.string_specified) {
353 find_replace_1st ("$data_source",
354 "\"" + data.substr (0, 10) + "...\"",
355 call_code);
356 } else if (set_data.file_specified) {
357 find_replace_1st ("$data_source", "from file " + set_data.file_path,
358 call_code);
359 } else {
360 find_replace_1st (" $data_source", "", call_code);
361 }
362*/ // Fill in the call itself:
363 if (print_data || hash_data) {
364 // Dump to variable; no data-check code needed:
365 check_code.assign (test_state->bplate->bplate_string[get_sst_check]);
366 } else {
367 // Check either against literal or variable, so need data-check code too:
368 check_code.assign (test_state->bplate->bplate_string[get_sst_check_all]);
369 }
370 /* Note: Can fill in the check code identically between the dump-to-variable
371 and check-data cases, because the boilerplate for the former is just an
372 abbreviated version of the latter. The find_replace_1st() calls for
373 the check-data stuff will just simply not have any effect. */
374 if (exp_data.data_var_specified) {
375 // Check against data in variable:
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200376 exp_var_name.assign (exp_data.data_var);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800377 } else {
378 var_name_suffix = "_exp_data";
379 if (exp_data.n_exp_vars > 0) {
380 var_name_suffix =
381 var_name_suffix + "_" + to_string(exp_data.n_exp_vars);
382 }
383 exp_var_name.assign (asset_info.get_name() + var_name_suffix);
384 }
385 if (assign_data_var_specified) {
386 act_var_name.assign (assign_data_var + "_data");
387 act_data_length.assign (assign_data_var + "_length");
388 } else {
389 act_var_name.assign (asset_info.get_name() + "_act_data");
390 act_data_length.assign (asset_info.get_name() + "_act_length");
391 }
392
393 id_string = to_string((long) asset_info.id_n);
394 // Fill in the PSA command itself:
395 find_replace_1st ("$uid", id_string, call_code);
396 find_replace_all ("$length", to_string(set_data.get().length()), call_code);
397 find_replace_1st ("$offset", to_string(set_data.data_offset), call_code);
398 find_replace_1st ("$exp_data", exp_var_name, call_code);
399 find_replace_all ("$act_data", act_var_name, call_code);
400 find_replace_all ("$act_length", act_data_length, call_code);
401 // Perform most of the same substitutions in the check_code:
Nik Dewally298a8042024-07-23 15:03:13 +0100402 // TODO: Make data checks contingent upon the PSA call itself passing?
Karl Zhang3de5ab12021-05-31 11:45:48 +0800403 find_replace_1st ("$offset", "0", check_code);
404 find_replace_1st ("$exp_data", exp_var_name, check_code);
405 find_replace_all ("$act_data", act_var_name, check_code);
Nik Dewally298a8042024-07-23 15:03:13 +0100406 find_replace_all ("$length", to_string(set_data.get().length()), check_code);
407 find_replace_all ("$act_length", act_data_length, check_code);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800408 if (print_data) {
409 check_code.append (test_state->bplate->bplate_string[test_log]);
410 find_replace_1st ("$message", act_var_name, check_code);
411 }
412 if (hash_data) {
Mate Toth-Palffba10e2021-09-22 21:38:03 +0200413 hash_var_name.assign (asset_info.get_name() + "_hash");
Karl Zhang3de5ab12021-05-31 11:45:48 +0800414 // this is where to put the hash of the data
415 check_code.append (test_state->bplate->bplate_string[get_sst_hash]);
416 find_replace_all ("$act_data_var", act_var_name, check_code);
417 find_replace_all ("$hash_var", hash_var_name, check_code);
418 }
419 // Figure out what expected results:
420 calc_result_code(); // this only fills $expect check_code
421 // Fill in expected data, actual data, and length:
422}
423
424/**********************************************************************************
425 End of methods of class sst_get_call.
426**********************************************************************************/
427
428
429/**********************************************************************************
430 Methods of class sst_remove_call follow:
431**********************************************************************************/
432
433sst_remove_call::sst_remove_call (tf_fuzz_info *test_state, // (constructor)
434 long &call_ser_no,
435 asset_search how_asset_found)
436 : sst_call(test_state, call_ser_no, how_asset_found)
437{
438 // Copy the boilerplate text into local buffers:
439 prep_code.assign ("");
440 call_code.assign (test_state->bplate->bplate_string[remove_sst]);
441 check_code.assign (test_state->bplate->bplate_string[remove_sst_check]);
442 call_description = "SST-remove call";
443}
444sst_remove_call::~sst_remove_call (void)
445{
446 return; // just to have something to pin a breakpoint onto
447}
448
449bool sst_remove_call::copy_call_to_asset (void)
450{
451 vector<psa_asset*>::iterator found_asset;
452
453 found_asset = resolve_asset (dont_create_asset, psa_asset_usage::all);
454 if (asset_info.how_asset_found != asset_search::not_found) {
455 asset_info.the_asset = reinterpret_cast<sst_asset*>(*found_asset);
456 // Note: Vector is of base-class type, but the assets *are* sst_asset.
457 if (asset_info.how_asset_found == asset_search::found_active) {
458 // Delete asset; move it from active vector to deleted vector:
459 test_state->deleted_sst_asset.push_back (asset_info.the_asset);
460 test_state->active_sst_asset.erase (found_asset);
461 } /* if not active, we'll deem the call expected to fail. */
462 }
463 return true;
464}
465
466bool sst_remove_call::copy_asset_to_call (void)
467{
468 if (asset_info.the_asset != nullptr) {
469 set_data.string_specified = asset_info.the_asset->set_data.string_specified;
470 set_data.file_specified = asset_info.the_asset->set_data.file_specified;
471 set_data.flags_string = asset_info.the_asset->set_data.flags_string;
472 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
473 asset_info.name_specified = asset_info.the_asset->asset_info.name_specified;
474 }
475 return true;
476}
477
478void sst_remove_call::fill_in_prep_code (void)
479{
480 // No prep-code.
481 return; // just to have something to pin a breakpoint onto
482}
483
484void sst_remove_call::fill_in_command (void)
485{
486 // Fill in the call:
487 string id_string = to_string((long) asset_info.id_n);
488 find_replace_1st ("$uid", id_string, call_code);
489 // Fill in expected results:
490 calc_result_code(); // this only fills $expect check_code
491}
492
493/**********************************************************************************
494 End of methods of class sst_remove_call.
495**********************************************************************************/