Add local attestation demo

This commit is contained in:
Hui, Chunyang 2020-02-24 04:07:06 +00:00 committed by Tate, Hongliang Tian
parent 83dfdc4f0f
commit 95ef2819db
30 changed files with 3476 additions and 1 deletions

@ -26,4 +26,5 @@ This set of demos shows how real-world apps can be easily run inside SGX enclave
* `embedded_mode/`: A cross-enclave memory throughput benchmark enabled by the embedded mode of Occlum. * `embedded_mode/`: A cross-enclave memory throughput benchmark enabled by the embedded mode of Occlum.
* `gdb_support/`: This demo explains the technical detail of GDB support and demonstrates how to debug an app running upon Occlum with GDB. * `gdb_support/`: This demo explains the technical detail of GDB support and demonstrates how to debug an app running upon Occlum with GDB.
* `local_attestation/`: This project demonstrates how an app running upon Occlum can perform SGX local attestation.
* `remote_attestation/`: This project demonstrates how an app running upon Occlum can perform SGX remote attestation. * `remote_attestation/`: This project demonstrates how an app running upon Occlum can perform SGX remote attestation.

8
demos/local_attestation/.gitignore vendored Normal file

@ -0,0 +1,8 @@
bin
deps
occlum_context
DiffieHellmanLibrary/*.cpp
DiffieHellmanLibrary/*.so
DiffieHellmanLibrary/*.o
DiffieHellmanLibrary/include
Include

@ -0,0 +1,118 @@
#
# Copyright (C) 2011-2019 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
TARGET = appinitiator
RM = rm -f
#SGX_SDK ?= /opt/intel/sgxsdk
OCCLUM_PREFIX ?= /opt/occlum
CFLAGS := -Wall \
-I$(SGX_SDK)/include \
-I$(OCCLUM_PREFIX)/include \
-I../Include
CXXFLAGS := -Wall \
-I$(SGX_SDK)/include \
-I$(OCCLUM_PREFIX)/include \
-I../Include
ifneq ($(SGX_MODE), HW)
URTS_LIB_NAME := sgx_urts_sim
UAE_SERVICE_LIB := sgx_uae_service_sim
BUILD_DIR:= build_sim
else
URTS_LIB_NAME := sgx_urts
UAE_SERVICE_LIB := sgx_uae_service
BUILD_DIR:= build
endif
INC:=-I$(SGX_SDK)/include -I../Include
LIB := -l$(URTS_LIB_NAME) -l$(UAE_SERVICE_LIB) -L$(SGX_SDK)/lib64 -lpthread
CXXFLAGS += $(INC) $(LIB)
CFLAGS += $(INC) $(LIB)
ifeq ($(SGX_DEBUG), 1)
CXXFLAGS += -DDEBUG -UNDEBUG -UEDEBUG
CFLAGS += -DDEBUG -UNDEBUG -UEDEBUG
else ifeq ($(SGX_PRERELEASE), 1)
CXXFLAGS += -DEDEBUG -DNDEBUG -UDEBUG
CFLAGS += -DEDEBUG -DNDEBUG -UDEBUG
else
CXXFLAGS += -DNDEBUG -UEDEBUG -UDEBUG
CFLAGS += -DNDEBUG -UEDEBUG -UDEBUG
endif
LINK_FLAGS := $(CXXFLAGS) -lpthread \
-L$(SGX_SDK)/lib64 -lsgx_uprotected_fs \
-L$(OCCLUM_PREFIX)/$(BUILD_DIR)/lib -locclum-pal
SRC_CPP=$(wildcard *.cpp)
SRC_OBJ += $(SRC_CPP:.cpp=.o)
SRC_OBJ += $(SRC_C:.c=.o)
.PHONY = all clean
all: $(TARGET)
SGX_COMMON_CFLAGS := -I$(SGX_SDK)/include
UntrustedEnclaveMessageExchange.o: UntrustedEnclaveMessageExchange.cpp
@$(CXX) $(CXXFLAGS) -c $< -o $@
@echo "CC <= $<"
App.o: App.cpp
@$(CXX) $(CXXFLAGS) -c $< -o $@
@echo "CXX <= $<"
fifo.o: fifo.cpp
@$(CXX) $(CXXFLAGS) -c $< -o $@
@echo "CXX <= $<"
EnclaveInitiator_u.o: EnclaveInitiator_u.c
@$(CC) $(CFLAGS) -c $< -o $@
@echo "CC <= $<"
EnclaveInitiator_u.c:
@$(SGX_EDGER8R) --untrusted ../EnclaveInitiator/EnclaveInitiator.edl --search-path $(SGX_SDK)/include
$(TARGET): EnclaveInitiator_u.o $(SRC_OBJ)
@$(CXX) $^ $(LINK_FLAGS) -o $@
@echo "GEN => $@"
@mkdir -p $(TOPDIR)/$(OUTDIR)
@mv $@ $(TOPDIR)/$(OUTDIR)/
clean:
@$(RM) $(TARGET) *.o *_u.c *_u.h

@ -0,0 +1,202 @@
/*
* Copyright (C) 2011-2019 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 <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "sgx_eid.h"
#include "error_codes.h"
#include "datatypes.h"
#include "sgx_urts.h"
#include "UntrustedEnclaveMessageExchange.h"
#include "sgx_dh.h"
#include "fifo_def.h"
/* Function Description: This is OCALL interface for initiator enclave to get ECDH message 1 and session id from responder enclave
* Parameter Description:
* [input, output] dh_msg1: pointer to ecdh msg1 buffer, this buffer is alloated in initiator enclave and filled by reponser enclave
* [output] session_id: pointer to session id which is allocated by responder enclave
* */
extern "C" ATTESTATION_STATUS session_request_ocall(sgx_dh_msg1_t* dh_msg1, uint32_t* session_id)
{
FIFO_MSG msg1_request;
FIFO_MSG *msg1_response;
SESSION_MSG1_RESP * msg1_respbody = NULL;
size_t msg1_resp_size;
msg1_request.header.type = FIFO_DH_REQ_MSG1;
msg1_request.header.size = 0;
if ((client_send_receive(&msg1_request, sizeof(FIFO_MSG), &msg1_response, &msg1_resp_size) != 0)
|| (msg1_response == NULL))
{
printf("fail to send and receive message: session_request_ocall.\n");
return INVALID_SESSION;
}
msg1_respbody = (SESSION_MSG1_RESP *)msg1_response->msgbuf;
memcpy(dh_msg1, &msg1_respbody->dh_msg1, sizeof(sgx_dh_msg1_t));
*session_id = msg1_respbody->sessionid;
free(msg1_response);
return (ATTESTATION_STATUS)0;
}
/* Function Description: This is OCALL interface for initiator enclave to send ECDH message 2 to responder enclave, and receive ECDH message 3 from responder enclave
* Parameter Description:
* [input] dh_msg2: this is pointer to ECDH message 2 generated by initiator enclave
* [input, output]dh_msg3: this is pointer to ECDH message 3, this buffer is allocated in initiator enclave and filled by respoonder enclave
* [input] session_id: this is session id allocated by responder enclave
* */
ATTESTATION_STATUS exchange_report_ocall(sgx_dh_msg2_t *dh_msg2, sgx_dh_msg3_t *dh_msg3, uint32_t session_id)
{
FIFO_MSG * msg2 = NULL, * msg3 = NULL;
FIFO_MSG_HEADER * msg2_header = NULL;
SESSION_MSG2 *msg2_body = NULL;
SESSION_MSG3 *msg3_body = NULL;
size_t msg2size, msg3size;
msg2size = sizeof(FIFO_MSG_HEADER) + sizeof(SESSION_MSG2);
msg2 = (FIFO_MSG *)malloc(msg2size);
if (!msg2)
{
return ERROR_OUT_OF_MEMORY;
}
memset(msg2, 0, msg2size);
msg2_header = (FIFO_MSG_HEADER *)msg2;
msg2_header->type = FIFO_DH_MSG2;
msg2_header->size = sizeof(SESSION_MSG2);
msg2_body = (SESSION_MSG2 *)msg2->msgbuf;
memcpy(&msg2_body->dh_msg2, dh_msg2, sizeof(sgx_dh_msg2_t));
msg2_body->sessionid = session_id;
if (client_send_receive(msg2, msg2size, &msg3, &msg3size) != 0)
{
printf("failed to send and receive message.exchange_report_ocall\n");
return INVALID_SESSION;
}
msg3_body = (SESSION_MSG3 *)msg3->msgbuf;
memcpy(dh_msg3, &msg3_body->dh_msg3, sizeof(sgx_dh_msg3_t));
free(msg3);
free(msg2);
return (ATTESTATION_STATUS)0;
}
/* Function Description: This is OCALL interface for initiator enclave to send request message(encrypted) to responder enclave, and receive response message from responder enclave
* Parameter Description:
* [input] session_id: this is session id allocated by responder enclave
* [input] req_message: this is pointer to request message
* [input] req_message_size: this is request message size
* [input] max_payload_size: this is maxium payload size in response message
* [input, output] this is pointer to response message, the buffer is allocated by initiator enclave and filled by responder enclave
* [input] response message size
* */
ATTESTATION_STATUS send_request_ocall(uint32_t session_id, secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, secure_message_t* resp_message, size_t resp_message_size)
{
FIFO_MSG *msgreq = NULL, * msgresp= NULL;
FIFO_MSGBODY_REQ * msgbody;
size_t reqsize, respsize;
reqsize = sizeof(FIFO_MSG_HEADER) + sizeof(FIFO_MSGBODY_REQ) + req_message_size;
msgreq = (FIFO_MSG *)malloc(reqsize);
if (!msgreq)
{
return ERROR_OUT_OF_MEMORY;
}
memset(msgreq, 0, reqsize);
msgreq->header.type = FIFO_DH_MSG_REQ;
msgreq->header.size = sizeof(FIFO_MSGBODY_REQ) + req_message_size;
msgbody = (FIFO_MSGBODY_REQ *)msgreq->msgbuf;
msgbody->max_payload_size = max_payload_size;
msgbody->size = req_message_size;
msgbody->session_id = session_id;
memcpy(msgbody->buf, req_message, req_message_size);
if (client_send_receive(msgreq, reqsize, &msgresp, &respsize) != 0)
{
printf("fail to send and receive message.send_request_ocall\n");
return INVALID_SESSION;
}
memcpy(resp_message, msgresp->msgbuf, msgresp->header.size < resp_message_size ? msgresp->header.size : resp_message_size);
free(msgresp);
free(msgreq);
return (ATTESTATION_STATUS)0;
}
/* Function Description: this is OCALL interface for initiator enclave to close secure session
* Parameter Description:
* [input] session_id: this is session id allocated by responder enclave
* */
ATTESTATION_STATUS end_session_ocall(uint32_t session_id)
{
FIFO_MSG *msgresp = NULL;
FIFO_MSG *closemsg;
SESSION_CLOSE_REQ * body;
size_t reqsize, respsize;
reqsize = sizeof(FIFO_MSG) + sizeof(SESSION_CLOSE_REQ);
closemsg = (FIFO_MSG *)malloc(reqsize);
if (!closemsg)
{
return ERROR_OUT_OF_MEMORY;
}
memset(closemsg, 0,reqsize);
closemsg->header.type = FIFO_DH_CLOSE_REQ;
closemsg->header.size = sizeof(SESSION_CLOSE_REQ);
body = (SESSION_CLOSE_REQ *)closemsg->msgbuf;
body->session_id = session_id;
if (client_send_receive(closemsg, reqsize, &msgresp, &respsize) != 0)
{
printf("fail to send and receive message.end_session_ocall\n");
return INVALID_SESSION;
}
free(msgresp);
return (ATTESTATION_STATUS)0;
}

