Secure Request Framework

| Secure Request Framework

Macros | Functions
Secure Request Pool Library

## General Description

Secure Request Pool Library provides an implementation of secure request pool mtb_srf_pool_t, which is composed of multiple secure request objects mtb_srf_request_ns_t.

Secure request objects need to be accessible by both the secure and non-secure world. In practice, this means that they should be allocated out of the "shared memory" region rather than e.g. off the stack. This, in turn, means that any RAM which is allocated for secure request pool description struct mtb_srf_pool_t is statically allocated for the lifetime of the program. Therefore, it would be inefficient for every secure request client to allocate its own secure request object. There needs to be a means for sharing. This need is satisfied by a secure request pool, which allows multiple secure request clients to share a small number of pre-allocated secure request pool description struct. A secure request pool is specific to a particular non-secure processing environment. I.e. in a system where both the CM33_NS and the CM55 are making secure requests, there would be two secure request pools, one for the CM33_NS and one for the CM55. Usage of this mechanism is optional. If needed to satisfy some special case, a secure request client can allocate their own custom secure request object and use that instead.

Features:

- Secure request pool initialization can be performed.
- Secure reqest object can be allocated or freed.

# Prerequisites

There are three parameters which define a secure request pool:

- Maximum input argument count MTB_SRF_MAX_ARG_IN_SIZE: This will default to 5.
- Maximum output argument count MTB_SRF_MAX_ARG_OUT_SIZE: This will default to 1 because most functions return only one value, but is left configurable for flexibility and future proofing.
- Number of requests allocated MTB_SRF_POOL_SIZE: This determines the number of requests that can be pending in parallel (if the system is configured to permit non-secure threads or interrupts to pre-empt secure processing). This will default to 3 in RTOS-aware usage, and 1 otherwise. A default secure request pool is created during initialization of the secure request context, and uses the values described in the previous section. These values can be overridden by defining the corresponding macro in mtb_srf_config.h

Pool initialization can be performed explicitly via the mtb_srf_pool_init function.

A secure request pool consolidates three user-provided memory allocations:

- Array of pre-allocated secure request description structs
- Array that can be used to store input arguments
- Array that can be used to store output arguments.

The input and output argument arrays are shared equally between all requests in the pool. For example, if a secure reqest pool contains three entries and args_in_length is 12, then each secure request would support up to 4 input arguments. The benefit is that the pool initialization process is simpler because there are fewer allocations required

A default pool is defined in the BSP and initialized as part of the non-secure application initialization. This default pool is expected to be sufficient for the majority of uses cases, so users should generally not need to do any manual allocation or management of pools.

Note
  the default secure request pool setup is only performed when we are not running in the secure world. This is because the secure request pools are the means by which the non-secure world submits requests to the secure world. There would be no reason for the secure world to submit a request to itself.

Secure request object allocation is performed via the mtb_srf_pool_allocate function. Secure request object free is performed via the mtb_srf_pool_free function.

# Code Snippets

Init sequence for secure request pool

#define MY_INPUT_ARRAY_SIZE (6UL) // Means 6 bytes
#define MY_OUTPUT_ARRAY_SIZE (2UL) // Means 2 bytes
#define MY_NUM_REQ_IN_POOL (6UL)
CY_SECTION_SHAREDMEM mtb_srf_pool_t pool;
CY_SECTION_SHAREDMEM static uint32_t pool_memory[(MTB_SRF_POOL_ENTRY_SIZE(MTB_SRF_MAX_ARG_IN_SIZE,
MTB_SRF_MAX_ARG_OUT_SIZE)
* MTB_SRF_POOL_SIZE) / sizeof(uint32_t)];
//--------------------------------------------------------------------------------------------------
// snippet_mtb_srf_pool_init_api
//--------------------------------------------------------------------------------------------------
cy_rslt_t snippet_mtb_srf_pool_init_api(void)
{
cy_rslt_t result = CY_RSLT_SUCCESS;
// Other initialization steps
result = mtb_srf_pool_init(&pool,
&pool_memory[0],
MY_NUM_REQ_IN_POOL,
MY_INPUT_ARRAY_SIZE,
MY_OUTPUT_ARRAY_SIZE);
(void)result;
return result;
}
mtb_srf_pool_init
cy_rslt_t mtb_srf_pool_init(mtb_srf_pool_t *pool, uint32_t *allocated_mem, size_t num_entries, size_t input_len_per_entry, size_t output_len_per_entry)
Initializes an secure request pool instance.
Definition: mtb_srf_pool.c:73
MTB_SRF_POOL_ENTRY_SIZE
#define MTB_SRF_POOL_ENTRY_SIZE(input_values_length, output_values_length)
A tool to calculate how much memory to provide for a pool.
Definition: mtb_srf_pool_init.h:71

Allocation/Free operation

