Deeptrust for PCI security architecture  SPEC98T17 rev E
Specification of Deeptrust, the Security Architecture for Cortex-M.
uVisor API

Data Structures

struct  UvisorBoxAclItem
 

Macros

#define UVISOR_BOX_CONFIG(box_nameconst UvBoxAclItem module_acl_listuint32_t module_stack_size, struct __your_context, verif_key_id)
 Secure box configuration. More...
 
#define UVISOR_BOX_NAMESPACE(static const char const namespace)
 Specify the namespace for a box. C/C++ pre-processor macro (pseudo-function) More...
 
#define UVISOR_SET_MODE(uvisor_mode)
 Set mode for the uVisor [temporary]. More...
 
#define UVISOR_SET_MODE_ACL(uvisor_mode, const UvBoxAcl main_box_acl_list)
 Set mode for the uVisor and provide background ACLs for the main box. More...
 

List of types

typedef uint32_t UvisorBoxAcl
 

List of functions

int check_acl (uint32_t *p_acl, uint32_t keyindex)
 Hook called by uVisor during loading of secure boxes. More...
 
int rpc_fncall_waitfor (const TFN_Ptr fn_ptr_array[], size_t fn_count, int *box_id_caller, uint32_t timeout_ms)
 Handle incoming RPC, setting the parameter box_id_caller to the caller box ID. More...
 
int uvisor_box_id_self (void)
 Get the ID of the current box. More...
 
int uvisor_box_namespace (int box_id, char *box_namespace, size_t length)
 Copy the namespace of the specified box to the provided buffer. More...
 
int uvisor_box_signingkey (int box_id, int *keyindex)
 Get the signing key ID of the specified box, hence its box privilege. More...
 
void vIRQ_ClearPendingIRQ (uint32_t irqn)
 Clear pending status of IRQn. More...
 
void vIRQ_DisableIRQ (uint32_t irqn)
 Disable IRQn for the currently active box. More...
 
void vIRQ_EnableIRQ (uint32_t irqn)
 Enable IRQn for the currently active box. More...
 
int vIRQ_GetLevel (void)
 Get level of currently active IRQn, if any. More...
 
uint32_t vIRQ_GetPendingIRQ (uint32_t irqn)
 Get pending status of IRQn. More...
 
uint32_t vIRQ_GetPriority (uint32_t irqn)
 Get priority level of IRQn. More...
 
uint32_t vIRQ_GetVector (uint32_t irqn)
 Get the ISR registered for IRQn. More...
 
void vIRQ_SetPendingIRQ (uint32_t irqn)
 Set pending status of IRQn. More...
 
void vIRQ_SetPriority (uint32_t irqn, uint32_t priority)
 Set priority level of IRQn. More...
 
void vIRQ_SetVector (uint32_t irqn, uint32_t vector)
 Register an ISR to the currently active box. More...
 

Detailed Description

The payment application is to be developed by the payment terminal vendor. It dialogs with the 2 secure boxes through remote procedure calls (RPC). The API is described below in this document. Shortly this API allows to display trusted messages on the display, perform EMV-level 1 compliant APDU exchanges with the smart card, perform PIN processing, capture Mag Stripe… basically everything required to perform an EMV Level-2 compliant payment.

Here you can find detailed documentation for:

  1. Configuration macros, to configure a secure box and protect data and peripherals.
  2. Box Identity, to retrieve a box-specific ID or the namespace of the current or calling box.
    • A box identity identifies a security domain uniquely and globally.
    • The box identity API can be used to determine the source box of an inbound secure gateway call. This can be useful for implementing complex authorization logic between mutually distrustful security domains.
    • uVisor provides the ability to retrieve the box ID of the current box (uvisor_box_id_self), or of the box that called the current box through an RPC gateway via the box_id_caller parameter of rpc_fncall_waitfor.
    • The box ID number is not constant and can change between reboots. But, the box ID number can be used as a token to retrieve a constant string identifier, known as the box namespace.
    • A box namespace is a static, box-specific string, that can help identify which box has which ID at run-time. In the future, the box namespace will be guaranteed to be globally unique.
    • A full example using this API is available at mbed-os-example-uvisor-number-store.
  3. Low level APIs, to access uVisor functions that are not available to unprivileged code (interrupts, restricted system registers).
  4. Type definitions.
  5. Error codes.
Error reason Error code
PERMISSION_DENIED 1
SANITY_CHECK_FAILED 2
NOT_IMPLEMENTED 3
NOT_ALLOWED 4
FAULT_MEMMANAGE 5
FAULT_BUS 6
FAULT_USAGE 7
FAULT_HARD 8
FAULT_DEBUG 9

Data Structure Documentation

§ UvisorBoxAclItem

struct UvisorBoxAclItem

{ item_description }

Data Fields
UvisorBoxAcl acl
uint32_t length
const volatile void * start

Macro Definition Documentation

§ UVISOR_BOX_CONFIG

