blob: dae9c7d06b3ba6dff41a051a2de7f0c1a0299bf2 [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;
102 create_key_call *creKeyCal = nullptr;
103 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 */
374%token <tokenN> ATTR TYPE ALG /* "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
1135policy_specs:
1136 %empty /* nothing */
1137 | policy_spec policy_specs {
1138 IVM(cout << "Key-policy specs at line number " << dec << yylineno
1139 << "." << endl;)
1140 }
1141 ;
1142
1143policy_spec: policy_usage_list | policy_type | policy_algorithm;
1144
1145policy_asset_spec:
1146 %empty /* nothing */
1147 | NAME ASSET_IDENTIFIER_LIST {
1148 IVM(cout << "policy-asset identifier list: \"" << flush;)
1149 random_name = false;
Nik Dewallyabac0e52024-08-02 13:42:27 +01001150 asset_name = identifier; /* TODO: Not sure this ultimately has any effect... */
Karl Zhang3de5ab12021-05-31 11:45:48 +08001151 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
1152 parsed_asset.id_n_not_name = false;
1153 IVM(cout << yytext << "\"" << endl;)
1154 }
1155 | NAME STAR {
1156 IVM(cout << "policy-asset random identifier: \"" << flush;)
1157 random_name = true;
1158 rand_data_length = 2 + (rand() % 10);
1159 gib.word (false, gib_buff, gib_buff + rand_data_length - 1);
1160 aid.assign (gib_buff);
1161 parsed_asset.asset_name_vector.push_back (aid);
1162 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
1163 parsed_asset.id_n_not_name = false;
1164 IVM(cout << yytext << "\"" << endl;)
1165 }
1166 ;
1167
1168policy_asset_name:
1169 NAME IDENTIFIER {
1170 IVM(cout << "policy-asset identifier list: \"" << flush;)
1171 random_name = false;
1172 policy_info.get_policy_from_key = false;
Nik Dewallyabac0e52024-08-02 13:42:27 +01001173 asset_name = identifier; /* TODO: Not sure this ultimately has any effect... */
Karl Zhang3de5ab12021-05-31 11:45:48 +08001174 parsed_asset.asset_name_vector.push_back (identifier);
1175 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
1176 parsed_asset.id_n_not_name = false;
1177 IVM(cout << yytext << "\"" << endl;)
1178 }
1179 | STAR ACTIVE {
1180 IVM(cout << "policy-asset random active: \"" << flush;)
1181 policy_info.get_policy_from_key = false;
1182 random_asset = psa_asset_usage::active;
1183 parsed_asset.id_n_not_name = false;
1184 IVM(cout << yytext << "\"" << endl;)
1185 }
1186 | STAR DELETED {
1187 IVM(cout << "policy-asset random deleted: \"" << flush;)
1188 policy_info.get_policy_from_key = false;
1189 random_asset = psa_asset_usage::deleted;
1190 parsed_asset.id_n_not_name = false;
1191 IVM(cout << yytext << "\"" << endl;)
1192 }
1193 | KEY IDENTIFIER {
1194 IVM(cout << "policy-asset specified by key: \"" << flush;)
1195 policy_info.get_policy_from_key = true;
1196 random_name = false;
1197 asset_name.assign (identifier); /* ask this key what it's policy is */
1198 random_asset = psa_asset_usage::all; /* don't randomly choose existing asset */
1199 parsed_asset.id_n_not_name = false;
1200 IVM(cout << yytext << "\"" << endl;)
1201 }
1202 ;
1203
1204policy_set_args:
1205 policy_asset_spec policy_specs {
1206 IVM(cout << "Policy-create arguments: \"" << yytext << "\"" << endl;)
1207 }
1208 ;
1209
Nik Dewallyabac0e52024-08-02 13:42:27 +01001210policy_valid:
1211 %empty /* nothing */ {
1212 policy_must_be_valid = false;
1213 }
1214 | VALID /* policy must be valid */ {
1215 IVM(cout << "Policy-create must be valid" << endl;)
1216 policy_must_be_valid = true;
1217
1218 }
Karl Zhang3de5ab12021-05-31 11:45:48 +08001219policy_read_args:
1220 policy_asset_name read_args {
1221 IVM(cout << "Policy-read arguments: " << yytext << "\"" << endl;)
1222 }
1223 ;
1224
1225key_set_sources:
1226 %empty /* nothing */
1227 | key_set_source key_set_sources {
1228 IVM(cout << "Key-set sources at Line number "
1229 << yytext << "\"" << endl;)
1230 }
1231 ;
1232
1233key_set_source:
1234 literal_or_random_data {
1235 IVM(cout << "Key-set sources, literal or random data: "
1236 << yytext << "\"" << endl;)
1237 }
1238 | POLICY IDENTIFIER {
1239 IVM(cout << "Key-set sources, explicitly-specified policy name: "
1240 << flush;)
Nik Dewallyabac0e52024-08-02 13:42:27 +01001241 policy_info.get_policy_from_policy = identifier;
Karl Zhang3de5ab12021-05-31 11:45:48 +08001242 policy_info.asset_2_name = identifier; /* policy */
1243 /* Make note that key data (key material) was not specified: */
1244 IVM(cout << yytext << "\"" << endl;)
1245 }
1246 ;
1247
1248key_data_or_not:
1249 %empty /* nothing */
1250 | literal_or_random_data {
1251 IVM(cout << "Key data, literal or random data: "
1252 << yytext << "\"" << endl;)
1253 }
1254 ;
1255
1256key_set_args:
1257 asset_designator key_set_sources {
1258 IVM(cout << "Key-create from data, policy, or nothing (default): \""
1259 << yytext << "\"" << endl;)
1260 policy_info.copy_key = false;
1261 policy_info.implicit_policy = false;
1262 }
1263 | asset_designator FROM single_existing_asset POLICY IDENTIFIER {
1264 IVM(cout << "Key-copy from other key: \"" << flush;)
1265 policy_info.asset_2_name = identifier; /* policy */
1266 policy_info.copy_key = true;
1267 policy_info.implicit_policy = false;
1268 IVM(cout << yytext << "\"" << endl;)
1269 }
1270 | asset_designator key_data_or_not WITH policy_specs {
1271 IVM(cout << "Key-create directly specifying policy attributes (implicit policy): \""
1272 << yytext << "\"" << endl;)
1273 policy_info.copy_key = false;
1274 policy_info.implicit_policy = true;
1275 cerr << "\nError: Defining keys with implicit policies is not yet implemented."
1276 << endl;
1277 exit (772);
1278 }
1279 ;
1280
1281key_remove_args:
1282 asset_designator {
1283 IVM(cout << "Key-remove arguments: \""
1284 << yytext << "\"" << endl;)
1285 }
1286 ;
1287
1288key_read_args:
1289 asset_designator read_args {
1290 IVM(cout << "Key dump: \"" << yytext << "\"" << endl;)
1291 }
1292 ;
1293
1294/* Code structuring: */
1295block:
1296 SHUFFLE block_content {
1297 IVM(cout << "Shuffled block: \"" << flush;)
1298 if (nesting_level > 1) {
1299 cerr << "\nError: Sorry, currently only one level of { } "
1300 << "nesting is allowed." << endl;
1301 exit (500);
1302 }
1303 shuffle_not_pick = true;
1304 low_nmbr_lines = high_nmbr_lines = 0; /* not used, but... */
1305 IVM(cout << yytext << "\"" << endl;)
1306 }
1307 | exact_sel_count OF block_content {
1308 IVM(cout << "Fixed number of lines from block: \"" << flush;)
1309 shuffle_not_pick = false;
1310 /* low_nmbr_lines and high_nmbr_lines are set below. */
1311 IVM(cout << yytext << "\"" << endl;)
1312 }
1313 | low_sel_count TO high_sel_count OF block_content {
1314 IVM(cout << "Range number of lines from block: \"" << flush;)
1315 if (nesting_level > 1) {
1316 cerr << "\nError: Sorry, currently only one level of { } "
1317 << "nesting is allowed." << endl;
1318 exit (502);
1319 }
1320 shuffle_not_pick = false;
1321 /* low_nmbr_lines and high_nmbr_lines are set below. */
1322 IVM(cout << yytext << "\"" << endl;)
1323 }
1324 ;
1325
1326block_content:
1327 open_brace lines close_brace {
1328 IVM(cout << "Block content: \"" << yytext << "\"" << endl;)
1329 }
1330 | line {
1331 IVM(cout << "Single-line would-be-block content: \"" << flush;)
1332 IVM(cout << yytext << "\"" << endl;)
1333 }
1334 ;
1335
1336open_brace:
1337 OPEN_BRACE {
1338 IVM(cout << "Open brace: \"" << flush;)
1339 template_block_vector.clear(); // clean slate of template lines
1340 nesting_level = 1;
1341 IVM(cout << yytext << "\"" << endl;)
1342 }
1343 ;
1344
1345close_brace:
1346 CLOSE_BRACE {
1347 IVM(cout << "Close brace: " << flush;)
1348 IVM(cout << yytext << "\"" << endl;)
1349 }
1350 ;
1351
1352 /* Low-level structures: */
1353
1354 /* Please see comment before ASSET_IDENTIFIER_LIST, below. */
1355ASSET_NUMBER_LIST:
1356 ASSET_NUMBER ASSET_NUMBERS; /* at least one number */
1357
1358ASSET_NUMBERS:
1359 %empty /* nothing */
1360 | ASSET_NUMBER ASSET_NUMBERS;
1361
1362ASSET_NUMBER:
1363 NUMBER_TOK {
1364 IVM(cout << "ASSET_NUMBER: \"" << flush;)
1365 nid = atol(yytext);
1366 parsed_asset.asset_id_n_vector.push_back (nid);
1367 IVM(cout << yytext << "\"" << endl;)
1368 }
1369 ;
1370
1371 /* ASSET_IDENTIFIER are used specifically for lists of assets within a singletemplate
1372 line. That, as opposed to list of identifers in general. The difference is the
1373 need to queue ASSET_IDENTIFIERS up into parsed_asset.asset_name_vector, and have to
1374 do so here before they "vanish." */
1375ASSET_IDENTIFIER_LIST:
1376 ASSET_IDENTIFIER ASSET_IDENTIFIERS; /* (at least one) */
1377
1378ASSET_IDENTIFIERS:
1379 %empty /* nothing */
1380 | ASSET_IDENTIFIER ASSET_IDENTIFIERS;
1381
1382ASSET_IDENTIFIER:
1383 IDENTIFIER_TOK {
1384 IVM(cout << "ASSET_IDENTIFIER: \"" << flush;)
1385 aid = identifier = yytext;
1386 parsed_asset.asset_name_vector.push_back (aid);
1387 IVM(cout << yytext << "\"" << endl;)
1388 }
1389 ;
1390
1391IDENTIFIER:
1392 IDENTIFIER_TOK {
1393 IVM(cout << "IDENTIFIER: \"" << flush;)
1394 identifier = yytext;
1395 IVM(cout << yytext << "\"" << endl;)
1396 }
1397 ;
1398
1399FILE_PATH:
1400 FILE_PATH_TOK {
1401 IVM(cout << "FILE_PATH: \"" << flush;)
1402 set_data.file_path = yytext;
1403 IVM(cout << yytext << "\"" << endl;)
1404 }
1405 ;
1406
1407 /* These are related to randomized blocks of template lines: */
1408
1409exact_sel_count:
1410 NUMBER {
1411 IVM(cout << "Exact number of random template lines: \"" << flush;)
1412 low_nmbr_lines = high_nmbr_lines = exact_nmbr_lines = number;
1413 ++nesting_level;
1414 IVM(cout << number << "\"" << endl;)
1415 }
1416 ;
1417
1418low_sel_count:
1419 NUMBER {
1420 IVM(cout << "Least number of random template lines: \"" << flush;)
1421 low_nmbr_lines = number;
1422 IVM(cout << number << "\"" << endl;)
1423 }
1424 ;
1425
1426high_sel_count:
1427 NUMBER {
1428 IVM(cout << "Most number of random template lines: \"" << flush;)
1429 high_nmbr_lines = number;
1430 ++nesting_level;
1431 IVM(cout << number << "\"" << endl;)
1432 }
1433 ;
1434
1435
1436 /* These are general-case numbers, literals and such: */
1437
1438NUMBER: NUMBER_TOK {
1439 IVM(cout << "NUMBER: \"" << flush;)
1440 number = atol(yytext);
1441 IVM(cout << yytext << "\"" << endl;)
1442 }
1443 ;
1444
1445LITERAL:
1446 LITERAL_TOK {
1447 IVM(cout << "LITERAL string: " << flush;)
1448 literal = yytext;
1449 literal_is_string = true;
1450 IVM(cout << yytext << endl;)
1451 }
1452 | HEX_LIST {
1453 IVM(cout << "LITERAL hex-value list: " << flush;)
1454 literal = yytext;
1455 literal_is_string = false;
1456 IVM(cout << yytext << endl;)
1457 }
1458 ;
1459
1460
1461%%