Struct fortanix_sgx_abi::Usercalls[][src]

pub struct Usercalls;
Expand description

The list of all usercalls.

This is not a real structure, it’s just a convenient way to group functions with rustdoc.

The usercall number is passed in the first register. Up to 4 arguments may be passed in the remaining registers. Unspecified arguments and return values must be 0. Userspace must check the arguments and the enclave must check the return value.

The usercall number may be one of the predefined numbers associated with one of the usercalls defined below, or, if bit USERCALL_USER_DEFINED is set, an otherwise arbitrary number with an application-defined meaning.

Raw pointers must always point to user memory. When receiving raw pointers from userspace, the enclave must verify that the entire pointed-to memory space is outside the enclave memory range. It must then copy all data in user memory to enclave memory before operating on it.

Implementations

Asynchronous usercalls

Due to rustdoc, this section may appear at the top of the Usercalls documentation. You might want to read the other sections first and then come back to this one.

See also the async module documentation.

Request FIFO queues for asynchronous usercalls. usercall_queue and return_queue must point to valid user memory with the correct size and alignment for their types. On return, userspace will have filled these structures with information about the queues. A single set of queues will be allocated per enclave. Once this usercall has returned succesfully, calling this usercall again is equivalent to calling exit(true).

May fail if the platform does not support asynchronous usercalls.

The enclave must ensure that the data pointed to in the fields of FifoDescriptor is outside the enclave.

Streams

The enclave must not assume anything about data read or written using these calls. Data written may be piped directly to /dev/null by userspace, or it may be published in the local newspaper. Similarly, data read may be arbitrarily deleted, inserted, or changed. The enclave must use additional security primitives such as sealing or TLS to obtain stronger guarantees.

When a stream is read from by multiple threads simultaneously, the read calls may be serialized in any order. This means the data returned by a read call appeared that way in the stream, and every single byte in the stream will be read and be read only once. However, the order in which all stream data is returned is not defined. The same applies when simultaneously submitting multiple read calls for the same stream asynchronously. This all applies similarly to writing to a stream.

To make sure to be able to re-assemble the stream, the enclave can take one of the following approaches:

  1. Submit all read calls to a single stream on a single thread.
  2. Serializing read calls by synchronizing access to a single stream.

In addition, the enclave should use cryptographic integrity protection of the stream data to ensure the stream data has not been tampered with.

Read up to len bytes from stream fd.

buf must point to a buffer in userspace with a size of at least len. On a succesful return, the number of bytes written is returned. The enclave must check that the returned length is no more than len. If len is 0, this call should block until the stream is ready for reading. If len is 0 or end of stream is reached, 0 may be returned.

The enclave may mix calls to read and read_alloc.

Read some data from stream fd, letting the callee choose the amount.

buf must point to a ByteBuffer in userspace, and buf.data must contain null. On success, userspace will allocate memory for the read data and populate ByteBuffer appropriately. The enclave must handle and deallocate the buffer according to the ByteBuffer documentation.

Since every read operation using this usercall requires two usercalls, it is recommended to only call this usercall asynchronously.

The enclave may mix calls to read and read_alloc.

Write up to len bytes to stream fd.

buf must point to a buffer in userspace with a size of at least len. On a succesful return, the number of bytes written is returned. The enclave must check that the returned length is no more than len. If len is 0, this call should block until the stream is ready for writing. If len is 0 or the stream is closed, 0 may be returned.

Flush stream fd, ensuring that all intermediately buffered contents reach their destination.

Close stream fd.

Once the stream is closed, no further data may be read or written. Userspace may reuse the fd in the future for a different stream.

Networking

In keeping with the design goals for this specification, the networking/socket interface doesn’t use sockaddr types and doesn’t have a separate API for name resolution. Userspace can’t be trusted to do name resolution correctly, and even if it did, userspace can’t be trusted to actually connect streams to the correct address specified by the enclave. Therefore, addresses specified should merely be treated as a suggestion, and additional measures must be taken by an enclave to verify the stream is connected to the correct peer, e.g. TLS.

The networking API works with strings as addresses. All byte buffers representing network addresses should contain a valid UTF-8 string. The enclave should panic if it is passed an invalid string by userspace. It is suggested that userspace supports at least the following notations:

  • hostname:port-number (e.g. example.com:123)
  • dotted-octet-ipv4-address:port-number (e.g. 192.0.2.1:123)
  • [ipv6-address]:port-number (e.g. [2001:db8::1]:123)

Additionally, other forms may be accepted, for example service names:

  • fully-qualified-service-name (e.g. _example._tcp.example.com)
  • address:service-name (e.g. address:example)

Errors

Networking calls taking an address may return the InvalidInput error if the address could not be interpreted by userspace.

Setup a listening socket.

The socket is bound to the address specified in addr. addr must be a buffer in user memory with a size of at least len.