#define UVISOR_BOX_CONFIG (   box_nameconst UvBoxAclItem module_acl_listuint32_tmodule_stack_size,
  struct __your_context,
  verif_key_id 
)

Secure box configuration.

C/C++ pre-processor macro (pseudo-function)

Parameters
box_nameSecure box name
module_acl_listList of ACLs for the module
module_stack_sizeRequired stack size for the secure box
__your_context[optional] Type definition of the struct hosting the box context data
verif_key_idthe Id of the key to use for the verification of the signature of the box #define KEYINDEX_FW 0x4E5F739aUL #define KEYINDEX_TRUSTEDAPP 0xebf78ac4UL #define KEYINDEX_OTHERAPP 0x9cfb3459UL

Example: ``` #include "uvisor-lib/uvisor-lib.h"

// Required stack size #define BOX_STACK_SIZE 0x100

// Define the box context. typedef struct { uint8_t secret[SECRET_SIZE]; bool initialized; State_t current_state } BoxContext;

// Create the ACL list for the module. static const UvBoxAclItem g_box_acl[] = { {PORTB, sizeof(*PORTB), UVISOR_TACLDEF_PERIPH}, {RTC, sizeof(*RTC), * UVISOR_TACLDEF_PERIPH}, {LPTMR0, sizeof(*LPTMR0), UVISOR_TACLDEF_PERIPH}, };

// Configure the secure box compartment. UVISOR_BOX_NAMESPACE("com.example.my-box-name"); UVISOR_BOX_CONFIG(my_box_name, g_box_acl, BOX_STACK_SIZE, BoxContext);

```

§ UVISOR_BOX_NAMESPACE

#define UVISOR_BOX_NAMESPACE (   static const char constnamespace)

Specify the namespace for a box. C/C++ pre-processor macro (pseudo-function)

Parameters
namespaceThe namespace of the box

The namespace of the box must be a null-terminated string no longer than MAX_BOX_NAMESPACE_LENGTH (including the terminating null).

The namespace must also be stored in public flash. uVisor will verify that the namespace is null-terminated and stored in public flash at boot-time, and will halt if the namespace fails this verification. For now, use a reverse domain name for the box namespace.

If you don't have a reverse domain name, use a GUID string identifier. We currently don't verify that the namespace is globally unique, but we will perform this validation in the future.

Use of this configuration macro before UVISOR_BOX_CONFIG is required. If you do not wish to give your box a namespace, specify NULL as the namespace to create an anonymous box.

Example:

#include "uvisor-lib/uvisor-lib.h"
// Configure the secure box.
UVISOR_BOX_NAMESPACE("com.example.my-box-name");
UVISOR_BOX_CONFIG(my_box_name, UVISOR_BOX_STACK_SIZE);

§ UVISOR_SET_MODE

#define UVISOR_SET_MODE (   uvisor_mode)

Set mode for the uVisor [temporary].

C/C++ pre-processor macro (object declaration)

Parameters
[in]uvisor_modeThe uvisor mode:
  • UVISOR_DISABLED = disabled [default]
  • UVISOR_PERMISSIVE = permissive [currently n.a.]
  • UVISOR_ENABLED = enabled

Example:

#include "uvisor-lib/uvisor-lib.h"
// Set the uVisor mode.
UVISOR_SET_MODE(UVISOR_ENABLED);

Note:

  1. This macro is only needed temporarily (uVisor disabled by default) and will be removed in the future.
  2. This macro must be used only once in the top level yotta executable.

§ UVISOR_SET_MODE_ACL

#define UVISOR_SET_MODE_ACL (   uvisor_mode,
  const UvBoxAclmain_box_acl_list 
)

Set mode for the uVisor and provide background ACLs for the main box.

C/C++ pre-processor macro (object declaration)

Parameters
[in]uvisor_modeThe uvisor mode
  • UVISOR_DISABLED< = disabled [default]
  • UVISOR_PERMISSIVE = permissive [currently n.a.]
  • UVISOR_ENABLED = enabled
main_box_acl_listList of ACLs for the main box (background ACLs)

Example:

#include "uvisor-lib/uvisor-lib.h"
// Create background ACLs for the main box.
static const UvBoxAclItem g_background_acl[] = {
{UART0, sizeof(*UART0), UVISOR_TACL_PERIPHERAL},
{UART1, sizeof(*UART1), UVISOR_TACL_PERIPHERAL},
{PIT, sizeof(*PIT), UVISOR_TACL_PERIPHERAL},
};
// Set the uVisor mode.
UVISOR_SET_MODE_ACL(UVISOR_ENABLED, g_background_acl);

Note:

  1. This macro is only needed temporarily (uVisor disabled by default) and will be removed in the future.
  2. This macro must be used only once in the top level yotta executable.

Typedef Documentation

§ UvisorBoxAcl

typedef uint32_t UvisorBoxAcl

{ item_description }

Function Documentation

§ check_acl()

