Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 1 | /* |
Nik Dewally | 841612a | 2024-07-22 15:27:43 +0100 | [diff] [blame] | 2 | * Copyright (c) 2019-2024, Arm Limited. All rights reserved. |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | * |
| 6 | */ |
| 7 | |
| 8 | /* These classes "cut down the clutter" by grouping together related data and |
| 9 | associated methods (most importantly their constructors) used in template_ |
| 10 | line, psa_call, psa_asset (etc.). */ |
| 11 | |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 12 | #include <stdexcept> |
Nik Dewally | bacae6c | 2024-07-30 16:58:14 +0100 | [diff] [blame] | 13 | #include <stdlib.h> |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 14 | #include <string> |
| 15 | #include <vector> |
Nik Dewally | bacae6c | 2024-07-30 16:58:14 +0100 | [diff] [blame] | 16 | #include <iostream> |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 17 | |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 18 | #include "randomization.hpp" |
| 19 | #include "gibberish.hpp" |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 20 | #include "data_blocks.hpp" |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 21 | #include "find_or_create_asset.hpp" |
| 22 | #include "psa_call.hpp" |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 23 | |
| 24 | |
| 25 | |
| 26 | /********************************************************************************** |
| 27 | Methods of class expect_info follow: |
| 28 | **********************************************************************************/ |
| 29 | |
| 30 | expect_info::expect_info (void) // (default constructor) |
| 31 | { |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 32 | result_code_checking_enabled_f = true; |
| 33 | return_code_result_string.assign (""); |
| 34 | |
| 35 | expected_return_code = expected_return_code_t::DontKnow; |
| 36 | |
| 37 | data.assign (""); |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 38 | data_var.assign (""); // name of expected-data variable |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 39 | |
| 40 | data_var_specified = false; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 41 | data_specified = false; |
| 42 | data_matches_asset = false; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 43 | n_exp_vars = -1; // so the first reference is 0 (no suffix), then _1, _2, ... |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 44 | } |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 45 | |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 46 | expect_info::~expect_info (void) // (destructor) |
| 47 | {} |
| 48 | |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 49 | bool expect_info::simulation_needed(void) { |
| 50 | if (result_code_checking_enabled_f && |
| 51 | expected_return_code == expected_return_code_t::DontKnow) { |
| 52 | return true; |
| 53 | } |
| 54 | |
| 55 | return false; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 56 | } |
| 57 | |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 58 | void expect_info::expect_pass (void) |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 59 | { |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 60 | expected_return_code = expected_return_code_t::Pass; |
| 61 | return_code_result_string = ""; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 62 | } |
| 63 | |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 64 | void expect_info::expect_failure(void) |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 65 | { |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 66 | expected_return_code = expected_return_code_t::Fail; |
| 67 | return_code_result_string = ""; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 68 | } |
| 69 | |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 70 | void expect_info::expect_error_code (string error) |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 71 | { |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 72 | expected_return_code = expected_return_code_t::SpecificFail; |
| 73 | return_code_result_string = error; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 74 | } |
| 75 | |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 76 | |
| 77 | void expect_info::clear_expected_code (void) |
| 78 | { |
| 79 | expected_return_code = expected_return_code_t::DontKnow; |
| 80 | } |
| 81 | |
| 82 | expected_return_code_t expect_info::get_expected_return_code(void) { |
| 83 | |
| 84 | // NOTE: we do not store DontCare in expected_return_code, as this would erase |
| 85 | // the value stored prior to checks being disabled. This way, when |
| 86 | // enable_result_code_checking is called, it can use the value given by the |
| 87 | // user previously. |
| 88 | // .. |
| 89 | // Despite this, having DontCare as a value is still useful: it allows user |
| 90 | // code that uses expected return codes to just be a switch statement. |
| 91 | |
| 92 | if (result_code_checking_enabled_f) { |
| 93 | return expected_return_code; |
| 94 | } |
| 95 | |
| 96 | return expected_return_code_t::DontCare; |
| 97 | } |
| 98 | |
| 99 | string expect_info::get_expected_return_code_string(void) { |
| 100 | if (result_code_checking_enabled_f && expected_return_code == expected_return_code_t::SpecificFail) { |
| 101 | return return_code_result_string; |
| 102 | } |
| 103 | throw std::logic_error("get_expected_return_code_string called when return code is not SpecificFail"); |
| 104 | } |
| 105 | |
| 106 | void expect_info::disable_result_code_checking (void) |
| 107 | { |
| 108 | result_code_checking_enabled_f = false; |
| 109 | } |
| 110 | |
| 111 | void expect_info::enable_result_code_checking (void) |
| 112 | { |
| 113 | result_code_checking_enabled_f = true; |
| 114 | } |
| 115 | |
| 116 | bool expect_info::result_code_checking_enabled (void) { |
| 117 | return result_code_checking_enabled_f; |
| 118 | } |
| 119 | |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 120 | void expect_info::copy_expect_to_call (psa_call *the_call) |
| 121 | { |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 122 | the_call->exp_data = *this; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | /********************************************************************************** |
| 126 | End of methods of class expect_info. |
| 127 | **********************************************************************************/ |
| 128 | |
| 129 | |
| 130 | /********************************************************************************** |
| 131 | Class set_data_info methods regarding setting and getting asset-data values: |
| 132 | **********************************************************************************/ |
| 133 | |
| 134 | string set_data_info::rand_creation_flags (void) |
| 135 | { |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 136 | string result = ""; |
Nik Dewally | 841612a | 2024-07-22 15:27:43 +0100 | [diff] [blame] | 137 | const int most_flags = 2; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 138 | int n_flags = (rand() % most_flags); |
| 139 | |
Nik Dewally | 841612a | 2024-07-22 15:27:43 +0100 | [diff] [blame] | 140 | for (int i = 0; i < n_flags; ++i) { |
| 141 | switch (rand() % 3) { |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 142 | case 0: |
| 143 | result += "PSA_STORAGE_FLAG_NONE"; |
| 144 | break; |
| 145 | case 1: |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 146 | result += "PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION"; |
| 147 | break; |
Nik Dewally | 841612a | 2024-07-22 15:27:43 +0100 | [diff] [blame] | 148 | case 2: |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 149 | result += "PSA_STORAGE_FLAG_NO_CONFIDENTIALITY"; |
| 150 | break; |
| 151 | } |
| 152 | if (i < n_flags-1) |
| 153 | result += " | "; |
| 154 | } |
| 155 | if (result == "") result = "PSA_STORAGE_FLAG_NONE"; |
Nik Dewally | 841612a | 2024-07-22 15:27:43 +0100 | [diff] [blame] | 156 | |
| 157 | return result; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 158 | } |
| 159 | |
| 160 | set_data_info::set_data_info (void) // (default constructor) |
| 161 | { |
| 162 | literal_data_not_file = true; // currently, not using files as data sources |
| 163 | string_specified = false; |
| 164 | data.assign (""); |
| 165 | random_data = false; |
| 166 | file_specified = false; |
| 167 | file_path.assign (""); |
| 168 | n_set_vars = -1; // so the first reference is 0 (no suffix), then _1, _2, ... |
| 169 | data_offset = 0; |
| 170 | flags_string = rand_creation_flags(); |
| 171 | } |
| 172 | set_data_info::~set_data_info (void) // (destructor) |
| 173 | {} |
| 174 | |
| 175 | /* set() establishes: |
| 176 | * An asset's data value from a template line (e.g., set sst snort data "data |
| 177 | value"), and |
| 178 | * *That* such a value was directly specified, as opposed to no data value having |
| 179 | been specified, or a random data value being requested. |
| 180 | Arguably, this method "has side effects," in that it not only sets a value, but |
| 181 | also "takes notes" about where that value came from. |
| 182 | */ |
| 183 | void set_data_info::set (string set_val) |
| 184 | { |
| 185 | literal_data_not_file = true; // currently, not using files as data sources |
| 186 | string_specified = true; |
| 187 | data.assign (set_val); |
| 188 | } |
| 189 | |
| 190 | /* set_calculated() establishes: |
| 191 | * An asset's data value as *not* taken from a template line, and |
| 192 | * *That* such a value was not directly specified in any template line, such as |
| 193 | if a random data value being requested. |
| 194 | Arguably, this method "has side effects," in that it not only sets a value, but |
| 195 | also "takes notes" about where that value came from. |
| 196 | */ |
| 197 | void set_data_info::set_calculated (string set_val) |
| 198 | { |
| 199 | literal_data_not_file = true; // currently, not using files as data sources |
| 200 | string_specified = false; |
| 201 | data.assign (set_val); |
| 202 | } |
| 203 | |
| 204 | /* randomize() establishes: |
| 205 | * An asset's data value as *not* taken from a template line, and |
| 206 | * *That* such a value was randomized. |
| 207 | Arguably, this method "has side effects," in that it not only sets a value, but |
| 208 | also "takes notes" about where that value came from. |
| 209 | */ |
| 210 | void set_data_info::randomize (void) |
| 211 | { |
| 212 | gibberish gib; |
| 213 | char gib_buff[4096]; // spew gibberish into here |
| 214 | int rand_data_length = 0; |
| 215 | |
| 216 | string_specified = false; |
| 217 | random_data = true; |
| 218 | literal_data_not_file = true; |
| 219 | rand_data_length = 40 + (rand() % 256); |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 220 | /* Note: Multiple assets do get different random data */ |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 221 | gib.sentence (gib_buff, gib_buff + rand_data_length - 1); |
| 222 | data = gib_buff; |
| 223 | } |
| 224 | |
| 225 | /* Getter for protected member, data. Protected so that it can only be set by |
| 226 | set() or set_calculated(), above, to establish not only its value but |
| 227 | how it came about. */ |
| 228 | string set_data_info::get (void) |
| 229 | { |
| 230 | return data; |
| 231 | } |
| 232 | |
| 233 | /* Currently, files as data sources aren't used, so this whole method is not "of |
| 234 | use," but that might change at some point. */ |
| 235 | bool set_data_info::set_file (string file_name) |
| 236 | { |
| 237 | literal_data_not_file = true; |
| 238 | string_specified = false; |
| 239 | data.assign (""); |
| 240 | file_specified = true; |
| 241 | // Remove the ' ' quotes around the file name: |
| 242 | file_name.erase (0, 1); |
| 243 | file_name.erase (file_name.length()-1, 1); |
| 244 | file_path = file_name; |
| 245 | return true; |
| 246 | } |
| 247 | |
| 248 | /********************************************************************************** |
| 249 | End of methods of class set_data_info. |
| 250 | **********************************************************************************/ |
| 251 | |
| 252 | |
| 253 | /********************************************************************************** |
| 254 | Class asset_name_id_info methods regarding setting and getting asset-data values: |
| 255 | **********************************************************************************/ |
| 256 | |
| 257 | asset_name_id_info::asset_name_id_info (void) // (default constructor) |
| 258 | { |
| 259 | id_n_not_name = false; // (arbitrary) |
| 260 | id_n = 100LL + ((uint64_t) rand() % 10000); // default to random ID# |
| 261 | asset_name.assign (""); |
| 262 | id_n_specified = name_specified = false; // no ID info yet |
| 263 | asset_type = psa_asset_type::unknown; |
| 264 | how_asset_found = asset_search::not_found; |
| 265 | the_asset = nullptr; |
| 266 | asset_ser_no = -1; |
| 267 | } |
| 268 | asset_name_id_info::~asset_name_id_info (void) |
| 269 | { |
| 270 | asset_name_vector.clear(); |
| 271 | asset_id_n_vector.clear(); |
| 272 | } |
| 273 | |
| 274 | /* set_name() establishes: |
| 275 | * An asset's "human" name from a template line, and |
| 276 | * *That* that name was directly specified, as opposed to the asset being defined |
| 277 | by ID only, or a random name being requested. |
| 278 | Arguably, this method "has side effects," in that it not only sets a name, but |
| 279 | also "takes notes" about where that name came from. |
| 280 | */ |
| 281 | void asset_name_id_info::set_name (string set_val) |
| 282 | { |
| 283 | /* Use this to set the name as specified in the template file. Call this only |
| 284 | if the template file does indeed define a name. */ |
| 285 | name_specified = true; |
| 286 | asset_name.assign (set_val); |
| 287 | } |
| 288 | |
| 289 | /* set_calc_name() establishes: |
| 290 | * An asset's "human" name *not* from a template line, and |
| 291 | * *That* that name was *not* directly specified in any template line. |
| 292 | Arguably, this method "has side effects," in that it not only sets a name, but |
| 293 | also "takes notes" about where that name came from. |
| 294 | */ |
| 295 | void asset_name_id_info::set_calc_name (string set_val) |
| 296 | { |
| 297 | name_specified = false; |
| 298 | asset_name.assign (set_val); |
| 299 | } |
| 300 | |
| 301 | // set_just_name() sets an asset's "human" name, without noting how that name came up. |
| 302 | void asset_name_id_info::set_just_name (string set_val) |
| 303 | { |
| 304 | asset_name.assign (set_val); |
| 305 | } |
| 306 | |
| 307 | /* Getter for protected member, asset_name. Protected so that it can only be set by |
| 308 | set_name() or set_calc_name(), above, to establish not only its value but |
| 309 | how it came about. */ |
| 310 | string asset_name_id_info::get_name (void) |
| 311 | { |
| 312 | return asset_name; |
| 313 | } |
| 314 | |
| 315 | // Asset IDs can be set directly from a uint64_t or converted from a string: |
| 316 | void asset_name_id_info::set_id_n (string set_val) |
| 317 | { |
| 318 | id_n = stol (set_val, 0, 0); |
| 319 | } |
| 320 | void asset_name_id_info::set_id_n (uint64_t set_val) |
| 321 | { |
| 322 | id_n = set_val; |
| 323 | } |
| 324 | |
| 325 | // Create ID-based name: |
| 326 | string asset_name_id_info::make_id_n_based_name (uint64_t id_n) |
| 327 | { |
| 328 | string result; |
| 329 | |
| 330 | switch (asset_type) { |
| 331 | case psa_asset_type::sst: |
| 332 | result = "SST_ID_"; |
| 333 | break; |
| 334 | case psa_asset_type::key: |
| 335 | result = "Key_ID_"; |
| 336 | break; |
| 337 | case psa_asset_type::policy: |
| 338 | result = "Policy_ID_"; |
| 339 | break; |
| 340 | default: |
| 341 | cerr << "\nError: Tool-internal: Please report error " |
Nik Dewally | 6663dde | 2024-08-09 16:12:27 +0100 | [diff] [blame] | 342 | << "#1223 to the TF-Fuzz developers." << endl; |
Karl Zhang | 3de5ab1 | 2021-05-31 11:45:48 +0800 | [diff] [blame] | 343 | exit(1223); |
| 344 | } |
| 345 | result.append(to_string(id_n)); |
| 346 | return result; |
| 347 | } |
| 348 | |
| 349 | /********************************************************************************** |
| 350 | End of methods of class asset_name_id_info. |
| 351 | **********************************************************************************/ |
| 352 | |
| 353 | |
| 354 | /********************************************************************************** |
| 355 | Class key_policy_info methods: |
| 356 | **********************************************************************************/ |
| 357 | |
| 358 | key_policy_info::key_policy_info (void) // (default constructor) |
| 359 | { |
| 360 | get_policy_from_key = false; // specify policy asset by a key that uses it. |
| 361 | copy_key = false; // not copying one key to another |
| 362 | /* The following settings are not necessarily being randomized in mutually- |
| 363 | consistent ways, for two reasons: First, the template should set all that |
| 364 | matter, and second, testing TF response to nonsensical settings is also |
| 365 | valuable. */ |
| 366 | exportable = (rand()%2==1? true : false); |
| 367 | copyable = (rand()%2==1? true : false); |
| 368 | can_encrypt = (rand()%2==1? true : false); |
| 369 | can_decrypt = (rand()%2==1? true : false); |
| 370 | can_sign = (rand()%2==1? true : false); |
| 371 | can_verify = (rand()%2==1? true : false); |
| 372 | derivable = (rand()%2==1? true : false); |
| 373 | persistent = (rand()%2==1? true : false); |
| 374 | // There's a really huge number of possible key types; won't randomize all: |
| 375 | key_type = rand_key_type(); |
| 376 | usage_string.assign (""); |
| 377 | print_usage_true_string.assign (""); |
| 378 | print_usage_false_string.assign (""); |
| 379 | key_algorithm = rand_key_algorithm(); |
| 380 | n_bits = 55 + (rand() % 1000); |
| 381 | gibberish *gib = new gibberish; |
| 382 | char buffer[256]; |
| 383 | char *end; |
| 384 | int buf_len = 5ULL + (uint64_t) (rand() % 10); |
| 385 | end = gib->word (false, buffer, buffer + buf_len); |
| 386 | *end = '\0'; |
| 387 | buffer[buf_len] = '\0'; |
| 388 | handle_str = buffer; |
| 389 | gib->sentence (buffer, buffer + (40ULL + (uint64_t) (rand() % 200))); |
| 390 | key_data = buffer; |
| 391 | delete gib; |
| 392 | } |
| 393 | key_policy_info::~key_policy_info (void) // (destructor) |
| 394 | { |
| 395 | return; // (even if only to have something to pin a breakpoint on) |
| 396 | } |
| 397 | |
| 398 | |
| 399 | /********************************************************************************** |
| 400 | End of methods of class key_policy_info. |
| 401 | **********************************************************************************/ |