blob: 41889a91d577ec15560ae52ddb17a980db5c989d [file] [log] [blame]
Karl Zhang3de5ab12021-05-31 11:45:48 +08001/*
Nik Dewally6663dde2024-08-09 16:12:27 +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
8%{
9#include <iostream>
10#include <vector>
11#include <set>
12
13#include "class_forwards.hpp"
14#include "data_blocks.hpp"
15#include "boilerplate.hpp"
16#include "gibberish.hpp"
17#include "compute.hpp"
18#include "string_ops.hpp"
19#include "psa_asset.hpp"
20#include "find_or_create_asset.hpp"
21#include "template_line.hpp"
22#include "tf_fuzz.hpp"
23#include "sst_asset.hpp"
24#include "crypto_asset.hpp"
25#include "psa_call.hpp"
26#include "crypto_call.hpp"
27#include "sst_call.hpp"
28#include "security_call.hpp"
29#include "secure_template_line.hpp"
30#include "sst_template_line.hpp"
31#include "crypto_template_line.hpp"
Nik Dewallyabac0e52024-08-02 13:42:27 +010032#include "fill_in_policy.hpp"
Karl Zhang3de5ab12021-05-31 11:45:48 +080033
34/* These items are defined in tf_fuzz_grammar.l. Note, however that, because
35 of "name mangling," defining them as extern "C" may or may not be ideal,
36 depending upon which compiler -- gcc vs. g++, compiles the output from lex.
37 So far, it seems best without the extern "C", including also compiling
38 under Visual Studio. */
39/* extern "C"
40{ */
41 extern int yylineno;
42 int yywrap() {return 1;}
43 extern char yytext[];
44 extern int yyleng;
45/* } */
46
47int yylex (void);
48void yyerror (tf_fuzz_info *, const char *);
49 /* Sends the yyparse() argument to yyerror(), probably, to print incorrect
50 text it parsed. */
51
52/* A few consts just to make code more comprehensible: */
53const bool yes_fill_in_template = true;
54const bool dont_fill_in_template = false;
55const bool yes_create_call = true;
56const bool dont_create_call = false;
57
58tf_fuzz_info *rsrc;
59
60/* These are object pointers used to parse the template and create the test. Ac-
61 tually, probably only templateLin is used for now, but this is a good outline of
62 of the template_line class hierarchy. */
63template_line *templateLin = nullptr;
64 sst_template_line *sstTemplateLin = nullptr;
65 set_sst_template_line *setSstTemplateLin = nullptr;
66 read_sst_template_line *reaSstTemplateLin = nullptr;
67 remove_sst_template_line *remSstTemplateLin = nullptr;
68 policy_template_line *polTemplateLin = nullptr;
69 set_policy_template_line *setPolTemplateLin = nullptr;
70 read_policy_template_line *reaPolTemplateLin = nullptr;
71 key_template_line *keyTemplateLin = nullptr;
72 set_key_template_line *setKeyTemplateLin = nullptr;
73 read_key_template_line *reaKeyTemplateLin = nullptr;
74 remove_key_template_line *remKeyTemplateLin = nullptr;
75 security_template_line *secTemplateLin = nullptr;
76 security_hash_template_line *secHasTemplateLin = nullptr;
77/* Call and asset objects are presumably not immediately needed, because the objects
78 of these types are within the resource object, *rsrc, but even if only just to
79 show that class hierarchy: */
80psa_call *psaCal = nullptr;
81 sst_call *sstCal = nullptr;
82 sst_set_call *sstSetCal = nullptr;
83 sst_get_call *sstGetCal = nullptr;
84 sst_remove_call *sstRemCal = nullptr;
85 crypto_call *cryCal = nullptr;
86 policy_call *polCal = nullptr;
87 init_policy_call *iniPolCal = nullptr;
88 reset_policy_call *resPolCal = nullptr;
89 add_policy_usage_call *addPolUsaCal = nullptr;
90 set_policy_lifetime_call *setPolLifCal = nullptr;
91 set_policy_type_call *setPolTypCal = nullptr;
92 set_policy_algorithm_call *setPolAlgCal = nullptr;
93 set_policy_usage_call *setPolUsaCal = nullptr;
94 get_policy_lifetime_call *getPolLifCal = nullptr;
95 get_policy_type_call *getPolTypCal = nullptr;
96 get_policy_algorithm_call *getPolAlgCal = nullptr;
97 get_policy_usage_call *getPolUsaCal = nullptr;
98 get_policy_size_call *getPolSizCal = nullptr;
99 get_key_policy_call *getKeyPolCal = nullptr;
100 key_call *keyCal = nullptr;
101 generate_key_call *genKeyCal = nullptr;
Nik Dewallyed341b72024-08-20 17:02:30 +0100102 import_key_call *creKeyCal = nullptr;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800103 copy_key_call *copKeyCal = nullptr;
104 read_key_data_call *reaKeyDatCal = nullptr;
105 remove_key_call *remKeyCal = nullptr;
106psa_asset *psaAst = nullptr;
107 sst_asset *sstAst = nullptr;
108 crypto_asset *cryAst = nullptr;
109 policy_asset *polAst = nullptr;
110 key_asset *keyAst = nullptr;
111
112/* For generating random, but readable/memorable, data: */
113gibberish gib;
114char gib_buff[4096]; // spew gibberish into here
115int rand_data_length = 0;
116
117/* General-utility variables: */
118bool purpose_defined = false;
119psa_asset_usage random_asset = psa_asset_usage::all;
120 /* to pick what type of asset at random */
121bool random_name; /* template didn't specify name, so it's generated randomly */
122string literal_data; /* literal data for an asset value */
123
124/* Holders for state in read commands: */
125expect_info expect; /* everything about expected results and data */
126set_data_info set_data; /* everything about setting the value of PSA-asset data */
127asset_name_id_info parsed_asset; /* everything about identifying assets */
128string target_barrier = ""; /* asset to set and search barrier when re-ordering PSA calls */
129key_policy_info policy_info; /* everything about key policies */
130bool assign_data_var_specified = false;
131string assign_data_var;
132bool print_data = false; /* true to just print asset data to the test log */
133bool hash_data = false; /* true to just print asset data to the test log */
134bool literal_is_string = true;
135 /* if true, literal value is character-string; if false, is list of hex values */
136
Nik Dewallyabac0e52024-08-02 13:42:27 +0100137bool policy_must_be_valid = false;
138
Karl Zhang3de5ab12021-05-31 11:45:48 +0800139/* The following are more tied to the template syntax than to the resulting PSA calls */
140string literal; /* temporary holder for all string literals */
141string identifier; /* temporary holder for strings representing identifiers */
142string var_name; /* a variable name */
143string asset_name; /* as parsed, not yet put into parsed_asset */
144string aid; /* string-typed holder for an asset ID in a list thereof */
145int nid; /* same idea as aid, but for asset ID# lists */
146size_t strFind1, strFind2; /* for searching through strings */
147
148/* Because of the parsing order, psa_calls of the specific type have to be
149 push_back()ed onto rsrc->calls before their expected results are known. Therefore,
150 must inject those results after parsing the expected results. add_expect is a
151 loop index to track where to add results. */
152unsigned int add_expect = 0;
153
154/* Temporaries: */
155vector<psa_asset*>::iterator t_sst_asset;
156vector<psa_asset*>::iterator t_key_asset;
157vector<psa_asset*>::iterator t_policy_asset;
158sst_call *t_sst_call = nullptr;
159key_call *t_key_call = nullptr;
160policy_call *t_policy_call = nullptr;
161long number; /* temporary holder for a number, e.g., sting form of UID */
162int i, j, k;
163
164/* Relating to template-statement blocks: */
165vector<template_line*> template_block_vector; /* (must be *pointers to* templates) */
166vector<int> block_order; /* "statisticalized" order of template lines in a block */
167int nesting_level = 0;
168 /* how many levels deep in { } nesting currently. Initially only 0 or 1. */
169bool shuffle_not_pick;
170 /* true to shuffle statements in a block, rather than pick so-and-so
171 number of them at random. */
172int low_nmbr_lines = 1; /* if picking so-and-so number of template lines from a ... */
173int high_nmbr_lines = 1; /* ... block at random, these are fewest and most lines. */
174int exact_nmbr_lines = 1;
175
176using namespace std;
177
178
179void set_purp_str (
180 char *raw_purpose, /* the purpose C string from parser */
181 tf_fuzz_info *rsrc /* test resources containing the actual test-purpose string */
182) {
183 size_t l; /* temporary of size_t type */
184 string purp_str = raw_purpose;
185 strFind1 = purp_str.find (" ");
186 purp_str = purp_str.substr (strFind1, purp_str.length());
187 purp_str.erase (0, 1); // (extra space)
188 strFind1 = purp_str.rfind (";");
189 purp_str = purp_str.substr (0, strFind1);
190 l = 0;
191 do { /* escape all " chars (if not already escaped) */
192 l = purp_str.find ("\"", l);
193 if ( l < purp_str.length()) { /* did find a quote character */
194 if ( l == 0 /* it's the first character in the string*/
195 || purp_str[l-1] != '\\' /* or it's not already escaped */
196 ) {
197 purp_str.insert (l, "\\"); /* then escape the " char */
198 l++; /* point l to the " again */
199 }
200 l++; /* point l past the " */
201 }
202 } while (l < purp_str.length());
203 rsrc->test_purpose = purp_str;
204}
205
206/* randomize_template_lines() chooses a template-line order in cases where they are to
207 be randomized -- shuffled or random picked. */
208void randomize_template_lines (
209 bool shuffle_not_pick, /* true to perform a shuffle operation rather than pick */
210 int &low_nmbr_lines, /* if picking so-and-so number of template lines from a ... */
211 int &high_nmbr_lines, /* ... block at random, these are fewest and most lines. */
212 int &exact_nmbr_lines,
213 vector<template_line*> &template_block_vector,
214 vector<int> &block_order,
215 tf_fuzz_info *rsrc /* test resources containing the actual test-purpose string */
216) {
217 set<int> template_used; /* used for shuffle */
218 low_nmbr_lines = (low_nmbr_lines < 0)? 0 : low_nmbr_lines;
219 high_nmbr_lines = (high_nmbr_lines < 0)? 0 : high_nmbr_lines;
220 if (low_nmbr_lines > high_nmbr_lines) {
221 int swap = low_nmbr_lines;
222 low_nmbr_lines = high_nmbr_lines;
223 high_nmbr_lines = swap;
224 }
225 template_used.clear();
226 if (shuffle_not_pick) {
227 /* Choose a random order in which to generate all of the
228 template lines in the block: */
229 while (template_used.size() < template_block_vector.size()) {
230 i = rand() % template_block_vector.size();
231 if (template_used.find (i) == template_used.end()) {
232 /* This template not already shuffled in. */
233 block_order.push_back (i);
234 template_used.insert (i);
235 }
236 }
237 /* Done shuffling; empty out the set: */
238 } else {
239 if (high_nmbr_lines == low_nmbr_lines) {
240 exact_nmbr_lines = low_nmbr_lines;
241 /* just in case the template says "3 to 3 of"... */
242 } else {
243 exact_nmbr_lines = low_nmbr_lines
244 + (rand() % ( high_nmbr_lines
245 - low_nmbr_lines + 1 ) );
246 }
247 for (int j = 0; j < exact_nmbr_lines; ++j) {
248 /* Repeatedly choose a random template line from the block: */
249 i = rand() % template_block_vector.size();
250 block_order.push_back (i);
251 }
252 }
253 IVM(cout << "Order of lines in block: " << flush;
254 for (auto i : block_order) {
255 cout << i << " ";
256 }
257 cout << endl;
258 )
259}
260
261/* interpret_template_line() fills in random data, locates PSA assets, (etc.) and
262 conditionally creates PSA calls for a given template line. Note that there needs
263 to be a single place where all of this is done, so that statement blocks can be
264 randomized and then dispatched from a single point. */
265void interpret_template_line (
266 template_line *templateLin, /* the template line to process */
267 tf_fuzz_info *rsrc, /* program resources in general */
268 set_data_info &set_data, psa_asset_usage random_asset,
269 bool assign_data_var_specified, expect_info &expect, key_policy_info &policy_info,
270 bool print_data, bool hash_data, string asset_name, string assign_data_var,
271 asset_name_id_info &asset_info, /* everything about the asset(s) involved */
272 bool create_call_bool, /* true to create the PSA call at this time */
273 bool create_asset_bool, /* true to create the PSA asset at this time */
274 bool fill_in_template, /* true to back-fill info into template */
Nik Dewallyabac0e52024-08-02 13:42:27 +0100275 int instance,
Karl Zhang3de5ab12021-05-31 11:45:48 +0800276 /* if further differentiation to the names or IDs is needed, make instance >0 */
Nik Dewallyabac0e52024-08-02 13:42:27 +0100277 bool do_fill_in_policy=false,
278 bool policy_must_be_valid=false
Karl Zhang3de5ab12021-05-31 11:45:48 +0800279) {
280 const bool yes_fill_in_template = true; /* just to improve readability */
281 vector<psa_asset*>::iterator t_psa_asset;
282
Nik Dewallyabac0e52024-08-02 13:42:27 +0100283 // take the partial policy info specified by the user, and flesh it out
284 // into either a random policy, or a random valid policy.
285 if (do_fill_in_policy) {
286 fill_in_policy(policy_info,policy_must_be_valid);
287 }
288
Karl Zhang3de5ab12021-05-31 11:45:48 +0800289 if (fill_in_template) {
290 /* Set basic parameters from the template line: */
291 templateLin->set_data = set_data;
292 templateLin->expect = expect;
293 templateLin->policy_info = policy_info;
294 templateLin->asset_info.id_n_not_name = asset_info.id_n_not_name;
295 templateLin->asset_info.set_name (asset_name);
296 /* Fill in state parsed from the template below: */
297 templateLin->assign_data_var_specified = assign_data_var_specified;
298 templateLin->assign_data_var.assign (assign_data_var);
299 templateLin->print_data = print_data;
300 templateLin->hash_data = hash_data;
301 templateLin->random_asset = random_asset;
302 if ( set_data.literal_data_not_file && !set_data.random_data
303 && set_data.string_specified) {
304 templateLin->set_data.set (literal_data);
305 }
306 /* Save names or IDs to the template-line tracker: */
307 for (auto id_no : asset_info.asset_id_n_vector) {
308 templateLin->asset_info.asset_id_n_vector.push_back (id_no);
309 }
310 asset_info.asset_id_n_vector.clear();
311 for (auto as_name : asset_info.asset_name_vector) {
312 templateLin->asset_info.asset_name_vector.push_back (as_name);
313 }
314 asset_info.asset_name_vector.clear();
315 }
316
317 /* Random asset choice (e.g., *active) case: */
318 if (templateLin->random_asset != psa_asset_usage::all) {
319 /* Just create the call tracker; random name chosen in simulation stage: */
320 templateLin->setup_call (set_data, templateLin->set_data.random_data,
321 yes_fill_in_template, create_call_bool,
322 templateLin, rsrc );
323 } else if (asset_info.id_n_not_name) {
324 /* Not random asset; asset(s) by ID rather than name. Go through all
325 specified asset IDs: */
326 uint64_t id_no;
327 for (auto id_n : templateLin->asset_info.asset_id_n_vector) {
328 id_no = id_n + (uint64_t) instance * 10000UL;
329 templateLin->asset_info.set_id_n(id_no); /* just a holder */
330 asset_name = templateLin->asset_info.make_id_n_based_name (id_no);
331 templateLin->asset_info.set_calc_name (asset_name);
332 templateLin->expect.data_var = var_name;
333 if (!set_data.literal_data_not_file) {
334 templateLin->set_data.set_file (set_data.file_path);
335 }
336 templateLin->setup_call (set_data, templateLin->set_data.random_data,
337 fill_in_template, create_call_bool,
338 templateLin, rsrc );
339 }
340 } else {
341 /* Not random asset, asset(s) specified by name. Go through all specified
342 asset names: */
343 for (auto as_name : templateLin->asset_info.asset_name_vector) {
344 /* Also copy into template line object's local vector: */
345 if (instance > 0) {
346 templateLin->asset_info.set_name (as_name + "_" + to_string (instance));
347 } else {
348 templateLin->asset_info.set_name (as_name);
349 }
350 /* Give each occurrence a different random ID: */
351 templateLin->asset_info.set_id_n (100 + (rand() % 10000));
352 /* TODO: unlikely, but this *could* alias! */
353 templateLin->setup_call (set_data, templateLin->set_data.random_data,
354 yes_fill_in_template, create_call_bool,
355 templateLin, rsrc );
356 }
357 }
358}
359
360%}
361
362%start lines
363
364%union {int valueN; int tokenN; char *str;}
365%token <tokenN> PURPOSE RAW_TEXT
366%token <tokenN> SET READ REMOVE SECURE DONE /* root commands */
367%token <tokenN> SST KEY POLICY NAME UID STAR ACTIVE DELETED EQUAL DATA DFNAME
368%token <tokenN> FLAG NONE WRITE_ONCE NO_RP NO_CONF /* SST creation flag keywords */
369%token <tokenN> OFFSET /* offset into an SST asset */
370%token <tokenN> CHECK VAR HASH NEQ PRINT EXPECT PASS FAIL NOTHING ERROR /* expected results */
371%token <str> IDENTIFIER_TOK LITERAL_TOK HEX_LIST FILE_PATH_TOK /* variables and content */
372%token <valueN> NUMBER_TOK /* variables and content */
373%token <tokenN> SEMICOLON SHUFFLE TO OF OPEN_BRACE CLOSE_BRACE /* block structure */
Nik Dewally5200f6e2024-08-15 14:08:50 +0100374%token <tokenN> ATTR TYPE ALG SIZE /* "set policy" line portions */
Nik Dewallyabac0e52024-08-02 13:42:27 +0100375%token <tokenN> VALID
Karl Zhang3de5ab12021-05-31 11:45:48 +0800376%token <tokenN> EXPORT COPY ENCRYPT DECRYPT SIGN VERIFY DERIVE /* key-usage keywords */
377%token <tokenN> NOEXPORT NOCOPY NOENCRYPT NODECRYPT NOSIGN NOVERIFY NODERIVE
378%token <tokenN> PERSISTENT VOLATILE /* key lifetime keywords */
379%token <tokenN> FROM /* for copying a key "from" another */
380%token <tokenN> WITH /* for specifying a key without explicitly defining a policy */
381
382%define parse.error verbose
383%locations
384%parse-param {tf_fuzz_info *rsrc}
385
386%%
387
388 /* Top-level syntax: */
389lines:
390 %empty /* nothing */
391 | line lines {
392 IVM(cout << "Lines: Line number " << dec << yylineno << "." << endl;)
393 /* Re-randomize objects we parse into: */
394 expect = expect_info();
395 set_data = set_data_info();
396 parsed_asset = asset_name_id_info();
Nik Dewallyabac0e52024-08-02 13:42:27 +0100397
398 // blank new policy -- this is filled in later by interpret template
Karl Zhang3de5ab12021-05-31 11:45:48 +0800399 policy_info = key_policy_info();
400 }
401 ;
402
403line:
404 PURPOSE {
405 IVM(cout << "Purpose line: " << flush;)
406 set_purp_str (yytext, rsrc);
407 IVM(cout << rsrc->test_purpose << endl;)
408 /* TODO: Is there much/any value in turning this back on? The
409 constructor clear()s them out, and run-time errors observed
410 under Visual Studio...
411 Just a precaution to make sure that these vectors start out empty.
412 Should inherently be, but purpose is typically specified first:
413 parsed_asset.asset_id_n_vector.clear();
414 parsed_asset.asset_name_vector.clear(); */
415 /* Re-randomize or re-initialize objects we parse into: */
416 purpose_defined = true;
417 expect = expect_info();
418 set_data = set_data_info();
419 parsed_asset = asset_name_id_info();
Nik Dewallyabac0e52024-08-02 13:42:27 +0100420
421 // blank new policy -- this is filled in later by interpret template
Karl Zhang3de5ab12021-05-31 11:45:48 +0800422 policy_info = key_policy_info();
Nik Dewallyabac0e52024-08-02 13:42:27 +0100423 policy_must_be_valid = false;
424
Karl Zhang3de5ab12021-05-31 11:45:48 +0800425 target_barrier = "";
426 }
427 | block {
Nik Dewallyabac0e52024-08-02 13:42:27 +0100428 policy_info = key_policy_info();
429 policy_must_be_valid = false;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800430 /* TODO: This code may not won't work with "secure hash neq ..." */
431 IVM(cout << "Block of lines." << endl;)
432 /* "Statisticalize" :-) the vector of template lines, then crank
433 the selected lines in order here. */
434 randomize_template_lines (shuffle_not_pick,
435 low_nmbr_lines, high_nmbr_lines, exact_nmbr_lines,
436 template_block_vector, block_order, rsrc
437 );
438 /* Vector block_order contains the sequence of template lines to be
439 realized, in order. Pop the indicated template line off the
440 vector and generate code from it: */
441 k = 0; /* ID adder to at least help ensure uniqueness */
442 for (int i : block_order) {
443 templateLin = template_block_vector[i];
444 /* Note that temLin will have its fields filled in already. */
445 interpret_template_line (
446 templateLin, rsrc, set_data, random_asset,
447 assign_data_var_specified, expect, policy_info,
448 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
449 yes_create_call, /* did not create call nor asset earlier */
450 yes_create_asset,
451 dont_fill_in_template, /* but did fill it all in before */
452 0
Nik Dewallyabac0e52024-08-02 13:42:27 +0100453
Karl Zhang3de5ab12021-05-31 11:45:48 +0800454 );
455 k++;
456 for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
457 if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
458 templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
459 templateLin->expect.expected_results_saved = true;
460 }
461 }
Nik Dewallyabac0e52024-08-02 13:42:27 +0100462 }
Karl Zhang3de5ab12021-05-31 11:45:48 +0800463 templateLin->asset_info.asset_id_n_vector.clear();
464 templateLin->asset_info.asset_name_vector.clear();
465 /* Done. Empty out the "statisticalization" vector: */
466 block_order.clear();
467 /* Empty out the vector of template lines; no longer needed. */
468 template_block_vector.clear();
469 --nesting_level;
470 IVM(cout << "Finished coding block of lines." << endl;)
471 }
472 | command SEMICOLON {
Nik Dewallyabac0e52024-08-02 13:42:27 +0100473 policy_info = key_policy_info();
474 policy_must_be_valid = false;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800475 IVM(cout << "Command with no expect: \"" << flush;)
476 if (!purpose_defined) {
477 cerr << endl << endl
478 << "Error: Please begin your test with the \"purpose\" "
479 << "directive. \n For example, "
480 << "\"purpose to exercise crypto and SST...\"" << endl;
481 exit (1024);
482 }
483 if (nesting_level == 0) { /* if laying down the code now... */
484 for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
485 if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
486 templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
487 templateLin->expect.expected_results_saved = true;
488 }
489 }
490 delete templateLin; /* done with this template line */
491 } else {
492 /* The template line is now fully decoded, so stuff it onto
493 vector of lines to be "statisticalized": */
494 template_block_vector.push_back (templateLin);
495 }
496 IVM(cout << yytext << "\"" << endl;)
497 }
498 | command expect SEMICOLON {
Nik Dewallyabac0e52024-08-02 13:42:27 +0100499 policy_info = key_policy_info();
500 policy_must_be_valid = false;
Karl Zhang3de5ab12021-05-31 11:45:48 +0800501 /* (This is the same as for command SEMICOLON, other than the IVM.) */
502 IVM(cout << "Command with expect: \"" << flush;)
503 if (!purpose_defined) {
504 cerr << endl << endl
505 << "Error: Please begin your test with the \"purpose\" "
506 << "directive. \n For example, "
507 << "\"purpose to exercise crypto and SST...\"" << endl;
508 exit (1024);
509 }
510 if (nesting_level == 0) {
511 for (add_expect = 0; add_expect < rsrc->calls.size(); ++add_expect) {
512 if (!(rsrc->calls[add_expect]->exp_data.expected_results_saved)) {
513 templateLin->expect.copy_expect_to_call (rsrc->calls[add_expect]);
514 templateLin->expect.expected_results_saved = true;
515 }
516 }
517 delete templateLin;
518 } else {
519 template_block_vector.push_back (templateLin);
520 }
521 IVM(cout << yytext << "\"" << endl;)
522 }
523 ;
524
525command:
526 set_command {
527 IVM(cout << "Set command: \"" << yytext << "\"" << endl;)
528 }
529 | remove_command {
530 IVM(cout << "Remove command: \"" << yytext << "\"" << endl;)
531 }
532 | read_command {
533 IVM(cout << "Read command: \"" << yytext << "\"" << endl;)
534 }
535 | secure_command {
536 IVM(cout << "Security command: \"" << yytext << "\"" << endl;)
537 }
538 | done_command {
539 IVM(cout << "Done command: \"" << yytext << "\"" << endl;)
540 }
541 ;
542
543expect:
544 EXPECT PASS {
545 IVM(cout << "Expect pass clause: \"" << flush;)
Nik Dewally6663dde2024-08-09 16:12:27 +0100546 templateLin->expect.expect_pass();
Karl Zhang3de5ab12021-05-31 11:45:48 +0800547 IVM(cout << yytext << "\"" << endl;)
548 }
549 | EXPECT FAIL {
550 IVM(cout << "Expect fail clause: \"" << flush;)
Nik Dewally6663dde2024-08-09 16:12:27 +0100551 templateLin->expect.expect_failure();
Karl Zhang3de5ab12021-05-31 11:45:48 +0800552 IVM(cout << yytext << "\"" << endl;)
553 }
554 | EXPECT NOTHING {
555 IVM(cout << "Expect nothing clause: \"" << flush;)
Nik Dewally6663dde2024-08-09 16:12:27 +0100556 templateLin->expect.disable_result_code_checking();
Karl Zhang3de5ab12021-05-31 11:45:48 +0800557 IVM(cout << yytext << "\"" << endl;)
558 }
559 | EXPECT IDENTIFIER {
560 IVM(cout << "Expect error clause: \"" << flush;)
Nik Dewally6663dde2024-08-09 16:12:27 +0100561 templateLin->expect.expect_error_code (identifier);
Karl Zhang3de5ab12021-05-31 11:45:48 +0800562 IVM(cout << yytext << "\"" << endl;)
563 }
564 ;
565
566 /* Root commands: */
567set_command:
568 SET SST sst_set_base_args sst_set_extended_args {
569 IVM(cout << "Set SST command: \"" << yytext << "\"" << endl;)
570 templateLin = new set_sst_template_line (rsrc);
571 interpret_template_line (
572 templateLin, rsrc, set_data, random_asset,
573 assign_data_var_specified, expect, policy_info,
574 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
575 nesting_level == 0 /* create call unless inside {} */,
576 nesting_level == 0 /* similarly, create asset unless inside {} */,
577 yes_fill_in_template, 0
578 );
579 }
580 | SET KEY key_set_args {
581 IVM(cout << "Set key command: \"" << yytext << "\"" << endl;)
582 templateLin = new set_key_template_line (rsrc);
583 target_barrier = policy_info.asset_2_name; /* policy */
584 interpret_template_line (
585 templateLin, rsrc, set_data, random_asset,
586 assign_data_var_specified, expect, policy_info,
587 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
588 nesting_level == 0 /* create call unless inside {} */,
589 nesting_level == 0 /* similarly, create asset unless inside {} */,
Nik Dewallyabac0e52024-08-02 13:42:27 +0100590 yes_fill_in_template, 0,
591 true,
592 policy_must_be_valid
Karl Zhang3de5ab12021-05-31 11:45:48 +0800593 );
594 }
Nik Dewallyabac0e52024-08-02 13:42:27 +0100595 | SET POLICY policy_set_args policy_valid{
Karl Zhang3de5ab12021-05-31 11:45:48 +0800596 IVM(cout << "Set policy command: \"" << yytext << "\"" << endl;;)
597 templateLin = new set_policy_template_line (rsrc);
598 interpret_template_line (
599 templateLin, rsrc, set_data, random_asset,
600 assign_data_var_specified, expect, policy_info,
601 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
602 nesting_level == 0 /* create call unless inside {} */,
603 nesting_level == 0 /* similarly, create asset unless inside {} */,
Nik Dewallyabac0e52024-08-02 13:42:27 +0100604 yes_fill_in_template, 0,
605 true,
606 policy_must_be_valid
Karl Zhang3de5ab12021-05-31 11:45:48 +0800607 );
608 }
609 ;
610
611read_command:
612 READ SST sst_read_args {
613 IVM(cout << "Read SST command: \"" << yytext << "\"" << endl;;)
614 templateLin = new read_sst_template_line (rsrc);
615 interpret_template_line (
616 templateLin, rsrc, set_data, random_asset,
617 assign_data_var_specified, expect, policy_info,
618 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
619 nesting_level == 0 /* create call unless inside {} */,
620 dont_create_asset /* if no such asset exists, fail the call */,
621 yes_fill_in_template, 0
622 );
623 }
624 | READ KEY key_read_args {
625 IVM(cout << "Read key command: \"" << yytext << "\"" << endl;;)
626 templateLin = new read_key_template_line (rsrc);
627 interpret_template_line (
628 templateLin, rsrc, set_data, random_asset,
629 assign_data_var_specified, expect, policy_info,
630 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
631 nesting_level == 0 /* create call unless inside {} */,
632 dont_create_asset /* if no such asset exists, fail the call */,
633 yes_fill_in_template, 0
634 );
635 }
636 | READ POLICY policy_read_args {
637 IVM(cout << "Read policy command: \"" << yytext << "\"" << endl;;)
638 templateLin = new read_policy_template_line (rsrc);
639 interpret_template_line (
640 templateLin, rsrc, set_data, random_asset,
641 assign_data_var_specified, expect, policy_info,
642 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
643 nesting_level == 0 /* create call unless inside {} */,
644 dont_create_asset /* if no such asset exists, fail the call */,
645 yes_fill_in_template, 0
646 );
647 }
648 ;
649
650remove_command:
651 REMOVE SST sst_remove_args {
652 IVM(cout << "Remove SST command: \"" << yytext << "\"" << endl;;)
653 templateLin = new remove_sst_template_line (rsrc);
654 interpret_template_line (
655 templateLin, rsrc, set_data, random_asset,
656 assign_data_var_specified, expect, policy_info,
657 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
658 nesting_level == 0 /* create call unless inside {} */,
659 dont_create_asset /* don't create an asset being deleted */,
660 yes_fill_in_template, 0
661 );
662 }
663 | REMOVE KEY key_remove_args {
664 IVM(cout << "Remove key command: \"" << yytext << "\"" << endl;;)
665 templateLin = new remove_key_template_line (rsrc);
666 templateLin->asset_info.set_name (asset_name); // set in key_asset_name, below
667 interpret_template_line (
668 templateLin, rsrc, set_data, random_asset,
669 assign_data_var_specified, expect, policy_info,
670 print_data, hash_data, asset_name, assign_data_var, parsed_asset,
671 nesting_level == 0 /* create call unless inside {} */,
672 dont_create_asset /* don't create an asset being deleted */,
673 yes_fill_in_template, 0
674 );
675 }
676 ;
677
678secure_command: SECURE HASH NEQ ASSET_IDENTIFIER_LIST {
679 /* TODO: This needs to allow not only SST assets, but mix and match with others
680 (keys especially) as well. */
681 IVM(cout << "Secure hash command: \"" << yytext << "\"" << endl;)
682 templateLin = new security_hash_template_line (rsrc);
683 templateLin->asset_info.set_name (asset_name);
684 templateLin->assign_data_var_specified = assign_data_var_specified;
685 templateLin->assign_data_var.assign (assign_data_var);
686 templateLin->expect = expect;
687 templateLin->print_data = print_data;
688 templateLin->hash_data = hash_data;
689 templateLin->random_asset = random_asset;
690 /* Hash checks are different from the rest in that there's a single
691 "call" -- not a PSA call though -- for all of the assets cited in the
692 template line. In *other* cases, create a single call for *each*
693 asset cited by the template line, but not in this case. */
694 for (auto as_name : parsed_asset.asset_name_vector) {
695 /* Also copy into template line object's local vector: */
696 templateLin->asset_info.asset_name_vector.push_back (as_name);
697 }
698 /* Don't need to locate the assets, so no searches required. */
699 templateLin->expect.data_var = var_name;
700 templateLin->setup_call (set_data, set_data.random_data, yes_fill_in_template,
701 nesting_level == 0, templateLin, rsrc );
702 parsed_asset.asset_name_vector.clear();
703
704
705 }
706 ;
707
708done_command: DONE {
709 if (nesting_level != 0) {
710 cerr << "\n\"done\" only available at outer-most { } nesting level."
711 << endl;
712 exit (702);
713 } else {
714 YYACCEPT;
715 }
716 }
717 ;
718
719literal_or_random_data:
720 DATA LITERAL {
721 IVM(cout << "Create from literal data: \"" << flush;)
722 set_data.random_data = false;
723 set_data.string_specified = true;
724 set_data.literal_data_not_file = true;
725 literal.erase(0,1); // zap the ""s
726 literal.erase(literal.length()-1,1);
727 literal_data.assign (literal);
728 IVM(cout << yytext << "\"" << endl;)
729 }
730 | DATA STAR { /* TF-Fuzz supplies random data */
731 IVM(cout << "Create from random data" << endl;)
732 set_data.randomize();
733 literal.assign (set_data.get()); /* just in case something uses literal */
734 set_data.random_data = true;
735 set_data.string_specified = false;
736 }
737 ;
738
739 /* Root-command parameters: */
740sst_set_base_args:
741 sst_asset_name literal_or_random_data
742 | sst_asset_name {
743 IVM(cout << "SST-create from random data (no 'data *')" << endl;)
744 set_data.randomize();
745 literal.assign (set_data.get()); /* just in case something uses literal */
746 }
747 | sst_asset_name VAR IDENTIFIER { /* set from variable */
748 IVM(cout << "SST-set set from variable: \"" << flush;)
749 assign_data_var.assign (identifier);
750 assign_data_var_specified = true;
751 expect.data_specified = false;
752 expect.data_var_specified = false;
753 IVM(cout << yytext << "\"" << endl;)
754 }
755 | sst_asset_name DFNAME sst_asset_set_file_path {
756 set_data.literal_data_not_file = set_data.random_data = false;
757 IVM(cout << "SST-create from file: " << yytext << "\"" << endl;)
758 /* TODO: Need to decide whether the concept of using files to set SST
759 asset values has meaning, and if so, write code to write code to
760 set data appropriately from the file. */
761 }
762 ;
763
764sst_set_extended_args:
765 %empty /* nothing */
766 | FLAG sst_flags {
767 IVM(cout << "SST creation flags" << endl;)
768 IVM(cout << yytext << "\"" << endl;)
769 }
770 ;
771
772sst_flags:
773 %empty /* nothing */
774 | sst_flag sst_flags {
775 IVM(cout << "SST creation flag" << endl;)
776 IVM(cout << yytext << "\"" << endl;)
777 }
778 ;
779
780sst_flag: none | write_once | no_rp | no_conf;
781
782none : NONE {
783 set_data.flags_string = "PSA_STORAGE_FLAG_NONE";
784 /* TODO: grab from boilerplate */
785 IVM(cout << "SST no storage flag: " << yytext << "\"" << endl;)
786 }
787 ;
788
789write_once : WRITE_ONCE {
790 set_data.flags_string = "PSA_STORAGE_FLAG_WRITE_ONCE";
791 /* TODO: grab from boilerplate */
792 IVM(cout << "SST write-once flag: " << yytext << "\"" << endl;)
793 }
794 ;
795
796no_rp : NO_RP {
797 set_data.flags_string = "PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION";
798 /* TODO: grab from boilerplate */
799 IVM(cout << "SST no-replay-protection flag: "
800 << yytext << "\"" << endl;)
801 }
802 ;
803
804no_conf : NO_CONF {
805 set_data.flags_string = "PSA_STORAGE_FLAG_NO_CONFIDENTIALITY";
806 /* TODO: grab from boilerplate */
807 IVM(cout << "SST no-confidentiality flag: " << yytext
808 << "\"" << endl;)
809 }
810 ;
811
812sst_offset_spec:
813 NUMBER_TOK {
814 IVM(cout << "SST-data offset: \"" << flush;)
815 set_data.data_offset = atol(yytext);
816 IVM(cout << yytext << "\"" << endl;)
817 }
818 ;
819
820
821sst_read_args:
822 sst_asset_name read_args sst_read_extended_args {
823 IVM(cout << "SST-read arguments: " << yytext << "\"" << endl;)
824 }
825 ;
826
827read_args:
828 VAR IDENTIFIER { /* dump to variable */
829 IVM(cout << "Read dump to variable: \"" << flush;)
830 assign_data_var.assign (identifier);
831 assign_data_var_specified = true;
832 expect.data_specified = false;
833 expect.data_var_specified = false;
834 IVM(cout << yytext << "\"" << endl;)
835 }
836 | CHECK read_args_var_name { /* check against variable */
837 IVM(cout << "Read check against variable: \""
838 << yytext << "\"" << endl;)
839 set_data.set (literal);
840 assign_data_var_specified = false;
841 expect.data_specified = false;
842 expect.data_var_specified = true;
843 expect.data_var = identifier;
844 }
845 | CHECK LITERAL { /* check against literal */
846 IVM(cout << "Read check against literal: " << flush;)
847 expect.data.assign (literal);
848 expect.data.erase(0,1); // zap the ""s
849 expect.data.erase(expect.data.length()-1,1);
850 assign_data_var_specified = false; /* don't read variable */
851 expect.data_specified = true; /* check against literal data */
852 expect.data_var_specified = false; /* don't check against variable */
853 IVM(cout << yytext << endl;)
854 }
855 | PRINT { /* print out content in test log */
856 IVM(cout << "Read log to test log: \"" << flush;)
857 /* TODO: set_data content probably doesn't need to be set here;
858 constructor probably sets it fine. */
859 set_data.random_data = false;
860 set_data.literal_data_not_file = true;
861 assign_data_var_specified = false;
862 expect.data_specified = false;
863 expect.data_var_specified = false;
864 print_data = true;
865 IVM(cout << yytext << "\"" << endl;)
866 }
867 | HASH { /* hash the data and save for later comparison */
868 IVM(cout << "Read hash for future data-leak detection: \"" << flush;)
869 /* TODO: set_data content probably doesn't need to be set here;
870 constructor probably sets it fine. */
871 set_data.random_data = false;
872 set_data.literal_data_not_file = true;
873 assign_data_var_specified = false;
874 expect.data_specified = false;
875 expect.data_var_specified = false;
876 hash_data = true;
877 rsrc->include_hashing_code = true;
878 IVM(cout << yytext << "\"" << endl;)
879 }
880 | DFNAME sst_asset_dump_file_path { /* dump to file */
881 IVM(cout << "Read dump to file: \""
882 << yytext << "\"" << endl;)
883 set_data.literal_data_not_file = set_data.random_data = false;
884 }
885 ;
886
887sst_read_extended_args:
888 %empty /* nothing */
889 | OFFSET sst_offset_spec {
890 IVM(cout << "SST data offset" << endl;)
891 set_data.data_offset = atol(yytext);
892 IVM(cout << yytext << "\"" << endl;)
893 }
894 ;
895
896sst_remove_args:
897 sst_asset_name | random_picked_asset {
898 IVM(cout << "SST-remove arguments: \""
899 << yytext << "\"" << endl;)
900 }
901 ;
902
903asset_designator:
904 NAME ASSET_IDENTIFIER_LIST {
905 IVM(cout << "Asset identifier list: \"" << flush;)
906 random_name = false;
907 asset_name.assign (identifier); /* TODO: Not sure this ultimately has any effect... */
908 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
909 parsed_asset.id_n_not_name = false;
910 IVM(cout << yytext << "\"" << endl;)
911 }
912 | NAME STAR {
913 IVM(cout << "Asset random identifier: \"" << flush;)
914 random_name = true;
915 rand_data_length = 4 + (rand() % 5);
916 gib.word (false, gib_buff, gib_buff + rand_data_length - 1);
917 aid.assign (gib_buff);
918 parsed_asset.asset_name_vector.push_back (aid);
919 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
920 parsed_asset.id_n_not_name = false;
921 IVM(cout << yytext << "\"" << endl;)
922 }
923 ;
924single_existing_asset:
925 IDENTIFIER {
926 IVM(cout << "Single existing asset by name: \"" << flush;)
927 random_name = false;
928 policy_info.asset_3_name.assign (identifier);
929 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
930 parsed_asset.id_n_not_name = false;
931 IVM(cout << yytext << "\"" << endl;)
932 }
933 | random_picked_asset
934 ;
935
936random_picked_asset:
937 STAR ACTIVE {
938 IVM(cout << "Asset random active: \"" << flush;)
939 random_asset = psa_asset_usage::active;
940 parsed_asset.id_n_not_name = false;
941 IVM(cout << yytext << "\"" << endl;)
942 }
943 | STAR DELETED {
944 IVM(cout << "Asset random deleted: \"" << flush;)
945 random_asset = psa_asset_usage::deleted;
946 parsed_asset.id_n_not_name = false;
947 IVM(cout << yytext << "\"" << endl;)
948 }
949 ;
950
951sst_asset_name:
952 asset_designator
953 | UID ASSET_NUMBER_LIST {
954 IVM(cout << "SST-asset UID list: \"" << flush;)
955 random_name = false;
956 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
957 parsed_asset.id_n_not_name = true;
958 parsed_asset.id_n_specified = true;
959 IVM(cout << yytext << "\"" << endl;)
960 }
961 | UID STAR {
962 IVM(cout << "SST-asset random UID: \"" << flush;)
963 parsed_asset.id_n_not_name = true;
964 random_name = false;
965 nid = 100 + (rand() % 10000);
966 parsed_asset.asset_id_n_vector.push_back (nid);
967 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
968 IVM(cout << yytext << "\"" << endl;)
969 }
970 ;
971
972sst_asset_set_file_path:
973 FILE_PATH {
974 IVM(cout << "SST-asset-create file path: \"" << flush;)
975 IVM(cout << yytext << "\"" << endl;)
976 }
977 ;
978
979read_args_var_name:
980 IDENTIFIER {
981 IVM(cout << "Read-arguments variable name: \"" << flush;)
982 var_name = yytext;
983 IVM(cout << yytext << "\"" << endl;)
984 }
985 ;
986
987sst_asset_dump_file_path:
988 FILE_PATH {
989 IVM(cout << "SST-asset dump-file path: \"" << flush;)
990 set_data.file_path = yytext;
991 IVM(cout << yytext << "\"" << endl;)
992 }
993 ;
994
995key_size:
996 NUMBER_TOK {
997 IVM(cout << "Key size: \"" << flush;)
998 policy_info.n_bits = atol(yytext);
999 IVM(cout << yytext << "\"" << endl;)
1000 }
1001 ;
1002
1003policy_usage_list: ATTR policy_usage policy_usages; /* at least one usage */
1004
1005policy_usages:
1006 %empty /* nothing */
1007 | policy_usage policy_usages {
1008 IVM(cout << "Key-policy usages at line number " << dec << yylineno
1009 << "." << endl;)
1010 }
1011 ;
1012
1013export : EXPORT {
1014 policy_info.exportable = true;
1015 IVM(cout << "Exportable key true: " << yytext << "\"" << endl;)
1016 }
1017 ;
1018
1019noexport : NOEXPORT {
Nik Dewallyabac0e52024-08-02 13:42:27 +01001020 policy_info.no_exportable = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001021 IVM(cout << "Non-exportable key: " << yytext << "\"" << endl;)
1022 }
1023 ;
1024
1025copy : COPY {
1026 policy_info.copyable = true;
1027 IVM(cout << "Copyable key true: " << yytext << "\"" << endl;)
1028 }
1029 ;
1030
1031nocopy : NOCOPY {
Nik Dewallyabac0e52024-08-02 13:42:27 +01001032 policy_info.no_copyable = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001033 IVM(cout << "Non-copyable key: " << yytext << "\"" << endl;)
1034 }
1035 ;
1036
1037encrypt : ENCRYPT {
1038 policy_info.can_encrypt = true;
1039 IVM(cout << "Encryption key true: " << yytext << "\"" << endl;)
1040 }
1041 ;
1042
1043noencrypt : NOENCRYPT {
Nik Dewallyabac0e52024-08-02 13:42:27 +01001044 policy_info.no_can_encrypt = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001045 IVM(cout << "Non-encryption key: " << yytext << "\"" << endl;)
1046 }
1047 ;
1048
1049decrypt : DECRYPT {
1050 policy_info.can_decrypt = true;
1051 IVM(cout << "Decryption key true: " << yytext << "\"" << endl;)
1052 }
1053 ;
1054
1055nodecrypt : NODECRYPT {
Nik Dewallyabac0e52024-08-02 13:42:27 +01001056 policy_info.no_can_decrypt = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001057 IVM(cout << "Non-decryption key: " << yytext << "\"" << endl;)
1058 }
1059 ;
1060
1061sign : SIGN {
1062 policy_info.can_sign = true;
1063 IVM(cout << "Signing key true: " << yytext << "\"" << endl;)
1064 }
1065 ;
1066
1067nosign : NOSIGN {
Nik Dewallyabac0e52024-08-02 13:42:27 +01001068 policy_info.no_can_sign = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001069 IVM(cout << "Non-signing key: " << yytext << "\"" << endl;)
1070 }
1071 ;
1072
1073verify : VERIFY {
1074 policy_info.can_verify = true;
1075 IVM(cout << "Verify key true: " << yytext << "\"" << endl;)
1076 }
1077 ;
1078
1079noverify : NOVERIFY {
Nik Dewallyabac0e52024-08-02 13:42:27 +01001080 policy_info.no_can_verify = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001081 IVM(cout << "Non-verify key: " << yytext << "\"" << endl;)
1082 }
1083 ;
1084
1085derive : DERIVE {
1086 policy_info.derivable = true;
1087 IVM(cout << "Derivable key true: " << yytext << "\"" << endl;)
1088 }
1089 ;
1090
1091noderive : NODERIVE {
Nik Dewallyabac0e52024-08-02 13:42:27 +01001092 policy_info.no_derivable = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001093 IVM(cout << "Non-derivable key: " << yytext << "\"" << endl;)
1094 }
1095 ;
1096
1097persistent : PERSISTENT {
1098 policy_info.persistent = true;
1099 IVM(cout << "Persistent key: " << yytext << "\"" << endl;)
1100 }
1101 ;
1102
1103volatle : VOLATILE {
Nik Dewallyabac0e52024-08-02 13:42:27 +01001104 policy_info.no_persistent = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001105 IVM(cout << "Volatile key: " << yytext << "\"" << endl;)
1106 }
1107 ;
1108
1109policy_usage:
1110 export | copy | encrypt | decrypt | sign | verify | derive
1111 | noexport | nocopy | noencrypt | nodecrypt | nosign | noverify
1112 | noderive | persistent | volatle | key_size {
1113 IVM(cout << "Policy usage: " << yytext << "\"" << endl;)
1114 }
1115 ;
1116
1117policy_type:
1118 TYPE IDENTIFIER {
1119 // Change type identifier, e.g., from "raw_data" to PSA_KEY_TYPE_RAW_DATA:
1120 identifier = formalize (identifier, "PSA_KEY_TYPE_");
1121 policy_info.key_type = identifier;
1122 IVM(cout << "Policy type: \""
1123 << policy_info.key_type << "\"" << endl;)
1124 }
1125
1126policy_algorithm:
1127 ALG IDENTIFIER {
1128 // Change type identifier, e.g., from "sha_256" to PSA_ALG_SHA_256:
1129 identifier = formalize (identifier, "PSA_ALG_");
1130 policy_info.key_algorithm = identifier;
1131 IVM(cout << "Policy algorithm: \""
1132 << policy_info.key_algorithm << "\"" << endl;)
1133 }
1134
Nik Dewally5200f6e2024-08-15 14:08:50 +01001135policy_size:
1136 SIZE NUMBER_TOK {
1137 IVM(cout << "Policy-Size: \"" << flush;)
1138 int num = atol(yytext);
1139 policy_info.n_bits = num;
1140 IVM(cout << yytext << "\"" << endl;)
1141 }
Nik Dewallyed341b72024-08-20 17:02:30 +01001142
1143 | SIZE STAR{
1144 IVM(cout << "Policy-Size: random \"" << flush;)
1145 int num = atol(yytext);
1146 policy_info.n_bits = -1;
1147 IVM(cout << yytext << "\"" << endl;)
1148 }
Karl Zhang3de5ab12021-05-31 11:45:48 +08001149policy_specs:
1150 %empty /* nothing */
1151 | policy_spec policy_specs {
1152 IVM(cout << "Key-policy specs at line number " << dec << yylineno
1153 << "." << endl;)
1154 }
1155 ;
1156
Nik Dewally5200f6e2024-08-15 14:08:50 +01001157policy_spec: policy_usage_list | policy_type | policy_algorithm | policy_size;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001158
1159policy_asset_spec:
1160 %empty /* nothing */
1161 | NAME ASSET_IDENTIFIER_LIST {
1162 IVM(cout << "policy-asset identifier list: \"" << flush;)
1163 random_name = false;
Nik Dewallyabac0e52024-08-02 13:42:27 +01001164 asset_name = identifier; /* TODO: Not sure this ultimately has any effect... */
Karl Zhang3de5ab12021-05-31 11:45:48 +08001165 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
1166 parsed_asset.id_n_not_name = false;
1167 IVM(cout << yytext << "\"" << endl;)
1168 }
1169 | NAME STAR {
1170 IVM(cout << "policy-asset random identifier: \"" << flush;)
1171 random_name = true;
1172 rand_data_length = 2 + (rand() % 10);
1173 gib.word (false, gib_buff, gib_buff + rand_data_length - 1);
1174 aid.assign (gib_buff);
1175 parsed_asset.asset_name_vector.push_back (aid);
1176 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
1177 parsed_asset.id_n_not_name = false;
1178 IVM(cout << yytext << "\"" << endl;)
1179 }
1180 ;
1181
1182policy_asset_name:
1183 NAME IDENTIFIER {
1184 IVM(cout << "policy-asset identifier list: \"" << flush;)
1185 random_name = false;
Nik Dewallyed341b72024-08-20 17:02:30 +01001186 policy_info.generate_get_policy_from_key_call = false;
Nik Dewallyabac0e52024-08-02 13:42:27 +01001187 asset_name = identifier; /* TODO: Not sure this ultimately has any effect... */
Karl Zhang3de5ab12021-05-31 11:45:48 +08001188 parsed_asset.asset_name_vector.push_back (identifier);
1189 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
1190 parsed_asset.id_n_not_name = false;
1191 IVM(cout << yytext << "\"" << endl;)
1192 }
1193 | STAR ACTIVE {
1194 IVM(cout << "policy-asset random active: \"" << flush;)
Nik Dewallyed341b72024-08-20 17:02:30 +01001195 policy_info.generate_get_policy_from_key_call = false;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001196 random_asset = psa_asset_usage::active;
1197 parsed_asset.id_n_not_name = false;
1198 IVM(cout << yytext << "\"" << endl;)
1199 }
1200 | STAR DELETED {
1201 IVM(cout << "policy-asset random deleted: \"" << flush;)
Nik Dewallyed341b72024-08-20 17:02:30 +01001202 policy_info.generate_get_policy_from_key_call = false;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001203 random_asset = psa_asset_usage::deleted;
1204 parsed_asset.id_n_not_name = false;
1205 IVM(cout << yytext << "\"" << endl;)
1206 }
1207 | KEY IDENTIFIER {
1208 IVM(cout << "policy-asset specified by key: \"" << flush;)
Nik Dewallyed341b72024-08-20 17:02:30 +01001209 policy_info.generate_get_policy_from_key_call = true;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001210 random_name = false;
1211 asset_name.assign (identifier); /* ask this key what it's policy is */
1212 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
1213 parsed_asset.id_n_not_name = false;
1214 IVM(cout << yytext << "\"" << endl;)
1215 }
1216 ;
1217
1218policy_set_args:
1219 policy_asset_spec policy_specs {
1220 IVM(cout << "Policy-create arguments: \"" << yytext << "\"" << endl;)
1221 }
1222 ;
1223
Nik Dewallyabac0e52024-08-02 13:42:27 +01001224policy_valid:
1225 %empty /* nothing */ {
1226 policy_must_be_valid = false;
1227 }
1228 | VALID /* policy must be valid */ {
1229 IVM(cout << "Policy-create must be valid" << endl;)
1230 policy_must_be_valid = true;
1231
1232 }
Karl Zhang3de5ab12021-05-31 11:45:48 +08001233policy_read_args:
1234 policy_asset_name read_args {
1235 IVM(cout << "Policy-read arguments: " << yytext << "\"" << endl;)
1236 }
1237 ;
1238
1239key_set_sources:
1240 %empty /* nothing */
1241 | key_set_source key_set_sources {
1242 IVM(cout << "Key-set sources at Line number "
1243 << yytext << "\"" << endl;)
1244 }
1245 ;
1246
1247key_set_source:
1248 literal_or_random_data {
1249 IVM(cout << "Key-set sources, literal or random data: "
1250 << yytext << "\"" << endl;)
1251 }
1252 | POLICY IDENTIFIER {
1253 IVM(cout << "Key-set sources, explicitly-specified policy name: "
1254 << flush;)
Nik Dewallyed341b72024-08-20 17:02:30 +01001255 policy_info.get_policy_info_from = identifier;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001256 policy_info.asset_2_name = identifier; /* policy */
1257 /* Make note that key data (key material) was not specified: */
1258 IVM(cout << yytext << "\"" << endl;)
1259 }
1260 ;
1261
1262key_data_or_not:
1263 %empty /* nothing */
1264 | literal_or_random_data {
1265 IVM(cout << "Key data, literal or random data: "
1266 << yytext << "\"" << endl;)
1267 }
1268 ;
1269
1270key_set_args:
1271 asset_designator key_set_sources {
1272 IVM(cout << "Key-create from data, policy, or nothing (default): \""
1273 << yytext << "\"" << endl;)
1274 policy_info.copy_key = false;
1275 policy_info.implicit_policy = false;
1276 }
1277 | asset_designator FROM single_existing_asset POLICY IDENTIFIER {
1278 IVM(cout << "Key-copy from other key: \"" << flush;)
1279 policy_info.asset_2_name = identifier; /* policy */
1280 policy_info.copy_key = true;
1281 policy_info.implicit_policy = false;
1282 IVM(cout << yytext << "\"" << endl;)
1283 }
1284 | asset_designator key_data_or_not WITH policy_specs {
1285 IVM(cout << "Key-create directly specifying policy attributes (implicit policy): \""
1286 << yytext << "\"" << endl;)
1287 policy_info.copy_key = false;
1288 policy_info.implicit_policy = true;
1289 cerr << "\nError: Defining keys with implicit policies is not yet implemented."
1290 << endl;
1291 exit (772);
1292 }
1293 ;
1294
1295key_remove_args:
1296 asset_designator {
1297 IVM(cout << "Key-remove arguments: \""
1298 << yytext << "\"" << endl;)
1299 }
1300 ;
1301
1302key_read_args:
1303 asset_designator read_args {
1304 IVM(cout << "Key dump: \"" << yytext << "\"" << endl;)
1305 }
1306 ;
1307
1308/* Code structuring: */
1309block:
1310 SHUFFLE block_content {
1311 IVM(cout << "Shuffled block: \"" << flush;)
1312 if (nesting_level > 1) {
1313 cerr << "\nError: Sorry, currently only one level of { } "
1314 << "nesting is allowed." << endl;
1315 exit (500);
1316 }
1317 shuffle_not_pick = true;
1318 low_nmbr_lines = high_nmbr_lines = 0; /* not used, but... */
1319 IVM(cout << yytext << "\"" << endl;)
1320 }
1321 | exact_sel_count OF block_content {
1322 IVM(cout << "Fixed number of lines from block: \"" << flush;)
1323 shuffle_not_pick = false;
1324 /* low_nmbr_lines and high_nmbr_lines are set below. */
1325 IVM(cout << yytext << "\"" << endl;)
1326 }
1327 | low_sel_count TO high_sel_count OF block_content {
1328 IVM(cout << "Range number of lines from block: \"" << flush;)
1329 if (nesting_level > 1) {
1330 cerr << "\nError: Sorry, currently only one level of { } "
1331 << "nesting is allowed." << endl;
1332 exit (502);
1333 }
1334 shuffle_not_pick = false;
1335 /* low_nmbr_lines and high_nmbr_lines are set below. */
1336 IVM(cout << yytext << "\"" << endl;)
1337 }
1338 ;
1339
1340block_content:
1341 open_brace lines close_brace {
1342 IVM(cout << "Block content: \"" << yytext << "\"" << endl;)
1343 }
1344 | line {
1345 IVM(cout << "Single-line would-be-block content: \"" << flush;)
1346 IVM(cout << yytext << "\"" << endl;)
1347 }
1348 ;
1349
1350open_brace:
1351 OPEN_BRACE {
1352 IVM(cout << "Open brace: \"" << flush;)
1353 template_block_vector.clear(); // clean slate of template lines
1354 nesting_level = 1;
1355 IVM(cout << yytext << "\"" << endl;)
1356 }
1357 ;
1358
1359close_brace:
1360 CLOSE_BRACE {
1361 IVM(cout << "Close brace: " << flush;)
1362 IVM(cout << yytext << "\"" << endl;)
1363 }
1364 ;
1365
1366 /* Low-level structures: */
1367
1368 /* Please see comment before ASSET_IDENTIFIER_LIST, below. */
1369ASSET_NUMBER_LIST:
1370 ASSET_NUMBER ASSET_NUMBERS; /* at least one number */
1371
1372ASSET_NUMBERS:
1373 %empty /* nothing */
1374 | ASSET_NUMBER ASSET_NUMBERS;
1375
1376ASSET_NUMBER:
1377 NUMBER_TOK {
Nik Dewally5200f6e2024-08-15 14:08:50 +01001378 IVM(cout << "Policy Size: \"" << flush;)
1379 int size = atol(yytext);
1380 policy_info.n_bits = size;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001381 IVM(cout << yytext << "\"" << endl;)
1382 }
1383 ;
1384
1385 /* ASSET_IDENTIFIER are used specifically for lists of assets within a singletemplate
1386 line. That, as opposed to list of identifers in general. The difference is the
1387 need to queue ASSET_IDENTIFIERS up into parsed_asset.asset_name_vector, and have to
1388 do so here before they "vanish." */
1389ASSET_IDENTIFIER_LIST:
1390 ASSET_IDENTIFIER ASSET_IDENTIFIERS; /* (at least one) */
1391
1392ASSET_IDENTIFIERS:
1393 %empty /* nothing */
1394 | ASSET_IDENTIFIER ASSET_IDENTIFIERS;
1395
1396ASSET_IDENTIFIER:
1397 IDENTIFIER_TOK {
1398 IVM(cout << "ASSET_IDENTIFIER: \"" << flush;)
1399 aid = identifier = yytext;
1400 parsed_asset.asset_name_vector.push_back (aid);
1401 IVM(cout << yytext << "\"" << endl;)
1402 }
1403 ;
1404
1405IDENTIFIER:
1406 IDENTIFIER_TOK {
1407 IVM(cout << "IDENTIFIER: \"" << flush;)
1408 identifier = yytext;
1409 IVM(cout << yytext << "\"" << endl;)
1410 }
1411 ;
1412
1413FILE_PATH:
1414 FILE_PATH_TOK {
1415 IVM(cout << "FILE_PATH: \"" << flush;)
1416 set_data.file_path = yytext;
1417 IVM(cout << yytext << "\"" << endl;)
1418 }
1419 ;
1420
1421 /* These are related to randomized blocks of template lines: */
1422
1423exact_sel_count:
1424 NUMBER {
1425 IVM(cout << "Exact number of random template lines: \"" << flush;)
1426 low_nmbr_lines = high_nmbr_lines = exact_nmbr_lines = number;
1427 ++nesting_level;
1428 IVM(cout << number << "\"" << endl;)
1429 }
1430 ;
1431
1432low_sel_count:
1433 NUMBER {
1434 IVM(cout << "Least number of random template lines: \"" << flush;)
1435 low_nmbr_lines = number;
1436 IVM(cout << number << "\"" << endl;)
1437 }
1438 ;
1439
1440high_sel_count:
1441 NUMBER {
1442 IVM(cout << "Most number of random template lines: \"" << flush;)
1443 high_nmbr_lines = number;
1444 ++nesting_level;
1445 IVM(cout << number << "\"" << endl;)
1446 }
1447 ;
1448
1449
1450 /* These are general-case numbers, literals and such: */
1451
1452NUMBER: NUMBER_TOK {
1453 IVM(cout << "NUMBER: \"" << flush;)
1454 number = atol(yytext);
1455 IVM(cout << yytext << "\"" << endl;)
1456 }
1457 ;
1458
1459LITERAL:
1460 LITERAL_TOK {
1461 IVM(cout << "LITERAL string: " << flush;)
1462 literal = yytext;
1463 literal_is_string = true;
1464 IVM(cout << yytext << endl;)
1465 }
1466 | HEX_LIST {
1467 IVM(cout << "LITERAL hex-value list: " << flush;)
1468 literal = yytext;
1469 literal_is_string = false;
1470 IVM(cout << yytext << endl;)
1471 }
1472 ;
1473
1474
1475%%