blob: 9a497c03bb0466084ed452947d8e37add22175d8 [file] [log] [blame]
/*
* Copyright (c) 2019-2024, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef PSA_CALL_HPP
#define PSA_CALL_HPP
#include <string>
#include <iosfwd>
#include <vector>
#include "data_blocks.hpp"
class psa_asset;
enum class psa_asset_usage;
class tf_fuzz_info;
using namespace std;
class psa_call
{
public:
string call_description; // description of the call, just for tracing
expect_info exp_data; // everything about expected results
set_data_info set_data; // everything about setting PSA-asset-data values
asset_name_id_info asset_info; // everything about the asset(s) for this line
key_policy_info policy; // (specific to crypto, but have to put this here)
string asset_2_name; // if there's a 2nd asset, then this is its name
string asset_3_name; // if there's a 3rd asset, then this is its name
psa_asset_usage random_asset;
/* if asked to use some random asset from active or deleted, this says
which. psa_asset_usage::all if not using this feature. */
bool assign_data_var_specified; // asset data to/from named variable
string assign_data_var; // name of variable to dump (assign) data into
// Expected-result info:
bool print_data; // true to print asset data to test log
bool hash_data; // true to hash data for later comparison
string id_string; // not all PSA calls involve an ID, but a diverse set do
long call_ser_no; // unique serial# for this psa_call (see note in tf_fuzz.hpp)
tf_fuzz_info *test_state; // the big blob with pointers to everything going on
string barrier;
/* "barrier" is used for template-line operations that resolve a series of
PSA calls. In particular, with respect to the fact that TF-Fuzz strives
to randomize these multiple calls where possible, meaning interspersing
them among other, earlier commands. However, for example, calls to set
the aspects of a policy can't be pushed too far back, such as in among
calls setting that same policy for a previous operation! "barrier" is
either "", in which case this call does not care whether you place calls
before it, or it contains the name of an asset that, calls related to
which must be placed *after* this call. */
string target_barrier;
/* asset to tell the psa_call objects to set and search barrier to when
re-ordering PSA calls. For key policies, this is not necessarily the
nominal asset of that call. For a policy call, it is that policy asset,
so that later re-settings of the same policy don't pollute the current
setting of that policy. However, for key sets and reads, it is not the
key asset, but its policy. */
virtual vector<psa_asset*>::iterator resolve_asset (bool create_asset_bool,
psa_asset_usage where) = 0;
/// Updates asset based on call information.
///
/// WARNING: previously, this used to be the place to do call simulation
/// logic such as modifiying assets. Code that does simulation or in any
/// way mutates the state should now instead go in simulate().
virtual bool copy_call_to_asset (void) = 0;
/// Updates call based on asset information.
virtual bool copy_asset_to_call (void) = 0;
/// Simulates the effect of the call, returning true if a change has been
/// made.
///
/// This is called before asset simulatio takes place. For more details on
/// control flow, see simulate_calls().
///
/// If no return code for the call was given in the template, this should be
/// updated here. However, if a return code is already present, it should
/// never be overwritten.
virtual bool simulate (void);
// Update policy information in the call based on the policy
// asset specified in policy.get_policy_from_policy. If this is unset,
// the existing values are used as-is.
//
// This enables the simulation time setting of the policy.
//
// See `key_policy_info.get_policy_from_policy`.
void copy_policy_to_call(void);
// TODO: move simulation and error modelling code code into simulate().
// once this is done, remove default impl so that simulate is mandatory for
// calls.
// ..
// In particular, need to move code from:
// ..
// - copy_call_to_asset
// ..
// - fill_in_command
// ..
// - fill_in_result_code
virtual void fill_in_prep_code (void) = 0;
/// WARNING: Previously, this used to also contain expected value
/// modelling code (alongside fill_in_command), and some error code
/// modelling may still be left over here. New expected value modelling code
/// should be put in simulate() where possible. Doing this gives a much
/// nicer split between the simulation step (simulate()), and the code
/// generation step (which this method is part of).
virtual void fill_in_command (void) = 0;
void write_out_prep_code (ofstream &test_file);
void write_out_command (ofstream &test_file);
void write_out_check_code (ofstream &test_file);
psa_call (tf_fuzz_info *test_state, long &asset_ser_no,
asset_search how_asset_found); // (constructor)
~psa_call (void);
protected:
string prep_code; // declarations and such prior to all of the calls
string call_code; // for the call itself
string check_code; // for the code to check success of the call
static long unique_id_counter; // counts off unique IDs for assets
/// Fill in expected result checks.
///
/// WARNING: Previously, this used to also contain expected value
/// modelling code (alongside fill_in_command), and some error code
/// modelling may still be left over here. New expected value modelling code
/// should be put in simulate() where possible. Doing this gives a much
/// nicer split between the simulation step (simulate()), and the code
/// generation step (which this method is part of).
virtual void fill_in_result_code (void) = 0;
private:
// Data members:
// Methods:
};
class sst_call : public psa_call
{
public:
// Data members: // (low value in hiding these behind setters and getters)
// Methods:
vector<psa_asset*>::iterator resolve_asset (bool create_asset_bool,
psa_asset_usage where);
sst_call (tf_fuzz_info *test_state, long &asset_ser_no,
asset_search how_asset_found); // (constructor)
~sst_call (void);
protected:
// Data members:
void fill_in_result_code (void);
private:
// Data members:
// Methods:
};
class crypto_call : public psa_call
{
public:
// Data members: // (low value in hiding these behind setters and getters)
// Methods:
bool copy_asset_to_call (void) override;
virtual bool simulate() override;
crypto_call (tf_fuzz_info *test_state, long &asset_ser_no,
asset_search how_asset_found); // (constructor)
~crypto_call (void);
protected:
// Data members:
// Methods:
void fill_in_result_code (void) override;
// for now, the method-overide buck stops here, but that'll probably change
bool simulate_ret_code(void);
private:
};
class security_call : public psa_call
/* Strictly speaking, these don't really correspond to PSA calls, so it's a little
iffy to subclass them from psa_call. However, the calling patterns work out
right. */
{
public:
// Data members: // (low value in hiding these behind setters and getters)
// Methods:
vector<psa_asset*>::iterator resolve_asset (bool create_asset_bool,
psa_asset_usage where);
security_call (tf_fuzz_info *test_state, long &asset_ser_no,
asset_search how_asset_found); // (constructor)
~security_call (void);
protected:
// Data members:
// Methods:
void fill_in_result_code (void);
// Should never be invoked, since security calls generate no PSA calls.
private:
// Data members:
// Methods:
};
#endif // PSA_CALL_HPP