@ -0,0 +1,85 @@
/*
* Copyright (C) 2011-2019 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 "sgx_eid.h"
#include "error_codes.h"
#include "datatypes.h"
#include "sgx_urts.h"
#include "dh_session_protocol.h"
#include "sgx_dh.h"
#include <cstddef>
#ifndef ULOCALATTESTATION_H_
#define ULOCALATTESTATION_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Function Description: This is OCALL interface for initiator enclave to get ECDH message 1 and session id from responder enclave
* Parameter Description:
* [input, output] dh_msg1: pointer to ecdh msg1 buffer, this buffer is alloated in initiator enclave and filled by reponser enclave
* [output] session_id: pointer to session id which is allocated by responder enclave
* */
uint32_t session_request_ocall(sgx_dh_msg1_t* dh_msg1, uint32_t* session_id);
/* Function Description: This is OCALL interface for initiator enclave to send ECDH message 2 to responder enclave, and receive ECDH message 3 from responder enclave
* Parameter Description:
* [input] dh_msg2: this is pointer to ECDH message 2 generated by initiator enclave
* [input, output]dh_msg3: this is pointer to ECDH message 3, this buffer is allocated in initiator enclave and filled by respoonder enclave
* [input] session_id: this is session id allocated by responder enclave
* */
uint32_t exchange_report_ocall(sgx_dh_msg2_t* dh_msg2, sgx_dh_msg3_t* dh_msg3, uint32_t session_id);
/* Function Description: This is OCALL interface for initiator enclave to send request message(encrypted) to responder enclave, and receive response message from responder enclave
* Parameter Description:
* [input] session_id: this is session id allocated by responder enclave
* [input] req_message: this is pointer to request message
* [input] req_message_size: this is request message size
* [input] max_payload_size: this is maxium payload size in response message
* [input, output] this is pointer to response message, the buffer is allocated by initiator enclave and filled by responder enclave
* [input] response message size
* */
uint32_t send_request_ocall(uint32_t session_id, secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, secure_message_t* resp_message, size_t resp_message_size);
/* Function Description: this is OCALL interface for initiator enclave to close secure session
* Parameter Description:
* [input] session_id: this is session id allocated by responder enclave
* */
uint32_t end_session_ocall(uint32_t session_id);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,116 @@
#include <stdio.h>
#include <sched.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <linux/limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <occlum_pal_api.h>
#include "sgx_eid.h"
#include "sgx_urts.h"
#include "EnclaveInitiator_u.h"
#define ENCLAVE_INITIATOR_NAME "./bin/libenclave_initiator.signed.so"
pthread_t thread;
sgx_enclave_id_t initiator_enclave_id = 0;
void* attestation(void *arg);
int main(int argc, char* argv[])
{
int update = 0;
sgx_launch_token_t token = {0};
sgx_status_t status;
int exit_status = 0;
const char* occlum_instance_dir = ".occlum";
const char* cmd_path = "/bin/responder"; // Prepare cmd path and arguments
const char* cmd_args[] = {NULL};
// create ECDH initiator enclave
status = sgx_create_enclave(ENCLAVE_INITIATOR_NAME, SGX_DEBUG_FLAG, &token, &update, &initiator_enclave_id, NULL);
if (status != SGX_SUCCESS)
{
printf("failed to load enclave %s, error code is 0x%x.\n", ENCLAVE_INITIATOR_NAME, status);
return -1;
}
printf("succeed to load enclave %s\n", ENCLAVE_INITIATOR_NAME);
if (occlum_pal_init(occlum_instance_dir) < 0)
{
return EXIT_FAILURE;
}
if (pthread_create(&thread, NULL, attestation, NULL) < 0)
{
printf("pthread_create failed\n");
return -1;
}
// Use Occlum PAL to execute the cmd
if (occlum_pal_exec(cmd_path, cmd_args, &exit_status) < 0)
{
return EXIT_FAILURE;
}
// wait for end and destroy
if (pthread_join(thread, NULL) < 0)
{
printf("pthread_join failed\n");
return -1;
}
status = sgx_destroy_enclave(initiator_enclave_id);
if (status != SGX_SUCCESS)
{
printf("failed to destroy enclave %s, error code is 0x%x.\n", ENCLAVE_INITIATOR_NAME, status);
return -1;
}
if (occlum_pal_destroy() < 0)
{
printf("occlum_pal_destroy failed, errno is %d\n", errno);
return -1;
}
printf("Local attestation Sucess!\n");
return 0;
}
// create ECDH session using initiator enclave
// it would create ECDH session with responder enclave running in another process
void* attestation(void *arg)
{
sgx_status_t status;
uint32_t ret_status;
sleep(3);
status = test_create_session(initiator_enclave_id, &ret_status);
if (status != SGX_SUCCESS || ret_status != 0)
{
printf("failed to establish secure channel: ECALL return 0x%x, error code is 0x%x.\n", status, ret_status);
return NULL;
}
printf("succeed to establish secure channel.\n");
status = test_message_exchange(initiator_enclave_id, &ret_status);
if (status != SGX_SUCCESS || ret_status != 0)
{
printf("test_message_exchange Ecall failed: ECALL return 0x%x, error code is 0x%x.\n", status, ret_status);
sgx_destroy_enclave(initiator_enclave_id);
return NULL;
}
printf("Succeed to exchange secure message.\n");
// close ECDH session
status = test_close_session(initiator_enclave_id, &ret_status);
if (status != SGX_SUCCESS || ret_status != 0)
{
printf("test_close_session Ecall failed: ECALL return 0x%x, error code is 0x%x.\n", status, ret_status);
return NULL;
}
printf("Succeed to close session.\n");
pthread_exit(NULL);
}

@ -0,0 +1,121 @@
/*
* Copyright (C) 2011-2019 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include "fifo_def.h"
#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT 8888
#define BUFFER_SIZE 1024
/* Function Description: this is for client to send request message and receive response message
* Parameter Description:
* [input] fiforequest: this is pointer to request message
* [input] fiforequest_size: this is request message size
* [output] fiforesponse: this is pointer fo response message, the buffer is allocated inside this function
* [output] fiforesponse_size: this is response message size
* */
int client_send_receive(FIFO_MSG *fiforequest, size_t fiforequest_size, FIFO_MSG **fiforesponse, size_t *fiforesponse_size) {
int ret = 0;
long byte_num;
char recv_msg[BUFFER_SIZE + 1] = {0};
FIFO_MSG * response = NULL;
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr)) ;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
serv_addr.sin_port = htons(SERVER_PORT);
int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock_fd == -1) {
printf("socket error");
return -1;
}
if (connect(server_sock_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
printf("connection error, %s, line %d.\n", strerror(errno), __LINE__);
ret = -1;
goto CLEAN;
} else printf("client connected\n");
if ((byte_num = send(server_sock_fd, reinterpret_cast<char *>(fiforequest), static_cast<int>(fiforequest_size), 0)) == -1) {
printf("connection error, %s, line %d..\n", strerror(errno), __LINE__);
ret = -1;
goto CLEAN;
} else printf("client send\n");
byte_num = recv(server_sock_fd, reinterpret_cast<char *>(recv_msg), BUFFER_SIZE, 0);
if (byte_num > 0) {
if (byte_num > BUFFER_SIZE) {
byte_num = BUFFER_SIZE;
}
recv_msg[byte_num] = '\0';
response = (FIFO_MSG *)malloc((size_t)byte_num);
if (!response) {
printf("memory allocation failure.\n");
return -1;
}
memset(response, 0, (size_t)byte_num);
memcpy(response, recv_msg, (size_t)byte_num);
*fiforesponse = response;
*fiforesponse_size = (size_t)byte_num;
printf("client received\n");
ret = 0;
} else if(byte_num < 0) {
printf("server error, error message is %s!\n", strerror(errno));
ret = -1;
} else {
printf("server exit!\n");
ret = -1;
}
CLEAN:
close(server_sock_fd);
return ret;
}

@ -0,0 +1,23 @@
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
PROJECT_DIR := $(realpath $(CUR_DIR)/../../../)
OPENSSL ?= $(CUR_DIR)/../deps/openssl
SGX_SDK ?= /opt/intel/sgxsdk
OBJS := session.o proc_msg.o
CC := occlum-gcc
CFLAGS := -fPIC
SOFLAGS := -shared $(CFLAGS)
OPENSSL := -L$(OPENSSL) -lcrypto
ECDH := -L$(CUR_DIR)/../DiffieHellmanLibrary -lecdh
INCLUDE_PATH := -I$(SGX_SDK)/include -I../Include
responder : $(OBJS)
$(CC) responder.c $(OBJS) $(OPENSSL) $(ECDH) $(INCLUDE_PATH) -o responder
session.o : session.c
$(CC) -c session.c $(CFLAGS) $(INCLUDE_PATH) -o session.o
proc_msg.o : proc_msg.c
$(CC) -c proc_msg.c $(CFLAGS) $(INCLUDE_PATH) -o proc_msg.o
clean:
rm -rf *.o responder

