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