int check_acl ( uint32_t *  p_acl,
uint32_t  keyindex 
)

Hook called by uVisor during loading of secure boxes.

It is the responsibility of the platform developer to implement this function to restrict ACLs based on the box privilege of the box being loaded.

Parameters
p_aclPointer to the ACL of the box being loaded
[in]keyindexThe key used to verify the box (hence its box privilege)
Returns
0 if the ACL conforms to the ACL policy

§ rpc_fncall_waitfor()

int rpc_fncall_waitfor ( const TFN_Ptr  fn_ptr_array[],
size_t  fn_count,
int *  box_id_caller,
uint32_t  timeout_ms 
)

Handle incoming RPC, setting the parameter box_id_caller to the caller box ID.

When deciding which memory to provide for rpc_fncall_waitfor to use when writing box_id_caller, strongly prefer thread local storage when multiple threads in a box can handle incoming RPC.

Parameters
[in]fn_ptr_arrayThe function pointer array
[in]fn_countThe function count
box_id_callerThe box identifier of the caller. After a call, box_id_caller is set to the box ID of the calling box (the source box of the RPC). This is set before the RPC is dispatched, so that the RPC target function can read from this location to determine the calling box ID. This parameter is optional.
[in]timeout_msThe timeout milliseconds
Returns
{ description_of_the_return_value }

§ uvisor_box_id_self()

int uvisor_box_id_self ( void  )

Get the ID of the current box.

Returns
The ID of the current box

§ uvisor_box_namespace()

int uvisor_box_namespace ( int  box_id,
char *  box_namespace,
size_t  length 
)

Copy the namespace of the specified box to the provided buffer.

Parameters
[in]box_idThe ID of the box you want to retrieve the namespace of
box_namespaceThe buffer where the box namespace will be copied to
[in]lengthThe length in bytes of the provided box_namespace buffer
Returns
Return how many bytes were copied into box_namespace.
Return values
UVISOR_ERROR_INVALID_BOX_IDif the provided box ID is invalid.
UVISOR_ERROR_BUFFER_TOO_SMALLif the provided box_namespace is too small to hold MAX_BOX_NAMESPACE_LENGTH bytes.
UVISOR_ERROR_BOX_NAMESPACE_ANONYMOUSif the box is anonymous.

§ uvisor_box_signingkey()

int uvisor_box_signingkey ( int  box_id,
int *  keyindex 
)

Get the signing key ID of the specified box, hence its box privilege.

Parameters
[in]box_idThe ID of the box you want to retrieve the signing key ID.
keyindexLocation where to receive the requested key ID
Returns
Status of execution
Return values
UVISOR_ERROR_INVALID_BOX_IDif the provided box ID is invalid.

§ vIRQ_ClearPendingIRQ()

void vIRQ_ClearPendingIRQ ( uint32_t  irqn)

Clear pending status of IRQn.

Parameters
[in]irqnIRQn

§ vIRQ_DisableIRQ()

void vIRQ_DisableIRQ ( uint32_t  irqn)

Disable IRQn for the currently active box.

Parameters
[in]irqnIRQn

§ vIRQ_EnableIRQ()

void vIRQ_EnableIRQ ( uint32_t  irqn)

Enable IRQn for the currently active box.

Parameters
[in]irqnIRQn

§ vIRQ_GetLevel()

int vIRQ_GetLevel ( void  )

Get level of currently active IRQn, if any.

Returns
The priority level of the currently active IRQn, if any; -1 otherwise

§ vIRQ_GetPendingIRQ()

uint32_t vIRQ_GetPendingIRQ ( uint32_t  irqn)

Get pending status of IRQn.

Parameters
[in]irqnIRQn
Returns
pending status of IRQn

§ vIRQ_GetPriority()

uint32_t vIRQ_GetPriority ( uint32_t  irqn)

Get priority level of IRQn.

Parameters
[in]irqnIRQn
Returns
The priority level of IRQn, if available; 0 otherwise

§ vIRQ_GetVector()

uint32_t vIRQ_GetVector ( uint32_t  irqn)

Get the ISR registered for IRQn.

Parameters
[in]irqnIRQn
Returns
The ISR registered for IRQn, if present; 0 otherwise

§ vIRQ_SetPendingIRQ()

void vIRQ_SetPendingIRQ ( uint32_t  irqn)

Set pending status of IRQn.

Parameters
[in]irqnIRQn

§ vIRQ_SetPriority()

void vIRQ_SetPriority ( uint32_t  irqn,
uint32_t  priority 
)

Set priority level of IRQn.

Parameters
[in]irqnIRQn
[in]priorityPriority level (minimum: 1)

§ vIRQ_SetVector()

void vIRQ_SetVector ( uint32_t  irqn,
uint32_t  vector 
)

Register an ISR to the currently active box.

Parameters
[in]irqnIRQn
[in]vectorInterrupt handler; if 0 the IRQn slot is de-registered for the current box