blob: 7ca407e5e7aba7163135358cb2cbf66a9f927353 [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 Dewallybacae6c2024-07-30 16:58:14 +01008#include <stdlib.h>
9#include <iostream>
Karl Zhang3de5ab12021-05-31 11:45:48 +080010
11#include "boilerplate.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080012#include "string_ops.hpp"
13#include "data_blocks.hpp"
14#include "psa_asset.hpp"
15#include "find_or_create_asset.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080016#include "tf_fuzz.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080017#include "psa_call.hpp"
18
19
20
21/**********************************************************************************
22 Methods of class psa_call follow:
23**********************************************************************************/
24
25//**************** psa_call methods ****************
26
27psa_call::psa_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
28 asset_search how_asset_found)
29{
30 this->test_state = test_state;
31 this->asset_info.how_asset_found = how_asset_found;
32 set_data.string_specified = false;
33 set_data.set (""); // actual data
34 assign_data_var.assign (""); // name of variable assigned (dumped) to
35 assign_data_var_specified = false;
36 set_data.file_specified = false;
37 set_data.file_path.assign ("");
38 this->call_ser_no = call_ser_no = unique_id_counter++;
39 // These will be set in the lower-level constructors, but...
40 prep_code = call_code = check_code = "";
41 print_data = hash_data = false;
42 barrier = target_barrier = ""; // not (yet) any barrier for re-ordering calls
43 call_description = "";
44}
45
46psa_call::~psa_call (void)
47{
48 return; // just to have something to pin a breakpoint onto
49}
50
51void psa_call::write_out_prep_code (ofstream &test_file)
52{
53 test_file << prep_code;
54}
55
56void psa_call::write_out_command (ofstream &test_file)
57{
58 test_file << call_code;
59}
60
61void psa_call::write_out_check_code (ofstream &test_file)
62{
Nik Dewally6663dde2024-08-09 16:12:27 +010063 if (exp_data.result_code_checking_enabled()) {
Karl Zhang3de5ab12021-05-31 11:45:48 +080064 test_file << check_code;
65 } else {
66 test_file << " /* (No checks for this PSA call.) */" << endl;
67 }
68}
69
Nik Dewally6663dde2024-08-09 16:12:27 +010070bool psa_call::simulate(void) {
71 return false;
72}
73
Karl Zhang3de5ab12021-05-31 11:45:48 +080074/**********************************************************************************
75 End of methods of class psa_call.
76**********************************************************************************/
77
78
79/**********************************************************************************
80 Methods of class sst_call follow:
81**********************************************************************************/
82
83/* calc_result_code() fills in the check_code string member with the correct
84 result code (e.g., "PSA_SUCCESS" or whatever).
85
86 This is a big part of where the target modeling -- error modeling -- occurs,
87 so lots of room for further refinement here. */
Nik Dewally6663dde2024-08-09 16:12:27 +010088void sst_call::fill_in_result_code (void)
Karl Zhang3de5ab12021-05-31 11:45:48 +080089{
Karl Zhang3de5ab12021-05-31 11:45:48 +080090
Nik Dewally6663dde2024-08-09 16:12:27 +010091 string formalized; // "proper" result string
92 switch (exp_data.get_expected_return_code()) {
93 case expected_return_code_t::DontCare: // Do not generate checks
Nik Dewallyf0ff5e92024-07-16 10:01:32 +010094 return;
95
Nik Dewally6663dde2024-08-09 16:12:27 +010096 case expected_return_code_t::Pass:
Nik Dewallyf0ff5e92024-07-16 10:01:32 +010097 find_replace_all ("$expect",
98 test_state->bplate->bplate_string[sst_pass_string],
99 check_code);
100
101 // `check "foo"`
102 find_replace_all ("$check_expect",
103 "0",
104 check_code);
105
Nik Dewally6663dde2024-08-09 16:12:27 +0100106 break;
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100107
Nik Dewally6663dde2024-08-09 16:12:27 +0100108 case expected_return_code_t::Fail:
109 // If the command is `... check "foo" expect fail;`, the fail
110 // binds to the check, not the command itself.
111 if (exp_data.data_specified) {
112 // expect a pass for the sst call itself.
113 find_replace_all ("$expect",
114 test_state->bplate->bplate_string[sst_pass_string],
115 check_code);
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100116
Nik Dewally6663dde2024-08-09 16:12:27 +0100117 // expect a failure for the check.
118 find_replace_all ("!= $check_expect",
119 "== 0",
120 check_code);
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100121
Nik Dewally6663dde2024-08-09 16:12:27 +0100122 find_replace_1st ("should be equal", "should not be equal",
123 check_code);
124 } else {
125 // Check for not-success:
126 find_replace_1st ("!=", "==",
127 check_code);
128 find_replace_all ("$expect",
129 test_state->bplate->bplate_string[sst_pass_string],
130 check_code);
131 find_replace_1st ("expected ", "expected not ",
132 check_code);
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100133 }
Nik Dewally6663dde2024-08-09 16:12:27 +0100134 break;
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100135
Nik Dewally6663dde2024-08-09 16:12:27 +0100136 case expected_return_code_t::SpecificFail:
137 formalized = formalize (exp_data.get_expected_return_code_string(), "PSA_ERROR_");
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100138 find_replace_all ("$expect", formalized, check_code);
139
140 // NOTE: Assumes that the variable used to store the actual
141 // value initialised to a different value than the expected
142 // value.
143 find_replace_all ("!= $check_expect","== 0",check_code);
144 find_replace_1st ("should be equal", "should not be equal",
145 check_code);
Nik Dewally6663dde2024-08-09 16:12:27 +0100146 break;
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100147
Nik Dewally6663dde2024-08-09 16:12:27 +0100148 // TODO: move error code simulation into simulate().
149 case expected_return_code_t::DontKnow: // Simulate
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100150 // Figure out what the message should read:
151 switch (asset_info.how_asset_found) {
152 case asset_search::found_active:
153 case asset_search::created_new:
154 find_replace_all ("$expect",
155 test_state->bplate->
156 bplate_string[sst_pass_string],
157 check_code);
158
159 find_replace_all ("$check_expect","0",check_code);
160 break;
161 case asset_search::found_deleted:
162 case asset_search::not_found:
163 find_replace_all ("$expect",
164 test_state->bplate->
165 bplate_string[sst_fail_removed],
166 check_code);
167
168 // NOTE: Assumes that the variable used to store the actual
169 // value initialised to a different value than the expected
170 // value.
171 find_replace_all ("!= $check_expect","== 0",check_code);
172 find_replace_1st ("should be equal", "should not be equal",
173 check_code);
174 break;
175 default:
176 find_replace_1st ("!=", "==",
177 check_code); // like "fail", just make sure...
178
179 find_replace_all ("$expect",
180 test_state->bplate->
181 bplate_string[sst_pass_string],
182 check_code); // ... it's *not* PSA_SUCCESS
183
184 // NOTE: Assumes that the variable used to store the actual
185 // value initialised to a different value than the expected
186 // value.
187 find_replace_all ("!= $check_expect","== 0",check_code);
188 find_replace_1st ("should be equal", "should not be equal",
189 check_code);
190 break;
Nik Dewally6663dde2024-08-09 16:12:27 +0100191 }
192 break;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800193 }
Karl Zhang3de5ab12021-05-31 11:45:48 +0800194}
195
196vector<psa_asset*>::iterator sst_call::resolve_asset (bool create_asset_bool,
197 psa_asset_usage where) {
198 vector<psa_asset*>::iterator found_asset;
199 vector<psa_asset*> *asset_vector;
200 int asset_pick;
201
202 if (random_asset != psa_asset_usage::all) {
203 // != psa_asset_usage::all means to choose some known asset at random:
204 if (random_asset == psa_asset_usage::active) {
205 asset_vector = &(test_state->active_sst_asset);
206 asset_info.how_asset_found = asset_search::found_active;
207 } else if (random_asset == psa_asset_usage::deleted) {
208 asset_vector = &(test_state->deleted_sst_asset);
209 asset_info.how_asset_found = asset_search::found_deleted;
210 } else {
211 // "invalid" assets are not currently used.
212 cerr << "\nError: Tool-internal: Please report error 1101 to " << endl
213 << "TF-Fuzz developers."
214 << endl;
215 exit(1101);
216 }
217 if (asset_vector->size() > 0) {
218 /* Pick an active or deleted asset at random: */
219 asset_pick = rand() % asset_vector->size();
220 found_asset = asset_vector->begin() + asset_pick;
221 /* Copy asset information into template tracker: */
222 asset_info.id_n = (*found_asset)->asset_info.id_n;
223 asset_info.asset_ser_no
224 = (*found_asset)->asset_info.asset_ser_no;
225 } else {
226 if (random_asset == psa_asset_usage::active) {
227 cerr << "\nError: An sst call asks for a "
228 << "randomly chosen active asset, when none " << endl
229 << "is currently defined." << endl;
230 exit(1008);
231 } else if (random_asset == psa_asset_usage::deleted) {
232 cerr << "\nError: An sst call asks for a "
233 << "randomly chosen deleted asset, when none " << endl
234 << "is currently defined." << endl;
235 exit(1009);
236 } // "invalid" assets are not currently used.
237 }
238 } else {
239 // Find the asset by name:
240 asset_info.how_asset_found = test_state->find_or_create_sst_asset (
241 psa_asset_search::name, where,
242 asset_info.get_name(), 0, asset_info.asset_ser_no,
243 create_asset_bool, found_asset );
244 if ( asset_info.how_asset_found == asset_search::unsuccessful
245 || asset_info.how_asset_found == asset_search::something_wrong ) {
246 cerr << "\nError: Tool-internal: Please report error 108 to " << endl
247 << "TF-Fuzz developers."
248 << endl;
249 exit(108);
250 }
251 }
252 return found_asset;
253}
254
255sst_call::sst_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
256 asset_search how_asset_found)
257 : psa_call(test_state, call_ser_no, how_asset_found)
258{
259 asset_info.the_asset = nullptr;
260 return; // just to have something to pin a breakpoint onto
261}
262sst_call::~sst_call (void)
263{
264 return; // just to have something to pin a breakpoint onto
265}
266
267/**********************************************************************************
268 End of methods of class sst_call.
269**********************************************************************************/
270
271
272/**********************************************************************************
273 Methods of class crypto_call follow:
274**********************************************************************************/
275
276/* calc_result_code() fills in the check_code string member with the correct
277 result code (e.g., "PSA_SUCCESS" or whatever). This "modeling" needs to be
278 improved and expanded upon *massively* more or less mirroring what is seen in
279 .../test/suites/crypto/crypto_tests_common.c in the psa_key_interface_test()
280 method, (starting around line 20ish). */
Nik Dewally6663dde2024-08-09 16:12:27 +0100281void crypto_call::fill_in_result_code (void)
Karl Zhang3de5ab12021-05-31 11:45:48 +0800282{
283 string formalized; // "proper" result string
284
Nik Dewally6663dde2024-08-09 16:12:27 +0100285 switch (exp_data.get_expected_return_code()) {
286
287 case expected_return_code_t::DontCare:
288 return;
289
290 case expected_return_code_t::Pass:
291 find_replace_all ("$expect",
292 test_state->bplate->bplate_string[sst_pass_string],
293 check_code);
294 break;
295
296 case expected_return_code_t::Fail:
297 // Check for not-success:
298 find_replace_1st ("!=", "==",
299 check_code);
300 find_replace_all ("$expect",
301 test_state->bplate->bplate_string[sst_pass_string],
302 check_code);
303 find_replace_1st ("expected ", "expected not ",
304 check_code);
305 break;
306
307 case expected_return_code_t::SpecificFail:
308 formalized = formalize (exp_data.get_expected_return_code_string(), "PSA_ERROR_");
309 find_replace_all ("$expect", formalized, check_code);
310 break;
311
312 // TODO: move error code simulation to simulate()
313 case expected_return_code_t::DontKnow: // Simulate
314 // Figure out what the message should read:
315 switch (asset_info.how_asset_found) {
316 case asset_search::found_active:
317 case asset_search::created_new:
318 find_replace_all ("$expect",
319 test_state->bplate->
320 bplate_string[sst_pass_string],
321 check_code);
322 break;
323 case asset_search::not_found:
324 case asset_search::found_deleted:
325 find_replace_all ("$expect", "PSA_ERROR_INVALID_HANDLE",
326 check_code); // TODO: take from boilerplate
327 break;
328 default:
329 find_replace_1st ("!=", "==",
330 check_code); // like "fail", just make sure...
331 find_replace_all ("$expect",
332 test_state->bplate->
333 bplate_string[sst_pass_string],
334 check_code); // ... it's *not* PSA_SUCCESS
335 break;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800336 }
Nik Dewally6663dde2024-08-09 16:12:27 +0100337 break;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800338 }
339}
340
341
342bool crypto_call::copy_asset_to_call (void)
343{
344 if (asset_info.the_asset == nullptr) {
345 return false;
346 } else {
347 // Get updated asset info from the asset:
348 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
349 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
350 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
351 exp_data.data = asset_info.the_asset->exp_data.data;
352 return true;
353 }
354}
355
356
357crypto_call::crypto_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
358 asset_search how_asset_found)
359 : psa_call(test_state, call_ser_no, how_asset_found)
360{
361 // Nothing further to initialize.
362 return; // just to have something to pin a breakpoint onto
363}
364crypto_call::~crypto_call (void)
365{
366 // Nothing further to delete.
367 return; // just to have something to pin a breakpoint onto
368}
369
370/**********************************************************************************
371 End of methods of class crypto_call.
372**********************************************************************************/
373
374
375/**********************************************************************************
376 Methods of class security_call follow:
377**********************************************************************************/
378
379security_call::security_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
380 asset_search how_asset_found)
381 : psa_call(test_state, call_ser_no, how_asset_found)
382{
383 // Nothing further to initialize.
384 return; // just to have something to pin a breakpoint onto
385}
386security_call::~security_call (void)
387{
388 // Nothing further to delete.
389 return; // just to have something to pin a breakpoint onto
390}
391
392// resolve_asset() doesn't do anything for security_calls, since there's no asset involved.
393vector<psa_asset*>::iterator security_call::resolve_asset (bool create_asset_bool,
394 psa_asset_usage where)
395{
396 return test_state->active_sst_asset.end(); // (anything)
397}
398
399/* calc_result_code() fills in the check_code string member with the correct result
400 code (e.g., "PSA_SUCCESS" or whatever).
401
402 Since there are no actual PSA calls associated with security calls (so far at least),
403 this should never be invoked. */
Nik Dewally6663dde2024-08-09 16:12:27 +0100404void security_call::fill_in_result_code (void)
Karl Zhang3de5ab12021-05-31 11:45:48 +0800405{
406 // Currently should not be invoked.
407 cerr << "\nError: Internal: Please report error #205 to TF-Fuzz developers." << endl;
408 exit (205);
409}
410
411/**********************************************************************************
412 End of methods of class security_call.
413**********************************************************************************/