blob: 1bb8c4624d417a2a77e75985c685300ea7a15340 [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{
63 if (!exp_data.pf_nothing) {
64 test_file << check_code;
65 } else {
66 test_file << " /* (No checks for this PSA call.) */" << endl;
67 }
68}
69
70/**********************************************************************************
71 End of methods of class psa_call.
72**********************************************************************************/
73
74
75/**********************************************************************************
76 Methods of class sst_call follow:
77**********************************************************************************/
78
79/* calc_result_code() fills in the check_code string member with the correct
80 result code (e.g., "PSA_SUCCESS" or whatever).
81
82 This is a big part of where the target modeling -- error modeling -- occurs,
83 so lots of room for further refinement here. */
84void sst_call::calc_result_code (void)
85{
86 string formalized; // "proper" result string
87
Nik Dewallyf0ff5e92024-07-16 10:01:32 +010088 if (exp_data.pf_nothing) { // do not generate result checks
89 return;
90
91 }
92 if (exp_data.pf_pass) { // expect pass
93 find_replace_all ("$expect",
94 test_state->bplate->bplate_string[sst_pass_string],
95 check_code);
96
97 // `check "foo"`
98 find_replace_all ("$check_expect",
99 "0",
100 check_code);
101
102 } else if (exp_data.pf_fail) { // expect fail
103
104 // If the command is `... check "foo" expect fail;`, the fail
105 // binds to the check, not the command itself.
106 if (exp_data.data_specified) {
107 // expect a pass for the sst call itself.
108 find_replace_all ("$expect",
109 test_state->bplate->bplate_string[sst_pass_string],
110 check_code);
111
112 // expect a failure for the check.
113 find_replace_all ("!= $check_expect",
114 "== 0",
115 check_code);
116
117 find_replace_1st ("should be equal", "should not be equal",
118 check_code);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800119 } else {
Nik Dewallyf0ff5e92024-07-16 10:01:32 +0100120 // Check for not-success:
121 find_replace_1st ("!=", "==",
122 check_code);
123 find_replace_all ("$expect",
124 test_state->bplate->bplate_string[sst_pass_string],
125 check_code);
126 find_replace_1st ("expected ", "expected not ",
127 check_code);
128 }
129 }
130
131 else if (exp_data.pf_specified) { // expect <PSA_ERROR_CODE>
132 formalized = formalize (exp_data.pf_result_string, "PSA_ERROR_");
133 find_replace_all ("$expect", formalized, check_code);
134
135 // NOTE: Assumes that the variable used to store the actual
136 // value initialised to a different value than the expected
137 // value.
138 find_replace_all ("!= $check_expect","== 0",check_code);
139 find_replace_1st ("should be equal", "should not be equal",
140 check_code);
141 }
142
143 else { // no explicit expect -- simulate
144
145 // Figure out what the message should read:
146 switch (asset_info.how_asset_found) {
147 case asset_search::found_active:
148 case asset_search::created_new:
149 find_replace_all ("$expect",
150 test_state->bplate->
151 bplate_string[sst_pass_string],
152 check_code);
153
154 find_replace_all ("$check_expect","0",check_code);
155 break;
156 case asset_search::found_deleted:
157 case asset_search::not_found:
158 find_replace_all ("$expect",
159 test_state->bplate->
160 bplate_string[sst_fail_removed],
161 check_code);
162
163 // NOTE: Assumes that the variable used to store the actual
164 // value initialised to a different value than the expected
165 // value.
166 find_replace_all ("!= $check_expect","== 0",check_code);
167 find_replace_1st ("should be equal", "should not be equal",
168 check_code);
169 break;
170 default:
171 find_replace_1st ("!=", "==",
172 check_code); // like "fail", just make sure...
173
174 find_replace_all ("$expect",
175 test_state->bplate->
176 bplate_string[sst_pass_string],
177 check_code); // ... it's *not* PSA_SUCCESS
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);
185 break;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800186 }
187 }
188}
189
190vector<psa_asset*>::iterator sst_call::resolve_asset (bool create_asset_bool,
191 psa_asset_usage where) {
192 vector<psa_asset*>::iterator found_asset;
193 vector<psa_asset*> *asset_vector;
194 int asset_pick;
195
196 if (random_asset != psa_asset_usage::all) {
197 // != psa_asset_usage::all means to choose some known asset at random:
198 if (random_asset == psa_asset_usage::active) {
199 asset_vector = &(test_state->active_sst_asset);
200 asset_info.how_asset_found = asset_search::found_active;
201 } else if (random_asset == psa_asset_usage::deleted) {
202 asset_vector = &(test_state->deleted_sst_asset);
203 asset_info.how_asset_found = asset_search::found_deleted;
204 } else {
205 // "invalid" assets are not currently used.
206 cerr << "\nError: Tool-internal: Please report error 1101 to " << endl
207 << "TF-Fuzz developers."
208 << endl;
209 exit(1101);
210 }
211 if (asset_vector->size() > 0) {
212 /* Pick an active or deleted asset at random: */
213 asset_pick = rand() % asset_vector->size();
214 found_asset = asset_vector->begin() + asset_pick;
215 /* Copy asset information into template tracker: */
216 asset_info.id_n = (*found_asset)->asset_info.id_n;
217 asset_info.asset_ser_no
218 = (*found_asset)->asset_info.asset_ser_no;
219 } else {
220 if (random_asset == psa_asset_usage::active) {
221 cerr << "\nError: An sst call asks for a "
222 << "randomly chosen active asset, when none " << endl
223 << "is currently defined." << endl;
224 exit(1008);
225 } else if (random_asset == psa_asset_usage::deleted) {
226 cerr << "\nError: An sst call asks for a "
227 << "randomly chosen deleted asset, when none " << endl
228 << "is currently defined." << endl;
229 exit(1009);
230 } // "invalid" assets are not currently used.
231 }
232 } else {
233 // Find the asset by name:
234 asset_info.how_asset_found = test_state->find_or_create_sst_asset (
235 psa_asset_search::name, where,
236 asset_info.get_name(), 0, asset_info.asset_ser_no,
237 create_asset_bool, found_asset );
238 if ( asset_info.how_asset_found == asset_search::unsuccessful
239 || asset_info.how_asset_found == asset_search::something_wrong ) {
240 cerr << "\nError: Tool-internal: Please report error 108 to " << endl
241 << "TF-Fuzz developers."
242 << endl;
243 exit(108);
244 }
245 }
246 return found_asset;
247}
248
249sst_call::sst_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
250 asset_search how_asset_found)
251 : psa_call(test_state, call_ser_no, how_asset_found)
252{
253 asset_info.the_asset = nullptr;
254 return; // just to have something to pin a breakpoint onto
255}
256sst_call::~sst_call (void)
257{
258 return; // just to have something to pin a breakpoint onto
259}
260
261/**********************************************************************************
262 End of methods of class sst_call.
263**********************************************************************************/
264
265
266/**********************************************************************************
267 Methods of class crypto_call follow:
268**********************************************************************************/
269
270/* calc_result_code() fills in the check_code string member with the correct
271 result code (e.g., "PSA_SUCCESS" or whatever). This "modeling" needs to be
272 improved and expanded upon *massively* more or less mirroring what is seen in
273 .../test/suites/crypto/crypto_tests_common.c in the psa_key_interface_test()
274 method, (starting around line 20ish). */
275void crypto_call::calc_result_code (void)
276{
277 string formalized; // "proper" result string
278
279 if (!exp_data.pf_nothing) {
280 if (exp_data.pf_pass) {
281 find_replace_all ("$expect",
282 test_state->bplate->bplate_string[sst_pass_string],
283 check_code);
284 } else if (exp_data.pf_fail) {
285 // Check for not-success:
286 find_replace_1st ("!=", "==",
287 check_code);
288 find_replace_all ("$expect",
289 test_state->bplate->bplate_string[sst_pass_string],
290 check_code);
291 find_replace_1st ("expected ", "expected not ",
292 check_code);
293 } else {
294 if (exp_data.pf_specified) {
295 formalized = formalize (exp_data.pf_result_string, "PSA_ERROR_");
296 find_replace_all ("$expect", formalized, check_code);
297 } else {
298 // Figure out what the message should read:
299 switch (asset_info.how_asset_found) {
300 case asset_search::found_active:
301 case asset_search::created_new:
302 find_replace_all ("$expect",
303 test_state->bplate->
304 bplate_string[sst_pass_string],
305 check_code);
306 break;
307 case asset_search::not_found:
308 case asset_search::found_deleted:
309 find_replace_all ("$expect", "PSA_ERROR_INVALID_HANDLE",
310 check_code); // TODO: take from boilerplate
311 break;
312 default:
313 find_replace_1st ("!=", "==",
314 check_code); // like "fail", just make sure...
315 find_replace_all ("$expect",
316 test_state->bplate->
317 bplate_string[sst_pass_string],
318 check_code); // ... it's *not* PSA_SUCCESS
319 break;
320 }
321 }
322 }
323 }
324}
325
326
327bool crypto_call::copy_asset_to_call (void)
328{
329 if (asset_info.the_asset == nullptr) {
330 return false;
331 } else {
332 // Get updated asset info from the asset:
333 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
334 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
335 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
336 exp_data.data = asset_info.the_asset->exp_data.data;
337 return true;
338 }
339}
340
341
342crypto_call::crypto_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
343 asset_search how_asset_found)
344 : psa_call(test_state, call_ser_no, how_asset_found)
345{
346 // Nothing further to initialize.
347 return; // just to have something to pin a breakpoint onto
348}
349crypto_call::~crypto_call (void)
350{
351 // Nothing further to delete.
352 return; // just to have something to pin a breakpoint onto
353}
354
355/**********************************************************************************
356 End of methods of class crypto_call.
357**********************************************************************************/
358
359
360/**********************************************************************************
361 Methods of class security_call follow:
362**********************************************************************************/
363
364security_call::security_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
365 asset_search how_asset_found)
366 : psa_call(test_state, call_ser_no, how_asset_found)
367{
368 // Nothing further to initialize.
369 return; // just to have something to pin a breakpoint onto
370}
371security_call::~security_call (void)
372{
373 // Nothing further to delete.
374 return; // just to have something to pin a breakpoint onto
375}
376
377// resolve_asset() doesn't do anything for security_calls, since there's no asset involved.
378vector<psa_asset*>::iterator security_call::resolve_asset (bool create_asset_bool,
379 psa_asset_usage where)
380{
381 return test_state->active_sst_asset.end(); // (anything)
382}
383
384/* calc_result_code() fills in the check_code string member with the correct result
385 code (e.g., "PSA_SUCCESS" or whatever).
386
387 Since there are no actual PSA calls associated with security calls (so far at least),
388 this should never be invoked. */
389void security_call::calc_result_code (void)
390{
391 // Currently should not be invoked.
392 cerr << "\nError: Internal: Please report error #205 to TF-Fuzz developers." << endl;
393 exit (205);
394}
395
396/**********************************************************************************
397 End of methods of class security_call.
398**********************************************************************************/