blob: 46af409719f4cb77df674150684f7e02384b986f [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
91 if (!exp_data.pf_nothing) {
92 if (exp_data.pf_pass) {
93 find_replace_all ("$expect",
94 test_state->bplate->bplate_string[sst_pass_string],
95 check_code);
96 } else if (exp_data.pf_fail) {
97 // Check for not-success:
98 find_replace_1st ("!=", "==",
99 check_code);
100 find_replace_all ("$expect",
101 test_state->bplate->bplate_string[sst_pass_string],
102 check_code);
103 find_replace_1st ("expected ", "expected not ",
104 check_code);
105 } else {
106 if (exp_data.pf_specified) {
107 formalized = formalize (exp_data.pf_result_string, "PSA_ERROR_");
108 find_replace_all ("$expect", formalized, check_code);
109 } else {
110 // Figure out what the message should read:
111 switch (asset_info.how_asset_found) {
112 case asset_search::found_active:
113 case asset_search::created_new:
114 find_replace_all ("$expect",
115 test_state->bplate->
116 bplate_string[sst_pass_string],
117 check_code);
118 break;
119 case asset_search::found_deleted:
120 case asset_search::not_found:
121 find_replace_all ("$expect",
122 test_state->bplate->
123 bplate_string[sst_fail_removed],
124 check_code);
125 break;
126 default:
127 find_replace_1st ("!=", "==",
128 check_code); // like "fail", just make sure...
129 find_replace_all ("$expect",
130 test_state->bplate->
131 bplate_string[sst_pass_string],
132 check_code); // ... it's *not* PSA_SUCCESS
133 break;
134 }
135 }
136 }
137 }
138}
139
140vector<psa_asset*>::iterator sst_call::resolve_asset (bool create_asset_bool,
141 psa_asset_usage where) {
142 vector<psa_asset*>::iterator found_asset;
143 vector<psa_asset*> *asset_vector;
144 int asset_pick;
145
146 if (random_asset != psa_asset_usage::all) {
147 // != psa_asset_usage::all means to choose some known asset at random:
148 if (random_asset == psa_asset_usage::active) {
149 asset_vector = &(test_state->active_sst_asset);
150 asset_info.how_asset_found = asset_search::found_active;
151 } else if (random_asset == psa_asset_usage::deleted) {
152 asset_vector = &(test_state->deleted_sst_asset);
153 asset_info.how_asset_found = asset_search::found_deleted;
154 } else {
155 // "invalid" assets are not currently used.
156 cerr << "\nError: Tool-internal: Please report error 1101 to " << endl
157 << "TF-Fuzz developers."
158 << endl;
159 exit(1101);
160 }
161 if (asset_vector->size() > 0) {
162 /* Pick an active or deleted asset at random: */
163 asset_pick = rand() % asset_vector->size();
164 found_asset = asset_vector->begin() + asset_pick;
165 /* Copy asset information into template tracker: */
166 asset_info.id_n = (*found_asset)->asset_info.id_n;
167 asset_info.asset_ser_no
168 = (*found_asset)->asset_info.asset_ser_no;
169 } else {
170 if (random_asset == psa_asset_usage::active) {
171 cerr << "\nError: An sst call asks for a "
172 << "randomly chosen active asset, when none " << endl
173 << "is currently defined." << endl;
174 exit(1008);
175 } else if (random_asset == psa_asset_usage::deleted) {
176 cerr << "\nError: An sst call asks for a "
177 << "randomly chosen deleted asset, when none " << endl
178 << "is currently defined." << endl;
179 exit(1009);
180 } // "invalid" assets are not currently used.
181 }
182 } else {
183 // Find the asset by name:
184 asset_info.how_asset_found = test_state->find_or_create_sst_asset (
185 psa_asset_search::name, where,
186 asset_info.get_name(), 0, asset_info.asset_ser_no,
187 create_asset_bool, found_asset );
188 if ( asset_info.how_asset_found == asset_search::unsuccessful
189 || asset_info.how_asset_found == asset_search::something_wrong ) {
190 cerr << "\nError: Tool-internal: Please report error 108 to " << endl
191 << "TF-Fuzz developers."
192 << endl;
193 exit(108);
194 }
195 }
196 return found_asset;
197}
198
199sst_call::sst_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
200 asset_search how_asset_found)
201 : psa_call(test_state, call_ser_no, how_asset_found)
202{
203 asset_info.the_asset = nullptr;
204 return; // just to have something to pin a breakpoint onto
205}
206sst_call::~sst_call (void)
207{
208 return; // just to have something to pin a breakpoint onto
209}
210
211/**********************************************************************************
212 End of methods of class sst_call.
213**********************************************************************************/
214
215
216/**********************************************************************************
217 Methods of class crypto_call follow:
218**********************************************************************************/
219
220/* calc_result_code() fills in the check_code string member with the correct
221 result code (e.g., "PSA_SUCCESS" or whatever). This "modeling" needs to be
222 improved and expanded upon *massively* more or less mirroring what is seen in
223 .../test/suites/crypto/crypto_tests_common.c in the psa_key_interface_test()
224 method, (starting around line 20ish). */
225void crypto_call::calc_result_code (void)
226{
227 string formalized; // "proper" result string
228
229 if (!exp_data.pf_nothing) {
230 if (exp_data.pf_pass) {
231 find_replace_all ("$expect",
232 test_state->bplate->bplate_string[sst_pass_string],
233 check_code);
234 } else if (exp_data.pf_fail) {
235 // Check for not-success:
236 find_replace_1st ("!=", "==",
237 check_code);
238 find_replace_all ("$expect",
239 test_state->bplate->bplate_string[sst_pass_string],
240 check_code);
241 find_replace_1st ("expected ", "expected not ",
242 check_code);
243 } else {
244 if (exp_data.pf_specified) {
245 formalized = formalize (exp_data.pf_result_string, "PSA_ERROR_");
246 find_replace_all ("$expect", formalized, check_code);
247 } else {
248 // Figure out what the message should read:
249 switch (asset_info.how_asset_found) {
250 case asset_search::found_active:
251 case asset_search::created_new:
252 find_replace_all ("$expect",
253 test_state->bplate->
254 bplate_string[sst_pass_string],
255 check_code);
256 break;
257 case asset_search::not_found:
258 case asset_search::found_deleted:
259 find_replace_all ("$expect", "PSA_ERROR_INVALID_HANDLE",
260 check_code); // TODO: take from boilerplate
261 break;
262 default:
263 find_replace_1st ("!=", "==",
264 check_code); // like "fail", just make sure...
265 find_replace_all ("$expect",
266 test_state->bplate->
267 bplate_string[sst_pass_string],
268 check_code); // ... it's *not* PSA_SUCCESS
269 break;
270 }
271 }
272 }
273 }
274}
275
276
277bool crypto_call::copy_asset_to_call (void)
278{
279 if (asset_info.the_asset == nullptr) {
280 return false;
281 } else {
282 // Get updated asset info from the asset:
283 asset_info.asset_ser_no = asset_info.the_asset->asset_info.asset_ser_no;
284 asset_info.id_n = asset_info.the_asset->asset_info.id_n;
285 exp_data.n_exp_vars = asset_info.the_asset->exp_data.n_exp_vars;
286 exp_data.data = asset_info.the_asset->exp_data.data;
287 return true;
288 }
289}
290
291
292crypto_call::crypto_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
293 asset_search how_asset_found)
294 : psa_call(test_state, call_ser_no, how_asset_found)
295{
296 // Nothing further to initialize.
297 return; // just to have something to pin a breakpoint onto
298}
299crypto_call::~crypto_call (void)
300{
301 // Nothing further to delete.
302 return; // just to have something to pin a breakpoint onto
303}
304
305/**********************************************************************************
306 End of methods of class crypto_call.
307**********************************************************************************/
308
309
310/**********************************************************************************
311 Methods of class security_call follow:
312**********************************************************************************/
313
314security_call::security_call (tf_fuzz_info *test_state, long &call_ser_no, // (constructor)
315 asset_search how_asset_found)
316 : psa_call(test_state, call_ser_no, how_asset_found)
317{
318 // Nothing further to initialize.
319 return; // just to have something to pin a breakpoint onto
320}
321security_call::~security_call (void)
322{
323 // Nothing further to delete.
324 return; // just to have something to pin a breakpoint onto
325}
326
327// resolve_asset() doesn't do anything for security_calls, since there's no asset involved.
328vector<psa_asset*>::iterator security_call::resolve_asset (bool create_asset_bool,
329 psa_asset_usage where)
330{
331 return test_state->active_sst_asset.end(); // (anything)
332}
333
334/* calc_result_code() fills in the check_code string member with the correct result
335 code (e.g., "PSA_SUCCESS" or whatever).
336
337 Since there are no actual PSA calls associated with security calls (so far at least),
338 this should never be invoked. */
339void security_call::calc_result_code (void)
340{
341 // Currently should not be invoked.
342 cerr << "\nError: Internal: Please report error #205 to TF-Fuzz developers." << endl;
343 exit (205);
344}
345
346/**********************************************************************************
347 End of methods of class security_call.
348**********************************************************************************/
349
350