On success, a file descriptor is returned which may be passed to accept_stream or close.

The enclave may optionally request the local socket address be returned in local_addr. On success, if local_addr is not NULL, userspace will allocate memory for the address and populate ByteBuffer appropriately. The enclave must handle and deallocate the buffer according to the ByteBuffer documentation.

The enclave must not make any security decisions based on the local address received.

Accept a new connection from a listening socket.

fd should be a file descriptor previously returned from bind_stream.

The enclave may optionally request the local or peer socket addresses be returned in local_addr or peer_addr, respectively. On success, if local_addr and/or peer_addr is not NULL, userspace will allocate memory for the address and populate the respective ByteBuffer appropriately.

The enclave must handle and deallocate each buffer according to the ByteBuffer documentation.

The enclave must not make any security decisions based on the local or peer address received.

Create a new stream connection to the specified address.

The enclave may optionally request the local or peer socket addresses be returned in local_addr or peer_addr, respectively. On success, if local_addr and/or peer_addr is not NULL, userspace will allocate memory for the address and populate the respective ByteBuffer appropriately.

The enclave must handle and deallocate each buffer according to the ByteBuffer documentation.

The enclave must not make any security decisions based on the local or peer address received.

Execution control

TCS event queues

Userspace will maintain a queue for each running TCS with events to be delivered. Each event is characterized by a bitset with at least one bit set. Userspace or the enclave (using the send usercall) can put events on this queue. If the enclave isn’t waiting for an event when an event is queued, the event remains on the queue until it delivered to the enclave in a later wait usercall. If an enclave is waiting for an event, and the queue contains an event that is a subset of the waited-for event mask, that event is removed from the queue and execution control is returned to the enclave.

Events not defined in this specification should not be generated.

In executables, this will instruct userspace to enter another TCS in another thread. This TCS should have the thread_entry entrypoint. As documented in thread_entry, the enclave should keep track of how many threads it launched and reconcile this with the number of entries into thread_entry. If no free TCSes are immediately available, this may return an error.

This function will never be succesful in libraries. See the library documentation on how to use threads with libraries.

Signals to userspace that this enclave needs to be destroyed.

The enclave must not rely on userspace to terminate other threads still running. Similarly, the enclave must not trust that it will no longer be entered by userspace, and it must safeguard against that in the entrypoints.

If panic is set to true, the enclave has exited due to a panic condition. If the enclave was running in debug mode, the enclave may have output a debug message according to the calling convention.

Wait for an event to occur, or check if an event is currently pending.

timeout must be WAIT_NO or WAIT_INDEFINITE or a positive value smaller than u64::MAX specifying number of nanoseconds to wait.

If timeout is WAIT_INDEFINITE, this call will block and return once a matching event is queued on this TCS. If timeout is WAIT_NO, this call will return immediately, and the return value will indicate if an event was pending. If it was, it has been dequeued. If not, the WouldBlock error value will be returned. If timeout is a value other than WAIT_NO and WAIT_INDEFINITE, this call will block until either a matching event is queued in which case the return value will indicate the event, or the timeout is reached in which case the TimedOut error value will be returned.

A matching event is one whose bits are equal to or a subset of event_mask. If event_mask is 0, this call will never return due to an event. If timeout is also WAIT_INDEFINITE, this call will simply never return.

Enclaves must not assume that this call only returns in response to valid events generated by the enclave. This call may return for invalid event sets, or before timeout has expired even though no event is pending.

When executed synchronously, this gives userspace an opportunity to schedule something else in a cooperative multitasking environment.

When executed asynchronously, this may trigger an EV_RETURNQ_NOT_EMPTY event on this or other TCSes. It is not recommended to execute this call asynchronously with a timeout value other than WAIT_NO.

Send an event to one or all TCSes.

If tcs is None, send the event event_set to all TCSes of this enclave, otherwise, send it to the TCS specified in tcs.

Error

This will return the InvalidInput error if tcs is set but doesn’t specify a valid TCS address.

This returns the number of nanoseconds since midnight UTC on January 1, 1970. The enclave must not rely on the accuracy of this time for security purposes, such as checking credential expiry or preventing rollback.

Memory

The enclave must not use any memory outside the enclave, except for memory explicitly returned from usercalls. You can obtain arbitrary memory in userspace using alloc.

Request user memory.

Request an allocation in user memory of size size and with alignment align. If succesful, a pointer to this memory will be returned. The enclave must check the pointer is correctly aligned and that the entire range of memory pointed to is outside the enclave.

It is an error to call this function with size equal to 0.

Free user memory.

This must be called to deallocate memory in userspace. The pointer ptr must have previously been returned by a usercall. The size and alignment specified must exactly match what was allocated. This function must be called exactly once for each user memory buffer.

Calling this function with size equal to 0 is a no-op.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.