From 1df89b3546815fbb2718e64e9a3d1da571aaa5c5 Mon Sep 17 00:00:00 2001 From: manju956 Date: Tue, 1 Sep 2020 03:21:28 -0700 Subject: [PATCH] Worker key refresh policy implemenation This feature initiates refresh of worker encryption key pair based on number of work orders processed in case of Singleton worker or number of pre-processed work orders in case of KME worker. A new pair of encryption key is generated in the enclave and the updated enclave signup details are stored in the KvStorage in workers table. Worker encryption key signature is re-computed when encryption key gets refreshed. When a worker key gets refreshed during the work order submission, a specific error code is returned to client to indicate worker key refresh. On receiving this error code, client retrieves the updated worker details and does work order submission again. Signed-off-by: manju956 --- common/cpp/CMakeLists.txt | 2 +- common/cpp/crypto/CMakeLists.txt | 2 +- common/cpp/error.h | 7 + common/cpp/tcf_error.h | 4 +- common/cpp/verify_ias_report/CMakeLists.txt | 2 +- common/python/error_code/enclave_error.py | 5 +- common/python/error_code/error_status.py | 3 +- config/kme_config.toml | 5 + config/singleton_enclave_config.toml | 4 + .../base_enclave_info.py | 2 - .../base_enclave_manager.py | 13 +- .../kme/kme_enclave_info.py | 6 +- .../kme/kme_enclave_manager.py | 27 +++- .../singleton/singleton_enclave_info.py | 7 +- .../singleton/singleton_enclave_manager.py | 5 +- .../work_order_processor_manager.py | 34 ++++- .../worker_key_refresh.py | 121 ++++++++++++++++++ .../wpe/wpe_enclave_manager.py | 1 + .../apps/generic_client/generic_client.py | 108 ++++++++++++++++ .../avalon_listener/tcs_work_order_handler.py | 2 + .../enclave/enclave_data.cpp | 15 +++ .../enclave/enclave_data.h | 7 + .../trusted_worker_manager/enclave/signup.edl | 7 + .../enclave/signup_enclave_common.cpp | 64 ++++++++- .../enclave/signup_enclave_common.h | 1 + .../singleton/signup_enclave_singleton.cpp | 1 + .../enclave/work_order_processor.cpp | 41 +++++- .../enclave_bridge/kme/signup_kme.cpp | 58 +++++++++ .../enclave_bridge/kme/signup_kme.h | 4 + .../singleton/signup_singleton.cpp | 60 +++++++++ .../singleton/signup_singleton.h | 4 + .../kme/signup_info_kme.cpp | 33 +++++ .../kme/signup_info_kme.h | 1 + .../singleton/signup_info_singleton.cpp | 33 +++++ .../singleton/signup_info_singleton.h | 2 + 35 files changed, 655 insertions(+), 36 deletions(-) create mode 100644 enclave_manager/avalon_enclave_manager/worker_key_refresh.py diff --git a/common/cpp/CMakeLists.txt b/common/cpp/CMakeLists.txt index 6944482fa..e5e264236 100644 --- a/common/cpp/CMakeLists.txt +++ b/common/cpp/CMakeLists.txt @@ -36,7 +36,7 @@ SET(COMMON_CXX_FLAGS ${DEBUG_FLAGS} "-m64" "-fvisibility=hidden" "-fpie" "-fPIC" SET(UNTRUSTED_LIB_NAME uavalon-common) PROJECT(${UNTRUSTED_LIB_NAME} CXX) -pkg_check_modules (OPENSSL REQUIRED openssl>=1.1.1d) +#pkg_check_modules (OPENSSL REQUIRED openssl>=1.1.1d) ADD_LIBRARY(${UNTRUSTED_LIB_NAME} STATIC ${PROJECT_HEADERS} ${PROJECT_SOURCES}) diff --git a/common/cpp/crypto/CMakeLists.txt b/common/cpp/crypto/CMakeLists.txt index 46c795337..15cbb7720 100644 --- a/common/cpp/crypto/CMakeLists.txt +++ b/common/cpp/crypto/CMakeLists.txt @@ -34,7 +34,7 @@ SET(COMMON_CXX_FLAGS ${DEBUG_FLAGS} "-m64" "-fvisibility=hidden" "-fpie" "-fPIC" SET(UNTRUSTED_LIB_NAME uavalon-crypto) PROJECT(${UNTRUSTED_LIB_NAME} CXX) -pkg_check_modules (OPENSSL REQUIRED openssl>=1.1.1d) +#pkg_check_modules (OPENSSL REQUIRED openssl>=1.1.1d) ADD_LIBRARY(${UNTRUSTED_LIB_NAME} STATIC ${PROJECT_HEADERS} ${PROJECT_SOURCES}) diff --git a/common/cpp/error.h b/common/cpp/error.h index 7c1a76bcd..9da0d4c0b 100644 --- a/common/cpp/error.h +++ b/common/cpp/error.h @@ -52,6 +52,13 @@ namespace tcf { ) : Error(TCF_ERR_CRYPTO, msg) {} }; // class CryptoError + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + class KeyRefreshError : public Error { + public: + explicit KeyRefreshError( + const std::string& msg + ) : Error(TCF_ERR_ENCRYPT_KEY_REFRESH, msg) {} + }; // class KeyRefreshError // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX class MemoryError : public Error { diff --git a/common/cpp/tcf_error.h b/common/cpp/tcf_error.h index 5d36ffe2b..e5575f7cd 100644 --- a/common/cpp/tcf_error.h +++ b/common/cpp/tcf_error.h @@ -42,7 +42,9 @@ typedef enum { TCF_ERR_SYSTEM_BUSY = -10, TCF_ERR_CRYPTO = -11, /** Invalid workload ID */ - TCF_ERR_INVALID_WORKLOAD = -12 + TCF_ERR_INVALID_WORKLOAD = -12, + /* Enclave key refresh error */ + TCF_ERR_ENCRYPT_KEY_REFRESH = -13 } tcf_err_t; typedef enum { diff --git a/common/cpp/verify_ias_report/CMakeLists.txt b/common/cpp/verify_ias_report/CMakeLists.txt index 189856d1f..86d310b19 100644 --- a/common/cpp/verify_ias_report/CMakeLists.txt +++ b/common/cpp/verify_ias_report/CMakeLists.txt @@ -45,7 +45,7 @@ add_custom_command(OUTPUT ${PROJECT_GENERATED_IAS_SOURCES} SET(UNTRUSTED_LIB_NAME uavalon-verify-ias-report) PROJECT(${UNTRUSTED_LIB_NAME} CXX) -pkg_check_modules (OPENSSL REQUIRED openssl>=1.1.1d) +#pkg_check_modules (OPENSSL REQUIRED openssl>=1.1.1d) ADD_LIBRARY(${UNTRUSTED_LIB_NAME} STATIC ${PROJECT_HEADERS} ${PROJECT_GENERATED_IAS_SOURCES} ${PROJECT_SOURCES}) diff --git a/common/python/error_code/enclave_error.py b/common/python/error_code/enclave_error.py index c45481644..aa8a15e64 100644 --- a/common/python/error_code/enclave_error.py +++ b/common/python/error_code/enclave_error.py @@ -31,4 +31,7 @@ class EnclaveError(IntEnum): # this should be converted to ENCLAVE_ERR_SYSTEM for reporting. ENCLAVE_ERR_SYSTEM_BUSY = -10, ENCLAVE_ERR_CRYPTO = -11, - ENCLAVE_ERR_INVALID_WORKLOAD = -12 # Invalid workload ID + # Invalid workload ID + ENCLAVE_ERR_INVALID_WORKLOAD = -12, + # Worker encryption key refresh error + ENCLAVE_ERR_ENCRYPT_KEY_REFRESH = -13 diff --git a/common/python/error_code/error_status.py b/common/python/error_code/error_status.py index 6ade03283..1289b4085 100644 --- a/common/python/error_code/error_status.py +++ b/common/python/error_code/error_status.py @@ -33,7 +33,8 @@ class WorkOrderStatus(IntEnum): PROCESSING = 7 BUSY = 8 INVALID_WORKLOAD = 9 - UNKNOWN_ERROR = 10 + WORKER_ENCRYPT_KEY_REFRESHED = 10 + UNKNOWN_ERROR = 11 @unique diff --git a/config/kme_config.toml b/config/kme_config.toml index 19ad1eefc..ebd4f4b8f 100755 --- a/config/kme_config.toml +++ b/config/kme_config.toml @@ -105,3 +105,8 @@ DataEncryptionAlgorithm = "AES-GCM-256" # Supported work order formats are JSON-RPC, JSON-RPC-JWT, and Custom format # starting with tilde "~" workOrderPayloadFormats = "JSON-RPC" + +[WorkerKeyRefresh] +# Configure key refresh interval based on number of preprocessed work orders. +# By default, key refresh feature is disabled. +work_orders_count = 0 diff --git a/config/singleton_enclave_config.toml b/config/singleton_enclave_config.toml index 67d983658..a096e5e89 100755 --- a/config/singleton_enclave_config.toml +++ b/config/singleton_enclave_config.toml @@ -116,3 +116,7 @@ DataEncryptionAlgorithm = "AES-GCM-256" # starting with tilde "~" workOrderPayloadFormats = "JSON-RPC" +[WorkerKeyRefresh] +# Configure key refresh interval based on number of processed work orders. +# By default, key refresh feature is disabled. +work_orders_count = 0 diff --git a/enclave_manager/avalon_enclave_manager/base_enclave_info.py b/enclave_manager/avalon_enclave_manager/base_enclave_info.py index e371e217c..5d5d9d034 100644 --- a/enclave_manager/avalon_enclave_manager/base_enclave_info.py +++ b/enclave_manager/avalon_enclave_manager/base_enclave_info.py @@ -316,5 +316,3 @@ def _get_sealed_data_file_name(self, relative_path, worker_id): @returns file_name - Fully qualified file name for sealed data """ return os.path.join(TCF_HOME, relative_path + "." + worker_id) - - # ----------------------------------------------------------------- diff --git a/enclave_manager/avalon_enclave_manager/base_enclave_manager.py b/enclave_manager/avalon_enclave_manager/base_enclave_manager.py index a8a257f82..0933b32a4 100755 --- a/enclave_manager/avalon_enclave_manager/base_enclave_manager.py +++ b/enclave_manager/avalon_enclave_manager/base_enclave_manager.py @@ -18,9 +18,11 @@ import json import logging import sys -import utility.hex_utils as hex_utils from abc import ABC, abstractmethod +import utility.hex_utils as hex_utils +import utility.file_utils as file_utils + from database import connector from avalon_enclave_manager.worker_kv_delegate import WorkerKVDelegate from avalon_enclave_manager.work_order_kv_delegate import WorkOrderKVDelegate @@ -34,6 +36,8 @@ class EnclaveManager(ABC): Abstract base class for Enclave Manager """ + signup_data = None + def __init__(self, config): super().__init__() @@ -143,10 +147,11 @@ def _setup_enclave(self): if signup_data is None: logger.error("Failed to create signup data") return None + EnclaveManager.signup_data = signup_data except Exception as e: logger.exception("failed to initialize/signup enclave; %s", str(e)) sys.exit(-1) - return self._get_JSON_from_signup_object(signup_data) + return self._get_JSON_from_signup_object(EnclaveManager.signup_data) # ----------------------------------------------------------------- @@ -161,7 +166,7 @@ def _create_signup_data(self): enclave """ pass - + # ----------------------------------------------------------------- def _get_JSON_from_signup_object(self, signup_data): @@ -204,7 +209,7 @@ def create_json_worker(enclave_data, config): worker_type_data["verificationKey"] = enclave_data.verifying_key worker_type_data["extendedMeasurements"] = \ enclave_data.extended_measurements - worker_type_data["proofDataType"] = enclave_data.proof_data_type + worker_type_data["proofDataType"] = config.get("WorkerConfig")["ProofDataType"] worker_type_data["proofData"] = enclave_data.proof_data worker_type_data["encryptionKey"] = enclave_data.encryption_key worker_type_data["encryptionKeySignature"] = \ diff --git a/enclave_manager/avalon_enclave_manager/kme/kme_enclave_info.py b/enclave_manager/avalon_enclave_manager/kme/kme_enclave_info.py index 1e355e9a1..461248458 100644 --- a/enclave_manager/avalon_enclave_manager/kme/kme_enclave_info.py +++ b/enclave_manager/avalon_enclave_manager/kme/kme_enclave_info.py @@ -25,6 +25,7 @@ import utility.file_utils as file_utils import avalon_enclave_manager.kme.kme_enclave as enclave import avalon_enclave_manager.base_enclave_info as enclave_info +import avalon_enclave_manager.worker_key_refresh as key_refresh logger = logging.getLogger(__name__) @@ -41,9 +42,9 @@ def __init__(self, config, worker_id): enclave._SetLogger(logger) super().__init__(enclave.is_sgx_simulator()) - self._config = config + self._config = config["EnclaveModule"] self._worker_id = worker_id - self._initialize_enclave(config) + self._initialize_enclave(self._config) enclave_info = self._create_enclave_signup_data() try: self.ias_nonce = enclave_info['ias_nonce'] @@ -58,6 +59,7 @@ def __init__(self, config, worker_id): except KeyError as ke: raise Exception("missing enclave initialization parameter; {}" .format(str(ke))) + self.worker_key_refresh = key_refresh.WorkerKeyRefresh(self, config, "kme") # ------------------------------------------------------- diff --git a/enclave_manager/avalon_enclave_manager/kme/kme_enclave_manager.py b/enclave_manager/avalon_enclave_manager/kme/kme_enclave_manager.py index 74a13850a..038e84061 100644 --- a/enclave_manager/avalon_enclave_manager/kme/kme_enclave_manager.py +++ b/enclave_manager/avalon_enclave_manager/kme/kme_enclave_manager.py @@ -20,6 +20,7 @@ import logging import os import sys +import asyncio import avalon_enclave_manager.sgx_work_order_request as work_order_request import avalon_enclave_manager.kme.kme_enclave_info as enclave_info @@ -42,6 +43,7 @@ def __init__(self, config): super().__init__(config) self.proof_data_type = config.get("WorkerConfig")["ProofDataType"] + self.preprocessed_wo_count = 0 # ------------------------------------------------------------------------- @@ -54,8 +56,7 @@ def _create_signup_data(self): enclave """ return enclave_info.\ - KeyManagementEnclaveInfo(self._config["EnclaveModule"], - self._worker_id) + KeyManagementEnclaveInfo(self._config, self._worker_id) # ------------------------------------------------------------------------- @@ -130,10 +131,8 @@ def start_enclave_manager(self): logger.error("Failed to execute boot time flow; " + "exiting Intel SGX Enclave manager: {}".format(err)) exit(1) - self._start_kme_listener() - # ------------------------------------------------------------------------- def _start_kme_listener(self): @@ -155,7 +154,6 @@ def _start_kme_listener(self): kme_listener = KMEListener(rpc_methods) kme_listener.start(host_name, port) - # ----------------------------------------------------------------- def GetUniqueVerificationKey(self, **params): @@ -207,11 +205,30 @@ def RegisterWorkOrderProcessor(self, **params): def PreProcessWorkOrder(self, **params): """ """ + try: + wo_threshold = \ + int(self._config["WorkerKeyRefresh"]["work_orders_count"]) + except Exception as err: + logger.warning("Failed to get work order count from config file. " + + "Setting work orders threshold to 0: %s", str(err)) + wo_threshold = 0 + wo_request = self._get_request_json("PreProcessWorkOrder") wo_request["params"] = params wo_response = self._execute_work_order(json.dumps(wo_request), "") wo_response_json = json.loads(wo_response) + self.preprocessed_wo_count += 1 + if wo_threshold > 0 and self.preprocessed_wo_count == wo_threshold: + try: + enclave_info = EnclaveManager.signup_data + enclave_info.worker_key_refresh._initiate_key_refresh() + # Set preprocessed_wo_count to 0 + self.preprocessed_wo_count = 0 + except Exception as e: + logger.error("failed to get signup data after key refresh: %s", + str(e)) + if "result" in wo_response_json: return wo_response_json["result"] else: diff --git a/enclave_manager/avalon_enclave_manager/singleton/singleton_enclave_info.py b/enclave_manager/avalon_enclave_manager/singleton/singleton_enclave_info.py index 5f5cfcf4f..7be475a84 100644 --- a/enclave_manager/avalon_enclave_manager/singleton/singleton_enclave_info.py +++ b/enclave_manager/avalon_enclave_manager/singleton/singleton_enclave_info.py @@ -23,6 +23,7 @@ from requests.exceptions import HTTPError import utility.file_utils as file_utils import avalon_enclave_manager.singleton.singleton_enclave as enclave +import avalon_enclave_manager.worker_key_refresh as key_refresh from avalon_enclave_manager.base_enclave_info import BaseEnclaveInfo logger = logging.getLogger(__name__) @@ -40,11 +41,11 @@ def __init__(self, config, worker_id): # Initialize the keys that can be used later to # register the enclave enclave._SetLogger(logger) - self._config = config + self._config = config["EnclaveModule"] self._worker_id = worker_id super().__init__(enclave.is_sgx_simulator()) - self._initialize_enclave(config) + self._initialize_enclave(self._config) enclave_info = self._create_enclave_signup_data() try: self.ias_nonce = enclave_info['ias_nonce'] @@ -59,6 +60,8 @@ def __init__(self, config, worker_id): except KeyError as ke: raise Exception("missing enclave initialization parameter; {}" .format(str(ke))) + self.worker_key_refresh = key_refresh.WorkerKeyRefresh(self, config, "singleton") + # ------------------------------------------------------- diff --git a/enclave_manager/avalon_enclave_manager/singleton/singleton_enclave_manager.py b/enclave_manager/avalon_enclave_manager/singleton/singleton_enclave_manager.py index 84e210d1e..e25cb96c3 100755 --- a/enclave_manager/avalon_enclave_manager/singleton/singleton_enclave_manager.py +++ b/enclave_manager/avalon_enclave_manager/singleton/singleton_enclave_manager.py @@ -19,6 +19,7 @@ import logging import os import sys +import asyncio import avalon_enclave_manager.sgx_work_order_request as work_order_request import avalon_enclave_manager.singleton.singleton_enclave_info as enclave_info @@ -73,8 +74,7 @@ def _create_signup_data(self): enclave """ return enclave_info.\ - SingletonEnclaveInfo(self._config.get("EnclaveModule"), - self._worker_id) + SingletonEnclaveInfo(self._config, self._worker_id) # ------------------------------------------------------------------------- @@ -101,7 +101,6 @@ def _execute_wo_in_trusted_enclave(self, input_json_str): # ----------------------------------------------------------------- - def main(args=None): import config.config as pconfig import utility.logger as plogger diff --git a/enclave_manager/avalon_enclave_manager/work_order_processor_manager.py b/enclave_manager/avalon_enclave_manager/work_order_processor_manager.py index 554c6e1a1..f93e007ca 100644 --- a/enclave_manager/avalon_enclave_manager/work_order_processor_manager.py +++ b/enclave_manager/avalon_enclave_manager/work_order_processor_manager.py @@ -20,6 +20,7 @@ import time import logging import utility.jrpc_utility as jrpc_utility +import zmq.asyncio from abc import abstractmethod from error_code.error_status import WorkOrderStatus @@ -36,6 +37,7 @@ class WOProcessorManager(EnclaveManager): def __init__(self, config): super().__init__(config) self._identity = None + self.wo_processed_count = 0 # ------------------------------------------------------------------------- @@ -76,6 +78,14 @@ def _process_work_orders(self): "About to process work orders found in wo-worker-scheduled table.") wo_id = self._kv_helper.csv_pop("wo-worker-scheduled", self._worker_id) + try: + wo_threshold = \ + int(self._config["WorkerKeyRefresh"]["work_orders_count"]) + except Exception as err: + logger.warning("Failed to get work order count from config file. " + + "Setting work orders threshold to 0: %s", str(err)) + wo_threshold = 0 + while wo_id is not None: self._process_work_order_by_id(wo_id) @@ -84,6 +94,17 @@ def _process_work_orders(self): wo_id = self._kv_helper.csv_pop("wo-worker-scheduled", self._worker_id) + self.wo_processed_count += 1 + if wo_threshold > 0 and self.wo_processed_count == wo_threshold: + try: + enclave_info = EnclaveManager.signup_data + enclave_info.worker_key_refresh._initiate_key_refresh() + # Set processed work orders count to 0 + self.wo_processed_count = 0 + except Exception as e: + logger.error("failed to get signup data after key refresh: %s", + str(e)) + # end of loop logger.info("No more worker orders in wo-worker-scheduled table.") @@ -248,12 +269,13 @@ def _validate_request(self, wo_id, wo_request): return False return True - # ------------------------------------------------------------------------- + # ----------------------------------------------------------------- def start_enclave_manager(self): """ - Execute boot flow and run time flow + Execute run time flow either by polling or by listening on ZMQ socket """ + try: logger.info( "--------------- Starting Boot time flow ----------------") @@ -277,7 +299,7 @@ def start_enclave_manager(self): def _start_polling_kvstore(self): """ - This function is runs indefinitely polling the KV Storage + This function is run indefinitely polling the KV Storage for new work-order request and processing them. The poll is interleaved with sleeps hence avoiding busy waits. It terminates only when an exception occurs. @@ -315,14 +337,16 @@ def _bind_zmq_socket(self, zmq_port): socket - An instance of a Socket bound to the configured port. """ + #zmq_context = zmq.asyncio.Context() context = zmq.Context() socket = context.socket(zmq.REP) + #socket = zmq.asyncio.Socket(context=zmq_context, socket_type=-1) socket.bind("tcp://0.0.0.0:"+zmq_port) return socket # ------------------------------------------------------------------------- - def _start_zmq_listener(self): + async def _start_zmq_listener(self): """ This function binds to the port configured for zmq and then indefinitely processes work order requests received @@ -347,7 +371,7 @@ def _start_zmq_listener(self): wo_id = socket.recv() wo_id = wo_id.decode() logger.info("Received request at enclave manager: %s" % wo_id) - result = self._process_work_order_sync(wo_id) + result = await self._process_work_order_sync(wo_id) if result is None: socket.send_string("Error while processing work order: " + str(wo_id)) diff --git a/enclave_manager/avalon_enclave_manager/worker_key_refresh.py b/enclave_manager/avalon_enclave_manager/worker_key_refresh.py new file mode 100644 index 000000000..b4c0594a2 --- /dev/null +++ b/enclave_manager/avalon_enclave_manager/worker_key_refresh.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 + +# Copyright 2020 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging +import asyncio +import importlib + +from database import connector +import utility.file_utils as file_utils +from avalon_enclave_manager.base_enclave_manager import EnclaveManager +from avalon_enclave_manager.worker_kv_delegate import WorkerKVDelegate + +logger = logging.getLogger(__name__) + +class WorkerKeyRefresh: + """ + Class for handling worker encryption key refresh + """ + def __init__(self, enclave_info, config, enclave_type): + super().__init__() + self._enclave_info = enclave_info + if enclave_type == "singleton": + self._enclave = importlib.import_module( + "avalon_enclave_manager.singleton.singleton_enclave") + self._enclave_type = "singleton" + elif enclave_type == "kme": + self._enclave = importlib.import_module( + "avalon_enclave_manager.kme.kme_enclave") + self._enclave_type = "kme" + self._config = config + self._worker_id = enclave_info._worker_id + + try: + self._kv_helper = connector.open(config['KvStorage']['remote_url']) + self._worker_kv_delegate = WorkerKVDelegate(self._kv_helper) + except Exception as err: + logger.error("Failed to open KV storage interface; " + + "exiting Intel SGX Enclave manager: {}".format(err)) + sys.exit(-1) + + def __refresh_worker_encryption_key(self): + """ + Refresh worker encryption key pair and retrieve updated + worker details from enclave + """ + # start enclave key refresh + if self._enclave_type == "singleton": + signup_cpp_obj = self._enclave.SignupInfoSingleton() + elif self._enclave_type == "kme": + signup_cpp_obj = self._enclave.SignupInfoKME() + updated_signup_data = signup_cpp_obj.RefreshWorkerEncryptionKey() + + if updated_signup_data is None: + return None + signup_info = { + 'encryption_key': + updated_signup_data['encryption_key'], + 'encryption_key_signature': + updated_signup_data['encryption_key_signature'], + 'sealed_enclave_data': + updated_signup_data['sealed_enclave_data'] + } + + if signup_info['sealed_enclave_data'] is None: + logger.info("Sealed data is None, so nothing to persist.") + else: + file_utils.write_to_file( + signup_info['sealed_enclave_data'], + self._enclave_info._get_sealed_data_file_name( + self._config["EnclaveModule"]["sealed_data_path"], + self._worker_id)) + return signup_info + +# ----------------------------------------------------------------- + + def _initiate_key_refresh(self): + + """ + Initiate worker encryption key refresh and update worker details + and updates worker details to kv storage + """ + + try: + enclave_signup_data = \ + self.__refresh_worker_encryption_key() + # Update worker encryption key, encryption key signature and + # sealed data after key refresh + logger.info("_initiate_key_refresh") + self._enclave_info.encryption_key = enclave_signup_data['encryption_key'] + self._enclave_info.encryption_key_signature = \ + enclave_signup_data['encryption_key_signature'] + self._enclave_info.sealed_enclave_data = enclave_signup_data['sealed_enclave_data'] + + # Add a new worker + worker_info = EnclaveManager.create_json_worker( + self._enclave_info, self._config) + logger.info( + "Persiting updated worker details after key refresh - %s", + worker_info) + # Hex string read from config which is 64 characters long + self._worker_kv_delegate.add_new_worker( + self._enclave_info._worker_id, worker_info) + return self + except Exception as e: + logger.error("failed to get signup data after key refresh: %s", + str(e)) + raise e + diff --git a/enclave_manager/avalon_enclave_manager/wpe/wpe_enclave_manager.py b/enclave_manager/avalon_enclave_manager/wpe/wpe_enclave_manager.py index ff238ba6d..81e397073 100644 --- a/enclave_manager/avalon_enclave_manager/wpe/wpe_enclave_manager.py +++ b/enclave_manager/avalon_enclave_manager/wpe/wpe_enclave_manager.py @@ -147,6 +147,7 @@ def _execute_wo_in_trusted_enclave(self, input_json_str): logger.info("unknown enclave type response = %s", wo_response) return wo_response + # ------------------------------------------------------------------------- diff --git a/examples/apps/generic_client/generic_client.py b/examples/apps/generic_client/generic_client.py index 12eca7d4c..99b95be5c 100755 --- a/examples/apps/generic_client/generic_client.py +++ b/examples/apps/generic_client/generic_client.py @@ -24,6 +24,7 @@ from proxy_model_generic_client import ProxyModelGenericClient import utility.hex_utils as hex_utils import avalon_crypto_utils.crypto_utility as crypto_utility +from error_code.error_status import WorkOrderStatus logging.basicConfig( format="%(asctime)s - %(levelname)s - %(message)s", level=logging.INFO) @@ -237,6 +238,111 @@ def uri(self): def mode(self): return self._mode + def _start_client(self, generic_client_obj, worker_obj, worker_id): + # Do worker verification + generic_client_obj.do_worker_verification(worker_obj) + + logging.info("**********Worker details Updated with Worker ID" + + "*********\n%s\n", worker_id) + + # Create session key and iv to sign work order request + session_key = crypto_utility.generate_key() + session_iv = crypto_utility.generate_iv() + + # Create work order + if self.in_data_plain_text(): + # As per TC spec, if encryptedDataEncryptionKey is "-" then + # input data is not encrypted + encrypted_data_encryption_key = "-" + else: + # As per TC spec, if encryptedDataEncryptionKey is not + # provided then set it to None which means + # use default session key to encrypt input data + encrypted_data_encryption_key = None + + code, wo_params = generic_client_obj.create_work_order_params( + worker_id, self.workload_id(), + self.in_data(), + worker_obj.encryption_key, + session_key, session_iv, + encrypted_data_encryption_key) + if not code: + logging.error("Work order request creation failed") + sys.exit(-1) + + client_private_key = crypto_utility.generate_signing_keys() + if self.requester_signature(): + # Add requester signature and requester verifying_key + if wo_params.add_requester_signature(client_private_key) is False: + logging.info("Work order request signing failed") + sys.exit(-1) + + submit_status, wo_submit_res = generic_client_obj.submit_work_order( + wo_params) + + if submit_status: + # Create receipt + if self.show_receipt(): + generic_client_obj.create_work_order_receipt( + wo_params, + client_private_key) + work_order_id = wo_params.get_work_order_id() + # Retrieve work order result + status, wo_res = generic_client_obj.get_work_order_result( + work_order_id + ) + + # Check if result field is present in work order response + if status and 'result' in wo_res: + # Verify work order response signature + if generic_client_obj.verify_wo_response_signature( + wo_res['result'], + worker_obj.verification_key, + wo_params.get_requester_nonce() + ) is False: + logging.error("Work order response signature" + " verification Failed") + sys.exit(-1) + # Decrypt work order response + if self.show_decrypted_output(): + decrypted_res = generic_client_obj.decrypt_wo_response( + wo_res['result']) + logging.info("\nDecrypted response:\n {}".format( + decrypted_res)) + elif 'error' in wo_res and wo_res['error']['code'] == \ + WorkOrderStatus.WORKER_ENCRYPT_KEY_REFRESHED: + logging.info("Worker Key refreshed. " + "Retrieving latest Worker details and resubmit work order") + # Retrieve updated worker details + worker_obj = generic_client_obj.get_worker_details( + worker_id) + if worker_obj is None: + logging.error("Unable to retrieve worker details\n") + sys.exit(-1) + self._start_client(generic_client_obj, worker_obj, worker_id) + else: + # Check for error response + logging.error("\n Work order get result failed\n") + sys.exit(-1) + + if self.show_receipt(): + # Retrieve receipt + retrieve_wo_receipt = \ + generic_client_obj.retrieve_work_order_receipt( + work_order_id) + # Verify receipt signature + if retrieve_wo_receipt: + if "result" in retrieve_wo_receipt: + if generic_client_obj.verify_receipt_signature( + retrieve_wo_receipt) is False: + logging.error("Receipt signature verification Failed") + sys.exit(-1) + else: + logging.info("Work Order receipt retrieve failed") + sys.exit(-1) + else: + logging.error("Work order submit failed {}".format(wo_submit_res)) + sys.exit(-1) def Main(args=None): parser = GenericClient(args) @@ -272,6 +378,7 @@ def Main(args=None): if worker_obj is None: logging.error("Unable to retrieve worker details\n") sys.exit(-1) +<<<<<<< HEAD # Create session key and iv to sign work order request session_key = crypto_utility.generate_key() @@ -368,6 +475,7 @@ def Main(args=None): logging.error("Work order submit failed {}".format(wo_submit_res)) sys.exit(-1) + parser._start_client(generic_client_obj, worker_obj, worker_id) # ----------------------------------------------------------------------------- Main() diff --git a/listener/avalon_listener/tcs_work_order_handler.py b/listener/avalon_listener/tcs_work_order_handler.py index e7ecbaa38..d643fa7d8 100755 --- a/listener/avalon_listener/tcs_work_order_handler.py +++ b/listener/avalon_listener/tcs_work_order_handler.py @@ -187,6 +187,8 @@ def WorkOrderGetResult(self, **params): if err_code == EnclaveError.ENCLAVE_ERR_VALUE: err_code = \ WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE + elif err_code == EnclaveError.ENCLAVE_ERR_ENCRYPT_KEY_REFRESH: + err_code = WorkOrderStatus.WORKER_ENCRYPT_KEY_REFRESHED elif err_code == EnclaveError.ENCLAVE_ERR_UNKNOWN: err_code = WorkOrderStatus.UNKNOWN_ERROR elif err_code == EnclaveError.ENCLAVE_ERR_INVALID_WORKLOAD: diff --git a/tc/sgx/trusted_worker_manager/enclave/enclave_data.cpp b/tc/sgx/trusted_worker_manager/enclave/enclave_data.cpp index f6a012e4f..49533b91a 100644 --- a/tc/sgx/trusted_worker_manager/enclave/enclave_data.cpp +++ b/tc/sgx/trusted_worker_manager/enclave/enclave_data.cpp @@ -280,3 +280,18 @@ void EnclaveData::SerializePublicData(void) { serialized_public_data_.assign(&serialized_buffer[0]); } + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +void EnclaveData::PerformEncryptionKeyRefresh() { + // Perform key refresh and update EnclaveData object with + // refreshed key pair + generate_new_encryption_key_pair(); + + // Generate encryption key signature for the refreshed key + generate_encryption_key_signature(); + + // Serialize private and public data after enclave key refresh + SerializePrivateData(); + SerializePublicData(); + Log(TCF_LOG_INFO, "generated new key enc key pair"); +} // EnclaveData::PerformEncryptionKeyRefresh diff --git a/tc/sgx/trusted_worker_manager/enclave/enclave_data.h b/tc/sgx/trusted_worker_manager/enclave/enclave_data.h index d8f7c0ef6..227f8bc6f 100644 --- a/tc/sgx/trusted_worker_manager/enclave/enclave_data.h +++ b/tc/sgx/trusted_worker_manager/enclave/enclave_data.h @@ -146,6 +146,13 @@ class EnclaveData { ByteArrayToHexEncodedString(encr_key_sig_bytes); } + void generate_new_encryption_key_pair(void) { + private_encryption_key_.Generate(); + public_encryption_key_ = private_encryption_key_.GetPublicKey(); + } + + void PerformEncryptionKeyRefresh(); + size_t get_sealed_data_size(void) const { size_t sdsize = sgx_calc_sealed_data_size(0, get_private_data_size()); return sdsize; diff --git a/tc/sgx/trusted_worker_manager/enclave/signup.edl b/tc/sgx/trusted_worker_manager/enclave/signup.edl index 4d4cd869a..c11d23c09 100644 --- a/tc/sgx/trusted_worker_manager/enclave/signup.edl +++ b/tc/sgx/trusted_worker_manager/enclave/signup.edl @@ -31,5 +31,12 @@ enclave { [out, size=inAllocatedPublicEnclaveDataSize] char* outPublicEnclaveData, size_t inAllocatedPublicEnclaveDataSize ); + + public tcf_err_t ecall_RefreshWorkerEncryptionKey( + [out, size=inAllocatedPublicEnclaveDataSize] char* outPublicEnclaveData, + size_t inAllocatedPublicEnclaveDataSize, + [out, size=inAllocatedSealedEnclaveDataSize] uint8_t* outSealedEnclaveData, + size_t inAllocatedSealedEnclaveDataSize + ); }; }; diff --git a/tc/sgx/trusted_worker_manager/enclave/signup_enclave_common.cpp b/tc/sgx/trusted_worker_manager/enclave/signup_enclave_common.cpp index eb7a7132c..1b8d1a037 100644 --- a/tc/sgx/trusted_worker_manager/enclave/signup_enclave_common.cpp +++ b/tc/sgx/trusted_worker_manager/enclave/signup_enclave_common.cpp @@ -19,9 +19,9 @@ #include "avalon_sgx_error.h" #include "zero.h" -#include "enclave_data.h" #include "enclave_utils.h" #include "signup_enclave_common.h" +#include "enclave_data.h" // Initializing singleton class object which gets initialized when @@ -128,3 +128,65 @@ tcf_err_t ecall_UnsealEnclaveData(char* outPublicEnclaveData, return result; } // ecall_UnsealEnclaveData + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +tcf_err_t ecall_RefreshWorkerEncryptionKey( + char* outPublicEnclaveData, + size_t inAllocatedPublicEnclaveDataSize, + uint8_t* outSealedEnclaveData, + size_t inAllocatedSealedEnclaveDataSize) { + + tcf_err_t result = TCF_SUCCESS; + + try { + + tcf::error::ThrowIfNull(outSealedEnclaveData, + "Sealed enclave data pointer is NULL"); + + Zero(outPublicEnclaveData, inAllocatedPublicEnclaveDataSize); + Zero(outSealedEnclaveData, inAllocatedSealedEnclaveDataSize); + + EnclaveData* enclave_data = EnclaveData::getInstance(); + enclave_data->PerformEncryptionKeyRefresh(); + tcf::error::ThrowIf( + inAllocatedPublicEnclaveDataSize < enclave_data->get_public_data_size(), + "Public enclave data buffer size is too small"); + + tcf::error::ThrowIf( + inAllocatedSealedEnclaveDataSize < enclave_data->get_sealed_data_size(), + "Sealed enclave data buffer size is too small"); + + /* + Seal up the signup data into the caller's buffer. + NOTE - the attributes mask 0xfffffffffffffff3 seems rather + arbitrary, but according to Intel SGX SDK documentation, this is + what sgx_seal_data uses, so it is good enough for us. + */ + sgx_attributes_t attribute_mask = {0xfffffffffffffff3, 0}; + sgx_status_t ret = sgx_seal_data_ex(SGX_KEYPOLICY_MRENCLAVE, attribute_mask, + 0, // misc_mask + 0, // additional mac text length + nullptr, // additional mac text + enclave_data->get_private_data_size(), + reinterpret_cast(enclave_data->get_private_data().c_str()), + static_cast(enclave_data->get_sealed_data_size()), + reinterpret_cast(outSealedEnclaveData)); + tcf::error::ThrowSgxError(ret, "Failed to seal signup data"); + + // Give the caller a copy of the signing and encryption keys + strncpy_s(outPublicEnclaveData, inAllocatedPublicEnclaveDataSize, + enclave_data->get_public_data().c_str(), + enclave_data->get_public_data_size()); + } catch (tcf::error::Error& e) { + SAFE_LOG(TCF_LOG_ERROR, + "Error in enclave(ecall_RefreshWorkerEncryptionKey): %04X -- %s", + e.error_code(), e.what()); + ocall_SetErrorMessage(e.what()); + result = e.error_code(); + } catch (...) { + SAFE_LOG(TCF_LOG_ERROR, + "Unknown error in enclave(ecall_RefreshWorkerEncryptionKey)"); + result = TCF_ERR_UNKNOWN; + } + return result; +} // ecall_RefreshWorkerEncryptionKey diff --git a/tc/sgx/trusted_worker_manager/enclave/signup_enclave_common.h b/tc/sgx/trusted_worker_manager/enclave/signup_enclave_common.h index 149891f80..f030df78b 100644 --- a/tc/sgx/trusted_worker_manager/enclave/signup_enclave_common.h +++ b/tc/sgx/trusted_worker_manager/enclave/signup_enclave_common.h @@ -15,6 +15,7 @@ #include #include + #include "tcf_error.h" tcf_err_t CreateEnclaveData(uint8_t* persistedSealedEnclaveData=nullptr); diff --git a/tc/sgx/trusted_worker_manager/enclave/singleton/signup_enclave_singleton.cpp b/tc/sgx/trusted_worker_manager/enclave/singleton/signup_enclave_singleton.cpp index 713bbea44..6c93c1a97 100644 --- a/tc/sgx/trusted_worker_manager/enclave/singleton/signup_enclave_singleton.cpp +++ b/tc/sgx/trusted_worker_manager/enclave/singleton/signup_enclave_singleton.cpp @@ -44,6 +44,7 @@ #include "enclave_utils.h" #include "verify-report.h" #include "signup_enclave_util.h" +#include "signup_enclave_common.h" // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX diff --git a/tc/sgx/trusted_worker_manager/enclave/work_order_processor.cpp b/tc/sgx/trusted_worker_manager/enclave/work_order_processor.cpp index 9cdcc7a4a..96caf07cb 100644 --- a/tc/sgx/trusted_worker_manager/enclave/work_order_processor.cpp +++ b/tc/sgx/trusted_worker_manager/enclave/work_order_processor.cpp @@ -171,8 +171,34 @@ namespace tcf { // Decrypt Encryption key ByteArray encrypted_session_key_bytes = \ HexStringToBinary(encrypted_session_key); - session_key = enclave_data->decrypt_message( - encrypted_session_key_bytes); + + try { + // Decrypt Encryption key + session_key = enclave_data->decrypt_message( + encrypted_session_key_bytes); + } catch (tcf::error::KeyRefreshError& e) { + Log(TCF_LOG_ERROR, "error::DecryptMessage - %d - %s", \ + e.error_code(), e.what()); + tcf::error::ThrowIf( + true == true, "Failed to decrypt encrypted session key. " \ + "Possibly worker key refreshed, " \ + "fetch latest Worker Encryption Key"); + } catch (tcf::error::Error& e) { + Log(TCF_LOG_ERROR, "error::DecryptMessage - %d - %s", \ + e.error_code(), e.what()); + tcf::error::ThrowIf( + true == true, "Failed to decrypt encrypted session key. " \ + "Possibly worker key refreshed, " \ + "fetch latest Worker Encryption Key"); + } catch (...) { + Log(TCF_LOG_ERROR, \ + "error::DecryptMessage - unknown internal error"); + tcf::error::ThrowIf( + true == true, "Failed to decrypt encrypted session key. " \ + "Possibly worker key refreshed, " \ + "fetch latest Worker Encryption Key"); + } + ByteArray session_key_iv_bytes = HexStringToBinary(session_key_iv); JSON_Object* request_object = json_value_get_object(wo_req_json_val); @@ -349,12 +375,13 @@ namespace tcf { } // Calculate final hash std::string final_hash_string = ByteArrayToString(hash_1); - if(!hash_in_data_str.empty()) { + + //if(!hash_in_data_str.empty()) { final_hash_string += ByteArrayToString(hash_in_data); - } - if(!hash_out_data_str.empty()) { + //} + //if(!hash_out_data_str.empty()) { final_hash_string += ByteArrayToString(hash_out_data); - } + //} ByteArray final_hash = tcf::crypto::ComputeMessageHash( StrToByteArray(final_hash_string)); return final_hash; @@ -546,6 +573,8 @@ namespace tcf { return SerializeJson(response_json); } catch (tcf::error::ValueError& e) { return CreateErrorResponse(e.error_code(), e.what()); + } catch (tcf::error::KeyRefreshError& e) { + return CreateErrorResponse(e.error_code(), e.what()); } catch (tcf::error::Error& e) { return CreateErrorResponse(e.error_code(), e.what()); } catch (...) { diff --git a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/kme/signup_kme.cpp b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/kme/signup_kme.cpp index 1409f75f6..9c2645f45 100644 --- a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/kme/signup_kme.cpp +++ b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/kme/signup_kme.cpp @@ -116,6 +116,64 @@ tcf_err_t SignupDataKME::CreateEnclaveData( return result; } // SignupDataKME::CreateEnclaveData +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +tcf_err_t SignupDataKME::RefreshWorkerEncryptionKey( + StringArray& outPublicEnclaveData, + Base64EncodedString& outSealedEnclaveData) { + + tcf_err_t result = TCF_SUCCESS; + + try { + tcf_err_t presult = TCF_SUCCESS; + sgx_status_t sresult; + + outPublicEnclaveData.resize(CalculatePublicEnclaveDataSize()); + + ByteArray sealed_enclave_data_buffer(CalculateSealedEnclaveDataSize()); + + // Get the enclave id for passing into the ecall + sgx_enclave_id_t enclaveid = g_Enclave[0].GetEnclaveId(); + + size_t computed_public_enclave_data_size = 0; + size_t computed_sealed_enclave_data_size = 0; + + sresult = g_Enclave[0].CallSgx( + [enclaveid, + &presult, + &outPublicEnclaveData, + &sealed_enclave_data_buffer, + &computed_sealed_enclave_data_size ] () { + sgx_status_t ret = ecall_RefreshWorkerEncryptionKey( + enclaveid, + &presult, + outPublicEnclaveData.data(), + outPublicEnclaveData.size(), + sealed_enclave_data_buffer.data(), + sealed_enclave_data_buffer.size()); + return tcf::error::ConvertErrorStatus(ret, presult); + }); + + tcf::error::ThrowSgxError(sresult, + "SGX enclave call failed (ecall_RefreshWorkerEncryptionKey), " + "failed to refresh enclave encryption key"); + g_Enclave[0].ThrowTCFError(presult); + + outSealedEnclaveData = \ + ByteArrayToBase64EncodedString(sealed_enclave_data_buffer); + } catch (tcf::error::Error& e) { + tcf::enclave_api::base::SetLastError(e.what()); + result = e.error_code(); + } catch (std::exception& e) { + tcf::enclave_api::base::SetLastError(e.what()); + result = TCF_ERR_UNKNOWN; + } catch (...) { + tcf::enclave_api::base::SetLastError( + "Unexpected exception in (RefreshEnclaveKey)"); + result = TCF_ERR_UNKNOWN; + } + return result; +} // SignupDataKME::RefreshEnclaveKey + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX tcf_err_t SignupDataKME::UnsealEnclaveData( StringArray& outPublicEnclaveData) { diff --git a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/kme/signup_kme.h b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/kme/signup_kme.h index 8b92ebef1..441f328e0 100644 --- a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/kme/signup_kme.h +++ b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/kme/signup_kme.h @@ -30,6 +30,10 @@ class SignupDataKME : public SignupData { Base64EncodedString& outSealedEnclaveData, Base64EncodedString& outEnclaveQuote); + tcf_err_t RefreshWorkerEncryptionKey( + StringArray& outPublicEnclaveData, + Base64EncodedString& outSealedEnclaveData); + tcf_err_t VerifyEnclaveInfo( const std::string& enclaveInfo, const std::string& mr_enclave, diff --git a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/singleton/signup_singleton.cpp b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/singleton/signup_singleton.cpp index cb59a1b12..6c4fd46be 100644 --- a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/singleton/signup_singleton.cpp +++ b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/singleton/signup_singleton.cpp @@ -108,6 +108,66 @@ tcf_err_t SignupDataSingleton::CreateEnclaveData( return result; } // SignupDataSingleton::CreateEnclaveData +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +tcf_err_t SignupDataSingleton::RefreshWorkerEncryptionKey( + StringArray& outPublicEnclaveData, + Base64EncodedString& outSealedEnclaveData) { + + tcf_err_t result = TCF_SUCCESS; + + try { + tcf_err_t presult = TCF_SUCCESS; + sgx_status_t sresult; + + // +1 for null character which is not included in std::string length() + outPublicEnclaveData.resize( + SignupData::CalculatePublicEnclaveDataSize() + 1); + ByteArray sealed_enclave_data_buffer( + SignupData::CalculateSealedEnclaveDataSize()); + + // Get the enclave id for passing into the ecall + sgx_enclave_id_t enclaveid = g_Enclave[0].GetEnclaveId(); + + size_t computed_public_enclave_data_size = 0; + size_t computed_sealed_enclave_data_size = 0; + + sresult = g_Enclave[0].CallSgx( + [enclaveid, + &presult, + &outPublicEnclaveData, + &sealed_enclave_data_buffer, + &computed_sealed_enclave_data_size ] () { + sgx_status_t ret = ecall_RefreshWorkerEncryptionKey( + enclaveid, + &presult, + outPublicEnclaveData.data(), + outPublicEnclaveData.size(), + sealed_enclave_data_buffer.data(), + sealed_enclave_data_buffer.size()); + return tcf::error::ConvertErrorStatus(ret, presult); + }); + + tcf::error::ThrowSgxError(sresult, + "SGX enclave call failed (ecall_RefreshWorkerEncryptionKey), " + "failed to refresh enclave encryption key"); + g_Enclave[0].ThrowTCFError(presult); + + outSealedEnclaveData = \ + ByteArrayToBase64EncodedString(sealed_enclave_data_buffer); + } catch (tcf::error::Error& e) { + tcf::enclave_api::base::SetLastError(e.what()); + result = e.error_code(); + } catch (std::exception& e) { + tcf::enclave_api::base::SetLastError(e.what()); + result = TCF_ERR_UNKNOWN; + } catch (...) { + tcf::enclave_api::base::SetLastError( + "Unexpected exception in (RefreshEnclaveKey)"); + result = TCF_ERR_UNKNOWN; + } + return result; +} // SignupDataSingleton::RefreshEnclaveKey + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX tcf_err_t SignupDataSingleton::UnsealEnclaveData( StringArray& outPublicEnclaveData) { diff --git a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/singleton/signup_singleton.h b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/singleton/signup_singleton.h index e07b3d2de..ea6f8ccff 100644 --- a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/singleton/signup_singleton.h +++ b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge/singleton/signup_singleton.h @@ -34,4 +34,8 @@ class SignupDataSingleton : public SignupData { const std::string& mr_enclave); tcf_err_t UnsealEnclaveData(StringArray& outPublicEnclaveData); + + tcf_err_t RefreshWorkerEncryptionKey( + StringArray& outPublicEnclaveData, + Base64EncodedString& outSealedEnclaveData); }; // SignupDataSingleton diff --git a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/kme/signup_info_kme.cpp b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/kme/signup_info_kme.cpp index 54feffc51..13dc7f26c 100644 --- a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/kme/signup_info_kme.cpp +++ b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/kme/signup_info_kme.cpp @@ -103,6 +103,39 @@ std::map SignupInfoKME::UnsealEnclaveData() { return result; } // SignupInfoKME::UnsealEnclaveData +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +std::map SignupInfoKME::RefreshWorkerEncryptionKey() { + tcf_err_t presult; + /* Create some buffers for receiving the output parameters */ + StringArray public_enclave_data(0); + Base64EncodedString out_sealed_enclave_data; + + SignupDataKME signup_data; + presult = signup_data.RefreshWorkerEncryptionKey( + public_enclave_data, + out_sealed_enclave_data); + ThrowTCFError(presult); + + /* Parse the json and save verifying key, encryption key and + encryption key signature */ + std::string verifying_key; + std::string encryption_key; + std::string encryption_key_signature; + presult = DeserializePublicEnclaveData( + public_enclave_data.str(), + verifying_key, + encryption_key, + encryption_key_signature); + ThrowTCFError(presult); + + std::map result; + result["encryption_key"] = encryption_key; + result["encryption_key_signature"] = encryption_key_signature; + result["sealed_enclave_data"] = out_sealed_enclave_data; + + return result; +} // SignupInfoKME::RefreshWorkerEncryptionKey + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX size_t SignupInfoKME::VerifyEnclaveInfo( const std::string& enclave_info, diff --git a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/kme/signup_info_kme.h b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/kme/signup_info_kme.h index 434ab9753..ae0527400 100644 --- a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/kme/signup_info_kme.h +++ b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/kme/signup_info_kme.h @@ -28,6 +28,7 @@ class SignupInfoKME : public SignupInfo { std::map UnsealEnclaveData(); + std::map RefreshWorkerEncryptionKey(); size_t VerifyEnclaveInfo( const std::string& enclaveInfo, const std::string& mr_enclave, diff --git a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/singleton/signup_info_singleton.cpp b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/singleton/signup_info_singleton.cpp index d339bba01..8be8106ac 100644 --- a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/singleton/signup_info_singleton.cpp +++ b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/singleton/signup_info_singleton.cpp @@ -96,6 +96,39 @@ std::map SignupInfoSingleton::UnsealEnclaveData() { return result; } // SignupInfoSingleton::UnsealEnclaveData +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +std::map SignupInfoSingleton::RefreshWorkerEncryptionKey() { + tcf_err_t presult; + /* Create some buffers for receiving the output parameters */ + StringArray public_enclave_data(0); + Base64EncodedString out_sealed_enclave_data; + + SignupDataSingleton signup_data; + presult = signup_data.RefreshWorkerEncryptionKey( + public_enclave_data, + out_sealed_enclave_data); + ThrowTCFError(presult); + + /* Parse the json and save verifying key, encryption key and + encryption key signature */ + std::string verifying_key; + std::string encryption_key; + std::string encryption_key_signature; + presult = DeserializePublicEnclaveData( + public_enclave_data.str(), + verifying_key, + encryption_key, + encryption_key_signature); + ThrowTCFError(presult); + + std::map result; + result["encryption_key"] = encryption_key; + result["encryption_key_signature"] = encryption_key_signature; + result["sealed_enclave_data"] = out_sealed_enclave_data; + + return result; +} // SignupInfoSingleton::RefreshWorkerEncryptionKey + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX size_t SignupInfoSingleton::VerifyEnclaveInfo(const std::string& enclave_info, const std::string& mr_enclave) { diff --git a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/singleton/signup_info_singleton.h b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/singleton/signup_info_singleton.h index 276bd88d4..72b3744a8 100644 --- a/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/singleton/signup_info_singleton.h +++ b/tc/sgx/trusted_worker_manager/enclave_untrusted/enclave_bridge_wrapper/singleton/signup_info_singleton.h @@ -26,6 +26,8 @@ class SignupInfoSingleton : public SignupInfo { std::map UnsealEnclaveData(); + std::map RefreshWorkerEncryptionKey(); + size_t VerifyEnclaveInfo( const std::string& enclaveInfo, const std::string& mr_enclave);