@ -0,0 +1,517 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sched.h>
#include "sgx_tseal.h"
#include "session.h"
#include "proc_msg.h"
#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr) = NULL;}}
#define MESSAGE_EXCHANGE 0x0
int proc(FIFO_MSG * message);
extern int m_shutdown;
typedef struct _secure_message_t
{
uint32_t session_id; //Session ID identifyting the session to which the message belongs
sgx_aes_gcm_data_t message_aes_gcm_data;
} secure_message_t;
typedef struct _ms_in_msg_exchange_t
{
uint32_t msg_type; //Type of Call E2E or general message exchange
uint32_t target_fn_id; //Function Id to be called in Destination. Is valid only when msg_type=ENCLAVE_TO_ENCLAVE_CALL
uint32_t inparam_buff_len; //Length of the serialized input parameters
char inparam_buff[1]; //Serialized input parameters
} ms_in_msg_exchange_t;
//Format of the return value and output function parameter structure
typedef struct _ms_out_msg_exchange_t
{
uint32_t retval_len; //Length of the return value
uint32_t ret_outparam_buff_len; //Length of the serialized return value and output parameters
char ret_outparam_buff[1]; //Serialized return value and output parameters
} ms_out_msg_exchange_t;
/* Function Description:
* This function responds to initiator enclave's connection request by generating and sending back ECDH message 1
* Parameter Description:
* [input] clientfd: this is client's connection id. After generating ECDH message 1, server would send back response through this connection id.
* */
int generate_and_send_session_msg1_resp(int clientfd)
{
int retcode = 0;
uint32_t status = 0;
sgx_status_t ret = SGX_SUCCESS;
SESSION_MSG1_RESP msg1resp;
FIFO_MSG * fifo_resp = NULL;
size_t respmsgsize;
memset(&msg1resp, 0, sizeof(SESSION_MSG1_RESP));
// call responder enclave to generate ECDH message 1
ret = session_request(&msg1resp.dh_msg1, &msg1resp.sessionid);
if (ret != SGX_SUCCESS)
{
printf("failed to do ECALL session_request.\n");
return -1;
}
respmsgsize = sizeof(FIFO_MSG) + sizeof(SESSION_MSG1_RESP);
fifo_resp = (FIFO_MSG *)malloc(respmsgsize);
if (!fifo_resp)
{
printf("memory allocation failure.\n");
return -1;
}
memset(fifo_resp, 0, respmsgsize);
fifo_resp->header.type = FIFO_DH_RESP_MSG1;
fifo_resp->header.size = sizeof(SESSION_MSG1_RESP);
memcpy(fifo_resp->msgbuf, &msg1resp, sizeof(SESSION_MSG1_RESP));
//send message 1 to client
if (send(clientfd, (char *)(fifo_resp), (int)(respmsgsize), 0) == -1)
{
printf("fail to send msg1 response.\n");
retcode = -1;
}
free(fifo_resp);
return retcode;
}
/* Function Description:
* This function process ECDH message 2 received from client and send message 3 to client
* Parameter Description:
* [input] clientfd: this is client's connection id
* [input] msg2: this contains ECDH message 2 received from client
* */
int process_exchange_report(int clientfd, SESSION_MSG2 * msg2)
{
uint32_t status = 0;
sgx_status_t ret = SGX_SUCCESS;
FIFO_MSG *response;
SESSION_MSG3 * msg3;
size_t msgsize;
if (!msg2)
return -1;
msgsize = sizeof(FIFO_MSG_HEADER) + sizeof(SESSION_MSG3);
response = (FIFO_MSG *)malloc(msgsize);
if (!response)
{
printf("memory allocation failure\n");
return -1;
}
memset(response, 0, msgsize);
response->header.type = FIFO_DH_MSG3;
response->header.size = sizeof(SESSION_MSG3);
msg3 = (SESSION_MSG3 *)response->msgbuf;
msg3->sessionid = msg2->sessionid;
// call responder enclave to process ECDH message 2 and generate message 3
ret = exchange_report(&msg2->dh_msg2, &msg3->dh_msg3, msg2->sessionid);
if (ret != SGX_SUCCESS)
{
printf("Enclave Response_exchange_report failure.\n");
free(response);
return -1;
}
// send ECDH message 3 to client
if (send(clientfd, (char *)(response), (int)(msgsize), 0) == -1)
{
printf("server_send() failure.\n");
free(response);
return -1;
}
free(response);
return 0;
}
uint32_t get_message_exchange_response(uint32_t inp_secret_data)
{
uint32_t secret_response;
printf("secret=0x%x\n",inp_secret_data);
//User should use more complex encryption method to protect their secret, below is just a simple example
secret_response = inp_secret_data & 0x11111111;
return secret_response;
}
int umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms)
{
char* buff;
size_t len;
if(!inp_secret_data || !ms)
return -1;
buff = ms->inparam_buff;
len = ms->inparam_buff_len;
if(len != sizeof(uint32_t))
return -1;
memcpy(inp_secret_data, buff, sizeof(uint32_t));
return 0;
}
int marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response)
{
ms_out_msg_exchange_t *ms;
size_t secret_response_len, ms_len;
size_t retval_len, ret_param_len;
if(!resp_length)
return -1;
secret_response_len = sizeof(secret_response);
retval_len = secret_response_len;
ret_param_len = secret_response_len;
ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len;
ms = (ms_out_msg_exchange_t *)malloc(ms_len);
if(!ms)
return -1;
ms->retval_len = (uint32_t)retval_len;
ms->ret_outparam_buff_len = (uint32_t)ret_param_len;
memcpy(&ms->ret_outparam_buff, &secret_response, secret_response_len);
*resp_buffer = (char*)ms;
*resp_length = ms_len;
return 0;
}
int message_exchange_response_generator(char* decrypted_data,
char** resp_buffer,
size_t* resp_length)
{
ms_in_msg_exchange_t *ms;
uint32_t inp_secret_data;
uint32_t out_secret_data;
if(!decrypted_data || !resp_length)
return -1;
ms = (ms_in_msg_exchange_t *)decrypted_data;
if(umarshal_message_exchange_request(&inp_secret_data,ms) <0)
return -1;
out_secret_data = get_message_exchange_response(inp_secret_data);
if(marshal_message_exchange_response(resp_buffer, resp_length, out_secret_data) < 0)
return -1;
return 0;
}
int generate_response(secure_message_t* req_message,
size_t req_message_size,
size_t max_payload_size,
secure_message_t* resp_message,
size_t resp_message_size,
uint32_t session_id)
{
#define TAG_SIZE 16
const uint8_t* plaintext;
uint32_t plaintext_length;
uint8_t *decrypted_data;
uint32_t decrypted_data_length;
uint32_t plain_text_offset;
ms_in_msg_exchange_t * ms;
size_t resp_data_length;
size_t resp_message_calc_size;
char* resp_data;
uint8_t l_tag[TAG_SIZE];
size_t header_size, expected_payload_size;
dh_session_t *session_info;
secure_message_t* temp_resp_message;
uint32_t ret;
sgx_status_t status;
plaintext = (const uint8_t*)(" ");
plaintext_length = 0;
if(!req_message || !resp_message)
{
return -1;
}
//Get the session information from the map corresponding to the source enclave id
session_info= get_session_info(session_id);
if (session_info == NULL) return -1;
//Set the decrypted data length to the payload size obtained from the message
decrypted_data_length = req_message->message_aes_gcm_data.payload_size;
header_size = sizeof(secure_message_t);
expected_payload_size = req_message_size - header_size;
//Verify the size of the payload
if(expected_payload_size != decrypted_data_length)
return -1;
memset(&l_tag, 0, 16);
plain_text_offset = decrypted_data_length;
decrypted_data = (uint8_t*)malloc(decrypted_data_length);
if(!decrypted_data)
{
return -1;
}
memset(decrypted_data, 0, decrypted_data_length);
status = sgx_rijndael128GCM_decrypt(&session_info->active.AEK, req_message->message_aes_gcm_data.payload,
decrypted_data_length, decrypted_data,
(uint8_t *)(&(req_message->message_aes_gcm_data.reserved)),
sizeof(req_message->message_aes_gcm_data.reserved), &(req_message->message_aes_gcm_data.payload[plain_text_offset]), plaintext_length,
&req_message->message_aes_gcm_data.payload_tag);
if(SGX_SUCCESS != status)
{
SAFE_FREE(decrypted_data);
return -1;
}
//Casting the decrypted data to the marshaling structure type to obtain type of request (generic message exchange/enclave to enclave call)
ms = (ms_in_msg_exchange_t *)decrypted_data;
// Verify if the nonce obtained in the request is equal to the session nonce
if((uint32_t)*(req_message->message_aes_gcm_data.reserved) != session_info->active.counter || *(req_message->message_aes_gcm_data.reserved) > ((2^32)-2))
{
SAFE_FREE(decrypted_data);
return -1;
}
if(ms->msg_type == MESSAGE_EXCHANGE)
{
//Call the generic secret response generator for message exchange
ret = message_exchange_response_generator((char*)decrypted_data, &resp_data, &resp_data_length);
if(ret !=0)
{
SAFE_FREE(decrypted_data);
SAFE_FREE(resp_data);
return -1;
}
}
else
{
SAFE_FREE(decrypted_data);
return -1;
}
if(resp_data_length > max_payload_size)
{
SAFE_FREE(resp_data);
SAFE_FREE(decrypted_data);
return -1;
}
resp_message_calc_size = sizeof(secure_message_t)+ resp_data_length;
if(resp_message_calc_size > resp_message_size)
{
SAFE_FREE(resp_data);
SAFE_FREE(decrypted_data);
return -1;
}
//Code to build the response back to the Source Enclave
temp_resp_message = (secure_message_t*)malloc(resp_message_calc_size);
if(!temp_resp_message)
{
SAFE_FREE(resp_data);
SAFE_FREE(decrypted_data);
return -1;
}
memset(temp_resp_message,0,sizeof(secure_message_t)+ resp_data_length);
const uint32_t data2encrypt_length = (uint32_t)resp_data_length;
temp_resp_message->session_id = session_info->session_id;
temp_resp_message->message_aes_gcm_data.payload_size = data2encrypt_length;
//Increment the Session Nonce (Replay Protection)
session_info->active.counter = session_info->active.counter + 1;
//Set the response nonce as the session nonce
memcpy(&temp_resp_message->message_aes_gcm_data.reserved,&session_info->active.counter,sizeof(session_info->active.counter));
//Prepare the response message with the encrypted payload
status = sgx_rijndael128GCM_encrypt(&session_info->active.AEK, (uint8_t*)resp_data, data2encrypt_length,
(uint8_t *)(&(temp_resp_message->message_aes_gcm_data.payload)),
(uint8_t *)(&(temp_resp_message->message_aes_gcm_data.reserved)),
sizeof(temp_resp_message->message_aes_gcm_data.reserved), plaintext, plaintext_length,
&(temp_resp_message->message_aes_gcm_data.payload_tag));
if(SGX_SUCCESS != status)
{
SAFE_FREE(resp_data);
SAFE_FREE(decrypted_data);
SAFE_FREE(temp_resp_message);
return -1;
}
memset(resp_message, 0, sizeof(secure_message_t)+ resp_data_length);
memcpy(resp_message, temp_resp_message, sizeof(secure_message_t)+ resp_data_length);
SAFE_FREE(decrypted_data);
SAFE_FREE(resp_data);
SAFE_FREE(temp_resp_message);
return 0;
}
int process_msg_transfer(int clientfd, FIFO_MSGBODY_REQ *req_msg)
{
uint32_t status = 0;
sgx_status_t ret = SGX_SUCCESS;
secure_message_t *resp_message = NULL;
FIFO_MSG * fifo_resp = NULL;
size_t resp_message_size;
if (!req_msg)
{
printf("invalid parameter.\n");
return -1;
}
resp_message_size = sizeof(secure_message_t) + req_msg->max_payload_size;
//Allocate memory for the response message
resp_message = (secure_message_t*)malloc(resp_message_size);
if (!resp_message)
{
printf("memory allocation failure.\n");
return -1;
}
memset(resp_message, 0, resp_message_size);
ret = generate_response( (secure_message_t *)req_msg->buf, req_msg->size, req_msg->max_payload_size, resp_message, resp_message_size, req_msg->session_id);
if (ret <0)
{
printf("EnclaveResponder_generate_response error.\n");
free(resp_message);
return -1;
}
fifo_resp = (FIFO_MSG *)malloc(sizeof(FIFO_MSG) + resp_message_size);
if (!fifo_resp)
{
printf("memory allocation failure.\n");
free(resp_message);
return -1;
}
memset(fifo_resp, 0, sizeof(FIFO_MSG) + resp_message_size);
fifo_resp->header.type = FIFO_DH_MSG_RESP;
fifo_resp->header.size = resp_message_size;
memcpy(fifo_resp->msgbuf, resp_message, resp_message_size);
free(resp_message);
if (send(clientfd, (char *)(fifo_resp), sizeof(FIFO_MSG) + (int)(resp_message_size), 0) == -1)
{
printf("server_send() failure.\n");
free(fifo_resp);
return -1;
}
free(fifo_resp);
return 0;
}
int process_close_req(int clientfd, SESSION_CLOSE_REQ * close_req)
{
uint32_t status = 0;
sgx_status_t ret = SGX_SUCCESS;
FIFO_MSG close_ack;
if (!close_req)
return -1;
// call responder enclave to close this session
ret = end_session( close_req->session_id);
if (ret != SGX_SUCCESS)
return -1;
// send back response
close_ack.header.type = FIFO_DH_CLOSE_RESP;
close_ack.header.size = 0;
if (send(clientfd, (char *)(&close_ack), sizeof(FIFO_MSG), 0) == -1)
{
printf("server_send() failure.\n");
return -1;
}
return 0;
}
int proc (FIFO_MSG * message)
{
if (message == NULL) return 0;
switch (message->header.type)
{
case FIFO_DH_REQ_MSG1:
{
// process ECDH session connection request
int clientfd = message->header.sockfd;
if (generate_and_send_session_msg1_resp(clientfd) != 0)
{
printf("failed to generate and send session msg1 resp.\n");
break;
}
else printf("generate and send session msg1 resp.\n");
}
break;
case FIFO_DH_MSG2:
{
// process ECDH message 2
int clientfd = message->header.sockfd;
SESSION_MSG2 * msg2 = NULL;
msg2 = (SESSION_MSG2 *)message->msgbuf;
if (process_exchange_report(clientfd, msg2) != 0)
{
printf("failed to process exchange_report request.\n");
break;
}
else printf(" process exchange_report request.\n");
}
break;
case FIFO_DH_MSG_REQ:
{
// process message transfer request
int clientfd = message->header.sockfd;
FIFO_MSGBODY_REQ *msg = NULL;
msg = (FIFO_MSGBODY_REQ *)message->msgbuf;
if (process_msg_transfer(clientfd, msg) != 0)
{
printf("failed to process message transfer request.\n");
break;
}
}
break;
case FIFO_DH_CLOSE_REQ:
{
// process message close request
int clientfd = message->header.sockfd;
SESSION_CLOSE_REQ * closereq = NULL;
closereq = (SESSION_CLOSE_REQ *)message->msgbuf;
process_close_req(clientfd, closereq);
printf("process close_requestt request.\n");
m_shutdown = 1;
}
break;
default:
{
printf("Unknown message.\n");
}
break;
}
free(message);
}

@ -0,0 +1,5 @@
#ifndef _PROC_MSG_H_
#define _PROC_MSG_H_
#include "fifo_def.h"
int proc(FIFO_MSG * message);
#endif

