Skip to content

Latest commit

 

History

History
497 lines (415 loc) · 12.5 KB

API.md

File metadata and controls

497 lines (415 loc) · 12.5 KB

uVisor API documentation

Configuration macros

You can use configuration macros to configure a secure box and protect data and peripherals.

UVISOR_BOX_CONFIG(box_name
                  const UvBoxAclItem *module_acl_list,
                  uint32_t module_stack_size,
                  [struct __your_context])
Description Secure box configuration
Type C/C++ preprocessor macro (pseudo-function)
Parameters
box_name
Secure box name
const UvBoxAclItem *module_acl_list
List of ACLs for the module
uint32_t module_stack_size
Required stack size for the secure box
struct __your_context
[optional] Type definition of the struct hosting the box context data

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_SET_MODE(uvisor_mode);
Description [temporary] Set mode for the uVisor
Type C/C++ pre-processor macro (object declaration)
Parameters
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: This macro is only temporary (uVisor disabled by default) and will be removed in the future.


UVISOR_SET_MODE_ACL(uvisor_mode, const UvBoxAcl *public_box_acl_list);
Description [temporary] Set mode for the uVisor and provide background ACLs for the public box
Type C/C++ pre-processor macro (object declaration)
Parameters
uvisor_mode
UVISOR_DISABLED = disabled [default]
UVISOR_PERMISSIVE = permissive [currently n.a.]
UVISOR_ENABLED = enabled
const UvBoxAclItem *public_box_acl_list
List of ACLs for the public box (background ACLs)

Example:

#include "uvisor-lib/uvisor-lib.h"

/* Create background ACLs for the public 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: This macro is only temporary (uVisor disabled by default) and will be removed in the future.


UVISOR_BOX_NAMESPACE(static const char const namespace[])
Description

Specify the namespace for a box.

  <p>The namespace of the box must be a null-terminated string no longer than <code>MAX_BOX_NAMESPACE_LENGTH</code> (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.</p>

  <p>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.</p>

  <p>You must use this configuration macro before <code>UVISOR_BOX_CONFIG</code>. If you do not wish to give your box a namespace, specify <code>NULL</code> as the namespace to create an anonymous box.</p>
Type C/C++ preprocessor macro (pseudo-function)
Parameters namespace The namespace of the 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);

Box identity

A box identity identifies a security domain uniquely and globally.

You can use the box identity API 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 you can use it 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 runtime. In the future, the box namespace will be globally unique.

A full example using this API is available at mbed-os-example-uvisor-number-store.

int uvisor_box_id_self(void)
Description Get the ID of the current box
Return value The ID of the current box

int rpc_fncall_waitfor(const TFN_Ptr fn_ptr_array[], size_t fn_count, int * box_id_caller, uint32_t timeout_ms)
Description Handle incoming RPC, setting the parameter `box_id_caller` to the caller box ID.
`box_id_caller` value 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.

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


int uvisor_box_namespace(int box_id, char *box_namespace, size_t length)
Description Copy the namespace of the specified box to the provided buffer.
Return value Return how many bytes were copied into box_namespace. Return UVISOR_ERROR_INVALID_BOX_ID if the provided box ID is invalid. Return UVISOR_ERROR_BUFFER_TOO_SMALL if the provided box_namespace is too small to hold MAX_BOX_NAMESPACE_LENGTH bytes. Return UVISOR_ERROR_BOX_NAMESPACE_ANONYMOUS if the box is anonymous.
Parameters int box_id The ID of the box you want to retrieve the namespace of
char *box_namespace The buffer where the box namespace will be copied to
size_t length The length in bytes of the provided box_namespace buffer

Low-level APIs

You can use low-level APIs to access uVisor functions that are not available to unprivileged code (interrupts, restricted system registers). The only permitted low-level operation is interrupt management.

Interrupt management

void vIRQ_SetVector(uint32_t irqn, uint32_t vector)
Description Register an ISR to the currently active box
Parameters
uint32_t irqn
IRQn
uint32_t vector
Interrupt handler; if 0 the IRQn slot is deregistered for the current box

uint32_t vIRQ_GetVector(uint32_t irqn)
Description Get the ISR registered for IRQn
Return value The ISR registered for IRQn, if present; 0 otherwise
Parameters
uint32_t irqn
IRQn

void vIRQ_EnableIRQ(uint32_t irqn)
Description Enable IRQn for the currently active box
Parameters
uint32_t irqn
IRQn

void vIRQ_DisableIRQ(uint32_t irqn)
Description Disable IRQn for the currently active box
Parameters
uint32_t irqn
IRQn

void vIRQ_ClearPendingIRQ(uint32_t irqn)
Description Clear pending status of IRQn
Parameters
uint32_t irqn
IRQn

void vIRQ_SetPendingIRQ(uint32_t irqn)
Description Set pending status of IRQn
Parameters
uint32_t irqn
IRQn

uint32_t vIRQ_GetPendingIRQ(uint32_t irqn)
Description Get pending status of IRQn
Parameters
uint32_t irqn
IRQn

void vIRQ_SetPriority(uint32_t irqn, uint32_t priority)
Description Set priority level of IRQn
Parameters
uint32_t irqn
IRQn
uint32_t priority
Priority level (minimum: 1)

uint32_t vIRQ_GetPriority(uint32_t irqn)
Description Get priority level of IRQn
Return value The priority level of IRQn, if available; 0 otherwise
Parameters
uint32_t irqn
IRQn

int vIRQ_GetLevel(void)
Description Get level of currently active IRQn, if any
Return value The priority level of the currently active IRQn, if any; -1 otherwise

Type definitions

typedef uint32_t UvisroBoxAcl;    /* Permission mask */

typedef struct
{
    const volatile void* start;   /* Start address of the protected area */
    uint32_t length;              /* Size of the protected area */
    UvisorBoxAcl acl;             /* Permission mask for the protected area */
} UvisorBoxAclItem;

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