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