From ed8fd10755073a5aedce2c730d3f80d20fbaa9ef Mon Sep 17 00:00:00 2001 From: danhe1 Date: Tue, 27 Oct 2020 18:37:46 +0800 Subject: [PATCH 1/3] add:examples/apps/data_owner/ Signed-off-by: danhe1 --- .../apps/data_owner/workload/CMakeLists.txt | 51 + .../apps/data_owner/workload/cfl-poc-defs.cpp | 71 ++ .../apps/data_owner/workload/cfl-poc-defs.h | 566 +++++++++ .../apps/data_owner/workload/cfl-utils.cpp | 82 ++ examples/apps/data_owner/workload/cfl-utils.h | 73 ++ .../data_owner/workload/data-owner-logic.cpp | 458 +++++++ .../data_owner/workload/data-owner-logic.h | 123 ++ .../workload/data-owner-node-config.cpp | 439 +++++++ .../workload/data-owner-node-config.h | 69 ++ .../workload/data-owner-plug-in.cpp | 204 ++++ .../data_owner/workload/data-owner-plug-in.h | 31 + .../workload/node-config-plug-in.cpp | 88 ++ .../data_owner/workload/node-config-plug-in.h | 32 + .../apps/data_owner/workload/node-config.cpp | 112 ++ .../apps/data_owner/workload/node-config.h | 55 + .../workload/requester-node-config.cpp | 1057 +++++++++++++++++ .../workload/requester-node-config.h | 126 ++ .../workload/requester-node-logic.cpp | 900 ++++++++++++++ .../workload/requester-node-logic.h | 133 +++ .../workload/requester-node-plug-in.cpp | 296 +++++ .../workload/requester-node-plug-in.h | 32 + .../data_owner/workload/verify-workers.cpp | 272 +++++ .../apps/data_owner/workload/verify-workers.h | 18 + 23 files changed, 5288 insertions(+) create mode 100644 examples/apps/data_owner/workload/CMakeLists.txt create mode 100644 examples/apps/data_owner/workload/cfl-poc-defs.cpp create mode 100644 examples/apps/data_owner/workload/cfl-poc-defs.h create mode 100644 examples/apps/data_owner/workload/cfl-utils.cpp create mode 100644 examples/apps/data_owner/workload/cfl-utils.h create mode 100644 examples/apps/data_owner/workload/data-owner-logic.cpp create mode 100644 examples/apps/data_owner/workload/data-owner-logic.h create mode 100644 examples/apps/data_owner/workload/data-owner-node-config.cpp create mode 100644 examples/apps/data_owner/workload/data-owner-node-config.h create mode 100644 examples/apps/data_owner/workload/data-owner-plug-in.cpp create mode 100644 examples/apps/data_owner/workload/data-owner-plug-in.h create mode 100644 examples/apps/data_owner/workload/node-config-plug-in.cpp create mode 100644 examples/apps/data_owner/workload/node-config-plug-in.h create mode 100644 examples/apps/data_owner/workload/node-config.cpp create mode 100644 examples/apps/data_owner/workload/node-config.h create mode 100644 examples/apps/data_owner/workload/requester-node-config.cpp create mode 100644 examples/apps/data_owner/workload/requester-node-config.h create mode 100644 examples/apps/data_owner/workload/requester-node-logic.cpp create mode 100644 examples/apps/data_owner/workload/requester-node-logic.h create mode 100644 examples/apps/data_owner/workload/requester-node-plug-in.cpp create mode 100644 examples/apps/data_owner/workload/requester-node-plug-in.h create mode 100644 examples/apps/data_owner/workload/verify-workers.cpp create mode 100644 examples/apps/data_owner/workload/verify-workers.h diff --git a/examples/apps/data_owner/workload/CMakeLists.txt b/examples/apps/data_owner/workload/CMakeLists.txt new file mode 100644 index 000000000..dcc0af09b --- /dev/null +++ b/examples/apps/data_owner/workload/CMakeLists.txt @@ -0,0 +1,51 @@ +# Copyright 2019 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. + +CMAKE_MINIMUM_REQUIRED(VERSION 3.2 FATAL_ERROR) + +FILE(GLOB PROJECT_HEADERS "*.h") +FILE(GLOB PROJECT_SOURCES "*.cpp") + +SET(GENERIC_CXX_FLAGS ${DEBUG_FLAGS} "-Wall" "-fPIC" "-Wno-write-strings" "-std=c++11") + +SET(SGX_SSL "$ENV{SGX_SSL}") +if("${SGX_SSL} " STREQUAL " ") + SET(SGX_SSL "/opt/intel/sgxssl") + message(STATUS "Setting default SGX_SSL=${SGX_SSL}") +endif() + +SET(DATA_OWNER_STATIC_NAME data_owner) +PROJECT(${DATA_OWNER_STATIC_NAME} C CXX) + +ADD_LIBRARY(${DATA_OWNER_STATIC_NAME} STATIC ${PROJECT_HEADERS} ${PROJECT_SOURCES}) + +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PRIVATE ${TCF_TOP_DIR}/tc/sgx/trusted_worker_manager/enclave) +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PRIVATE ${TCF_TOP_DIR}/tc/sgx/trusted_worker_manager/common) +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PRIVATE ${TCF_TOP_DIR}/common/cpp/crypto) +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PRIVATE ${TCF_TOP_DIR}/common/cpp/verify_ias_report) +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PRIVATE ${TCF_TOP_DIR}/common/cpp/packages/parson) +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PRIVATE ${GENERIC_PRIVATE_INCLUDE_DIRS}) +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PUBLIC ${GENERIC_PUBLIC_INCLUDE_DIRS}) +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PUBLIC "${SGX_SDK}/include/tlibc") +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PUBLIC "${SGX_SDK}/include/libcxx") +TARGET_INCLUDE_DIRECTORIES(${DATA_OWNER_STATIC_NAME} PUBLIC "${SGX_SSL}/include") + +TARGET_COMPILE_OPTIONS(${DATA_OWNER_STATIC_NAME} PRIVATE "${GENERIC_CXX_FLAGS}") +TARGET_COMPILE_OPTIONS(${DATA_OWNER_STATIC_NAME} PRIVATE "-nostdinc") +TARGET_COMPILE_OPTIONS(${DATA_OWNER_STATIC_NAME} PRIVATE "-nostdinc++") +TARGET_COMPILE_OPTIONS(${DATA_OWNER_STATIC_NAME} PRIVATE "-fno-builtin-printf") + +TARGET_COMPILE_DEFINITIONS(${DATA_OWNER_STATIC_NAME} PRIVATE "-DUSE_DL=1") + +################################################################################ diff --git a/examples/apps/data_owner/workload/cfl-poc-defs.cpp b/examples/apps/data_owner/workload/cfl-poc-defs.cpp new file mode 100644 index 000000000..d94d02aa1 --- /dev/null +++ b/examples/apps/data_owner/workload/cfl-poc-defs.cpp @@ -0,0 +1,71 @@ +// +// CFL_POC: cfl-poc-defs.h +// Common definitions for data owner and requster enclaves +// + +#include "cfl-poc-defs.h" + + +// this common functions reuasable by both Node and Requester enclaves + +namespace cfl { + +void AddOutput(int index, + std::vector& out_work_order_data, + const ByteArray& data) +{ + int out_wo_data_size = out_work_order_data.size(); + // If the out_work_order_data has entry to hold the data + if (index < out_wo_data_size) { + tcf::WorkOrderData& out_wo_data = out_work_order_data.at(index); + out_wo_data.decrypted_data = data; + } + else { + // Create a new entry + out_work_order_data.emplace_back(index, data); + } +} + +void AddOutput(int index, + std::vector& out_work_order_data, + const std::string& str) +{ + ByteArray ba(str.begin(), str.end()); + AddOutput(index, out_work_order_data, ba); +} + +void AddOutput(int index, + std::vector& out_work_order_data, + int num) +{ + std::string num_str = std::to_string(num); + AddOutput(index, out_work_order_data, num_str); +} + +void AddOutput(int index, + std::vector& out_work_order_data, + const char* ptr) +{ + std::string str = ptr; + AddOutput(index, out_work_order_data, str); +} + + +void MergeOutput(ByteArray& output, + const std::vector& out_work_order_data) +{ + output.resize(0); + + for (size_t i = 0; i < out_work_order_data.size(); i++) + { + if (i > 0) + { + output.emplace_back(' '); + } + + ByteArray decrypted_data = out_work_order_data.at(i).decrypted_data; + output.insert(output.end(), decrypted_data.begin(), decrypted_data.end()); + } +} + +} //namespace diff --git a/examples/apps/data_owner/workload/cfl-poc-defs.h b/examples/apps/data_owner/workload/cfl-poc-defs.h new file mode 100644 index 000000000..ff90503bb --- /dev/null +++ b/examples/apps/data_owner/workload/cfl-poc-defs.h @@ -0,0 +1,566 @@ +// +// CFL_POC: cfl-poc-defs.h +// Common definitions for data owner and requster enclaves +// + +#pragma once + +#include "work_order_data.h" +#include "crypto.h" +#include "cfl-utils.h" + +// TODO: Remove dummy placeholder for class ExWorkorderInfo when it is implemented +class ExWorkorderInfo { +public: + void SetVerificationKey(const ByteArray & key) + { + VerificationKey.assign(key.begin(), key.end()); + } + + void GetWorkorderSigningInfo(ByteArray& v_key) + { + v_key.assign(VerificationKey.begin(), VerificationKey.end()); + } + + void SetSignature(const ByteArray& sign) + { + Signature.assign(sign.begin(), sign.end()); + } + + void SetIndataHash(const std::vector in_work_order_data) + { + ByteArray concat_message; + for (auto& data: in_work_order_data) + { + ByteArray param = data.decrypted_data; + concat_message.insert(concat_message.end(), param.begin(), param.end()); + } + + Hash = tcf::crypto::ComputeMessageHash(concat_message); + } + + bool VerifyWorkorderSignature() + { + using tcf::crypto::sig::PublicKey; + std::string vk_block = cfl::VerificationKeyBlockFromByteArray(VerificationKey); + PublicKey public_key = PublicKey(vk_block); + return public_key.VerifySignature(Hash, Signature) == 0; + + } + +private: + ByteArray VerificationKey; + ByteArray Signature; + ByteArray Hash; +}; + + +#define CFL_POC_OP_CFG_NONCE "create-cfg-nonce" // used for both requester and DO nodes + +// Operations for RequesterList +#define CFL_POC_OP_SETUP_REQUESTER "setup-requester" +#define CFL_POC_OP_REMOVE_REQUESTER "remove-requester" +#define CFL_POC_OP_LOOKUP_REQUESTERS "lookup-requesters" + +//Operations for DataOwnerNondeConfig +#define CFL_POC_OP_CFG_SETUP_DO_WORKER "setup-do-worker" +#define CFL_POC_OP_CFG_REMOVE_DO_WORKER "remove-do-worker" + +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS "add-worker-measurement" +#define CFL_POC_OP_CFG_REMOVE_WORKER_MEAS "remove-worker-measurement" +#define CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS "lookup-worker-measurements" + +#define CFL_POC_OP_CFG_SEAL_ENC_KEY "seal-encryption-key" +#define CFL_POC_OP_CFG_UNSEAL_ENC_KEY "unseal-encryption-key" + +//Operations for DataOwnerLogic +#define CFL_POC_OP_NONCE "get-nonce" +#define CFL_POC_OP_PROCESS "process" + +//Operations for RequesterNodeConfig +#define CFL_POC_OP_ADD_DATASET "add-dataset" +#define CFL_POC_OP_REMOVE_DATASET "remove-dataset" +#define CFL_POC_OP_LOOKUP_DATASETS "lookup-datasets" +#define CFL_POC_OP_ADD_WORKER "add-worker" +#define CFL_POC_OP_REMOVE_WORKER "remove-worker" +#define CFL_POC_OP_UPDATE_WORKER "update-worker" +#define CFL_POC_OP_LOOKUP_WORKERS "lookup-workers" +#define CFL_POC_OP_ADD_USER "add-user" +#define CFL_POC_OP_REMOVE_USER "remove-user" +#define CFL_POC_OP_LOOKUP_USERS "lookup-users" +#define CFL_POC_OP_CLEAR_ALL_DATASETS "remove-all-datasets" + +//Operations for RequesterKifuc +#define CFL_POC_OP_CREATE_WORKFLOW "create-workflow" +#define CFL_POC_OP_REMOVE_WORKFLOW "remove-workflow" +#define CFL_POC_OP_JOIN_WORKFLOW "join-workflow" +#define CFL_POC_OP_QUIT_WORKFLOW "quit-workflow" +#define CFL_POC_OP_UPDATE_WORKFLOW "update-workflow" +#define CFL_POC_OP_LOOKUP_WORKFLOWS "lookup-workflows" +#define CFL_POC_OP_AVAILABLE_DATASETS "available-datasets" +#define CFL_POC_OP_GET_WORKFLOW_RESULT "get-workflow-result" +#define CFL_POC_OP_CREATE_DO_NONCE_RQST "create-do-nonce-request" +#define CFL_POC_OP_CREATE_DO_PROCESS_RQST "create-do-process-request" +#define CFL_POC_OP_PROCESS_DO_PROCESS_RESP "proces-do-nonce-response" + + +#define CFL_POC_E_OP_OK (0) +#define CFL_POC_E_OP_CODE (-1) +#define CFL_POC_E_PARAM_COUNT (-2) +#define CFL_POC_E_DATASET_NAME (-3) +#define CFL_POC_E_DATA_ITEM_INDEX (-4) +#define CFL_POC_E_DATASET_SETUP (-5) +#define CFL_POC_E_AUTH (-6) +#define CFL_POC_E_NONCE (-7) +#define CFL_POC_E_PARAM (-8) +#define CFL_POC_E_DATASET_ID (-9) +#define CFL_POC_E_WORKER_ID (-10) +#define CFL_POC_E_WORKFLOW_ID (-11) +#define CFL_POC_E_WORKFLOW_STATUS (-12) +#define CFL_POC_E_WORKER_BUSY (-13) +#define CFL_POC_E_OUT_OF_BOUND (-14) +#define CFL_POC_E_QUOTE (-15) + + +#define CFL_POC_WORKFLOW_WAITING (0) +#define CFL_POC_WORKFLOW_ONGOING (1) +#define CFL_POC_WORKFLOW_ABORTED (2) +#define CFL_POC_WORKFLOW_FINISHED (3) + + +// command nonce command +#define CFL_POC_CFG_NONCE_PARAM_MIN (0) +#define CFL_POC_CFG_NONCE_PARAM_MAX (0) + +#define CFL_POC_CFG_NONCE_RINDEX_STATUS (0) +#define CFL_POC_CFG_NONCE_RINDEX_NONCE (1) + + +#define CFL_POC_SETUP_DO_WORKER_PARAM_MIN (5) +#define CFL_POC_SETUP_DO_WORKER_PARAM_MAX (5) + +#define CFL_POC_SETUP_DO_WORKER_PINDEX_NONCE (0) +#define CFL_POC_SETUP_DO_WORKER_PINDEX_REQ_NONCE (1) +#define CFL_POC_SETUP_DO_WORKER_PINDEX_ID (2) +#define CFL_POC_SETUP_DO_WORKER_PINDEX_SIGNUP_DATA (3) +#define CFL_POC_SETUP_DO_WORKER_PINDEX_ADDRESS (4) + + +#define CFL_POC_SETUP_DO_WORKER_RINDEX_STATUS (0) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_OP (1) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_REQ_NONCE (2) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_ID (3) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_MRENCLAVE (4) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_MRSIGNER (5) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_ISV_PROD_ID (6) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_ISV_SVN (7) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_VKEY (8) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_EKEY (9) +#define CFL_POC_SETUP_DO_WORKER_RINDEX_ADDRESS (10) + +#define CFL_POC_SETUP_DO_WORKER_RINDEX_SIZE (11) + + +#define CFL_POC_REMOVE_DO_WORKER_PARAM_MIN (2) +#define CFL_POC_REMOVE_DO_WORKER_PARAM_MAX (2) + +#define CFL_POC_REMOVE_DO_WORKER_PINDEX_NONCE (0) +#define CFL_POC_REMOVE_DO_WORKER_PINDEX_VKEY (1) + +#define CFL_POC_REMOVE_DO_WORKER_RINDEX_STATUS (0) +#define CFL_POC_REMOVE_DO_WORKER_RINDEX_NONCE (1) + + + +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_PARAM_MIN (5) +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_PARAM_MAX (5) + +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_NONCE (0) +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_MRENCLAVE (1) +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_MRSIGNER (2) +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_ISV_PROD_ID (3) +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_ISV_SVN (4) + +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_RINDEX_STATUS (0) +#define CFL_POC_OP_CFG_ADD_WORKER_MEAS_RINDEX_NONCE (1) + + +#define CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_PARAM_MIN (2) +#define CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_PARAM_MAX (2) + +#define CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_PINDEX_NONCE (0) +#define CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_PINDEX_ID (1) + +#define CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_RINDEX_STATUS (0) +#define CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_RINDEX_NONCE (1) + + +#define CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_PARAM_MIN (1) +#define CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_PARAM_MAX (1) + +#define CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_PINDEX_NONCE (0) + +#define CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_STATUS (0) +#define CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_RESULT (1) +#define CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_NONCE (2) + +#define CFL_POC_OP_CFG_SEAL_ENC_KEY_PARAM_MIN (2) +#define CFL_POC_OP_CFG_SEAL_ENC_KEY_PARAM_MAX (2) + +#define CFL_POC_OP_CFG_SEAL_ENC_KEY_PINDEX_NONCE (0) +#define CFL_POC_OP_CFG_SEAL_ENC_KEY_PINDEX_KEY (1) + +#define CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_STATUS (0) +#define CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_SEALED_KEY (1) +#define CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_NONCE (2) + + +#define CFL_POC_OP_CFG_UNSEAL_ENC_KEY_PARAM_MIN (2) +#define CFL_POC_OP_CFG_UNSEAL_ENC_KEY_PARAM_MAX (2) + +#define CFL_POC_OP_CFG_UNSEAL_ENC_KEY_PINDEX_NONCE (0) +#define CFL_POC_OP_CFG_UNSEAL_ENC_KEY_PINDEX_KEY (1) + +#define CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_STATUS (0) +#define CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_KEY (1) +#define CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_NONCE (2) + + + + +// parameters counts and indexes for DO "setup" operation +#define CFL_POC_SETUP_PARAM_MIN (1) +#define CFL_POC_SETUP_PARAM_MAX (1) + +#define CFL_POC_SETUP_PINDEX_SETUP_DATA (0) + +#define CFL_POC_SETUP_RINDEX_STATUS (0) + +// parameters counts and indexes for DO "nonce" operation +#define CFL_POC_NONCE_PARAM_MIN (3) +#define CFL_POC_NONCE_PARAM_MAX (3) + +#define CFL_POC_NONCE_PINDEX_WORKFLOW_ID (0) +#define CFL_POC_NONCE_PINDEX_DATASET_ID (1) +#define CFL_POC_NONCE_PINDEX_ATT_DATA (2) + +#define CFL_POC_NONCE_RINDEX_STATUS (0) +#define CFL_POC_NONCE_RINDEX_WORKFLOW_ID (1) +#define CFL_POC_NONCE_RINDEX_DATASET_ID (2) +#define CFL_POC_NONCE_RINDEX_NONCE (3) + + +// parameters counts and indexes for DO "process" operation +#define CFL_POC_PROCESS_PARAM_MIN (6) +#define CFL_POC_PROCESS_PARAM_MAX (6) + +#define CFL_POC_PROCESS_PINDEX_FLOW_ID (0) +#define CFL_POC_PROCESS_PINDEX_NONCE (1) +#define CFL_POC_PROCESS_PINDEX_VKEY_SIG (2) +#define CFL_POC_PROCESS_PINDEX_DATASET_NAME (3) +#define CFL_POC_PROCESS_PINDEX_DATASET_KEY (4) +#define CFL_POC_PROCESS_PINDEX_QUERY_DATA (5) + +#define CFL_POC_PROCESS_RINDEX_STATUS (0) +#define CFL_POC_PROCESS_RINDEX_DATASET_NAME (1) +#define CFL_POC_PROCESS_RINDEX_DATA_ITEM (2) + +// parameters counts and indexes for DO "setup requester" operation +#define CFL_POC_SETUP_REQUESTER_PARAM_MIN (5) +#define CFL_POC_SETUP_REQUESTER_PARAM_MAX (5) + +#define CFL_POC_SETUP_REQUESTER_PINDEX_NONCE (0) +#define CFL_POC_SETUP_REQUESTER_PINDEX_ID (1) +#define CFL_POC_SETUP_REQUESTER_PINDEX_MRENCLAVE (2) +#define CFL_POC_SETUP_REQUESTER_PINDEX_MRSIGNER (3) +#define CFL_POC_SETUP_REQUESTER_PINDEX_VKEY (4) + +#define CFL_POC_SETUP_REQUESTER_RINDEX_STATUS (0) +#define CFL_POC_SETUP_REQUESTER_RINDEX_NONCE (1) + + +// parameters counts and indexes for DO "remove requester" operation +#define CFL_POC_REMOVE_REQUESTER_PARAM_MIN (2) +#define CFL_POC_REMOVE_REQUESTER_PARAM_MAX (2) + +#define CFL_POC_REMOVE_REQUESTER_PINDEX_NONCE (0) +#define CFL_POC_REMOVE_REQUESTER_PINDEX_VKEY (1) + +#define CFL_POC_REMOVE_REQUESTER_RINDEX_STATUS (0) +#define CFL_POC_REMOVE_REQUESTER_RINDEX_NONCE (1) + +// parameters counts and indexes for DO "lookup requesters" operation +#define CFL_POC_LOOKUP_REQUESTER_PARAM_MIN (1) +#define CFL_POC_LOOKUP_REQUESTER_PARAM_MAX (1) + +#define CFL_POC_LOOKUP_REQUESTER_PINDEX_NONCE (0) + +#define CFL_POC_LOOKUP_REQUESTER_RINDEX_STATUS (0) +#define CFL_POC_LOOKUP_REQUESTER_RINDEX_RESULT (1) +#define CFL_POC_LOOKUP_REQUESTER_RINDEX_NONCE (2) + + +// Requester node ops +#define CFL_POC_ADD_DATASET_PARAM_MIN (6) +#define CFL_POC_ADD_DATASET_PARAM_MAX (6) + +#define CFL_POC_ADD_DATASET_PINDEX_ID (0) +#define CFL_POC_ADD_DATASET_PINDEX_EK (1) +#define CFL_POC_ADD_DATASET_PINDEX_MRENCLAVE (2) +#define CFL_POC_ADD_DATASET_PINDEX_MRSIGNER (3) +#define CFL_POC_ADD_DATASET_PINDEX_WORKER_VKEY (4) +#define CFL_POC_ADD_DATASET_PINDEX_NONCE (5) + +#define CFL_POC_ADD_DATASET_RINDEX_STATUS (0) + + +#define CFL_POC_REMOVE_DATASET_PARAM_MIN (2) +#define CFL_POC_REMOVE_DATASET_PARAM_MAX (2) + +#define CFL_POC_REMOVE_DATASET_PINDEX_ID (0) +#define CFL_POC_REMOVE_DATASET_PINDEX_NONCE (1) + +#define CFL_POC_REMOVE_DATASET_RINDEX_STATUS (0) + + + +#define CFL_POC_LOOKUP_DATASET_PARAM_MIN (1) +#define CFL_POC_LOOKUP_DATASET_PARAM_MAX (1) + +#define CFL_POC_LOOKUP_DATASET_PINDEX_NONCE (0) + +#define CFL_POC_LOOKUP_DATASET_RINDEX_STATUS (0) +#define CFL_POC_LOOKUP_DATASET_RINDEX_RESULT (1) + + + +#define CFL_POC_ADD_AVALON_WORKER_PARAM_MIN (6) +#define CFL_POC_ADD_AVALON_WORKER_PARAM_MAX (6) +#define CFL_POC_ADD_GRAPHENE_WORKER_PARAM_MIN (8) +#define CFL_POC_ADD_GRAPHENE_WORKER_PARAM_MAX (8) + +#define CFL_POC_ADD_WORKER_PINDEX_NONCE (0) +#define CFL_POC_ADD_WORKER_PINDEX_TYPE (1) + +//For Avalon worker +#define CFL_POC_ADD_WORKER_PINDEX_ID (2) +#define CFL_POC_ADD_WORKER_PINDEX_MRENCLAVE (3) +#define CFL_POC_ADD_WORKER_PINDEX_MRSIGNER (4) +#define CFL_POC_ADD_WORKER_PINDEX_WORKER_VKEY (5) + +//For Graphene worker +#define CFL_POC_ADD_WORKER_PINDEX_INDATA (2) +#define CFL_POC_ADD_WORKER_PINDEX_PARENT_VKEY (3) +#define CFL_POC_ADD_WORKER_PINDEX_HASH1 (4) +#define CFL_POC_ADD_WORKER_PINDEX_SESSION_KEY (5) +#define CFL_POC_ADD_WORKER_PINDEX_SESSION_IV (6) +#define CFL_POC_ADD_WORKER_PINDEX_PARENT_SIGNATURE (7) + +#define CFL_POC_ADD_WORKER_RINDEX_STATUS (0) +#define CFL_POC_ADD_WORKER_RINDEX_NONCE (1) + + +#define CFL_POC_REMOVE_AVALON_WORKER_PARAM_MIN (3) +#define CFL_POC_REMOVE_AVALON_WORKER_PARAM_MAX (3) +#define CFL_POC_REMOVE_GRAPHENE_WORKER_PARAM_MIN (4) +#define CFL_POC_REMOVE_GRAPHENE_WORKER_PARAM_MAX (4) + +#define CFL_POC_REMOVE_WORKER_PINDEX_NONCE (0) +#define CFL_POC_REMOVE_WORKER_PINDEX_TYPE (1) +#define CFL_POC_REMOVE_WORKER_PINDEX_WORKER_VKEY (2) +// For Graphene worker only +#define CFL_POC_REMOVE_WORKER_PINDEX_PARENT_VKEY (3) + +#define CFL_POC_REMOVE_WORKER_RINDEX_STATUS (0) +#define CFL_POC_REMOVE_WORKER_RINDEX_NONCE (1) + + +#define CFL_POC_UPDATE_WORKER_PARAM_MIN (5) +#define CFL_POC_UPDATE_WORKER_PARAM_MAX (5) + +#define CFL_POC_UPDATE_WORKER_PINDEX_NONCE (0) +#define CFL_POC_UPDATE_WORKER_PINDEX_TYPE (1) +#define CFL_POC_UPDATE_WORKER_PINDEX_WORKER_VKEY (2) +#define CFL_POC_UPDATE_WORKER_PINDEX_EXTRA_SPECS (3) +// For graphene worker only +#define CFL_POC_UPDATE_WORKER_PINDEX_PARENT_VKEY (4) + +#define CFL_POC_UPDATE_WORKER_RINDEX_STATUS (0) +#define CFL_POC_UPDATE_WORKER_RINDEX_NONCE (1) + + + +//List workers +#define CFL_POC_LOOKUP_WORKER_PARAM_MIN (1) +#define CFL_POC_LOOKUP_WORKER_PARAM_MAX (1) + +#define CFL_POC_LOOKUP_WORKER_PINDEX_NONCE (0) + +#define CFL_POC_LOOKUP_WORKER_RINDEX_STATUS (0) +#define CFL_POC_LOOKUP_WORKER_RINDEX_RESULT (1) +#define CFL_POC_LOOKUP_WORKER_RINDEX_NONCE (2) + + +#define CFL_POC_ADD_USER_PARAM_MIN (2) +#define CFL_POC_ADD_USER_PARAM_MAX (2) + +#define CFL_POC_ADD_USER_PINDEX_VKEY (0) +#define CFL_POC_ADD_USER_PINDEX_NONCE (1) + +#define CFL_POC_ADD_USER_RINDEX_STATUS (0) + + +#define CFL_POC_REMOVE_USER_PARAM_MIN (2) +#define CFL_POC_REMOVE_USER_PARAM_MAX (2) + +#define CFL_POC_REMOVE_USER_PINDEX_VKEY (0) +#define CFL_POC_REMOVE_USER_PINDEX_NONCE (1) + +#define CFL_POC_REMOVE_USER_RINDEX_STATUS (0) + + +#define CFL_POC_LOOKUP_USER_PARAM_MIN (1) +#define CFL_POC_LOOKUP_USER_PARAM_MAX (1) + +#define CFL_POC_LOOKUP_USER_PINDEX_NONCE (0) + +#define CFL_POC_LOOKUP_USER_RINDEX_STATUS (0) +#define CFL_POC_LOOKUP_USER_RINDEX_RESULT (1) + + +#define CFL_POC_CREATE_WORKFLOW_PARAM_MIN (1) +#define CFL_POC_CREATE_WORKFLOW_PARAM_MAX (1) + +#define CFL_POC_CREATE_WORKFLOW_PINDEX_NONCE (0) + +#define CFL_POC_CREATE_WORKFLOW_RINDEX_STATUS (0) +#define CFL_POC_CREATE_WORKFLOW_RINDEX_ID (1) +#define CFL_POC_CREATE_WORKFLOW_RINDEX_NONCE (2) + +#define CFL_POC_JOIN_WORKFLOW_PARAM_MIN (4) +#define CFL_POC_JOIN_WORKFLOW_PARAM_MAX (4) + +#define CFL_POC_JOIN_WORKFLOW_PINDEX_NONCE (0) +#define CFL_POC_JOIN_WORKFLOW_PINDEX_WORKFLOW_ID (1) +#define CFL_POC_JOIN_WORKFLOW_PINDEX_WORKER_VKEY (2) +#define CFL_POC_JOIN_WORKFLOW_PINDEX_PARENT_VKEY (3) + +#define CFL_POC_JOIN_WORKFLOW_RINDEX_STATUS (0) +#define CFL_POC_JOIN_WORKFLOW_RINDEX_NONCE (1) + + +#define CFL_POC_QUIT_WORKFLOW_PARAM_MIN (4) +#define CFL_POC_QUIT_WORKFLOW_PARAM_MAX (4) + +#define CFL_POC_QUIT_WORKFLOW_PINDEX_NONCE (0) +#define CFL_POC_QUIT_WORKFLOW_PINDEX_WORKFLOW_ID (1) +#define CFL_POC_QUIT_WORKFLOW_PINDEX_WORKER_VKEY (2) +#define CFL_POC_QUIT_WORKFLOW_PINDEX_PARENT_VKEY (3) + +#define CFL_POC_QUIT_WORKFLOW_RINDEX_STATUS (0) +#define CFL_POC_QUIT_WORKFLOW_RINDEX_NONCE (1) + + + +#define CFL_POC_LOOKUP_WORKFLOWS_PARAM_MIN (1) +#define CFL_POC_LOOKUP_WORKFLOWS_PARAM_MAX (1) + +#define CFL_POC_LOOKUP_WORKFLOWS_PINDEX_NONCE (0) + +#define CFL_POC_LOOKUP_WORKFLOWS_RINDEX_STATUS (0) +#define CFL_POC_LOOKUP_WORKFLOWS_RINDEX_RESULT (1) +#define CFL_POC_LOOKUP_WORKFLOWS_RINDEX_NONCE (2) + +#define CFL_POC_WORKFLOW_RESULT_PARAM_MIN (1) +#define CFL_POC_WORKFLOW_RESULT_PARAM_MAX (1) + + +#define CFL_POC_WORKFLOW_RESULT_PINDEX_ID (0) + +#define CFL_POC_WORKFLOW_RESULT_RINDEX_STATUS (0) +#define CFL_POC_WORKFLOW_RESULT_RINDEX_RESULT (1) + + +#define CFL_POC_REMOVE_WORKFLOW_PARAM_MIN (2) +#define CFL_POC_REMOVE_WORKFLOW_PARAM_MAX (2) + +#define CFL_POC_REMOVE_WORKFLOW_PINDEX_NONCE (0) +#define CFL_POC_REMOVE_WORKFLOW_PINDEX_ID (1) + +#define CFL_POC_REMOVE_WORKFLOW_RINDEX_STATUS (0) +#define CFL_POC_REMOVE_WORKFLOW_RINDEX_NONCE (1) + + +#define CFL_POC_UPDATE_WORKFLOW_PARAM_MIN (3) +#define CFL_POC_UPDATE_WORKFLOW_PARAM_MAX (3) + +#define CFL_POC_UPDATE_WORKFLOW_PINDEX_NONCE (0) +#define CFL_POC_UPDATE_WORKFLOW_PINDEX_ID (1) +#define CFL_POC_UPDATE_WORKFLOW_PINDEX_STATUS (2) + +#define CFL_POC_UPDATE_WORKFLOW_RINDEX_STATUS (0) +#define CFL_POC_UPDATE_WORKFLOW_RINDEX_NONCE (1) + + +#define CFL_POC_AVAILABLE_DATASETS_PARAM_MIN (0) +#define CFL_POC_AVAILABLE_DATASETS_PARAM_MAX (0) + +#define CFL_POC_AVAILABLE_DATASETS_RINDEX_STATUS (0) +#define CFL_POC_AVAILABLE_DATASETS_RINDEX_RESULT (1) + + +#define CFL_POC_DO_NONCE_RQST_PARAM_MIN (3) +#define CFL_POC_DO_NONCE_RQST_PARAM_MAX (3) + +#define CFL_POC_DO_NONCE_RQST_PINDEX_ATT_DATA (0) +#define CFL_POC_DO_NONCE_RQST_PINDEX_WORKFLOW_ID (1) +#define CFL_POC_DO_NONCE_RQST_PINDEX_DATASET_ID (2) + +#define CFL_POC_DO_NONCE_RQST_RINDEX_STATUS (0) +#define CFL_POC_DO_NONCE_RQST_RINDEX_REQUEST (1) + + +#define CFL_POC_DO_PROCESS_RQST_PARAM_MIN (4) +#define CFL_POC_DO_PROCESS_RQST_PARAM_MAX (4) + +#define CFL_POC_DO_PROCESS_RQST_PINDEX_WORKFLOW_ID (0) +#define CFL_POC_DO_PROCESS_RQST_PINDEX_DATASET_ID (1) +#define CFL_POC_DO_PROCESS_RQST_PINDEX_QUERY_DATA (2) +#define CFL_POC_DO_PROCESS_RQST_PINDEX_JSON_RESULT (3) + +#define CFL_POC_DO_PROCESS_RQST_RINDEX_STATUS (0) +#define CFL_POC_DO_PROCESS_RQST_RINDEX_REQUEST (1) + + +#define CFL_POC_DO_PROCESS_RESP_PARAM_MIN (2) +#define CFL_POC_DO_PROCESS_RESP_PARAM_MAX (2) + +#define CFL_POC_DO_PROCESS_RESP_PINDEX_WORKFLOW_ID (0) +#define CFL_POC_DO_PROCESS_RESP_PINDEX_JSON_RESULT (1) + +#define CFL_POC_DO_PROCESS_RESP_RINDEX_STATUS (0) + +// this common functions reuasable by both Node and Requester enclaves + +namespace cfl { + void AddOutput(int index, + std::vector& out_work_order_data, + const ByteArray& data); + + + void AddOutput(int index, + std::vector& out_work_order_data, + const std::string& str); + + void AddOutput(int index, + std::vector& out_work_order_data, + int num); + + void AddOutput(int index, + std::vector& out_work_order_data, + const char* ptr); + + void MergeOutput(ByteArray& output, + const std::vector& out_work_order_data); + +} //namespace cfl diff --git a/examples/apps/data_owner/workload/cfl-utils.cpp b/examples/apps/data_owner/workload/cfl-utils.cpp new file mode 100644 index 000000000..06a5f4647 --- /dev/null +++ b/examples/apps/data_owner/workload/cfl-utils.cpp @@ -0,0 +1,82 @@ +#include +#include "cfl-utils.h" + +namespace cfl +{ + +ByteArray TransformBase64ByteArray(const ByteArray& data) +{ + std::string base64_str = ByteArrayToString(data); + if (base64_str.size() == 0 || base64_str == "null") + { + return ByteArray(); //empty + } + return Base64EncodedStringToByteArray(base64_str); + +} + +ByteArray TransformHexByteArray(const ByteArray& data) +{ + std::string hex_str = ByteArrayToString(data); + if (hex_str.size() == 0 || hex_str == "null") + { + return ByteArray(); //empty + } + return HexEncodedStringToByteArray(hex_str); + +} + +int TransformByteArrayToInteger(const ByteArray& data) +{ + std::string str = ByteArrayToString(data); + return std::stoi(str); +} + + +std::string VerificationKeyBlockFromByteArray(const ByteArray& vkey) +{ + std::string vkey_base64 = ByteArrayToBase64EncodedString(vkey); + return AddBeginEndBlockToVerificationKey(vkey_base64); +} + + +std::string AddBeginEndBlockToVerificationKey(const std::string& vkey_base64) +{ + std::string block = "-----BEGIN PUBLIC KEY-----\n"; + size_t vkey_len = vkey_base64.size(); + for(size_t i = 0; i < vkey_len; i += 64) + { + block += vkey_base64.substr(i, 64); + block += "\n"; + } + block += "-----END PUBLIC KEY-----\n"; + return block; + +} + + +bool GenerateNonce(ByteArray& nonce) { + uint8_t id[NONCE_LENGTH]; + sgx_status_t status = sgx_read_rand(reinterpret_cast(id), sizeof(id)); + if (status != SGX_SUCCESS) { + return false; + } + else { + nonce.assign(id, id + NONCE_LENGTH); + return true; + } +} + + +void Split(std::string str, std::vector& result) { + char *saved_ptr; + + char *token = strtok_r((char *)str.c_str(), " ", &saved_ptr); + while (token) { + result.push_back(token); + token = strtok_r(NULL, " ", &saved_ptr); + } +} + + +} //namespace cfl; diff --git a/examples/apps/data_owner/workload/cfl-utils.h b/examples/apps/data_owner/workload/cfl-utils.h new file mode 100644 index 000000000..418a20707 --- /dev/null +++ b/examples/apps/data_owner/workload/cfl-utils.h @@ -0,0 +1,73 @@ +#pragma once + +#include "work_order_data.h" +#include + +namespace cfl +{ + +struct WorkerMeasurement { + ByteArray id; + ByteArray mrenclave; + ByteArray mrsigner; + /* + * isv_prod_id and isv_svn are 16-bits numbers. we use -1 to indicate that they are not specified. + */ + int isv_prod_id; + int isv_svn; +}; + + +struct DatasetConfig +{ + ByteArray id; + ByteArray data_owner_vkey; + ByteArray data_ek; // encryption key + ByteArray worker_mrenclave; + ByteArray worker_mrsigner; // reserved + ByteArray worker_vkey; +}; + +struct GrapheneWorker +{ + ByteArray id; + ByteArray worker_mrenclave; + ByteArray worker_mrsigner; + int isv_prod_id; + int isv_svn; + ByteArray worker_vkey; + ByteArray worker_ekey; + ByteArray worker_addr; // TODO: remove this when block chain is enabled + ByteArray extra_specs; +}; + +struct AvalonWorker +{ + ByteArray id; + ByteArray worker_mrenclave; + ByteArray worker_mrsigner; + int isv_prod_id; + int isv_svn; + ByteArray worker_vkey; + ByteArray data_owner_vkey; + std::map children; +}; + + +const int NONCE_LENGTH = 32; + +ByteArray TransformBase64ByteArray(const ByteArray& data); + +ByteArray TransformHexByteArray(const ByteArray& data); + +int TransformByteArrayToInteger(const ByteArray& data); + +std::string VerificationKeyBlockFromByteArray(const ByteArray& vkey); + +std::string AddBeginEndBlockToVerificationKey(const std::string& vkey_base64); + +bool GenerateNonce(ByteArray& nonce); + +void Split(std::string str, std::vector& result); + +} //namespace cfl; diff --git a/examples/apps/data_owner/workload/data-owner-logic.cpp b/examples/apps/data_owner/workload/data-owner-logic.cpp new file mode 100644 index 000000000..ba5b368de --- /dev/null +++ b/examples/apps/data_owner/workload/data-owner-logic.cpp @@ -0,0 +1,458 @@ +// CFL POC: Plug-in.cpp +// Workload registration and entry point +// +// + + +#include "data-owner-logic.h" +#include "node-config.h" +#include "cfl-poc-defs.h" +#include "cfl-utils.h" + +namespace cfl { + +extern NodeConfig nodeConfig; + +} + +using namespace cfl; + +namespace CflPocDataOwner { + +RequesterList requester_list; +std::map DataOwnerProcessor::nonce_map; + + +void RequesterList::SetupRequesterEnclave(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo) +{ + if (in_work_order_data.size() < CFL_POC_SETUP_REQUESTER_PARAM_MIN) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + ByteArray data_owner_vkey; + ByteArray nonce = in_work_order_data[CFL_POC_SETUP_REQUESTER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + + if (!CheckDataOwner(exWorkorderInfo, data_owner_vkey)) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!VerifyWorkorderSignature(exWorkorderInfo)) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + } + else + { + RequesterInfo rinfo; + rinfo.id = in_work_order_data[CFL_POC_SETUP_REQUESTER_PINDEX_ID].decrypted_data; + rinfo.id = TransformHexByteArray(rinfo.id); + rinfo.mrenclave = in_work_order_data[CFL_POC_SETUP_REQUESTER_PINDEX_MRENCLAVE].decrypted_data; + rinfo.mrenclave = TransformHexByteArray(rinfo.mrenclave); + rinfo.mrsigner = in_work_order_data[CFL_POC_SETUP_REQUESTER_PINDEX_MRSIGNER].decrypted_data; + rinfo.verification_key = in_work_order_data[CFL_POC_SETUP_REQUESTER_PINDEX_VKEY].decrypted_data; + rinfo.verification_key = TransformBase64ByteArray(rinfo.verification_key); + + if (rinfo.id.size() == 0 || rinfo.mrenclave.size() == 0 || rinfo.verification_key.size() == 0) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM); + return; + } + + bool found = false; + + for (auto& r : requesters) + { + if (r.id == rinfo.id) + { + r = rinfo; + found = true; + } + } + + if (!found) + { + requesters.push_back(rinfo); + } + + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + nodeConfig.AddNonce(CFL_POC_SETUP_REQUESTER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + } +} + + +void RequesterList::RemoveRequesterEnclave(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo) +{ + if (in_work_order_data.size() < CFL_POC_REMOVE_REQUESTER_PARAM_MIN) + { + AddOutput(CFL_POC_REMOVE_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + ByteArray nonce = in_work_order_data[CFL_POC_REMOVE_REQUESTER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + + ByteArray data_owner_vkey; + if (!CheckDataOwner(exWorkorderInfo, data_owner_vkey)) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!VerifyWorkorderSignature(exWorkorderInfo)) + { + AddOutput(CFL_POC_REMOVE_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + } + else + { + ByteArray vkey = in_work_order_data[CFL_POC_REMOVE_REQUESTER_PINDEX_VKEY].decrypted_data; + vkey = TransformBase64ByteArray(vkey); + + for (size_t i = 0; i < requesters.size(); i++) + { + RequesterInfo r = requesters[i]; + if (r.verification_key == vkey) + { + requesters.erase(requesters.begin() + i); + break; + } + } + + AddOutput(CFL_POC_REMOVE_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + nodeConfig.AddNonce(CFL_POC_REMOVE_REQUESTER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + } +} + +void RequesterList::LookupRequesterEnclaves(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo) +{ + if (in_work_order_data.size() < CFL_POC_LOOKUP_REQUESTER_PARAM_MIN) + { + AddOutput(CFL_POC_LOOKUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + ByteArray nonce = in_work_order_data[CFL_POC_LOOKUP_REQUESTER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + + ByteArray data_owner_vkey; + if (!CheckDataOwner(exWorkorderInfo, data_owner_vkey)) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!VerifyWorkorderSignature(exWorkorderInfo)) + { + AddOutput(CFL_POC_LOOKUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_SETUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + } + else + { + std::string json = TranslateJSONResultOfRequesters(); + AddOutput(CFL_POC_LOOKUP_REQUESTER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + AddOutput(CFL_POC_LOOKUP_REQUESTER_RINDEX_RESULT, out_work_order_data, json); + nodeConfig.AddNonce(CFL_POC_LOOKUP_REQUESTER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + } +} + + + + +bool RequesterList::CheckDataOwner(ExWorkorderInfo* exWorkorderInfo, ByteArray& data_owner_vkey) +{ + return nodeConfig.CheckDataOwner(exWorkorderInfo, data_owner_vkey); +} + + + +bool RequesterList::CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey) +{ + return nodeConfig.CheckNonce(nonce, data_owner_vkey); +} + + +bool RequesterList::VerifyWorkorderSignature(ExWorkorderInfo* exWorkorderInfo) +{ + + return exWorkorderInfo->VerifyWorkorderSignature(); +} + +std::string RequesterList::TranslateJSONResultOfRequesters() +{ + std::string json = ""; + + size_t req_sz = requesters.size(); + for (size_t i = 0; i < req_sz; i++) + { + auto& r = requesters[i]; + std::string rjson = i > 0 ? ",{" : "{"; + rjson += "\"id\":\"" + ByteArrayToHexEncodedString(r.id) + "\","; + rjson += "\"mrenclave\":\"" + ByteArrayToHexEncodedString(r.mrenclave) + "\","; + //TODO: just a placeholder here + rjson += "\"mrsigner\":\"\","; + rjson += "\"verification_key\":\"" + ByteArrayToBase64EncodedString(r.verification_key) + "\"}"; + json += rjson; + } + + json = "[" + json + "]"; + + return json; +} + + +DataOwnerProcessor::DataOwnerProcessor() +{ + // stub the datasets + std::vector dataset1 = { "node-A-dataset1-1", "node-A-dataset1-2", "node-A-dataset1-3" }; + std::vector dataset2 = { "node-A-dataset2-1", "node-A-dataset2-2", "node-A-dataset2-3" }; + std::vector dataset3 = { "node-A-dataset3-1", "node-A-dataset3-2", "node-A-dataset3-3" }; + + dataset_map["dataset1"] = dataset1; + dataset_map["dataset2"] = dataset2; + dataset_map["dataset3"] = dataset3; +} + + +// TODO: Change nonce name to something else like ekey, beacuse it is actually pablic RSA key +void DataOwnerProcessor::CreateNonce(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo, + const RequesterList& rlist) +{ + if (in_work_order_data.size() < CFL_POC_NONCE_PARAM_MIN) + { + AddOutput(CFL_POC_PROCESS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + ByteArray nonce_vkey; + ByteArray skey; + ByteArray attestation_data = in_work_order_data[CFL_POC_NONCE_PINDEX_ATT_DATA].decrypted_data; + ByteArray workflow_id = in_work_order_data[CFL_POC_NONCE_PINDEX_WORKFLOW_ID].decrypted_data; + ByteArray dataset_id = in_work_order_data[CFL_POC_NONCE_PINDEX_DATASET_ID].decrypted_data; + + if (!VerifyDataSet(dataset_id)) + { + AddOutput(CFL_POC_NONCE_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + AddOutput(CFL_POC_NONCE_RINDEX_WORKFLOW_ID, out_work_order_data, workflow_id); + AddOutput(CFL_POC_NONCE_RINDEX_DATASET_ID, out_work_order_data, dataset_id); + } + else if (!VerifyRequestor(exWorkorderInfo, attestation_data, rlist)) + { + AddOutput(CFL_POC_NONCE_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + AddOutput(CFL_POC_NONCE_RINDEX_WORKFLOW_ID, out_work_order_data, workflow_id); + AddOutput(CFL_POC_NONCE_RINDEX_DATASET_ID, out_work_order_data, dataset_id); + } + else if (!GenerateNonce(nonce_vkey, skey)) + { + AddOutput(CFL_POC_NONCE_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + AddOutput(CFL_POC_NONCE_RINDEX_WORKFLOW_ID, out_work_order_data, workflow_id); + AddOutput(CFL_POC_NONCE_RINDEX_DATASET_ID, out_work_order_data, dataset_id); + } + else + { + // TODO: store a map to make sure that nonce generated for one dataset cannot be used for another + + nonce_map[nonce_vkey] = skey; + + AddOutput(CFL_POC_NONCE_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + AddOutput(CFL_POC_NONCE_RINDEX_WORKFLOW_ID, out_work_order_data, workflow_id); + AddOutput(CFL_POC_NONCE_RINDEX_DATASET_ID, out_work_order_data, dataset_id); + AddOutput(CFL_POC_NONCE_RINDEX_NONCE, out_work_order_data, nonce_vkey); + } + } +} + + +void DataOwnerProcessor::Process(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo) +{ + if (in_work_order_data.size() < CFL_POC_PROCESS_PARAM_MIN) + { + AddOutput(CFL_POC_PROCESS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = 0; + ByteArray flow_id = in_work_order_data[CFL_POC_PROCESS_PINDEX_FLOW_ID].decrypted_data; + ByteArray nonce = in_work_order_data[CFL_POC_PROCESS_PINDEX_NONCE].decrypted_data; + ByteArray vkey_sig = in_work_order_data[CFL_POC_PROCESS_PINDEX_VKEY_SIG].decrypted_data; + ByteArray dataset_name = in_work_order_data[CFL_POC_PROCESS_PINDEX_DATASET_NAME].decrypted_data; + ByteArray dataset_key = in_work_order_data[CFL_POC_PROCESS_PINDEX_DATASET_KEY].decrypted_data; + ByteArray query_data = in_work_order_data[CFL_POC_PROCESS_PINDEX_QUERY_DATA].decrypted_data; + std::string query_result; + + if (!CheckNonce(exWorkorderInfo, nonce, vkey_sig)) + { + err_code = CFL_POC_E_NONCE; + } + else + { + if (!PrepareDataset(dataset_name, dataset_key, vkey_sig)) + { + err_code = CFL_POC_E_DATASET_NAME; + } + else if (!ProcessQuery(query_data, query_result)) + { + err_code = CFL_POC_E_DATA_ITEM_INDEX; + } + RemoveNonce(nonce); + } + + AddOutput(CFL_POC_PROCESS_RINDEX_STATUS, out_work_order_data, err_code); + AddOutput(CFL_POC_PROCESS_RINDEX_DATASET_NAME, out_work_order_data, dataset_name); + + if (!err_code) + { + AddOutput(CFL_POC_PROCESS_RINDEX_DATA_ITEM, out_work_order_data, query_result); + } + } +} + + + +bool DataOwnerProcessor::CheckNonce(ExWorkorderInfo* exWorkorderInfo, const ByteArray& nonce, const ByteArray& vkey_sig) +{ + bool ret_val = false; + + // proper implemetation should + // - check the nonce exists in the nonce_map + // - get the requester signig key from the map + // - vetify the the workorder is sighed by this key using exWorkorderInfo::GetWorkorderSigningInfo() + // - directly in case of singleton + // - or indirectly in case of WPE (using nonce and vkey_sig) + + // it is a simple stub now - just chaeck that the nonce exist + auto search = nonce_map.find(nonce); + + if (search != nonce_map.end()) + { + ret_val = true; + } + + return ret_val; +} + + +bool DataOwnerProcessor::RemoveNonce(const ByteArray& nonce) +{ + bool ret_val = false; + auto search = nonce_map.find(nonce); + + if (search != nonce_map.end()) + { + nonce_map.erase(nonce); + ret_val = true; + } + + return ret_val; +} + + + +bool DataOwnerProcessor::GenerateNonce(ByteArray& nonce_vkey, ByteArray& skey) +{ + // Final implementation with call exWororderInfo API to generate RSA Key pair + // public key is used as nonce and key in the map below, and the value includes + // - secret (decryption) RSA key + // - the requester verification key (from the prior call to VerifyRequestor + + + // In the phase 1 we will use a stub below + + static uint32_t counter = 0; + bool ret_val = true; + + std::string result_str = std::to_string(++counter); + ByteArray ba(result_str.begin(), result_str.end()); + nonce_vkey = ba; + + return ret_val; +} + + + +bool DataOwnerProcessor::VerifyRequestor(ExWorkorderInfo* exWorkorderInfo, ByteArray& attestation_data, const RequesterList& rlist) +{ + // call ExWorkorderInfo::VerifyAttestaion(); + // calls requester_list.GetRequesters to get list of allowed requester MRENCLAVE values + // verify that MRENCLAVE value returened by call ExWorkorderInfo::VerifyAttestaion() is on the list + + return true; // stub it for now +} + + + +bool DataOwnerProcessor::PrepareDataset(const ByteArray& dataset_name, const ByteArray& dataset_key, const ByteArray& nonce) +{ + bool ret_val = false; + + // in the proper implementation dataset key comes encrypted with the RSA public key used known as nonce + // so the flow will be + // - check if the dataset name is valid + // - get secret RSA key by looking up nonce_map with "nonce" as the key + // - decrypt the dataset_key + // - load or setup an access to the dataset using dataset_name and dataset_key + + // stub it for now + // - check that the dataset name is valid + // - store the dataset name for later use in the ProcessQuery call + + dataset_name_str = ByteArrayToString(dataset_name); + auto search = dataset_map.find(dataset_name_str); + + if (search != dataset_map.end()) + { + ret_val = true; + } + + return ret_val; +} + + + +bool DataOwnerProcessor::ProcessQuery(const ByteArray& query_data, std::string& value) +{ + bool ret_val = false; + + // Previous calls PrepareDataset verified that dataset_name_str is valid + + std::vector dataset = dataset_map[dataset_name_str]; + std::string index_str = ByteArrayToString(query_data); + size_t index = atoi(index_str.data()); + + if (index >= 0 && index < dataset.size()) + { + value = dataset[index].data(); + ret_val = true; + } + + return ret_val; +} + + +bool DataOwnerProcessor::VerifyDataSet(const ByteArray& dataset_id) +{ + auto search = dataset_map.find(ByteArrayToString(dataset_id)); + return (search != dataset_map.end()); +} + +}//namespace CflPocDataOwner diff --git a/examples/apps/data_owner/workload/data-owner-logic.h b/examples/apps/data_owner/workload/data-owner-logic.h new file mode 100644 index 000000000..31878265d --- /dev/null +++ b/examples/apps/data_owner/workload/data-owner-logic.h @@ -0,0 +1,123 @@ +// +// CFL POC: logic.h +// Data owner workload logic definition and inline implementation +// + +// +// This a skeleton (pseudo_code) to serve as a reference for actual implementation +// + + +#pragma once + +#include +#include +#include "data-owner-plug-in.h" + +namespace CflPocDataOwner { + +const size_t VERIFICATION_KEY_SIZE = 88; + +struct RequesterInfo +{ + ByteArray id; + ByteArray mrenclave; + ByteArray mrsigner; + ByteArray verification_key; +}; + +// The class below is a placeholder to be extended later +// The class below is a placeholder to be extended later +// TODO: add nonce generation in a way similar to RequesterNodeConfig class +class RequesterList +{ +public: + RequesterList() { } + + virtual ~RequesterList() { } + + virtual void SetupRequesterEnclave(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo); + + virtual void RemoveRequesterEnclave(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo); + + virtual void LookupRequesterEnclaves(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo); + + virtual std::vector& GetRequesters() + { + return requesters; + } + +protected: + virtual bool CheckDataOwner(ExWorkorderInfo* exWorkorderInfo, ByteArray& data_owner_vkey); + + virtual bool CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey); + + virtual bool VerifyWorkorderSignature(ExWorkorderInfo* exWorkorderInfo); + + virtual std::string TranslateJSONResultOfRequesters(); + + + std::vector requesters; +}; + + +class DataOwnerProcessor +{ +public: + DataOwnerProcessor(); + + virtual ~DataOwnerProcessor() {} + + + // TODO: Change nonce name to something else like ekey, beacuse it is actually pablic RSA key + virtual void CreateNonce(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo, + const RequesterList& rlist); + + virtual void Process(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* exWorkorderInfo); + + // TODO: Uncomment the function below when exWorkorderInfo is available in tcf::Workload class + //virtual void SetExtendedWoroderInfoApi(tcf::ExWorkorderInfo* _exWorkorderInfo) + //{ + // exWorkorderInfo = _exWorkorderInfo; + //}; + + +protected: + virtual bool CheckNonce(ExWorkorderInfo* exWorkorderInfo, const ByteArray& nonce, const ByteArray& vkey_sig); + + virtual bool RemoveNonce(const ByteArray& nonce); + + virtual bool GenerateNonce(ByteArray& nonce_vkey, ByteArray& skey); + + virtual bool VerifyRequestor(ExWorkorderInfo* exWorkorderInfo, ByteArray& attestation_data, const RequesterList& rlist); + + virtual bool PrepareDataset(const ByteArray& dataset_name, const ByteArray& dataset_key, const ByteArray& nonce); + + virtual bool ProcessQuery(const ByteArray& query_data, std::string& value); + + virtual bool VerifyDataSet(const ByteArray& dataset_id); + + + std::map> dataset_map; + std::string dataset_name_str; + + static std::map nonce_map; + + + // TODO: Uncomment the line below exWorkorderInfo is available in tcf::Workload class + // tcf::ExWorkorderInfo* exWorkorderInfo; +}; + + +}//namespace CflPocDataOwner + diff --git a/examples/apps/data_owner/workload/data-owner-node-config.cpp b/examples/apps/data_owner/workload/data-owner-node-config.cpp new file mode 100644 index 000000000..cf4bd05c5 --- /dev/null +++ b/examples/apps/data_owner/workload/data-owner-node-config.cpp @@ -0,0 +1,439 @@ +#include + +#include "avalon_sgx_error.h" + +#include "data-owner-node-config.h" +#include "node-config.h" +#include "cfl-poc-defs.h" +#include "cfl-utils.h" +#include "verify-workers.h" + +namespace cfl { + +extern NodeConfig nodeConfig; + +} + +using namespace cfl; + +namespace CflPocDataOwner { + +DataOwnerNodeConfig dataOwnerNodeConfig; + +void DataOwnerNodeConfig::SetupWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_SETUP_DO_WORKER_PARAM_MIN) + { + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + + ByteArray nonce = in_work_order_data[CFL_POC_SETUP_DO_WORKER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + return; + } + + ByteArray signup_data = in_work_order_data[CFL_POC_SETUP_DO_WORKER_PINDEX_SIGNUP_DATA].decrypted_data; + signup_data = TransformBase64ByteArray(signup_data); + std::string signup_data_json = ByteArrayToString(signup_data); + + GrapheneWorker worker; + if (!VerifyWorker(signup_data_json.c_str(), nonce, worker)) + { + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_QUOTE); + return; + } + + + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_OP, out_work_order_data, CFL_POC_OP_ADD_WORKER); + + ByteArray req_nonce = in_work_order_data[CFL_POC_SETUP_DO_WORKER_PINDEX_REQ_NONCE].decrypted_data; + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_REQ_NONCE, out_work_order_data, req_nonce); + + ByteArray id = in_work_order_data[CFL_POC_SETUP_DO_WORKER_PINDEX_ID].decrypted_data; + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_ID, out_work_order_data, id); + + std::string mrenclave = ByteArrayToHexEncodedString(worker.worker_mrenclave); + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_MRENCLAVE, out_work_order_data, mrenclave); + std::string mrsigner = ByteArrayToHexEncodedString(worker.worker_mrsigner); + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_MRSIGNER, out_work_order_data, mrsigner); + + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_ISV_PROD_ID, out_work_order_data, worker.isv_prod_id); + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_ISV_SVN, out_work_order_data, worker.isv_svn); + + std::string vkey_base64 = ByteArrayToBase64EncodedString(worker.worker_vkey); + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_VKEY, out_work_order_data, vkey_base64); + + std::string ekey_base64 = ByteArrayToBase64EncodedString(worker.worker_ekey); + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_EKEY, out_work_order_data, ekey_base64); + + ByteArray address = in_work_order_data[CFL_POC_SETUP_DO_WORKER_PINDEX_ADDRESS].decrypted_data; + worker.worker_addr = address; + AddOutput(CFL_POC_SETUP_DO_WORKER_RINDEX_ADDRESS, out_work_order_data, address); + + children[worker.worker_vkey] = worker; + +} + +void DataOwnerNodeConfig::RemoveWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + //TODO + //This function should update the in-memory info of Graphene workers. + //By now, the info of Graphene workers is managed by requeter Avalon. + //Thus, as a data owner Avalon, we just return a constant value "0", + //so that the client could get the signature of the server. + if (in_work_order_data.size() < CFL_POC_REMOVE_DO_WORKER_PARAM_MIN) + { + AddOutput(CFL_POC_REMOVE_DO_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + ByteArray nonce = in_work_order_data[CFL_POC_REMOVE_DO_WORKER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + + ByteArray data_owner_vkey; + + int err_code = CFL_POC_E_OP_OK; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + + + AddOutput(CFL_POC_REMOVE_DO_WORKER_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + ByteArray vkey = in_work_order_data[CFL_POC_REMOVE_DO_WORKER_PINDEX_VKEY].decrypted_data; + vkey = TransformBase64ByteArray(vkey); + children.erase(vkey); + nodeConfig.AddNonce(CFL_POC_REMOVE_DO_WORKER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } +} + +bool DataOwnerNodeConfig::CheckUserVkey(const ByteArray& user_vkey) +{ + return children.find(user_vkey) != children.end(); +} + + +void DataOwnerNodeConfig::AddWorkerMeasurement(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_OP_CFG_ADD_WORKER_MEAS_PARAM_MIN) + { + AddOutput(CFL_POC_OP_CFG_ADD_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + + ByteArray data_owner_vkey; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + AddOutput(CFL_POC_OP_CFG_ADD_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_OP_CFG_ADD_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + ByteArray nonce = in_work_order_data[CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_OP_CFG_ADD_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + return; + } + + ByteArray mrenclave = in_work_order_data[CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_MRENCLAVE].decrypted_data; + mrenclave = TransformHexByteArray(mrenclave); + ByteArray mrsigner = in_work_order_data[CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_MRSIGNER].decrypted_data; + mrsigner = TransformHexByteArray(mrsigner); + ByteArray isv_prod_id_byte = in_work_order_data[CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_ISV_PROD_ID].decrypted_data; + int isv_prod_id = TransformByteArrayToInteger(isv_prod_id_byte); + ByteArray isv_svn_byte = in_work_order_data[CFL_POC_OP_CFG_ADD_WORKER_MEAS_PINDEX_ISV_SVN].decrypted_data; + int isv_svn = TransformByteArrayToInteger(isv_svn_byte); + ByteArray id; + ::cfl::GenerateNonce(id); + + WorkerMeasurement worker_meas; + worker_meas.id = id; + worker_meas.mrenclave = mrenclave; + worker_meas.mrsigner = mrsigner; + worker_meas.isv_prod_id = isv_prod_id; + worker_meas.isv_svn = isv_svn; + worker_measurements.emplace_back(worker_meas); + + AddOutput(CFL_POC_OP_CFG_ADD_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + nodeConfig.AddNonce(CFL_POC_OP_CFG_ADD_WORKER_MEAS_RINDEX_NONCE, out_work_order_data, data_owner_vkey); +} + + +void DataOwnerNodeConfig::RemoveWorkerMeasurement(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_PARAM_MIN) + { + AddOutput(CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + + ByteArray data_owner_vkey; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + AddOutput(CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + ByteArray nonce = in_work_order_data[CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + return; + } + + + ByteArray id = in_work_order_data[CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_PINDEX_ID].decrypted_data; + id = TransformHexByteArray(id); + for (auto it = worker_measurements.begin(); it != worker_measurements.end(); it++) + { + if (it->id == id) + { + worker_measurements.erase(it); + break; + } + } + + AddOutput(CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + nodeConfig.AddNonce(CFL_POC_OP_CFG_REMOVE_WORKER_MEAS_RINDEX_NONCE, out_work_order_data, data_owner_vkey); +} + + +void DataOwnerNodeConfig::LookupWorkerMeasurements(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_PARAM_MIN) + { + AddOutput(CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + + ByteArray data_owner_vkey; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + AddOutput(CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + ByteArray nonce = in_work_order_data[CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + return; + } + + std::string result = TranslateWorkerMeasurements(); + AddOutput(CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + AddOutput(CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_RESULT, out_work_order_data, result); + nodeConfig.AddNonce(CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS_RINDEX_NONCE, out_work_order_data, data_owner_vkey); +} + + +void DataOwnerNodeConfig::SealEncryptionKey(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_OP_CFG_SEAL_ENC_KEY_PARAM_MIN) + { + AddOutput(CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + + ByteArray data_owner_vkey; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + AddOutput(CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + ByteArray nonce = in_work_order_data[CFL_POC_OP_CFG_SEAL_ENC_KEY_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + return; + } + + ByteArray key = in_work_order_data[CFL_POC_OP_CFG_SEAL_ENC_KEY_PINDEX_KEY].decrypted_data; + key = TransformBase64ByteArray(key); + const uint8_t * key_ptr = key.data(); + size_t key_size = key.size(); + + const uint32_t sealed_key_size = sgx_calc_sealed_data_size(0, key_size); + ByteArray sealed_key_buffer(sealed_key_size); + 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 + key_size, + key_ptr, + sealed_key_size, + reinterpret_cast(sealed_key_buffer.data())); + + tcf::error::ThrowSgxError(ret, "Failed to seal encryption key"); + + + AddOutput(CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + AddOutput(CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_SEALED_KEY, out_work_order_data, + ByteArrayToBase64EncodedString(sealed_key_buffer)); + nodeConfig.AddNonce(CFL_POC_OP_CFG_SEAL_ENC_KEY_RINDEX_NONCE, out_work_order_data, data_owner_vkey); +} + + +void DataOwnerNodeConfig::UnsealEncryptionKey(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_OP_CFG_UNSEAL_ENC_KEY_PARAM_MIN) + { + AddOutput(CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + + ByteArray vkey; + bool is_data_owner = CheckDataOwner(wo_info, vkey); + + if (!is_data_owner && !CheckUserVkey(vkey)) + { + AddOutput(CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + ByteArray nonce = in_work_order_data[CFL_POC_OP_CFG_UNSEAL_ENC_KEY_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + if (!CheckNonce(nonce, vkey)) + { + AddOutput(CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + return; + } + + ByteArray sealed_key = in_work_order_data[CFL_POC_OP_CFG_UNSEAL_ENC_KEY_PINDEX_KEY].decrypted_data; + sealed_key = TransformBase64ByteArray(sealed_key); + + + uint32_t key_size = sgx_get_encrypt_txt_len(reinterpret_cast(sealed_key.data())); + ByteArray key_buffer(key_size); + + sgx_status_t ret = sgx_unseal_data(reinterpret_cast(sealed_key.data()), + nullptr, 0, key_buffer.data(), &key_size); + tcf::error::ThrowSgxError(ret, "Failed to unseal encryption key"); + + + AddOutput(CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + AddOutput(CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_KEY, out_work_order_data, + ByteArrayToBase64EncodedString(key_buffer)); + nodeConfig.AddNonce(CFL_POC_OP_CFG_UNSEAL_ENC_KEY_RINDEX_NONCE, out_work_order_data, vkey); +} + + + + +bool DataOwnerNodeConfig::CheckDataOwner(ExWorkorderInfo* wo_info, ByteArray& data_owner_vkey) +{ + return nodeConfig.CheckDataOwner(wo_info, data_owner_vkey); +} + +bool DataOwnerNodeConfig::CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey) +{ + return nodeConfig.CheckNonce(nonce, data_owner_vkey); +} + +bool DataOwnerNodeConfig::VerifyWorkorderSignature(ExWorkorderInfo* exWorkorderInfo) +{ + return exWorkorderInfo->VerifyWorkorderSignature(); +} + +std::string DataOwnerNodeConfig::TranslateWorkerMeasurements() +{ + std::string json = ""; + + bool first = true; + for (auto& worker_meas: worker_measurements) + { + if(first) json += TranslateWorkerMeasurement(worker_meas); + else json += "," + TranslateWorkerMeasurement(worker_meas); + } + return "[" + json + "]"; +} + + +std::string DataOwnerNodeConfig::TranslateWorkerMeasurement(const WorkerMeasurement & worker_meas) +{ + std::string json = ""; + + json += "{\"id\":\"" + ByteArrayToHexEncodedString(worker_meas.id) + "\","; + json += "\"mrenclave\":\"" + ByteArrayToHexEncodedString(worker_meas.mrenclave) + "\","; + json += "\"mrsigner\":\"" + ByteArrayToHexEncodedString(worker_meas.mrsigner) + "\","; + json += "\"isv_prod_id\":" + std::to_string(worker_meas.isv_prod_id) + ","; + json += "\"isv_svn\":" + std::to_string(worker_meas.isv_svn) + "}"; + + return json; + +} + +} //namespace CflPocDataOwner diff --git a/examples/apps/data_owner/workload/data-owner-node-config.h b/examples/apps/data_owner/workload/data-owner-node-config.h new file mode 100644 index 000000000..0aba5f9a1 --- /dev/null +++ b/examples/apps/data_owner/workload/data-owner-node-config.h @@ -0,0 +1,69 @@ +#pragma once + +#include +#include "cfl-poc-defs.h" + +namespace CflPocDataOwner { + +// The class below is a placeholder to be extended later + +// TODO: hardcode const data owner verification keys to use for RequesterNodeConfig::setting up data_owner_vkeys +// + + +class DataOwnerNodeConfig +{ +public: + + DataOwnerNodeConfig() {} + + virtual ~DataOwnerNodeConfig(){}; + + virtual void SetupWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void RemoveWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void AddWorkerMeasurement(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void RemoveWorkerMeasurement(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void LookupWorkerMeasurements(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void SealEncryptionKey(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void UnsealEncryptionKey(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + const std::vector& GetWorkerMeasurements() { return worker_measurements; } + + virtual bool CheckUserVkey(const ByteArray& user_vkey); + + +protected: + virtual bool CheckDataOwner(ExWorkorderInfo* wo_info, ByteArray& data_owner_vkey); + + virtual bool CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey); + + virtual bool VerifyWorkorderSignature(ExWorkorderInfo* exWorkorderInfo); + + virtual std::string TranslateWorkerMeasurements(); + virtual std::string TranslateWorkerMeasurement(const cfl::WorkerMeasurement& worker_meas); + + std::vector worker_measurements; + std::map children; +}; + +} //namespace CflPocDataOwner diff --git a/examples/apps/data_owner/workload/data-owner-plug-in.cpp b/examples/apps/data_owner/workload/data-owner-plug-in.cpp new file mode 100644 index 000000000..c0d9ae938 --- /dev/null +++ b/examples/apps/data_owner/workload/data-owner-plug-in.cpp @@ -0,0 +1,204 @@ +// +// CFL POC: Plug-in.cpp +// Workload registration and entry point +// + +#include + +#include "data-owner-logic.h" +#include "data-owner-plug-in.h" +#include "data-owner-node-config.h" +#include "cfl-poc-defs.h" +#include "cfl-utils.h" + +using namespace cfl; + + +typedef CflPocDataOwner::DataOwner DataOwnerSetupRequester; +typedef CflPocDataOwner::DataOwner DataOwnerRemoveRequester; +typedef CflPocDataOwner::DataOwner DataOwnerLookupRequesters; + +typedef CflPocDataOwner::DataOwner DataOwnerSetupDOWorker; +typedef CflPocDataOwner::DataOwner DataOwnerRemoveDOWorker; + +typedef CflPocDataOwner::DataOwner DataOwnerAddWorkerMeasuremnet; +typedef CflPocDataOwner::DataOwner DataOwnerRemoveWorkerMeasuremnet; +typedef CflPocDataOwner::DataOwner DataOwnerLookupWorkerMeasuremnets; +typedef CflPocDataOwner::DataOwner DataOwnerSealEncryptionKey; +typedef CflPocDataOwner::DataOwner DataOwnerUnsealEncryptionKey; + +typedef CflPocDataOwner::DataOwner DataOwnerNonce; +typedef CflPocDataOwner::DataOwner DataOwnerProcess; + +//TODO: change CFL_POC_OP_RLIST_NONCE to CFL_POC_OP_CFG_NONCE for release version +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_SETUP_REQUESTER, DataOwnerSetupRequester) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_REMOVE_REQUESTER, DataOwnerRemoveRequester) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_LOOKUP_REQUESTERS, DataOwnerLookupRequesters) + +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CFG_ADD_WORKER_MEAS, DataOwnerAddWorkerMeasuremnet) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CFG_REMOVE_WORKER_MEAS, DataOwnerRemoveWorkerMeasuremnet) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS, DataOwnerLookupWorkerMeasuremnets) + +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CFG_SETUP_DO_WORKER, DataOwnerSetupDOWorker) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CFG_REMOVE_DO_WORKER, DataOwnerRemoveDOWorker) + +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_NONCE, DataOwnerNonce) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_PROCESS, DataOwnerProcess) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CFG_SEAL_ENC_KEY, DataOwnerSealEncryptionKey) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CFG_UNSEAL_ENC_KEY, DataOwnerUnsealEncryptionKey) + +namespace CflPocDataOwner { + +extern RequesterList requester_list; +extern DataOwnerNodeConfig dataOwnerNodeConfig; +static ExWorkorderInfo data_owner_ex; + +void DataOwner::ProcessWorkOrder( + std::string workload_id, + const ByteArray& requester_id, + const ByteArray& worker_id, + const ByteArray& work_order_id, + const std::vector& in_work_order_data, + std::vector& out_work_order_data) +{ + DataOwnerProcessor processor; + + //TODO: + //Remove the block below, when class ExWorkorderInfo is available. + //By now, we have a fake ExWorkorderInfo, and the verifying key is passed through parameter. + size_t input_size = in_work_order_data.size(); + if(input_size < 2) + { + AddOutput(0, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + std::vector _in_work_order_data; + for(size_t i = 0; i < input_size - 2; i++) + { + _in_work_order_data.emplace_back(in_work_order_data[i]); + } + + ByteArray signature = in_work_order_data[input_size - 2].decrypted_data; + signature = TransformBase64ByteArray(signature); + ByteArray verificationKey = in_work_order_data[input_size - 1].decrypted_data; + verificationKey = TransformBase64ByteArray(verificationKey); + //std::string block = VerificationKeyBlockFromByteArray(verificationKey); + //AddOutput(0, out_work_order_data, block); + //return; + + + // TODO: Uncomment the line below exWorkorderInfo is available in tcf::Workload class + // processor.SetExtendedWoroderInfoApi(exWorkorderInfo); + + // TODO: remove line below exWorkorderInfo is available in tcf::Workload class and remove the dummy line + //ExWorkorderInfo* exWorkorderInfo = &data_owner_ex; // TODO: remove this dummy placeholder + std::unique_ptr exWorkorderInfo_ptr(new ExWorkorderInfo); + ExWorkorderInfo* exWorkorderInfo = exWorkorderInfo_ptr.get(); + exWorkorderInfo->SetVerificationKey(verificationKey); + exWorkorderInfo->SetSignature(signature); + + //TODO: + //Remove this when output data with multiple elementes is supported. + std::vector _out_work_order_data; + + + if (workload_id == CFL_POC_OP_SETUP_REQUESTER) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requester_list.SetupRequesterEnclave(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_REMOVE_REQUESTER) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requester_list.RemoveRequesterEnclave(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_LOOKUP_REQUESTERS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requester_list.LookupRequesterEnclaves(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_CFG_SETUP_DO_WORKER) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + dataOwnerNodeConfig.SetupWorker(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_CFG_REMOVE_DO_WORKER) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + dataOwnerNodeConfig.RemoveWorker(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_CFG_ADD_WORKER_MEAS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + dataOwnerNodeConfig.AddWorkerMeasurement(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_CFG_REMOVE_WORKER_MEAS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + dataOwnerNodeConfig.RemoveWorkerMeasurement(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_CFG_LOOKUP_WORKER_MEAS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + dataOwnerNodeConfig.LookupWorkerMeasurements(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_CFG_SEAL_ENC_KEY) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + dataOwnerNodeConfig.SealEncryptionKey(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_CFG_UNSEAL_ENC_KEY) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + dataOwnerNodeConfig.UnsealEncryptionKey(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else if (workload_id == CFL_POC_OP_NONCE) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + processor.CreateNonce(_in_work_order_data, _out_work_order_data, exWorkorderInfo, requester_list); + } + else if (workload_id == CFL_POC_OP_PROCESS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + processor.Process(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + { + //TODO: + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + AddOutput(0, _out_work_order_data, CFL_POC_E_OP_CODE); + } + + //TODO: + //Remove this when output data with multiple elementes is supported. + ByteArray output; + MergeOutput(output, _out_work_order_data); + AddOutput(0, out_work_order_data, output); +} + +} //namespace CflPocDataOwner diff --git a/examples/apps/data_owner/workload/data-owner-plug-in.h b/examples/apps/data_owner/workload/data-owner-plug-in.h new file mode 100644 index 000000000..3519b0f27 --- /dev/null +++ b/examples/apps/data_owner/workload/data-owner-plug-in.h @@ -0,0 +1,31 @@ +// +// CFL POC: Plug-in.h +// Definitions for the workload registration and entry point +// + +#pragma once + +#include "workload_processor.h" + +#include +#include +#include +#include "cfl-poc-defs.h" + +namespace CflPocDataOwner { + + class DataOwner : public WorkloadProcessor { + public: + IMPL_WORKLOAD_PROCESSOR_CLONE(DataOwner) + + virtual void ProcessWorkOrder( + std::string workload_id, + const ByteArray& requester_id, + const ByteArray& worker_id, + const ByteArray& work_order_id, + const std::vector& in_work_order_data, + std::vector& out_work_order_data); + }; + +} // namespace CflPocDataOwner + diff --git a/examples/apps/data_owner/workload/node-config-plug-in.cpp b/examples/apps/data_owner/workload/node-config-plug-in.cpp new file mode 100644 index 000000000..123fc73f7 --- /dev/null +++ b/examples/apps/data_owner/workload/node-config-plug-in.cpp @@ -0,0 +1,88 @@ +// +// CFL POC: requester-node-plug-in.cpp +// Workload registration and entry point +// + +#include "node-config-plug-in.h" +#include "node-config.h" +#include "cfl-poc-defs.h" +#include "cfl-utils.h" + +using namespace cfl; + +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CFG_NONCE, NodeConfigPlugin) + + +namespace cfl { + +extern NodeConfig nodeConfig; + +// TODO: this dummy placeholder when the interface is implemented +//static ExWorkorderInfo requester_ex; + +void NodeConfigPlugin::ProcessWorkOrder( + std::string workload_id, + const ByteArray& requester_id, + const ByteArray& worker_id, + const ByteArray& work_order_id, + const std::vector& in_work_order_data, + std::vector& out_work_order_data) +{ + //TODO: + //Remove the block below, when class ExWorkorderInfo is available. + //By now, we have a fake ExWorkorderInfo, and the verifying key is passed through parameter. + size_t input_size = in_work_order_data.size(); + if(input_size < 2) + { + AddOutput(0, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + std::vector _in_work_order_data; + for(size_t i = 0; i < input_size - 2; i++) + { + _in_work_order_data.emplace_back(in_work_order_data[i]); + } + + ByteArray signature = in_work_order_data[input_size - 2].decrypted_data; + signature = TransformBase64ByteArray(signature); + ByteArray verificationKey = in_work_order_data[input_size - 1].decrypted_data; + verificationKey = TransformBase64ByteArray(verificationKey); + + + // TODO: remove line below exWorkorderInfo is available in tcf::Workload class and remove the dummy line + //ExWorkorderInfo* exWorkorderInfo = &requester_ex; // TODO: remove this dummy placeholder + + std::unique_ptr exWorkorderInfo_ptr(new ExWorkorderInfo); + ExWorkorderInfo* exWorkorderInfo = exWorkorderInfo_ptr.get(); + exWorkorderInfo->SetVerificationKey(verificationKey); + exWorkorderInfo->SetSignature(signature); + + + //TODO: + //Remove this when output data with multiple elementes is supported. + std::vector _out_work_order_data; + + + if (workload_id == CFL_POC_OP_CFG_NONCE) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + nodeConfig.CreateNonce(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + { + //TODO: + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + AddOutput(0, _out_work_order_data, CFL_POC_E_OP_CODE); + } + + //TODO: + //Remove this when output data with multiple elementes is supported. + ByteArray output; + MergeOutput(output, _out_work_order_data); + AddOutput(0, out_work_order_data, output); +} + +} //namespace cfl diff --git a/examples/apps/data_owner/workload/node-config-plug-in.h b/examples/apps/data_owner/workload/node-config-plug-in.h new file mode 100644 index 000000000..f69035bb6 --- /dev/null +++ b/examples/apps/data_owner/workload/node-config-plug-in.h @@ -0,0 +1,32 @@ +// +// CFL POC: Plug-in.h +// Definitions for the workload registration and entry point +// + +#pragma once + +#include "workload_processor.h" + +#include +#include +#include +#include "cfl-poc-defs.h" + +namespace cfl { + + class NodeConfigPlugin : public WorkloadProcessor { + public: + IMPL_WORKLOAD_PROCESSOR_CLONE(NodeConfigPlugin) + + virtual void ProcessWorkOrder( + std::string workload_id, + const ByteArray& requester_id, + const ByteArray& worker_id, + const ByteArray& work_order_id, + const std::vector& in_work_order_data, + std::vector& out_work_order_data); + }; + +} // namespace cfl + + diff --git a/examples/apps/data_owner/workload/node-config.cpp b/examples/apps/data_owner/workload/node-config.cpp new file mode 100644 index 000000000..afdb9d471 --- /dev/null +++ b/examples/apps/data_owner/workload/node-config.cpp @@ -0,0 +1,112 @@ +#include "node-config.h" +#include "cfl-poc-defs.h" +#include "requester-node-logic.h" +#include "cfl-utils.h" + +namespace CflPocRequester { + +extern RequesterNodeConfig requesterNodeConfig; + +} + +namespace CflPocDataOwner { + +extern DataOwnerNodeConfig dataOwnerNodeConfig; + +} + +namespace cfl { + +NodeConfig nodeConfig; + + +NodeConfig::NodeConfig() +{ + size_t num_of_keys = sizeof(data_owner_verification_keys) / VERIFICATION_KEY_SIZE; + for (size_t i = 0; i < num_of_keys; i++) + { + ByteArray data_owner_vkey(data_owner_verification_keys[i], data_owner_verification_keys[i] + VERIFICATION_KEY_SIZE); + data_owner_vkeys[data_owner_vkey] = 1; + } +} + + +void NodeConfig::CreateNonce(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_CFG_NONCE_PARAM_MIN) + { + AddOutput(CFL_POC_CFG_NONCE_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray data_owner_vkey; + ByteArray nonce; + + if (!CheckDataOwner(wo_info, data_owner_vkey) && + !CflPocRequester::requesterNodeConfig.CheckUserVkey(data_owner_vkey) && + !CflPocDataOwner::dataOwnerNodeConfig.CheckUserVkey(data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CreateNonce(data_owner_vkey, nonce)) + { + err_code = CFL_POC_E_NONCE; + } + AddOutput(CFL_POC_CFG_NONCE_RINDEX_STATUS, out_work_order_data, err_code); + if (!err_code) + { + std::string nonce_hex = ByteArrayToHexEncodedString(nonce); + AddOutput(CFL_POC_CFG_NONCE_RINDEX_NONCE, out_work_order_data, nonce_hex); + } + } +} + +bool NodeConfig::CreateNonce(const ByteArray& data_owner_vkey, ByteArray& nonce) +{ + if (! ::cfl::GenerateNonce(nonce)) + { + return false; + } + nonce_map[nonce] = data_owner_vkey; + return true; +} + +void NodeConfig::AddNonce(int index, std::vector& out_work_order_data, const ByteArray& data_owner_vkey) +{ + ByteArray nonce; + if (CreateNonce(data_owner_vkey, nonce)) + { + std::string nonce_hex = ByteArrayToHexEncodedString(nonce); + AddOutput(index, out_work_order_data, nonce_hex); + } +} + + +bool NodeConfig::CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey) +{ + bool ret_val = false; + + auto search = nonce_map.find(nonce); + if (search != nonce_map.end()) + { + if (nonce_map[nonce] == data_owner_vkey) + { + ret_val = true; + } + nonce_map.erase(nonce); + } + + return ret_val; +} + +bool NodeConfig::CheckDataOwner(ExWorkorderInfo* wo_info, ByteArray& data_owner_vkey) +{ + wo_info->GetWorkorderSigningInfo(data_owner_vkey); + return data_owner_vkeys.find(data_owner_vkey) != data_owner_vkeys.end(); +} + + +} //namespace cfl diff --git a/examples/apps/data_owner/workload/node-config.h b/examples/apps/data_owner/workload/node-config.h new file mode 100644 index 000000000..e07d58be3 --- /dev/null +++ b/examples/apps/data_owner/workload/node-config.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include "cfl-poc-defs.h" +#include "data-owner-node-config.h" +#include "requester-node-config.h" + +namespace cfl { + +const size_t VERIFICATION_KEY_SIZE = 88; + +class NodeConfig { +public: + NodeConfig(); + + ~NodeConfig() { } + + virtual void CreateNonce(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual bool CheckDataOwner(ExWorkorderInfo* wo_info, ByteArray& data_owner_vkey); + + virtual bool CreateNonce(const ByteArray& data_owner_vkey, ByteArray& nonce); + + virtual bool CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey); + + virtual void AddNonce(int index, std::vector& out_work_order_data, const ByteArray& data_owner_vkey); + +private: + + std::map nonce_map; + std::map data_owner_vkeys; + + const uint8_t data_owner_verification_keys[3][VERIFICATION_KEY_SIZE] = + { + {0x30, 0x56, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x03, 0x42, + 0x00, 0x04, 0x42, 0xc6, 0xd8, 0x0e, 0xf8, 0xe0, 0x18, 0x0a, 0xd3, 0xba, 0x61, 0x95, 0xf2, 0x50, 0xdd, 0xdb, 0xb9, 0x5f, 0x1c, 0x0f, + 0xe5, 0xf3, 0xb5, 0x6f, 0xe1, 0xb1, 0x9d, 0x7f, 0xd4, 0x9f, 0x3d, 0xe3, 0x23, 0x6d, 0x39, 0xa5, 0x3b, 0xa3, 0xf4, 0xd5, 0x98, 0xaa, + 0xb6, 0x47, 0x27, 0x99, 0xb8, 0xa2, 0xf6, 0xe6, 0x51, 0x6a, 0x81, 0x57, 0xe6, 0xb4, 0x2c, 0x75, 0x53, 0xf6, 0x12, 0xe6, 0x5e, 0x8a}, + + {0x30, 0x56, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x03, 0x42, + 0x00, 0x04, 0x25, 0xe6, 0x95, 0x65, 0x4e, 0x2d, 0x17, 0x05, 0x32, 0x2f, 0xf9, 0x77, 0x1d, 0x40, 0xfc, 0x15, 0xa2, 0x09, 0xab, 0x8a, + 0xbf, 0xa4, 0x9d, 0xc9, 0x72, 0x29, 0xdf, 0x60, 0xb0, 0x0c, 0xf6, 0x18, 0xf1, 0x75, 0x9f, 0x10, 0x3c, 0xff, 0x6b, 0x05, 0x56, 0xa1, + 0xa3, 0x35, 0x0f, 0x41, 0xef, 0xfd, 0x8d, 0xea, 0x13, 0x8f, 0x3a, 0x20, 0xa2, 0xd0, 0x14, 0x27, 0x16, 0x61, 0xe6, 0x47, 0xa1, 0x05}, + + {0x30, 0x56, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x0a, 0x03, 0x42, + 0x00, 0x04, 0x51, 0x1b, 0xb8, 0x09, 0x87, 0xb2, 0x0f, 0xdf, 0xa2, 0x51, 0xa9, 0x4d, 0x5e, 0x7c, 0xd2, 0xf2, 0xa6, 0x35, 0x52, 0xe2, + 0x5f, 0x84, 0x27, 0xea, 0xbc, 0x1f, 0x25, 0x4f, 0xd7, 0x88, 0x53, 0xd3, 0xf5, 0x12, 0xbb, 0x75, 0xad, 0xcf, 0x79, 0xce, 0xc1, 0x5a, + 0xdf, 0x8c, 0xfa, 0xcc, 0x08, 0xdb, 0x43, 0xd6, 0x1d, 0x5e, 0x3f, 0xb1, 0x63, 0x46, 0xdd, 0x80, 0x77, 0xdb, 0x6c, 0x46, 0x4b, 0x78} + }; + +}; + +} //namespace cfl diff --git a/examples/apps/data_owner/workload/requester-node-config.cpp b/examples/apps/data_owner/workload/requester-node-config.cpp new file mode 100644 index 000000000..d448fd1f9 --- /dev/null +++ b/examples/apps/data_owner/workload/requester-node-config.cpp @@ -0,0 +1,1057 @@ +#include "requester-node-config.h" +#include "requester-node-logic.h" +#include "node-config.h" +#include "cfl-poc-defs.h" +#include "cfl-utils.h" + + +namespace cfl { + +extern NodeConfig nodeConfig; + +} + +using namespace cfl; + +namespace CflPocRequester { + +void RequesterNodeConfig::AddWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_ADD_WORKER_PINDEX_TYPE + 1) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + ByteArray worker_type_byte = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_TYPE].decrypted_data; + std::string worker_type = ByteArrayToString(worker_type_byte); + if (worker_type == "avalon") + { + AddAvalonWorker(in_work_order_data, out_work_order_data, wo_info); + } + else if(worker_type == "graphene") + { + AddGrapheneWorker(in_work_order_data, out_work_order_data, wo_info); + } + else + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM); + } + } +} + +void RequesterNodeConfig::RemoveWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_REMOVE_WORKER_PINDEX_TYPE + 1) + { + AddOutput(CFL_POC_REMOVE_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + ByteArray worker_type_byte = in_work_order_data[CFL_POC_REMOVE_WORKER_PINDEX_TYPE].decrypted_data; + std::string worker_type = ByteArrayToString(worker_type_byte); + if (worker_type == "avalon") + { + RemoveAvalonWorker(in_work_order_data, out_work_order_data, wo_info); + } + else if(worker_type == "graphene") + { + RemoveGrapheneWorker(in_work_order_data, out_work_order_data, wo_info); + } + else + { + AddOutput(CFL_POC_REMOVE_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM); + } + } +} + + +void RequesterNodeConfig::RemoveAvalonWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_REMOVE_AVALON_WORKER_PARAM_MIN) + { + AddOutput(CFL_POC_REMOVE_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + + RequesterProcessor p; + ByteArray worker_vkey = in_work_order_data[CFL_POC_REMOVE_WORKER_PINDEX_WORKER_VKEY].decrypted_data; + worker_vkey = TransformBase64ByteArray(worker_vkey); + ByteArray nonce = in_work_order_data[CFL_POC_REMOVE_WORKER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + + ByteArray data_owner_vkey; + + int err_code = CFL_POC_E_OP_OK; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (worker_map.find(worker_vkey) == worker_map.end()) + { + err_code = CFL_POC_E_WORKER_ID; + } + else if (worker_map[worker_vkey].data_owner_vkey != data_owner_vkey) + { + err_code = CFL_POC_E_AUTH; + } + else if(p.IsWorkerActive(worker_vkey)) + { + err_code = CFL_POC_E_WORKER_BUSY; + } + else + { + worker_map.erase(worker_vkey); + } + AddOutput(CFL_POC_REMOVE_WORKER_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + nodeConfig.AddNonce(CFL_POC_REMOVE_WORKER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + +} + + +void RequesterNodeConfig::RemoveGrapheneWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_REMOVE_GRAPHENE_WORKER_PARAM_MIN) + { + AddOutput(CFL_POC_REMOVE_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + + RequesterProcessor p; + ByteArray worker_vkey = in_work_order_data[CFL_POC_REMOVE_WORKER_PINDEX_WORKER_VKEY].decrypted_data; + worker_vkey = TransformBase64ByteArray(worker_vkey); + ByteArray nonce = in_work_order_data[CFL_POC_REMOVE_WORKER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray parent_vkey = in_work_order_data[CFL_POC_REMOVE_WORKER_PINDEX_PARENT_VKEY].decrypted_data; + parent_vkey = TransformBase64ByteArray(parent_vkey); + + ByteArray data_owner_vkey; + + int err_code = CFL_POC_E_OP_OK; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (worker_map.find(parent_vkey) == worker_map.end()) + { + err_code = CFL_POC_E_WORKER_ID; + } + else if (worker_map[parent_vkey].data_owner_vkey != data_owner_vkey) + { + err_code = CFL_POC_E_AUTH; + } + else if(p.IsWorkerActive(worker_vkey)) + { + err_code = CFL_POC_E_WORKER_BUSY; + } + else + { + worker_map[parent_vkey].children.erase(worker_vkey); + } + AddOutput(CFL_POC_REMOVE_WORKER_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + nodeConfig.AddNonce(CFL_POC_REMOVE_WORKER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } +} + + +void RequesterNodeConfig::UpdateGrapheneWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_UPDATE_WORKER_PARAM_MIN) + { + AddOutput(CFL_POC_UPDATE_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + + RequesterProcessor p; + ByteArray worker_vkey = in_work_order_data[CFL_POC_UPDATE_WORKER_PINDEX_WORKER_VKEY].decrypted_data; + worker_vkey = TransformBase64ByteArray(worker_vkey); + ByteArray nonce = in_work_order_data[CFL_POC_UPDATE_WORKER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray parent_vkey = in_work_order_data[CFL_POC_UPDATE_WORKER_PINDEX_PARENT_VKEY].decrypted_data; + parent_vkey = TransformBase64ByteArray(parent_vkey); + + ByteArray data_owner_vkey; + + int err_code = CFL_POC_E_OP_OK; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (worker_map.find(parent_vkey) == worker_map.end()) + { + err_code = CFL_POC_E_WORKER_ID; + } + else if (worker_map[parent_vkey].data_owner_vkey != data_owner_vkey) + { + err_code = CFL_POC_E_AUTH; + } + else if(p.IsWorkerActive(worker_vkey)) + { + err_code = CFL_POC_E_WORKER_BUSY; + } + else + { + auto& worker = worker_map[parent_vkey].children[worker_vkey]; + ByteArray extra_specs = in_work_order_data[CFL_POC_UPDATE_WORKER_PINDEX_EXTRA_SPECS].decrypted_data; + worker.extra_specs = extra_specs; + } + AddOutput(CFL_POC_UPDATE_WORKER_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + nodeConfig.AddNonce(CFL_POC_UPDATE_WORKER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } +} + + + +void RequesterNodeConfig::LookupWorkers(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_LOOKUP_WORKER_PARAM_MIN) + { + AddOutput(CFL_POC_LOOKUP_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + ByteArray nonce = in_work_order_data[CFL_POC_LOOKUP_WORKER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + AddOutput(CFL_POC_LOOKUP_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_LOOKUP_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + } + else if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_LOOKUP_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else + { + std::string worker_info = TranslateWorkerInfo(); + AddOutput(CFL_POC_LOOKUP_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + AddOutput(CFL_POC_LOOKUP_WORKER_RINDEX_RESULT, out_work_order_data, worker_info); + nodeConfig.AddNonce(CFL_POC_LOOKUP_WORKER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + + } + +} + + +void RequesterNodeConfig::AddAvalonWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_ADD_AVALON_WORKER_PARAM_MIN) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + ByteArray id = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_ID].decrypted_data; + id = TransformHexByteArray(id); + ByteArray worker_mrenclave = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_MRENCLAVE].decrypted_data; + worker_mrenclave = TransformHexByteArray(worker_mrenclave); + ByteArray worker_mrsigner = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_MRSIGNER].decrypted_data; + ByteArray worker_vkey = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_WORKER_VKEY].decrypted_data; + worker_vkey = TransformBase64ByteArray(worker_vkey); + ByteArray nonce = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + + ByteArray data_owner_vkey; + + int err_code = CFL_POC_E_OP_OK; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + auto search = worker_map.find(worker_vkey); + + if (search != worker_map.end()) + { + if (worker_map[worker_vkey].data_owner_vkey != data_owner_vkey) + { + err_code = CFL_POC_E_WORKER_ID; + } + else + { + worker_map[worker_vkey].worker_mrenclave = worker_mrenclave; + worker_map[worker_vkey].worker_mrsigner = worker_mrsigner; + worker_map[worker_vkey].worker_vkey = worker_vkey; + } + } + else + { + AvalonWorker worker; + + worker.id = id; + worker.data_owner_vkey = data_owner_vkey; + worker.worker_mrenclave = worker_mrenclave; + worker.worker_mrsigner = worker_mrsigner; + //TODO Avalon worker verification is not enabled by now. + //Set isv prod id and isv svn to fake values. + worker.isv_prod_id = -1; + worker.isv_svn = -1; + worker.worker_vkey = worker_vkey; + worker_map[worker_vkey] = worker; + } + } + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + nodeConfig.AddNonce(CFL_POC_ADD_WORKER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } +} + + +void RequesterNodeConfig::AddGrapheneWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_ADD_GRAPHENE_WORKER_PARAM_MIN) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + + ByteArray nonce = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray indata = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_INDATA].decrypted_data; + ByteArray parent_vkey = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_PARENT_VKEY].decrypted_data; + parent_vkey = TransformBase64ByteArray(parent_vkey); + + ByteArray data_owner_vkey; + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + return; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + auto search = worker_map.find(parent_vkey); + if (search == worker_map.end()) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_WORKER_ID); + return; + } + + AvalonWorker& parent = worker_map[parent_vkey]; + if (parent.data_owner_vkey != data_owner_vkey) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + ByteArray session_key = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_SESSION_KEY].decrypted_data; + session_key = TransformHexByteArray(session_key); + ByteArray session_iv = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_SESSION_IV].decrypted_data; + session_iv = TransformHexByteArray(session_iv); + + indata = TransformBase64ByteArray(indata); + indata = tcf::crypto::skenc::DecryptMessage(session_key, session_iv, indata); + /*code */ + ByteArray hash2; + hash2 = tcf::crypto::ComputeMessageHash(indata); + + ByteArray hash1 = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_HASH1].decrypted_data; + ByteArray concat_hash; + concat_hash.insert(concat_hash.end(),hash1.begin(),hash1.end()); + concat_hash.insert(concat_hash.end(),hash2.begin(),hash2.end()); + ByteArray final_hash; + final_hash = tcf::crypto::ComputeMessageHash(concat_hash); + + using tcf::crypto::sig::PublicKey; + std::string vk_block = cfl::VerificationKeyBlockFromByteArray(parent_vkey); + PublicKey public_key = PublicKey(vk_block); + ByteArray parent_sig = in_work_order_data[CFL_POC_ADD_WORKER_PINDEX_PARENT_SIGNATURE].decrypted_data; + parent_sig = TransformBase64ByteArray(parent_sig); + if(public_key.VerifySignature(final_hash, parent_sig) != 0) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + /*code*/ + std::string indata_string = ByteArrayToString(indata); + std::vector indata_array; + Split(indata_string, indata_array); + + if (indata_array.size() != CFL_POC_SETUP_DO_WORKER_RINDEX_SIZE) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + return; + } + if (indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_STATUS] != "0") + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + return; + } + if (indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_OP] != CFL_POC_OP_ADD_WORKER) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_CODE); + return; + } + std::string indata_nonce_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_REQ_NONCE]; + ByteArray indata_nonce = HexEncodedStringToByteArray(indata_nonce_string); + if (indata_nonce != nonce) + { + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + return; + } + + std::string indata_id_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_ID]; + std::string indata_mrenclave_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_MRENCLAVE]; + std::string indata_mrsigner_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_MRSIGNER]; + std::string indata_prodid_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_ISV_PROD_ID]; + std::string indata_svn_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_ISV_SVN]; + std::string indata_vkey_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_VKEY]; + std::string indata_ekey_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_EKEY]; + std::string indata_address_string = indata_array[CFL_POC_SETUP_DO_WORKER_RINDEX_ADDRESS]; + + ByteArray indata_id = HexEncodedStringToByteArray(indata_id_string); + ByteArray indata_mrenclave = HexEncodedStringToByteArray(indata_mrenclave_string); + ByteArray indata_mrsigner = HexEncodedStringToByteArray(indata_mrsigner_string); + int indata_prod_id = std::stoi(indata_prodid_string); + int indata_svn = std::stoi(indata_svn_string); + ByteArray indata_vkey = Base64EncodedStringToByteArray(indata_vkey_string); + ByteArray indata_ekey = Base64EncodedStringToByteArray(indata_ekey_string); + ByteArray indata_address(indata_address_string.begin(), indata_address_string.end()); + + auto& graphenes = parent.children; + if (graphenes.find(indata_vkey) != graphenes.end()) + { + GrapheneWorker& g = graphenes[indata_id]; + g.worker_mrenclave = indata_mrenclave; + g.worker_mrsigner = indata_mrsigner; + g.isv_prod_id = indata_prod_id; + g.isv_svn = indata_svn; + g.worker_ekey = indata_ekey; + g.worker_addr = indata_address; + } + else + { + GrapheneWorker g; + g.id = indata_id; + g.worker_mrenclave = indata_mrenclave; + g.worker_mrsigner = indata_mrsigner; + g.isv_prod_id = indata_prod_id; + g.isv_svn = indata_svn; + g.worker_vkey = indata_vkey; + g.worker_ekey = indata_ekey; + g.worker_addr = indata_address; + graphenes[indata_vkey] = g; + } + + AddOutput(CFL_POC_ADD_WORKER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + nodeConfig.AddNonce(CFL_POC_ADD_WORKER_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + +} + + +void RequesterNodeConfig::AddDataset(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_ADD_DATASET_PARAM_MIN) + { + AddOutput(CFL_POC_ADD_DATASET_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray dataset_id = in_work_order_data[CFL_POC_ADD_DATASET_PINDEX_ID].decrypted_data; + ByteArray dataset_ek = in_work_order_data[CFL_POC_ADD_DATASET_PINDEX_EK].decrypted_data; + dataset_ek = TransformBase64ByteArray(dataset_ek); + ByteArray worker_mrenclave = in_work_order_data[CFL_POC_ADD_DATASET_PINDEX_MRENCLAVE].decrypted_data; + worker_mrenclave = TransformHexByteArray(worker_mrenclave); + ByteArray worker_mrsigner = in_work_order_data[CFL_POC_ADD_DATASET_PINDEX_MRSIGNER].decrypted_data; //TODO: place holder + ByteArray worker_vkey = in_work_order_data[CFL_POC_ADD_DATASET_PINDEX_WORKER_VKEY].decrypted_data; + worker_vkey = TransformBase64ByteArray(worker_vkey); + ByteArray nonce = in_work_order_data[CFL_POC_ADD_DATASET_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + auto search = dataset_map.find(dataset_id); + + if (search != dataset_map.end()) + { + if (dataset_map[dataset_id].data_owner_vkey != data_owner_vkey) + { + err_code = CFL_POC_E_DATASET_ID; + } + else + { + dataset_map[dataset_id].data_ek = dataset_ek; + dataset_map[dataset_id].worker_mrenclave = worker_mrenclave; + dataset_map[dataset_id].worker_mrsigner = worker_mrsigner; + dataset_map[dataset_id].worker_vkey = worker_vkey; + } + } + else + { + DatasetConfig dataset; + + dataset.id = dataset_id; + dataset.data_owner_vkey = data_owner_vkey; + dataset.data_ek = dataset_ek; + dataset.worker_mrenclave = worker_mrenclave; + dataset.worker_mrsigner = worker_mrsigner; + dataset.worker_vkey = worker_vkey; + + dataset_map[dataset_id] = dataset; + } + } + AddOutput(CFL_POC_ADD_DATASET_RINDEX_STATUS, out_work_order_data, err_code); + } +} + + +std::string RequesterNodeConfig::AvailableDatasets(const ByteArray& user_vkey) +{ + std::string json = ""; + int found = 0; + + for (auto iter = dataset_map.begin(); iter != dataset_map.end(); iter++) + { + const DatasetConfig& dataset = iter->second; + const ByteArray& data_owner_vkey = dataset.data_owner_vkey; + + if (user_map.find(data_owner_vkey) == user_map.end()) + { + continue; + } + + auto& users = user_map[data_owner_vkey]; + if(users.find(user_vkey) == users.end()) + { + continue; + } + + if (found == 0) + { + json += TranslateDataset(dataset); + } + else { + json += "," + TranslateDataset(dataset); + } + + found++; + + } + + return "[" + json + "]"; +} + + + +void RequesterNodeConfig::RemoveDataset(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_REMOVE_DATASET_PARAM_MIN) + { + AddOutput(CFL_POC_REMOVE_DATASET_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray dataset_id = in_work_order_data[CFL_POC_REMOVE_DATASET_PINDEX_ID].decrypted_data; + ByteArray nonce = in_work_order_data[CFL_POC_REMOVE_DATASET_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + auto search = dataset_map.find(dataset_id); + + if (search != dataset_map.end()) + { + if (dataset_map[dataset_id].data_owner_vkey == data_owner_vkey) + { + dataset_map.erase(dataset_id); + } + else + { + err_code = CFL_POC_E_AUTH; + } + } + } + AddOutput(CFL_POC_REMOVE_DATASET_RINDEX_STATUS, out_work_order_data, err_code); + } +} + + +void RequesterNodeConfig::LookupDatasets(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_LOOKUP_DATASET_PARAM_MIN) + { + AddOutput(CFL_POC_LOOKUP_DATASET_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + ByteArray nonce = in_work_order_data[CFL_POC_LOOKUP_DATASET_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + AddOutput(CFL_POC_LOOKUP_DATASET_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + AddOutput(CFL_POC_LOOKUP_DATASET_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_LOOKUP_DATASET_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else + { + std::string json = TranslateDatasets(data_owner_vkey); + AddOutput(CFL_POC_LOOKUP_DATASET_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + AddOutput(CFL_POC_LOOKUP_DATASET_RINDEX_RESULT, out_work_order_data, json); + } + } +} + + +void RequesterNodeConfig::AddUser(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_ADD_USER_PARAM_MIN) + { + AddOutput(CFL_POC_ADD_USER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray user_vkey = in_work_order_data[CFL_POC_ADD_USER_PINDEX_VKEY].decrypted_data; + user_vkey = TransformBase64ByteArray(user_vkey); + ByteArray nonce = in_work_order_data[CFL_POC_ADD_USER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + auto search = user_map.find(data_owner_vkey); + + if (search != user_map.end()) + { + user_map[data_owner_vkey][user_vkey] = 1; + } + else + { + std::map users; + users[user_vkey] = 1; + user_map[data_owner_vkey] = users; + } + } + AddOutput(CFL_POC_ADD_DATASET_RINDEX_STATUS, out_work_order_data, err_code); + } +} + + +void RequesterNodeConfig::RemoveUser(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_REMOVE_USER_PARAM_MIN) + { + AddOutput(CFL_POC_REMOVE_USER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray user_vkey = in_work_order_data[CFL_POC_REMOVE_USER_PINDEX_VKEY].decrypted_data; + user_vkey = TransformBase64ByteArray(user_vkey); + ByteArray nonce = in_work_order_data[CFL_POC_REMOVE_USER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + auto search = user_map.find(data_owner_vkey); + + if (search != user_map.end()) + { + user_map.erase(user_vkey); + } + } + AddOutput(CFL_POC_REMOVE_USER_RINDEX_STATUS, out_work_order_data, err_code); + } +} + + +void RequesterNodeConfig::LookupUsers(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_LOOKUP_USER_PARAM_MIN) + { + AddOutput(CFL_POC_LOOKUP_USER_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray nonce = in_work_order_data[CFL_POC_LOOKUP_USER_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + std::string json = TranslateUserVKeys(data_owner_vkey); + AddOutput(CFL_POC_LOOKUP_USER_RINDEX_STATUS, out_work_order_data, err_code); + AddOutput(CFL_POC_LOOKUP_USER_RINDEX_RESULT, out_work_order_data, json); + + } + } +} + + +bool RequesterNodeConfig::GetDatasetByVkey(const ByteArray& user_vkey, const ByteArray& dataset_id, ByteArray& dataset_ek) +{ + bool ret_val = false; + + auto search = dataset_map.find(dataset_id); + + if (search != dataset_map.end()) + { + ByteArray dataset_owner_vkey = dataset_map[dataset_id].data_owner_vkey; + + auto search = user_map.find(dataset_owner_vkey); + + if (search != user_map.end()) + { + auto search = user_map[dataset_owner_vkey].find(user_vkey); + + if (search != user_map[dataset_owner_vkey].end()) + { + ret_val = true; + dataset_ek = dataset_map[dataset_id].data_ek; + } + } + } + + return ret_val; +} + + +bool RequesterNodeConfig::CheckDataOwner(ExWorkorderInfo* wo_info, ByteArray& data_owner_vkey) +{ + return nodeConfig.CheckDataOwner(wo_info, data_owner_vkey); +} + + + +bool RequesterNodeConfig::CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey) +{ + return nodeConfig.CheckNonce(nonce, data_owner_vkey); +} + + +bool RequesterNodeConfig::VerifyWorkorderSignature(ExWorkorderInfo* exWorkorderInfo) +{ + + return exWorkorderInfo->VerifyWorkorderSignature(); +} + + +std::string RequesterNodeConfig::TranslateDatasets(const ByteArray& data_owner_vkey) +{ + std::string json = ""; + int found = 0; + for (auto iter = dataset_map.begin(); iter != dataset_map.end(); iter++) + { + const DatasetConfig& d = iter->second; + if (d.data_owner_vkey != data_owner_vkey) + { + continue; + } + + if (found == 0) + { + json += TranslateDataset(d); + } + else { + json += "," + TranslateDataset(d); + } + found++; + } + + return "[" + json + "]"; +} + + +std::string RequesterNodeConfig::TranslateDataset(const DatasetConfig& d) +{ + std::string json = "{"; + + json += "\"dataset_id\":\"" + ByteArrayToString(d.id) + "\","; + json += "\"dataset_ek\":\"" + ByteArrayToBase64EncodedString(d.data_ek) + "\","; + json += "\"mrenclave\":\"" + ByteArrayToHexEncodedString(d.worker_mrenclave) + "\","; + //TODO: just a placeholder here + json += "\"mrsigner\":\"\","; + json += "\"worker_vkey\":\"" + ByteArrayToBase64EncodedString(d.worker_vkey) + "\"}"; + + return json; +} + + +std::string RequesterNodeConfig::TranslateUserVKeys(const ByteArray& data_owner_vkey) +{ + std::string json = ""; + if (user_map.find(data_owner_vkey) != user_map.end()) + { + std::map& users = user_map[data_owner_vkey]; + int found = 0; + for (auto iter = users.begin(); iter != users.end(); iter++) + { + const ByteArray& vkey_byte = iter->first; + std::string vkey_string = ByteArrayToBase64EncodedString(vkey_byte); + if (found == 0) + { + json += "\"" + vkey_string + "\""; + } + else + { + json += ",\"" + vkey_string + "\""; + } + found++; + } + } + return "[" + json + "]"; +} + + +std::string RequesterNodeConfig::TranslateWorkerInfo() +{ + std::string json = ""; + bool first = true; + for (auto it = worker_map.begin(); it != worker_map.end(); it++) + { + if (first) + { + json += TranslateAvalonWorker(it->second); + } + else + { + json += "," + TranslateAvalonWorker(it->second); + } + first = false; + } + return "[" + json + "]"; +} + + +std::string RequesterNodeConfig::TranslateAvalonWorker(const AvalonWorker& worker) +{ + std::string json = "{"; + json += "\"id\":\"" + ByteArrayToHexEncodedString(worker.id) + "\","; + json += "\"mrenclave\":\"" + ByteArrayToHexEncodedString(worker.worker_mrenclave) + "\","; + json += "\"mrsigner\":\"" + ByteArrayToString(worker.worker_mrsigner) + "\","; + json += "\"isv_prod_id\":" + std::to_string(worker.isv_prod_id) + ","; + json += "\"isv_svn\":" + std::to_string(worker.isv_svn) + ","; + json += "\"verification_key\":\"" + ByteArrayToBase64EncodedString(worker.worker_vkey) + "\","; + json += "\"data_owner_vkey\":\"" + ByteArrayToBase64EncodedString(worker.data_owner_vkey) + "\","; + json += "\"children\":" + TranslateGrapheneWorker(worker.children, worker) + "}"; + return json; +} + + +std::string RequesterNodeConfig::TranslateGrapheneWorker(const std::map& workers, const AvalonWorker& parent) +{ + std::string json = ""; + bool first = true; + for (auto it = workers.begin(); it != workers.end(); it++) + { + if (first) + { + json += TranslateGrapheneWorker(it->second, parent); + } + else + { + json += "," + TranslateGrapheneWorker(it->second, parent); + } + first = false; + } + return "[" + json + "]"; +} + + +std::string RequesterNodeConfig::TranslateGrapheneWorker(const GrapheneWorker& worker, const AvalonWorker& parent) +{ + std::string json = "{"; + json += "\"id\":\"" + ByteArrayToHexEncodedString(worker.id) + "\","; + json += "\"mrenclave\":\"" + ByteArrayToHexEncodedString(worker.worker_mrenclave) + "\","; + json += "\"mrsigner\":\"" + ByteArrayToHexEncodedString(worker.worker_mrsigner) + "\","; + json += "\"isv_prod_id\":" + std::to_string(worker.isv_prod_id) + ","; + json += "\"isv_svn\":" + std::to_string(worker.isv_svn) + ","; + json += "\"verification_key\":\"" + ByteArrayToBase64EncodedString(worker.worker_vkey) + "\","; + json += "\"encryption_key\":\"" + ByteArrayToBase64EncodedString(worker.worker_ekey) + "\","; + json += "\"parent_id\":\"" + ByteArrayToHexEncodedString(parent.id) + "\","; + json += "\"data_owner_vkey\":\"" + ByteArrayToBase64EncodedString(parent.data_owner_vkey) + "\","; + json += "\"address\":\"" + ByteArrayToString(worker.worker_addr) + "\","; + json += "\"extra_specs\":\"" + ByteArrayToString(worker.extra_specs) + "\"}"; + return json; +} + + +bool RequesterNodeConfig::CheckUserVkey(const ByteArray& user_vkey) +{ + for (auto iter = worker_map.begin(); iter != worker_map.end(); iter++) + { + auto& graphenes = iter->second.children; + if (graphenes.find(user_vkey) != graphenes.end()) + { + return true; + } + } + return false; +} + +bool RequesterNodeConfig::CheckAvalonWorkerOwner(const ByteArray& avalon_vkey, const ByteArray& data_owner_vkey) +{ + if (worker_map.find(avalon_vkey) == worker_map.end()) + { + return false; + } + return worker_map[avalon_vkey].data_owner_vkey == data_owner_vkey; +} + +bool RequesterNodeConfig::CheckGrapheneWorkerParent(const ByteArray& graphene_vkey, const ByteArray& avalon_vkey) +{ + if (worker_map.find(avalon_vkey) == worker_map.end()) + { + return false; + } + auto& graphenes = worker_map[avalon_vkey].children; + return graphenes.find(graphene_vkey) != graphenes.end(); + +} + +} // namespace CflPocRequester + + diff --git a/examples/apps/data_owner/workload/requester-node-config.h b/examples/apps/data_owner/workload/requester-node-config.h new file mode 100644 index 000000000..2762a7c5a --- /dev/null +++ b/examples/apps/data_owner/workload/requester-node-config.h @@ -0,0 +1,126 @@ +#pragma once + +#include +#include "cfl-utils.h" +#include "cfl-poc-defs.h" +#include "requester-node-logic.h" + +namespace CflPocRequester { + +const size_t VERIFICATION_KEY_SIZE = 88; + +// The class below is a placeholder to be extended later + +// TODO: hardcode const data owner verification keys to use for RequesterNodeConfig::setting up data_owner_vkeys + +class RequesterNodeConfig +{ +public: + friend RequesterProcessor; + + + RequesterNodeConfig() { } + + virtual ~RequesterNodeConfig() { } + + virtual void AddWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void RemoveWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void LookupWorkers(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void UpdateGrapheneWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void AddDataset(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void RemoveDataset(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void LookupDatasets(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void AddUser(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void RemoveUser(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void LookupUsers(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual bool GetDatasetByVkey(const ByteArray& user_vkey, const ByteArray& dataset_id, ByteArray& dataset_ek); + + virtual bool CheckUserVkey(const ByteArray& user_vkey); + + virtual bool CheckAvalonWorkerOwner(const ByteArray& avalon_vkey, const ByteArray& data_owner_vkey); + + virtual bool CheckGrapheneWorkerParent(const ByteArray& graphene_vkey, const ByteArray& avalon_vkey); + + virtual std::string AvailableDatasets(const ByteArray& user_vkey); + + virtual bool GetDatasetByWorkerAttastation(const ByteArray& attestation, const ByteArray& dataset_id, ByteArray& dataset_ek) + { + // TODO: add impleentation + return false; + }; + + +protected: + virtual bool CheckDataOwner(ExWorkorderInfo* wo_info, ByteArray& data_owner_vkey); + + virtual bool CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey); + + virtual bool VerifyWorkorderSignature(ExWorkorderInfo* exWorkorderInfo); + + virtual std::string TranslateDatasets(const ByteArray& data_owner_vkey); + + virtual std::string TranslateUserVKeys(const ByteArray& data_owner_vkey); + + std::string TranslateDataset(const cfl::DatasetConfig& d); + + virtual void AddAvalonWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void AddGrapheneWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void RemoveAvalonWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void RemoveGrapheneWorker(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual std::string TranslateWorkerInfo(); + + virtual std::string TranslateAvalonWorker(const cfl::AvalonWorker& worker); + + virtual std::string TranslateGrapheneWorker(const std::map& workers, const cfl::AvalonWorker& parent); + + virtual std::string TranslateGrapheneWorker(const cfl::GrapheneWorker& worker, const cfl::AvalonWorker& parent); + + + std::map dataset_map; + std::map> user_map; + std::map worker_map; +}; + +} //namespace CflPocRequester diff --git a/examples/apps/data_owner/workload/requester-node-logic.cpp b/examples/apps/data_owner/workload/requester-node-logic.cpp new file mode 100644 index 000000000..cac4ef56d --- /dev/null +++ b/examples/apps/data_owner/workload/requester-node-logic.cpp @@ -0,0 +1,900 @@ +#include "requester-node-logic.h" +#include "requester-node-config.h" +#include "node-config.h" +#include "cfl-utils.h" + +namespace cfl { + +extern NodeConfig nodeConfig; + +} + +using namespace cfl; + +namespace CflPocRequester { + +std::map RequesterProcessor::workflow_map; +RequesterNodeConfig requesterNodeConfig; + +void RequesterProcessor::CreateWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_CREATE_WORKFLOW_PARAM_MIN) + { + AddOutput(CFL_POC_CREATE_WORKFLOW_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray workflow_id; + + ByteArray nonce = in_work_order_data[CFL_POC_CREATE_WORKFLOW_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!AddWorkflow(data_owner_vkey, workflow_id)) + { + err_code = CFL_POC_E_NONCE; + } + + AddOutput(CFL_POC_CREATE_WORKFLOW_RINDEX_STATUS, out_work_order_data, err_code); + if (!err_code) + { + std::string wid_str = ByteArrayToHexEncodedString(workflow_id); + AddOutput(CFL_POC_CREATE_WORKFLOW_RINDEX_ID, out_work_order_data, wid_str); + nodeConfig.AddNonce(CFL_POC_CREATE_WORKFLOW_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + } +} + +void RequesterProcessor::JoinWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_JOIN_WORKFLOW_PARAM_MIN) + { + AddOutput(CFL_POC_JOIN_WORKFLOW_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray workflow_id = in_work_order_data[CFL_POC_JOIN_WORKFLOW_PINDEX_WORKFLOW_ID].decrypted_data; + workflow_id = TransformHexByteArray(workflow_id); + + ByteArray nonce = in_work_order_data[CFL_POC_JOIN_WORKFLOW_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (workflow_map.find(workflow_id) == workflow_map.end()) + { + err_code = CFL_POC_E_WORKFLOW_ID; + } + else if (workflow_map[workflow_id].status != CFL_POC_WORKFLOW_WAITING) + { + err_code = CFL_POC_E_WORKFLOW_STATUS; + } + else + { + ByteArray graphene_vkey = in_work_order_data[CFL_POC_JOIN_WORKFLOW_PINDEX_WORKER_VKEY].decrypted_data; + graphene_vkey = TransformBase64ByteArray(graphene_vkey); + ByteArray avalon_vkey = in_work_order_data[CFL_POC_JOIN_WORKFLOW_PINDEX_PARENT_VKEY].decrypted_data; + avalon_vkey = TransformBase64ByteArray(avalon_vkey); + if (!requesterNodeConfig.CheckAvalonWorkerOwner(avalon_vkey, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!requesterNodeConfig.CheckGrapheneWorkerParent(graphene_vkey, avalon_vkey)) + { + err_code = CFL_POC_E_WORKER_ID; + } + else + { + workflow_map[workflow_id].joined_workers[graphene_vkey] = avalon_vkey; + } + + } + + AddOutput(CFL_POC_JOIN_WORKFLOW_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + nodeConfig.AddNonce(CFL_POC_JOIN_WORKFLOW_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + } +} + + +void RequesterProcessor::QuitWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_QUIT_WORKFLOW_PARAM_MIN) + { + AddOutput(CFL_POC_QUIT_WORKFLOW_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray workflow_id = in_work_order_data[CFL_POC_QUIT_WORKFLOW_PINDEX_WORKFLOW_ID].decrypted_data; + workflow_id = TransformHexByteArray(workflow_id); + + ByteArray nonce = in_work_order_data[CFL_POC_QUIT_WORKFLOW_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (workflow_map.find(workflow_id) == workflow_map.end()) + { + err_code = CFL_POC_E_WORKFLOW_ID; + } + else if (workflow_map[workflow_id].status != CFL_POC_WORKFLOW_WAITING) + { + err_code = CFL_POC_E_WORKFLOW_STATUS; + } + else + { + ByteArray graphene_vkey = in_work_order_data[CFL_POC_QUIT_WORKFLOW_PINDEX_WORKER_VKEY].decrypted_data; + graphene_vkey = TransformBase64ByteArray(graphene_vkey); + ByteArray avalon_vkey = in_work_order_data[CFL_POC_QUIT_WORKFLOW_PINDEX_PARENT_VKEY].decrypted_data; + avalon_vkey = TransformBase64ByteArray(avalon_vkey); + if (!requesterNodeConfig.CheckAvalonWorkerOwner(avalon_vkey, data_owner_vkey) && + workflow_map[workflow_id].data_owner_vkey != data_owner_vkey) + { + err_code = CFL_POC_E_AUTH; + } + else if (!requesterNodeConfig.CheckGrapheneWorkerParent(graphene_vkey, avalon_vkey)) + { + err_code = CFL_POC_E_WORKER_ID; + } + else + { + workflow_map[workflow_id].joined_workers.erase(graphene_vkey); + } + } + + AddOutput(CFL_POC_QUIT_WORKFLOW_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + nodeConfig.AddNonce(CFL_POC_QUIT_WORKFLOW_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + } +} + + +void RequesterProcessor::LookupWorkflows(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + ByteArray vkey; + bool is_data_owner = CheckDataOwner(wo_info, vkey); + + if (!is_data_owner && !requesterNodeConfig.CheckUserVkey(vkey)) + { + AddOutput(CFL_POC_LOOKUP_WORKFLOWS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else if (in_work_order_data.size() < CFL_POC_LOOKUP_WORKFLOWS_PARAM_MIN) + { + AddOutput(CFL_POC_LOOKUP_WORKFLOWS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + ByteArray nonce = in_work_order_data[CFL_POC_LOOKUP_WORKFLOWS_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + + if (!CheckNonce(nonce, vkey)) + { + AddOutput(CFL_POC_LOOKUP_WORKFLOWS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_NONCE); + } + else if (!VerifyWorkorderSignature(wo_info)) + { + AddOutput(CFL_POC_LOOKUP_WORKFLOWS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_AUTH); + } + else + { + AddOutput(CFL_POC_LOOKUP_WORKFLOWS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_OP_OK); + std::string workflow_info; + if (is_data_owner) + { + workflow_info = TranslateWorkflowInfo(); + } + else + { + workflow_info = TranslateWorkflowInfo(vkey); + } + AddOutput(CFL_POC_LOOKUP_WORKFLOWS_RINDEX_RESULT, out_work_order_data, workflow_info); + nodeConfig.AddNonce(CFL_POC_LOOKUP_WORKFLOWS_RINDEX_NONCE, out_work_order_data, vkey); + } + } +} + +void RequesterProcessor::GetWorkflowResult(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_WORKFLOW_RESULT_PARAM_MIN) + { + AddOutput(CFL_POC_WORKFLOW_RESULT_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray workflow_id = in_work_order_data[CFL_POC_WORKFLOW_RESULT_PINDEX_ID].decrypted_data; + ByteArray user_vkey; + ByteArray result; + + if (!CheckUser(wo_info, workflow_id, user_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + AggregateData(workflow_id, result); + } + + AddOutput(CFL_POC_WORKFLOW_RESULT_RINDEX_STATUS, out_work_order_data, err_code); + if (!err_code) + { + AddOutput(CFL_POC_WORKFLOW_RESULT_RINDEX_RESULT, out_work_order_data, result); + } + } +} + + +void RequesterProcessor::RemoveWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_REMOVE_WORKFLOW_PARAM_MIN) + { + AddOutput(CFL_POC_REMOVE_WORKFLOW_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + + ByteArray nonce = in_work_order_data[CFL_POC_REMOVE_WORKFLOW_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray workflow_id = in_work_order_data[CFL_POC_REMOVE_WORKFLOW_PINDEX_ID].decrypted_data; + workflow_id = TransformHexByteArray(workflow_id); + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (workflow_map.find(workflow_id) == workflow_map.end()) + { + err_code = CFL_POC_E_WORKFLOW_ID; + } + else if (workflow_map[workflow_id].data_owner_vkey != data_owner_vkey) + { + err_code = CFL_POC_E_AUTH; + } + if (!err_code) + { + workflow_map.erase(workflow_id); + } + AddOutput(CFL_POC_REMOVE_WORKFLOW_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + nodeConfig.AddNonce(CFL_POC_REMOVE_WORKFLOW_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + } +} + + +void RequesterProcessor::UpdateWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_REMOVE_WORKFLOW_PARAM_MIN) + { + AddOutput(CFL_POC_UPDATE_WORKFLOW_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + + ByteArray nonce = in_work_order_data[CFL_POC_UPDATE_WORKFLOW_PINDEX_NONCE].decrypted_data; + nonce = TransformHexByteArray(nonce); + ByteArray workflow_id = in_work_order_data[CFL_POC_UPDATE_WORKFLOW_PINDEX_ID].decrypted_data; + workflow_id = TransformHexByteArray(workflow_id); + + ByteArray status_bytes = in_work_order_data[CFL_POC_UPDATE_WORKFLOW_PINDEX_STATUS].decrypted_data; + std::string status_str = ByteArrayToString(status_bytes); + int status = std::stoi(status_str); + + ByteArray data_owner_vkey; + + if (!CheckDataOwner(wo_info, data_owner_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckNonce(nonce, data_owner_vkey)) + { + err_code = CFL_POC_E_NONCE; + } + else if (!VerifyWorkorderSignature(wo_info)) + { + err_code = CFL_POC_E_AUTH; + } + else if (workflow_map.find(workflow_id) == workflow_map.end()) + { + err_code = CFL_POC_E_WORKFLOW_ID; + } + else if (workflow_map[workflow_id].data_owner_vkey != data_owner_vkey) + { + err_code = CFL_POC_E_AUTH; + } + if (!err_code) + { + workflow_map[workflow_id].status = status; + } + AddOutput(CFL_POC_UPDATE_WORKFLOW_RINDEX_STATUS, out_work_order_data, err_code); + if (err_code == CFL_POC_E_OP_OK) + { + nodeConfig.AddNonce(CFL_POC_UPDATE_WORKFLOW_RINDEX_NONCE, out_work_order_data, data_owner_vkey); + } + + } +} + + + +void RequesterProcessor::AvailableDatasets(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_AVAILABLE_DATASETS_PARAM_MIN) + { + AddOutput(CFL_POC_AVAILABLE_DATASETS_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray user_vkey; + + if (!GetUserVkey(wo_info, user_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + + AddOutput(CFL_POC_AVAILABLE_DATASETS_RINDEX_STATUS, out_work_order_data, err_code); + + if (!err_code) + { + std::string datasets = requesterNodeConfig.AvailableDatasets(user_vkey); + AddOutput(CFL_POC_AVAILABLE_DATASETS_RINDEX_RESULT, out_work_order_data, datasets); + } + } +} + + + +void RequesterProcessor::CreateNonceRequest(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_DO_NONCE_RQST_PARAM_MIN) + { + AddOutput(CFL_POC_DO_NONCE_RQST_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray attestation_data = in_work_order_data[CFL_POC_DO_NONCE_RQST_PINDEX_ATT_DATA].decrypted_data; + ByteArray workflow_id = in_work_order_data[CFL_POC_DO_NONCE_RQST_PINDEX_WORKFLOW_ID].decrypted_data; + ByteArray dataset_id = in_work_order_data[CFL_POC_DO_NONCE_RQST_PINDEX_DATASET_ID].decrypted_data; + ByteArray user_vkey; + ByteArray json_request; + ByteArray dataset_ek; + + if (!CheckUser(wo_info, workflow_id, user_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckDatasetAccess(workflow_id, user_vkey, dataset_id, dataset_ek)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + err_code = CreateGetNonceWoRequest(wo_info, attestation_data, workflow_id, dataset_id, json_request); + } + + AddOutput(CFL_POC_DO_NONCE_RQST_RINDEX_STATUS, out_work_order_data, err_code); + + if (!err_code) + { + AddOutput(CFL_POC_DO_NONCE_RQST_RINDEX_REQUEST, out_work_order_data, json_request); + } + else + { + workflow_map.erase(workflow_id); + } + } +} + + +void RequesterProcessor::CreateProcessDatasetRequest(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_DO_PROCESS_RQST_PARAM_MIN) + { + AddOutput(CFL_POC_DO_PROCESS_RQST_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray workflow_id = in_work_order_data[CFL_POC_DO_PROCESS_RQST_PINDEX_WORKFLOW_ID].decrypted_data; + ByteArray dataset_id = in_work_order_data[CFL_POC_DO_PROCESS_RQST_PINDEX_DATASET_ID].decrypted_data; + ByteArray query_data = in_work_order_data[CFL_POC_DO_PROCESS_RQST_PINDEX_QUERY_DATA].decrypted_data; + ByteArray json_result = in_work_order_data[CFL_POC_DO_PROCESS_RQST_PINDEX_JSON_RESULT].decrypted_data; + ByteArray user_vkey; + ByteArray json_request; + ByteArray dataset_ek; + + if (!CheckUser(wo_info, workflow_id, user_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else if (!CheckDatasetAccess(workflow_id, user_vkey, dataset_id, dataset_ek)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + ByteArray nonce; + + if (!(err_code = ParseDoNonceResult(wo_info, workflow_id, json_result, nonce))) + { + err_code = CreateProcessDatasetRequest(wo_info, workflow_id, nonce, dataset_id, dataset_ek, query_data, json_request); + } + } + + AddOutput(CFL_POC_DO_PROCESS_RQST_RINDEX_STATUS, out_work_order_data, err_code); + + if (!err_code) + { + AddOutput(CFL_POC_DO_PROCESS_RQST_RINDEX_REQUEST, out_work_order_data, json_request); + } + else + { + workflow_map.erase(workflow_id); + } + } +} + + + +void RequesterProcessor::ProcessDatasetResult(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info) +{ + if (in_work_order_data.size() < CFL_POC_DO_PROCESS_RESP_PARAM_MIN) + { + AddOutput(CFL_POC_DO_PROCESS_RESP_RINDEX_STATUS, out_work_order_data, CFL_POC_E_PARAM_COUNT); + } + else + { + int err_code = CFL_POC_E_OP_OK; + ByteArray workflow_id = in_work_order_data[CFL_POC_DO_PROCESS_RESP_PINDEX_WORKFLOW_ID].decrypted_data; + ByteArray json_result = in_work_order_data[CFL_POC_DO_PROCESS_RESP_PINDEX_JSON_RESULT].decrypted_data; + ByteArray user_vkey; + + if (!CheckUser(wo_info, workflow_id, user_vkey)) + { + err_code = CFL_POC_E_AUTH; + } + else + { + err_code = ParseProcessDatasetResult(wo_info, workflow_id, json_result); + } + + AddOutput(CFL_POC_DO_PROCESS_RESP_RINDEX_STATUS, out_work_order_data, err_code); + + if (err_code) + { + workflow_map.erase(workflow_id); + } + } +} + + + +int RequesterProcessor::ParseDoNonceResult(ExWorkorderInfo* wo_info, const ByteArray& workflow_id, const ByteArray& json_result, ByteArray nonce) +{ + // TODO: + // parse json workorder result returned by DO for "get-nonce" + // use generic_client as a base for porting frok python code + // use dataset from the json_result to locate right workorder id, nonce, and ek + // stub for now + + std::string str = "do-nonce"; + nonce.assign(str.begin(), str.end()); + + return CFL_POC_E_OP_OK; +} + + +int RequesterProcessor::CreateProcessDatasetRequest(ExWorkorderInfo* wo_info, + const ByteArray& work_flow_id, + const ByteArray& nonce, + const ByteArray& dataset_id, + const ByteArray& dataset_ek, + const ByteArray& query_data, + ByteArray& json_request) +{ + // TODO: make a "process" workorder request to be sent to the DO node + // use generic_client as a base for porting frok python code + // it also needs to set up wororder_id, workorder_nonce, and workorder_ek in the workflow_map for this dataset_id + // stub for now + + std::string str = "{\"op\":\"process\"}"; + json_request.assign(str.begin(), str.end()); + + return CFL_POC_E_OP_OK; +} + + + +int RequesterProcessor::ParseProcessDatasetResult(ExWorkorderInfo* wo_info, const ByteArray& workflow_id, const ByteArray& json_result) +{ + // TODO: + // parse json workorder result returned by DO for "process" + // use generic_client as a base for porting frok python code + // use dataset from the json_result to locate right workorder id, nonce, and ek + // make sure that dataset_id and workload_id match corresponding items in the workflow_map[workflow_id] + // add dataitem from json_result to a corresponding dataset in workflow_map[workflow_id].datasets + + // stub for now by + // adding content of the json_result to the last item in the workflow_map[workflow_id].datasets + + /*size_t size = workflow_map[workflow_id].datasets.size(); + if (size) + { + workflow_map[workflow_id].datasets[size - 1].processing_result = json_result; + } */ + return CFL_POC_E_OP_OK; +} + + + +bool RequesterProcessor::CheckUser(ExWorkorderInfo* wo_info, const ByteArray& workflow_id, ByteArray& user_vkey) +{ + bool ret_val = false; + // TODO: + // call ExWorkorderInfo::GetWorkorderSigningInfo() + // it must returned true (meaning that the workorder request was signed) + // In future there should be an additional check user_vk known in RequesterNodeConfig + // currently stub it + + /* wo_info->GetWorkorderSigningInfo(user_vkey); + + auto search = workflow_map.find(workflow_id); + if (search != workflow_map.end()) + { + if (workflow_map[workflow_id].user_vkey == user_vkey) + { + ret_val = true; + } + }*/ + + return ret_val; +} + + +bool RequesterProcessor::GetUserVkey(ExWorkorderInfo* wo_info, ByteArray& user_vkey) +{ + // TODO: + // call ExWorkorderInfo::GetWorkorderSigningInfo() + // it must returned true (meaning that the workorder request was signed + // return verification_key parameter from the prevoius call in user_vkey + // In future there should be an additional check user_vk known in RequesterNodeConfig + + // currently stub it + wo_info->GetWorkorderSigningInfo(user_vkey); + return requesterNodeConfig.CheckUserVkey(user_vkey); +} + + +void RequesterProcessor::AggregateData(const ByteArray& workflow_id, ByteArray& result) +{ + /*size_t size = 1; + WorkflowInfo& wi = workflow_map[workflow_id]; + + for (size_t i = 0; i < wi.datasets.size(); i++) + { + size += wi.datasets[i].processing_result.size() + 1; + } + + result.resize(size); + int index = 0; + for (size_t i = 0; i < wi.datasets.size(); i++) + { + result.data()[index++] = '_'; + memmove(&result.data()[index], wi.datasets[i].processing_result.data(), wi.datasets[i].processing_result.size()); + index += wi.datasets[i].processing_result.size(); + } + result.data()[index] = '_';*/ +} + + +bool RequesterProcessor::AddWorkflow(const ByteArray& data_owner_vkey, ByteArray& workflow_id) +{ + // TODO:generate a random workflow id, foe now stun=b as below + if (! ::cfl::GenerateNonce(workflow_id)) { + return false; + } + + WorkflowInfo wi; + wi.data_owner_vkey = data_owner_vkey; + wi.workflow_id = workflow_id; + wi.status = CFL_POC_WORKFLOW_WAITING; + + workflow_map[workflow_id] = wi; + return true; +} + + +bool RequesterProcessor::CheckWorkflowOwner(const ByteArray& data_owner_vkey, const ByteArray& workflow_id) +{ + // TODO:generate a random workflow id, foe now stun=b as below + if (workflow_map.find(workflow_id) == workflow_map.end()) { + return false; + } + + if ( workflow_map[workflow_id].data_owner_vkey != data_owner_vkey) + { + return false; + } + + return true; +} + + + + +int RequesterProcessor::CreateGetNonceWoRequest(ExWorkorderInfo* wo_info, + const ByteArray& attestation_data, const ByteArray& workflow_id, + const ByteArray& dataset_id, + ByteArray& json_request) +{ + // TODO: make a "get-nonce" workorder request to be sent to the DO node + // use generic_client as a base for porting frok python code + // it also needs to set up wororder_id, workorder_nonce, and workorder_ek in the workflow_map for this dataset_id + // stub for now + + std::string str = "{\"op\":\"get-nonce\"}"; + json_request.assign(str.begin(), str.end()); + + return CFL_POC_E_OP_OK; +} + + +bool RequesterProcessor::CheckDatasetAccess(const ByteArray& workflow_id, const ByteArray& user_vkey, const ByteArray& dataset_id, ByteArray& dataset_ek) +{ + bool ret_val = false; + + /*if (requesterNodeConfig.GetDatasetByVkey(user_vkey, dataset_id, dataset_ek)) + { + WorkflowInfo& wi = workflow_map[workflow_id]; + + for (size_t i = 0; i < wi.datasets.size(); i++) + { + if (wi.datasets[i].dataset_id == dataset_id) + { + // item exists - reset it + wi.datasets[i].workorder_id.resize(0); + wi.datasets[i].workorder_nonce.resize(0); + wi.datasets[i].processing_result.resize(0); + ret_val = true; + } + } + if (!ret_val) + { + DatasetInfo di; + di.dataset_id = dataset_id; + wi.datasets.push_back(di); + ret_val = true; + } + }*/ + + return ret_val; +} + +bool RequesterProcessor::CheckDataOwner(ExWorkorderInfo* wo_info, ByteArray& data_owner_vkey) +{ + return nodeConfig.CheckDataOwner(wo_info, data_owner_vkey); +} + + + +bool RequesterProcessor::CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey) +{ + return nodeConfig.CheckNonce(nonce, data_owner_vkey); +} + + +bool RequesterProcessor::VerifyWorkorderSignature(ExWorkorderInfo* exWorkorderInfo) +{ + + return exWorkorderInfo->VerifyWorkorderSignature(); +} + +std::string RequesterProcessor::TranslateWorkflowInfo() +{ + bool first = true; + std::string json = ""; + for (auto it = workflow_map.begin(); it != workflow_map.end(); it++) + { + if (first) + { + json += TranslateWorkflowInfo(it->second); + } + else + { + json += "," + TranslateWorkflowInfo(it->second); + } + first = false; + } + return "[" + json + "]"; +} + +std::string RequesterProcessor::TranslateWorkflowInfo(const ByteArray& user_vkey) +{ + bool first = true; + std::string json = ""; + for (auto it = workflow_map.begin(); it != workflow_map.end(); it++) + { + if (!JoinedWorkflow(user_vkey, it->second)) + { + continue; + } + if (first) + { + json += TranslateWorkflowInfo(it->second); + } + else + { + json += "," + TranslateWorkflowInfo(it->second); + } + first = false; + } + return "[" + json + "]"; + +} + +std::string RequesterProcessor::TranslateWorkflowInfo(const WorkflowInfo& workflow) +{ + std::string json = "{"; + json += "\"id\":\"" + ByteArrayToHexEncodedString(workflow.workflow_id) + "\","; + json += "\"data_owner_vkey\":\"" + ByteArrayToBase64EncodedString(workflow.data_owner_vkey) + "\","; + json += "\"status\":" + std::to_string(workflow.status) + ","; + json += "\"result\":\"" + ByteArrayToString(workflow.workflow_result) + "\","; + if (workflow.status == CFL_POC_WORKFLOW_ABORTED || workflow.status == CFL_POC_WORKFLOW_FINISHED) + { + json += "\"joined_workers\":" + TranslateBriefWorkflowWorkers(workflow) + "}"; + } + else + { + json += "\"joined_workers\":" + TranslateDetailedWorkflowWorkers(workflow) + "}"; + } + return json; +} + +std::string RequesterProcessor::TranslateBriefWorkflowWorkers(const WorkflowInfo& workflow) +{ + bool first = true; + std::string json = ""; + for (auto it = workflow.joined_workers.begin(); it != workflow.joined_workers.end(); it++) + { + if (first) + { + json += "{\"worker_vkey\":\"" + ByteArrayToBase64EncodedString(it->first) + + "\",\"parent_vkey\":\"" + ByteArrayToBase64EncodedString(it->second) + "\"}"; + } + else + { + json += ",{\"worker_vkey\":\"" + ByteArrayToBase64EncodedString(it->first) + + "\",\"parent_vkey\":\"" + ByteArrayToBase64EncodedString(it->second) + "\"}"; + } + first = false; + } + return "[" + json + "]"; +} + +std::string RequesterProcessor::TranslateDetailedWorkflowWorkers(const WorkflowInfo& workflow) +{ + bool first = true; + std::string json = ""; + for (auto it = workflow.joined_workers.begin(); it != workflow.joined_workers.end(); it++) + { + const auto& p = requesterNodeConfig.worker_map[it->second]; + const auto& g = requesterNodeConfig.worker_map[it->second].children[it->first]; + if (first) + { + json += requesterNodeConfig.TranslateGrapheneWorker(g, p); + } + else + { + json += "," + requesterNodeConfig.TranslateGrapheneWorker(g, p); + } + first = false; + } + return "[" + json + "]"; +} + + +bool RequesterProcessor::JoinedWorkflow(const ByteArray& user_vkey, const WorkflowInfo& workflow) +{ + return workflow.joined_workers.find(user_vkey) != workflow.joined_workers.end(); +} + +bool RequesterProcessor::IsWorkerActive(const ByteArray& worker_vkey) +{ + for (auto wf_it = workflow_map.begin(); wf_it != workflow_map.end(); wf_it++) + { + WorkflowInfo& workflow = wf_it->second; + if (workflow.status == CFL_POC_WORKFLOW_ABORTED || workflow.status == CFL_POC_WORKFLOW_FINISHED) + { + continue; + } + for (auto it = workflow.joined_workers.begin(); it != workflow.joined_workers.end(); it++) + { + if (it->first == worker_vkey || it->second == worker_vkey) + { + return true; + } + } + } + + return false; +} + + +} //namespace CflPocRequester diff --git a/examples/apps/data_owner/workload/requester-node-logic.h b/examples/apps/data_owner/workload/requester-node-logic.h new file mode 100644 index 000000000..1da067367 --- /dev/null +++ b/examples/apps/data_owner/workload/requester-node-logic.h @@ -0,0 +1,133 @@ +#pragma once + +#include +#include "cfl-poc-defs.h" + +namespace CflPocRequester { + +class RequesterProcessor +{ +public: + struct DatasetInfo + { + ByteArray dataset_id; + ByteArray processing_result; + ByteArray workorder_id; + ByteArray workorder_nonce; + ByteArray workorder_ek; + DatasetInfo() {}; + virtual ~DatasetInfo() {}; + }; + + struct WorkflowInfo + { + ByteArray workflow_id; + ByteArray data_owner_vkey; + std::map joined_workers; + int status; + ByteArray workflow_result; + WorkflowInfo() {}; + virtual ~WorkflowInfo() {}; + }; + + virtual void CreateWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void JoinWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void QuitWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void UpdateWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void LookupWorkflows(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void GetWorkflowResult(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void RemoveWorkflow(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void AvailableDatasets(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void CreateNonceRequest(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void CreateProcessDatasetRequest(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual void ProcessDatasetResult(const std::vector& in_work_order_data, + std::vector& out_work_order_data, + ExWorkorderInfo* wo_info); + + virtual bool IsWorkerActive(const ByteArray& worker_vkey); + +protected: + virtual bool CheckDataOwner(ExWorkorderInfo* wo_info, ByteArray& data_owner_vkey); + + virtual bool CheckNonce(const ByteArray& nonce, const ByteArray& data_owner_vkey); + + virtual bool VerifyWorkorderSignature(ExWorkorderInfo* exWorkorderInfo); + + virtual int ParseDoNonceResult(ExWorkorderInfo* wo_info, const ByteArray& workflow_id, const ByteArray& json_result, ByteArray nonce); + + virtual int CreateProcessDatasetRequest(ExWorkorderInfo* wo_info, + const ByteArray& work_flow_id, + const ByteArray& nonce, + const ByteArray& dataset_id, + const ByteArray& dataset_ek, + const ByteArray& query_data, + ByteArray& json_request); + + virtual int ParseProcessDatasetResult(ExWorkorderInfo* wo_info, const ByteArray& workflow_id, const ByteArray& json_result); + + virtual bool CheckWorkflowOwner(const ByteArray& data_owner_vkey, const ByteArray& workflow_id); + + virtual bool CheckUser(ExWorkorderInfo* wo_info, const ByteArray& workflow_id, ByteArray& user_vkey); + + virtual bool GetUserVkey(ExWorkorderInfo* wo_info, ByteArray& user_vkey); + + virtual void AggregateData(const ByteArray& workflow_id, ByteArray& result); + + virtual bool AddWorkflow(const ByteArray& user_vkey, ByteArray& workflow_id); + + virtual int CreateGetNonceWoRequest(ExWorkorderInfo* wo_info, + const ByteArray& attestation_data, const ByteArray& workflow_id, + const ByteArray& dataset_id, + ByteArray& json_request); + + + virtual bool CheckDatasetAccess(const ByteArray& workflow_id, const ByteArray& user_vkey, const ByteArray& dataset_id, ByteArray& dataset_ek); + + virtual std::string TranslateWorkflowInfo(); + + virtual std::string TranslateWorkflowInfo(const ByteArray& user_vkey); + + virtual std::string TranslateWorkflowInfo(const WorkflowInfo& workflow); + + virtual std::string TranslateBriefWorkflowWorkers(const WorkflowInfo& workflow); + + virtual std::string TranslateDetailedWorkflowWorkers(const WorkflowInfo& workflow); + + virtual bool JoinedWorkflow(const ByteArray& user_vkey, const WorkflowInfo& workflow); + + + static std::map workflow_map; +}; + + +} //namespace CflPocRequester diff --git a/examples/apps/data_owner/workload/requester-node-plug-in.cpp b/examples/apps/data_owner/workload/requester-node-plug-in.cpp new file mode 100644 index 000000000..30d184024 --- /dev/null +++ b/examples/apps/data_owner/workload/requester-node-plug-in.cpp @@ -0,0 +1,296 @@ +// +// CFL POC: requester-node-plug-in.cpp +// Workload registration and entry point +// + +#include "requester-node-config.h" +#include "requester-node-logic.h" +#include "requester-node-plug-in.h" +#include "cfl-poc-defs.h" +#include "cfl-utils.h" + +using namespace cfl; + +typedef CflPocRequester::Requester RequesterAddDataset; +typedef CflPocRequester::Requester RequesterRemoveDataset; +typedef CflPocRequester::Requester RequesterLookupDatasets; +typedef CflPocRequester::Requester RequesterAddWorker; +typedef CflPocRequester::Requester RequesterRemoveWorker; +typedef CflPocRequester::Requester RequesterUpdateWorker; +typedef CflPocRequester::Requester RequesterLookupWorkers; +typedef CflPocRequester::Requester RequesterAddUser; +typedef CflPocRequester::Requester RequesterRemoveUser; +typedef CflPocRequester::Requester RequesterLookupUsers; +typedef CflPocRequester::Requester RequesterCreateWorkflow; +typedef CflPocRequester::Requester RequesterJoinWorkflow; +typedef CflPocRequester::Requester RequesterQuitWorkflow; +typedef CflPocRequester::Requester RequesterUpdateWorkflow; +typedef CflPocRequester::Requester RequesterLookupWorkflows; +typedef CflPocRequester::Requester RequesterRemoveWorkflow; +typedef CflPocRequester::Requester RequesterAvailableDatasets; +typedef CflPocRequester::Requester RequesterWorkflowResult; +typedef CflPocRequester::Requester RequesterDoNonce; +typedef CflPocRequester::Requester RequesterDoProcess; +typedef CflPocRequester::Requester RequesterResponseProcess; + +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_ADD_DATASET, RequesterAddDataset) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_REMOVE_DATASET, RequesterRemoveDataset) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_LOOKUP_DATASETS, RequesterLookupDatasets) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_ADD_WORKER, RequesterAddWorker) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_REMOVE_WORKER, RequesterRemoveWorker) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_UPDATE_WORKER, RequesterUpdateWorker) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_LOOKUP_WORKERS, RequesterLookupWorkers) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_ADD_USER, RequesterAddUser) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_REMOVE_USER, RequesterRemoveUser) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_LOOKUP_USERS, RequesterLookupUsers) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CREATE_WORKFLOW, RequesterCreateWorkflow) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_JOIN_WORKFLOW, RequesterJoinWorkflow) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_QUIT_WORKFLOW, RequesterQuitWorkflow) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_UPDATE_WORKFLOW, RequesterUpdateWorkflow) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_LOOKUP_WORKFLOWS, RequesterLookupWorkflows) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_REMOVE_WORKFLOW, RequesterRemoveWorkflow) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_AVAILABLE_DATASETS, RequesterAvailableDatasets) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_GET_WORKFLOW_RESULT, RequesterWorkflowResult) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CREATE_DO_NONCE_RQST, RequesterDoNonce) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_CREATE_DO_PROCESS_RQST, RequesterDoProcess) +REGISTER_WORKLOAD_PROCESSOR(CFL_POC_OP_PROCESS_DO_PROCESS_RESP, RequesterResponseProcess) + + +namespace CflPocRequester { + + +// TODO: this dummy placeholder when the interface is implemented +static ExWorkorderInfo requester_ex; + + +extern RequesterNodeConfig requesterNodeConfig; + +void Requester::ProcessWorkOrder( + std::string workload_id, + const ByteArray& requester_id, + const ByteArray& worker_id, + const ByteArray& work_order_id, + const std::vector& in_work_order_data, + std::vector& out_work_order_data) +{ + RequesterProcessor p; + + //TODO: + //Remove the block below, when class ExWorkorderInfo is available. + //By now, we have a fake ExWorkorderInfo, and the verifying key is passed through parameter. + size_t input_size = in_work_order_data.size(); + if(input_size < 2) + { + AddOutput(0, out_work_order_data, CFL_POC_E_AUTH); + return; + } + + std::vector _in_work_order_data; + for(size_t i = 0; i < input_size - 2; i++) + { + _in_work_order_data.emplace_back(in_work_order_data[i]); + } + + ByteArray signature = in_work_order_data[input_size - 2].decrypted_data; + signature = TransformBase64ByteArray(signature); + ByteArray verificationKey = in_work_order_data[input_size - 1].decrypted_data; + verificationKey = TransformBase64ByteArray(verificationKey); + + + // TODO: remove line below exWorkorderInfo is available in tcf::Workload class and remove the dummy line + //ExWorkorderInfo* exWorkorderInfo = &requester_ex; // TODO: remove this dummy placeholder + + std::unique_ptr exWorkorderInfo_ptr(new ExWorkorderInfo); + ExWorkorderInfo* exWorkorderInfo = exWorkorderInfo_ptr.get(); + exWorkorderInfo->SetVerificationKey(verificationKey); + exWorkorderInfo->SetSignature(signature); + + + //TODO: + //Remove this when output data with multiple elementes is supported. + std::vector _out_work_order_data; + + + if (workload_id == CFL_POC_OP_ADD_DATASET) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.AddDataset(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_REMOVE_DATASET) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.RemoveDataset(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_LOOKUP_DATASETS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.LookupDatasets(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_ADD_WORKER) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.AddWorker(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_REMOVE_WORKER) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.RemoveWorker(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_UPDATE_WORKER) + { + //TODO: + //By now, we only support updating extra specs of Graphene worker. + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.UpdateGrapheneWorker(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_LOOKUP_WORKERS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.LookupWorkers(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_ADD_USER) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.AddUser(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_REMOVE_USER) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.RemoveUser(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_LOOKUP_USERS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + requesterNodeConfig.LookupUsers(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_CREATE_WORKFLOW) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.CreateWorkflow(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_JOIN_WORKFLOW) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.JoinWorkflow(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_QUIT_WORKFLOW) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.QuitWorkflow(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_UPDATE_WORKFLOW) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.UpdateWorkflow(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_LOOKUP_WORKFLOWS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.LookupWorkflows(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_REMOVE_WORKFLOW) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.RemoveWorkflow(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_AVAILABLE_DATASETS) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.AvailableDatasets(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_GET_WORKFLOW_RESULT) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.GetWorkflowResult(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_CREATE_DO_NONCE_RQST) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.CreateNonceRequest(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_CREATE_DO_PROCESS_RQST) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.CreateProcessDatasetRequest(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + if (workload_id == CFL_POC_OP_PROCESS_DO_PROCESS_RESP) + { + //TODO: + //Change the variable _in_work_order_data back to in_work_order_data when output data with multiple elementes is supported. + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + p.ProcessDatasetResult(_in_work_order_data, _out_work_order_data, exWorkorderInfo); + } + else + { + //TODO: + //Change the variable _out_work_order_data back to out_work_order_data when output data with multiple elementes is supported. + AddOutput(0, _out_work_order_data, CFL_POC_E_OP_CODE); + } + + //TODO: + //Remove this when output data with multiple elementes is supported. + ByteArray output; + MergeOutput(output, _out_work_order_data); + AddOutput(0, out_work_order_data, output); +} + +} //namespace CflPocRequester diff --git a/examples/apps/data_owner/workload/requester-node-plug-in.h b/examples/apps/data_owner/workload/requester-node-plug-in.h new file mode 100644 index 000000000..61a8890a9 --- /dev/null +++ b/examples/apps/data_owner/workload/requester-node-plug-in.h @@ -0,0 +1,32 @@ +// +// CFL POC: Plug-in.h +// Definitions for the workload registration and entry point +// + +#pragma once + +#include "workload_processor.h" + +#include +#include +#include +#include "cfl-poc-defs.h" + +namespace CflPocRequester { + + class Requester : public WorkloadProcessor { + public: + IMPL_WORKLOAD_PROCESSOR_CLONE(Requester) + + virtual void ProcessWorkOrder( + std::string workload_id, + const ByteArray& requester_id, + const ByteArray& worker_id, + const ByteArray& work_order_id, + const std::vector& in_work_order_data, + std::vector& out_work_order_data); + }; + +} // namespace CflPocDataOwner + + diff --git a/examples/apps/data_owner/workload/verify-workers.cpp b/examples/apps/data_owner/workload/verify-workers.cpp new file mode 100644 index 000000000..22cc47306 --- /dev/null +++ b/examples/apps/data_owner/workload/verify-workers.cpp @@ -0,0 +1,272 @@ +#include +#include + +#include "data-owner-node-config.h" +#include "cfl-utils.h" + +#include "verify-workers.h" +#include "parson.h" +#include "jsonvalue.h" +#include "error.h" +#include "tcf_error.h" +#include "types.h" +#include "verify-report.h" +#include "utils.h" + + +namespace CflPocDataOwner { + + extern DataOwnerNodeConfig dataOwnerNodeConfig; +} + +using CflPocDataOwner::dataOwnerNodeConfig; + +namespace cfl { + +const char * cert_pem = "-----BEGIN CERTIFICATE-----\n" +"MIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV\n" +"BAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV\n" +"BAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0\n" +"YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIw\n" +"MDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1Nh\n" +"bnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwk\n" +"SW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG\n" +"9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA+t\n" +"beCTUR106AL1ENcWA4FX3K+E9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtId\n" +"cv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuv\n" +"LUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV+W9tOhA\n" +"ImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt++qO/6+KAXJuKwZqjRlEtSEz8\n" +"gZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGh\n" +"MB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN+s1fDuHAVE8MA4GA1UdDwEB/wQEAwIG\n" +"wDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVk\n" +"c2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJl\n" +"cG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4r\n" +"Rq+ZKE+7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9\n" +"lpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYv\n" +"WLrtXXfFBSSPD4Afn7+3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUd\n" +"ZseZCcaZZZn65tdqee8UXZlDvx0+NdO0LR+5pFy+juM0wWbu59MvzcmTXbjsi7HY\n" +"6zd53Yq5K244fwFHRQ8eOB0IWB+4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW7\n" +"2uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN+KwPbpA39+xOsStjhP9N1Y1a2\n" +"tQAVo+yVgLgV2Hws73Fc0o3wC78qPEA+v2aRs/Be3ZFDgDyghc/1fgU+7C+P6kbq\n" +"d4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA==\n" +"-----END CERTIFICATE-----\n" +"-----BEGIN CERTIFICATE-----\n" +"MIIFSzCCA7OgAwIBAgIJANEHdl0yo7CUMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV\n" +"BAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV\n" +"BAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0\n" +"YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwIBcNMTYxMTE0MTUzNzMxWhgPMjA0OTEy\n" +"MzEyMzU5NTlaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwL\n" +"U2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQD\n" +"DCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwggGiMA0G\n" +"CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCfPGR+tXc8u1EtJzLA10Feu1Wg+p7e\n" +"LmSRmeaCHbkQ1TF3Nwl3RmpqXkeGzNLd69QUnWovYyVSndEMyYc3sHecGgfinEeh\n" +"rgBJSEdsSJ9FpaFdesjsxqzGRa20PYdnnfWcCTvFoulpbFR4VBuXnnVLVzkUvlXT\n" +"L/TAnd8nIZk0zZkFJ7P5LtePvykkar7LcSQO85wtcQe0R1Raf/sQ6wYKaKmFgCGe\n" +"NpEJUmg4ktal4qgIAxk+QHUxQE42sxViN5mqglB0QJdUot/o9a/V/mMeH8KvOAiQ\n" +"byinkNndn+Bgk5sSV5DFgF0DffVqmVMblt5p3jPtImzBIH0QQrXJq39AT8cRwP5H\n" +"afuVeLHcDsRp6hol4P+ZFIhu8mmbI1u0hH3W/0C2BuYXB5PC+5izFFh/nP0lc2Lf\n" +"6rELO9LZdnOhpL1ExFOq9H/B8tPQ84T3Sgb4nAifDabNt/zu6MmCGo5U8lwEFtGM\n" +"RoOaX4AS+909x00lYnmtwsDVWv9vBiJCXRsCAwEAAaOByTCBxjBgBgNVHR8EWTBX\n" +"MFWgU6BRhk9odHRwOi8vdHJ1c3RlZHNlcnZpY2VzLmludGVsLmNvbS9jb250ZW50\n" +"L0NSTC9TR1gvQXR0ZXN0YXRpb25SZXBvcnRTaWduaW5nQ0EuY3JsMB0GA1UdDgQW\n" +"BBR4Q3t2pn680K9+QjfrNXw7hwFRPDAfBgNVHSMEGDAWgBR4Q3t2pn680K9+Qjfr\n" +"NXw7hwFRPDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkq\n" +"hkiG9w0BAQsFAAOCAYEAeF8tYMXICvQqeXYQITkV2oLJsp6J4JAqJabHWxYJHGir\n" +"IEqucRiJSSx+HjIJEUVaj8E0QjEud6Y5lNmXlcjqRXaCPOqK0eGRz6hi+ripMtPZ\n" +"sFNaBwLQVV905SDjAzDzNIDnrcnXyB4gcDFCvwDFKKgLRjOB/WAqgscDUoGq5ZVi\n" +"zLUzTqiQPmULAQaB9c6Oti6snEFJiCQ67JLyW/E83/frzCmO5Ru6WjU4tmsmy8Ra\n" +"Ud4APK0wZTGtfPXU7w+IBdG5Ez0kE1qzxGQaL4gINJ1zMyleDnbuS8UicjJijvqA\n" +"152Sq049ESDz+1rRGc2NVEqh1KaGXmtXvqxXcTB+Ljy5Bw2ke0v8iGngFBPqCTVB\n" +"3op5KBG3RjbF6RRSzwzuWfL7QErNC8WEy5yDVARzTA5+xmBc388v9Dm21HGfcC8O\n" +"DD+gT9sSpssq0ascmvH49MOgjt1yoysLtdCtJW/9FZpoOypaHx0R+mJTLwPXVMrv\n" +"DaVzWh5aiEx+idkSGMnX\n" +"-----END CERTIFICATE-----\n"; + + +bool VerifyWorker(const char* worker_info, const ByteArray& nonce, GrapheneWorker& worker) +{ + const char* svalue = nullptr; + + JsonValue worker_info_json(json_parse_string(worker_info)); + tcf::error::ThrowIfNull(worker_info_json.value, "Failed to parse the worker info, badly formed JSON"); + + JSON_Object* worker_info_object = json_value_get_object(worker_info_json); + tcf::error::ThrowIfNull(worker_info_object, "Invalid worker_info, expecting object"); + + svalue = json_object_dotget_string(worker_info_object, "verifying_key"); + tcf::error::ThrowIfNull(svalue, "Invalid verifying_key"); + std::string verification_key(svalue); + + svalue = json_object_dotget_string(worker_info_object, "encryption_key"); + tcf::error::ThrowIfNull(svalue, "Invalid encryption_key"); + std::string encryption_key(svalue); + + // Parse proof data + svalue = json_object_dotget_string(worker_info_object, "proof_data"); + tcf::error::ThrowIfNull(svalue, "Invalid proof_data"); + std::string proof_data(svalue); + JsonValue proof_data_json(json_parse_string(proof_data.c_str())); + tcf::error::ThrowIfNull(proof_data_json.value, "Failed to parse the proofData, badly formed JSON"); + JSON_Object* proof_object = json_value_get_object(proof_data_json); + tcf::error::ThrowIfNull(proof_object, "Invalid proof, expecting object"); + + svalue = json_object_dotget_string(proof_object, "ias_report_signature"); + tcf::error::ThrowIfNull(svalue, "Invalid proof_signature"); + const std::string proof_signature(svalue); + + //Parse verification report + const char* verification_report = json_object_dotget_string(proof_object, "verification_report"); + tcf::error::ThrowIfNull(svalue, "Invalid proof_verification_report"); + JsonValue verification_report_json(json_parse_string(verification_report)); + tcf::error::ThrowIfNull(verification_report_json.value, "Failed to parse the verificationReport, badly formed JSON"); + JSON_Object* verification_report_object = json_value_get_object(verification_report_json); + tcf::error::ThrowIfNull(verification_report_object, "Invalid verification_report, expecting object"); + + if (!VerifyReportFields(verification_report_object)) + { + return false; + } + + if(!verify_enclave_quote_status(verification_report, strlen(verification_report), 1)) + { + return false; + } + + std::vector proof_signature_vec(proof_signature.begin(), proof_signature.end()); + proof_signature_vec.push_back('\0'); + char* proof_signature_arr = &proof_signature_vec[0]; + if (!verify_ias_report_signature(cert_pem, + verification_report, + strlen(verification_report), + proof_signature_arr, + strlen(proof_signature_arr))) + { + return false; + } + if (!ExtractQuoteBody(verification_report_object, verification_key, encryption_key, nonce, worker)) + { + return false; + } + + worker.worker_vkey = Base64EncodedStringToByteArray(verification_key); + worker.worker_ekey = StrToByteArray(encryption_key); + + return true; + +} + +bool VerifyReportFields(JSON_Object* verification_report_object) +{ + const char* svalue = nullptr; + + svalue = json_object_dotget_string(verification_report_object, "id"); + tcf::error::ThrowIfNull(svalue, "AVR does not contain id field"); + + svalue = json_object_dotget_string(verification_report_object, "revocationReason"); + if (svalue != nullptr) + { + throw tcf::error::ValueError("AVR indicates the EPID group has been revoked"); + } + + svalue = json_object_dotget_string(verification_report_object, "isvEnclaveQuoteStatus"); + tcf::error::ThrowIfNull(svalue, "AVR does not include an enclave quote status"); + + svalue = json_object_dotget_string(verification_report_object, "isvEnclaveQuoteBody"); + tcf::error::ThrowIfNull(svalue, "AVR does not contain quote body"); + + svalue = json_object_dotget_string(verification_report_object, "epidPseudonym"); + tcf::error::ThrowIfNull(svalue, "AVR does not contain an EPID pseudonym"); + + svalue = json_object_dotget_string(verification_report_object, "nonce"); + tcf::error::ThrowIfNull(svalue, "AVR does not contain a nonce"); + + return true; +} + +ByteArray CalculateReportData(const std::string& vkey, const std::string& ekey, const ByteArray & nonce) +{ + std::string vkey_pem = AddBeginEndBlockToVerificationKey(vkey); + std::string concat_str = vkey_pem + ekey; + ByteArray hash = tcf::crypto::ComputeMessageHash(StrToByteArray(concat_str)); + hash.insert(hash.end(), nonce.begin(), nonce.end()); + return hash; +} + + +bool ExtractQuoteBody(JSON_Object* verification_report_object, + const std::string& vkey, + const std::string& ekey, + const ByteArray & nonce, + GrapheneWorker& worker) +{ + const char* svalue = json_object_dotget_string(verification_report_object, "isvEnclaveQuoteBody"); + tcf::error::ThrowIfNull(svalue, "Invalid enclave_quote_body"); + const std::string enclave_quote_body(svalue); + ByteArray enclave_quote_body_byte = Base64EncodedStringToByteArray(enclave_quote_body); + + sgx_quote_t* quote_body = reinterpret_cast(enclave_quote_body_byte.data()); + + //Verify treport dataaaaaaaaa + sgx_report_body_t* report_body = "e_body->report_body; + uint8_t* expected_report_data = (report_body->report_data).d; + ByteArray computed_report_data = CalculateReportData(vkey, ekey, nonce); + ByteArray expected_report_data_byte(expected_report_data, expected_report_data + SGX_REPORT_DATA_SIZE); + + std::string error_msg = "Invalid Report data: computedReportData " + ByteArrayToHexEncodedString(computed_report_data) + " does not match expectedReportData " + ByteArrayToHexEncodedString(expected_report_data_byte); + + tcf::error::ThrowIf( + memcmp(computed_report_data.data(), expected_report_data, SGX_REPORT_DATA_SIZE) != 0, + error_msg.c_str()); + + const std::vector& worker_measurements = dataOwnerNodeConfig.GetWorkerMeasurements(); + + for(const WorkerMeasurement& meas: worker_measurements) + { + if (meas.mrenclave.size() != 0) + { + if (memcmp(meas.mrenclave.data(), (report_body->mr_enclave).m, SGX_HASH_SIZE) != 0) + { + continue; + } + } + + if (meas.mrsigner.size() != 0) + { + if (memcmp(meas.mrsigner.data(), (report_body->mr_signer).m, SGX_HASH_SIZE) != 0) + { + continue; + } + } + + if (meas.isv_prod_id >= 0) + { + uint16_t isv_prod_id = (uint16_t) report_body->isv_prod_id; + if (meas.isv_prod_id != isv_prod_id) + { + continue; + } + } + + if (meas.isv_svn >= 0) + { + uint16_t isv_svn = (uint16_t) report_body->isv_svn; + if (meas.isv_prod_id != isv_svn) + { + continue; + } + } + + worker.worker_mrenclave = ByteArray((report_body->mr_enclave).m, (report_body->mr_enclave).m + SGX_HASH_SIZE); + worker.worker_mrsigner = ByteArray((report_body->mr_signer).m, (report_body->mr_signer).m + SGX_HASH_SIZE); + worker.isv_prod_id = (uint16_t) report_body->isv_prod_id; + worker.isv_svn = (uint16_t) report_body->isv_svn; + + return true; + } + + + return false; +} + + +} //namespace cfl diff --git a/examples/apps/data_owner/workload/verify-workers.h b/examples/apps/data_owner/workload/verify-workers.h new file mode 100644 index 000000000..bb94fc9cf --- /dev/null +++ b/examples/apps/data_owner/workload/verify-workers.h @@ -0,0 +1,18 @@ +#pragma once + +#include "parson.h" +#include "cfl-utils.h" + +namespace cfl { + + + bool VerifyWorker(const char* enclave_data, const ByteArray& nonce, GrapheneWorker& worker); + ByteArray CalculateReportData(const std::string& vkey, const std::string& ekey, const ByteArray & nonce); + bool VerifyReportFields(JSON_Object* verification_report_object); + bool ExtractQuoteBody(JSON_Object* verification_report_object, + const std::string& vkey, + const std::string& ekey, + const ByteArray& nonce, + GrapheneWorker& worker); +} + From 1b274d2137ef913f7e0c21fe20e75ab1103079c4 Mon Sep 17 00:00:00 2001 From: danhe1 Date: Tue, 27 Oct 2020 18:38:52 +0800 Subject: [PATCH 2/3] modified: examples/apps/CMakeLists.txt Signed-off-by: danhe1 --- examples/apps/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/apps/CMakeLists.txt b/examples/apps/CMakeLists.txt index bdc986b31..8cee86228 100644 --- a/examples/apps/CMakeLists.txt +++ b/examples/apps/CMakeLists.txt @@ -23,6 +23,7 @@ ADD_SUBDIRECTORY(echo/workload) ADD_SUBDIRECTORY(heart_disease_eval/workload) ADD_SUBDIRECTORY(inside_out_demo/workload) ADD_SUBDIRECTORY(simple_wallet/workload) +ADD_SUBDIRECTORY(data_owner/workload) # To add a new workload, uncomment the following line and change # $WORKLOAD_STATIC_NAME$ to the appropriate name (such as hello_world): From 5e5804ea202df910ff614f95f00e6491ddc06c89 Mon Sep 17 00:00:00 2001 From: danhe1 Date: Tue, 27 Oct 2020 18:40:05 +0800 Subject: [PATCH 3/3] modified: tc/sgx/trusted_worker_manager/enclave/CMakeLists.txt Signed-off-by: danhe1 --- tc/sgx/trusted_worker_manager/enclave/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tc/sgx/trusted_worker_manager/enclave/CMakeLists.txt b/tc/sgx/trusted_worker_manager/enclave/CMakeLists.txt index 46ae0ad2f..e8feb5381 100644 --- a/tc/sgx/trusted_worker_manager/enclave/CMakeLists.txt +++ b/tc/sgx/trusted_worker_manager/enclave/CMakeLists.txt @@ -205,6 +205,7 @@ SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-L,${TCF_TOP_DIR SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-L,${TCF_TOP_DIR}/examples/apps/build/heart_disease_eval/workload") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-L,${TCF_TOP_DIR}/examples/apps/build/inside_out_demo/workload") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-L,${TCF_TOP_DIR}/examples/apps/build/simple_wallet/workload") +SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-L,${TCF_TOP_DIR}/examples/apps/build/data_owner/workload") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-L,$ENV{SGX_SSL}/lib64") # Remove all the default windows libraries (kernel32, etc) SET(CMAKE_C_STANDARD_LIBRARIES_INIT "") @@ -237,6 +238,8 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} -Wl,--whole-archive -lheart_disease_eval - TARGET_LINK_LIBRARIES(${PROJECT_NAME} -Wl,--whole-archive -linside_out_eval -Wl,--no-whole-archive) # Add simple wallet workload TARGET_LINK_LIBRARIES(${PROJECT_NAME} -Wl,--whole-archive -lsimple_wallet -Wl,--no-whole-archive) +# Add VE Processor workload +TARGET_LINK_LIBRARIES(${PROJECT_NAME} -Wl,--whole-archive -ldata_owner -Wl,--no-whole-archive) TARGET_LINK_LIBRARIES(${PROJECT_NAME} -Wl,--start-group -ltavalon-common -ltavalon-base64 -ltavalon-parson -ltavalon-crypto -ltavalon-verify-ias-report -ltavalon-sgx-common -lsgx_tsgxssl_crypto -lsgx_tstdc -lsgx_tcxx -lsgx_tcrypto -l${SERVICE_LIBRARY_NAME} -Wl,--end-group)