@ -0,0 +1,195 @@
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/un.h>
#include <sys/select.h>
#include <sys/time.h>
#include "fifo_def.h"
#include "proc_msg.h"
#define BACKLOG 5
#define CONCURRENT_MAX 32
#define SERVER_PORT 8888
#define BUFFER_SIZE 1024
int m_server_sock_fd;
int m_shutdown;
int server_init()
{
struct sockaddr_in srv_addr;
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr.s_addr = INADDR_ANY;
srv_addr.sin_port = htons(SERVER_PORT);
m_server_sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);;
if (m_server_sock_fd == -1)
{
printf("socket initiazation error: %d\n", errno);
return -1;
}
int bind_result = bind(m_server_sock_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
if (bind_result == -1)
{
printf("bind error: %d\n", errno);
close(m_server_sock_fd);
return -1;
}
if (listen(m_server_sock_fd, BACKLOG) == -1)
{
printf("listen error: %d\n", errno);
close(m_server_sock_fd);
return -1;
}
m_shutdown = 0;
return 0;
}
int work()
{
int client_fds[CONCURRENT_MAX] = {0};
fd_set server_fd_set;
int max_fd = -1;
struct timeval tv;
char input_msg[BUFFER_SIZE];
char recv_msg[BUFFER_SIZE];
int ret;
while (!m_shutdown)
{
// set 10s timeout for select()
tv.tv_sec = 10;
tv.tv_usec = 0;
FD_ZERO(&server_fd_set);
// listening on server socket
FD_SET(m_server_sock_fd, &server_fd_set);
if (max_fd < m_server_sock_fd)
max_fd = m_server_sock_fd;
// listening on all client connections
for(int i =0; i < CONCURRENT_MAX; i++)
{
if(client_fds[i] != 0)
{
FD_SET(client_fds[i], &server_fd_set);
if(max_fd < client_fds[i])
max_fd = client_fds[i];
}
}
ret = select(max_fd + 1, &server_fd_set, NULL, NULL, &tv);
if (ret < 0)
{
printf("Warning: server would shutdown\n");
continue;
}
else if(ret == 0)
{
// timeout
continue;
}
if(FD_ISSET(m_server_sock_fd, &server_fd_set))
{
// if there is new connection request
struct sockaddr_in clt_addr;
socklen_t len = sizeof(clt_addr);
// accept this connection request
int client_sock_fd = accept(m_server_sock_fd, (struct sockaddr *)&clt_addr, &len);
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)
{
index = i;
client_fds[i] = client_sock_fd;
break;
}
}
if(index < 0)
{
printf("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)
{
printf("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)))
{
// there is request messages from client connectsions
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;
recv_msg[byte_num] = '\0';
msg = (FIFO_MSG *)malloc(byte_num);
if (!msg)
{
printf("memory allocation failure\n");
continue;
}
memset(msg, 0, byte_num);
memcpy(msg, recv_msg, byte_num);
msg->header.sockfd = client_fds[i];
proc(msg);
}
else if(byte_num < 0)
{
printf("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;
}
}
}
}
}
int main()
{
int rc;
rc = server_init();
if (rc != 0)
{
printf("server init failure\n");
return rc;
}
return work();
}

@ -0,0 +1,195 @@
#include <string.h>
#include <stdio.h>
#include "session.h"
#define MAX_SESSION_COUNT 16
typedef struct _session_id_tracker_t
{
uint32_t session_id;
} session_id_tracker_t;
int generate_session_id(uint32_t *session_id);
int is_session_id_valid(uint32_t session_id);
session_id_tracker_t *g_session_id_tracker[MAX_SESSION_COUNT];
dh_session_t g_dest_session_info_map[MAX_SESSION_COUNT];
uint32_t g_session_count = 0;
int verify_peer_enclave_trust(sgx_dh_session_enclave_identity_t* peer_enclave_identity)
{
if(!peer_enclave_identity)
return ERROR;
if(!(peer_enclave_identity->attributes.flags & SGX_FLAGS_INITTED))
return ERROR;
return SUCCESS;
}
int session_request(sgx_dh_msg1_t *dh_msg1,
uint32_t *session_id )
{
sgx_dh_session_t sgx_dh_session;
sgx_status_t status = SGX_SUCCESS;
if(!session_id || !dh_msg1)
{
return ERROR;
}
//Intialize the session as a session responder
status = sgx_dh_init_session(SGX_DH_SESSION_RESPONDER, &sgx_dh_session);
if(SGX_SUCCESS != status)
{
printf("sgx_dh_init_session failed\n");
return ERROR;
}
//get a new SessionID
if (generate_session_id(session_id) < 0)
return ERROR; //no more sessions available
//Allocate memory for the session id tracker
g_session_id_tracker[*session_id] = (session_id_tracker_t *)malloc(sizeof(session_id_tracker_t));
if(!g_session_id_tracker[*session_id])
{
printf("g_session_id_tracker failed\n");
return ERROR;
}
memset(g_session_id_tracker[*session_id], 0, sizeof(session_id_tracker_t));
g_session_id_tracker[*session_id]->session_id = *session_id;
//Generate Message1 that will be returned to Source Enclave
status = sgx_dh_responder_gen_msg1((sgx_dh_msg1_t*)dh_msg1, &sgx_dh_session);
if(SGX_SUCCESS != status)
{
free(g_session_id_tracker[*session_id]);
printf("sgx_dh_responder_gen_msg1 failed\n");
return ERROR;
}
memcpy(&g_dest_session_info_map[*session_id].in_progress.dh_session, &sgx_dh_session, sizeof(sgx_dh_session_t));
//Store the session information under the correspoding source enlave id key
g_dest_session_info_map[*session_id].status = IN_PROGRESS;
return SUCCESS;
}
int exchange_report(sgx_dh_msg2_t *dh_msg2,
sgx_dh_msg3_t *dh_msg3,
uint32_t session_id)
{
sgx_key_128bit_t dh_aek; // Session key
dh_session_t *session_info;
int status = SUCCESS;
sgx_dh_session_t sgx_dh_session;
sgx_dh_session_enclave_identity_t initiator_identity;
if(!dh_msg2 || !dh_msg3|| !is_session_id_valid(session_id))
{
return ERROR;
}
memset(&dh_aek,0, sizeof(sgx_key_128bit_t));
do
{
//Retreive the session information for the corresponding source enclave id
session_info = &g_dest_session_info_map[session_id];
memcpy(&sgx_dh_session, &session_info->in_progress.dh_session, sizeof(sgx_dh_session_t));
dh_msg3->msg3_body.additional_prop_length = 0;
//Process message 2 from source enclave and obtain message 3
sgx_status_t se_ret = sgx_dh_responder_proc_msg2(dh_msg2,
dh_msg3,
&sgx_dh_session,
&dh_aek,
&initiator_identity);
if(SGX_SUCCESS != se_ret)
{
status = ERROR;
printf("sgx_dh_responder_proc_msg2 failed\n");
break;
}
//Verify source enclave's trust
if(verify_peer_enclave_trust(&initiator_identity) != SUCCESS)
{
status = ERROR;
break;
}
//save the session ID, status and initialize the session nonce
session_info->session_id = session_id;
session_info->status = ACTIVE;
session_info->active.counter = 0;
memcpy(session_info->active.AEK, &dh_aek, sizeof(sgx_key_128bit_t));
memset(&dh_aek,0, sizeof(sgx_key_128bit_t));
g_session_count++;
}
while(0);
if(status != SUCCESS)
{
end_session(session_id);
}
return status;
}
int end_session(uint32_t session_id)
{
int status = SUCCESS;
int i;
dh_session_t *session_info;
if (!is_session_id_valid(session_id)) return ERROR;
//Get the session information from the map corresponding to the source enclave id
session_info = &g_dest_session_info_map[session_id];
//Erase the session information for the current session
//Update the session id tracker
if (g_session_count > 0)
{
//check if session exists
for (i=1; i <= MAX_SESSION_COUNT; i++)
{
if(g_session_id_tracker[i-1] != NULL && g_session_id_tracker[i-1]->session_id == session_id)
{
memset(g_session_id_tracker[i-1], 0, sizeof(session_id_tracker_t));
free(g_session_id_tracker[i-1]);
g_session_count--;
break;
}
}
}
return status;
}
int is_session_id_valid(uint32_t session_id)
{
if (session_id >= MAX_SESSION_COUNT|| session_id <0) return 0;
return (g_session_id_tracker[session_id] != NULL);
}
dh_session_t* get_session_info(uint32_t session_id )
{
if (!is_session_id_valid(session_id))
return NULL;
return &(g_dest_session_info_map[session_id]);
}
int generate_session_id(uint32_t *session_id)
{
if(!session_id)
{
return ERROR;
}
//if the session structure is untintialized, set that as the next session ID
for (int i = 0; i < MAX_SESSION_COUNT; i++)
{
if (g_session_id_tracker[i] == NULL)
{
*session_id = i;
return SUCCESS;
}
}
return ERROR;
}

@ -0,0 +1,22 @@
#ifndef _EC_DH_SESSION_H_
#define _EC_DH_SESSION_H_
#define ERROR -1
#define SUCCESS 0
#define CLOSED 0x0
#define IN_PROGRESS 0x1
#define ACTIVE 0x2
#include "sgx_dh.h"
#include "dh_session_protocol.h"
int session_request(sgx_dh_msg1_t *dh_msg1,
uint32_t *session_id );
int exchange_report(sgx_dh_msg2_t *dh_msg2,
sgx_dh_msg3_t *dh_msg3,
uint32_t session_id);
int end_session(uint32_t session_id);
dh_session_t* get_session_info(uint32_t session_id );
#endif

@ -0,0 +1,386 @@
From a99d284c16a46f02bff4ff56c8e7361ebc0ae7b2 Mon Sep 17 00:00:00 2001
From: "Hui,Chunyang" <sanqian.hcy@antfin.com>
Date: Tue, 3 Mar 2020 09:45:53 +0000
Subject: [PATCH] Diffie-hellman library change for Occlum local attestation
demo
---
.../DiffieHellmanLibrary/crypto_aes_gcm.cpp | 7 +-
.../DiffieHellmanLibrary/ec_dh.cpp | 221 +++++++++++++++++-
.../include/sgx_dh_internal.h | 3 +-
.../DiffieHellmanLibrary/sgx_cmac128.cpp | 1 -
.../DiffieHellmanLibrary/sgx_ecc256.cpp | 11 +-
.../DiffieHellmanLibrary/sgx_sha256_msg.cpp | 1 -
6 files changed, 225 insertions(+), 19 deletions(-)
diff --git a/demos/local_attestation/DiffieHellmanLibrary/crypto_aes_gcm.cpp b/demos/local_attestation/DiffieHellmanLibrary/crypto_aes_gcm.cpp
index 329338b..bb0c604 100644
--- a/demos/local_attestation/DiffieHellmanLibrary/crypto_aes_gcm.cpp
+++ b/demos/local_attestation/DiffieHellmanLibrary/crypto_aes_gcm.cpp
@@ -31,8 +31,7 @@
#include "stdlib.h"
#include "string.h"
-#include "ssl_crypto.h"
-#include "sgx_memset_s.h"
+#include "sgx_tcrypto.h"
#include <openssl/aes.h>
#include <openssl/evp.h>
@@ -143,7 +142,7 @@ sgx_status_t sgx_rijndael128GCM_decrypt(const sgx_aes_gcm_128bit_key_t *p_key, c
// Autenthication Tag returned by Decrypt to be compared with Tag created during seal
//
- memset_s(&l_tag, SGX_AESGCM_MAC_SIZE, 0, SGX_AESGCM_MAC_SIZE);
+ memset(&l_tag, 0, SGX_AESGCM_MAC_SIZE);
memcpy(l_tag, p_in_mac, SGX_AESGCM_MAC_SIZE);
do {
@@ -205,6 +204,6 @@ sgx_status_t sgx_rijndael128GCM_decrypt(const sgx_aes_gcm_128bit_key_t *p_key, c
{
EVP_CIPHER_CTX_free(pState);
}
- memset_s(&l_tag, SGX_AESGCM_MAC_SIZE, 0, SGX_AESGCM_MAC_SIZE);
+ memset(&l_tag, 0, SGX_AESGCM_MAC_SIZE);
return ret;
}
diff --git a/demos/local_attestation/DiffieHellmanLibrary/ec_dh.cpp b/demos/local_attestation/DiffieHellmanLibrary/ec_dh.cpp
index 40c1539..dd8ab9e 100644
--- a/demos/local_attestation/DiffieHellmanLibrary/ec_dh.cpp
+++ b/demos/local_attestation/DiffieHellmanLibrary/ec_dh.cpp
@@ -29,21 +29,25 @@
*
*/
-#include <sgx_secure_align.h>
+#define __STDC_WANT_LIB_EXT1__ 1
#include <limits.h>
-#include "stdlib.h"
-#include "string.h"
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "sgx_secure_align.h"
#include "sgx.h"
#include "sgx_defs.h"
-#include "sgx_utils.h"
#include "sgx_ecp_types.h"
#include "sgx_key.h"
#include "sgx_report.h"
#include "sgx_attributes.h"
-#include "sgx_trts.h"
#include "ecp_interface.h"
#include "sgx_dh_internal.h"
#include "sgx_lfence.h"
+#include "sgx_dh.h"
#define NONCE_SIZE 16
#define MSG_BUF_LEN (static_cast<uint32_t>(sizeof(sgx_ec256_public_t)*2))
@@ -53,6 +57,213 @@
#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}}
#endif
+typedef struct {
+ const sgx_target_info_t* target_info; // input (optinal)
+ const sgx_report_data_t* report_data; // input (optional)
+ sgx_report_t* report; // output
+} sgxioc_create_report_arg_t;
+
+#define SGXIOC_SELF_TARGET _IOR('s', 3, sgx_target_info_t)
+#define SGXIOC_CREATE_REPORT _IOWR('s', 4, sgxioc_create_report_arg_t)
+#define SGXIOC_VERIFY_REPORT _IOW('s', 5, sgx_report_t)
+
+sgx_status_t sgx_create_report(const sgx_target_info_t *target_info, const sgx_report_data_t *report_data, sgx_report_t *report)
+{
+ sgxioc_create_report_arg_t arg;
+ arg.target_info = target_info;
+ arg.report_data = report_data;
+ arg.report=report;
+ int sgx_fd;
+
+ if ((sgx_fd = open("/dev/sgx", O_RDONLY)) < 0) {
+ printf("open sgx device error\n");
+ return SGX_ERROR_UNEXPECTED;
+ }
+
+ if (ioctl(sgx_fd, SGXIOC_CREATE_REPORT, &arg) < 0) {
+ close(sgx_fd);
+ printf("ioctl error\n");
+ return SGX_ERROR_UNEXPECTED;
+ }
+ close(sgx_fd);
+ return SGX_SUCCESS;
+}
+
+sgx_status_t sgx_verify_report(const sgx_report_t *report)
+{
+ int sgx_fd;
+ if ((sgx_fd = open("/dev/sgx", O_RDONLY)) < 0) {
+ return SGX_ERROR_UNEXPECTED;
+ }
+ if (ioctl(sgx_fd, SGXIOC_VERIFY_REPORT, report) < 0) {
+ printf("failed to verify report");
+ close(sgx_fd);
+ return SGX_ERROR_UNEXPECTED;
+ }
+ close(sgx_fd);
+ return SGX_SUCCESS;
+}
+
+const sgx_report_t *sgx_self_report(void)
+{
+ static sgx_report_t _report = {
+ .body = {
+ .cpu_svn = {0},
+ .misc_select = 0,
+ .reserved1 = {0},
+ .isv_ext_prod_id = {0},
+ .attributes = {0, 0},
+ .mr_enclave = {0},
+ .reserved2 = {0},
+ .mr_signer = {0},
+ .reserved3 = {0},
+ .config_id = {0},
+ .isv_prod_id = 0,
+ .isv_svn = 0,
+ .config_svn = 0,
+ .reserved4 = {0},
+ .isv_family_id = {0},
+ .report_data = {0}
+ },
+ .key_id = {0},
+ .mac = {0}
+ };
+ if (0 == _report.body.attributes.flags)
+ sgx_create_report(nullptr, nullptr, &_report);
+
+ return &_report;
+}
+
+#ifndef ERROR_BREAK
+#define ERROR_BREAK(x) if(x != ippStsNoErr){break;}
+#endif
+#ifndef NULL_BREAK
+#define NULL_BREAK(x) if(!x){break;}
+#endif
+#ifndef SAFE_FREE
+#define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}}
+#endif
+
+#define MAC_KEY_SIZE 16
+
+#define EC_DERIVATION_BUFFER_SIZE(label_length) ((label_length) +4)
+
+sgx_status_t derive_key(
+ const sgx_ec256_dh_shared_t* shared_key,
+ const char* label,
+ uint32_t label_length,
+ sgx_ec_key_128bit_t* derived_key)
+{
+ sgx_status_t se_ret = SGX_SUCCESS;
+ uint8_t cmac_key[MAC_KEY_SIZE];
+ sgx_ec_key_128bit_t key_derive_key;
+ if (!shared_key || !derived_key || !label) {
+ return SGX_ERROR_INVALID_PARAMETER;
+ }
+
+ /*check integer overflow */
+ if (label_length > EC_DERIVATION_BUFFER_SIZE(label_length)) {
+ return SGX_ERROR_INVALID_PARAMETER;
+ }
+ memset(cmac_key, 0, MAC_KEY_SIZE);
+ se_ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t *)cmac_key,
+ (uint8_t*)shared_key,
+ sizeof(sgx_ec256_dh_shared_t),
+ (sgx_cmac_128bit_tag_t *)&key_derive_key);
+ if (SGX_SUCCESS != se_ret) {
+ memset(&key_derive_key, 0, sizeof(key_derive_key));
+ INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret);
+ return se_ret;
+ }
+ /* derivation_buffer = counter(0x01) || label || 0x00 || output_key_len(0x0080) */
+ uint32_t derivation_buffer_length = EC_DERIVATION_BUFFER_SIZE(label_length);
+ uint8_t *p_derivation_buffer = (uint8_t *)malloc(derivation_buffer_length);
+ if (p_derivation_buffer == NULL) {
+ return SGX_ERROR_OUT_OF_MEMORY;
+ }
+ memset(p_derivation_buffer, 0, derivation_buffer_length);
+
+ /*counter = 0x01 */
+ p_derivation_buffer[0] = 0x01;
+ /*label*/
+ memcpy(&p_derivation_buffer[1], label, label_length);
+ /*output_key_len=0x0080*/
+ uint16_t *key_len = (uint16_t *)&p_derivation_buffer[derivation_buffer_length - 2];
+ *key_len = 0x0080;
+
+ se_ret = sgx_rijndael128_cmac_msg((sgx_cmac_128bit_key_t *)&key_derive_key,
+ p_derivation_buffer,
+ derivation_buffer_length,
+ (sgx_cmac_128bit_tag_t *)derived_key);
+ memset(&key_derive_key, 0, sizeof(key_derive_key));
+ free(p_derivation_buffer);
+ if(SGX_SUCCESS != se_ret) {
+ INTERNAL_SGX_ERROR_CODE_CONVERTOR(se_ret);
+ }
+ return se_ret;
+}
+
+static void * (* const volatile __memset_vp)(void *, int, size_t)
+ = (memset);
+
+#undef memset_s /* in case it was defined as a macro */
+
+int memset_s(void *s, size_t smax, int c, size_t n)
+{
+ int err = 0;
+
+ if (s == NULL) {
+ err = -1;
+ goto out;
+ }
+ if (smax > SIZE_MAX) {
+ err = -1;
+ goto out;
+ }
+ if (n > SIZE_MAX) {
+ err = -1;
+ n = smax;
+ }
+ if (n > smax) {
+ err = -1;
+ n = smax;
+ }
+
+ /* Calling through a volatile pointer should never be optimised away. */
+ (*__memset_vp)(s, c, n);
+
+out:
+ if (err == 0)
+ return 0;
+ else {
+ /* XXX call runtime-constraint handler */
+ return err;
+ }
+}
+
+int consttime_memequal(const void *b1, const void *b2, size_t len)
+{
+ const unsigned char *c1 = (const unsigned char *)b1, *c2 =(const unsigned char *) b2;
+ unsigned int res = 0;
+
+ while (len--)
+ res |= *c1++ ^ *c2++;
+
+ /*
+ * Map 0 to 1 and [1, 256) to 0 using only constant-time
+ * arithmetic.
+ *
+ * This is not simply `!res' because although many CPUs support
+ * branchless conditional moves and many compilers will take
+ * advantage of them, certain compilers generate branches on
+ * certain CPUs for `!res'.
+ */
+ return (1 & ((res - 1) >> 8));
+}
+
+#define sgx_is_within_enclave(ptr, len) (1)
+#define offsetof(type,field) ((char *) &((type *) 0)->field - (char *) 0)
+
static bool LAv2_verify_message2(const sgx_dh_msg2_t *, const sgx_key_128bit_t *);
static sgx_status_t LAv2_generate_message3(const sgx_dh_msg2_t *,
const sgx_ec256_public_t *, const sgx_key_128bit_t *, sgx_dh_msg3_t *);
diff --git a/demos/local_attestation/DiffieHellmanLibrary/include/sgx_dh_internal.h b/demos/local_attestation/DiffieHellmanLibrary/include/sgx_dh_internal.h
index 98b7d3f..5a7a75a 100644
--- a/demos/local_attestation/DiffieHellmanLibrary/include/sgx_dh_internal.h
+++ b/demos/local_attestation/DiffieHellmanLibrary/include/sgx_dh_internal.h
@@ -36,7 +36,6 @@
#include "sgx.h"
#include "sgx_defs.h"
#include "sgx_ecp_types.h"
-#include "arch.h"
// Disable SGX_USE_LAv2_INITIATOR to allow compiling both LAv1/2 APIs
#ifdef SGX_USE_LAv2_INITIATOR
@@ -81,7 +80,7 @@ typedef struct _sgx_internal_dh_session_t{
};
} sgx_internal_dh_session_t;
-se_static_assert(sizeof(sgx_internal_dh_session_t) == SGX_DH_SESSION_DATA_SIZE); /*size mismatch on sgx_internal_dh_session_t and sgx_dh_session_t*/
+//se_static_assert(sizeof(sgx_internal_dh_session_t) == SGX_DH_SESSION_DATA_SIZE); /*size mismatch on sgx_internal_dh_session_t and sgx_dh_session_t*/
#pragma pack(pop)
diff --git a/demos/local_attestation/DiffieHellmanLibrary/sgx_cmac128.cpp b/demos/local_attestation/DiffieHellmanLibrary/sgx_cmac128.cpp
index a810542..53f9b90 100644
--- a/demos/local_attestation/DiffieHellmanLibrary/sgx_cmac128.cpp
+++ b/demos/local_attestation/DiffieHellmanLibrary/sgx_cmac128.cpp
@@ -32,7 +32,6 @@
#include "stdlib.h"
#include "string.h"
#include "sgx_tcrypto.h"
-#include "se_tcrypto_common.h"
#include "openssl/cmac.h"
#include "openssl/err.h"
diff --git a/demos/local_attestation/DiffieHellmanLibrary/sgx_ecc256.cpp b/demos/local_attestation/DiffieHellmanLibrary/sgx_ecc256.cpp
index 85a482e..ed8ec46 100644
--- a/demos/local_attestation/DiffieHellmanLibrary/sgx_ecc256.cpp
+++ b/demos/local_attestation/DiffieHellmanLibrary/sgx_ecc256.cpp
@@ -30,7 +30,6 @@
*/
#include "string.h"
-#include "se_tcrypto_common.h"
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/err.h>
@@ -170,9 +169,9 @@ sgx_status_t sgx_ecc256_create_key_pair(sgx_ec256_private_t *p_private,
if (SGX_SUCCESS != ret) {
// in case of error, clear output buffers
//
- memset_s(p_private, sizeof(p_private), 0, sizeof(p_private));
- memset_s(p_public->gx, sizeof(p_public->gx), 0, sizeof(p_public->gx));
- memset_s(p_public->gy, sizeof(p_public->gy), 0, sizeof(p_public->gy));
+ memset(p_private, 0, sizeof(p_private));
+ memset(p_public->gx, 0, sizeof(p_public->gx));
+ memset(p_public->gy, 0, sizeof(p_public->gy));
}
//free temp data
@@ -367,7 +366,7 @@ sgx_status_t sgx_ecc256_compute_shared_dhkey(sgx_ec256_private_t *p_private_b,
} while(0);
if (ret != SGX_SUCCESS) {
- memset_s(p_shared_key->s, sizeof(p_shared_key->s), 0, sizeof(p_shared_key->s));
+ memset(p_shared_key->s, 0, sizeof(p_shared_key->s));
}
// clear and free memory
@@ -470,7 +469,7 @@ sgx_status_t sgx_ecc256_calculate_pub_from_priv(const sgx_ec256_private_t *p_att
//in case of failure clear public key
//
if (ret != SGX_SUCCESS) {
- (void)memset_s(p_att_pub_key, sizeof(sgx_ec256_public_t), 0, sizeof(sgx_ec256_public_t));
+ (void)memset(p_att_pub_key, 0, sizeof(sgx_ec256_public_t));
}
BN_clear_free(bn_o);
diff --git a/demos/local_attestation/DiffieHellmanLibrary/sgx_sha256_msg.cpp b/demos/local_attestation/DiffieHellmanLibrary/sgx_sha256_msg.cpp
index 44fd1e2..b3ee3ed 100644
--- a/demos/local_attestation/DiffieHellmanLibrary/sgx_sha256_msg.cpp
+++ b/demos/local_attestation/DiffieHellmanLibrary/sgx_sha256_msg.cpp
@@ -29,7 +29,6 @@
*
*/
-#include "se_tcrypto_common.h"
#include <openssl/sha.h>
#include <openssl/err.h>
#include "sgx_tcrypto.h"
--
2.17.1

@ -0,0 +1,29 @@
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
PROJECT_DIR := $(realpath $(CUR_DIR)/../../../)
OPENSSL ?= $(CUR_DIR)/../deps/openssl
SGX_SDK ?= /opt/intel/sgxsdk
OBJS = sgx_ecc256.o sgx_cmac128.o sgx_sha256_msg.o crypto_aes_gcm.o
CC = occlum-gcc
CXX = occlum-g++
CFLAGS = -I$(OPENSSL)/include -L$(OPENSSL) -lcrypto -fPIC
SOFLAGS = -shared $(CFLAGS)
CFLAGS += -I$(SGX_SDK)/include -Iinclude
ec_dh : $(OBJS)
$(CXX) $(SOFLAGS) -o libecdh.so ec_dh.cpp $(OBJS)
sgx_ecc256.o : sgx_ecc256.cpp
$(CXX) -c sgx_ecc256.cpp $(CFLAGS) -o sgx_ecc256.o
sgx_cmac128.o : sgx_cmac128.cpp
$(CXX) -c sgx_cmac128.cpp $(CFLAGS) -o sgx_cmac128.o
sgx_sha256_msg.o : sgx_sha256_msg.cpp
$(CXX) -c sgx_sha256_msg.cpp $(CFLAGS) -o sgx_sha256_msg.o
crypto_aes_gcm.o : crypto_aes_gcm.cpp
$(CXX) -c crypto_aes_gcm.cpp $(CFLAGS) -o crypto_aes_gcm.o
clean:
rm -rf *.o ec_dh *.so

@ -0,0 +1,9 @@
<EnclaveConfiguration>
<ProdID>0</ProdID>
<ISVSVN>0</ISVSVN>
<StackMaxSize>0x40000</StackMaxSize>
<HeapMaxSize>0x100000</HeapMaxSize>
<TCSNum>1</TCSNum>
<TCSPolicy>1</TCSPolicy>
<DisableDebug>0</DisableDebug>
</EnclaveConfiguration>

@ -0,0 +1,187 @@
/*
* Copyright (C) 2011-2019 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 <string>
#include "sgx_eid.h"
#include "EnclaveInitiator_t.h"
#include "EnclaveMessageExchange.h"
#include "error_codes.h"
#include "Utility_EnclaveInitiator.h"
#include "sgx_dh.h"
#define UNUSED(val) (void)(val)
#define RESPONDER_PRODID 1
dh_session_t g_session;
/* Function Description:
* This is ECALL routine to create ECDH session.
* When it succeeds to create ECDH session, the session context is saved in g_session.
* */
extern "C" uint32_t test_create_session()
{
return create_session(&g_session);
}
/* Function Description:
* This is ECALL routine to transfer message with ECDH peer
* */
uint32_t test_message_exchange()
{
ATTESTATION_STATUS ke_status = SUCCESS;
uint32_t target_fn_id, msg_type;
char* marshalled_inp_buff;
size_t marshalled_inp_buff_len;
char* out_buff;
size_t out_buff_len;
size_t max_out_buff_size;
char* secret_response;
uint32_t secret_data;
target_fn_id = 0;
msg_type = MESSAGE_EXCHANGE;
max_out_buff_size = 50; // it's assumed the maximum payload size in response message is 50 bytes, it's for demontration purpose
secret_data = 0x12345678; //Secret Data here is shown only for purpose of demonstration.
//Marshals the secret data into a buffer
ke_status = marshal_message_exchange_request(target_fn_id, msg_type, secret_data, &marshalled_inp_buff, &marshalled_inp_buff_len);
if(ke_status != SUCCESS)
{
return ke_status;
}
//Core Reference Code function
ke_status = send_request_receive_response(&g_session, marshalled_inp_buff,
marshalled_inp_buff_len, max_out_buff_size, &out_buff, &out_buff_len);
if(ke_status != SUCCESS)
{
SAFE_FREE(marshalled_inp_buff);
SAFE_FREE(out_buff);
return ke_status;
}
//Un-marshal the secret response data
ke_status = umarshal_message_exchange_response(out_buff, &secret_response);
if(ke_status != SUCCESS)
{
SAFE_FREE(marshalled_inp_buff);
SAFE_FREE(out_buff);
return ke_status;
}
SAFE_FREE(marshalled_inp_buff);
SAFE_FREE(out_buff);
SAFE_FREE(secret_response);
return SUCCESS;
}
/* Function Descriptin:
* This is ECALL interface to close secure session*/
uint32_t test_close_session()
{
ATTESTATION_STATUS ke_status;
ke_status = close_session(&g_session);
//Erase the session context
memset(&g_session, 0, sizeof(dh_session_t));
return ke_status;
}
/* Function Description:
* This is to verify peer enclave's identity.
* For demonstration purpose, we verify below points:
* 1. peer enclave's MRSIGNER is as expected
* 2. peer enclave's PROD_ID is as expected
* 3. peer enclave's attribute is reasonable: it's INITIALIZED'ed enclave; in non-debug build configuraiton, the enlave isn't loaded with enclave debug mode.
**/
extern "C" uint32_t verify_peer_enclave_trust(sgx_dh_session_enclave_identity_t* peer_enclave_identity)
{
if (!peer_enclave_identity)
return INVALID_PARAMETER_ERROR;
// check peer enclave's MRSIGNER
// check peer enclave's product ID and enclave attribute (should be INITIALIZED'ed)
if ( !(peer_enclave_identity->attributes.flags & SGX_FLAGS_INITTED))
{
return ENCLAVE_TRUST_ERROR;
}
// check the enclave isn't loaded in enclave debug mode, except that the project is built for debug purpose
return SUCCESS;
}
/* Function Desciption: Operates on the input secret and generate the output secret
* */
uint32_t get_message_exchange_response(uint32_t inp_secret_data)
{
uint32_t secret_response;
//User should use more complex encryption method to protect their secret, below is just a simple example
secret_response = inp_secret_data & 0x11111111;
return secret_response;
}
//Generates the response from the request message
/* Function Description:
* process request message and generate response
* Parameter Descriptin:
* [input] decrypted_data: this is pointer to decrypted message
* [output] resp_buffer: this is pointer to response message, the buffer is allocated inside this function
* [output] resp_length: this points to response length
* */
extern "C" uint32_t message_exchange_response_generator(char* decrypted_data,
char** resp_buffer,
size_t* resp_length)
{
ms_in_msg_exchange_t *ms;
uint32_t inp_secret_data;
uint32_t out_secret_data;
if(!decrypted_data || !resp_length)
{
return INVALID_PARAMETER_ERROR;
}
ms = (ms_in_msg_exchange_t *)decrypted_data;
if(umarshal_message_exchange_request(&inp_secret_data,ms) != SUCCESS)
return ATTESTATION_ERROR;
out_secret_data = get_message_exchange_response(inp_secret_data);
if(marshal_message_exchange_response(resp_buffer, resp_length, out_secret_data) != SUCCESS)
return MALLOC_ERROR;
return SUCCESS;
}

@ -0,0 +1,50 @@
/*
* Copyright (C) 2011-2019 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 {
include "sgx_eid.h"
include "datatypes.h"
include "dh_session_protocol.h"
trusted{
public uint32_t test_create_session();
public uint32_t test_message_exchange();
public uint32_t test_close_session();
};
untrusted{
uint32_t session_request_ocall([out] sgx_dh_msg1_t *dh_msg1,[out] uint32_t *session_id);
uint32_t exchange_report_ocall([in] sgx_dh_msg2_t *dh_msg2, [out] sgx_dh_msg3_t *dh_msg3, uint32_t session_id);
uint32_t send_request_ocall(uint32_t session_id, [in, size = req_message_size] secure_message_t* req_message, size_t req_message_size, size_t max_payload_size, [out, size=resp_message_size] secure_message_t* resp_message, size_t resp_message_size);
uint32_t end_session_ocall(uint32_t session_id);
};
};

@ -0,0 +1,10 @@
Enclave1.so
{
global:
g_global_data_sim;
g_global_data;
enclave_entry;
g_peak_heap_used;
local:
*;
};

@ -0,0 +1,39 @@
-----BEGIN RSA PRIVATE KEY-----
MIIG4wIBAAKCAYEAuJh4w/KzndQhzEqwH6Ut/3BmOom5CN117KT1/cemEbDLPhn0
c5yjAfe4NL1qtGqz0RTK9X9BBSi89b6BrsM9S6c2cUJaeYAPrAtJ+IuzN/5BAmmf
RXbPccETd7rHvDdQ9KBRjCipTx+H0D5nOB76S5PZPVrduwrCmSqVFmLNVWWfPYQx
YewbJ2QfEfioICZFYR0Jou38mJqDTl+CH0gLAuQ4n1kdpQ3VGymzt3oUiPzf5ImJ
oZh5HjarRRiWV+cyNyXYJTnx0dOtFQDgd8HhniagbRB0ZOIt6599JjMkWGkVP0Ni
U/NIlXG5musU35GfLB8MbTcxblMNm9sMYz1R8y/eAreoPTXUhtK8NG2TEywRh3UP
RF9/jM9WczjQXxJ3RznKOwNVwg4cRY2AOqD2vb1iGSqyc/WMzVULgfclkcScp75/
Auz9Y6473CQvaxyrseSWHGwCG7KG1GxYE8Bg8T6OlYD4mzKggoMdwVLAzUepRaPZ
5hqRDZzbTGUxJ+GLAgEDAoIBgHsQUIKhzRPiwTLcdWpuHqpK7tGxJgXo+Uht+VPa
brZ13NQRTaJobKv6es3TnHhHIotjMfj/gK4bKKPUVnSCKN0aJEuBkaZVX8gHhqWy
d3qpgKxGai5PNPaAt6UnL9LPi03ANl1wcN9qWorURNAUpt0NO348k9IHLGYcY2RB
3jjuaikCy5adZ2+YFLalxWrELkC+BmyeqGW8V4mVAWowB1dC0Go7aRiz42dxInpR
YwX96phbsRZlphQkci4QZDqaIFg3ndzTO5bo704zaMcbWtEjmFrYRyb519tRoDkN
Y0rGwOxFANeRV5dSfGGLm7K5JztiuHN0nMu3PhY4LOV0SeZ4+5sYn0LzB2nyKqgy
/c3AA2OG34DEdGxxh94kD66iKFVPyJG38/gnu9CsGmrLl3n4fgutPEVIbPdSSjex
4Y9EQfcnqImPxTrpP9CqD208VPcQHD/uy8s9q3961Ew3RPdHMZ8amIJdXkOmPEme
KZ7SG+VENBaj8r038iq1mPzcWwKBwQDcvJg75LfVuKX+cWMrTO2+MFVcEFiZ/NB/
gh7mgL6lCleROVa9P6iR2Wn6vHq8nP5BkChehm/rXEG78fgXEMoArimF7FrrICfI
4yB0opDJz/tWrE/62impN7OR8Ce+RQThFj4RTnibQEEVt++JMUXFiMKLdWDSpC2i
tNWnlTOb7d89bk0yk62IoLElCZK/MIMxkCHBKW6YgrmvlPJKQwpA6Z3wQbUpE6Rb
9f8xJfxZGEJPH0s3Ds9A0CVuEt8OOXcCgcEA1hXTHhhgmb2gIUJgIcvrpkDmiLux
EG6ZoyLt6h5QwzScS6KKU1mcoJyVDd0wlt7mEXrPYYHWUWPuvpTQ8/4ZGMw7FCZe
bakhnwRbw36FlLwRG35wCF6nQO1XFBKRGto15ivfTyDvMpJBdtNpET5NwT/ifDF3
OWS7t6TGhtcfnvBad5S1AgGoAq+q/huFiBGpDbxJ+1xh0lNL5Z8nVypvPWomNpde
rpLuwRPEIb+GBfQ9Hp5AjRXVsPjKnkHsnl2NAoHBAJMoZX1DJTklw/72Qhzd89Qg
OOgK5bv94FUBae8Afxixj7YmOdN/xbaQ8VHS/H29/tZgGumu9UeS1n1L+roLMVXJ
cQPy50dqxTCXavhsYIaKp48diqc8G8YlImFKxSmDWJYO1AuJpbzVgLklSlt2LoOw
gbJOQIxtc8HN48UOImfz6ij0M3cNHlsVy24GYdTLAiEKwStw9GWse8pjTDGCBtXx
E/WBI3C3wuf5VMtuqDtlgYoU3M9fNNXgGPQMlLQmTwKBwQCOuTdpZZW708AWLEAW
h/Ju1e8F0nYK9GZswfPxaYsszb2HwbGM5mhrEw4JPiBklJlg/IpBATmLl/R/DeCi
qWYQiCdixD7zxhZqAufXqa5jKAtnqaAFlG+AnjoNYbYR5s6ZcpTfa0ohttZPN5tg
1DPWKpb9dk97mH0lGIRZ5L+/Sub6YyNWq8VXH8dUElkFYRtefYankuvhjN1Dv2+P
cZ9+RsQkZOnJt0nWDS1r1QQD+Ci/FCsIuTkgpdxpgUhpk7MCgcEAkfkmaBDb7DG2
Kc39R6ZZuPnV10w+WOpph7ugwcguG/E0wGq+jFWv6HFckCPeHT4BNtOk8Dem/kPp
teF51eAuFWEefj2tScvlSBBPcnla+WzMWXrlxVnajTt73w+oT2Ql//WhgREpsNfx
SvU80YPVu4GJfl+hhxBifLx+0FM20OESW93qFRc3p040bNrDY9JIZuly/y5zaiBa
mRZF9H8P+x3Lu5AJpdXQEOMZ/XJ/xkoWWjbTojkmgOmmZSMLd5Te
-----END RSA PRIVATE KEY-----

@ -0,0 +1,358 @@
/*
* Copyright (C) 2011-2019 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 <string>
#include "sgx_trts.h"
#include "sgx_utils.h"
#include "EnclaveMessageExchange.h"
#include "sgx_eid.h"
#include "error_codes.h"
#include "sgx_ecp_types.h"
#include "sgx_thread.h"
#include "dh_session_protocol.h"
#include "sgx_dh.h"
#include "sgx_tcrypto.h"
#include "EnclaveInitiator_t.h"
#ifdef __cplusplus
extern "C" {
#endif
uint32_t message_exchange_response_generator(char* decrypted_data, char** resp_buffer, size_t* resp_length);
uint32_t verify_peer_enclave_trust(sgx_dh_session_enclave_identity_t* peer_enclave_identity);
#ifdef __cplusplus
}
#endif
#define MAX_SESSION_COUNT 16
//number of open sessions
uint32_t g_session_count = 0;
ATTESTATION_STATUS generate_session_id(uint32_t *session_id);
ATTESTATION_STATUS end_session(sgx_enclave_id_t src_enclave_id);
//Array of open session ids
session_id_tracker_t *g_session_id_tracker[MAX_SESSION_COUNT];
//Create a session with the destination enclave
ATTESTATION_STATUS create_session(dh_session_t *session_info)
{
sgx_dh_msg1_t dh_msg1; //Diffie-Hellman Message 1
sgx_key_128bit_t dh_aek; // Session Key
sgx_dh_msg2_t dh_msg2; //Diffie-Hellman Message 2
sgx_dh_msg3_t dh_msg3; //Diffie-Hellman Message 3
uint32_t session_id;
uint32_t retstatus;
sgx_status_t status = SGX_SUCCESS;
sgx_dh_session_t sgx_dh_session;
sgx_dh_session_enclave_identity_t responder_identity;
if(!session_info)
{
return INVALID_PARAMETER_ERROR;
}
memset(&dh_aek,0, sizeof(sgx_key_128bit_t));
memset(&dh_msg1, 0, sizeof(sgx_dh_msg1_t));
memset(&dh_msg2, 0, sizeof(sgx_dh_msg2_t));
memset(&dh_msg3, 0, sizeof(sgx_dh_msg3_t));
memset(session_info, 0, sizeof(dh_session_t));
//Intialize the session as a session initiator
status = sgx_dh_init_session(SGX_DH_SESSION_INITIATOR, &sgx_dh_session);
if(SGX_SUCCESS != status)
{
return status;
}
//Ocall to request for a session with the destination enclave and obtain session id and Message 1 if successful
status = session_request_ocall(&retstatus, &dh_msg1, &session_id);
if (status == SGX_SUCCESS)
{
if ((ATTESTATION_STATUS)retstatus != SUCCESS)
return ((ATTESTATION_STATUS)retstatus);
}
else
{
return ATTESTATION_SE_ERROR;
}
//Process the message 1 obtained from desination enclave and generate message 2
status = sgx_dh_initiator_proc_msg1(&dh_msg1, &dh_msg2, &sgx_dh_session);
if(SGX_SUCCESS != status)
{
return status;
}
//Send Message 2 to Destination Enclave and get Message 3 in return
status = exchange_report_ocall(&retstatus, &dh_msg2, &dh_msg3, session_id);
if (status == SGX_SUCCESS)
{
if ((ATTESTATION_STATUS)retstatus != SUCCESS)
return ((ATTESTATION_STATUS)retstatus);
}
else
{
return ATTESTATION_SE_ERROR;
}
//Process Message 3 obtained from the destination enclave
status = sgx_dh_initiator_proc_msg3(&dh_msg3, &sgx_dh_session, &dh_aek, &responder_identity);
if(SGX_SUCCESS != status)
{
return status;
}
// Verify the identity of the destination enclave
if(verify_peer_enclave_trust(&responder_identity) != SUCCESS)
{
return INVALID_SESSION;
}
memcpy(session_info->active.AEK, &dh_aek, sizeof(sgx_key_128bit_t));
session_info->session_id = session_id;
session_info->active.counter = 0;
session_info->status = ACTIVE;
memset(&dh_aek,0, sizeof(sgx_key_128bit_t));
return status;
}
//Request for the response size, send the request message to the destination enclave and receive the response message back
ATTESTATION_STATUS send_request_receive_response(dh_session_t *session_info,
char *inp_buff,
size_t inp_buff_len,
size_t max_out_buff_size,
char **out_buff,
size_t* out_buff_len)
{
const uint8_t* plaintext;
uint32_t plaintext_length;
sgx_status_t status;
uint32_t retstatus;
secure_message_t* req_message;
secure_message_t* resp_message;
uint8_t *decrypted_data;
uint32_t decrypted_data_length;
uint32_t plain_text_offset;
uint8_t l_tag[TAG_SIZE];
size_t max_resp_message_length;
plaintext = (const uint8_t*)(" ");
plaintext_length = 0;
if(!session_info || !inp_buff)
{
return INVALID_PARAMETER_ERROR;
}
//Check if the nonce for the session has not exceeded 2^32-2 if so end session and start a new session
if(session_info->active.counter == ((uint32_t) - 2))
{
close_session(session_info);
create_session(session_info);
}
//Allocate memory for the AES-GCM request message
req_message = (secure_message_t*)malloc(sizeof(secure_message_t)+ inp_buff_len);
if(!req_message)
return MALLOC_ERROR;
memset(req_message, 0, sizeof(secure_message_t)+ inp_buff_len);
const uint32_t data2encrypt_length = (uint32_t)inp_buff_len;
//Set the payload size to data to encrypt length
req_message->message_aes_gcm_data.payload_size = data2encrypt_length;
//Use the session nonce as the payload IV
memcpy(req_message->message_aes_gcm_data.reserved, &session_info->active.counter, sizeof(session_info->active.counter));
//Set the session ID of the message to the current session id
req_message->session_id = session_info->session_id;
//Prepare the request message with the encrypted payload
status = sgx_rijndael128GCM_encrypt(&session_info->active.AEK, (uint8_t*)inp_buff, data2encrypt_length,
reinterpret_cast<uint8_t *>(&(req_message->message_aes_gcm_data.payload)),
reinterpret_cast<uint8_t *>(&(req_message->message_aes_gcm_data.reserved)),
sizeof(req_message->message_aes_gcm_data.reserved), plaintext, plaintext_length,
&(req_message->message_aes_gcm_data.payload_tag));
if(SGX_SUCCESS != status)
{
SAFE_FREE(req_message);
return status;
}
//Allocate memory for the response payload to be copied
*out_buff = (char*)malloc(max_out_buff_size);
if(!*out_buff)
{
SAFE_FREE(req_message);
return MALLOC_ERROR;
}
memset(*out_buff, 0, max_out_buff_size);
//Allocate memory for the response message
resp_message = (secure_message_t*)malloc(sizeof(secure_message_t)+ max_out_buff_size);
if(!resp_message)
{
SAFE_FREE(req_message);
return MALLOC_ERROR;
}
memset(resp_message, 0, sizeof(secure_message_t)+ max_out_buff_size);
//Ocall to send the request to the Destination Enclave and get the response message back
status = send_request_ocall(&retstatus, session_info->session_id, req_message,
(sizeof(secure_message_t)+ inp_buff_len), max_out_buff_size,
resp_message, (sizeof(secure_message_t)+ max_out_buff_size));
if (status == SGX_SUCCESS)
{
if ((ATTESTATION_STATUS)retstatus != SUCCESS)
{
SAFE_FREE(req_message);
SAFE_FREE(resp_message);
return ((ATTESTATION_STATUS)retstatus);
}
}
else
{
SAFE_FREE(req_message);
SAFE_FREE(resp_message);
return ATTESTATION_SE_ERROR;
}
max_resp_message_length = sizeof(secure_message_t)+ max_out_buff_size;
if(sizeof(resp_message) > max_resp_message_length)
{
SAFE_FREE(req_message);
SAFE_FREE(resp_message);
return INVALID_PARAMETER_ERROR;
}
//Code to process the response message from the Destination Enclave
decrypted_data_length = resp_message->message_aes_gcm_data.payload_size;
plain_text_offset = decrypted_data_length;
decrypted_data = (uint8_t*)malloc(decrypted_data_length);
if(!decrypted_data)
{
SAFE_FREE(req_message);
SAFE_FREE(resp_message);
return MALLOC_ERROR;
}
memset(&l_tag, 0, 16);
memset(decrypted_data, 0, decrypted_data_length);
//Decrypt the response message payload
status = sgx_rijndael128GCM_decrypt(&session_info->active.AEK, resp_message->message_aes_gcm_data.payload,
decrypted_data_length, decrypted_data,
reinterpret_cast<uint8_t *>(&(resp_message->message_aes_gcm_data.reserved)),
sizeof(resp_message->message_aes_gcm_data.reserved), &(resp_message->message_aes_gcm_data.payload[plain_text_offset]), plaintext_length,
&resp_message->message_aes_gcm_data.payload_tag);
if(SGX_SUCCESS != status)
{
SAFE_FREE(req_message);
SAFE_FREE(decrypted_data);
SAFE_FREE(resp_message);
return status;
}
// Verify if the nonce obtained in the response is equal to the session nonce + 1 (Prevents replay attacks)
if(*(resp_message->message_aes_gcm_data.reserved) != (session_info->active.counter + 1 ))
{
SAFE_FREE(req_message);
SAFE_FREE(resp_message);
SAFE_FREE(decrypted_data);
return INVALID_PARAMETER_ERROR;
}
//Update the value of the session nonce in the source enclave
session_info->active.counter = session_info->active.counter + 1;
memcpy(out_buff_len, &decrypted_data_length, sizeof(decrypted_data_length));
memcpy(*out_buff, decrypted_data, decrypted_data_length);
SAFE_FREE(decrypted_data);
SAFE_FREE(req_message);
SAFE_FREE(resp_message);
return SUCCESS;
}
//Close a current session
ATTESTATION_STATUS close_session(dh_session_t *session_info)
{
sgx_status_t status;
uint32_t retstatus;
if(!session_info)
{
return INVALID_PARAMETER_ERROR;
}
//Ocall to ask the destination enclave to end the session
status = end_session_ocall(&retstatus, session_info->session_id);
if (status == SGX_SUCCESS)
{
if ((ATTESTATION_STATUS)retstatus != SUCCESS)
return ((ATTESTATION_STATUS)retstatus);
}
else
{
return ATTESTATION_SE_ERROR;
}
return SUCCESS;
}
//Returns a new sessionID for the source destination session
ATTESTATION_STATUS generate_session_id(uint32_t *session_id)
{
ATTESTATION_STATUS status = SUCCESS;
if(!session_id)
{
return INVALID_PARAMETER_ERROR;
}
//if the session structure is untintialized, set that as the next session ID
for (int i = 0; i < MAX_SESSION_COUNT; i++)
{
if (g_session_id_tracker[i] == NULL)
{
*session_id = i;
return status;
}
}
status = NO_AVAILABLE_SESSION_ERROR;
return status;
}

@ -0,0 +1,53 @@
/*
* Copyright (C) 2011-2019 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 "datatypes.h"
#include "sgx_eid.h"
#include "sgx_trts.h"
#include "dh_session_protocol.h"
#ifndef LOCALATTESTATION_H_
#define LOCALATTESTATION_H_
#ifdef __cplusplus
extern "C" {
#endif
uint32_t SGXAPI create_session(dh_session_t *p_session_info);
uint32_t SGXAPI send_request_receive_response(dh_session_t *p_session_info, char *inp_buff, size_t inp_buff_len, size_t max_out_buff_size, char **out_buff, size_t* out_buff_len);
uint32_t SGXAPI close_session(dh_session_t *p_session_info);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,133 @@
#
# Copyright (C) 2011-2019 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
ifneq ($(SGX_MODE), HW)
Trts_Library_Name := sgx_trts_sim
Service_Library_Name := sgx_tservice_sim
else
Trts_Library_Name := sgx_trts
Service_Library_Name := sgx_tservice
endif
ifneq ($(SGX_MODE), HW)
Urts_Library_Name := sgx_urts_sim
else
Urts_Library_Name := sgx_urts
endif
Crypto_Library_Name := sgx_tcrypto
ENCLAVE_NAME := libenclave_initiator.so
SIGNED_ENCLAVE_NAME := libenclave_initiator.signed.so
$(SIGNED_ENCLAVE_NAME) : $(ENCLAVE_NAME)
@$(SGX_ENCLAVE_SIGNER) sign -key EnclaveInitiator_private.pem -enclave $(ENCLAVE_NAME) -out $@ -config EnclaveInitiator.config.xml
@cp $(SIGNED_ENCLAVE_NAME) $(TOPDIR)/$(OUTDIR)/
@echo "SIGN => $@"
# 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 := $(Enclave_Security_Link_Flags) \
-Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \
-Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \
-Wl,--start-group -l$(Urts_Library_Name) -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -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=EnclaveInitiator.lds
SGX_COMMON_FLAGS += -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type \
-Waddress -Wsequence-point -Wformat-security \
-Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow \
-Wcast-align -Wconversion -Wredundant-decls
SGX_COMMON_CFLAGS := $(SGX_COMMON_FLAGS) -Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants
SGX_COMMON_CXXFLAGS := $(SGX_COMMON_FLAGS) -Wnon-virtual-dtor -std=c++11
Enclave_Include_Paths := -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/libcxx -I../Include
Enclave_C_Flags := $(Enclave_Include_Paths) -nostdinc -fvisibility=hidden -fpie -ffunction-sections -fdata-sections
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++
ifeq ($(LAv2), 1)
Enclave_C_Flags += -DSGX_USE_LAv2_INITIATOR
Enclave_Cpp_Flags += -DSGX_USE_LAv2_INITIATOR
endif
Enclave_Cpp_Files := $(wildcard *.cpp)
ENCLAVE_CPP_OBJECTS := $(Enclave_Cpp_Files:.cpp=.o)
.PHONY = all clean target
target = $(SIGNED_ENCLAVE_NAME)
all:
@make target
clean:
@rm -f $(ENCLAVE_NAME) $(SIGNED_ENCLAVE_NAME) *.o *_t.c *_t.h *_u.c *_u.h
$(ENCLAVE_NAME):EnclaveInitiator_t.o $(ENCLAVE_CPP_OBJECTS)
@$(CXX) $^ -o $@ $(ENCLAVE_LINK_FLAGS)
@echo "LINK => $@"
######## Enclave Objects ########
EnclaveInitiator_t.h: $(SGX_EDGER8R) EnclaveInitiator.edl
@$(SGX_EDGER8R) --trusted EnclaveInitiator.edl --search-path $(SGX_SDK)/include
@echo "GEN => $@"
EnclaveInitiator_t.c: EnclaveInitiator_t.h
EnclaveInitiator_t.o: EnclaveInitiator_t.c
@$(CC) $(SGX_COMMON_CFLAGS) $(Enclave_C_Flags) -c $< -o $@
@echo "CC <= $<"
%.o: %.cpp EnclaveInitiator_t.h
@$(CXX) $(SGX_COMMON_CXXFLAGS) $(Enclave_Cpp_Flags) -c $< -o $@
@echo "CXX <= $<"

@ -0,0 +1,222 @@
/*
* Copyright (C) 2011-2019 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 "sgx_eid.h"
#include "EnclaveMessageExchange.h"
#include "error_codes.h"
#include "Utility_EnclaveInitiator.h"
#include "stdlib.h"
#include "string.h"
uint32_t marshal_input_parameters_e2_foo1(uint32_t target_fn_id, uint32_t msg_type, uint32_t var1, uint32_t var2, char** marshalled_buff, size_t* marshalled_buff_len)
{
ms_in_msg_exchange_t *ms;
size_t param_len, ms_len;
char *temp_buff;
param_len = sizeof(var1)+sizeof(var2);
temp_buff = (char*)malloc(param_len);
if(!temp_buff)
return MALLOC_ERROR;
memcpy(temp_buff,&var1,sizeof(var1));
memcpy(temp_buff+sizeof(var1),&var2,sizeof(var2));
ms_len = sizeof(ms_in_msg_exchange_t) + param_len;
ms = (ms_in_msg_exchange_t *)malloc(ms_len);
if(!ms)
{
SAFE_FREE(temp_buff);
return MALLOC_ERROR;
}
ms->msg_type = msg_type;
ms->target_fn_id = target_fn_id;
ms->inparam_buff_len = (uint32_t)param_len;
memcpy(&ms->inparam_buff, temp_buff, param_len);
*marshalled_buff = (char*)ms;
*marshalled_buff_len = ms_len;
SAFE_FREE(temp_buff);
return SUCCESS;
}
uint32_t unmarshal_retval_and_output_parameters_e2_foo1(char* out_buff, char** retval)
{
size_t retval_len;
ms_out_msg_exchange_t *ms;
if(!out_buff)
return INVALID_PARAMETER_ERROR;
ms = (ms_out_msg_exchange_t *)out_buff;
retval_len = ms->retval_len;
*retval = (char*)malloc(retval_len);
if(!*retval)
return MALLOC_ERROR;
memcpy(*retval, ms->ret_outparam_buff, retval_len);
return SUCCESS;
}
uint32_t unmarshal_input_parameters_e1_foo1(external_param_struct_t *pstruct, ms_in_msg_exchange_t* ms)
{
char* buff;
size_t len;
if(!pstruct || !ms)
return INVALID_PARAMETER_ERROR;
buff = ms->inparam_buff;
len = ms->inparam_buff_len;
if(len != (sizeof(pstruct->var1)+sizeof(pstruct->var2)+sizeof(pstruct->p_internal_struct->ivar1)+sizeof(pstruct->p_internal_struct->ivar2)))
return ATTESTATION_ERROR;
memcpy(&pstruct->var1, buff, sizeof(pstruct->var1));
memcpy(&pstruct->var2, buff + sizeof(pstruct->var1), sizeof(pstruct->var2));
memcpy(&pstruct->p_internal_struct->ivar1, buff+(sizeof(pstruct->var1)+sizeof(pstruct->var2)), sizeof(pstruct->p_internal_struct->ivar1));
memcpy(&pstruct->p_internal_struct->ivar2, buff+(sizeof(pstruct->var1)+sizeof(pstruct->var2)+sizeof(pstruct->p_internal_struct->ivar1)), sizeof(pstruct->p_internal_struct->ivar2));
return SUCCESS;
}
uint32_t marshal_retval_and_output_parameters_e1_foo1(char** resp_buffer, size_t* resp_length, uint32_t retval, external_param_struct_t *p_struct_var, size_t len_data, size_t len_ptr_data)
{
ms_out_msg_exchange_t *ms;
size_t param_len, ms_len, ret_param_len;;
char *temp_buff;
int* addr;
char* struct_data;
size_t retval_len;
if(!resp_length || !p_struct_var)
return INVALID_PARAMETER_ERROR;
retval_len = sizeof(retval);
struct_data = (char*)p_struct_var;
param_len = len_data + len_ptr_data;
ret_param_len = param_len + retval_len;
addr = *(int **)(struct_data + len_data);
temp_buff = (char*)malloc(ret_param_len);
if(!temp_buff)
return MALLOC_ERROR;
memcpy(temp_buff, &retval, sizeof(retval));
memcpy(temp_buff + sizeof(retval), struct_data, len_data);
memcpy(temp_buff + sizeof(retval) + len_data, addr, len_ptr_data);
ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len;
ms = (ms_out_msg_exchange_t *)malloc(ms_len);
if(!ms)
{
SAFE_FREE(temp_buff);
return MALLOC_ERROR;
}
ms->retval_len = (uint32_t)retval_len;
ms->ret_outparam_buff_len = (uint32_t)ret_param_len;
memcpy(&ms->ret_outparam_buff, temp_buff, ret_param_len);
*resp_buffer = (char*)ms;
*resp_length = ms_len;
SAFE_FREE(temp_buff);
return SUCCESS;
}
uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, uint32_t secret_data, char** marshalled_buff, size_t* marshalled_buff_len)
{
ms_in_msg_exchange_t *ms;
size_t secret_data_len, ms_len;
if(!marshalled_buff_len)
return INVALID_PARAMETER_ERROR;
secret_data_len = sizeof(secret_data);
ms_len = sizeof(ms_in_msg_exchange_t) + secret_data_len;
ms = (ms_in_msg_exchange_t *)malloc(ms_len);
if(!ms)
return MALLOC_ERROR;
ms->msg_type = msg_type;
ms->target_fn_id = target_fn_id;
ms->inparam_buff_len = (uint32_t)secret_data_len;
memcpy(&ms->inparam_buff, &secret_data, secret_data_len);
*marshalled_buff = (char*)ms;
*marshalled_buff_len = ms_len;
return SUCCESS;
}
uint32_t umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms)
{
char* buff;
size_t len;
if(!inp_secret_data || !ms)
return INVALID_PARAMETER_ERROR;
buff = ms->inparam_buff;
len = ms->inparam_buff_len;
if(len != sizeof(uint32_t))
return ATTESTATION_ERROR;
memcpy(inp_secret_data, buff, sizeof(uint32_t));
return SUCCESS;
}
uint32_t marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response)
{
ms_out_msg_exchange_t *ms;
size_t secret_response_len, ms_len;
size_t retval_len, ret_param_len;
if(!resp_length)
return INVALID_PARAMETER_ERROR;
secret_response_len = sizeof(secret_response);
retval_len = secret_response_len;
ret_param_len = secret_response_len;
ms_len = sizeof(ms_out_msg_exchange_t) + ret_param_len;
ms = (ms_out_msg_exchange_t *)malloc(ms_len);
if(!ms)
return MALLOC_ERROR;
ms->retval_len = (uint32_t)retval_len;
ms->ret_outparam_buff_len = (uint32_t)ret_param_len;
memcpy(&ms->ret_outparam_buff, &secret_response, secret_response_len);
*resp_buffer = (char*)ms;
*resp_length = ms_len;
return SUCCESS;
}
uint32_t umarshal_message_exchange_response(char* out_buff, char** secret_response)
{
size_t retval_len;
ms_out_msg_exchange_t *ms;
if(!out_buff)
return INVALID_PARAMETER_ERROR;
ms = (ms_out_msg_exchange_t *)out_buff;
retval_len = ms->retval_len;
*secret_response = (char*)malloc(retval_len);
if(!*secret_response)
{
return MALLOC_ERROR;
}
memcpy(*secret_response, ms->ret_outparam_buff, retval_len);
return SUCCESS;
}

@ -0,0 +1,65 @@
/*
* Copyright (C) 2011-2019 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.
*
*/
#ifndef UTILITY_E1_H__
#define UTILITY_E1_H__
#include "stdint.h"
typedef struct _internal_param_struct_t
{
uint32_t ivar1;
uint32_t ivar2;
} internal_param_struct_t;
typedef struct _external_param_struct_t
{
uint32_t var1;
uint32_t var2;
internal_param_struct_t *p_internal_struct;
} external_param_struct_t;
#ifdef __cplusplus
extern "C" {
#endif
uint32_t marshal_input_parameters_e2_foo1(uint32_t target_fn_id, uint32_t msg_type, uint32_t var1, uint32_t var2, char** marshalled_buff, size_t* marshalled_buff_len);
uint32_t unmarshal_retval_and_output_parameters_e2_foo1(char* out_buff, char** retval);
uint32_t unmarshal_input_parameters_e1_foo1(external_param_struct_t *pstruct, ms_in_msg_exchange_t* ms);
uint32_t marshal_retval_and_output_parameters_e1_foo1(char** resp_buffer, size_t* resp_length, uint32_t retval, external_param_struct_t *p_struct_var, size_t len_data, size_t len_ptr_data);
uint32_t marshal_message_exchange_request(uint32_t target_fn_id, uint32_t msg_type, uint32_t secret_data, char** marshalled_buff, size_t* marshalled_buff_len);
uint32_t umarshal_message_exchange_request(uint32_t* inp_secret_data, ms_in_msg_exchange_t* ms);
uint32_t marshal_message_exchange_response(char** resp_buffer, size_t* resp_length, uint32_t secret_response);
uint32_t umarshal_message_exchange_response(char* out_buff, char** secret_response);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,46 @@
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
OPENSSL ?= $(CUR_DIR)/deps/openssl
SGX_SDK ?= /opt/intel/sgxsdk
BIN_DIR := bin
APP := $(BIN_DIR)/appinitiator
SGX_MODE ?= HW
ifneq ($(SGX_MODE), HW)
OCCLUM_LIB := /opt/occlum/build_sim/lib
else
OCCLUM_LIB := /opt/occlum/build/lib
endif
occlum_=$(CUR_DIR)/../..
.PHONY: all build_src test clean
all: occlum_context
occlum_context: build_src
@mkdir -p occlum_context
@cd occlum_context && \
occlum init && \
cp $(CUR_DIR)/AppResponder/responder image/bin/ && \
cp $(OPENSSL)/libcrypto.so.1.1 image/lib/ && \
cp $(CUR_DIR)/DiffieHellmanLibrary/libecdh.so image/lib/ && \
occlum build
@cp -r occlum_context/.occlum .occlum
build_src:
@$(MAKE) --no-print-directory -C DiffieHellmanLibrary
@$(MAKE) --no-print-directory -C AppInitiator
@$(MAKE) --no-print-directory -C AppResponder
@$(MAKE) --no-print-directory -C EnclaveInitiator
test: build_src
LD_LIBRARY_PATH=$(OCCLUM_LIB):$(SGX_SDK)/sdk_libs RUST_BACKTRACE=1 \
./$(APP)
clean:
@$(MAKE) --no-print-directory -C AppInitiator clean
@$(MAKE) --no-print-directory -C AppResponder clean
@$(MAKE) --no-print-directory -C EnclaveInitiator clean
@$(MAKE) --no-print-directory -C DiffieHellmanLibrary clean
@rm -rf .occlum occlum_context bin

@ -0,0 +1,38 @@
# Occlum Local Attestation Demo
This project demonstrates how an SGX SDK enclave can do local attestation with and establish a secure connection to an Occlum enclave, where a trusted app running upon the Occlum LibOS.
## Introduction
This project consists of four components:
1. **EnclaveInitiator**: an SGX SDK enclave that initiates requests for local attestation;
2. **AppInitiator**: an untrusted app that hosts the enclave of EnclaveInitiator and sends the enclave's requests to a responder enclave through socket.
3. **AppResponder**: a trusted socket server hosted by Occlum LibOS in another enclave, which responses to the requests initiated by EnclaveInitator and sent by AppInitiator;
4. **DiffieHellmanLibrary**: a library used by AppResponder that implements an Attestation-based, Diffie-Hellman Key Exchange protocol.
## Interopability
To do local attestation and establish a secure channel between two enclaves, they must talk in the same protocol. The protocol chosen and implemented by Intel SGX SDK is an Attestation-based, Diffie-Hellman Key Exchange protocol, whose APIs are defined in `sgx_dh.h` and used by the local attestation demo shipped with Intel SGX SDK.
To achieve interoperability with SGX SDK-based enclaves, an Occlum enclave must also talk in this protocol. But apps hosted by Occlum LibOS do not and may not use Intel SGX SDK (at least directly), thus no access to the protocol APIs exposed in `sgx_dh.h`. To resolve this problem, we build DiffieHellmanLibrary, which provides the same set of APIs as `sgx_dh.h`. And to ensure the full compatibility with Intel SGX SDK, DiffieHellmanLibrary actually reuses the code of Intel SGX SDK as much as possible. This is why EnclaveInitiator and AppResponder can talk to and negotiate with each other.
## Local Attestation through Ioctls
In the same vein as remote attestation, Occlum LibOS itself only provides three minimal APIs regarding local attestation and leaves most of the work to the user space. The three APIs are exposed to the user space through ioctls on device `/dev/sgx`. We offer a user-space library (i.e., DiffieHellmanLibrary) to hide the low-level details of ioctls and provide a high-level, user-friendly APIs. This design achieves both the easy-of-use of high-level APIs and the flexibility of low-level APIs.
## How to Build and Run
**Step 1.** Get prerequisites
```shell
./download_src_and_build_deps.sh
```
which downloads some source code and build dependencies (e.g., OpenSSL).
**Step 2.** Build and run the demo
```shell
make
make test
```
To run the demo in the SGX simulation mode, do `export SGX_MODE=SIM` before running the commands above.

@ -0,0 +1,157 @@
#
# Copyright (C) 2011-2019 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.
#
#
# -------------------------------------------------------------------
# Function : parent-dir
# Arguments: 1: path
# Returns : Parent dir or path of $1, with final separator removed.
# -------------------------------------------------------------------
parent-dir = $(patsubst %/,%,$(dir $(1:%/=%)))
# ------------------------------------------------------------------
# Macro : my-dir
# Returns : the directory of the current Makefile
# Usage : $(my-dir)
# ------------------------------------------------------------------
my-dir = $(realpath $(call parent-dir,$(lastword $(MAKEFILE_LIST))))
ROOT_DIR := $(call my-dir)
ifneq ($(words $(subst :, ,$(ROOT_DIR))), 1)
$(error main directory cannot contain spaces nor colons)
endif
# -------------------------------------------------------------------
# User needs to install SGX SDK installer before compiling this project.
# -------------------------------------------------------------------
ifeq ($(SGX_SDK),)
$(warning "import SGX SDK environment variable")
export SGX_SDK=/opt/intel/sgxsdk/
endif
SGX_SDK_PATH ?= $(SGX_SDK)
#-------------------------------------------------------------------
# This is the output folder.
#-------------------------------------------------------------------
BIN_DIR := bin
TOPDIR = $(ROOT_DIR)
OUTDIR := $(BIN_DIR)
CP = cp
CC ?= gcc
CXX ?= g++
# turn on cet
CC_GREAT_EQUAL_8 := $(shell expr "`$(CC) -dumpversion`" \>= "8")
ifeq ($(CC_GREAT_EQUAL_8), 1)
COMMON_FLAGS += -fcf-protection
endif
# ------------------------------------------------------------------
# Define common variables
# ------------------------------------------------------------------
SGX_MODE ?= HW
SGX_ARCH ?= x64
SGX_DEBUG ?= 1
#-------------------------------------------------------------------
# Define common compile flags used for GCC and G++
#-------------------------------------------------------------------
COMMON_FLAGS = -ffunction-sections -fdata-sections
COMMON_FLAGS += -Wall -Wextra -Wchar-subscripts -Wno-coverage-mismatch -Winit-self \
-Wpointer-arith -Wreturn-type -Waddress -Wsequence-point -Wformat-security \
-Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow \
-Wcast-align -Wconversion -Wredundant-decls
ifeq ($(SGX_DEBUG), 1)
ifeq ($(SGX_PRERELEASE), 1)
$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!)
endif
endif
ifeq ($(SGX_DEBUG), 1)
COMMON_FLAGS += -ggdb -DDEBUG
COMMON_FLAGS += -DDEBUG_LEVEL=TRACE_DEBUG
else
COMMON_FLAGS += -o2 -UDEBUG
endif
CFLAGS = $(COMMON_FLAGS)
CXXFLAGS = $(COMMON_FLAGS)
# additional warnings flags for C
CFLAGS += -Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants
# additional warnings flags for C++
CXXFLAGS += -Wnon-virtual-dtor -std=c++11
# ----------------------------------------------------------------
# Define common link options
# ----------------------------------------------------------------
COMMON_LDFLAGS := -Wl,-z,relro,-z,now,-z,noexecstack
# Compiler and linker options for an Enclave
#
# We are using '--export-dynamic' so that `g_global_data_sim' etc.
# will be exported to dynamic symbol table.
#
# When `pie' is enabled, the linker (both BFD and Gold) under Ubuntu 14.04
# will hide all symbols from dynamic symbol table even if they are marked
# as `global' in the LD version script.
ENCLAVE_CFLAGS = -ffreestanding -nostdinc -fvisibility=hidden -fpie
ifeq ($(CC_GREAT_EQUAL_8), 1)
ENCLAVE_CFLAGS += -fcf-protection
endif
ENCLAVE_CXXFLAGS = $(ENCLAVE_CFLAGS) -nostdinc++
ENCLAVE_LDFLAGS = $(COMMON_LDFLAGS)
RM = rm -f
ifeq ($(shell getconf LONG_BIT), 32)
SGX_ARCH := x86
else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32)
SGX_ARCH := x86
endif
ifeq ($(SGX_ARCH), x86)
SGX_COMMON_FLAGS := -m32
SGX_LIBRARY_PATH := $(SGX_SDK)/lib
SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign
SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r
else
SGX_COMMON_FLAGS := -m64
SGX_LIBRARY_PATH := $(SGX_SDK)/lib64
SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign
SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r
endif
SGX_COMMON_FLAGS += $(COMMON_FLAGS)

@ -0,0 +1,85 @@
#!/usr/bin/env bash
export CC=occlum-gcc
export CXX=occlum-g++
THISDIR="$(dirname $(readlink -f $0))"
INSTALLDIR="/usr/local/occlum/x86_64-linux-musl"
DEPSDIR="$THISDIR/deps"
TARGET_SO="$DEPSDIR/openssl/libcrypto.so"
mkdir -p $DEPSDIR || exit 1
# Download OpenSSL 1.1.1
OPENSSLDIR="${DEPSDIR}/openssl"
if [ ! -d "$OPENSSLDIR" ] ; then
echo "Downloading openssl ..."
cd "$DEPSDIR" && \
wget https://github.com/openssl/openssl/archive/OpenSSL_1_1_1.tar.gz && \
tar -xvzf OpenSSL_1_1_1.tar.gz && \
mv openssl-OpenSSL_1_1_1 openssl && \
echo "Download openssl successfully" || exit 1
else
echo "The openssl code is already existent"
fi
# Build openssl
if [ ! -f "$TARGET_SO" ] ; then
echo "Building openssl ..."
cd "$OPENSSLDIR" && \
CC=occlum-gcc ./config \
--prefix=$INSTALLDIR \
--openssldir=/usr/local/occlum/ssl \
--with-rand-seed=rdcpu \
no-zlib no-async no-tests && \
make -j${nproc} && \
echo "Build openssl successfully" || exit 1
else
echo "The openssl library is aleady existent"
fi
SGX_VER=2.8
# Download SGX SDK
SGX_SDK="${DEPSDIR}/linux-sgx-sdk"
if [ ! -d "$SGX_SDK" ] ; then
echo "Downloading linux-sgx-sdk ..."
cd "$DEPSDIR" && \
wget https://github.com/intel/linux-sgx/archive/sgx_$SGX_VER.tar.gz && \
tar -xvzf "sgx_$(SGX_VER).tar.gz" && \
mv linux-sgx-sgx_$SGX_VER linux-sgx-sdk && \
echo "Download sgx-sdk successfully" || exit 1
else
echo "The sgx-sdk code is already existent"
fi
# Copy files to DiffieHellmanLibrary dir
DH_DIR=$THISDIR/DiffieHellmanLibrary
DH_PATCH=DiffieHellmanLibrary.patch
mkdir -p $DH_DIR/include
cp $SGX_SDK/{sdk/ec_dh_lib/sgx_dh_internal.h,\
common/inc/internal/ecp_interface.h,\
common/inc/internal/ssl_wrapper.h\
} $DH_DIR/include
cp $SGX_SDK/{psw/ae/aesm_service/source/utils/crypto_aes_gcm.cpp,\
sdk/ec_dh_lib/ec_dh.cpp,\
sdk/tlibcrypto/sgxssl/sgx_cmac128.cpp,\
sdk/tlibcrypto/sgxssl/sgx_ecc256.cpp,\
sdk/tlibcrypto/sgxssl/sgx_sha256_msg.cpp\
} $DH_DIR
cd $DH_DIR && git apply $DH_PATCH >/dev/null 2>&1 || git apply $DH_PATCH -R --check
cd - >/dev/null 2>&1
echo "DiffieHellmanLibrary is ready"
# Copy header files from linux-sgx-sdk local attestation demo
mkdir -p Include
cp $SGX_SDK/SampleCode/LocalAttestation/Include/{datatypes.h,\
dh_session_protocol.h,\
error_codes.h,\
fifo_def.h\
} Include
echo "Include is ready"

@ -163,7 +163,7 @@ static int do_SGXIOC_CREATE_AND_VERIFY_REPORT(int sgx_fd) {
if (ioctl(sgx_fd, SGXIOC_SELF_TARGET, &target_info) < 0) { if (ioctl(sgx_fd, SGXIOC_SELF_TARGET, &target_info) < 0) {
THROW_ERROR("failed to ioctl /dev/sgx"); THROW_ERROR("failed to ioctl /dev/sgx");
} }
sgx_report_t report_data; sgx_report_data_t report_data;
sgx_report_t report; sgx_report_t report;
sgxioc_create_report_arg_t args[] = { sgxioc_create_report_arg_t args[] = {