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