cy_rslt_t snippet_mtb_srf_pool_allocate_free_api(void)
{
cy_rslt_t result = CY_RSLT_SUCCESS;
// Assuming an already initialized request pool
mtb_srf_invec_ns_t* inVec = NULL;
mtb_srf_outvec_ns_t* outVec = NULL;
uint8_t inVec_cnt = 1;
uint8_t outVec_cnt = 1;
// If it is in ISR, timeout_us should be zero.
uint32_t timeout_us = 2000;
result = mtb_srf_pool_allocate(&cy_pdl_srf_default_pool, &inVec, &outVec, timeout_us);
if (result != CY_RSLT_SUCCESS)
{
return result;
}
// Populate the mtb_srf_request_ns_t structure, then submit it
// See snippet_mtb_srf_submit_request_api for example on population
result = mtb_srf_request_submit(inVec, inVec_cnt, outVec, outVec_cnt);
// Free to allow other assets to reuse the memory
result = mtb_srf_pool_free(&cy_pdl_srf_default_pool, inVec, outVec);
return result;
}
mtb_srf_pool_allocate
cy_rslt_t mtb_srf_pool_allocate(mtb_srf_pool_t *pool, mtb_srf_invec_ns_t **inVec, mtb_srf_outvec_ns_t **outVec, uint32_t timeout_us)
Allocate secure request object within an secure request pool.
Definition: mtb_srf_pool.c:104
mtb_srf_pool_free
cy_rslt_t mtb_srf_pool_free(mtb_srf_pool_t *pool, const mtb_srf_invec_ns_t *inVec, const mtb_srf_outvec_ns_t *outVec)
Free secure request object within an secure request pool.
Definition: mtb_srf_pool.c:177
mtb_srf_invec_ns_t
An input vector - a section of memory to be used along with the length.
Definition: mtb_srf_iovec.h:72
mtb_srf_outvec_ns_t
An output vector - a section of memory to be used along with the length.
Definition: mtb_srf_iovec.h:79
mtb_srf_request_submit
cy_rslt_t mtb_srf_request_submit(mtb_srf_invec_ns_t *inVec_ns, uint8_t inVec_cnt_ns, mtb_srf_outvec_ns_t *outVec_ns, uint8_t outVec_cnt_ns)
Submit a request from the non-secure side to the secure.

## Macros
#define | MTB_SRF_ROUND_UP(N, S) ((((N) + (S) - 1UL) / (S)) * (S))
| Round up.
#define | MTB_SRF_POOL_ALIGNMENT (4UL)
| Address alignment value of pool in bytes.

## Functions
cy_rslt_t | mtb_srf_pool_allocate (mtb_srf_pool_t *pool, mtb_srf_invec_ns_t **inVec, mtb_srf_outvec_ns_t **outVec, uint32_t timeout_us)
| Allocate secure request object within an secure request pool. More...
cy_rslt_t | mtb_srf_pool_free (mtb_srf_pool_t *pool, const mtb_srf_invec_ns_t *inVec, const mtb_srf_outvec_ns_t *outVec)
| Free secure request object within an secure request pool. More...
cy_rslt_t | mtb_srf_pool_get_entry_len (mtb_srf_pool_t *pool, size_t *input_len_per_entry, size_t *output_len_per_entry)
| Get the input and output length per entry configuration of a pool that were set at initalization. More...

## Function Documentation

## ◆ mtb_srf_pool_allocate()

cy_rslt_t mtb_srf_pool_allocate | ( | mtb_srf_pool_t * | pool,
|  | mtb_srf_invec_ns_t ** | inVec,
|  | mtb_srf_outvec_ns_t ** | outVec,
|  | uint32_t | timeout_us
| ) |  |

Allocate secure request object within an secure request pool.

Parameters

  [in,out] | pool | The pool object that was populated by mtb_srf_pool_init
  [in,out] | inVec | Pointer to an array of input vectors for the pool to allocate
  [in,out] | outVec | Pointer to an array of output vectors for the pool to allocate
  [in] | timeout_us | Timeout to wait in microsecond. Set to 0 to perform no wait.

Note
  The timeout_us must always be 0 if allocation is invoked from an interrupt context.

Returns
  the status of allocate request

Allocate secure request object within an secure request pool.

## ◆ mtb_srf_pool_free()

cy_rslt_t mtb_srf_pool_free | ( | mtb_srf_pool_t * | pool,
|  | const mtb_srf_invec_ns_t * | inVec,
|  | const mtb_srf_outvec_ns_t * | outVec
| ) |  |

Free secure request object within an secure request pool.

Parameters

  [in,out] | pool | The pool object that was populated by mtb_srf_pool_init
  [in] | inVec | Pointer to an input vectors for the pool to free
  [in] | outVec | Pointer to an output vectors for the pool to free. This must belong to the same request as inVec

Returns
  the status of free request

Free secure request object within an secure request pool.

## ◆ mtb_srf_pool_get_entry_len()

cy_rslt_t mtb_srf_pool_get_entry_len | ( | mtb_srf_pool_t * | pool,
|  | size_t * | input_len_per_entry,
|  | size_t * | output_len_per_entry
| ) |  |

Get the input and output length per entry configuration of a pool that were set at initalization.

Parameters

  [in,out] | pool | The pool object that was populated by mtb_srf_pool_init
  [in,out] | input_len_per_entry | Value to store the input length per entry
  [in,out] | output_len_per_entry | Value to store the output length per entry

Returns
  the status of the initialization