mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-12 20:51:21 +00:00
Implement SGX getrandom/getentropy without ocall (#1176)
Implement SGX getrandom with sgx_read_rand and getentropy with `rdseed` instruction instead of ocall to improve the security.
This commit is contained in:
parent
c72501781a
commit
37cc6eac3b
|
@ -28,6 +28,7 @@
|
||||||
#include "sgx_time.h"
|
#include "sgx_time.h"
|
||||||
#include "sgx_socket.h"
|
#include "sgx_socket.h"
|
||||||
#include "sgx_signal.h"
|
#include "sgx_signal.h"
|
||||||
|
#include "sgx_trts.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -116,10 +116,6 @@ int
|
||||||
ocall_getopt(int *p_ret, int argc, char *argv_buf, unsigned int argv_buf_len,
|
ocall_getopt(int *p_ret, int argc, char *argv_buf, unsigned int argv_buf_len,
|
||||||
const char *optstring);
|
const char *optstring);
|
||||||
int
|
int
|
||||||
ocall_getrandom(ssize_t *p_ret, void *buf, size_t buflen, unsigned int flags);
|
|
||||||
int
|
|
||||||
ocall_getentropy(int *p_ret, void *buffer, size_t length);
|
|
||||||
int
|
|
||||||
ocall_sched_yield(int *p_ret);
|
ocall_sched_yield(int *p_ret);
|
||||||
|
|
||||||
/** struct iovec **/
|
/** struct iovec **/
|
||||||
|
@ -891,29 +887,124 @@ sched_yield(void)
|
||||||
ssize_t
|
ssize_t
|
||||||
getrandom(void *buf, size_t buflen, unsigned int flags)
|
getrandom(void *buf, size_t buflen, unsigned int flags)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
sgx_status_t ret;
|
||||||
|
|
||||||
if (ocall_getrandom(&ret, buf, buflen, flags) != SGX_SUCCESS) {
|
if (!buf || buflen > INT32_MAX || flags != 0) {
|
||||||
TRACE_OCALL_FAIL();
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ret == -1)
|
|
||||||
errno = get_errno();
|
ret = sgx_read_rand(buf, buflen);
|
||||||
return ret;
|
if (ret != SGX_SUCCESS) {
|
||||||
|
errno = EFAULT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ssize_t)buflen;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RDRAND_RETRIES 3
|
||||||
|
|
||||||
|
static int
|
||||||
|
rdrand64_step(uint64 *seed)
|
||||||
|
{
|
||||||
|
uint8 ok;
|
||||||
|
__asm__ volatile("rdseed %0; setc %1" : "=r"(*seed), "=qm"(ok));
|
||||||
|
return (int)ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rdrand64_retry(uint64 *rand, uint32 retries)
|
||||||
|
{
|
||||||
|
uint32 count = 0;
|
||||||
|
|
||||||
|
while (count++ <= retries) {
|
||||||
|
if (rdrand64_step(rand)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32
|
||||||
|
rdrand_get_bytes(uint8 *dest, uint32 n)
|
||||||
|
{
|
||||||
|
uint8 *head_start = dest, *tail_start = NULL;
|
||||||
|
uint64 *block_start;
|
||||||
|
uint32 count, ltail, lhead, lblock;
|
||||||
|
uint64 i, temp_rand;
|
||||||
|
|
||||||
|
/* Get the address of the first 64-bit aligned block in the
|
||||||
|
destination buffer. */
|
||||||
|
if (((uintptr_t)head_start & (uintptr_t)7) == 0) {
|
||||||
|
/* already 8-byte aligned */
|
||||||
|
block_start = (uint64 *)head_start;
|
||||||
|
lhead = 0;
|
||||||
|
lblock = n & ~7;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* next 8-byte aligned */
|
||||||
|
block_start = (uint64 *)(((uintptr_t)head_start + 7) & ~(uintptr_t)7);
|
||||||
|
lhead = (uint32)((uintptr_t)block_start - (uintptr_t)head_start);
|
||||||
|
lblock = (n - lhead) & ~7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the number of 64-bit blocks and the remaining number
|
||||||
|
of bytes (the tail) */
|
||||||
|
ltail = n - lblock - lhead;
|
||||||
|
if (ltail > 0) {
|
||||||
|
tail_start = (uint8 *)block_start + lblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the starting, mis-aligned section (the head) */
|
||||||
|
if (lhead > 0) {
|
||||||
|
if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(head_start, &temp_rand, lhead);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the central, aligned blocks */
|
||||||
|
count = lblock / 8;
|
||||||
|
for (i = 0; i < count; i++, block_start++) {
|
||||||
|
if (!rdrand64_retry(block_start, RDRAND_RETRIES)) {
|
||||||
|
return i * 8 + lhead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the tail */
|
||||||
|
if (ltail > 0) {
|
||||||
|
if (!rdrand64_retry(&temp_rand, RDRAND_RETRIES)) {
|
||||||
|
return count * 8 + lhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(tail_start, &temp_rand, ltail);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
getentropy(void *buffer, size_t length)
|
getentropy(void *buffer, size_t length)
|
||||||
{
|
{
|
||||||
int ret;
|
uint32 size;
|
||||||
|
|
||||||
if (ocall_getentropy(&ret, buffer, length) != SGX_SUCCESS) {
|
if (!buffer || length > INT32_MAX) {
|
||||||
TRACE_OCALL_FAIL();
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ret == -1)
|
|
||||||
errno = get_errno();
|
if (length == 0) {
|
||||||
return ret;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = rdrand_get_bytes(buffer, (uint32)length);
|
||||||
|
if (size != length) {
|
||||||
|
errno = EFAULT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -250,6 +250,7 @@ sched_yield(void);
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
getrandom(void *buf, size_t buflen, unsigned int flags);
|
getrandom(void *buf, size_t buflen, unsigned int flags);
|
||||||
|
|
||||||
int
|
int
|
||||||
getentropy(void *buffer, size_t length);
|
getentropy(void *buffer, size_t length);
|
||||||
|
|
||||||
|
|
|
@ -77,9 +77,6 @@ enclave {
|
||||||
[in, size=argv_buf_len]char *argv_buf,
|
[in, size=argv_buf_len]char *argv_buf,
|
||||||
unsigned int argv_buf_len,
|
unsigned int argv_buf_len,
|
||||||
[in, string]const char *optstring);
|
[in, string]const char *optstring);
|
||||||
ssize_t ocall_getrandom([out, size=buflen]void *buf, size_t buflen,
|
|
||||||
unsigned int flags);
|
|
||||||
int ocall_getentropy([out, size=length]void *buffer, size_t length);
|
|
||||||
ssize_t ocall_readv(int fd,
|
ssize_t ocall_readv(int fd,
|
||||||
[in, out, size=buf_size]char *iov_buf,
|
[in, out, size=buf_size]char *iov_buf,
|
||||||
unsigned int buf_size, int iovcnt,
|
unsigned int buf_size, int iovcnt,
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/random.h>
|
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -303,18 +302,6 @@ ocall_getopt(int argc, char *argv_buf, unsigned int argv_buf_len,
|
||||||
return getopt(argc, argv, optstring);
|
return getopt(argc, argv, optstring);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t
|
|
||||||
ocall_getrandom(void *buf, size_t buflen, unsigned int flags)
|
|
||||||
{
|
|
||||||
return getrandom(buf, buflen, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ocall_getentropy(void *buffer, size_t length)
|
|
||||||
{
|
|
||||||
return getentropy(buffer, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ocall_sched_yield()
|
ocall_sched_yield()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user