blob: c9763aa927fd50d28524b2ce9114ada3e34cd9f4 [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
Nik Dewallyabac0e52024-08-02 13:42:27 +01008#include <stdexcept>
Nik Dewallybacae6c2024-07-30 16:58:14 +01009#include <stdlib.h>
10#include <iostream>
Karl Zhang3de5ab12021-05-31 11:45:48 +080011
12#include "boilerplate.hpp"
Nik Dewallyabac0e52024-08-02 13:42:27 +010013#include "crypto_asset.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080014#include "string_ops.hpp"
15#include "data_blocks.hpp"
16#include "psa_asset.hpp"
17#include "find_or_create_asset.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080018#include "tf_fuzz.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080019#include "psa_call.hpp"
20
21
22
23/**********************************************************************************
24 Methods of class psa_call follow:
25**********************************************************************************/
26
27//**************** psa_call methods ****************
28
29psa_call::psa_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
30 asset_search how_asset_found)
31{
32 this->test_state = test_state;
33 this->asset_info.how_asset_found = how_asset_found;
34 set_data.string_specified = false;
35 set_data.set (""); // actual data
36 assign_data_var.assign (""); // name of variable assigned (dumped) to
37 assign_data_var_specified = false;
38 set_data.file_specified = false;
39 set_data.file_path.assign ("");
40 this->call_ser_no = call_ser_no = unique_id_counter++;
41 // These will be set in the lower-level constructors, but...
42 prep_code = call_code = check_code = "";
43 print_data = hash_data = false;
44 barrier = target_barrier = ""; // not (yet) any barrier for re-ordering calls
45 call_description = "";
46}
47
48psa_call::~psa_call (void)
49{
50 return; // just to have something to pin a breakpoint onto
51}
52
53void psa_call::write_out_prep_code (ofstream &test_file)
54{
55 test_file << prep_code;
56}
57
58void psa_call::write_out_command (ofstream &test_file)
59{
60 test_file << call_code;
61}
62
63void psa_call::write_out_check_code (ofstream &test_file)
64{
Nik Dewally6663dde2024-08-09 16:12:27 +010065 if (exp_data.result_code_checking_enabled()) {
Karl Zhang3de5ab12021-05-31 11:45:48 +080066 test_file << check_code;
67 } else {
68 test_file << " /* (No checks for this PSA call.) */" << endl;
69 }
70}
71
Nik Dewally6663dde2024-08-09 16:12:27 +010072bool psa_call::simulate(void) {
73 return false;
74}
75
Nik Dewallyabac0e52024-08-02 13:42:27 +010076void psa_call::copy_policy_to_call(void) {
77
78 string name = policy.get_policy_from_policy;
79
80 // name represents the policy asset we want to use for this call.
81
82 // We don't want to use a policy asset, so we have nothing to do here.
83 if (name == ""){
84 return;
85 }
86
87 vector<psa_asset*>::iterator found_asset;
88 long x; // doesnt matter
89 asset_search status = test_state->find_or_create_policy_asset(psa_asset_search::name,psa_asset_usage::all,name,0,x,dont_create_asset,found_asset);
90
91 switch (status) {
92
93 case asset_search::found_active:
94 case asset_search::found_deleted:
95 case asset_search::found_invalid:
96 break;
97
98 default:
99 cerr << "Fatal: could not find policy asset " << name << endl;
100 exit(1);
101 }
102
103 string handle = policy.handle_str;
104 string asset_2_name = policy.asset_2_name;
105 string asset_3_name = policy.asset_3_name;
106
107 policy = found_asset[0]->policy;
108 policy.handle_str = handle;
109 policy.asset_2_name = asset_2_name;
110 policy.asset_3_name = asset_3_name;
111}
112
Karl Zhang3de5ab12021-05-31 11:45:48 +0800113/**********************************************************************************
114 End of methods of class psa_call.
115**********************************************************************************/
116
117
118/**********************************************************************************
119 Methods of class sst_call follow:
120**********************************************************************************/
121
122/* calc_result_code() fills in the check_code string member with the correct
123 result code (e.g., "PSA_SUCCESS" or whatever).
124
125 This is a big part of where the target modeling -- error modeling -- occurs,
126 so lots of room for further refinement here. */
Nik Dewally6663dde2024-08-09 16:12:27 +0100127void sst_call::fill_in_result_code (void)
Karl Zhang3de5ab12021-05-31 11:45:48 +0800128{
Karl Zhang3de5ab12021-05-31 11:45:48 +0800129
Nik Dewally6663dde2024-08-09 16:12:27 +0100130 string formalized; // "proper" result string
131 switch (exp_data.get_expected_return_code()) {
132 case expected_return_code_t::DontCare: // Do not generate checks
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100133 return;
134
Nik Dewally6663dde2024-08-09 16:12:27 +0100135 case expected_return_code_t::Pass:
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100136 find_replace_all ("$expect",
137 test_state->bplate->bplate_string[sst_pass_string],
138 check_code);
139
140 // `check "foo"`
141 find_replace_all ("$check_expect",
142 "0",
143 check_code);
144
Nik Dewally6663dde2024-08-09 16:12:27 +0100145 break;
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100146
Nik Dewally6663dde2024-08-09 16:12:27 +0100147 case expected_return_code_t::Fail:
148 // If the command is `... check "foo" expect fail;`, the fail
149 // binds to the check, not the command itself.
150 if (exp_data.data_specified) {
151 // expect a pass for the sst call itself.
152 find_replace_all ("$expect",
153 test_state->bplate->bplate_string[sst_pass_string],
154 check_code);
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100155
Nik Dewally6663dde2024-08-09 16:12:27 +0100156 // expect a failure for the check.
157 find_replace_all ("!= $check_expect",
158 "== 0",
159 check_code);
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100160
Nik Dewally6663dde2024-08-09 16:12:27 +0100161 find_replace_1st ("should be equal", "should not be equal",
162 check_code);
163 } else {
164 // Check for not-success:
165 find_replace_1st ("!=", "==",
166 check_code);
167 find_replace_all ("$expect",
168 test_state->bplate->bplate_string[sst_pass_string],
169 check_code);
170 find_replace_1st ("expected ", "expected not ",
171 check_code);
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100172 }
Nik Dewally6663dde2024-08-09 16:12:27 +0100173 break;
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100174
Nik Dewally6663dde2024-08-09 16:12:27 +0100175 case expected_return_code_t::SpecificFail:
176 formalized = formalize (exp_data.get_expected_return_code_string(), "PSA_ERROR_");
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100177 find_replace_all ("$expect", formalized, check_code);
178
179 // NOTE: Assumes that the variable used to store the actual
180 // value initialised to a different value than the expected
181 // value.
182 find_replace_all ("!= $check_expect","== 0",check_code);
183 find_replace_1st ("should be equal", "should not be equal",
184 check_code);
Nik Dewally6663dde2024-08-09 16:12:27 +0100185 break;
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100186
Nik Dewally6663dde2024-08-09 16:12:27 +0100187 // TODO: move error code simulation into simulate().
188 case expected_return_code_t::DontKnow: // Simulate
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100189 // Figure out what the message should read:
190 switch (asset_info.how_asset_found) {
191 case asset_search::found_active:
192 case asset_search::created_new:
193 find_replace_all ("$expect",
194 test_state->bplate->
195 bplate_string[sst_pass_string],
196 check_code);
197
198 find_replace_all ("$check_expect","0",check_code);
199 break;
200 case asset_search::found_deleted:
201 case asset_search::not_found:
202 find_replace_all ("$expect",
203 test_state->bplate->
204 bplate_string[sst_fail_removed],
205 check_code);
206
207 // NOTE: Assumes that the variable used to store the actual
208 // value initialised to a different value than the expected
209 // value.
210 find_replace_all ("!= $check_expect","== 0",check_code);
211 find_replace_1st ("should be equal", "should not be equal",
212 check_code);
213 break;
214 default:
215 find_replace_1st ("!=", "==",
216 check_code); // like "fail", just make sure...
217
218 find_replace_all ("$expect",
219 test_state->bplate->
220 bplate_string[sst_pass_string],
221 check_code); // ... it's *not* PSA_SUCCESS
222
223 // NOTE: Assumes that the variable used to store the actual
224 // value initialised to a different value than the expected
225 // value.
226 find_replace_all ("!= $check_expect","== 0",check_code);
227 find_replace_1st ("should be equal", "should not be equal",
228 check_code);
229 break;
Nik Dewally6663dde2024-08-09 16:12:27 +0100230 }
231 break;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800232 }
Karl Zhang3de5ab12021-05-31 11:45:48 +0800233}
234
235vector<psa_asset*>::iterator sst_call::resolve_asset (bool create_asset_bool,
236 psa_asset_usage where) {
237 vector<psa_asset*>::iterator found_asset;
238 vector<psa_asset*> *asset_vector;
239 int asset_pick;
240
241 if (random_asset != psa_asset_usage::all) {
242 // != psa_asset_usage::all means to choose some known asset at random:
243 if (random_asset == psa_asset_usage::active) {
244 asset_vector = &(test_state->active_sst_asset);
245 asset_info.how_asset_found = asset_search::found_active;
246 } else if (random_asset == psa_asset_usage::deleted) {
247 asset_vector = &(test_state->deleted_sst_asset);
248 asset_info.how_asset_found = asset_search::found_deleted;
249 } else {
250 // "invalid" assets are not currently used.
251 cerr << "\nError: Tool-internal: Please report error 1101 to " << endl
252 << "TF-Fuzz developers."
253 << endl;
254 exit(1101);
255 }
256 if (asset_vector->size() > 0) {
257 /* Pick an active or deleted asset at random: */
258 asset_pick = rand() % asset_vector->size();
259 found_asset = asset_vector->begin() + asset_pick;
260 /* Copy asset information into template tracker: */
261 asset_info.id_n = (*found_asset)->asset_info.id_n;
262 asset_info.asset_ser_no
263 = (*found_asset)->asset_info.asset_ser_no;
264 } else {
265 if (random_asset == psa_asset_usage::active) {
266 cerr << "\nError: An sst call asks for a "
267 << "randomly chosen active asset, when none " << endl
268 << "is currently defined." << endl;
269 exit(1008);
270 } else if (random_asset == psa_asset_usage::deleted) {
271 cerr << "\nError: An sst call asks for a "
272 << "randomly chosen deleted asset, when none " << endl
273 << "is currently defined." << endl;
274 exit(1009);
275 } // "invalid" assets are not currently used.
276 }
277 } else {
278 // Find the asset by name:
279 asset_info.how_asset_found = test_state->find_or_create_sst_asset (
280 psa_asset_search::name, where,
281 asset_info.get_name(), 0, asset_info.asset_ser_no,
282 create_asset_bool, found_asset );
283 if ( asset_info.how_asset_found == asset_search::unsuccessful
284 || asset_info.how_asset_found == asset_search::something_wrong ) {
285 cerr << "\nError: Tool-internal: Please report error 108 to " << endl
286 << "TF-Fuzz developers."
287 << endl;
288 exit(108);
289 }
290 }
291 return found_asset;
292}
293
294sst_call::sst_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
295 asset_search how_asset_found)
296 : psa_call(test_state, call_ser_no, how_asset_found)
297{
298 asset_info.the_asset = nullptr;
299 return; // just to have something to pin a breakpoint onto
300}
301sst_call::~sst_call (void)
302{
303 return; // just to have something to pin a breakpoint onto
304}
305
306/**********************************************************************************
307 End of methods of class sst_call.
308**********************************************************************************/
309
310
311/**********************************************************************************
312 Methods of class crypto_call follow:
313**********************************************************************************/
314
Nik Dewallyabac0e52024-08-02 13:42:27 +0100315bool crypto_call::simulate(void) {
316 bool has_changed = false;
317 has_changed |= simulate_ret_code();
318
319 return has_changed;
320}
321
322
323
324bool crypto_call::simulate_ret_code(void) {
325 if (!exp_data.simulation_needed()) {
326 return false;
327 }
328 switch (asset_info.how_asset_found) {
329 case asset_search::found_active:
330 case asset_search::created_new:
331 exp_data.expect_pass();
332 return true;
333 case asset_search::not_found:
334 case asset_search::found_deleted:
335 exp_data.expect_failure();
336 return true;
337 default:
338 exp_data.expect_failure();
339 return true;
340 }
341}
342
Karl Zhang3de5ab12021-05-31 11:45:48 +0800343/* calc_result_code() fills in the check_code string member with the correct
344 result code (e.g., "PSA_SUCCESS" or whatever). This "modeling" needs to be
345 improved and expanded upon *massively* more or less mirroring what is seen in
346 .../test/suites/crypto/crypto_tests_common.c in the psa_key_interface_test()
347 method, (starting around line 20ish). */
Nik Dewally6663dde2024-08-09 16:12:27 +0100348void crypto_call::fill_in_result_code (void)
Karl Zhang3de5ab12021-05-31 11:45:48 +0800349{
350 string formalized; // "proper" result string
351
Nik Dewally6663dde2024-08-09 16:12:27 +0100352 switch (exp_data.get_expected_return_code()) {
353
354 case expected_return_code_t::DontCare:
355 return;
356
357 case expected_return_code_t::Pass:
358 find_replace_all ("$expect",
359 test_state->bplate->bplate_string[sst_pass_string],
360 check_code);
361 break;
362
363 case expected_return_code_t::Fail:
364 // Check for not-success:
365 find_replace_1st ("!=", "==",
366 check_code);
367 find_replace_all ("$expect",
368 test_state->bplate->bplate_string[sst_pass_string],
369 check_code);
370 find_replace_1st ("expected ", "expected not ",
371 check_code);
372 break;
373
374 case expected_return_code_t::SpecificFail:
375 formalized = formalize (exp_data.get_expected_return_code_string(), "PSA_ERROR_");
376 find_replace_all ("$expect", formalized, check_code);
377 break;
378
Nik Dewallyabac0e52024-08-02 13:42:27 +0100379 case expected_return_code_t::DontKnow: // Simulate -- SHOULD NEVER HAPPEN
380 throw std::logic_error("Crypto call fill_in_result_code: return code is don't know");
Karl Zhang3de5ab12021-05-31 11:45:48 +0800381 }
382}
383
384
385bool crypto_call::copy_asset_to_call (void)
386{
387 if (asset_info.the_asset == nullptr) {
388 return false;
389 } else {
390 // Get updated asset info from the asset:
391 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
392 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
393 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
394 exp_data.data = asset_info.the_asset->exp_data.data;
395 return true;
396 }
397}
398
399
400crypto_call::crypto_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
401 asset_search how_asset_found)
402 : psa_call(test_state, call_ser_no, how_asset_found)
403{
Nik Dewallyabac0e52024-08-02 13:42:27 +0100404 policy = key_policy_info::create_random();
Karl Zhang3de5ab12021-05-31 11:45:48 +0800405 return; // just to have something to pin a breakpoint onto
406}
407crypto_call::~crypto_call (void)
408{
409 // Nothing further to delete.
410 return; // just to have something to pin a breakpoint onto
411}
412
413/**********************************************************************************
414 End of methods of class crypto_call.
415**********************************************************************************/
416
417
418/**********************************************************************************
419 Methods of class security_call follow:
420**********************************************************************************/
421
422security_call::security_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
423 asset_search how_asset_found)
424 : psa_call(test_state, call_ser_no, how_asset_found)
425{
426 // Nothing further to initialize.
427 return; // just to have something to pin a breakpoint onto
428}
429security_call::~security_call (void)
430{
431 // Nothing further to delete.
432 return; // just to have something to pin a breakpoint onto
433}
434
435// resolve_asset() doesn't do anything for security_calls, since there's no asset involved.
436vector<psa_asset*>::iterator security_call::resolve_asset (bool create_asset_bool,
437 psa_asset_usage where)
438{
439 return test_state->active_sst_asset.end(); // (anything)
440}
441
442/* calc_result_code() fills in the check_code string member with the correct result
443 code (e.g., "PSA_SUCCESS" or whatever).
444
445 Since there are no actual PSA calls associated with security calls (so far at least),
446 this should never be invoked. */
Nik Dewally6663dde2024-08-09 16:12:27 +0100447void security_call::fill_in_result_code (void)
Karl Zhang3de5ab12021-05-31 11:45:48 +0800448{
449 // Currently should not be invoked.
450 cerr << "\nError: Internal: Please report error #205 to TF-Fuzz developers." << endl;
451 exit (205);
452}
453
454/**********************************************************************************
455 End of methods of class security_call.
456**********************************************************************************/