diff --git a/Makefile b/Makefile index 8f0da189..faaf740b 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ include buildenv.mk -SUB_DIR := utils/tkey_exchange utils/ukey_exchange core dkeycache dkeyserver enroll_app +SUB_DIR := utils/tkey_exchange utils/ukey_exchange core dkeycache dkeyserver dkeyserver/dkeyrotation enroll_app SSL_DIR := third_party/intel-sgx-ssl export DESTDIR = ${OPENSSL_PATH} diff --git a/core/App/ehsm_provider.cpp b/core/App/ehsm_provider.cpp index 7dd2f36d..c0551e59 100644 --- a/core/App/ehsm_provider.cpp +++ b/core/App/ehsm_provider.cpp @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include "enclave_hsm_u.h" #include "ehsm_provider.h" @@ -93,6 +95,48 @@ sgx_ra_context_t g_context = INT_MAX; sgx_enclave_id_t g_enclave_id; +#define UNIX_DOMAIN (std::string(RUNTIME_FOLDER) + "dkeyprovision.sock").c_str() + +bool g_ready_flag = true; + +int server_sock_fd; + +void recv_msg() +{ + int byte_num; + _response_header_t *res_msg = (_response_header_t*)malloc(sizeof(_response_header_t)); + + do + { + uint32_t sgxStatus; + sgx_status_t ret; + + byte_num = recv(server_sock_fd, reinterpret_cast(res_msg), sizeof(_response_header_t), 0); + if (byte_num > 0) + { + if (res_msg->type == MSG_ROTATE_END) + { + ret = enclave_la_message_exchange(g_enclave_id, &sgxStatus); + if (ret != SGX_SUCCESS || sgxStatus != SGX_SUCCESS) + { + log_e("test_message_exchange Ecall failed: ECALL return 0x%x, error code is 0x%x.\n", ret, sgxStatus); + return; + } + log_i("update dk\n"); + + g_ready_flag = true; + log_i("ready flag change to %s\n", g_ready_flag == true ? "true" : "false"); + } + else if (res_msg->type == MSG_ROTATE_START) + { + g_ready_flag = false; + log_i("ready flag change to %s\n", g_ready_flag == true ? "true" : "false"); + } + } + + } while (1); +} + static ehsm_status_t SetupSecureChannel(sgx_enclave_id_t eid) { uint32_t sgxStatus; @@ -117,13 +161,30 @@ static ehsm_status_t SetupSecureChannel(sgx_enclave_id_t eid) log_i("Succeed to exchange secure message...\n"); // close ECDH session - ret = enclave_la_close_session(eid, &sgxStatus); - if (ret != SGX_SUCCESS || sgxStatus != SGX_SUCCESS) + // ret = enclave_la_close_session(eid, &sgxStatus); + // if (ret != SGX_SUCCESS || sgxStatus != SGX_SUCCESS) + // { + // log_e("test_close_session Ecall failed: ECALL return 0x%x, error code is 0x%x.\n", ret, sgxStatus); + // return EH_LA_CLOSE_ERROR; + // } + // log_i("Succeed to close Session...\n"); + + server_sock_fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (server_sock_fd == -1) { - log_e("test_close_session Ecall failed: ECALL return 0x%x, error code is 0x%x.\n", ret, sgxStatus); - return EH_LA_CLOSE_ERROR; + log_e("socket error"); + return EH_FUNCTION_FAILED; } - log_i("Succeed to close Session...\n"); + + struct sockaddr_un server_addr; + server_addr.sun_family = AF_UNIX; + strcpy(server_addr.sun_path, UNIX_DOMAIN); + + if (connect(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) >= 0) + log_w("socket connect ok"); + + std::thread thread(recv_msg); + thread.detach(); return EH_OK; } @@ -209,7 +270,17 @@ uint32_t EHSM_FFI_CALL(const char *reqJson, char *respJson) RetJsonObj retJsonObj; uint32_t action = -1; JsonObj payloadJson; - if(respJson == NULL){ + + if (g_ready_flag == false) + { + retJsonObj.setCode(retJsonObj.CODE_FAILED); + retJsonObj.setMessage("rotating."); + retJsonObj.toChar(respJson); + return EH_GENERAL_ERROR; + } + + if (respJson == NULL) + { retJsonObj.setCode(retJsonObj.CODE_FAILED); retJsonObj.setMessage("Argument bad."); retJsonObj.toChar(respJson); diff --git a/core/Enclave/enclave_hsm.cpp b/core/Enclave/enclave_hsm.cpp index e0297f17..1fc4bd51 100644 --- a/core/Enclave/enclave_hsm.cpp +++ b/core/Enclave/enclave_hsm.cpp @@ -31,10 +31,13 @@ #include "enclave_hsm_t.h" #include "openssl/rand.h" +#include "openssl/sha.h" #include "datatypes.h" #include "key_factory.h" #include "key_operation.h" +extern sgx_aes_gcm_256bit_key_t g_domain_key; + using namespace std; // Used to store the secret passed by the SP in the sample code. @@ -109,6 +112,17 @@ static size_t get_signature_length(ehsm_keyspec_t keyspec) } } +void compute_dk_hash(ehsm_keyblob_t *cmk) +{ + SHA256_CTX ctx; + SHA256_Init(&ctx); + unsigned int len = SGX_DOMAIN_KEY_SIZE; + unsigned char result[SHA256_DIGEST_LENGTH] = {0}; + SHA256_Update(&ctx, g_domain_key, len); + SHA256_Final(result, &ctx); + memcpy(cmk->metadata.dk_hashcode, result, SHA256_DIGEST_LENGTH); +} + sgx_status_t enclave_create_key(ehsm_keyblob_t *cmk, size_t cmk_size) { sgx_status_t ret = SGX_ERROR_UNEXPECTED; @@ -120,6 +134,8 @@ sgx_status_t enclave_create_key(ehsm_keyblob_t *cmk, size_t cmk_size) return SGX_ERROR_INVALID_PARAMETER; } + compute_dk_hash(cmk); + switch (cmk->metadata.keyspec) { case EH_AES_GCM_128: diff --git a/core/Enclave/key_factory.cpp b/core/Enclave/key_factory.cpp index cfcd2092..1d577d23 100644 --- a/core/Enclave/key_factory.cpp +++ b/core/Enclave/key_factory.cpp @@ -115,7 +115,7 @@ sgx_status_t ehsm_create_keyblob(uint8_t *plaintext, if (SGX_SUCCESS != ret) { log_e("gcm encrypting failed.\n"); - } + } else { keyblob_data->ciphertext_size = plaintext_size; @@ -331,7 +331,7 @@ sgx_status_t ehsm_create_rsa_key(ehsm_keyblob_t *cmk) if (bio) BIO_free(bio); if (e) - BN_free(e); + BN_free(e); SAFE_MEMSET(pem_keypair, key_size, 0, key_size); SAFE_FREE(pem_keypair); diff --git a/dkeycache/App/la_server.cpp b/dkeycache/App/la_server.cpp index 51794061..da0a4aa1 100644 --- a/dkeycache/App/la_server.cpp +++ b/dkeycache/App/la_server.cpp @@ -28,7 +28,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ - + #include #include #include @@ -38,179 +38,261 @@ #include #include #include - + #include "la_server.h" #include "ulog_utils.h" - -#define BACKLOG 5 -#define CONCURRENT_MAX 32 +#include "enclave_u.h" +#include "datatypes.h" + +#define BACKLOG 5 +#define CONCURRENT_MAX 32 #define SERVER_PORT 8888 #define BUFFER_SIZE 1024 +#define RECONNECT_TIMES 3 +#define SLEEP_INTV 3 + +extern bool g_is_ready; +extern FdPool g_client_resrved_fds[CONCURRENT_MAX]; +/* Function Description: + * This function is to check client liveness status and clear useless fd. + * */ +static void *HeartbeatToClientHandler(void *args) +{ + int bytes_written = 0; + _response_header_t *heart_beat = nullptr; + heart_beat = (_response_header_t *)malloc(sizeof(_response_header_t)); + if (heart_beat == nullptr) + { + log_d("getDomainkey malloc failed\n"); + goto out; + } + heart_beat->type = MSG_HEARTBEAT; + while (true) + { + ocall_sleep(SLEEP_INTV); + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_resrved_fds[i].fd != 0) + { + if (g_client_resrved_fds[i].errorCnt < RECONNECT_TIMES) + { + bytes_written = send(g_client_resrved_fds[i].fd, reinterpret_cast(heart_beat), sizeof(_response_header_t), MSG_NOSIGNAL); + if (bytes_written<= 0) + { + g_client_resrved_fds[i].errorCnt++; + } + else + { + g_client_resrved_fds[i].errorCnt = 0; + } + } + else + { + close(g_client_resrved_fds[i].fd); + g_client_resrved_fds[i].fd = 0; + g_client_resrved_fds[i].errorCnt = 0; + } + } + } + } +out: + SAFE_FREE(heart_beat); + pthread_exit((void *)-1); +} /* Function Description: * This is server initialization routine, it creates TCP sockets and listen on a port. * In Linux, it would listen on domain socket named '/var/run/ehsm/dkeyprovision.sock' - * In Windows, it would listen on port 8888, which is for demonstration purpose + * In Windows, it would listen on port 8888, which is for demonstration purpose * */ int LaServer::init() { - log_i("Initializing ProtocolHandler [\"socket: %s\"]", UNIX_DOMAIN); + log_i("Initializing ProtocolHandler [\"socket: %s\"]", UNIX_DOMAIN); struct sockaddr_un srv_addr; - + m_server_sock_fd = socket(AF_UNIX, SOCK_STREAM, 0); if (m_server_sock_fd == -1) { log_d("socket initiazation error\n"); return -1; } - + srv_addr.sun_family = AF_UNIX; - strncpy(srv_addr.sun_path, UNIX_DOMAIN, sizeof(srv_addr.sun_path)-1); + strncpy(srv_addr.sun_path, UNIX_DOMAIN, sizeof(srv_addr.sun_path) - 1); unlink(UNIX_DOMAIN); - - int bind_result = bind(m_server_sock_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr)); + + int bind_result = bind(m_server_sock_fd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); if (bind_result == -1) { log_d("bind error\n"); close(m_server_sock_fd); return -1; } - + if (listen(m_server_sock_fd, BACKLOG) == -1) { log_d("listen error\n"); close(m_server_sock_fd); return -1; } - + m_shutdown = 0; - - log_i("Starting ProtocolHandler [\"socket: %s\"]", UNIX_DOMAIN); + + log_i("Starting ProtocolHandler [\"socket: %s\"]", UNIX_DOMAIN); + return 0; } - + /* Function Description: * This function is server's major routine, it uses select() to accept new connection and receive messages from clients. * When it receives clients' request messages, it would put the message to task queue and wake up worker thread to process the requests. * */ void LaServer::doWork() { - int client_fds[CONCURRENT_MAX] = {0}; fd_set server_fd_set; int max_fd = -1; - struct timeval tv; + struct timeval tv; char input_msg[BUFFER_SIZE]; char recv_msg[BUFFER_SIZE]; - + pthread_t HeartbeatToClient_thread; + if (pthread_create(&HeartbeatToClient_thread, NULL, HeartbeatToClientHandler, NULL) < 0) + { + log_d("could not create thread\n"); + // error handler + } while (!m_shutdown) { - // set 20s timeout for select() + // set 20s timeout for select() tv.tv_sec = 20; tv.tv_usec = 0; FD_ZERO(&server_fd_set); - + FD_SET(STDIN_FILENO, &server_fd_set); - if (max_fd 0) { + + // if dkeycache is not ready close the fd immediately + if (g_is_ready == false) + { + close(client_sock_fd); + client_sock_fd = 0; + } + + if (client_sock_fd > 0) + { // add new connection to connection pool if it's not full int index = -1; - for(int i = 0; i < CONCURRENT_MAX; i++) { - if(client_fds[i] == 0) { + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_resrved_fds[i].fd == 0) + { index = i; - client_fds[i] = client_sock_fd; + g_client_resrved_fds[i].fd = client_sock_fd; break; } } - - if(index < 0) { + + if (index < 0) + { log_i("server reach maximum connection!\n"); bzero(input_msg, BUFFER_SIZE); strcpy(input_msg, "server reach maximum connection\n"); send(client_sock_fd, input_msg, BUFFER_SIZE, 0); } - }else if (client_sock_fd < 0) { - log_d("server: accept() return failure, %s, would exit.\n", strerror(errno)); + } + else if (client_sock_fd < 0) + { + log_d("server: accept() return failure, %s, would exit.\n", strerror(errno)); close(m_server_sock_fd); break; } } - - for(int i =0; i < CONCURRENT_MAX; i++) { - if ((client_fds[i] !=0) - && (FD_ISSET(client_fds[i], &server_fd_set))) + + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if ((g_client_resrved_fds[i].fd != 0) && (FD_ISSET(g_client_resrved_fds[i].fd, &server_fd_set))) { // there is request messages from client connectsions - FIFO_MSG * msg; - + FIFO_MSG *msg; + bzero(recv_msg, BUFFER_SIZE); - long byte_num = recv(client_fds[i], recv_msg, BUFFER_SIZE, 0); - if (byte_num > 0) { - if(byte_num > BUFFER_SIZE) - byte_num = BUFFER_SIZE; - + long byte_num = recv(g_client_resrved_fds[i].fd, recv_msg, BUFFER_SIZE, 0); + if (byte_num > 0) + { + if (byte_num > BUFFER_SIZE) + byte_num = BUFFER_SIZE; + recv_msg[byte_num] = '\0'; - + msg = (FIFO_MSG *)malloc(byte_num); - if (!msg) { + if (!msg) + { log_e("memory allocation failure\n"); continue; } memset(msg, 0, byte_num); - + memcpy(msg, recv_msg, byte_num); - - msg->header.sockfd = client_fds[i]; - + + msg->header.sockfd = g_client_resrved_fds[i].fd; + // put request message to event queue m_cptask->puttask(msg); } - else if(byte_num < 0) { - log_d("failed to receive message.\n"); - } else { + else if (byte_num < 0) + { + log_d("failed to receive message.\n"); + } + else + { // client connect is closed - FD_CLR(client_fds[i], &server_fd_set); - close(client_fds[i]); - client_fds[i] = 0; + FD_CLR(g_client_resrved_fds[i].fd, &server_fd_set); + close(g_client_resrved_fds[i].fd); + g_client_resrved_fds[i].fd = 0; } } } } } - + /* Function Description: * This function is to shutdown server. It's called when process exits. * */ @@ -219,7 +301,6 @@ void LaServer::shutDown() log_i("Server would shutdown...\n"); m_shutdown = 1; m_cptask->shutdown(); - + close(m_server_sock_fd); -} - +} \ No newline at end of file diff --git a/dkeycache/App/main.cpp b/dkeycache/App/main.cpp index 397ab496..35d6a354 100644 --- a/dkeycache/App/main.cpp +++ b/dkeycache/App/main.cpp @@ -28,8 +28,14 @@ #define ENCLAVE_PATH "libenclave-ehsm-dkeycache.signed.so" #include +#define CONCURRENT_MAX 32 + +FdPool g_client_resrved_fds[CONCURRENT_MAX] = {{0, 0}}; + sgx_enclave_id_t g_enclave_id; +bool g_is_ready = false; // dkeycache get latest domainkey the status is ready or (ROTATE_START connect failed) status is not ready + void ocall_print_string(uint32_t log_level, const char *str, const char *filename, uint32_t line) { switch (log_level) @@ -46,11 +52,55 @@ void ocall_print_string(uint32_t log_level, const char *str, const char *filenam } } +// update is ready flag and send rotation status to core +void ocall_update_rotate_flag(const bool *rotate_flag) +{ + _response_header_t *rotate_msg = nullptr; + rotate_msg = (_response_header_t *)malloc(sizeof(_response_header_t)); + if (rotate_msg == nullptr) + { + log_d("getDomainkey malloc failed\n"); + } + if (*rotate_flag) + { + rotate_msg->type = MSG_ROTATE_START; + g_is_ready = false; + log_i("dkeycache is ready is set to false\n"); + } + else + { + rotate_msg->type = MSG_ROTATE_END; + g_is_ready = true; + log_i("dkeycache is ready is set to true\n"); + } + + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_resrved_fds[i].fd != 0) + { + // error is handled by heartbeat; + send(g_client_resrved_fds[i].fd, reinterpret_cast(rotate_msg), sizeof(_response_header_t), MSG_NOSIGNAL); + } + } + SAFE_FREE(rotate_msg) +} + +void ocall_update_is_ready(const bool *is_ready) +{ + g_is_ready = *is_ready; + log_i("is ready set to %s\n", g_is_ready == true ? "true" : "false"); +} + int ocall_close(int fd) { return close(fd); } +void ocall_sleep(int second) +{ + sleep(second); +} + void ocall_get_current_time(uint64_t *p_current_time) { time_t rawtime; @@ -224,6 +274,7 @@ int main(int argc, char *argv[]) // register signal handler so to respond to user interception signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); + signal(SIGPIPE, SIG_IGN); g_la_task->start(); diff --git a/dkeycache/Enclave/enclave.edl b/dkeycache/Enclave/enclave.edl index 87440231..176e81b7 100644 --- a/dkeycache/Enclave/enclave.edl +++ b/dkeycache/Enclave/enclave.edl @@ -55,6 +55,9 @@ enclave { void ocall_get_current_time([out] uint64_t *p_current_time); int ocall_socket (int domain, int type, int protocol) propagate_errno; int ocall_connect (int fd, [in, size=len] const struct sockaddr *addr, socklen_t len) propagate_errno; + void ocall_sleep(int second); + void ocall_update_rotate_flag([in] const bool *rotate_flag); + void ocall_update_is_ready([in] const bool *is_ready); }; trusted { diff --git a/dkeycache/Enclave/enclave_la.cpp b/dkeycache/Enclave/enclave_la.cpp index 6332b97f..07e70eb5 100644 --- a/dkeycache/Enclave/enclave_la.cpp +++ b/dkeycache/Enclave/enclave_la.cpp @@ -47,7 +47,7 @@ #include "sgx_tcrypto.h" -void log_printf(uint32_t log_level, const char* filename, uint32_t line, const char *fmt, ...); +extern void log_printf(uint32_t log_level, const char* filename, uint32_t line, const char *fmt, ...); #define MAX_SESSION_COUNT 16 diff --git a/dkeycache/Enclave/enclave_ra.cpp b/dkeycache/Enclave/enclave_ra.cpp index 8e28e54e..c5c658c7 100644 --- a/dkeycache/Enclave/enclave_ra.cpp +++ b/dkeycache/Enclave/enclave_ra.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -40,14 +41,26 @@ #include #include #include -#include "sgx_trts.h" + #include "openssl_utility.h" #include "enclave_t.h" #include "elog_utils.h" #include "datatypes.h" +#define RECONNECT_TIMES 3 + +#define ROTATE_START true + +#define ROTATE_END false + uint8_t g_domain_key[SGX_DOMAIN_KEY_SIZE] = {0}; +SSL *g_ssl_session = nullptr; + +std::string g_server_name; + +uint16_t g_server_port = 0; + int verify_callback(int preverify_ok, X509_STORE_CTX *ctx); void log_printf(uint32_t log_level, const char* filename, uint32_t line, const char *fmt, ...) @@ -112,94 +125,6 @@ unsigned long inet_addr2(const char *str) return lHost; } -// This routine conducts a simple HTTP request/response communication with server -int communicate_with_server(SSL *ssl) -{ - unsigned char buf[200]; - int ret = 1; - int error = 0; - int len = 0; - int bytes_written = 0; - int bytes_read = 0; - - // Write an GET request to the server - log_d(TLS_CLIENT "-----> Write to server:\n"); - len = snprintf((char *)buf, sizeof(buf) - 1, CLIENT_PAYLOAD); - - while ((bytes_written = SSL_write(ssl, buf, (size_t)len)) <= 0) - { - error = SSL_get_error(ssl, bytes_written); - if (error == SSL_ERROR_WANT_WRITE) - continue; - log_d(TLS_CLIENT "Failed! SSL_write returned %d\n", error); - ret = bytes_written; - goto done; - } - - log_d(TLS_CLIENT "%d bytes written\n", bytes_written); - - // Read the HTTP response from server - log_d(TLS_CLIENT "<---- Read from server:\n"); - do - { - len = sizeof(buf) - 1; - memset(buf, 0, sizeof(buf)); - bytes_read = SSL_read(ssl, buf, (size_t)len); - - if (bytes_read <= 0) - { - int error = SSL_get_error(ssl, bytes_read); - if (error == SSL_ERROR_WANT_READ) - continue; - - log_d(TLS_CLIENT "Failed! SSL_read returned error=%d\n", error); - ret = bytes_read; - break; - } - - log_d(TLS_CLIENT " %d bytes read\n", bytes_read); - - if (bytes_read != SGX_DOMAIN_KEY_SIZE) - { - log_d( - TLS_CLIENT "ERROR: expected reading %lu bytes but only " - "received %d bytes\n", - SGX_DOMAIN_KEY_SIZE, - bytes_read); - ret = bytes_read; - break; - } - else - { - log_d(TLS_CLIENT - " received all the expected data from server\n\n"); - ret = 0; - memcpy(g_domain_key, buf, SGX_DOMAIN_KEY_SIZE); - log_i("Successfully received the DomainKey from deploy server.\n"); - for (unsigned long int i = 0; i < sizeof(g_domain_key); i++) - { - log_d("domain_key[%u]=%2u\n", i, g_domain_key[i]); - } - int retval = 0; - if (ocall_set_dkeycache_done(&retval) != SGX_SUCCESS) - { - ret = 1; - log_e("OCALL status failed.\n"); - goto done; - } - if (retval != 0) - { - ret = 1; - log_e("Dkeycache service setting isready status failed .\n"); - goto done; - } - break; - } - } while (1); -done: - return ret; -} - // create a socket and connect to the server_name:server_port int create_socket(const char *server_name, uint16_t server_port) { @@ -240,10 +165,84 @@ int create_socket(const char *server_name, uint16_t server_port) return sockfd; } -int enclave_launch_tls_client(const char *server_name, uint16_t server_port) +// send msg to g_ssl_session +static bool SendAll(const void *data, int32_t data_size) { - log_d(TLS_CLIENT " called launch tls client\n"); + const char *data_ptr = (const char *)data; + int32_t bytes_sent; + int error = 0; + + while ((bytes_sent = SSL_write(g_ssl_session, data_ptr, data_size)) <= 0) + { + error = SSL_get_error(g_ssl_session, bytes_sent); + if (error == SSL_ERROR_WANT_WRITE) + continue; + log_d(TLS_SERVER "Failed! SSL_write returned %d\n", error); + return false; + } + log_d(TLS_SERVER "%d bytes sent\n", bytes_sent); + return true; +} + + +// receive msg from g_ssl_session +static bool RecvAll(void *data, int32_t data_size) +{ + char *data_ptr = (char *)data; + int32_t bytes_recv; + int error = 0; + + while (true) + { + bytes_recv = SSL_read(g_ssl_session, data_ptr, data_size); + if (bytes_recv <= 0) + { + error = SSL_get_error(g_ssl_session, bytes_recv); + if (error == SSL_ERROR_WANT_READ) + continue; + log_d(TLS_SERVER "Failed! SSL_read returned error=%d\n", error); + return false; + } + log_d(TLS_SERVER "%d bytes recv\n", bytes_recv); + return true; + } + return true; +} + +// send get domainkey request to dkeyserver worker +int SendGetDomainkeyReq() +{ + int ret = 1; + + _request_header_t *req = nullptr; + _response_header_t *resp = nullptr; + + log_d(TLS_CLIENT "-----> Write getdomainkey cmd to server:\n"); + + req = (_request_header_t *)malloc(sizeof(_request_header_t)); + resp = (_response_header_t *)malloc(sizeof(_response_header_t)); + + if (req == nullptr || resp == nullptr) + { + log_d(TLS_CLIENT "getDomainkey malloc failed\n"); + goto out; + } + req->cmd = GET_DOMAINKEY; + + if (!SendAll(req, sizeof(_request_header_t))) + { + goto out; + } + ret = 0; +out: + SAFE_FREE(req); + return ret; +} + +// set up tls channel with g_ssl_session and send get domainkey request to dkeyserver worker +int enclave_connect_and_get_domainkey() +{ int ret = -1; SSL_CTX *ssl_client_ctx = nullptr; @@ -255,11 +254,7 @@ int enclave_launch_tls_client(const char *server_name, uint16_t server_port) int client_socket = -1; int error = 0; - if (server_name == NULL) - { - log_d("Starting" TLS_CLIENT "failed: server name unavailable.\n"); - goto done; - } + log_d("\nStarting" TLS_CLIENT "\n\n\n"); if ((ssl_client_ctx = SSL_CTX_new(TLS_client_method())) == nullptr) @@ -290,7 +285,7 @@ int enclave_launch_tls_client(const char *server_name, uint16_t server_port) goto done; } - if ((ssl_session = SSL_new(ssl_client_ctx)) == nullptr) + if ((g_ssl_session = SSL_new(ssl_client_ctx)) == nullptr) { log_d(TLS_CLIENT "Unable to create a new SSL connection state object\n"); @@ -298,21 +293,21 @@ int enclave_launch_tls_client(const char *server_name, uint16_t server_port) } log_d(TLS_CLIENT "new ssl connection getting created\n"); - client_socket = create_socket(server_name, server_port); + client_socket = create_socket(g_server_name.c_str(), g_server_port); if (client_socket == -1) { log_d( TLS_CLIENT "create a socket and initiate a TCP connect to server: %s:%d " "(errno=%d)\n", - server_name, - server_port, + g_server_name, + g_server_port, errno); goto done; } // set up ssl socket and initiate TLS connection with TLS server - if (SSL_set_fd(ssl_session, client_socket) != 1) + if (SSL_set_fd(g_ssl_session, client_socket) != 1) { log_d(TLS_CLIENT "ssl set fd error.\n"); } @@ -321,23 +316,22 @@ int enclave_launch_tls_client(const char *server_name, uint16_t server_port) log_d(TLS_CLIENT "ssl set fd succeed.\n"); } - if ((error = SSL_connect(ssl_session)) != 1) + if ((error = SSL_connect(g_ssl_session)) != 1) { log_d( TLS_CLIENT "Error: Could not establish a TLS session ret2=%d " "SSL_get_error()=%d\n", error, - SSL_get_error(ssl_session, error)); + SSL_get_error(g_ssl_session, error)); goto done; } log_d( TLS_CLIENT "successfully established TLS channel:%s\n", - SSL_get_version(ssl_session)); + SSL_get_version(g_ssl_session)); - // start the client server communication - if ((error = communicate_with_server(ssl_session)) != 0) + if ((error = SendGetDomainkeyReq()) != 0) { - log_d(TLS_CLIENT "Failed: communicate_with_server (ret=%d)\n", error); + log_d(TLS_CLIENT "Failed: get domainkey (ret=%d)\n", error); goto done; } @@ -345,23 +339,6 @@ int enclave_launch_tls_client(const char *server_name, uint16_t server_port) ret = 0; done: - if (client_socket != -1) - { - int closeRet; - ocall_close(&closeRet, client_socket); - if (closeRet != 0) - { - log_d(TLS_CLIENT "OCALL: error close socket\n"); - ret = -1; - } - } - - if (ssl_session) - { - SSL_shutdown(ssl_session); - SSL_free(ssl_session); - } - if (cert) X509_free(cert); @@ -373,7 +350,183 @@ int enclave_launch_tls_client(const char *server_name, uint16_t server_port) if (ssl_confctx) SSL_CONF_CTX_free(ssl_confctx); + if (ret == -1) + { + SSL_shutdown(g_ssl_session); + if (g_ssl_session) + SSL_free(g_ssl_session); + } + return ret; +} + +// send heartbeat to dkeyserver worker if connection lost then reconnect and get new domainkey +static void *HeartbeatToServerHandler(void *arg) +{ + int numberOfErrors = 0; + int res = -1; + bool is_ready = false; + _response_header_t *heart_beat = nullptr; + heart_beat = (_response_header_t *)malloc(sizeof(_response_header_t)); + + if (heart_beat == nullptr) + { + log_d(TLS_CLIENT "HeartbeatToServer malloc failed\n"); + goto out; + } + heart_beat->type = MSG_HEARTBEAT; + + while (true) + { + if (g_ssl_session != nullptr) + { + while (numberOfErrors < RECONNECT_TIMES) + { + + if (!SendAll(heart_beat, sizeof(_response_header_t))) + { + numberOfErrors++; + } + else + { + numberOfErrors = 0; + } + ocall_sleep(5); // sleep 5s. + } + // send failed reach max time then reconnect + if (g_ssl_session) + { + SSL_shutdown(g_ssl_session); + SSL_free(g_ssl_session); + ocall_close(&res, SSL_get_fd(g_ssl_session)); + g_ssl_session = nullptr; + } + if (0 != enclave_connect_and_get_domainkey()) + { + log_d(TLS_CLIENT "Failed: reconnect_with_server\n"); + ocall_update_is_ready(&is_ready); + } + numberOfErrors = 0; + } + } +out: + SAFE_FREE(heart_beat); + pthread_exit((void *)-1); +} + +int UpdateRotateFlag(bool rotate_flag) +{ + int ret = 0; + if (ocall_update_rotate_flag(&rotate_flag) != SGX_SUCCESS) + { + ret = 1; + log_e("OCALL status failed.\n"); + } + return ret; +} + +static void *RecvMsgHandler(void *args) +{ + int ret = 1; + _response_header_t *recv_msg = nullptr; + recv_msg = (_response_header_t *)malloc(sizeof(_response_header_t)); + if (recv_msg == nullptr) + { + log_d(TLS_CLIENT "getDomainkey malloc failed\n"); + } + + while (true) + { + if (g_ssl_session == nullptr) + { + continue; + } + + memset(recv_msg, 0, sizeof(_response_header_t)); + RecvAll(recv_msg, sizeof(_response_header_t)); + + switch (recv_msg->type) + { + case MSG_ROTATE_START: + { + if (UpdateRotateFlag(ROTATE_START)) + { + log_d(TLS_CLIENT "Failed: update rotate flag\n"); + ret = -1; + goto done; + } + } + break; + case MSG_ROTATE_END: + { + if ((ret = SendGetDomainkeyReq()) != 0) + { + log_d(TLS_CLIENT "Failed: get send get domainkey req\n"); + goto done; + } + } + break; + case MSG_DOMAINKEY: + { + ret = 0; + memcpy(g_domain_key, recv_msg->domainKey, SGX_DOMAIN_KEY_SIZE); + log_i("Successfully received the DomainKey from deploy server.\n"); + for (unsigned long int i = 0; i < SGX_DOMAIN_KEY_SIZE; i++) + { + log_d("domain_key[%u]=%2u\n", i, g_domain_key[i]); + } + int retval = 0; + if (UpdateRotateFlag(ROTATE_END)) + { + log_d(TLS_CLIENT "Failed: update rotate flag\n"); + ret = -1; + goto done; + } + } + break; + default: + break; + } + } +done: + SAFE_FREE(recv_msg); + pthread_exit((void *)-1); +} +int enclave_launch_tls_client(const char *server_name, uint16_t server_port) +{ + log_d(TLS_CLIENT " called launch tls client\n"); + + int ret = -1; + if (server_name == nullptr) + { + log_d(TLS_CLIENT "Failed: null server_name"); + goto done; + } + + g_server_name = server_name; + g_server_port = server_port; + if (0 != enclave_connect_and_get_domainkey()) + { + log_d(TLS_CLIENT "Failed: reconnect_with_server\n"); + goto done; + } + + pthread_t heartbeat_to_server_thread, recvmsg_thread; + if (pthread_create(&heartbeat_to_server_thread, NULL, HeartbeatToServerHandler, NULL) < 0) + { + log_d("could not create thread\n"); + goto done; + } + + if (pthread_create(&recvmsg_thread, NULL, RecvMsgHandler, NULL) < 0) + { + log_d("could not create thread\n"); + goto done; + } + + // Free the structures we don't need anymore + ret = 0; +done: log_d(TLS_CLIENT " %s\n", (ret == 0) ? "success" : "failed"); return ret; } diff --git a/dkeycache/Makefile b/dkeycache/Makefile index 0a8f43d0..4e7359e7 100644 --- a/dkeycache/Makefile +++ b/dkeycache/Makefile @@ -49,7 +49,8 @@ App_Include_Paths := \ -IApp \ -I$(LOG_DIR) \ -I$(SGX_SDK)/include \ - -I$(TOPDIR)/include + -I$(TOPDIR)/include \ + -I$(TOPDIR)/utils/sgx_socket/tls App_C_Flags := $(SGX_COMMON_FLAGS) -fPIC -Wno-attributes $(App_Include_Paths) -DRUNTIME_FOLDER=\"$(RUNTIME_FOLDER)\" diff --git a/dkeyserver/App/base64.cpp b/dkeyserver/App/base64.cpp new file mode 100644 index 00000000..60bb85c1 --- /dev/null +++ b/dkeyserver/App/base64.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2021-2022 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "base64.h" + + +static const std::string encode_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +std::string base64_encode(const uint8_t *bytes_to_encode, uint32_t in_len) { + std::string encode_str; + uint32_t i = 0; + uint32_t j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + encode_str += encode_table[char_array_4[i]]; + i = 0; + } + } + + if (i) { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + encode_str += encode_table[char_array_4[j]]; + + while((i++ < 3)) + encode_str += '='; + } + + return encode_str; + +} + +std::string base64_decode(const std::string &encoded_string) { + uint32_t in_len = encoded_string.size(); + uint32_t i = 0; + uint32_t j = 0; + uint32_t in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string decode_str; + + while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i ==4) { + for (i = 0; i <4; i++) + char_array_4[i] = static_cast(encode_table.find(char_array_4[i])); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + decode_str += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j <4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + char_array_4[j] = static_cast(encode_table.find(char_array_4[j])); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) + decode_str += char_array_3[j]; + } + + return decode_str; +} + + diff --git a/dkeyserver/App/base64.h b/dkeyserver/App/base64.h new file mode 100644 index 00000000..9b5ef6eb --- /dev/null +++ b/dkeyserver/App/base64.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021-2022 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _BASE64_H_ +#define _BASE64_H_ + +#include + +std::string base64_encode(const uint8_t *bytes_to_encode, uint32_t in_len); + +std::string base64_decode(const std::string &encoded_string); + +#endif + diff --git a/dkeyserver/App/couchdb_curl.cpp b/dkeyserver/App/couchdb_curl.cpp new file mode 100644 index 00000000..baa63326 --- /dev/null +++ b/dkeyserver/App/couchdb_curl.cpp @@ -0,0 +1,142 @@ +#include "couchdb_curl.h" + +using namespace std; + +size_t getUrlResponse(void *buffer, size_t size, size_t count, void *response) +{ + string *str = (string *)response; + (*str).append((char *)buffer, size * count); + + return size * count; +} + +string setRequest(string url, string data) +{ + string response = ""; + + CURL *curl = NULL; + struct curl_slist *headers = NULL; + curl_global_init(CURL_GLOBAL_ALL); + + curl = curl_easy_init(); + + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + headers = curl_slist_append(headers, "charsets: utf-8"); + + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); + + // curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); + // curl_easy_setopt(curl, CURLOPT_HEADER, 0L); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &getUrlResponse); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + int res = curl_easy_perform(curl); + + curl_slist_free_all(headers); + curl_easy_cleanup(curl); + curl_global_cleanup(); + + return response; +} + +string getRequest(string url) +{ + string response = ""; + + CURL *curl = NULL; + struct curl_slist *headers = NULL; + curl_global_init(CURL_GLOBAL_ALL); + + curl = curl_easy_init(); + + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, "Content-Type: application/json"); + headers = curl_slist_append(headers, "charsets: utf-8"); + + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &getUrlResponse); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + curl_easy_perform(curl); + + curl_easy_cleanup(curl); + curl_global_cleanup(); + + return response; +} + +void print_json(JsonValue data, vector &keylist, string req_data) +{ + JsonValue::Members mem = data.getMemberNames(); + + for (auto iter = mem.begin(); iter != mem.end(); iter++) + { + if (data[*iter].type() == Json::objectValue) + { + print_json(data[*iter], keylist, req_data); + } + else if (data[*iter].type() == Json::arrayValue) + { + auto cnt = data[*iter].size(); + for (auto i = 0; i < cnt; i++) + { + print_json(data[*iter][i], keylist, req_data); + } + } + else if (data[*iter].type() == Json::stringValue) + { + string str = data[*iter].asString(); + if (string::npos != str.find(req_data)) + if (keylist.at(keylist.size() - 1).compare(data[*iter].asString())) + keylist.push_back(data[*iter].asString()); + } + } +} + +int couchdb_get(vector &data, string req_data, string url) +{ + auto res = getRequest(url + "/ehsm_kms_db/_all_docs"); + + JsonReader reader; + JsonValue value; + if (!reader.parse(res, value)) + return -1; + + vector _ids; + _ids.push_back(""); + print_json(value, _ids, req_data); + _ids.erase(_ids.begin()); + + for (auto id : _ids) + { + auto res = getRequest(url + "/ehsm_kms_db/" + id); + JsonObj temp; + temp.parse(res); + cout<<"couchdb_get in="< +#include +#include +#include +#include +#include +#include + +#include "json_utils.h" +#include "auto_version.h" + +using namespace std; + +typedef Json::Reader JsonReader; +typedef Json::Value JsonValue; + +int couchdb_get(vector &data, + string req_data, + string url); + +int couchdb_put(JsonObj data, string url); + +#endif diff --git a/dkeyserver/App/main.cpp b/dkeyserver/App/main.cpp index e32f4f4a..ee790f3a 100644 --- a/dkeyserver/App/main.cpp +++ b/dkeyserver/App/main.cpp @@ -1,6 +1,7 @@ #include #include #include "sgx_urts.h" +#include #include "auto_version.h" #include "ulog_utils.h" @@ -10,38 +11,93 @@ #include #include #include +#include #include #include #include #include #include #include - +#include #include +#include +#include + +#include "base64.h" +#include "couchdb_curl.h" +#include "datatypes.h" +#include "json_utils.h" #define ENCLAVE_PATH "libenclave-ehsm-dkeyserver.signed.so" #define ROLE_WORKER "worker" #define ROLE_ROOT "root" +#define CMK_DB "cmk:" +#define USER_INFO_DB "user_info:" char s_port[] = "8888"; #define FILE_NAME (std::string(RUNTIME_FOLDER) + "dkey.bin").c_str() -sgx_enclave_id_t g_enclave_id; +#define CMK_INFO 0 +#define USER_INFO 1 + +#define KEYBLOB 0 +#define CMK 1 +#define SM_DEFAULT_CMK 2 + +sgx_enclave_id_t g_enclave_id = 0; +std::string g_couchdb_url; using namespace std; +errno_t memcpy_s( + void *dest, + size_t numberOfElements, + const void *src, + size_t count) +{ + if (numberOfElements < count) + return -1; + memcpy(dest, src, count); + return 0; +} + +int ocall_select(int fd) +{ + fd_set server_fd_set; + FD_ZERO(&server_fd_set); + FD_SET(fd, &server_fd_set); + + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 5000; + + int ret = select(fd + 1, &server_fd_set, NULL, NULL, &tv); + if (ret > 0) + { + if (FD_ISSET(fd, &server_fd_set)) + { + log_d("%d\n", ret); + return 1; + } + } + + sleep(1); + + return 0; +} + void ocall_print_string(uint32_t log_level, const char *str, const char *filename, uint32_t line) { - switch (log_level) + switch (log_level) { - case LOG_INFO: - case LOG_DEBUG: - case LOG_ERROR: - case LOG_WARN: - log_c(log_level, str, filename, line); - break; - default: - log_c(LOG_ERROR, "log system error in ocall print.\n", filename, line); - break; + case LOG_INFO: + case LOG_DEBUG: + case LOG_ERROR: + case LOG_WARN: + log_c(log_level, str, filename, line); + break; + default: + log_c(LOG_ERROR, "log system error in ocall print.\n", filename, line); + break; } } @@ -60,6 +116,11 @@ void ocall_get_current_time(uint64_t *p_current_time) *p_current_time = (uint64_t)rawtime; } +void ocall_sleep(int second) +{ + sleep(second); +} + int ocall_set_dkeyserver_done() { return (system("touch /tmp/dkeyserver_isready.status")); @@ -71,39 +132,77 @@ static inline bool file_exists(const std::string &name) return (stat(name.c_str(), &buffer) == 0); } -int ocall_read_domain_key(uint8_t *cipher_dk, uint32_t cipher_dk_len) +int ocall_read_domain_key(uint8_t *cipher_dk, + uint32_t cipher_dk_len, + uint64_t *create_time, + uint8_t *dk_hash, + uint32_t dk_hash_size) { if (!file_exists(FILE_NAME)) { - log_e("ocall_read_domain_key file does not exist.\n"); + log_e("ocall_read_domain_key: file does not exist.\n"); return -2; } fstream file; + JsonReader reader; + JsonValue value; + uint64_t temp_time = 0; + file.open(FILE_NAME, ios::in | ios::binary); if (!file) { - log_e("Failed to open file...\n"); + log_e("ocall_read_domain_key: failed to open file\n"); return -1; } file.seekg(0, std::ios::end); size_t size = file.tellg(); file.seekg(0); - if (size != cipher_dk_len) - { - log_e("mismatched length: %ld:%d.\n", size, cipher_dk_len); - return -1; - } - uint8_t tmp[size] = {0}; - if (file.read((char *)&tmp, size)) + uint8_t tmp_buf[size] = {0}; + + //Get the latest domainkey json in buf + if (file.read((char *)&tmp_buf, size)) { - memcpy(cipher_dk, tmp, cipher_dk_len); + if (!reader.parse((char *)tmp_buf, value)) + return -1; + + JsonValue::Members mem = value.getMemberNames(); + + JsonObj latest_domainkey_json; + latest_domainkey_json.addData_uint64("createDate", 0); + + for (auto iter = mem.begin(); iter != mem.end(); iter++) + { + for (auto iter = mem.begin(); iter != mem.end(); iter++) + { + if (value[*iter].type() == Json::objectValue) + { + JsonObj temp; + temp.setJson(value[*iter]); + uint64_t time = temp.readData_uint64("createDate"); + if (time > latest_domainkey_json.readData_uint64("createDate")) + { + latest_domainkey_json = temp; + } + } + } + } + //get the domainkey ciper, createdate and dk_hash in json + *create_time = latest_domainkey_json.readData_uint64("createDate"); + memcpy(dk_hash, + base64_decode(latest_domainkey_json.readData_string("dk_hashcode").c_str()).c_str(), + 32); + + log_i("base64 hash=%s", latest_domainkey_json.readData_string("dk_hashcode").c_str()); + log_i("createDate=%d", latest_domainkey_json.readData_uint64("createDate")); + + latest_domainkey_json.readData_uint8Array("dkey", cipher_dk); } else { - log_e("Failed to read data from file...\n"); + log_e("ocall_read_domain_key: Failed to read data from file...\n"); return -1; } @@ -112,22 +211,85 @@ int ocall_read_domain_key(uint8_t *cipher_dk, uint32_t cipher_dk_len) return 0; } -int ocall_store_domain_key(uint8_t *cipher_dk, uint32_t cipher_dk_len) +int ocall_store_domain_key(uint8_t *cipher_dk, + uint32_t cipher_dk_len, + uint8_t *dk_hash, + uint32_t dk_hash_size) { + fstream file; + + string dk_hash_base64 = base64_encode(dk_hash, dk_hash_size); + + if (!file_exists(FILE_NAME)) + { + log_d("domain key file does not exist.\n"); + file.open(FILE_NAME, ios::out | ios::binary | ios::trunc); + if (!file) + { + log_e("Failed to create file...\n"); + return -1; + } + file.write("{}", 3); + file.close(); + } uint8_t tmp[cipher_dk_len]; + JsonObj domainkey_json; + JsonObj storeJson; + time_t createdate; + + time(&createdate); memcpy(tmp, cipher_dk, cipher_dk_len); - fstream file; - file.open(FILE_NAME, ios::out | ios::binary | ios::trunc); + file.open(FILE_NAME, ios::in | ios::binary); if (!file) { - log_e("Failed to create file...\n"); + log_e("store_domain_key: Failed to open file...\n"); return -1; } + file.seekg(0, std::ios::end); + size_t size = file.tellg(); + file.seekg(0); + char tmp_buf[size + 1] = {0}; - file.write((char *)&tmp, cipher_dk_len); + if (file.read(tmp_buf, size)) + storeJson.parse(tmp_buf); + else + { + log_e("store_domain_key: Failed to read data from file...\n"); + return -1; + } file.close(); + /*store json format: + { + "PHr4qY1m4afiJFgHoiRC4+Y2SP7oImkRqmBDFwA1LTk=": + {createDate":"1673835139", + "dk_hashcode":"PHr4qY1m4afiJFgHoiRC4+Y2SP7oImkRqmBDFwA1LTk=", + "dkey":[4,0,2,0,0,0,0,0,5,8,8,9,255,255,0,0,0,0,0,1]} + { + "PHr4qY1m4afiJFgHoiRC4+Y2SP7oImkRqmBDFwA1LTk=": + {createDate":"1673835139", + "dk_hashcode":"PHr4qY1m4afiJFgHoiRC4+Y2SP7oImkRqmBDFwA1LTk=", + "dkey":[4,0,2,0,0,0,0,0,5,8,8,9,255,255,0,0,0,0,0,1]} + } + */ + if (!storeJson.hasOwnProperty(dk_hash_base64)) + { + domainkey_json.addData_uint8Array("dkey", tmp, cipher_dk_len); + domainkey_json.addData_uint64("createDate", (uint64_t)createdate); + domainkey_json.addData_string("dk_hashcode", dk_hash_base64); + + storeJson.addData_JsonValue(dk_hash_base64, domainkey_json.getJson()); + // log_d("storeJson=> %s", storeJson.toString().c_str()); + + file.open(FILE_NAME, ios::out | ios::binary | ios::trunc); + file.write(storeJson.toString().c_str(), strlen(storeJson.toString().c_str())); + file.close(); + } + + log_i("new dkey base64 hash=%s", dk_hash_base64.c_str()); + log_i("new dkey createDate=%d", createdate); + return 0; } @@ -138,6 +300,11 @@ int ocall_socket(int domain, int type, int protocol) return socket(domain, type, protocol); } +int ocall_send(int fd, const char *msg, uint32_t msg_size, int flag) +{ + return send(fd, msg, msg_size, flag); +} + int ocall_bind(int fd, const struct sockaddr *addr, socklen_t len) { return bind(fd, addr, len); @@ -191,18 +358,190 @@ int ocall_connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen return -1; } +std::vector couchdb_data; + +int ocall_load_couchdb(int db_type) +{ + int db_size; + couchdb_data.clear(); + + switch (db_type) + { + case CMK_INFO: + db_size = couchdb_get(couchdb_data, CMK_DB, g_couchdb_url); + break; + case USER_INFO: + db_size = couchdb_get(couchdb_data, USER_INFO_DB, g_couchdb_url); + break; + default: + return 0; + } + + if (db_size == 0) + { + log_d("no cmkdb data\n"); + return 0; + } + return db_size; +} + +int update_CMK_by_dbName(std::string dbName, + std::string keyName, + uint8_t *cipher_cmk_dk, + uint32_t cipher_cmk_dk_len, + uint8_t *dk_hash) +{ + int error = 0; + int ret; + fstream file; + JsonObj dkey_storeJson; + JsonObj domainkeyJson; + string cmk_dk_hash_base64; + + std::string cmk_str; + string new_cmk; + size_t cmk_size = 0; + size_t new_cmk_size = 0; + string new_dk_hash_base64 = base64_encode(dk_hash, 32); + ehsm_keyblob_t *cmk = NULL; + + //read the local domainkey file + file.open(FILE_NAME, ios::in | ios::binary); + if (!file) + { + log_e("update_CMK_by_dbName: Failed to open file...\n"); + return -1; + } + file.seekg(0, std::ios::end); + size_t size = file.tellg(); + file.seekg(0); + char tmp_buf[size] = {0}; + + if (file.read(tmp_buf, size)) + dkey_storeJson.parse(tmp_buf); + else + { + log_e("update_CMK_by_dbName: Failed to read data from file...\n"); + return -1; + } + file.close(); + + auto iter = couchdb_data.at(0); + log_i("iter0=%s", iter.toString().c_str()); + + if (iter.hasOwnProperty("error")) + { + log_e("iter:\n%s", iter.toString().c_str()); + goto out; + } + //decode cmk from couchdb + cmk_str = base64_decode(iter.readData_string(keyName)); + cmk_size = cmk_str.size(); + cmk = (ehsm_keyblob_t *)malloc(cmk_size); + if (cmk == NULL) + { + log_e("cmk = NULL"); + goto out; + } + memcpy(cmk, (uint8_t *)cmk_str.data(), cmk_size); + cmk_dk_hash_base64 = base64_encode(cmk->metadata.dk_hashcode, 32); + //if dk_hash is the same, it is the latest version of domainkey and there is no need to re-encrypt cmk + if (strncmp(cmk_dk_hash_base64.c_str(), new_dk_hash_base64.c_str(), new_dk_hash_base64.size()) == 0) + { + SAFE_FREE(cmk); + log_i("this cmk has been updated"); + couchdb_data.erase(couchdb_data.begin()); + return 0; + } + //get the ciphertext of the domainkey used to encrypt the cmk + domainkeyJson.setJson(dkey_storeJson.readData_JsonValue(cmk_dk_hash_base64)); + domainkeyJson.readData_uint8Array("dkey", cipher_cmk_dk); + log_i("ecall_reencrypt_cmk in"); + error = ecall_reencrypt_cmk(g_enclave_id, &ret, cipher_cmk_dk, cipher_cmk_dk_len, cmk, APPEND_SIZE_TO_KEYBLOB_T(cmk->keybloblen)); + if (ret != SGX_SUCCESS || error != SGX_SUCCESS) + { + SAFE_FREE(cmk); + log_e("store new domain key failed (%d)(%d)", error, ret); + goto out; + } + log_i("ecall_reencrypt_cmk out"); + // sleep(1); + + new_cmk_size = APPEND_SIZE_TO_KEYBLOB_T(cmk->keybloblen); + new_cmk = base64_encode((uint8_t *)cmk, new_cmk_size); + + if (new_cmk.size() > 0) + { + iter.addData_string(keyName, new_cmk); + SAFE_FREE(cmk); + } + else + { + SAFE_FREE(cmk); + goto out; + } + if (couchdb_put(iter, g_couchdb_url) < 0) + { + goto out; + } + //delete the processed data from the vector + couchdb_data.erase(couchdb_data.begin()); + return 0; +out: + couchdb_data.erase(couchdb_data.begin()); + return -1; +} + +int ocall_update_CMK(uint8_t *cipher_dk, + uint32_t cipher_dk_len, + uint8_t *dk_hash, + uint32_t dk_hash_size, + int key_type) +{ + int ret = 0; + + std::string key; + std::string db; + switch (key_type) + { + case KEYBLOB: + key = "keyBlob"; + db = CMK_DB; + break; + case CMK: + key = "cmk"; + db = USER_INFO_DB; + break; + case SM_DEFAULT_CMK: + key = "sm_default_cmk"; + db = USER_INFO_DB; + break; + default: + return -1; + } + // update cmk_db data + ret = update_CMK_by_dbName(db, key, cipher_dk, cipher_dk_len, dk_hash); + if (ret == -1) + return -1; + + return ret; +} + void print_usage(int code) { log_i("Usage: ehsm-dkeyserver " "-r [ server role ] " + "-w [ password ] " + "-t [ period ] " + "-u [ couchdb_url ] " "-i [ target server ip ] " - "-u [ target server url ] " "-p [target server port]\n"); log_i("-h Print usage information and quit.\n" "-r Set the role of this machine as root or worker in server cluster.\n" "-i Set the ip address of target server.\n" - "-u Set the url of target server.\n" - "-p Set the port of target server.\n"); + "-w Set the password of root server.\n" + "-u Set the url to connect to couchdb, if you want use roration dk function, you must set couchdb_url. eg:http:// + user + : + password + @ + ip + : + port\n" + "-P Set the period of root server.\n"); exit(code); } @@ -210,18 +549,21 @@ static void parse_args(int argc, char *argv[], string &server_role, string &target_ip_addr, - uint16_t *target_port) + string &couchdb_url, + uint16_t *target_port, + size_t *password, + int *period) { int opt; int oidx = 0; - string host; - struct hostent *hptr; - static const char *_sopts = "r:i:u:p:h"; + static const char *_sopts = "r:i:p:h:w:P:u:"; static const struct option _lopts[] = {{"role", required_argument, NULL, 'r'}, {"ip", optional_argument, NULL, 'i'}, - {"url", optional_argument, NULL, 'u'}, {"port", optional_argument, NULL, 'p'}, + {"password", optional_argument, NULL, 'w'}, + {"period", optional_argument, NULL, 'P'}, {"help", no_argument, NULL, 'h'}, + {"couchdb_url", optional_argument, NULL, 'u'}, {0, 0, 0, 0}}; while ((opt = getopt_long(argc, argv, _sopts, _lopts, &oidx)) != -1) { @@ -239,26 +581,41 @@ static void parse_args(int argc, target_ip_addr = strdup(optarg); break; case 'u': - host = strdup(optarg); - hptr = gethostbyname(host.c_str()); - if (hptr == NULL || hptr->h_addr == NULL) + couchdb_url = strdup(optarg); + break; + case 'p': + try { - log_e("can't parse hostname [%s].", host.c_str()); + *target_port = std::stoi(strdup(optarg)); } - else + catch (...) { - char *ip = NULL; - target_ip_addr = inet_ntoa(*(struct in_addr *)hptr->h_addr_list[0]); + log_e("[-p %s] port must be a number.", optarg); } break; - case 'p': + case 'w': try { - *target_port = std::stoi(strdup(optarg)); + *password = std::stoi(strdup(optarg)); } catch (...) { - log_e("[-p %s] port must be a number.", optarg); + log_e("[-w %s] password must be a number.", optarg); + } + break; + case 'P': + try + { + *period = std::stoi(strdup(optarg)); + if (*period <= 30 || *period >= 365) + { + log_e("the period must greater than 30 days and less than 365 days."); + print_usage(EXIT_FAILURE); + } + } + catch (...) + { + log_e("[-t %s] period time must be a number.", optarg); } break; case 'h': @@ -273,7 +630,10 @@ static void parse_args(int argc, int validate_parameter(string server_role, string target_ip_addr, - uint16_t target_port) + string couchdb_url, + uint16_t target_port, + size_t password, + int period) { if (server_role[0] == '\0') { @@ -292,6 +652,37 @@ int validate_parameter(string server_role, log_e("please set correct target server ip and port.\n"); return -1; } + if (server_role == ROLE_WORKER && password != 0 && period != -1) + { + log_e("worker server cannot set password and period\n"); + return -1; + } + if (server_role == ROLE_ROOT && couchdb_url[0] == '\0') + { + log_e("root server must set couchdb_url\n"); + return -1; + } + return 0; +} + +int initialize_enclave(const sgx_uswitchless_config_t *us_config) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + /* Call sgx_create_enclave to initialize an enclave instance */ + /* Debug Support: set 2nd parameter to 1 */ + + const void *enclave_ex_p[32] = {0}; + + enclave_ex_p[SGX_CREATE_ENCLAVE_EX_SWITCHLESS_BIT_IDX] = (const void *)us_config; + + ret = sgx_create_enclave_ex(ENCLAVE_PATH, SGX_DEBUG_FLAG, NULL, NULL, &g_enclave_id, NULL, SGX_CREATE_ENCLAVE_EX_SWITCHLESS, enclave_ex_p); + if (ret != SGX_SUCCESS) + { + // print_error_message(ret); + return -1; + } + return 0; } @@ -306,30 +697,46 @@ int main(int argc, char *argv[]) return -1; } } + if (initLogger("dkeyserver.log") < 0) return -1; log_i("Service name:\t\tDomainKey Provisioning Service %s", EHSM_VERSION); log_i("Service built:\t\t%s", EHSM_DATE); log_i("Service git_sha:\t\t%s", EHSM_GIT_SHA); log_i("Runtime folder:\t%s", RUNTIME_FOLDER); + + signal(SIGPIPE, SIG_IGN); + string server_role; string target_ip_addr; + string couchdb_url; uint16_t target_port = 0; + size_t root_password = 0; + int root_period = -1; - sgx_status_t sgxStatus = SGX_ERROR_UNEXPECTED; parse_args(argc, argv, server_role, target_ip_addr, - &target_port); - - int ret = validate_parameter(server_role, target_ip_addr, target_port); + couchdb_url, + &target_port, + &root_password, + &root_period); + + int ret = validate_parameter(server_role, + target_ip_addr, + couchdb_url, + target_port, + root_password, + root_period); if (ret != 0) { log_i("Usage: ehsm-dkeyserver " "-r [server role] " "-i [target server ip] " - "-u [target server url] " + "-w [set root password] " + "-P [set period, eg:40(days)] " + "-u [set couchdb_url eg:http:// + user + : + password + @ + ip + : + port] " "-p [target server port]\n"); return -1; } @@ -343,25 +750,31 @@ int main(int argc, char *argv[]) log_i("Target Server:\t%s:%d", target_ip_addr.c_str(), target_port); } - ret = sgx_create_enclave(ENCLAVE_PATH, - SGX_DEBUG_FLAG, - NULL, NULL, - &g_enclave_id, NULL); - if (SGX_SUCCESS != ret) + sgx_uswitchless_config_t us_config = SGX_USWITCHLESS_CONFIG_INITIALIZER; + us_config.num_uworkers = 2; + us_config.num_tworkers = 2; + + /* Initialize the enclave */ + if (initialize_enclave(&us_config) < 0) { - log_e("failed(%d) to create enclave.\n", ret); + printf("Error: enclave initialization failed\n"); return -1; } + g_couchdb_url = couchdb_url; + + int sgxStatus = -1; ret = sgx_set_up_tls_server(g_enclave_id, - &ret, + &sgxStatus, s_port, server_role.c_str(), target_ip_addr.c_str(), - target_port); + target_port, + root_password, + root_period); if (ret != SGX_SUCCESS || sgxStatus != SGX_SUCCESS) { - log_d("Host: setup_tls_server failed\n"); + log_d("Host: setup_tls_server failed(%d)(%d)\n", ret, sgxStatus); } logger_shutDown(); diff --git a/dkeyserver/Enclave/domainkey_factory.cpp b/dkeyserver/Enclave/domainkey_factory.cpp new file mode 100644 index 00000000..8ed33cb7 --- /dev/null +++ b/dkeyserver/Enclave/domainkey_factory.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2020-2022 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "elog_utils.h" +#include "sgx_tseal.h" + +#include +#include +#include +#include + +#include "sgx_report.h" +#include "sgx_utils.h" +#include "sgx_tkey_exchange.h" + +#include "datatypes.h" +#include "domainkey_factory.h" +#include "enclave_t.h" + +extern void log_printf(uint32_t log_level, const char* filename, uint32_t line, const char *fmt, ...); + +bool ehsm_get_symmetric_key_size(ehsm_keyspec_t key_spec, uint32_t &key_size) +{ + switch (key_spec) + { + case EH_AES_GCM_128: + case EH_SM4_CTR: + case EH_SM4_CBC: + key_size = 16; + break; + case EH_AES_GCM_192: + key_size = 24; + break; + case EH_AES_GCM_256: + key_size = 32; + break; + default: + return false; + } + return true; +} + +uint32_t ehsm_get_gcm_ciphertext_size(const sgx_aes_gcm_data_ex_t *gcm_data) +{ + if (NULL == gcm_data) + return UINT32_MAX; + + return gcm_data->ciphertext_size; +} + +// https://github.com/openssl/openssl/blob/master/test/aesgcmtest.c#L38 +sgx_status_t aes_gcm_encrypt(uint8_t *key, + uint8_t *cipherblob, + const EVP_CIPHER *block_mode, + uint8_t *plaintext, + uint32_t plaintext_len, + uint8_t *aad, + uint32_t aad_len, + uint8_t *iv, + uint32_t iv_len, + uint8_t *tag, + uint32_t tag_len) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + int temp_len = 0; + EVP_CIPHER_CTX *pctx = NULL; + + // Create and init ctx + if (!(pctx = EVP_CIPHER_CTX_new())) + goto out; + + if (1 != EVP_EncryptInit_ex(pctx, block_mode, NULL, NULL, NULL)) + goto out; + + if (iv_len != SGX_AESGCM_IV_SIZE) + if (1 != EVP_CIPHER_CTX_ctrl(pctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) + goto out; + + // Initialise encrypt/decrpty, key and IV + if (1 != EVP_EncryptInit_ex(pctx, NULL, NULL, key, iv)) + goto out; + + // Provide AAD data if exist + if (aad != NULL && aad_len > 0) + if (1 != EVP_EncryptUpdate(pctx, NULL, &temp_len, aad, aad_len)) + goto out; + + if (plaintext != NULL && plaintext_len > 0) + { + // Provide the message to be encrypted, and obtain the encrypted output. + if (1 != EVP_EncryptUpdate(pctx, cipherblob, &temp_len, plaintext, plaintext_len)) + goto out; + } + else + { + ret = SGX_ERROR_INVALID_PARAMETER; + goto out; + } + + // Finalise the encryption/decryption + if (1 != EVP_EncryptFinal_ex(pctx, cipherblob + temp_len, &temp_len)) + goto out; + + // Get tag + if (1 != EVP_CIPHER_CTX_ctrl(pctx, EVP_CTRL_GCM_GET_TAG, tag_len, tag)) + goto out; + + ret = SGX_SUCCESS; + +out: + EVP_CIPHER_CTX_free(pctx); + return ret; +} + +sgx_status_t aes_gcm_decrypt(uint8_t *key, + uint8_t *plaintext, + const EVP_CIPHER *block_mode, + uint8_t *ciphertext, + uint32_t ciphertext_len, + uint8_t *aad, + uint32_t aad_len, + uint8_t *iv, + uint32_t iv_len, + uint8_t *tag, + uint32_t tag_len) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + int temp_len = 0; + EVP_CIPHER_CTX *pctx = NULL; + // Create and initialise the context + if (!(pctx = EVP_CIPHER_CTX_new())) + goto out; + + if (1 != EVP_EncryptInit_ex(pctx, block_mode, NULL, NULL, NULL)) + goto out; + + if (iv_len != SGX_AESGCM_IV_SIZE) + if (1 != EVP_CIPHER_CTX_ctrl(pctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) + goto out; + + // Initialise decrypt, key and IV + if (!EVP_DecryptInit_ex(pctx, NULL, NULL, key, iv)) + goto out; + + if (aad != NULL && aad_len > 0) + if (!EVP_DecryptUpdate(pctx, NULL, &temp_len, aad, aad_len)) + goto out; + + // Decrypt message, obtain the plaintext output + if (ciphertext != NULL && ciphertext_len > 0) + { + if (!EVP_DecryptUpdate(pctx, plaintext, &temp_len, ciphertext, ciphertext_len)) + goto out; + } + else + { + ret = SGX_ERROR_INVALID_PARAMETER; + goto out; + } + + // Update expected tag value + if (!EVP_CIPHER_CTX_ctrl(pctx, EVP_CTRL_GCM_SET_TAG, tag_len, tag)) + goto out; + + // Finalise the decryption. A positive return value indicates success, + // anything else is a failure - the plaintext is not trustworthy. + if (EVP_DecryptFinal_ex(pctx, plaintext + temp_len, &temp_len) <= 0) + { + ret = SGX_ERROR_MAC_MISMATCH; + goto out; + } + + ret = SGX_SUCCESS; + +out: + EVP_CIPHER_CTX_free(pctx); + return ret; +} + +// use the g_domain_key to decrypt the cmk and get it plaintext +sgx_status_t ehsm_parse_keyblob(uint8_t *plaintext, + sgx_aes_gcm_data_ex_t *keyblob_data, + uint8_t *domainkey) +{ + if (NULL == keyblob_data || NULL == plaintext) + return SGX_ERROR_INVALID_PARAMETER; + + sgx_status_t ret = aes_gcm_decrypt(domainkey, + plaintext, EVP_aes_256_gcm(), + keyblob_data->payload, + keyblob_data->ciphertext_size, + NULL, + 0, + keyblob_data->iv, + SGX_AESGCM_IV_SIZE, + keyblob_data->mac, + SGX_AESGCM_MAC_SIZE); + + if (SGX_SUCCESS != ret) + log_e("gcm decrypting failed.\n"); + + return ret; +} + +// use the g_domain_key to encrypt the cmk and get it ciphertext +sgx_status_t ehsm_create_keyblob(uint8_t *plaintext, + uint32_t plaintext_size, + sgx_aes_gcm_data_ex_t *keyblob_data, + uint8_t *domainkey) +{ + if (keyblob_data == NULL || plaintext == NULL) + return SGX_ERROR_INVALID_PARAMETER; + + sgx_status_t ret = sgx_read_rand(keyblob_data->iv, sizeof(keyblob_data->iv)); + if (ret != SGX_SUCCESS) + { + log_d("error generating iv.\n"); + return ret; + } + + ret = aes_gcm_encrypt(domainkey, + keyblob_data->payload, EVP_aes_256_gcm(), + plaintext, plaintext_size, + NULL, 0, + keyblob_data->iv, SGX_AESGCM_IV_SIZE, + keyblob_data->mac, SGX_AESGCM_MAC_SIZE); + + if (SGX_SUCCESS != ret) + { + log_e("gcm encrypting failed.\n"); + } + else + { + keyblob_data->ciphertext_size = plaintext_size; + keyblob_data->aad_size = 0; + } + + return ret; +} diff --git a/dkeyserver/Enclave/domainkey_factory.h b/dkeyserver/Enclave/domainkey_factory.h new file mode 100644 index 00000000..9c31f51f --- /dev/null +++ b/dkeyserver/Enclave/domainkey_factory.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2020-2022 Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "elog_utils.h" +#include "sgx_tseal.h" + +#include +#include +#include +#include + +#include "openssl/evp.h" +#include "openssl/pem.h" +#include "openssl/bio.h" +#include "openssl/err.h" + +#include "sgx_report.h" +#include "sgx_utils.h" +#include "sgx_tkey_exchange.h" + +typedef struct _aes_gcm_data_ex_t +{ + uint32_t ciphertext_size; + uint32_t aad_size; + uint8_t reserve1[8]; + uint8_t iv[SGX_AESGCM_IV_SIZE]; + uint8_t reserve2[4]; + uint8_t mac[SGX_AESGCM_MAC_SIZE]; + uint8_t payload[]; /* ciphertext + aad */ +} sgx_aes_gcm_data_ex_t; + +// use the g_domain_key to encrypt the cmk and get it ciphertext +sgx_status_t ehsm_parse_keyblob(uint8_t *plaintext, + sgx_aes_gcm_data_ex_t *keyblob_data, + uint8_t *domainkey); + +// use the g_domain_key to decrypt the cmk and get it plaintext +sgx_status_t ehsm_create_keyblob(uint8_t *plaintext, uint32_t plaintext_size, + sgx_aes_gcm_data_ex_t *keyblob_data, uint8_t *domainkey); + +bool ehsm_get_symmetric_key_size(ehsm_keyspec_t key_spec, uint32_t &key_size); + +uint32_t ehsm_get_gcm_ciphertext_size(const sgx_aes_gcm_data_ex_t *gcm_data); \ No newline at end of file diff --git a/dkeyserver/Enclave/enclave.config.xml b/dkeyserver/Enclave/enclave.config.xml index 12b5df99..5f7ed09b 100644 --- a/dkeyserver/Enclave/enclave.config.xml +++ b/dkeyserver/Enclave/enclave.config.xml @@ -3,7 +3,7 @@ 0 0x40000 0xA00000 - 8 + 32 1 0 0 diff --git a/dkeyserver/Enclave/enclave.cpp b/dkeyserver/Enclave/enclave.cpp index ff50790f..bae03793 100644 --- a/dkeyserver/Enclave/enclave.cpp +++ b/dkeyserver/Enclave/enclave.cpp @@ -42,27 +42,57 @@ #include #include #include +#include + +#include +#include +#include + #include "openssl/evp.h" #include "openssl/ssl.h" +#include "openssl/sha.h" #include "sys/socket.h" #include "netinet/in.h" #include "byteswap.h" #include "openssl_utility.h" #include "datatypes.h" +#include "domainkey_factory.h" -#define CLIENT_MAX_NUM 20 #define ROLE_WORKER "worker" #define ROLE_ROOT "root" +std::string g_server_name; +uint16_t g_server_port; +std::string g_server_role; + +SSL *g_ssl_session = nullptr; +int g_socket_fd = -1; + +dkey_server_domainkey g_domainkey; + +uint64_t g_nextRotationTime = 0; +int g_period = -1; + +size_t g_password = 0; +bool g_ready_flag = false; + +typedef struct g_sessionPoolStruct +{ + SSL *ssl_session; + int errorCnt; +} g_sessionPoolStruct; + +g_sessionPoolStruct g_client_session[CONCURRENT_MAX] = {{NULL, 0}}; + typedef struct SocketMsgHandlerParam { - int client_socket_fd; + int socket_fd; SSL_CTX *ssl_server_ctx; SSL *ssl_session; uint8_t *domainkey; } SocketMsgHandlerParam; -void log_printf(uint32_t log_level, const char* filename, uint32_t line, const char *fmt, ...) +void log_printf(uint32_t log_level, const char *filename, uint32_t line, const char *fmt, ...) { char buf[BUFSIZ] = {'\0'}; va_list ap; @@ -72,11 +102,36 @@ void log_printf(uint32_t log_level, const char* filename, uint32_t line, const c ocall_print_string(log_level, buf, filename, line); } +int update_couch_db(int db_type, int key_type) +{ + int db_size; + ocall_load_couchdb(&db_size, db_type); + log_i("db_size=%d", db_size); + + for (int i = 0; i < db_size; i++) + { + int ret; + + uint32_t dk_cipher_len = sgx_calc_sealed_data_size(0, SGX_DOMAIN_KEY_SIZE); + uint8_t dk_cipher[dk_cipher_len] = {0}; + + ocall_update_CMK(&ret, dk_cipher, dk_cipher_len, g_domainkey.dk_hash, DOMAINKEY_HASH_SIZE, key_type); + if (ret == -1) + return -1; + } + return 0; +} + void t_time(time_t *current_t) { ocall_get_current_time((uint64_t *)current_t); } +void t_sleep(int second) +{ + ocall_sleep(second); +} + uint32_t htonl(uint32_t n) { union @@ -177,133 +232,424 @@ int setsockopt( return ret; } -int verify_callback(int preverify_ok, X509_STORE_CTX *ctx); - -static void *SocketMsgHandler(void *arg) +int create_listener_socket(int port, int &server_socket) { - if (arg == NULL) - { - log_d(TLS_SERVER - "arg cannot be obtained\n"); - return ((void *)0); - } - SSL *ssl_session = nullptr; - SocketMsgHandlerParam handler_ctx = *(SocketMsgHandlerParam *)arg; - int test_error = 1; int ret = -1; - // create a new SSL structure for a connection - if ((ssl_session = SSL_new(handler_ctx.ssl_server_ctx)) == nullptr) + const int reuse = 1; + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (server_socket < 0) { - log_d(TLS_SERVER - "Unable to create a new SSL connection state object\n"); + log_d(TLS_SERVER "socket creation failed\n"); goto exit; } - if (SSL_set_fd(ssl_session, handler_ctx.client_socket_fd) != 1) + if (setsockopt( + server_socket, + SOL_SOCKET, + SO_REUSEADDR, + (const void *)&reuse, + sizeof(reuse)) < 0) { - log_d(TLS_SERVER - "SSL set fd failed\n"); + log_d(TLS_SERVER "setsocket failed \n"); goto exit; } - // wait for a TLS/SSL client to initiate a TLS/SSL handshake - log_i(TLS_SERVER "initiating a passive connect SSL_accept\n"); - test_error = SSL_accept(ssl_session); - if (test_error <= 0) + if (bind(server_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - log_d(TLS_SERVER " SSL handshake failed, error(%d)(%d)\n", - test_error, SSL_get_error(ssl_session, test_error)); + log_d(TLS_SERVER "Unable to bind socket to the port\n"); goto exit; } - log_d(TLS_SERVER "<---- Read from client:\n"); - if (read_from_session_peer( - ssl_session, CLIENT_PAYLOAD, CLIENT_PAYLOAD_SIZE) != 0) + if (listen(server_socket, CLIENT_MAX_NUM) < 0) { - log_d(TLS_SERVER " Read from client failed\n"); + log_d(TLS_SERVER "Unable to open socket for listening\n"); goto exit; } + ret = 0; +exit: + return ret; +} + +int verify_callback(int preverify_ok, X509_STORE_CTX *ctx); + +std::mutex mtx; + +static bool RecvAll(SSL *ssl_session, void *data, int32_t data_size) +{ + char *data_ptr = (char *)data; + int32_t bytes_recv; + int error = 0; + + while (true) + { + // mtx.lock(); + + bytes_recv = SSL_read(ssl_session, data_ptr, data_size); + + // log_i("bytes_recv=%d\n", bytes_recv); + // mtx.unlock(); + + if (bytes_recv <= 0) + { + error = SSL_get_error(ssl_session, bytes_recv); + if (error == SSL_ERROR_WANT_READ) + { + log_i("SSL_ERROR_WANT_READ"); + continue; + } + + // log_d(TLS_SERVER "Failed! SSL_read returned error=%d\n", error); + return false; + } + + // t_sleep(1); + // log_d(TLS_SERVER "%d bytes recv\n", bytes_recv); + return true; + } + + return true; +} + +static bool SendAll(SSL *ssl_session, const void *data, int32_t data_size) +{ + // mtx.lock(); + + const char *data_ptr = (const char *)data; + int32_t bytes_sent; + int error = 0; - for (unsigned long int i = 0; i < SGX_DOMAIN_KEY_SIZE; i++) + while (true) { - log_d("domain_key[%u]=%2u", i, handler_ctx.domainkey[i]); + bytes_sent = SSL_write(ssl_session, data_ptr, data_size); + + if (bytes_sent <= 0) + { + error = SSL_get_error(ssl_session, bytes_sent); + if (error == SSL_ERROR_WANT_WRITE) + { + continue; + } + else + { + // mtx.unlock(); + + return false; + } + } + else + { + break; + } } - log_d(TLS_SERVER "<---- Write to client:\n"); - if (write_to_session_peer( - ssl_session, handler_ctx.domainkey, SGX_DOMAIN_KEY_SIZE) != 0) + // mtx.unlock(); + + return true; +} + +int SocketDispatchCmd(_request_header_t *req, SSL *ssl_session) +{ + //parse the command sent by the client + int bytes_written = 0; + _response_header_t *server_res = NULL; + + if (req->password != g_password && req->cmd != GET_DOMAINKEY && g_password != 0) { - log_d(TLS_SERVER " Write to client failed\n"); - goto exit; + if (!SendAll(ssl_session, PASSWORD_WRONG, PASSWORD_WRONG_SIZE)) + { + log_d("failed to send PASSWORD_WRONG datas\n"); + } + return -1; } - if (handler_ctx.client_socket_fd > 0) + + switch (req->cmd) { - ocall_close(&ret, handler_ctx.client_socket_fd); - if (ret != 0) + case GET_DOMAINKEY: + { + //send domainkey to the client + log_d(TLS_SERVER "<---- Write domainkey to client:\n"); + + server_res = (_response_header_t *)malloc(sizeof(_response_header_t)); + memcpy_s(server_res->domainKey, SGX_DOMAIN_KEY_SIZE, g_domainkey.domainkey, SGX_DOMAIN_KEY_SIZE); + server_res->type = MSG_DOMAINKEY; + + if (!SendAll(ssl_session, server_res, sizeof(_response_header_t))) { - log_d(TLS_SERVER "OCALL: error closing client socket before starting a new TLS session.\n"); - goto exit; + log_d("failed to send domainkey data\n"); + SAFE_FREE(server_res); + return -1; } + SAFE_FREE(server_res); + return 0; + } + case STOP_AUTO_ROTATION: + { + g_period = -1; + g_nextRotationTime = g_period; + if (!SendAll(ssl_session, STOP_AUTO_ROTATION_MSG, STOP_AUTO_ROTATION_MSG_SIZE)) + { + log_d("failed to send STOP_AUTO_ROTATION_MSG datas\n"); + return -1; + } + return 0; + } + case START_ROTATION: + { + log_i("START_ROTATION!"); + t_time((time_t *)&g_nextRotationTime); + if (!SendAll(ssl_session, START_ROTATION_MSG, START_ROTATION_MSG_SIZE)) + { + log_d("failed to send START_ROTATION_MSG datas\n"); + return -1; + } + return 0; + } + case SET_PERIOD: + { + std::string set_period_msg; + uint32_t set_period_msg_size = 0; + if (req->period <= 30 || req->period >= 365) + { + log_d("the period must greater than 30 days and less than 365 days"); + set_period_msg = SET_PERIOD_FAILED_MSG; + set_period_msg_size = SET_PERIOD_FAILED_MSG_SIZE; + } + else + { + g_period = req->period; + g_nextRotationTime = g_period * 24 * 60 * 60 + g_domainkey.createTime; + set_period_msg = SET_PERIOD_SUCCESS_MSG; + set_period_msg_size = SET_PERIOD_SUCCESS_MSG_SIZE; + } + if (!SendAll(ssl_session, set_period_msg.c_str(), set_period_msg_size)) + { + log_d("failed to send SET_PERIOD_MSG datas\n"); + return -1; + } + return 0; + } + case GET_PERIOD: + { + std::string get_period_msg = "The period time is " + std::to_string(g_period) + " days."; + if (!SendAll(ssl_session, get_period_msg.c_str(), get_period_msg.size() + 1)) + { + log_d("failed to send get_period_msg datas\n"); + return -1; + } + return 0; + } + case GET_NEXT_ROTATION_DATETIME: + { + std::string get_next_rotation_datetime_msg = "The next retation time is " + + std::to_string(g_nextRotationTime) + "."; + if (!SendAll(ssl_session, get_next_rotation_datetime_msg.c_str(), get_next_rotation_datetime_msg.size() + 1)) + { + log_d("failed to send get_next_rotation_datetime_msg datas\n"); + return -1; + } + return 0; + } + case UPDATE_CMK: + { + uint32_t dk_cipher_len = sgx_calc_sealed_data_size(0, SGX_DOMAIN_KEY_SIZE); + uint8_t dk_cipher[dk_cipher_len] = {0}; + std::string update_cmk_msg; + + int ret; + ret = update_couch_db(CMK_INFO, KEYBLOB); + if (ret == -1) + { + update_cmk_msg = "Update CMK failed"; + } + + ret = update_couch_db(USER_INFO, CMK); + if (ret == -1) + { + update_cmk_msg = "Update CMK failed"; + } + + ret = update_couch_db(USER_INFO, SM_DEFAULT_CMK); + if (ret == -1) + { + update_cmk_msg = "Update CMK failed"; + } + + if (ret == 1) + { + update_cmk_msg = "Update CMK done"; + log_i("UPDATE_CMK ok"); + } + + if (!SendAll(ssl_session, update_cmk_msg.c_str(), strlen(update_cmk_msg.c_str()) + 1)) + log_e("failed to send update_cmk_msg datas\n"); + } + default: + return -1; } -exit: - SSL_free(ssl_session); - log_i("write domainkey to clent success\n"); - return ((void *)0); } -int create_listener_socket(int port, int &server_socket) +static void *Server_heart(void *args) { - int ret = -1; - const int reuse = 1; - struct sockaddr_in addr; - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_ANY); + (void)args; + log_d("in Server_heart"); - server_socket = socket(AF_INET, SOCK_STREAM, 0); - if (server_socket < 0) + int bytes_written = 0; + int test_error = 0; + + _response_header_t *server_res = NULL; + server_res = (_response_header_t *)malloc(sizeof(_response_header_t)); + server_res->type = MSG_HEARTBEAT; + //session in the pool is connected every 10 seconds. + //If a session connection fails for three times, the session is deleted + while (true) { - log_d(TLS_SERVER "socket creation failed\n"); - goto exit; + t_sleep(10); + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_session[i].ssl_session != NULL) + { + if (g_client_session[i].errorCnt < MAX_RECONNECT) + { + log_i("Server->client heart start index = %d", i); + int r = SendAll(g_client_session[i].ssl_session, server_res, sizeof(_response_header_t)); + if (!r) + g_client_session[i].errorCnt++; + else + g_client_session[i].errorCnt = 0; + continue; + } + + int client_fd = SSL_get_fd(g_client_session[i].ssl_session); + if (client_fd > 0) + { + int closeRet; + ocall_close(&closeRet, client_fd); + } + + SSL_shutdown(g_client_session[i].ssl_session); + SSL_free(g_client_session[i].ssl_session); + + g_client_session[i].ssl_session = nullptr; + g_client_session[i].errorCnt = 0; + + log_i("remove session index=%d", i); + } + } } +} - if (setsockopt( - server_socket, - SOL_SOCKET, - SO_REUSEADDR, - (const void *)&reuse, - sizeof(reuse)) < 0) +static void *SocketMsgHandler(void *arg) +{ + if (arg == NULL) { - log_d(TLS_SERVER "setsocket failed \n"); + log_d(TLS_SERVER + "arg cannot be obtained\n"); + return ((void *)0); + } + + int index = -1; + _request_header_t *client_req = NULL; + client_req = (_request_header_t *)malloc(sizeof(_request_header_t)); + + // add new connection to connection pool if it's not full + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_session[i].ssl_session == NULL) + { + index = i; + log_i("create session index=%d", index); + break; + } + } + if (index < 0) + { + log_d(TLS_SERVER "The connection pool was full.\n"); + return ((void *)0); + } + + SocketMsgHandlerParam handler_ctx = *(SocketMsgHandlerParam *)arg; + int test_error = 1; + + // create a new SSL structure for a connection + if ((g_client_session[index].ssl_session = SSL_new(handler_ctx.ssl_server_ctx)) == nullptr) + { + log_d(TLS_SERVER + "Unable to create a new SSL connection state object\n"); goto exit; } - if (bind(server_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) + if (SSL_set_fd(g_client_session[index].ssl_session, handler_ctx.socket_fd) != 1) { - log_d(TLS_SERVER "Unable to bind socket to the port\n"); + log_d(TLS_SERVER + "SSL set fd failed\n"); goto exit; } - if (listen(server_socket, CLIENT_MAX_NUM) < 0) + // wait for a TLS/SSL client to initiate a TLS/SSL handshake + log_i(TLS_SERVER "initiating a passive connect SSL_accept\n"); + test_error = SSL_accept(g_client_session[index].ssl_session); + if (test_error <= 0) { - log_d(TLS_SERVER "Unable to open socket for listening\n"); + log_d(TLS_SERVER " SSL handshake failed, error(%d)(%d)\n", + test_error, SSL_get_error(g_client_session[index].ssl_session, test_error)); goto exit; } - ret = 0; + + //Receive messages from the client + while (true) + { + if (g_client_session[index].ssl_session == NULL) + continue; + + // log_d(TLS_SERVER "<---- Read cmd from client:\n"); + + memset(client_req, 0, sizeof(client_req)); + + if (!RecvAll(g_client_session[index].ssl_session, client_req, sizeof(_request_header_t))) + { + // log_d("failed to get res data\n"); + t_sleep(1); + continue; + } + + // log_i("\ntype=%d\n", client_req->cmd); + + test_error = SocketDispatchCmd(client_req, g_client_session[index].ssl_session); + // t_sleep(20); + if (test_error < 0) + { + // log_d("parse cmd failed\n"); + } + } + exit: - return ret; + if (client_req) + SAFE_FREE(client_req); + return ((void *)0); } int handle_communication_until_done( int &server_socket_fd, int &client_socket_fd, - SSL_CTX *&ssl_server_ctx, - uint8_t *domainkey) + SSL_CTX *&ssl_server_ctx) { int ret = -1; // waiting_for_connection_request: struct sockaddr_in addr; uint len = sizeof(addr); + pthread_t heart_thread; + + //start the server heartbeat thread + if (pthread_create(&heart_thread, NULL, Server_heart, NULL) < 0) + { + log_d("could not create thread\n"); + goto exit; + } // reset ssl_session and client_socket_fd to prepare for the new TLS // connection @@ -313,6 +659,16 @@ int handle_communication_until_done( waiting_for_connection_request: client_socket_fd = accept(server_socket_fd, (struct sockaddr *)&addr, &len); + + if (g_ready_flag == false) + { + if (client_socket_fd != -1) + { + int closeRet; + ocall_close(&closeRet, client_socket_fd); + } + goto waiting_for_connection_request; + } if (client_socket_fd < 0) { @@ -321,11 +677,11 @@ int handle_communication_until_done( } SocketMsgHandlerParam param; - param.client_socket_fd = client_socket_fd; + param.socket_fd = client_socket_fd; param.ssl_server_ctx = ssl_server_ctx; - param.domainkey = domainkey; pthread_t sniffer_thread; + //start the thread that receive and parse command if (pthread_create(&sniffer_thread, NULL, SocketMsgHandler, (void *)¶m) < 0) { log_d("could not create thread\n"); @@ -375,7 +731,6 @@ int create_socket(const char *server_name, uint16_t server_port) goto out; } - dest_sock.sin_family = AF_INET; dest_sock.sin_port = htons(server_port); dest_sock.sin_addr.s_addr = inet_addr(server_name); @@ -402,28 +757,36 @@ int create_socket(const char *server_name, uint16_t server_port) return sockfd; } -sgx_status_t get_domainkey_from_target(uint8_t *domain_key, - const char *target_server_name, - uint16_t target_server_port) +sgx_status_t store_domain_key(uint8_t *domain_key) { sgx_status_t ret = SGX_ERROR_UNEXPECTED; + uint32_t dk_cipher_len = sgx_calc_sealed_data_size(0, SGX_DOMAIN_KEY_SIZE); + uint8_t dk_cipher[dk_cipher_len] = {0}; + time_t current_time; + int retstatus; - if (target_server_name[0] == '\0') - return ret; + SHA256(domain_key, SGX_DOMAIN_KEY_SIZE, g_domainkey.dk_hash); - SSL_CTX *ssl_client_ctx = nullptr; - SSL *ssl_session = nullptr; + ret = sgx_seal_data(0, NULL, SGX_DOMAIN_KEY_SIZE, domain_key, dk_cipher_len, (sgx_sealed_data_t *)dk_cipher); + if (ret != SGX_SUCCESS) + return SGX_ERROR_UNEXPECTED; + + ret = ocall_store_domain_key(&retstatus, dk_cipher, dk_cipher_len, g_domainkey.dk_hash, DOMAINKEY_HASH_SIZE); + if (ret != SGX_SUCCESS || retstatus != 0) + return SGX_ERROR_UNEXPECTED; + t_time((time_t *)&g_domainkey.createTime); + + return ret; +} + +int generate_ssl_session() +{ + SSL_CTX *ssl_client_ctx = nullptr; X509 *cert = nullptr; EVP_PKEY *pkey = nullptr; SSL_CONF_CTX *ssl_confctx = SSL_CONF_CTX_new(); - - int client_socket = -1; - int error = 0; - unsigned char buf[200]; - int len = 0; - int bytes_written = 0; - int bytes_read = 0; + int ret = -1; if ((ssl_client_ctx = SSL_CTX_new(TLS_client_method())) == nullptr) { @@ -446,15 +809,70 @@ sgx_status_t get_domainkey_from_target(uint8_t *domain_key, goto out; } - if ((ssl_session = SSL_new(ssl_client_ctx)) == nullptr) + if ((g_ssl_session = SSL_new(ssl_client_ctx)) == nullptr) { - log_e(TLS_SERVER "Unable to create a new SSL connection state object\n"); + log_d(TLS_SERVER "Unable to create a new SSL connection state object\n"); + goto out; + } + + ret = 0; + +out: + if (cert) + X509_free(cert); + + if (pkey) + EVP_PKEY_free(pkey); + + if (ssl_client_ctx) + SSL_CTX_free(ssl_client_ctx); + + if (ssl_confctx) + SSL_CONF_CTX_free(ssl_confctx); + + return ret; +} + +//send the getdomainkey command to the server +static int req_domainkey(SSL *ssl_session) +{ + if (ssl_session == NULL) + return -1; + + _request_header_t *client_req = NULL; + + log_d(TLS_SERVER "-----> Write getdomainkey cmd to server:\n"); + + client_req = (_request_header_t *)malloc(sizeof(_request_header_t)); + client_req->cmd = GET_DOMAINKEY; + + if (!SendAll(ssl_session, client_req, sizeof(_request_header_t))) + { + log_d("failed to send req data\n"); + SAFE_FREE(client_req); + return -1; + } + + SAFE_FREE(client_req); + return 0; +} + +static int connect_target_server(const char *target_server_name, + uint16_t target_server_port) +{ + int error = 0; + int ret = SGX_ERROR_UNEXPECTED; + + if (generate_ssl_session() < 0) + { + log_d(TLS_SERVER "generate ssl session in get_domainkey_from_target failed\n"); goto out; } log_d(TLS_SERVER "New ssl connection getting created\n"); - client_socket = create_socket(target_server_name, target_server_port); - if (client_socket == -1) + g_socket_fd = create_socket(target_server_name, target_server_port); + + if (g_socket_fd == -1) { log_e( TLS_SERVER "Create a socket and initiate a TCP connect to target server: %s:%d " @@ -466,116 +884,288 @@ sgx_status_t get_domainkey_from_target(uint8_t *domain_key, } // set up ssl socket and initiate TLS connection with TLS target server - if (SSL_set_fd(ssl_session, client_socket) != 1) + if (SSL_set_fd(g_ssl_session, g_socket_fd) != 1) { log_e(TLS_SERVER "Ssl set fd error.\n"); goto out; } - if ((error = SSL_connect(ssl_session)) != 1) + if ((error = SSL_connect(g_ssl_session)) != 1) { log_e(TLS_SERVER "Error: Could not establish a TLS session ret2=%d " "SSL_get_error()=%d\n", error, - SSL_get_error(ssl_session, error)); + SSL_get_error(g_ssl_session, error)); goto out; } + log_d(TLS_SERVER "successfully established TLS channel:%s\n", - SSL_get_version(ssl_session)); + SSL_get_version(g_ssl_session)); - // start the communication - // Write an GET request to the target server - log_d(TLS_SERVER "-----> Write to server:\n"); - len = snprintf((char *)buf, sizeof(buf) - 1, CLIENT_PAYLOAD); + ret = SGX_SUCCESS; +out: + if (ret != SGX_SUCCESS) + g_ready_flag = false; + log_i("ready flag change to %s\n", g_ready_flag == true ? "true" : "false"); + return ret; +} - while ((bytes_written = SSL_write(ssl_session, buf, (size_t)len)) <= 0) - { - error = SSL_get_error(ssl_session, bytes_written); - if (error == SSL_ERROR_WANT_WRITE) - continue; - log_e(TLS_SERVER "Failed! SSL_write returned %d\n", error); - goto out; - } +static void *ClientSocketMsgHandler(void *args) +{ + (void)args; - log_d(TLS_SERVER "%d bytes written\n", bytes_written); + _response_header_t *server_res = NULL; + server_res = (_response_header_t *)malloc(sizeof(_response_header_t)); - // Read the HTTP response from target server - log_d(TLS_SERVER "<---- Read from server:\n"); - do + while (true) { - len = sizeof(buf) - 1; - memset_s(buf, sizeof(buf), 0, sizeof(buf)); - bytes_read = SSL_read(ssl_session, buf, (size_t)len); + if (g_ssl_session == nullptr || g_socket_fd == -1) + { + t_sleep(1); + continue; + } - if (bytes_read <= 0) + memset(server_res, 0, sizeof(_response_header_t)); + //receives messages from the server + if (!RecvAll(g_ssl_session, server_res, sizeof(_response_header_t))) { - int error = SSL_get_error(ssl_session, bytes_read); - if (error == SSL_ERROR_WANT_READ) - continue; + log_d("failed to get res data\n"); - log_e(TLS_SERVER "Failed! SSL_read returned error=%d\n", error); - goto out; + continue; } - log_d(TLS_SERVER " %d bytes read\n", bytes_read); + log_i("server_res->type=%d\n", server_res->type); - if (bytes_read != SGX_DOMAIN_KEY_SIZE) + switch (server_res->type) { - log_e( - TLS_SERVER "ERROR: expected reading %lu bytes but only " - "received %d bytes\n", - SGX_DOMAIN_KEY_SIZE, - bytes_read); - goto out; + case MSG_DOMAINKEY: + log_i("in msg_domainkey type"); + memcpy_s(g_domainkey.domainkey, SGX_DOMAIN_KEY_SIZE, server_res->domainKey, SGX_DOMAIN_KEY_SIZE); + + for (unsigned long int i = 0; i < SGX_DOMAIN_KEY_SIZE; i++) + { + log_d("new domain_key from root[%u]=%2u\n", i, g_domainkey.domainkey[i]); + } + + if (store_domain_key(g_domainkey.domainkey) != SGX_SUCCESS) + { + log_d("store_domain_key failed\n"); + continue; + } + + log_d(TLS_SERVER "new domainkey received succeed:\n"); + + memset(server_res, 0, sizeof(_response_header_t)); + server_res->type = MSG_ROTATE_END; + + g_ready_flag = true; + log_i("ready flag change to %s\n", g_ready_flag == true ? "true" : "false"); + + //Send MSG_ROTATE_END to all connected clients + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_session[i].ssl_session != NULL) + { + if (!SendAll(g_client_session[i].ssl_session, + server_res, + sizeof(_response_header_t))) + { + log_d("failed to send ROTATION_START datas\n"); + continue; + } + } + } + break; + + case MSG_ROTATE_START: + g_ready_flag = false; + log_i("ready flag change to %s\n", g_ready_flag == true ? "true" : "false"); + + //Send MSG_ROTATE_START to all connected clients + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_session[i].ssl_session != NULL) + { + if (!SendAll(g_client_session[i].ssl_session, + server_res, + sizeof(_response_header_t))) + { + log_d("failed to send ROTATION_START datas\n"); + continue; + } + } + } + break; + + case MSG_ROTATE_END: + if (req_domainkey(g_ssl_session) < 0) + { + log_d("send get_domainkey cmd failed\n"); + } + + break; + + default: + break; } - else + + //root server only needs to get the domainkey once + if (strncmp(g_server_role.c_str(), ROLE_ROOT, strlen(g_server_role.c_str())) == 0 && + server_res->type == MSG_DOMAINKEY) { - memcpy_s(domain_key, SGX_DOMAIN_KEY_SIZE, buf, SGX_DOMAIN_KEY_SIZE); - memset_s(buf, SGX_DOMAIN_KEY_SIZE, 0, SGX_DOMAIN_KEY_SIZE); - log_i(TLS_SERVER "domainkey received succeed:\n"); + if (g_socket_fd != -1) + { + int closeRet; + ocall_close(&closeRet, g_socket_fd); + } + + if (g_ssl_session) + { + SSL_shutdown(g_ssl_session); + SSL_free(g_ssl_session); + } break; } - } while (1); + } + + SAFE_FREE(server_res); + + return ((void *)0); +} + +static void *Client_Heart(void *args) +{ + (void)args; + + int len = 0; + int error = 0; + int bytes_written = 0; + int numberOfErrors = 0; + + _response_header_t *server_res = NULL; + server_res = (_response_header_t *)malloc(sizeof(_response_header_t)); + server_res->type = MSG_HEARTBEAT; - for (unsigned long int i = 0; i < SGX_DOMAIN_KEY_SIZE; i++) + //reconnect after three failures + while (true) { - log_d("domain_key[%u]=%2u", i, domain_key[i]); + if (g_ssl_session == nullptr || g_socket_fd == -1) + { + t_sleep(1); + continue; + } + + while (numberOfErrors <= MAX_RECONNECT) + { + log_i("client->server heart start"); + if (!SendAll(g_ssl_session, server_res, sizeof(_response_header_t))) + numberOfErrors++; + else + numberOfErrors = 0; + log_i("client->server heart end"); + t_sleep(10); + } + while (true) + { + // Empty g_socket_fd and g_ssl_session + if (g_socket_fd != -1) + { + int closeRet; + ocall_close(&closeRet, g_socket_fd); + if (closeRet != 0) + { + log_d(TLS_CLIENT "OCALL: error close socket\n"); + continue; + } + } + if (g_ssl_session) + { + SSL_shutdown(g_ssl_session); + SSL_free(g_ssl_session); + } + // Reconnect to the target server + if (connect_target_server(g_server_name.c_str(), g_server_port) < 0) + { + log_d(TLS_SERVER "connect to target failed\n"); + continue; + } + numberOfErrors = 0; + if (req_domainkey(g_ssl_session) < 0) + { + log_d("send get_domainkey cmd failed\n"); + continue; + } + break; + } } + return ((void *)0); +} - ret = SGX_SUCCESS; +sgx_status_t get_domainkey_from_target(const char *target_server_name, + uint16_t target_server_port) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; -out: + if (target_server_name[0] == '\0') + return ret; + + pthread_t sniffer_thread; + pthread_t heart_thread; + + _response_header_t *server_res = NULL; - if (client_socket != -1) + if (connect_target_server(target_server_name, target_server_port) < 0) { - int closeRet; - ocall_close(&closeRet, client_socket); - if (closeRet != 0) + log_d(TLS_SERVER "connect to target failed\n"); + goto out; + } + + // start heart thread + if (strncmp(g_server_role.c_str(), ROLE_WORKER, strlen(g_server_role.c_str())) == 0) + { + log_d("create Client_Heart thread\n"); + if (pthread_create(&heart_thread, NULL, Client_Heart, NULL) < 0) { - log_e(TLS_CLIENT "OCALL: error close socket\n"); - ret = SGX_ERROR_UNEXPECTED; + log_d("could not create Client_Heart thread\n"); + goto out; } } - if (ssl_session) + // start the communication + // Read the HTTP response from target server + if (pthread_create(&sniffer_thread, NULL, ClientSocketMsgHandler, NULL) < 0) { - SSL_shutdown(ssl_session); - SSL_free(ssl_session); + log_d("could not create sniffer thread\n"); + goto out; } - if (cert) - X509_free(cert); + // Write an GET request to the target server + if (req_domainkey(g_ssl_session) < 0) + { + log_d("send get_domainkey cmd failed\n"); + goto out; + } - if (pkey) - EVP_PKEY_free(pkey); + ret = SGX_SUCCESS; - if (ssl_client_ctx) - SSL_CTX_free(ssl_client_ctx); +out: + log_d(TLS_SERVER "get domain key from target server %s\n", (ret == SGX_SUCCESS) ? "success" : "failed"); + return ret; +} - if (ssl_confctx) - SSL_CONF_CTX_free(ssl_confctx); +sgx_status_t create_new_domainkey(uint8_t *domainkey) +{ + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + ret = sgx_read_rand(domainkey, SGX_DOMAIN_KEY_SIZE); + if (ret != SGX_SUCCESS) + return ret; + + log_i("start store domain key to disk"); + ret = store_domain_key(domainkey); + if (ret != SGX_SUCCESS) + return ret; - log_i(TLS_SERVER "get domain key from target server %s\n", (ret == SGX_SUCCESS) ? "success" : "failed"); return ret; } @@ -591,7 +1181,12 @@ sgx_status_t get_domainkey_from_local(uint8_t *domain_key) uint8_t dk_cipher[dk_cipher_len] = {0}; uint8_t tmp[SGX_DOMAIN_KEY_SIZE] = {0}; - ret = ocall_read_domain_key(&retstatus, dk_cipher, dk_cipher_len); + ret = ocall_read_domain_key(&retstatus, + dk_cipher, + dk_cipher_len, + &g_domainkey.createTime, + g_domainkey.dk_hash, + DOMAINKEY_HASH_SIZE); if (ret != SGX_SUCCESS) return ret; @@ -607,7 +1202,8 @@ sgx_status_t get_domainkey_from_local(uint8_t *domain_key) else if (retstatus == -2) { log_d("enclave file does not exist.\n"); - ret = sgx_read_rand(tmp, SGX_DOMAIN_KEY_SIZE); + + ret = create_new_domainkey(tmp); if (ret != SGX_SUCCESS) return ret; } @@ -616,67 +1212,194 @@ sgx_status_t get_domainkey_from_local(uint8_t *domain_key) memcpy_s(domain_key, SGX_DOMAIN_KEY_SIZE, tmp, SGX_DOMAIN_KEY_SIZE); memset_s(tmp, SGX_DOMAIN_KEY_SIZE, 0, SGX_DOMAIN_KEY_SIZE); + g_ready_flag = true; + log_i("ready flag change to %s\n", g_ready_flag == true ? "true" : "false"); return ret; } -sgx_status_t store_domain_key(uint8_t *domain_key) +sgx_status_t sgx_get_domainkey(const char *target_server_name, + uint16_t target_server_port) { sgx_status_t ret = SGX_ERROR_UNEXPECTED; - uint32_t dk_cipher_len = sgx_calc_sealed_data_size(0, SGX_DOMAIN_KEY_SIZE); - uint8_t dk_cipher[dk_cipher_len] = {0}; - int retstatus; + int errorNumber = 0; - ret = sgx_seal_data(0, NULL, SGX_DOMAIN_KEY_SIZE, domain_key, dk_cipher_len, (sgx_sealed_data_t *)dk_cipher); - if (ret != SGX_SUCCESS) - return SGX_ERROR_UNEXPECTED; + log_i("start get domain key from target server. \n"); + ret = get_domainkey_from_target(target_server_name, target_server_port); + if (strncmp(g_server_role.c_str(), ROLE_WORKER, strlen(g_server_role.c_str())) == 0 && ret != SGX_SUCCESS) + { + log_e("worker get domain key from target failed. \n"); + return ret; + } - ret = ocall_store_domain_key(&retstatus, dk_cipher, dk_cipher_len); - if (ret != SGX_SUCCESS || retstatus != 0) - return SGX_ERROR_UNEXPECTED; + t_sleep(10); + if (g_ready_flag == false && strncmp(g_server_role.c_str(), ROLE_ROOT, strlen(g_server_role.c_str())) == 0) + { + log_i("start get domain key from disk\n"); + ret = get_domainkey_from_local(g_domainkey.domainkey); + } return ret; } -sgx_status_t sgx_get_domainkey(uint8_t *domain_key, - const char *server_role, - const char *target_server_name, - uint16_t target_server_port) +int ecall_reencrypt_cmk(uint8_t *cipher_dk, + uint32_t cipher_dk_len, + ehsm_keyblob_t *cmk, + size_t cmk_size) { - sgx_status_t ret = SGX_ERROR_UNEXPECTED; - if (domain_key == NULL) - { - log_e("domain key is null. \n"); - return ret; - } + uint8_t *key = NULL; + uint8_t tmp[SGX_DOMAIN_KEY_SIZE] = {0}; + uint32_t keyblob_size = 0; + int ret = SGX_ERROR_UNEXPECTED; - log_i("start get domain key from target server. \n"); - ret = get_domainkey_from_target(domain_key, target_server_name, target_server_port); - if (strncmp(server_role, ROLE_WORKER, strlen(server_role)) == 0 && ret != SGX_SUCCESS) + uint32_t dk_len = sgx_get_encrypt_txt_len((const sgx_sealed_data_t *)cipher_dk); + if (sgx_unseal_data((const sgx_sealed_data_t *)cipher_dk, NULL, 0, tmp, &dk_len) != SGX_SUCCESS) + return SGX_ERROR_UNEXPECTED; + + uint32_t key_size = ehsm_get_gcm_ciphertext_size((sgx_aes_gcm_data_ex_t *)cmk->keyblob); + keyblob_size = key_size; + log_i("keyblob_size=%d", key_size); + + SHA256(g_domainkey.domainkey, SGX_DOMAIN_KEY_SIZE, cmk->metadata.dk_hashcode); + + key = (uint8_t *)malloc(keyblob_size); + if (key == NULL) + return SGX_ERROR_OUT_OF_MEMORY; + + //Decrypt keyblob with the domainkey + if (SGX_SUCCESS != ehsm_parse_keyblob(key, (sgx_aes_gcm_data_ex_t *)cmk->keyblob, tmp)) { - log_i("worker get domain key from target failed. \n"); - return ret; + log_d("ehsm_parse_keyblob failed\n"); + goto out; } - - if (strncmp(server_role, ROLE_ROOT, strlen(server_role)) == 0 && ret != SGX_SUCCESS) + //Encrypt keyblob with the latest cmk + if (SGX_SUCCESS != ehsm_create_keyblob(key, keyblob_size, (sgx_aes_gcm_data_ex_t *)cmk->keyblob, g_domainkey.domainkey)) { - log_i("start get domain key from disk\n"); - ret = get_domainkey_from_local(domain_key); + log_d("ehsm_create_keyblob failed\n"); + goto out; } + ret = SGX_SUCCESS; - if (ret == SGX_SUCCESS) +out: + if (key) { - log_i("start store domain key to disk\n"); - ret = store_domain_key(domain_key); + memset_s(key, keyblob_size, 0, keyblob_size); + free(key); } return ret; } +static void *rotationTimerListener(void *arg) +{ + log_i("rotation thread start."); + log_i("g_nextRotationTime %d.", g_nextRotationTime); + time_t current_time; + int bytes_written; + int test_error; + int failed_number; + uint32_t dk_cipher_len = sgx_calc_sealed_data_size(0, SGX_DOMAIN_KEY_SIZE); + uint8_t dk_cipher[dk_cipher_len] = {0}; + int ret; + _response_header_t *server_req = (_response_header_t *)malloc(sizeof(_response_header_t)); + + while (true) + { + t_time(¤t_time); + // TODO : g_nextRotationTime always > 0 + if (current_time >= g_nextRotationTime && g_nextRotationTime > 0) + { + g_ready_flag = false; + log_i("ready flag change to %s\n", g_ready_flag == true ? "true" : "false"); + server_req->type = MSG_ROTATE_START; + // + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_session[i].ssl_session != NULL) + { + if (!SendAll(g_client_session[i].ssl_session, + server_req, + sizeof(_response_header_t))) + { + log_d("failed to send ROTATION_START datas"); + continue; + } + else + { + log_i("send to fd=%d", SSL_get_fd(g_client_session[i].ssl_session)); + } + } + } + log_i("server sleep 60s for client change flag."); + t_sleep(60); + log_i("rotation start."); + //Generate a new domainkey + uint8_t new_domainkey[SGX_DOMAIN_KEY_SIZE] = {0}; + if (create_new_domainkey(new_domainkey) != SGX_SUCCESS) + continue; + + memcpy_s(g_domainkey.domainkey, SGX_DOMAIN_KEY_SIZE, new_domainkey, SGX_DOMAIN_KEY_SIZE); + + int ret; + + ret = update_couch_db(CMK_INFO, KEYBLOB); + if (ret == -1) + { + log_i("goto out"); + goto out; + } + + ret = update_couch_db(USER_INFO, CMK); + if (ret == -1) + { + log_i("goto out"); + goto out; + } + + ret = update_couch_db(USER_INFO, SM_DEFAULT_CMK); + if (ret == -1) + { + log_i("goto out"); + goto out; + } + + log_i("UPDATE_CMK ok"); + server_req->type = MSG_ROTATE_END; + g_ready_flag = true; + log_i("ready flag change to %s\n", g_ready_flag == true ? "true" : "false"); + + for (int i = 0; i < CONCURRENT_MAX; i++) + { + if (g_client_session[i].ssl_session != NULL) + { + if (!SendAll(g_client_session[i].ssl_session, + server_req, + sizeof(_response_header_t))) + { + log_d("failed to send ROTATION_END datas\n"); + continue; + } + } + } + + out: + // always + if (g_period == -1) + g_nextRotationTime = -1; + else + g_nextRotationTime = g_domainkey.createTime + g_period * 24 * 60 * 60; + } + t_sleep(5); + } + log_i("rotation thread end."); +} + int sgx_set_up_tls_server(char *server_port, const char *server_role, const char *target_server_name, - uint16_t target_server_port) + uint16_t target_server_port, + size_t root_password, + int root_period) { int ret = -1; int server_socket_fd; @@ -688,7 +1411,18 @@ int sgx_set_up_tls_server(char *server_port, EVP_PKEY *pkey = nullptr; SSL_CONF_CTX *ssl_confctx = SSL_CONF_CTX_new(); SSL_CTX *ssl_server_ctx = nullptr; - uint8_t domain_key[SGX_DOMAIN_KEY_SIZE]; + pthread_t sniffer_thread; + + if (root_period >= 0) + { + log_d("set period to %dd\n", root_period); + g_period = root_period; + } + + g_password = root_password; + g_server_role = server_role; + g_server_name = target_server_name; + g_server_port = target_server_port; if (server_port == NULL) { @@ -723,10 +1457,7 @@ int sgx_set_up_tls_server(char *server_port, } // get domainkey - if (sgx_get_domainkey(domain_key, - server_role, - target_server_name, - target_server_port) != SGX_SUCCESS) + if (sgx_get_domainkey(target_server_name, target_server_port) != SGX_SUCCESS) { log_e("Failed to get domain key.\n"); goto exit; @@ -743,10 +1474,20 @@ int sgx_set_up_tls_server(char *server_port, goto exit; } + //root server start a rotation time listener thread + if (strncmp(g_server_role.c_str(), ROLE_ROOT, strlen(g_server_role.c_str())) == 0) + { + if (g_period < 0) + g_nextRotationTime = g_period; + else + g_nextRotationTime = g_domainkey.createTime + root_period * 24 * 60 * 60; + pthread_create(&sniffer_thread, NULL, rotationTimerListener, NULL); + } + server_port_number = (unsigned int)atoi(server_port); // convert to char* to int if (create_listener_socket(server_port_number, server_socket_fd) != 0) { - log_e(TLS_SERVER " unable to create listener socket on the server\n "); + log_e(TLS_SERVER "unable to create listener socket on the server\n "); goto exit; } @@ -754,8 +1495,7 @@ int sgx_set_up_tls_server(char *server_port, ret = handle_communication_until_done( server_socket_fd, client_socket_fd, - ssl_server_ctx, - domain_key); + ssl_server_ctx); if (ret != 0) { log_e(TLS_SERVER "server communication error %d\n", ret); @@ -763,19 +1503,6 @@ int sgx_set_up_tls_server(char *server_port, } exit: - int closeRet; - ocall_close(&closeRet, client_socket_fd); // close the socket connections - if (closeRet != 0) - { - log_e(TLS_SERVER "OCALL: error closing client socket\n"); - ret = -1; - } - ocall_close(&closeRet, server_socket_fd); - if (closeRet != 0) - { - log_e(TLS_SERVER "OCALL: error closing server socket\n"); - ret = -1; - } if (ssl_server_ctx) SSL_CTX_free(ssl_server_ctx); if (ssl_confctx) diff --git a/dkeyserver/Enclave/enclave.edl b/dkeyserver/Enclave/enclave.edl index f4807a92..7b8963e5 100644 --- a/dkeyserver/Enclave/enclave.edl +++ b/dkeyserver/Enclave/enclave.edl @@ -34,6 +34,8 @@ enclave { from "sgx_tsgxssl.edl" import *; from "sgx_pthread.edl" import *; from "sgx_ttls.edl" import *; + from "sgx_tstdc.edl" import *; + from "sgx_tswitchless.edl" import *; include "sgx_key_exchange.h" include "sgx_quote.h" @@ -44,26 +46,42 @@ enclave { include "sys/select.h" include "netdb.h" include "poll.h" + include "datatypes.h" - untrusted { + untrusted { void ocall_print_string(uint32_t log_level, [in, string] const char *str, [in, string] const char *filename, uint32_t line); int ocall_close(int fd); void ocall_get_current_time([out] uint64_t *p_current_time); - int ocall_set_dkeyserver_done(); + void ocall_sleep(int second); + + int ocall_select(int fd); + int ocall_send(int fd, [in, size = msg_size]const char* msg, uint32_t msg_size, int flag); - int ocall_read_domain_key([out, size=cipher_dk_len] uint8_t* cipher_dk, uint32_t cipher_dk_len); - int ocall_store_domain_key([in, size=cipher_dk_len] uint8_t* cipher_dk, uint32_t cipher_dk_len); + int ocall_set_dkeyserver_done(); + int ocall_update_CMK([out, size=cipher_dk_len] uint8_t* cipher_dk, uint32_t cipher_dk_len, + [in, size=dk_hash_size] uint8_t* dk_hash, uint32_t dk_hash_size, + int key_type) transition_using_threads; + int ocall_load_couchdb(int db_type); + + int ocall_read_domain_key([out, size=cipher_dk_len] uint8_t* cipher_dk, uint32_t cipher_dk_len, + [out]uint64_t* create_time, + [out, size=dk_hash_size] uint8_t* dk_hash, uint32_t dk_hash_size); + int ocall_store_domain_key([in, size=cipher_dk_len] uint8_t* cipher_dk, uint32_t cipher_dk_len, + [in, size=dk_hash_size] uint8_t* dk_hash, uint32_t dk_hash_size); + int ocall_socket (int domain, int type, int protocol) propagate_errno; int ocall_bind (int fd, [in, size=len] const struct sockaddr *addr, socklen_t len) propagate_errno; int ocall_listen (int fd, int n) propagate_errno; int ocall_accept (int fd, [out, size=addrlen_in] struct sockaddr *addr, socklen_t addrlen_in, [out] socklen_t *addrlen_out) propagate_errno; - int ocall_connect (int fd, [in, size=len] const struct sockaddr *addr, socklen_t len) propagate_errno; + int ocall_connect (int fd, [in, size=len] const struct sockaddr *addr, socklen_t len) propagate_errno; int ocall_setsockopt (int fd, int level, int optname, [in, size=optlen] const void *optval, socklen_t optlen) propagate_errno; }; - + trusted { public int sgx_set_up_tls_server([in, string] char* port, [in, string] const char* server_role, [in, string] const char* server_name, - uint16_t server_port); + uint16_t server_port, size_t root_password, int root_period); + public int ecall_reencrypt_cmk([in, size=cipher_dk_len] uint8_t* cipher_dk, uint32_t cipher_dk_len, + [in, out, size=cmk_size] ehsm_keyblob_t* cmk, size_t cmk_size) transition_using_threads; }; }; diff --git a/dkeyserver/Makefile b/dkeyserver/Makefile index 561bea7d..152a6baf 100644 --- a/dkeyserver/Makefile +++ b/dkeyserver/Makefile @@ -65,12 +65,15 @@ else App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG endif -App_Cpp_Flags := $(App_C_Flags) -std=c++11 +App_Cpp_Flags := $(App_C_Flags) -std=c++11 -g App_Link_Flags := -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) \ -lpthread \ -lsgx_dcap_quoteverify \ -ldl \ + -ljsoncpp \ + -lcurl \ -llog4cplus \ + -Wl,--whole-archive -lsgx_uswitchless -Wl,--no-whole-archive \ -lsgx_utls -lsgx_dcap_ql -lsgx_dcap_quoteverify -lcrypto\ -lra_ukey_exchange -L$(TOPDIR)/$(OUTLIB_DIR) \ -L$(OPENSSL_LIBRARY_PATH) -l$(SGXSSL_Untrusted_Library_Name) @@ -97,7 +100,8 @@ Enclave_C_Flags := \ -nostdinc -fvisibility=hidden \ -fpie -ffunction-sections \ -fdata-sections \ - $(MITIGATION_CFLAGS) + $(MITIGATION_CFLAGS) \ + -g CC_BELOW_4_9 := $(shell expr "`$(CC) -dumpversion`" \< "4.9") ifeq ($(CC_BELOW_4_9), 1) @@ -121,7 +125,7 @@ Enclave_Security_Link_Flags := -Wl,-z,relro,-z,now,-z,noexecstack Enclave_Link_Flags := $(MITIGATION_LDFLAGS) $(Enclave_Security_Link_Flags) \ $(SgxSSL_Link_Libraries) \ -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_TRUSTED_LIBRARY_PATH) \ - -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--whole-archive -lsgx_tswitchless -l$(Trts_Library_Name) -Wl,--no-whole-archive \ -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -lsgx_tcrypto -lsgx_dcap_tvl -lsgx_ttls -l$(Service_Library_Name) -lra_tkey_exchange -L$(TOPDIR)/$(OUTLIB_DIR) -Wl,--end-group \ -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ @@ -201,7 +205,7 @@ Enclave/%.o: Enclave/%.cpp Enclave/enclave_t.h @echo "CXX <= $<" $(Enclave_Name): Enclave/enclave_t.o $(Enclave_Cpp_Objects) - @$(CXX) $^ -o $@ $(Enclave_Link_Flags) + @$(CXX) $^ -o $@ $(Enclave_Link_Flags) -g @echo "LINK => $@" $(Signed_Enclave_Name): $(Enclave_Name) diff --git a/dkeyserver/dkeyrotation/App/auto_version.h b/dkeyserver/dkeyrotation/App/auto_version.h new file mode 100644 index 00000000..f987679e --- /dev/null +++ b/dkeyserver/dkeyrotation/App/auto_version.h @@ -0,0 +1,6 @@ +#ifndef EHSM_DKEYCACHE_AUTO_VERSION_H +#define EHSM_DKEYCACHE_AUTO_VERSION_H +#define EHSM_VERSION "0.3.2" +#define EHSM_DATE "2023.01.14 0:04" +#define EHSM_GIT_SHA "fd59274" +#endif //EHSM_DKEYCACHE_AUTO_VERSION_H diff --git a/dkeyserver/dkeyrotation/App/enclave_u.c b/dkeyserver/dkeyrotation/App/enclave_u.c new file mode 100644 index 00000000..7108e042 --- /dev/null +++ b/dkeyserver/dkeyrotation/App/enclave_u.c @@ -0,0 +1,443 @@ +#include "enclave_u.h" +#include + +typedef struct ms_enclave_launch_tls_client_t { + int ms_retval; + const char* ms_server_name; + size_t ms_server_name_len; + uint16_t ms_server_port; + uint32_t ms_key; + const char* ms_action; + size_t ms_action_len; +} ms_enclave_launch_tls_client_t; + +typedef struct ms_sgx_ra_get_ga_t { + sgx_status_t ms_retval; + sgx_ra_context_t ms_context; + sgx_ec256_public_t* ms_g_a; +} ms_sgx_ra_get_ga_t; + +typedef struct ms_sgx_ra_proc_msg2_trusted_t { + sgx_status_t ms_retval; + sgx_ra_context_t ms_context; + const sgx_ra_msg2_t* ms_p_msg2; + const sgx_target_info_t* ms_p_qe_target; + sgx_report_t* ms_p_report; + sgx_quote_nonce_t* ms_p_nonce; +} ms_sgx_ra_proc_msg2_trusted_t; + +typedef struct ms_sgx_ra_get_msg3_trusted_t { + sgx_status_t ms_retval; + sgx_ra_context_t ms_context; + uint32_t ms_quote_size; + sgx_report_t* ms_qe_report; + sgx_ra_msg3_t* ms_p_msg3; + uint32_t ms_msg3_size; +} ms_sgx_ra_get_msg3_trusted_t; + +typedef struct ms_ocall_printf_t { + const char* ms_str; +} ms_ocall_printf_t; + +typedef struct ms_ocall_close_t { + int ms_retval; + int ms_fd; +} ms_ocall_close_t; + +typedef struct ms_ocall_sleep_t { + int ms_sec; +} ms_ocall_sleep_t; + +typedef struct ms_ocall_get_current_time_t { + uint64_t* ms_p_current_time; +} ms_ocall_get_current_time_t; + +typedef struct ms_ocall_socket_t { + int ms_retval; + int ocall_errno; + int ms_domain; + int ms_type; + int ms_protocol; +} ms_ocall_socket_t; + +typedef struct ms_ocall_connect_t { + int ms_retval; + int ocall_errno; + int ms_fd; + const struct sockaddr* ms_addr; + socklen_t ms_len; +} ms_ocall_connect_t; + +typedef struct ms_sgx_oc_cpuidex_t { + int* ms_cpuinfo; + int ms_leaf; + int ms_subleaf; +} ms_sgx_oc_cpuidex_t; + +typedef struct ms_sgx_thread_wait_untrusted_event_ocall_t { + int ms_retval; + const void* ms_self; +} ms_sgx_thread_wait_untrusted_event_ocall_t; + +typedef struct ms_sgx_thread_set_untrusted_event_ocall_t { + int ms_retval; + const void* ms_waiter; +} ms_sgx_thread_set_untrusted_event_ocall_t; + +typedef struct ms_sgx_thread_setwait_untrusted_events_ocall_t { + int ms_retval; + const void* ms_waiter; + const void* ms_self; +} ms_sgx_thread_setwait_untrusted_events_ocall_t; + +typedef struct ms_sgx_thread_set_multiple_untrusted_events_ocall_t { + int ms_retval; + const void** ms_waiters; + size_t ms_total; +} ms_sgx_thread_set_multiple_untrusted_events_ocall_t; + +typedef struct ms_u_sgxssl_ftime_t { + void* ms_timeptr; + uint32_t ms_timeb_len; +} ms_u_sgxssl_ftime_t; + +typedef struct ms_u_sgxssl_write_t { + size_t ms_retval; + int ms_fd; + const void* ms_buf; + size_t ms_n; +} ms_u_sgxssl_write_t; + +typedef struct ms_u_sgxssl_read_t { + size_t ms_retval; + int ms_fd; + void* ms_buf; + size_t ms_count; +} ms_u_sgxssl_read_t; + +typedef struct ms_u_sgxssl_close_t { + int ms_retval; + int ms_fd; +} ms_u_sgxssl_close_t; + +typedef struct ms_sgx_tls_get_qe_target_info_ocall_t { + quote3_error_t ms_retval; + sgx_target_info_t* ms_p_target_info; + size_t ms_target_info_size; +} ms_sgx_tls_get_qe_target_info_ocall_t; + +typedef struct ms_sgx_tls_get_quote_size_ocall_t { + quote3_error_t ms_retval; + uint32_t* ms_p_quote_size; +} ms_sgx_tls_get_quote_size_ocall_t; + +typedef struct ms_sgx_tls_get_quote_ocall_t { + quote3_error_t ms_retval; + sgx_report_t* ms_p_report; + size_t ms_report_size; + uint8_t* ms_p_quote; + uint32_t ms_quote_size; +} ms_sgx_tls_get_quote_ocall_t; + +typedef struct ms_sgx_tls_get_supplemental_data_size_ocall_t { + quote3_error_t ms_retval; + uint32_t* ms_p_supplemental_data_size; +} ms_sgx_tls_get_supplemental_data_size_ocall_t; + +typedef struct ms_sgx_tls_verify_quote_ocall_t { + quote3_error_t ms_retval; + const uint8_t* ms_p_quote; + uint32_t ms_quote_size; + time_t ms_expiration_check_date; + sgx_ql_qv_result_t* ms_p_quote_verification_result; + sgx_ql_qe_report_info_t* ms_p_qve_report_info; + size_t ms_qve_report_info_size; + uint8_t* ms_p_supplemental_data; + uint32_t ms_supplemental_data_size; +} ms_sgx_tls_verify_quote_ocall_t; + +typedef struct ms_pthread_wait_timeout_ocall_t { + int ms_retval; + unsigned long long ms_waiter; + unsigned long long ms_timeout; +} ms_pthread_wait_timeout_ocall_t; + +typedef struct ms_pthread_create_ocall_t { + int ms_retval; + unsigned long long ms_self; +} ms_pthread_create_ocall_t; + +typedef struct ms_pthread_wakeup_ocall_t { + int ms_retval; + unsigned long long ms_waiter; +} ms_pthread_wakeup_ocall_t; + +static sgx_status_t SGX_CDECL enclave_ocall_printf(void* pms) +{ + ms_ocall_printf_t* ms = SGX_CAST(ms_ocall_printf_t*, pms); + ocall_printf(ms->ms_str); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_ocall_close(void* pms) +{ + ms_ocall_close_t* ms = SGX_CAST(ms_ocall_close_t*, pms); + ms->ms_retval = ocall_close(ms->ms_fd); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_ocall_sleep(void* pms) +{ + ms_ocall_sleep_t* ms = SGX_CAST(ms_ocall_sleep_t*, pms); + ocall_sleep(ms->ms_sec); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_ocall_get_current_time(void* pms) +{ + ms_ocall_get_current_time_t* ms = SGX_CAST(ms_ocall_get_current_time_t*, pms); + ocall_get_current_time(ms->ms_p_current_time); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_ocall_socket(void* pms) +{ + ms_ocall_socket_t* ms = SGX_CAST(ms_ocall_socket_t*, pms); + ms->ms_retval = ocall_socket(ms->ms_domain, ms->ms_type, ms->ms_protocol); + ms->ocall_errno = errno; + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_ocall_connect(void* pms) +{ + ms_ocall_connect_t* ms = SGX_CAST(ms_ocall_connect_t*, pms); + ms->ms_retval = ocall_connect(ms->ms_fd, ms->ms_addr, ms->ms_len); + ms->ocall_errno = errno; + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_oc_cpuidex(void* pms) +{ + ms_sgx_oc_cpuidex_t* ms = SGX_CAST(ms_sgx_oc_cpuidex_t*, pms); + sgx_oc_cpuidex(ms->ms_cpuinfo, ms->ms_leaf, ms->ms_subleaf); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_thread_wait_untrusted_event_ocall(void* pms) +{ + ms_sgx_thread_wait_untrusted_event_ocall_t* ms = SGX_CAST(ms_sgx_thread_wait_untrusted_event_ocall_t*, pms); + ms->ms_retval = sgx_thread_wait_untrusted_event_ocall(ms->ms_self); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_thread_set_untrusted_event_ocall(void* pms) +{ + ms_sgx_thread_set_untrusted_event_ocall_t* ms = SGX_CAST(ms_sgx_thread_set_untrusted_event_ocall_t*, pms); + ms->ms_retval = sgx_thread_set_untrusted_event_ocall(ms->ms_waiter); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_thread_setwait_untrusted_events_ocall(void* pms) +{ + ms_sgx_thread_setwait_untrusted_events_ocall_t* ms = SGX_CAST(ms_sgx_thread_setwait_untrusted_events_ocall_t*, pms); + ms->ms_retval = sgx_thread_setwait_untrusted_events_ocall(ms->ms_waiter, ms->ms_self); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_thread_set_multiple_untrusted_events_ocall(void* pms) +{ + ms_sgx_thread_set_multiple_untrusted_events_ocall_t* ms = SGX_CAST(ms_sgx_thread_set_multiple_untrusted_events_ocall_t*, pms); + ms->ms_retval = sgx_thread_set_multiple_untrusted_events_ocall(ms->ms_waiters, ms->ms_total); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_u_sgxssl_ftime(void* pms) +{ + ms_u_sgxssl_ftime_t* ms = SGX_CAST(ms_u_sgxssl_ftime_t*, pms); + u_sgxssl_ftime(ms->ms_timeptr, ms->ms_timeb_len); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_u_sgxssl_write(void* pms) +{ + ms_u_sgxssl_write_t* ms = SGX_CAST(ms_u_sgxssl_write_t*, pms); + ms->ms_retval = u_sgxssl_write(ms->ms_fd, ms->ms_buf, ms->ms_n); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_u_sgxssl_read(void* pms) +{ + ms_u_sgxssl_read_t* ms = SGX_CAST(ms_u_sgxssl_read_t*, pms); + ms->ms_retval = u_sgxssl_read(ms->ms_fd, ms->ms_buf, ms->ms_count); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_u_sgxssl_close(void* pms) +{ + ms_u_sgxssl_close_t* ms = SGX_CAST(ms_u_sgxssl_close_t*, pms); + ms->ms_retval = u_sgxssl_close(ms->ms_fd); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_tls_get_qe_target_info_ocall(void* pms) +{ + ms_sgx_tls_get_qe_target_info_ocall_t* ms = SGX_CAST(ms_sgx_tls_get_qe_target_info_ocall_t*, pms); + ms->ms_retval = sgx_tls_get_qe_target_info_ocall(ms->ms_p_target_info, ms->ms_target_info_size); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_tls_get_quote_size_ocall(void* pms) +{ + ms_sgx_tls_get_quote_size_ocall_t* ms = SGX_CAST(ms_sgx_tls_get_quote_size_ocall_t*, pms); + ms->ms_retval = sgx_tls_get_quote_size_ocall(ms->ms_p_quote_size); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_tls_get_quote_ocall(void* pms) +{ + ms_sgx_tls_get_quote_ocall_t* ms = SGX_CAST(ms_sgx_tls_get_quote_ocall_t*, pms); + ms->ms_retval = sgx_tls_get_quote_ocall(ms->ms_p_report, ms->ms_report_size, ms->ms_p_quote, ms->ms_quote_size); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_tls_get_supplemental_data_size_ocall(void* pms) +{ + ms_sgx_tls_get_supplemental_data_size_ocall_t* ms = SGX_CAST(ms_sgx_tls_get_supplemental_data_size_ocall_t*, pms); + ms->ms_retval = sgx_tls_get_supplemental_data_size_ocall(ms->ms_p_supplemental_data_size); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_sgx_tls_verify_quote_ocall(void* pms) +{ + ms_sgx_tls_verify_quote_ocall_t* ms = SGX_CAST(ms_sgx_tls_verify_quote_ocall_t*, pms); + ms->ms_retval = sgx_tls_verify_quote_ocall(ms->ms_p_quote, ms->ms_quote_size, ms->ms_expiration_check_date, ms->ms_p_quote_verification_result, ms->ms_p_qve_report_info, ms->ms_qve_report_info_size, ms->ms_p_supplemental_data, ms->ms_supplemental_data_size); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_pthread_wait_timeout_ocall(void* pms) +{ + ms_pthread_wait_timeout_ocall_t* ms = SGX_CAST(ms_pthread_wait_timeout_ocall_t*, pms); + ms->ms_retval = pthread_wait_timeout_ocall(ms->ms_waiter, ms->ms_timeout); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_pthread_create_ocall(void* pms) +{ + ms_pthread_create_ocall_t* ms = SGX_CAST(ms_pthread_create_ocall_t*, pms); + ms->ms_retval = pthread_create_ocall(ms->ms_self); + + return SGX_SUCCESS; +} + +static sgx_status_t SGX_CDECL enclave_pthread_wakeup_ocall(void* pms) +{ + ms_pthread_wakeup_ocall_t* ms = SGX_CAST(ms_pthread_wakeup_ocall_t*, pms); + ms->ms_retval = pthread_wakeup_ocall(ms->ms_waiter); + + return SGX_SUCCESS; +} + +static const struct { + size_t nr_ocall; + void * table[23]; +} ocall_table_enclave = { + 23, + { + (void*)enclave_ocall_printf, + (void*)enclave_ocall_close, + (void*)enclave_ocall_sleep, + (void*)enclave_ocall_get_current_time, + (void*)enclave_ocall_socket, + (void*)enclave_ocall_connect, + (void*)enclave_sgx_oc_cpuidex, + (void*)enclave_sgx_thread_wait_untrusted_event_ocall, + (void*)enclave_sgx_thread_set_untrusted_event_ocall, + (void*)enclave_sgx_thread_setwait_untrusted_events_ocall, + (void*)enclave_sgx_thread_set_multiple_untrusted_events_ocall, + (void*)enclave_u_sgxssl_ftime, + (void*)enclave_u_sgxssl_write, + (void*)enclave_u_sgxssl_read, + (void*)enclave_u_sgxssl_close, + (void*)enclave_sgx_tls_get_qe_target_info_ocall, + (void*)enclave_sgx_tls_get_quote_size_ocall, + (void*)enclave_sgx_tls_get_quote_ocall, + (void*)enclave_sgx_tls_get_supplemental_data_size_ocall, + (void*)enclave_sgx_tls_verify_quote_ocall, + (void*)enclave_pthread_wait_timeout_ocall, + (void*)enclave_pthread_create_ocall, + (void*)enclave_pthread_wakeup_ocall, + } +}; +sgx_status_t enclave_launch_tls_client(sgx_enclave_id_t eid, int* retval, const char* server_name, uint16_t server_port, uint32_t key, const char* action) +{ + sgx_status_t status; + ms_enclave_launch_tls_client_t ms; + ms.ms_server_name = server_name; + ms.ms_server_name_len = server_name ? strlen(server_name) + 1 : 0; + ms.ms_server_port = server_port; + ms.ms_key = key; + ms.ms_action = action; + ms.ms_action_len = action ? strlen(action) + 1 : 0; + status = sgx_ecall(eid, 0, &ocall_table_enclave, &ms); + if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval; + return status; +} + +sgx_status_t sgx_ra_get_ga(sgx_enclave_id_t eid, sgx_status_t* retval, sgx_ra_context_t context, sgx_ec256_public_t* g_a) +{ + sgx_status_t status; + ms_sgx_ra_get_ga_t ms; + ms.ms_context = context; + ms.ms_g_a = g_a; + status = sgx_ecall(eid, 1, &ocall_table_enclave, &ms); + if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval; + return status; +} + +sgx_status_t sgx_ra_proc_msg2_trusted(sgx_enclave_id_t eid, sgx_status_t* retval, sgx_ra_context_t context, const sgx_ra_msg2_t* p_msg2, const sgx_target_info_t* p_qe_target, sgx_report_t* p_report, sgx_quote_nonce_t* p_nonce) +{ + sgx_status_t status; + ms_sgx_ra_proc_msg2_trusted_t ms; + ms.ms_context = context; + ms.ms_p_msg2 = p_msg2; + ms.ms_p_qe_target = p_qe_target; + ms.ms_p_report = p_report; + ms.ms_p_nonce = p_nonce; + status = sgx_ecall(eid, 2, &ocall_table_enclave, &ms); + if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval; + return status; +} + +sgx_status_t sgx_ra_get_msg3_trusted(sgx_enclave_id_t eid, sgx_status_t* retval, sgx_ra_context_t context, uint32_t quote_size, sgx_report_t* qe_report, sgx_ra_msg3_t* p_msg3, uint32_t msg3_size) +{ + sgx_status_t status; + ms_sgx_ra_get_msg3_trusted_t ms; + ms.ms_context = context; + ms.ms_quote_size = quote_size; + ms.ms_qe_report = qe_report; + ms.ms_p_msg3 = p_msg3; + ms.ms_msg3_size = msg3_size; + status = sgx_ecall(eid, 3, &ocall_table_enclave, &ms); + if (status == SGX_SUCCESS && retval) *retval = ms.ms_retval; + return status; +} + diff --git a/dkeyserver/dkeyrotation/App/enclave_u.h b/dkeyserver/dkeyrotation/App/enclave_u.h new file mode 100644 index 00000000..a13333c9 --- /dev/null +++ b/dkeyserver/dkeyrotation/App/enclave_u.h @@ -0,0 +1,136 @@ +#ifndef ENCLAVE_U_H__ +#define ENCLAVE_U_H__ + +#include +#include +#include +#include +#include "sgx_edger8r.h" /* for sgx_status_t etc. */ + +#include "sgx_ttls.h" +#include "sgx_key_exchange.h" +#include "sgx_quote.h" +#include "sgx_trts.h" +#include "stdbool.h" +#include "datatypes.h" +#include "dh_session_protocol.h" +#include "sys/socket.h" +#include "sys/select.h" +#include "netdb.h" +#include "poll.h" +#include "sgx_report.h" +#include "sgx_qve_header.h" +#include "sgx_ql_lib_common.h" +#include "sgx_ql_quote.h" + +#include /* for size_t */ + +#define SGX_CAST(type, item) ((type)(item)) + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef OCALL_PRINTF_DEFINED__ +#define OCALL_PRINTF_DEFINED__ +void SGX_UBRIDGE(SGX_NOCONVENTION, ocall_printf, (const char* str)); +#endif +#ifndef OCALL_CLOSE_DEFINED__ +#define OCALL_CLOSE_DEFINED__ +int SGX_UBRIDGE(SGX_NOCONVENTION, ocall_close, (int fd)); +#endif +#ifndef OCALL_SLEEP_DEFINED__ +#define OCALL_SLEEP_DEFINED__ +void SGX_UBRIDGE(SGX_NOCONVENTION, ocall_sleep, (int sec)); +#endif +#ifndef OCALL_GET_CURRENT_TIME_DEFINED__ +#define OCALL_GET_CURRENT_TIME_DEFINED__ +void SGX_UBRIDGE(SGX_NOCONVENTION, ocall_get_current_time, (uint64_t* p_current_time)); +#endif +#ifndef OCALL_SOCKET_DEFINED__ +#define OCALL_SOCKET_DEFINED__ +int SGX_UBRIDGE(SGX_NOCONVENTION, ocall_socket, (int domain, int type, int protocol)); +#endif +#ifndef OCALL_CONNECT_DEFINED__ +#define OCALL_CONNECT_DEFINED__ +int SGX_UBRIDGE(SGX_NOCONVENTION, ocall_connect, (int fd, const struct sockaddr* addr, socklen_t len)); +#endif +#ifndef SGX_OC_CPUIDEX_DEFINED__ +#define SGX_OC_CPUIDEX_DEFINED__ +void SGX_UBRIDGE(SGX_CDECL, sgx_oc_cpuidex, (int cpuinfo[4], int leaf, int subleaf)); +#endif +#ifndef SGX_THREAD_WAIT_UNTRUSTED_EVENT_OCALL_DEFINED__ +#define SGX_THREAD_WAIT_UNTRUSTED_EVENT_OCALL_DEFINED__ +int SGX_UBRIDGE(SGX_CDECL, sgx_thread_wait_untrusted_event_ocall, (const void* self)); +#endif +#ifndef SGX_THREAD_SET_UNTRUSTED_EVENT_OCALL_DEFINED__ +#define SGX_THREAD_SET_UNTRUSTED_EVENT_OCALL_DEFINED__ +int SGX_UBRIDGE(SGX_CDECL, sgx_thread_set_untrusted_event_ocall, (const void* waiter)); +#endif +#ifndef SGX_THREAD_SETWAIT_UNTRUSTED_EVENTS_OCALL_DEFINED__ +#define SGX_THREAD_SETWAIT_UNTRUSTED_EVENTS_OCALL_DEFINED__ +int SGX_UBRIDGE(SGX_CDECL, sgx_thread_setwait_untrusted_events_ocall, (const void* waiter, const void* self)); +#endif +#ifndef SGX_THREAD_SET_MULTIPLE_UNTRUSTED_EVENTS_OCALL_DEFINED__ +#define SGX_THREAD_SET_MULTIPLE_UNTRUSTED_EVENTS_OCALL_DEFINED__ +int SGX_UBRIDGE(SGX_CDECL, sgx_thread_set_multiple_untrusted_events_ocall, (const void** waiters, size_t total)); +#endif +#ifndef U_SGXSSL_FTIME_DEFINED__ +#define U_SGXSSL_FTIME_DEFINED__ +void SGX_UBRIDGE(SGX_NOCONVENTION, u_sgxssl_ftime, (void* timeptr, uint32_t timeb_len)); +#endif +#ifndef U_SGXSSL_WRITE_DEFINED__ +#define U_SGXSSL_WRITE_DEFINED__ +size_t SGX_UBRIDGE(SGX_NOCONVENTION, u_sgxssl_write, (int fd, const void* buf, size_t n)); +#endif +#ifndef U_SGXSSL_READ_DEFINED__ +#define U_SGXSSL_READ_DEFINED__ +size_t SGX_UBRIDGE(SGX_NOCONVENTION, u_sgxssl_read, (int fd, void* buf, size_t count)); +#endif +#ifndef U_SGXSSL_CLOSE_DEFINED__ +#define U_SGXSSL_CLOSE_DEFINED__ +int SGX_UBRIDGE(SGX_NOCONVENTION, u_sgxssl_close, (int fd)); +#endif +#ifndef SGX_TLS_GET_QE_TARGET_INFO_OCALL_DEFINED__ +#define SGX_TLS_GET_QE_TARGET_INFO_OCALL_DEFINED__ +quote3_error_t SGX_UBRIDGE(SGX_NOCONVENTION, sgx_tls_get_qe_target_info_ocall, (sgx_target_info_t* p_target_info, size_t target_info_size)); +#endif +#ifndef SGX_TLS_GET_QUOTE_SIZE_OCALL_DEFINED__ +#define SGX_TLS_GET_QUOTE_SIZE_OCALL_DEFINED__ +quote3_error_t SGX_UBRIDGE(SGX_NOCONVENTION, sgx_tls_get_quote_size_ocall, (uint32_t* p_quote_size)); +#endif +#ifndef SGX_TLS_GET_QUOTE_OCALL_DEFINED__ +#define SGX_TLS_GET_QUOTE_OCALL_DEFINED__ +quote3_error_t SGX_UBRIDGE(SGX_NOCONVENTION, sgx_tls_get_quote_ocall, (sgx_report_t* p_report, size_t report_size, uint8_t* p_quote, uint32_t quote_size)); +#endif +#ifndef SGX_TLS_GET_SUPPLEMENTAL_DATA_SIZE_OCALL_DEFINED__ +#define SGX_TLS_GET_SUPPLEMENTAL_DATA_SIZE_OCALL_DEFINED__ +quote3_error_t SGX_UBRIDGE(SGX_NOCONVENTION, sgx_tls_get_supplemental_data_size_ocall, (uint32_t* p_supplemental_data_size)); +#endif +#ifndef SGX_TLS_VERIFY_QUOTE_OCALL_DEFINED__ +#define SGX_TLS_VERIFY_QUOTE_OCALL_DEFINED__ +quote3_error_t SGX_UBRIDGE(SGX_NOCONVENTION, sgx_tls_verify_quote_ocall, (const uint8_t* p_quote, uint32_t quote_size, time_t expiration_check_date, sgx_ql_qv_result_t* p_quote_verification_result, sgx_ql_qe_report_info_t* p_qve_report_info, size_t qve_report_info_size, uint8_t* p_supplemental_data, uint32_t supplemental_data_size)); +#endif +#ifndef PTHREAD_WAIT_TIMEOUT_OCALL_DEFINED__ +#define PTHREAD_WAIT_TIMEOUT_OCALL_DEFINED__ +int SGX_UBRIDGE(SGX_CDECL, pthread_wait_timeout_ocall, (unsigned long long waiter, unsigned long long timeout)); +#endif +#ifndef PTHREAD_CREATE_OCALL_DEFINED__ +#define PTHREAD_CREATE_OCALL_DEFINED__ +int SGX_UBRIDGE(SGX_CDECL, pthread_create_ocall, (unsigned long long self)); +#endif +#ifndef PTHREAD_WAKEUP_OCALL_DEFINED__ +#define PTHREAD_WAKEUP_OCALL_DEFINED__ +int SGX_UBRIDGE(SGX_CDECL, pthread_wakeup_ocall, (unsigned long long waiter)); +#endif + +sgx_status_t enclave_launch_tls_client(sgx_enclave_id_t eid, int* retval, const char* server_name, uint16_t server_port, uint32_t key, const char* action); +sgx_status_t sgx_ra_get_ga(sgx_enclave_id_t eid, sgx_status_t* retval, sgx_ra_context_t context, sgx_ec256_public_t* g_a); +sgx_status_t sgx_ra_proc_msg2_trusted(sgx_enclave_id_t eid, sgx_status_t* retval, sgx_ra_context_t context, const sgx_ra_msg2_t* p_msg2, const sgx_target_info_t* p_qe_target, sgx_report_t* p_report, sgx_quote_nonce_t* p_nonce); +sgx_status_t sgx_ra_get_msg3_trusted(sgx_enclave_id_t eid, sgx_status_t* retval, sgx_ra_context_t context, uint32_t quote_size, sgx_report_t* qe_report, sgx_ra_msg3_t* p_msg3, uint32_t msg3_size); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/dkeyserver/dkeyrotation/App/enclave_u.o b/dkeyserver/dkeyrotation/App/enclave_u.o new file mode 100644 index 00000000..4b55c0e2 Binary files /dev/null and b/dkeyserver/dkeyrotation/App/enclave_u.o differ diff --git a/dkeyserver/dkeyrotation/App/main.cpp b/dkeyserver/dkeyrotation/App/main.cpp new file mode 100644 index 00000000..a07a44e9 --- /dev/null +++ b/dkeyserver/dkeyrotation/App/main.cpp @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// Need to create enclave and do ecall. +#include "sgx_urts.h" + +#include +#include +#include +#include + +#include "fifo_def.h" +#include "datatypes.h" +#include "json_utils.h" + +#include "auto_version.h" + +#define __STDC_FORMAT_MACROS +#define ENCLAVE_PATH "libenclave-ehsm-dkeyrotation.signed.so" +#include + +using namespace std; + +sgx_enclave_id_t g_enclave_id; + +int ocall_close(int fd) +{ + return close(fd); +} + +void ocall_printf(const char *str) +{ + printf("%s", str); +} + +void ocall_get_current_time(uint64_t *p_current_time) +{ + time_t rawtime; + time(&rawtime); + + if (!p_current_time) + return; + *p_current_time = (uint64_t)rawtime; +} + +/* ocalls to use socket APIs , call socket syscalls */ + +int ocall_socket(int domain, int type, int protocol) +{ + return socket(domain, type, protocol); +} + +int ocall_connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen) +{ + int32_t retry_count = 60; + do + { + int ret = connect(sockfd, servaddr, addrlen); + if (ret >= 0) + return ret; + + printf("Failed to Connect dkeyserver, sleep 0.5s and try again...\n"); + usleep(500000); // 0.5s + } while (retry_count-- > 0); + + printf("Failed to connect dkeyserver.\n"); + return -1; +} + +std::string deploy_ip_addr; +uint32_t key; +std::string action; +uint16_t deploy_port = 0; +static const char *_sopts = "i:p:k:a:"; +static const struct option _lopts[] = {{"ip", required_argument, NULL, 'i'}, + {"port", required_argument, NULL, 'p'}, + {"key", required_argument, NULL, 'k'}, + {"action", required_argument, NULL, 'a'}, + {0, 0, 0, 0}}; + +static void show_usage_and_exit(int code) +{ + printf("Required parameters:\n" + " -i ip\n" + " -p port\n" + " -k key\n" + " -a action:\n" + " start_rotation, stop_auto_rotation, set_period\n" + " get_period, get_next_rotation_time, update_cmk\n"); + exit(code); +} + +void ocall_sleep(int sec) +{ + sleep(sec); +} + +static void parse_args(int argc, char *argv[]) +{ + int opt; + int oidx = 0; + while ((opt = getopt_long(argc, argv, _sopts, _lopts, &oidx)) != -1) + { + switch (opt) + { + case 'i': + deploy_ip_addr = strdup(optarg); + break; + case 'p': + try + { + deploy_port = std::stoi(strdup(optarg)); + } + catch (...) + { + printf("[-p %s] port must be a number.", optarg); + } + break; + case 'k': + key = std::stoi(strdup(optarg)); + break; + case 'a': + action = strdup(optarg); + break; + default: + show_usage_and_exit(EXIT_FAILURE); + } + } + if (deploy_ip_addr.empty() || deploy_port == 0) + show_usage_and_exit(EXIT_FAILURE); +} + +int main(int argc, char *argv[]) +{ + // process argv + parse_args(argc, argv); + + int ret = 0; + + ret = sgx_create_enclave(_T(ENCLAVE_PATH), + SGX_DEBUG_FLAG, + NULL, + NULL, + &g_enclave_id, NULL); + if (SGX_SUCCESS != ret) + { + printf("failed to create enclave.\n"); + return -1; + } + + // Connect to the dkeyserver and retrieve the domain key via the remote secure channel + ret = enclave_launch_tls_client(g_enclave_id, &ret, deploy_ip_addr.c_str(), deploy_port, + key, action.c_str()); + + if (ret != 0) + sgx_destroy_enclave(g_enclave_id); + + sgx_destroy_enclave(g_enclave_id); + + return 0; +} diff --git a/dkeyserver/dkeyrotation/App/main.o b/dkeyserver/dkeyrotation/App/main.o new file mode 100644 index 00000000..28cbc495 Binary files /dev/null and b/dkeyserver/dkeyrotation/App/main.o differ diff --git a/dkeyserver/dkeyrotation/Enclave/enclave.config.xml b/dkeyserver/dkeyrotation/Enclave/enclave.config.xml new file mode 100644 index 00000000..12b5df99 --- /dev/null +++ b/dkeyserver/dkeyrotation/Enclave/enclave.config.xml @@ -0,0 +1,11 @@ + + 0 + 0 + 0x40000 + 0xA00000 + 8 + 1 + 0 + 0 + 0xFFFFFFFF + diff --git a/dkeyserver/dkeyrotation/Enclave/enclave.edl b/dkeyserver/dkeyrotation/Enclave/enclave.edl new file mode 100644 index 00000000..2aa180ad --- /dev/null +++ b/dkeyserver/dkeyrotation/Enclave/enclave.edl @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020-2021 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +enclave { + from "sgx_tkey_exchange.edl" import *; + from "sgx_tstdc.edl" import *; + from "sgx_tsgxssl.edl" import *; + from "sgx_ttls.edl" import *; + from "sgx_pthread.edl" import *; + + include "sgx_ttls.h" + include "sgx_key_exchange.h" + include "sgx_quote.h" + include "sgx_trts.h" + include "stdbool.h" + include "datatypes.h" + include "dh_session_protocol.h" + include "sys/socket.h" + include "sys/select.h" + include "netdb.h" + include "poll.h" + + untrusted { + void ocall_printf([in, string] const char *str); + int ocall_close(int fd); + void ocall_sleep(int sec); + void ocall_get_current_time([out] uint64_t *p_current_time); + int ocall_socket (int domain, int type, int protocol) propagate_errno; + int ocall_connect (int fd, [in, size=len] const struct sockaddr *addr, socklen_t len) propagate_errno; + }; + + trusted { + public int enclave_launch_tls_client( + [in, string] const char* server_name, + uint16_t server_port, + uint32_t key, + [in, string] const char* action); + }; +}; diff --git a/dkeyserver/dkeyrotation/Enclave/enclave.lds b/dkeyserver/dkeyrotation/Enclave/enclave.lds new file mode 100644 index 00000000..e3d9d0ee --- /dev/null +++ b/dkeyserver/dkeyrotation/Enclave/enclave.lds @@ -0,0 +1,9 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + local: + *; +}; diff --git a/dkeyserver/dkeyrotation/Enclave/enclave_private_test.pem b/dkeyserver/dkeyrotation/Enclave/enclave_private_test.pem new file mode 100644 index 00000000..b8ace89e --- /dev/null +++ b/dkeyserver/dkeyrotation/Enclave/enclave_private_test.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEA0MvI9NpdP4GEqCvtlJQv00OybzTXzxBhPu/257VYt9cYw/ph +BN1WRyxBBcrZs15xmcvlb3xNmFGWs4w5oUgrFBNgi6g+CUOCsj0cM8xw7P/y3K0H +XaZUf+T3CXCp8NvlkZHzfdWAFA5lGGR9g6kmuk7SojE3h87Zm1KjPU/PvAe+BaMU +trlRr4gPNVnu19Vho60xwuswPxfl/pBFUIk7qWEUR3l2hiqWMeLgf3Ays/WSnkXA +uijwPt5g0hxsgIlyDrI3jKbf0zkFB56jvPwSykfU8aw4Gkbo5qSZxUAKnwH2L8Uf +yM6inBaaYtM79icRwsu45Yt6X0GAt7CSb/1TKBrnm5exmK1sug3YSQ/YuK1FYawU +vIaDD0YfzOndTNVBewA+Hr5xNPvqGJoRKHuGbyu2lI9jrKYpVxQWsmx38wnxF6kE +zX6N4m7KZiLeLpDdBVQtLuOzIdIE4wT3t/ckeqElxO/1Ut9bj765GcTTrYwMKHRw +ukWIH7ZtHtAjj0KzAgEDAoIBgQCLMoX4kZN/q63Fcp5jDXU3gnb0zeU0tZYp9U9F +I5B6j2XX/ECt6OQvctYD3JEiPvZmh+5KUt5li7nNCCZrhXINYkBdGtQGLQHMKL13 +3aCd//c9yK+TxDhVQ09boHFLPUO2YUz+jlVitENlmFOtG28m3zcWy3paieZnjGzT +iop9Wn6ubLh50OEfsAojkUnlOOvCc3aB8iAqD+6ptYOLBifGQLgvpk8EHGQhQer/ +oCHNTmG+2SsmxfV/Pus2vZ2rBkrUbZU0hwrnvKOIPhnt3Qwtmx9xsC67jF+MpWko +UisJXC27FAGz2gpIGMhBp35HEppwG9hhCuMQdK2g62bvweyr1tC4qOVdQrKvhksN +r6CMjS9eSXvmWdF7lU4oxStN0V56/LICSIsLbggUaxTPKhAVEgfTSqwEJoQuFA3Q +4GmgTydPhcRH1L/lhbWJqZQm7V1Gt+5i5J6iATD32uNQQ2iZi5GsUhr+jZC+WlE5 +6lS813cRNiaK52HIk62bG7IXOksCgcEA+6RxZhQ5GaCPYZNsk7TqxqsKopXKoYAr +2R4KWuexJTd+1kcNMk0ETX8OSgpY2cYL2uPFWmdutxPpLfpr8S2u92Da/Wxs70Ti +QSb0426ybTmnS5L7nOnGOHiddXILhW175liAszTeoR7nQ6vpr9YjfcnrXiB8bKIm +akft2DQoxrBPzEe9tA8gfkyDTsSG2j7kncSbvYRtkKcJOmmypotVU6uhRPSrSXCc +J59uBQkg6Bk4CKA1mz8ctG07MluFY0/ZAoHBANRpZlfIFl39gFmuEER7lb80GySO +J190LbqOca3dGOvAMsDgEAi6juJyX7ZNpbHFHj++LvmTtw9+kxhVDBcswS7304kt +7J2EfnGdctEZtXif1wiq30YWAp1tjRpQENKtt9wssmgcwgK39rZNiEHmStHGv3l+ +5TnKPKeuFCDnsLvi5lQYoK2wTYvZtsjf+Rnt7H17q90IV54pMjTS8BkGskCkKf2A +IYuaZkqX0T3cM6ovoYYDAU6rWL5rrYPLEwkbawKBwQCnwvZEDXtmawpBDPMNI0cv +HLHBuTHBAB07aVw8mnYYz6nkL14hiK2I/17cBuXmhAfnQoORmknPYptz/Ef2HnSk +6zyo8vNKLewrb03s9Hbze8TdDKe98S7QUGj49rJY86fu5asiIz8WFJotHUZ1OWz+ +hpzpav2dwW7xhUk6zXCEdYqIL9PNX2r+3azfLa88Ke2+gxJ+WEkLGgYm8SHEXOON +HRYt+HIw9b1vv56uBhXwENAFwCO81L3Nnid2565CNTsCgcEAjZuZj9q5k/5VkR61 +gv0Of3gSGF7E6k1z0bRLyT4QnSrMgJVgBdG0lvbqeYkZIS4UKn7J+7fPX6m3ZY4I +D3MrdKU3sMlIaQL+9mj3NhEjpb/ksHHqLrlXE55eEYq14cklPXMhmr3WrHqkeYkF +gUQx4S8qUP9De9wob8liwJp10pdEOBBrHnWJB+Z52z/7Zp6dqP0dPgWPvsYheIyg +EK8hgG1xU6rBB7xEMbqLfpLNHB/BBAIA3xzl1EfJAodiBhJHAoHAeTS2znDHYayI +TvK86tBAPVORiBVTSdRUONdGF3dipo24hyeyrI5MtiOoMc3sKWXnSTkDQWa3WiPx +qStBmmO/SbGTuz7T6+oOwGeMiYzYBe87Ayn8Y0KYYshFikieJbGusHjUlIGmCVPy +UHrDMYGwFGUGBwW47gBsnZa+YPHtxWCPDe/U80et2Trx0RXJJQPmupAVMSiJWObI +9k5gRU+xDqkHanyD1gkGGwhFTUNX94EJEOdQEWw3hxLnVtePoke/ +-----END RSA PRIVATE KEY----- diff --git a/dkeyserver/dkeyrotation/Enclave/enclave_ra.cpp b/dkeyserver/dkeyrotation/Enclave/enclave_ra.cpp new file mode 100644 index 00000000..f23ff8a0 --- /dev/null +++ b/dkeyserver/dkeyrotation/Enclave/enclave_ra.cpp @@ -0,0 +1,332 @@ +/** + * + * MIT License + * + * Copyright (c) Open Enclave SDK contributors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sgx_trts.h" +#include "openssl_utility.h" +#include "enclave_t.h" +#include "datatypes.h" + +int verify_callback(int preverify_ok, X509_STORE_CTX *ctx); + +void log_printf(uint32_t log_level, const char *filename, uint32_t line, const char *fmt, ...) +{ + char buf[BUFSIZ] = {'\0'}; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, BUFSIZ, fmt, ap); + va_end(ap); + ocall_printf(buf); +} + +void printf(const char *fmt, ...) +{ + char buf[BUFSIZ] = {'\0'}; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, BUFSIZ, fmt, ap); + va_end(ap); + ocall_printf(buf); +} + +void t_time(time_t *current_t) +{ + ocall_get_current_time((uint64_t *)current_t); +} + +uint16_t htons(uint16_t n) +{ + union + { + int i; + char c; + } u = {1}; + return u.c ? bswap_16(n) : n; +} + +int socket(int domain, int type, int protocol) +{ + int ret = -1; + + if (ocall_socket(&ret, domain, type, protocol) == SGX_SUCCESS) + return ret; + + return -1; +} + +int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen) +{ + int ret = -1; + + if (ocall_connect(&ret, sockfd, servaddr, addrlen) == SGX_SUCCESS) + return ret; + + return -1; +} + +unsigned long inet_addr2(const char *str) +{ + unsigned long lHost = 0; + char *pLong = (char *)&lHost; + char *p = (char *)str; + while (p) + { + *pLong++ = atoi(p); + p = strchr(p, '.'); + if (p) + ++p; + } + return lHost; +} + +// This routine conducts a simple HTTP request/response communication with server +static int communicate_with_server(SSL *ssl, uint32_t key, const char *action) +{ + unsigned char buf[200] = {0}; + int ret = 1; + int error = 0; + int bytes_written = 0; + int bytes_read = 0; + + _response_header_t *heart_msg = NULL; + heart_msg = (_response_header_t *)malloc(sizeof(_response_header_t)); + + _request_header_t *send_msg = (_request_header_t *)malloc(sizeof(_request_header_t)); + if (send_msg == NULL) + { + return -1; + } + + send_msg->password = key; + + if (!strcasecmp(action, "start_rotation")) + { + send_msg->cmd = START_ROTATION; + } + else if (!strcasecmp(action, "stop_auto_rotation")) + { + send_msg->cmd = STOP_AUTO_ROTATION; + } + else if (!strcasecmp(action, "set_period")) + { + send_msg->cmd = SET_PERIOD; + } + else if (!strcasecmp(action, "get_period")) + { + send_msg->cmd = GET_PERIOD; + } + else if (!strcasecmp(action, "get_next_rotation_time")) + { + send_msg->cmd = GET_NEXT_ROTATION_DATETIME; + } + else if (!strcasecmp(action, "update_cmk")) + { + send_msg->cmd = UPDATE_CMK; + } + else + { + return -1; + } + + // Write an GET request to the server + int len = sizeof(_request_header_t); + + log_i("rotation = %d\n", SSL_get_fd(ssl)); + + while ((bytes_written = SSL_write(ssl, (char *)send_msg, (size_t)len)) <= 0) + { + error = SSL_get_error(ssl, bytes_written); + if (error == SSL_ERROR_WANT_WRITE) + continue; + ret = bytes_written; + goto done; + } + + // Read the HTTP response from server + while (1) + { + memset(buf, 0, 200); + + bytes_read = SSL_read(ssl, buf, sizeof(buf) - 1); + log_i("bytes_read=%d\n", bytes_read); + + if (bytes_read <= 0) + { + int error = SSL_get_error(ssl, bytes_read); + if (error == SSL_ERROR_WANT_READ) + continue; + ret = bytes_read; + break; + } + else + { + memcpy(heart_msg, buf, sizeof(_response_header_t)); + + if (heart_msg->type == MSG_HEARTBEAT) + { + printf("this is a heart message"); + continue; + } + + printf("========================================\n"); + printf("res msg: %s\n", buf); + printf("========================================\n"); + } + + ret = 0; + + break; + } +done: + + // ocall_sleep(10); + return ret; +} + +// create a socket and connect to the server_name:server_port +int create_socket(const char *server_name, uint16_t server_port) +{ + int sockfd = -1; + struct sockaddr_in dest_sock; + int res = -1; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) + goto done; + + dest_sock.sin_family = AF_INET; + dest_sock.sin_port = htons(server_port); + dest_sock.sin_addr.s_addr = inet_addr2(server_name); + bzero(&(dest_sock.sin_zero), sizeof(dest_sock.sin_zero)); + + if (connect( + sockfd, (sockaddr *)&dest_sock, + sizeof(struct sockaddr)) == -1) + { + ocall_close(&res, sockfd); + sockfd = -1; + goto done; + } + +done: + return sockfd; +} + +int enclave_launch_tls_client(const char *server_name, uint16_t server_port, uint32_t key, const char *action) +{ + int ret = -1; + + SSL_CTX *ssl_client_ctx = nullptr; + SSL *ssl_session = nullptr; + + X509 *cert = nullptr; + EVP_PKEY *pkey = nullptr; + SSL_CONF_CTX *ssl_confctx = SSL_CONF_CTX_new(); + + int client_socket = -1; + int error = 0; + if (server_name == NULL) + goto done; + + if ((ssl_client_ctx = SSL_CTX_new(TLS_client_method())) == nullptr) + goto done; + + if (SSL_CTX_set_cipher_list(ssl_client_ctx, "TLS_AES_256_GCM_SHA384") != SGX_SUCCESS) + goto done; + + if (initalize_ssl_context(ssl_confctx, ssl_client_ctx) != SGX_SUCCESS) + goto done; + + // specify the verify_callback for custom verification + SSL_CTX_set_verify(ssl_client_ctx, SSL_VERIFY_PEER, &verify_callback); + if (load_tls_certificates_and_keys(ssl_client_ctx, cert, pkey) != 0) + goto done; + + if ((ssl_session = SSL_new(ssl_client_ctx)) == nullptr) + goto done; + + client_socket = create_socket(server_name, server_port); + if (client_socket == -1) + goto done; + + // set up ssl socket and initiate TLS connection with TLS server + SSL_set_fd(ssl_session, client_socket); + + if ((error = SSL_connect(ssl_session)) != 1) + goto done; + + // start the client server communication + if ((error = communicate_with_server(ssl_session, key, action)) != 0) + goto done; + + // Free the structures we don't need anymore + + ret = 0; +done: + + if (client_socket != -1) + { + int closeRet; + ocall_close(&closeRet, client_socket); + if (closeRet != 0) + ret = -1; + } + + if (ssl_session) + { + SSL_shutdown(ssl_session); + SSL_free(ssl_session); + } + + if (cert) + X509_free(cert); + + if (pkey) + EVP_PKEY_free(pkey); + + if (ssl_client_ctx) + SSL_CTX_free(ssl_client_ctx); + + if (ssl_confctx) + SSL_CONF_CTX_free(ssl_confctx); + + return ret; +} diff --git a/dkeyserver/dkeyrotation/Enclave/enclave_ra.o b/dkeyserver/dkeyrotation/Enclave/enclave_ra.o new file mode 100644 index 00000000..2746eff8 Binary files /dev/null and b/dkeyserver/dkeyrotation/Enclave/enclave_ra.o differ diff --git a/dkeyserver/dkeyrotation/Enclave/enclave_t.c b/dkeyserver/dkeyrotation/Enclave/enclave_t.c new file mode 100644 index 00000000..08ced78a --- /dev/null +++ b/dkeyserver/dkeyrotation/Enclave/enclave_t.c @@ -0,0 +1,1539 @@ +#include "enclave_t.h" + +#include "sgx_trts.h" /* for sgx_ocalloc, sgx_is_outside_enclave */ +#include "sgx_lfence.h" /* for sgx_lfence */ + +#include +#include /* for memcpy_s etc */ +#include /* for malloc/free etc */ + +#define CHECK_REF_POINTER(ptr, siz) do { \ + if (!(ptr) || ! sgx_is_outside_enclave((ptr), (siz))) \ + return SGX_ERROR_INVALID_PARAMETER;\ +} while (0) + +#define CHECK_UNIQUE_POINTER(ptr, siz) do { \ + if ((ptr) && ! sgx_is_outside_enclave((ptr), (siz))) \ + return SGX_ERROR_INVALID_PARAMETER;\ +} while (0) + +#define CHECK_ENCLAVE_POINTER(ptr, siz) do { \ + if ((ptr) && ! sgx_is_within_enclave((ptr), (siz))) \ + return SGX_ERROR_INVALID_PARAMETER;\ +} while (0) + +#define ADD_ASSIGN_OVERFLOW(a, b) ( \ + ((a) += (b)) < (b) \ +) + + +typedef struct ms_enclave_launch_tls_client_t { + int ms_retval; + const char* ms_server_name; + size_t ms_server_name_len; + uint16_t ms_server_port; + uint32_t ms_key; + const char* ms_action; + size_t ms_action_len; +} ms_enclave_launch_tls_client_t; + +typedef struct ms_sgx_ra_get_ga_t { + sgx_status_t ms_retval; + sgx_ra_context_t ms_context; + sgx_ec256_public_t* ms_g_a; +} ms_sgx_ra_get_ga_t; + +typedef struct ms_sgx_ra_proc_msg2_trusted_t { + sgx_status_t ms_retval; + sgx_ra_context_t ms_context; + const sgx_ra_msg2_t* ms_p_msg2; + const sgx_target_info_t* ms_p_qe_target; + sgx_report_t* ms_p_report; + sgx_quote_nonce_t* ms_p_nonce; +} ms_sgx_ra_proc_msg2_trusted_t; + +typedef struct ms_sgx_ra_get_msg3_trusted_t { + sgx_status_t ms_retval; + sgx_ra_context_t ms_context; + uint32_t ms_quote_size; + sgx_report_t* ms_qe_report; + sgx_ra_msg3_t* ms_p_msg3; + uint32_t ms_msg3_size; +} ms_sgx_ra_get_msg3_trusted_t; + +typedef struct ms_ocall_printf_t { + const char* ms_str; +} ms_ocall_printf_t; + +typedef struct ms_ocall_close_t { + int ms_retval; + int ms_fd; +} ms_ocall_close_t; + +typedef struct ms_ocall_sleep_t { + int ms_sec; +} ms_ocall_sleep_t; + +typedef struct ms_ocall_get_current_time_t { + uint64_t* ms_p_current_time; +} ms_ocall_get_current_time_t; + +typedef struct ms_ocall_socket_t { + int ms_retval; + int ocall_errno; + int ms_domain; + int ms_type; + int ms_protocol; +} ms_ocall_socket_t; + +typedef struct ms_ocall_connect_t { + int ms_retval; + int ocall_errno; + int ms_fd; + const struct sockaddr* ms_addr; + socklen_t ms_len; +} ms_ocall_connect_t; + +typedef struct ms_sgx_oc_cpuidex_t { + int* ms_cpuinfo; + int ms_leaf; + int ms_subleaf; +} ms_sgx_oc_cpuidex_t; + +typedef struct ms_sgx_thread_wait_untrusted_event_ocall_t { + int ms_retval; + const void* ms_self; +} ms_sgx_thread_wait_untrusted_event_ocall_t; + +typedef struct ms_sgx_thread_set_untrusted_event_ocall_t { + int ms_retval; + const void* ms_waiter; +} ms_sgx_thread_set_untrusted_event_ocall_t; + +typedef struct ms_sgx_thread_setwait_untrusted_events_ocall_t { + int ms_retval; + const void* ms_waiter; + const void* ms_self; +} ms_sgx_thread_setwait_untrusted_events_ocall_t; + +typedef struct ms_sgx_thread_set_multiple_untrusted_events_ocall_t { + int ms_retval; + const void** ms_waiters; + size_t ms_total; +} ms_sgx_thread_set_multiple_untrusted_events_ocall_t; + +typedef struct ms_u_sgxssl_ftime_t { + void* ms_timeptr; + uint32_t ms_timeb_len; +} ms_u_sgxssl_ftime_t; + +typedef struct ms_u_sgxssl_write_t { + size_t ms_retval; + int ms_fd; + const void* ms_buf; + size_t ms_n; +} ms_u_sgxssl_write_t; + +typedef struct ms_u_sgxssl_read_t { + size_t ms_retval; + int ms_fd; + void* ms_buf; + size_t ms_count; +} ms_u_sgxssl_read_t; + +typedef struct ms_u_sgxssl_close_t { + int ms_retval; + int ms_fd; +} ms_u_sgxssl_close_t; + +typedef struct ms_sgx_tls_get_qe_target_info_ocall_t { + quote3_error_t ms_retval; + sgx_target_info_t* ms_p_target_info; + size_t ms_target_info_size; +} ms_sgx_tls_get_qe_target_info_ocall_t; + +typedef struct ms_sgx_tls_get_quote_size_ocall_t { + quote3_error_t ms_retval; + uint32_t* ms_p_quote_size; +} ms_sgx_tls_get_quote_size_ocall_t; + +typedef struct ms_sgx_tls_get_quote_ocall_t { + quote3_error_t ms_retval; + sgx_report_t* ms_p_report; + size_t ms_report_size; + uint8_t* ms_p_quote; + uint32_t ms_quote_size; +} ms_sgx_tls_get_quote_ocall_t; + +typedef struct ms_sgx_tls_get_supplemental_data_size_ocall_t { + quote3_error_t ms_retval; + uint32_t* ms_p_supplemental_data_size; +} ms_sgx_tls_get_supplemental_data_size_ocall_t; + +typedef struct ms_sgx_tls_verify_quote_ocall_t { + quote3_error_t ms_retval; + const uint8_t* ms_p_quote; + uint32_t ms_quote_size; + time_t ms_expiration_check_date; + sgx_ql_qv_result_t* ms_p_quote_verification_result; + sgx_ql_qe_report_info_t* ms_p_qve_report_info; + size_t ms_qve_report_info_size; + uint8_t* ms_p_supplemental_data; + uint32_t ms_supplemental_data_size; +} ms_sgx_tls_verify_quote_ocall_t; + +typedef struct ms_pthread_wait_timeout_ocall_t { + int ms_retval; + unsigned long long ms_waiter; + unsigned long long ms_timeout; +} ms_pthread_wait_timeout_ocall_t; + +typedef struct ms_pthread_create_ocall_t { + int ms_retval; + unsigned long long ms_self; +} ms_pthread_create_ocall_t; + +typedef struct ms_pthread_wakeup_ocall_t { + int ms_retval; + unsigned long long ms_waiter; +} ms_pthread_wakeup_ocall_t; + +static sgx_status_t SGX_CDECL sgx_enclave_launch_tls_client(void* pms) +{ + CHECK_REF_POINTER(pms, sizeof(ms_enclave_launch_tls_client_t)); + // + // fence after pointer checks + // + sgx_lfence(); + ms_enclave_launch_tls_client_t* ms = SGX_CAST(ms_enclave_launch_tls_client_t*, pms); + sgx_status_t status = SGX_SUCCESS; + const char* _tmp_server_name = ms->ms_server_name; + size_t _len_server_name = ms->ms_server_name_len ; + char* _in_server_name = NULL; + const char* _tmp_action = ms->ms_action; + size_t _len_action = ms->ms_action_len ; + char* _in_action = NULL; + + CHECK_UNIQUE_POINTER(_tmp_server_name, _len_server_name); + CHECK_UNIQUE_POINTER(_tmp_action, _len_action); + + // + // fence after pointer checks + // + sgx_lfence(); + + if (_tmp_server_name != NULL && _len_server_name != 0) { + _in_server_name = (char*)malloc(_len_server_name); + if (_in_server_name == NULL) { + status = SGX_ERROR_OUT_OF_MEMORY; + goto err; + } + + if (memcpy_s(_in_server_name, _len_server_name, _tmp_server_name, _len_server_name)) { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + + _in_server_name[_len_server_name - 1] = '\0'; + if (_len_server_name != strlen(_in_server_name) + 1) + { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + } + if (_tmp_action != NULL && _len_action != 0) { + _in_action = (char*)malloc(_len_action); + if (_in_action == NULL) { + status = SGX_ERROR_OUT_OF_MEMORY; + goto err; + } + + if (memcpy_s(_in_action, _len_action, _tmp_action, _len_action)) { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + + _in_action[_len_action - 1] = '\0'; + if (_len_action != strlen(_in_action) + 1) + { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + } + + ms->ms_retval = enclave_launch_tls_client((const char*)_in_server_name, ms->ms_server_port, ms->ms_key, (const char*)_in_action); + +err: + if (_in_server_name) free(_in_server_name); + if (_in_action) free(_in_action); + return status; +} + +static sgx_status_t SGX_CDECL sgx_sgx_ra_get_ga(void* pms) +{ + CHECK_REF_POINTER(pms, sizeof(ms_sgx_ra_get_ga_t)); + // + // fence after pointer checks + // + sgx_lfence(); + ms_sgx_ra_get_ga_t* ms = SGX_CAST(ms_sgx_ra_get_ga_t*, pms); + sgx_status_t status = SGX_SUCCESS; + sgx_ec256_public_t* _tmp_g_a = ms->ms_g_a; + size_t _len_g_a = sizeof(sgx_ec256_public_t); + sgx_ec256_public_t* _in_g_a = NULL; + + CHECK_UNIQUE_POINTER(_tmp_g_a, _len_g_a); + + // + // fence after pointer checks + // + sgx_lfence(); + + if (_tmp_g_a != NULL && _len_g_a != 0) { + if ((_in_g_a = (sgx_ec256_public_t*)malloc(_len_g_a)) == NULL) { + status = SGX_ERROR_OUT_OF_MEMORY; + goto err; + } + + memset((void*)_in_g_a, 0, _len_g_a); + } + + ms->ms_retval = sgx_ra_get_ga(ms->ms_context, _in_g_a); + if (_in_g_a) { + if (memcpy_s(_tmp_g_a, _len_g_a, _in_g_a, _len_g_a)) { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + } + +err: + if (_in_g_a) free(_in_g_a); + return status; +} + +static sgx_status_t SGX_CDECL sgx_sgx_ra_proc_msg2_trusted(void* pms) +{ + CHECK_REF_POINTER(pms, sizeof(ms_sgx_ra_proc_msg2_trusted_t)); + // + // fence after pointer checks + // + sgx_lfence(); + ms_sgx_ra_proc_msg2_trusted_t* ms = SGX_CAST(ms_sgx_ra_proc_msg2_trusted_t*, pms); + sgx_status_t status = SGX_SUCCESS; + const sgx_ra_msg2_t* _tmp_p_msg2 = ms->ms_p_msg2; + size_t _len_p_msg2 = sizeof(sgx_ra_msg2_t); + sgx_ra_msg2_t* _in_p_msg2 = NULL; + const sgx_target_info_t* _tmp_p_qe_target = ms->ms_p_qe_target; + size_t _len_p_qe_target = sizeof(sgx_target_info_t); + sgx_target_info_t* _in_p_qe_target = NULL; + sgx_report_t* _tmp_p_report = ms->ms_p_report; + size_t _len_p_report = sizeof(sgx_report_t); + sgx_report_t* _in_p_report = NULL; + sgx_quote_nonce_t* _tmp_p_nonce = ms->ms_p_nonce; + size_t _len_p_nonce = sizeof(sgx_quote_nonce_t); + sgx_quote_nonce_t* _in_p_nonce = NULL; + + CHECK_UNIQUE_POINTER(_tmp_p_msg2, _len_p_msg2); + CHECK_UNIQUE_POINTER(_tmp_p_qe_target, _len_p_qe_target); + CHECK_UNIQUE_POINTER(_tmp_p_report, _len_p_report); + CHECK_UNIQUE_POINTER(_tmp_p_nonce, _len_p_nonce); + + // + // fence after pointer checks + // + sgx_lfence(); + + if (_tmp_p_msg2 != NULL && _len_p_msg2 != 0) { + _in_p_msg2 = (sgx_ra_msg2_t*)malloc(_len_p_msg2); + if (_in_p_msg2 == NULL) { + status = SGX_ERROR_OUT_OF_MEMORY; + goto err; + } + + if (memcpy_s(_in_p_msg2, _len_p_msg2, _tmp_p_msg2, _len_p_msg2)) { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + + } + if (_tmp_p_qe_target != NULL && _len_p_qe_target != 0) { + _in_p_qe_target = (sgx_target_info_t*)malloc(_len_p_qe_target); + if (_in_p_qe_target == NULL) { + status = SGX_ERROR_OUT_OF_MEMORY; + goto err; + } + + if (memcpy_s(_in_p_qe_target, _len_p_qe_target, _tmp_p_qe_target, _len_p_qe_target)) { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + + } + if (_tmp_p_report != NULL && _len_p_report != 0) { + if ((_in_p_report = (sgx_report_t*)malloc(_len_p_report)) == NULL) { + status = SGX_ERROR_OUT_OF_MEMORY; + goto err; + } + + memset((void*)_in_p_report, 0, _len_p_report); + } + if (_tmp_p_nonce != NULL && _len_p_nonce != 0) { + if ((_in_p_nonce = (sgx_quote_nonce_t*)malloc(_len_p_nonce)) == NULL) { + status = SGX_ERROR_OUT_OF_MEMORY; + goto err; + } + + memset((void*)_in_p_nonce, 0, _len_p_nonce); + } + + ms->ms_retval = sgx_ra_proc_msg2_trusted(ms->ms_context, (const sgx_ra_msg2_t*)_in_p_msg2, (const sgx_target_info_t*)_in_p_qe_target, _in_p_report, _in_p_nonce); + if (_in_p_report) { + if (memcpy_s(_tmp_p_report, _len_p_report, _in_p_report, _len_p_report)) { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + } + if (_in_p_nonce) { + if (memcpy_s(_tmp_p_nonce, _len_p_nonce, _in_p_nonce, _len_p_nonce)) { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + } + +err: + if (_in_p_msg2) free(_in_p_msg2); + if (_in_p_qe_target) free(_in_p_qe_target); + if (_in_p_report) free(_in_p_report); + if (_in_p_nonce) free(_in_p_nonce); + return status; +} + +static sgx_status_t SGX_CDECL sgx_sgx_ra_get_msg3_trusted(void* pms) +{ + CHECK_REF_POINTER(pms, sizeof(ms_sgx_ra_get_msg3_trusted_t)); + // + // fence after pointer checks + // + sgx_lfence(); + ms_sgx_ra_get_msg3_trusted_t* ms = SGX_CAST(ms_sgx_ra_get_msg3_trusted_t*, pms); + sgx_status_t status = SGX_SUCCESS; + sgx_report_t* _tmp_qe_report = ms->ms_qe_report; + size_t _len_qe_report = sizeof(sgx_report_t); + sgx_report_t* _in_qe_report = NULL; + sgx_ra_msg3_t* _tmp_p_msg3 = ms->ms_p_msg3; + + CHECK_UNIQUE_POINTER(_tmp_qe_report, _len_qe_report); + + // + // fence after pointer checks + // + sgx_lfence(); + + if (_tmp_qe_report != NULL && _len_qe_report != 0) { + _in_qe_report = (sgx_report_t*)malloc(_len_qe_report); + if (_in_qe_report == NULL) { + status = SGX_ERROR_OUT_OF_MEMORY; + goto err; + } + + if (memcpy_s(_in_qe_report, _len_qe_report, _tmp_qe_report, _len_qe_report)) { + status = SGX_ERROR_UNEXPECTED; + goto err; + } + + } + + ms->ms_retval = sgx_ra_get_msg3_trusted(ms->ms_context, ms->ms_quote_size, _in_qe_report, _tmp_p_msg3, ms->ms_msg3_size); + +err: + if (_in_qe_report) free(_in_qe_report); + return status; +} + +SGX_EXTERNC const struct { + size_t nr_ecall; + struct {void* ecall_addr; uint8_t is_priv; uint8_t is_switchless;} ecall_table[4]; +} g_ecall_table = { + 4, + { + {(void*)(uintptr_t)sgx_enclave_launch_tls_client, 0, 0}, + {(void*)(uintptr_t)sgx_sgx_ra_get_ga, 0, 0}, + {(void*)(uintptr_t)sgx_sgx_ra_proc_msg2_trusted, 0, 0}, + {(void*)(uintptr_t)sgx_sgx_ra_get_msg3_trusted, 0, 0}, + } +}; + +SGX_EXTERNC const struct { + size_t nr_ocall; + uint8_t entry_table[23][4]; +} g_dyn_entry_table = { + 23, + { + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + {0, 0, 0, 0, }, + } +}; + + +sgx_status_t SGX_CDECL ocall_printf(const char* str) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_str = str ? strlen(str) + 1 : 0; + + ms_ocall_printf_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_ocall_printf_t); + void *__tmp = NULL; + + + CHECK_ENCLAVE_POINTER(str, _len_str); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (str != NULL) ? _len_str : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_ocall_printf_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_printf_t)); + ocalloc_size -= sizeof(ms_ocall_printf_t); + + if (str != NULL) { + ms->ms_str = (const char*)__tmp; + if (_len_str % sizeof(*str) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + if (memcpy_s(__tmp, ocalloc_size, str, _len_str)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + __tmp = (void *)((size_t)__tmp + _len_str); + ocalloc_size -= _len_str; + } else { + ms->ms_str = NULL; + } + + status = sgx_ocall(0, ms); + + if (status == SGX_SUCCESS) { + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL ocall_close(int* retval, int fd) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_ocall_close_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_ocall_close_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_ocall_close_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_close_t)); + ocalloc_size -= sizeof(ms_ocall_close_t); + + ms->ms_fd = fd; + status = sgx_ocall(1, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL ocall_sleep(int sec) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_ocall_sleep_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_ocall_sleep_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_ocall_sleep_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_sleep_t)); + ocalloc_size -= sizeof(ms_ocall_sleep_t); + + ms->ms_sec = sec; + status = sgx_ocall(2, ms); + + if (status == SGX_SUCCESS) { + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL ocall_get_current_time(uint64_t* p_current_time) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_p_current_time = sizeof(uint64_t); + + ms_ocall_get_current_time_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_ocall_get_current_time_t); + void *__tmp = NULL; + + void *__tmp_p_current_time = NULL; + + CHECK_ENCLAVE_POINTER(p_current_time, _len_p_current_time); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_current_time != NULL) ? _len_p_current_time : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_ocall_get_current_time_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_get_current_time_t)); + ocalloc_size -= sizeof(ms_ocall_get_current_time_t); + + if (p_current_time != NULL) { + ms->ms_p_current_time = (uint64_t*)__tmp; + __tmp_p_current_time = __tmp; + if (_len_p_current_time % sizeof(*p_current_time) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + memset(__tmp_p_current_time, 0, _len_p_current_time); + __tmp = (void *)((size_t)__tmp + _len_p_current_time); + ocalloc_size -= _len_p_current_time; + } else { + ms->ms_p_current_time = NULL; + } + + status = sgx_ocall(3, ms); + + if (status == SGX_SUCCESS) { + if (p_current_time) { + if (memcpy_s((void*)p_current_time, _len_p_current_time, __tmp_p_current_time, _len_p_current_time)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL ocall_socket(int* retval, int domain, int type, int protocol) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_ocall_socket_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_ocall_socket_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_ocall_socket_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_socket_t)); + ocalloc_size -= sizeof(ms_ocall_socket_t); + + ms->ms_domain = domain; + ms->ms_type = type; + ms->ms_protocol = protocol; + status = sgx_ocall(4, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + errno = ms->ocall_errno; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL ocall_connect(int* retval, int fd, const struct sockaddr* addr, socklen_t len) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_addr = len; + + ms_ocall_connect_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_ocall_connect_t); + void *__tmp = NULL; + + + CHECK_ENCLAVE_POINTER(addr, _len_addr); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (addr != NULL) ? _len_addr : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_ocall_connect_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_ocall_connect_t)); + ocalloc_size -= sizeof(ms_ocall_connect_t); + + ms->ms_fd = fd; + if (addr != NULL) { + ms->ms_addr = (const struct sockaddr*)__tmp; + if (memcpy_s(__tmp, ocalloc_size, addr, _len_addr)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + __tmp = (void *)((size_t)__tmp + _len_addr); + ocalloc_size -= _len_addr; + } else { + ms->ms_addr = NULL; + } + + ms->ms_len = len; + status = sgx_ocall(5, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + errno = ms->ocall_errno; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_oc_cpuidex(int cpuinfo[4], int leaf, int subleaf) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_cpuinfo = 4 * sizeof(int); + + ms_sgx_oc_cpuidex_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_oc_cpuidex_t); + void *__tmp = NULL; + + void *__tmp_cpuinfo = NULL; + + CHECK_ENCLAVE_POINTER(cpuinfo, _len_cpuinfo); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (cpuinfo != NULL) ? _len_cpuinfo : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_oc_cpuidex_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_oc_cpuidex_t)); + ocalloc_size -= sizeof(ms_sgx_oc_cpuidex_t); + + if (cpuinfo != NULL) { + ms->ms_cpuinfo = (int*)__tmp; + __tmp_cpuinfo = __tmp; + if (_len_cpuinfo % sizeof(*cpuinfo) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + memset(__tmp_cpuinfo, 0, _len_cpuinfo); + __tmp = (void *)((size_t)__tmp + _len_cpuinfo); + ocalloc_size -= _len_cpuinfo; + } else { + ms->ms_cpuinfo = NULL; + } + + ms->ms_leaf = leaf; + ms->ms_subleaf = subleaf; + status = sgx_ocall(6, ms); + + if (status == SGX_SUCCESS) { + if (cpuinfo) { + if (memcpy_s((void*)cpuinfo, _len_cpuinfo, __tmp_cpuinfo, _len_cpuinfo)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_thread_wait_untrusted_event_ocall(int* retval, const void* self) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_sgx_thread_wait_untrusted_event_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_thread_wait_untrusted_event_ocall_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_thread_wait_untrusted_event_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_thread_wait_untrusted_event_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_thread_wait_untrusted_event_ocall_t); + + ms->ms_self = self; + status = sgx_ocall(7, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_thread_set_untrusted_event_ocall(int* retval, const void* waiter) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_sgx_thread_set_untrusted_event_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_thread_set_untrusted_event_ocall_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_thread_set_untrusted_event_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_thread_set_untrusted_event_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_thread_set_untrusted_event_ocall_t); + + ms->ms_waiter = waiter; + status = sgx_ocall(8, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_thread_setwait_untrusted_events_ocall(int* retval, const void* waiter, const void* self) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_sgx_thread_setwait_untrusted_events_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_thread_setwait_untrusted_events_ocall_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_thread_setwait_untrusted_events_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_thread_setwait_untrusted_events_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_thread_setwait_untrusted_events_ocall_t); + + ms->ms_waiter = waiter; + ms->ms_self = self; + status = sgx_ocall(9, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_thread_set_multiple_untrusted_events_ocall(int* retval, const void** waiters, size_t total) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_waiters = total * sizeof(void*); + + ms_sgx_thread_set_multiple_untrusted_events_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_thread_set_multiple_untrusted_events_ocall_t); + void *__tmp = NULL; + + + CHECK_ENCLAVE_POINTER(waiters, _len_waiters); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (waiters != NULL) ? _len_waiters : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_thread_set_multiple_untrusted_events_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_thread_set_multiple_untrusted_events_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_thread_set_multiple_untrusted_events_ocall_t); + + if (waiters != NULL) { + ms->ms_waiters = (const void**)__tmp; + if (_len_waiters % sizeof(*waiters) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + if (memcpy_s(__tmp, ocalloc_size, waiters, _len_waiters)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + __tmp = (void *)((size_t)__tmp + _len_waiters); + ocalloc_size -= _len_waiters; + } else { + ms->ms_waiters = NULL; + } + + ms->ms_total = total; + status = sgx_ocall(10, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL u_sgxssl_ftime(void* timeptr, uint32_t timeb_len) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_timeptr = timeb_len; + + ms_u_sgxssl_ftime_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_u_sgxssl_ftime_t); + void *__tmp = NULL; + + void *__tmp_timeptr = NULL; + + CHECK_ENCLAVE_POINTER(timeptr, _len_timeptr); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (timeptr != NULL) ? _len_timeptr : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_u_sgxssl_ftime_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_u_sgxssl_ftime_t)); + ocalloc_size -= sizeof(ms_u_sgxssl_ftime_t); + + if (timeptr != NULL) { + ms->ms_timeptr = (void*)__tmp; + __tmp_timeptr = __tmp; + memset(__tmp_timeptr, 0, _len_timeptr); + __tmp = (void *)((size_t)__tmp + _len_timeptr); + ocalloc_size -= _len_timeptr; + } else { + ms->ms_timeptr = NULL; + } + + ms->ms_timeb_len = timeb_len; + status = sgx_ocall(11, ms); + + if (status == SGX_SUCCESS) { + if (timeptr) { + if (memcpy_s((void*)timeptr, _len_timeptr, __tmp_timeptr, _len_timeptr)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL u_sgxssl_write(size_t* retval, int fd, const void* buf, size_t n) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_buf = n; + + ms_u_sgxssl_write_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_u_sgxssl_write_t); + void *__tmp = NULL; + + + CHECK_ENCLAVE_POINTER(buf, _len_buf); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (buf != NULL) ? _len_buf : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_u_sgxssl_write_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_u_sgxssl_write_t)); + ocalloc_size -= sizeof(ms_u_sgxssl_write_t); + + ms->ms_fd = fd; + if (buf != NULL) { + ms->ms_buf = (const void*)__tmp; + if (memcpy_s(__tmp, ocalloc_size, buf, _len_buf)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + __tmp = (void *)((size_t)__tmp + _len_buf); + ocalloc_size -= _len_buf; + } else { + ms->ms_buf = NULL; + } + + ms->ms_n = n; + status = sgx_ocall(12, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL u_sgxssl_read(size_t* retval, int fd, void* buf, size_t count) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_buf = count; + + ms_u_sgxssl_read_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_u_sgxssl_read_t); + void *__tmp = NULL; + + void *__tmp_buf = NULL; + + CHECK_ENCLAVE_POINTER(buf, _len_buf); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (buf != NULL) ? _len_buf : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_u_sgxssl_read_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_u_sgxssl_read_t)); + ocalloc_size -= sizeof(ms_u_sgxssl_read_t); + + ms->ms_fd = fd; + if (buf != NULL) { + ms->ms_buf = (void*)__tmp; + __tmp_buf = __tmp; + memset(__tmp_buf, 0, _len_buf); + __tmp = (void *)((size_t)__tmp + _len_buf); + ocalloc_size -= _len_buf; + } else { + ms->ms_buf = NULL; + } + + ms->ms_count = count; + status = sgx_ocall(13, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + if (buf) { + if (memcpy_s((void*)buf, _len_buf, __tmp_buf, _len_buf)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL u_sgxssl_close(int* retval, int fd) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_u_sgxssl_close_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_u_sgxssl_close_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_u_sgxssl_close_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_u_sgxssl_close_t)); + ocalloc_size -= sizeof(ms_u_sgxssl_close_t); + + ms->ms_fd = fd; + status = sgx_ocall(14, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_tls_get_qe_target_info_ocall(quote3_error_t* retval, sgx_target_info_t* p_target_info, size_t target_info_size) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_p_target_info = target_info_size; + + ms_sgx_tls_get_qe_target_info_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_tls_get_qe_target_info_ocall_t); + void *__tmp = NULL; + + void *__tmp_p_target_info = NULL; + + CHECK_ENCLAVE_POINTER(p_target_info, _len_p_target_info); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_target_info != NULL) ? _len_p_target_info : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_tls_get_qe_target_info_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_tls_get_qe_target_info_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_tls_get_qe_target_info_ocall_t); + + if (p_target_info != NULL) { + ms->ms_p_target_info = (sgx_target_info_t*)__tmp; + __tmp_p_target_info = __tmp; + memset(__tmp_p_target_info, 0, _len_p_target_info); + __tmp = (void *)((size_t)__tmp + _len_p_target_info); + ocalloc_size -= _len_p_target_info; + } else { + ms->ms_p_target_info = NULL; + } + + ms->ms_target_info_size = target_info_size; + status = sgx_ocall(15, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + if (p_target_info) { + if (memcpy_s((void*)p_target_info, _len_p_target_info, __tmp_p_target_info, _len_p_target_info)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_tls_get_quote_size_ocall(quote3_error_t* retval, uint32_t* p_quote_size) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_p_quote_size = sizeof(uint32_t); + + ms_sgx_tls_get_quote_size_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_tls_get_quote_size_ocall_t); + void *__tmp = NULL; + + void *__tmp_p_quote_size = NULL; + + CHECK_ENCLAVE_POINTER(p_quote_size, _len_p_quote_size); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_quote_size != NULL) ? _len_p_quote_size : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_tls_get_quote_size_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_tls_get_quote_size_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_tls_get_quote_size_ocall_t); + + if (p_quote_size != NULL) { + ms->ms_p_quote_size = (uint32_t*)__tmp; + __tmp_p_quote_size = __tmp; + if (_len_p_quote_size % sizeof(*p_quote_size) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + memset(__tmp_p_quote_size, 0, _len_p_quote_size); + __tmp = (void *)((size_t)__tmp + _len_p_quote_size); + ocalloc_size -= _len_p_quote_size; + } else { + ms->ms_p_quote_size = NULL; + } + + status = sgx_ocall(16, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + if (p_quote_size) { + if (memcpy_s((void*)p_quote_size, _len_p_quote_size, __tmp_p_quote_size, _len_p_quote_size)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_tls_get_quote_ocall(quote3_error_t* retval, sgx_report_t* p_report, size_t report_size, uint8_t* p_quote, uint32_t quote_size) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_p_report = report_size; + size_t _len_p_quote = quote_size; + + ms_sgx_tls_get_quote_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_tls_get_quote_ocall_t); + void *__tmp = NULL; + + void *__tmp_p_quote = NULL; + + CHECK_ENCLAVE_POINTER(p_report, _len_p_report); + CHECK_ENCLAVE_POINTER(p_quote, _len_p_quote); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_report != NULL) ? _len_p_report : 0)) + return SGX_ERROR_INVALID_PARAMETER; + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_quote != NULL) ? _len_p_quote : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_tls_get_quote_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_tls_get_quote_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_tls_get_quote_ocall_t); + + if (p_report != NULL) { + ms->ms_p_report = (sgx_report_t*)__tmp; + if (memcpy_s(__tmp, ocalloc_size, p_report, _len_p_report)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + __tmp = (void *)((size_t)__tmp + _len_p_report); + ocalloc_size -= _len_p_report; + } else { + ms->ms_p_report = NULL; + } + + ms->ms_report_size = report_size; + if (p_quote != NULL) { + ms->ms_p_quote = (uint8_t*)__tmp; + __tmp_p_quote = __tmp; + if (_len_p_quote % sizeof(*p_quote) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + memset(__tmp_p_quote, 0, _len_p_quote); + __tmp = (void *)((size_t)__tmp + _len_p_quote); + ocalloc_size -= _len_p_quote; + } else { + ms->ms_p_quote = NULL; + } + + ms->ms_quote_size = quote_size; + status = sgx_ocall(17, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + if (p_quote) { + if (memcpy_s((void*)p_quote, _len_p_quote, __tmp_p_quote, _len_p_quote)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_tls_get_supplemental_data_size_ocall(quote3_error_t* retval, uint32_t* p_supplemental_data_size) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_p_supplemental_data_size = sizeof(uint32_t); + + ms_sgx_tls_get_supplemental_data_size_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_tls_get_supplemental_data_size_ocall_t); + void *__tmp = NULL; + + void *__tmp_p_supplemental_data_size = NULL; + + CHECK_ENCLAVE_POINTER(p_supplemental_data_size, _len_p_supplemental_data_size); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_supplemental_data_size != NULL) ? _len_p_supplemental_data_size : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_tls_get_supplemental_data_size_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_tls_get_supplemental_data_size_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_tls_get_supplemental_data_size_ocall_t); + + if (p_supplemental_data_size != NULL) { + ms->ms_p_supplemental_data_size = (uint32_t*)__tmp; + __tmp_p_supplemental_data_size = __tmp; + if (_len_p_supplemental_data_size % sizeof(*p_supplemental_data_size) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + memset(__tmp_p_supplemental_data_size, 0, _len_p_supplemental_data_size); + __tmp = (void *)((size_t)__tmp + _len_p_supplemental_data_size); + ocalloc_size -= _len_p_supplemental_data_size; + } else { + ms->ms_p_supplemental_data_size = NULL; + } + + status = sgx_ocall(18, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + if (p_supplemental_data_size) { + if (memcpy_s((void*)p_supplemental_data_size, _len_p_supplemental_data_size, __tmp_p_supplemental_data_size, _len_p_supplemental_data_size)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL sgx_tls_verify_quote_ocall(quote3_error_t* retval, const uint8_t* p_quote, uint32_t quote_size, time_t expiration_check_date, sgx_ql_qv_result_t* p_quote_verification_result, sgx_ql_qe_report_info_t* p_qve_report_info, size_t qve_report_info_size, uint8_t* p_supplemental_data, uint32_t supplemental_data_size) +{ + sgx_status_t status = SGX_SUCCESS; + size_t _len_p_quote = quote_size; + size_t _len_p_quote_verification_result = sizeof(sgx_ql_qv_result_t); + size_t _len_p_qve_report_info = qve_report_info_size; + size_t _len_p_supplemental_data = supplemental_data_size; + + ms_sgx_tls_verify_quote_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_sgx_tls_verify_quote_ocall_t); + void *__tmp = NULL; + + void *__tmp_p_quote_verification_result = NULL; + void *__tmp_p_qve_report_info = NULL; + void *__tmp_p_supplemental_data = NULL; + + CHECK_ENCLAVE_POINTER(p_quote, _len_p_quote); + CHECK_ENCLAVE_POINTER(p_quote_verification_result, _len_p_quote_verification_result); + CHECK_ENCLAVE_POINTER(p_qve_report_info, _len_p_qve_report_info); + CHECK_ENCLAVE_POINTER(p_supplemental_data, _len_p_supplemental_data); + + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_quote != NULL) ? _len_p_quote : 0)) + return SGX_ERROR_INVALID_PARAMETER; + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_quote_verification_result != NULL) ? _len_p_quote_verification_result : 0)) + return SGX_ERROR_INVALID_PARAMETER; + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_qve_report_info != NULL) ? _len_p_qve_report_info : 0)) + return SGX_ERROR_INVALID_PARAMETER; + if (ADD_ASSIGN_OVERFLOW(ocalloc_size, (p_supplemental_data != NULL) ? _len_p_supplemental_data : 0)) + return SGX_ERROR_INVALID_PARAMETER; + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_sgx_tls_verify_quote_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_sgx_tls_verify_quote_ocall_t)); + ocalloc_size -= sizeof(ms_sgx_tls_verify_quote_ocall_t); + + if (p_quote != NULL) { + ms->ms_p_quote = (const uint8_t*)__tmp; + if (_len_p_quote % sizeof(*p_quote) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + if (memcpy_s(__tmp, ocalloc_size, p_quote, _len_p_quote)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + __tmp = (void *)((size_t)__tmp + _len_p_quote); + ocalloc_size -= _len_p_quote; + } else { + ms->ms_p_quote = NULL; + } + + ms->ms_quote_size = quote_size; + ms->ms_expiration_check_date = expiration_check_date; + if (p_quote_verification_result != NULL) { + ms->ms_p_quote_verification_result = (sgx_ql_qv_result_t*)__tmp; + __tmp_p_quote_verification_result = __tmp; + memset(__tmp_p_quote_verification_result, 0, _len_p_quote_verification_result); + __tmp = (void *)((size_t)__tmp + _len_p_quote_verification_result); + ocalloc_size -= _len_p_quote_verification_result; + } else { + ms->ms_p_quote_verification_result = NULL; + } + + if (p_qve_report_info != NULL) { + ms->ms_p_qve_report_info = (sgx_ql_qe_report_info_t*)__tmp; + __tmp_p_qve_report_info = __tmp; + if (memcpy_s(__tmp, ocalloc_size, p_qve_report_info, _len_p_qve_report_info)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + __tmp = (void *)((size_t)__tmp + _len_p_qve_report_info); + ocalloc_size -= _len_p_qve_report_info; + } else { + ms->ms_p_qve_report_info = NULL; + } + + ms->ms_qve_report_info_size = qve_report_info_size; + if (p_supplemental_data != NULL) { + ms->ms_p_supplemental_data = (uint8_t*)__tmp; + __tmp_p_supplemental_data = __tmp; + if (_len_p_supplemental_data % sizeof(*p_supplemental_data) != 0) { + sgx_ocfree(); + return SGX_ERROR_INVALID_PARAMETER; + } + memset(__tmp_p_supplemental_data, 0, _len_p_supplemental_data); + __tmp = (void *)((size_t)__tmp + _len_p_supplemental_data); + ocalloc_size -= _len_p_supplemental_data; + } else { + ms->ms_p_supplemental_data = NULL; + } + + ms->ms_supplemental_data_size = supplemental_data_size; + status = sgx_ocall(19, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + if (p_quote_verification_result) { + if (memcpy_s((void*)p_quote_verification_result, _len_p_quote_verification_result, __tmp_p_quote_verification_result, _len_p_quote_verification_result)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + if (p_qve_report_info) { + if (memcpy_s((void*)p_qve_report_info, _len_p_qve_report_info, __tmp_p_qve_report_info, _len_p_qve_report_info)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + if (p_supplemental_data) { + if (memcpy_s((void*)p_supplemental_data, _len_p_supplemental_data, __tmp_p_supplemental_data, _len_p_supplemental_data)) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + } + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL pthread_wait_timeout_ocall(int* retval, unsigned long long waiter, unsigned long long timeout) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_pthread_wait_timeout_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_pthread_wait_timeout_ocall_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_pthread_wait_timeout_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_pthread_wait_timeout_ocall_t)); + ocalloc_size -= sizeof(ms_pthread_wait_timeout_ocall_t); + + ms->ms_waiter = waiter; + ms->ms_timeout = timeout; + status = sgx_ocall(20, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL pthread_create_ocall(int* retval, unsigned long long self) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_pthread_create_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_pthread_create_ocall_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_pthread_create_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_pthread_create_ocall_t)); + ocalloc_size -= sizeof(ms_pthread_create_ocall_t); + + ms->ms_self = self; + status = sgx_ocall(21, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + +sgx_status_t SGX_CDECL pthread_wakeup_ocall(int* retval, unsigned long long waiter) +{ + sgx_status_t status = SGX_SUCCESS; + + ms_pthread_wakeup_ocall_t* ms = NULL; + size_t ocalloc_size = sizeof(ms_pthread_wakeup_ocall_t); + void *__tmp = NULL; + + + __tmp = sgx_ocalloc(ocalloc_size); + if (__tmp == NULL) { + sgx_ocfree(); + return SGX_ERROR_UNEXPECTED; + } + ms = (ms_pthread_wakeup_ocall_t*)__tmp; + __tmp = (void *)((size_t)__tmp + sizeof(ms_pthread_wakeup_ocall_t)); + ocalloc_size -= sizeof(ms_pthread_wakeup_ocall_t); + + ms->ms_waiter = waiter; + status = sgx_ocall(22, ms); + + if (status == SGX_SUCCESS) { + if (retval) *retval = ms->ms_retval; + } + sgx_ocfree(); + return status; +} + diff --git a/dkeyserver/dkeyrotation/Enclave/enclave_t.h b/dkeyserver/dkeyrotation/Enclave/enclave_t.h new file mode 100644 index 00000000..86de1f47 --- /dev/null +++ b/dkeyserver/dkeyrotation/Enclave/enclave_t.h @@ -0,0 +1,66 @@ +#ifndef ENCLAVE_T_H__ +#define ENCLAVE_T_H__ + +#include +#include +#include +#include "sgx_edger8r.h" /* for sgx_ocall etc. */ + +#include "sgx_ttls.h" +#include "sgx_key_exchange.h" +#include "sgx_quote.h" +#include "sgx_trts.h" +#include "stdbool.h" +#include "datatypes.h" +#include "dh_session_protocol.h" +#include "sys/socket.h" +#include "sys/select.h" +#include "netdb.h" +#include "poll.h" +#include "sgx_report.h" +#include "sgx_qve_header.h" +#include "sgx_ql_lib_common.h" +#include "sgx_ql_quote.h" + +#include /* for size_t */ + +#define SGX_CAST(type, item) ((type)(item)) + +#ifdef __cplusplus +extern "C" { +#endif + +int enclave_launch_tls_client(const char* server_name, uint16_t server_port, uint32_t key, const char* action); +sgx_status_t sgx_ra_get_ga(sgx_ra_context_t context, sgx_ec256_public_t* g_a); +sgx_status_t sgx_ra_proc_msg2_trusted(sgx_ra_context_t context, const sgx_ra_msg2_t* p_msg2, const sgx_target_info_t* p_qe_target, sgx_report_t* p_report, sgx_quote_nonce_t* p_nonce); +sgx_status_t sgx_ra_get_msg3_trusted(sgx_ra_context_t context, uint32_t quote_size, sgx_report_t* qe_report, sgx_ra_msg3_t* p_msg3, uint32_t msg3_size); + +sgx_status_t SGX_CDECL ocall_printf(const char* str); +sgx_status_t SGX_CDECL ocall_close(int* retval, int fd); +sgx_status_t SGX_CDECL ocall_sleep(int sec); +sgx_status_t SGX_CDECL ocall_get_current_time(uint64_t* p_current_time); +sgx_status_t SGX_CDECL ocall_socket(int* retval, int domain, int type, int protocol); +sgx_status_t SGX_CDECL ocall_connect(int* retval, int fd, const struct sockaddr* addr, socklen_t len); +sgx_status_t SGX_CDECL sgx_oc_cpuidex(int cpuinfo[4], int leaf, int subleaf); +sgx_status_t SGX_CDECL sgx_thread_wait_untrusted_event_ocall(int* retval, const void* self); +sgx_status_t SGX_CDECL sgx_thread_set_untrusted_event_ocall(int* retval, const void* waiter); +sgx_status_t SGX_CDECL sgx_thread_setwait_untrusted_events_ocall(int* retval, const void* waiter, const void* self); +sgx_status_t SGX_CDECL sgx_thread_set_multiple_untrusted_events_ocall(int* retval, const void** waiters, size_t total); +sgx_status_t SGX_CDECL u_sgxssl_ftime(void* timeptr, uint32_t timeb_len); +sgx_status_t SGX_CDECL u_sgxssl_write(size_t* retval, int fd, const void* buf, size_t n); +sgx_status_t SGX_CDECL u_sgxssl_read(size_t* retval, int fd, void* buf, size_t count); +sgx_status_t SGX_CDECL u_sgxssl_close(int* retval, int fd); +sgx_status_t SGX_CDECL sgx_tls_get_qe_target_info_ocall(quote3_error_t* retval, sgx_target_info_t* p_target_info, size_t target_info_size); +sgx_status_t SGX_CDECL sgx_tls_get_quote_size_ocall(quote3_error_t* retval, uint32_t* p_quote_size); +sgx_status_t SGX_CDECL sgx_tls_get_quote_ocall(quote3_error_t* retval, sgx_report_t* p_report, size_t report_size, uint8_t* p_quote, uint32_t quote_size); +sgx_status_t SGX_CDECL sgx_tls_get_supplemental_data_size_ocall(quote3_error_t* retval, uint32_t* p_supplemental_data_size); +sgx_status_t SGX_CDECL sgx_tls_verify_quote_ocall(quote3_error_t* retval, const uint8_t* p_quote, uint32_t quote_size, time_t expiration_check_date, sgx_ql_qv_result_t* p_quote_verification_result, sgx_ql_qe_report_info_t* p_qve_report_info, size_t qve_report_info_size, uint8_t* p_supplemental_data, uint32_t supplemental_data_size); +sgx_status_t SGX_CDECL pthread_wait_timeout_ocall(int* retval, unsigned long long waiter, unsigned long long timeout); +sgx_status_t SGX_CDECL pthread_create_ocall(int* retval, unsigned long long self); +sgx_status_t SGX_CDECL pthread_wakeup_ocall(int* retval, unsigned long long waiter); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/dkeyserver/dkeyrotation/Enclave/enclave_t.o b/dkeyserver/dkeyrotation/Enclave/enclave_t.o new file mode 100644 index 00000000..0f9257f2 Binary files /dev/null and b/dkeyserver/dkeyrotation/Enclave/enclave_t.o differ diff --git a/dkeyserver/dkeyrotation/Makefile b/dkeyserver/dkeyrotation/Makefile new file mode 100644 index 00000000..11568c65 --- /dev/null +++ b/dkeyserver/dkeyrotation/Makefile @@ -0,0 +1,208 @@ +# +# Copyright (C) 2011-2021 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# + +include ../../buildenv.mk + +App_Name := ehsm-dkeyrotation +Enclave_Name := libenclave-$(App_Name).so +Signed_Enclave_Name := libenclave-$(App_Name).signed.so + +Enclave_Config_File := Enclave/enclave.config.xml +Enclave_Signing_Key := Enclave/enclave_private_test.pem + +OUT = $(TOPDIR)/$(OUTDIR)/$(App_Name) + +######## App Settings ######## + +App_Cpp_Files := $(wildcard App/*.cpp) +App_Cpp_Files += $(wildcard $(LOG_DIR)/*.cpp) + +App_Include_Paths := \ + -IApp \ + -I$(LOG_DIR) \ + -I$(SGX_SDK)/include \ + -I$(TOPDIR)/include + +App_C_Flags := $(SGX_COMMON_FLAGS) -fPIC -Wno-attributes $(App_Include_Paths) -DRUNTIME_FOLDER=\"$(RUNTIME_FOLDER)\" + +# Three configuration modes - Debug, prerelease, release +# Debug - Macro DEBUG enabled. +# Prerelease - Macro NDEBUG and EDEBUG enabled. +# Release - Macro NDEBUG enabled. +ifeq ($(SGX_DEBUG), 1) + App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG +else ifeq ($(SGX_PRERELEASE), 1) + App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG +else + App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG +endif + +App_Cpp_Flags := $(App_C_Flags) -std=c++11 +App_Link_Flags := -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread -lra_ukey_exchange -L$(TOPDIR)/$(OUTLIB_DIR) -Wl,-rpath=$(CURDIR) -L$(OPENSSL_LIBRARY_PATH) -Wl,--whole-archive -l$(SGXSSL_Untrusted_Library_Name) -Wl,--no-whole-archive -lsgx_utls -lsgx_dcap_ql -lsgx_dcap_quoteverify -lcrypto -llog4cplus + +ifneq ($(SGX_MODE), HW) + App_Link_Flags += -lsgx_epid_sim -lsgx_quote_ex_sim +else + App_Link_Flags += -lsgx_quote_ex -lsgx_uae_service -lsgx_dcap_ql -ldl +endif + +App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o) + +######## Enclave Settings ######## +Enclave_Cpp_Files := $(wildcard Enclave/*.cpp) +Enclave_Cpp_Files += $(wildcard ../../utils/sgx_socket/tls/*.cpp) + +Enclave_Include_Paths := \ + -IEnclave \ + -I$(SGX_SDK)/include \ + -I$(SGX_SDK)/include/tlibc \ + -I$(SGX_SDK)/include/libcxx \ + -I$(TOPDIR)/include \ + -I$(OPENSSL_PATH)/include \ + -I$(SOCKET_DIR) \ + -I$(LOG_DIR) \ + -I$(SOCKET_DIR)/tls + +Enclave_C_Flags := \ + $(Enclave_Include_Paths) \ + -nostdinc -fvisibility=hidden \ + -fpie -ffunction-sections \ + -fdata-sections \ + $(MITIGATION_CFLAGS) + +CC_BELOW_4_9 := $(shell expr "`$(CC) -dumpversion`" \< "4.9") +ifeq ($(CC_BELOW_4_9), 1) + Enclave_C_Flags += -fstack-protector +else + Enclave_C_Flags += -fstack-protector-strong +endif + +Enclave_Cpp_Flags := $(Enclave_C_Flags) -nostdinc++ -include "tsgxsslio.h" + +# Enable the security flags +Enclave_Security_Link_Flags := -Wl,-z,relro,-z,now,-z,noexecstack + +# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries: +# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options, +# so that the whole content of trts is included in the enclave. +# 2. For other libraries, you just need to pull the required symbols. +# Use `--start-group' and `--end-group' to link these libraries. +# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options. +# Otherwise, you may get some undesirable errors. +Enclave_Link_Flags := $(MITIGATION_LDFLAGS) $(Enclave_Security_Link_Flags) \ + $(SgxSSL_Link_Libraries) \ + -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_TRUSTED_LIBRARY_PATH) \ + -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \ + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -lsgx_tcrypto -lsgx_dcap_tvl -lsgx_ttls -l$(Service_Library_Name) -lra_tkey_exchange -L$(TOPDIR)/$(OUTLIB_DIR) -Wl,--end-group \ + -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ + -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ + -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections \ + -Wl,--version-script=Enclave/enclave.lds + +Enclave_Cpp_Objects := $(sort $(Enclave_Cpp_Files:.cpp=.o)) + +######## Build Settings ######## +.PHONY: all target clean +all: target + @$(MAKE) target + @mkdir -p $(OUT) + @mv $(App_Name) $(Signed_Enclave_Name) $(Enclave_Name) $(OUT) + +ifeq ($(Build_Mode), HW_RELEASE) +target: $(App_Name) $(Enclave_Name) +else +target: $(App_Name) $(Signed_Enclave_Name) +endif + +clean: + @rm -f $(App_Cpp_Objects) $(Enclave_Cpp_Objects) App/auto_version.h App/enclave_u.* Enclave/enclave_t.* + @rm -rf $(OUT) + +######## App Objects ######## +App/auto_version.h: + @`touch App/auto_version.h` + @echo "#ifndef EHSM_DKEYCACHE_AUTO_VERSION_H" > App/auto_version.h + @echo "#define EHSM_DKEYCACHE_AUTO_VERSION_H" >> App/auto_version.h + @echo "#define EHSM_VERSION \"$(VERSION_STRING)\"" >> App/auto_version.h + @echo "#define EHSM_DATE \"$(DATE_STRING)\"" >> App/auto_version.h + @echo "#define EHSM_GIT_SHA \"$(EHSM_KMS_GIT_SHA)\"" >> App/auto_version.h + @echo "#endif //EHSM_DKEYCACHE_AUTO_VERSION_H" >> App/auto_version.h + @echo " ==> touch App/auto_version.h" + +App/enclave_u.h: $(SGX_EDGER8R) Enclave/enclave.edl + @cd App && $(SGX_EDGER8R) --untrusted ../Enclave/enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include --search-path $(OPENSSL_PATH)/include --search-path $(SOCKET_DIR) --search-path $(LOG_DIR) + @echo "GEN => $@" + +App/enclave_u.c: App/enclave_u.h + +App/enclave_u.o: App/enclave_u.c + @$(CXX) $(SGX_COMMON_CFLAGS) $(App_C_Flags) -c $< -o $@ + @echo "CXX <= $<" + +App/%.o: App/%.cpp App/auto_version.h + @$(CXX) $(SGX_COMMON_CXXFLAGS) $(App_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(LOG_DIR)/%.o: $(LOG_DIR)/%.cpp + @$(CXX) $(App_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(App_Name): App/enclave_u.o $(App_Cpp_Objects) App/auto_version.h + @$(CXX) $^ -o $@ $(App_Link_Flags) -lcurl -ljsoncpp + @echo "LINK => $@" + +######## Enclave Objects ######## + +Enclave/enclave_t.h: $(SGX_EDGER8R) Enclave/enclave.edl + @cd Enclave && $(SGX_EDGER8R) --trusted enclave.edl --search-path ../Enclave --search-path $(SOCKET_DIR)/tls --search-path $(SGX_SDK)/include --search-path $(OPENSSL_PATH)/include --search-path $(SOCKET_DIR) + @echo "GEN => $@" + +Enclave/enclave_t.c: Enclave/enclave_t.h + +Enclave/enclave_t.o: Enclave/enclave_t.c + @$(CXX) $(SGX_COMMON_CFLAGS) $(Enclave_C_Flags) -c $< -o $@ + @echo "CXX <= $<" + +Enclave/%.o: Enclave/%.cpp Enclave/enclave_t.h + @$(CXX) $(SGX_COMMON_CXXFLAGS) $(Enclave_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +../../utils/sgx_socket/tls/%.o: ../../utils/sgx_socket/tls/%.cpp Enclave/enclave_t.h + @$(CXX) $(SGX_COMMON_CXXFLAGS) $(Enclave_Cpp_Flags) -c $< -o $@ + @echo "CXX <= $<" + +$(Enclave_Name): Enclave/enclave_t.o $(Enclave_Cpp_Objects) + @$(CXX) $^ -o $@ $(Enclave_Link_Flags) + @echo "LINK => $@" + +$(Signed_Enclave_Name): $(Enclave_Name) + @$(SGX_ENCLAVE_SIGNER) sign -key $(Enclave_Signing_Key) -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File) + @echo "SIGN => $@" diff --git a/include/datatypes.h b/include/datatypes.h index 81027a8a..7e4619f3 100644 --- a/include/datatypes.h +++ b/include/datatypes.h @@ -115,7 +115,8 @@ typedef int errno_t; #define EH_PAYLOAD_MAX_SIZE (12*1024) #define EH_QUOTE_MAX_SIZE (8*1024) -#define SGX_DOMAIN_KEY_SIZE 32 +#define SGX_DOMAIN_KEY_SIZE 32 +#define DOMAINKEY_HASH_SIZE 32 #define RSA_2048_KEY_BITS 2048 #define RSA_3072_KEY_BITS 3072 @@ -187,7 +188,48 @@ typedef enum { EH_PAD_RSA_PKCS1_PSS = 6 } ehsm_padding_mode_t; -#pragma pack(push,1) +typedef enum +{ + UNKNOWN_CMD = 0, + GET_DOMAINKEY = 1, + START_ROTATION = 2, + STOP_AUTO_ROTATION = 3, + SET_PERIOD = 4, + GET_PERIOD = 5, + GET_NEXT_ROTATION_DATETIME = 6, + UPDATE_CMK = 7 +} dkeyserver_command; + +typedef enum +{ + MSG_HEARTBEAT = 0, + MSG_ROTATE_START = -1, + MSG_ROTATE_END = -2, + MSG_DOMAINKEY = -3 +} ehsm_tls_msg_type_t; + +typedef struct dkey_server_domainkey +{ + uint64_t createTime; + uint8_t dk_hash[DOMAINKEY_HASH_SIZE]; + uint8_t domainkey[SGX_DOMAIN_KEY_SIZE]; +} dkey_server_domainkey; + +typedef struct _request_header_t +{ + uint32_t cmd; + size_t period; + size_t password; +} _request_header_t; + +typedef struct _response_header_t +{ + uint32_t type; + uint8_t domainKey[32]; + size_t period; +} _response_header_t; + +#pragma pack(push, 1) typedef struct { uint32_t datalen; @@ -201,9 +243,10 @@ typedef struct { ehsm_keyorigin_t origin; ehsm_keypurpose_t purpose; - uint32_t apiversion; - uint8_t descrption[16]; - uint8_t createdate[8]; + uint32_t apiversion; + uint8_t descrption[16]; + uint8_t createdate[8]; + uint8_t dk_hashcode[32]; } ehsm_keymetadata_t; typedef struct { @@ -218,6 +261,11 @@ typedef enum { LOG_WARN = 30000, LOG_ERROR = 40000 } log_type; +typedef struct FdPoolStruct +{ + int fd; + int errorCnt; +} FdPool; //Format of the AES-GCM message being exchanged between the source and the destination enclaves typedef struct _secure_message_t diff --git a/include/json_utils.h b/include/json_utils.h index ee23637c..f004a775 100644 --- a/include/json_utils.h +++ b/include/json_utils.h @@ -297,7 +297,7 @@ class JsonObj return readData(key); } - bool hasOwnProperty(std::string key) { return !m_json[key].isNull(); } + bool hasOwnProperty(std::string key) { return m_json.isMember(key); } }; class RetJsonObj diff --git a/utils/log4cplus/elog_utils.h b/utils/log4cplus/elog_utils.h index 0ecdd89c..23ced65a 100644 --- a/utils/log4cplus/elog_utils.h +++ b/utils/log4cplus/elog_utils.h @@ -36,7 +36,7 @@ #include #include "datatypes.h" -#define IS_DEBUG false +#define IS_DEBUG true #define BLUE "\033[0;32;34m" #define NONE "\033[m" diff --git a/utils/log4cplus/ulog_utils.h b/utils/log4cplus/ulog_utils.h index f35b178e..55d36577 100644 --- a/utils/log4cplus/ulog_utils.h +++ b/utils/log4cplus/ulog_utils.h @@ -34,8 +34,8 @@ #include #include -#define IS_DEBUG false -#define MAX_LOG_BUF 1024 +#define IS_DEBUG true +#define MAX_LOG_BUF 4096 using namespace log4cplus; using namespace log4cplus::helpers; diff --git a/utils/sgx_socket/tls/common.h b/utils/sgx_socket/tls/common.h index e30ab0f4..7afe3576 100644 --- a/utils/sgx_socket/tls/common.h +++ b/utils/sgx_socket/tls/common.h @@ -24,17 +24,35 @@ * */ +#define CONCURRENT_MAX 50 +#define MAX_RECONNECT 3 +#define CLIENT_MAX_NUM 20 #define TLS_CLIENT "TLS client: " #define TLS_SERVER "TLS server: " -#define CLIENT_PAYLOAD "GET / HTTP/1.0\r\n\r\n" +#define CLIENT_PAYLOAD "GET / HTTP/1.0\r\n\r\n" +#define PASSWORD_WRONG "The password is wrong!" +#define START_ROTATION_MSG "Domian key rotation start!" +#define SET_PERIOD_SUCCESS_MSG "Update period success!" +#define SET_PERIOD_FAILED_MSG "Update period failed, the period must greater than 30 days and less than 365 days!" +#define STOP_AUTO_ROTATION_MSG "Stop auto rotation success!" -#define CLIENT_PAYLOAD_SIZE strlen(CLIENT_PAYLOAD) +#define CLIENT_PAYLOAD_SIZE sizeof(CLIENT_PAYLOAD) +#define PASSWORD_WRONG_SIZE sizeof(PASSWORD_WRONG) +#define START_ROTATION_MSG_SIZE sizeof(START_ROTATION_MSG) +#define SET_PERIOD_SUCCESS_MSG_SIZE sizeof(SET_PERIOD_SUCCESS_MSG) +#define SET_PERIOD_FAILED_MSG_SIZE sizeof(SET_PERIOD_FAILED_MSG) +#define STOP_AUTO_ROTATION_MSG_SIZE sizeof(STOP_AUTO_ROTATION_MSG) + +#define CMK_INFO 0 +#define USER_INFO 1 +#define KEYBLOB 0 +#define CMK 1 +#define SM_DEFAULT_CMK 2 #include "sgx_ttls.h" #include "elog_utils.h" - #define GETCURRTIME t_time #define VERIFY_CALLBACK tee_verify_certificate_with_evidence #define FREE_SUPDATA tee_free_supplemental_data