diff --git a/.cmake-format.py b/.cmake-format.py index faabea0f9440..d31810ae2cd7 100644 --- a/.cmake-format.py +++ b/.cmake-format.py @@ -11,6 +11,7 @@ "INCLUDE_DIRS": "*", "LINK_LIBS_ENCLAVE": "*", "LINK_LIBS_VIRTUAL": "*", + "LINK_LIBS_SNP": "*", }, }, "add_client_exe": { diff --git a/.daily_canary b/.daily_canary index 73ba4d8643d8..a82d9b28fde9 100644 --- a/.daily_canary +++ b/.daily_canary @@ -1,4 +1,4 @@ ___ ___ - (+ *) (O o) | Y - ( V ) ( V ) O / + (- *) (O o) | Y + ( V ) < V ) O / /--x-m- /--m-m---xXx--/ diff --git a/.snpcc_canary b/.snpcc_canary index 81c8b7d9d815..fcc36d74a03b 100644 --- a/.snpcc_canary +++ b/.snpcc_canary @@ -1,4 +1,4 @@ | Y O / -/-xXx--/----- +/-xXx--/-----) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2e191a72be7..81c1ca419b82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. [4.0.0-dev0]: https://github.com/microsoft/CCF/releases/tag/ccf-4.0.0-dev0 +### Changed + +- `enclave.type` configuration entry now only supports `Debug` or `Release`. Trusted Execution Environment platform should be specified via new `enclave.platform` configuration entry (`SGX`, `SNP` or `Virtual`) (#4569). + ### Fixed - Fix issue with large snapshots that may cause node crash on startup (join/recover) if configured stack size was too low (#4566). diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a12effcd831..6b2a143ae75a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,12 +122,16 @@ if(COMPILE_TARGET STREQUAL "sgx") ) target_link_libraries( - ccf.enclave PUBLIC quickjs.enclave http_parser.enclave sss.enclave - ccf_endpoints.enclave ccfcrypto.enclave ccf_kv.enclave + ccf.enclave + PUBLIC quickjs.enclave + http_parser.enclave + sss.enclave + ccf_endpoints.enclave + ccfcrypto.enclave + ccf_kv.enclave + nghttp2.enclave ) - target_link_libraries(ccf.enclave PUBLIC nghttp2.enclave) - add_lvi_mitigations(ccf.enclave) install( @@ -141,19 +145,19 @@ if(COMPILE_TARGET STREQUAL "sgx") # Same as virtual for the time being but will diverge soon elseif(COMPILE_TARGET STREQUAL "snp") - # virtual version - add_library(ccf.virtual STATIC ${CCF_IMPL_SOURCE}) + # SNP version + add_library(ccf.snp STATIC ${CCF_IMPL_SOURCE}) target_compile_definitions( - ccf.virtual PUBLIC INSIDE_ENCLAVE VIRTUAL_ENCLAVE - _LIBCPP_HAS_THREAD_API_PTHREAD PLATFORM_SNP + ccf.snp PUBLIC INSIDE_ENCLAVE VIRTUAL_ENCLAVE + _LIBCPP_HAS_THREAD_API_PTHREAD PLATFORM_SNP ) - target_compile_options(ccf.virtual PUBLIC ${COMPILE_LIBCXX}) - add_warning_checks(ccf.virtual) + target_compile_options(ccf.snp PUBLIC ${COMPILE_LIBCXX}) + add_warning_checks(ccf.snp) target_include_directories( - ccf.virtual SYSTEM + ccf.snp SYSTEM PUBLIC $ $ #< This contains the private headers @@ -164,32 +168,31 @@ elseif(COMPILE_TARGET STREQUAL "snp") ) target_link_libraries( - ccf.virtual + ccf.snp PUBLIC ${LINK_LIBCXX} -lgcc - http_parser.host - quickjs.host - sss.host - ccf_endpoints.host - ccfcrypto.host - ccf_kv.host + http_parser.snp + quickjs.snp + sss.snp + ccf_endpoints.snp + ccfcrypto.snp + ccf_kv.snp + nghttp2.snp ${OE_HOST_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ) - target_link_libraries(ccf.virtual PUBLIC nghttp2.host) - - set_property(TARGET ccf.virtual PROPERTY POSITION_INDEPENDENT_CODE ON) + set_property(TARGET ccf.snp PROPERTY POSITION_INDEPENDENT_CODE ON) - add_san(ccf.virtual) + add_san(ccf.snp) install( - TARGETS ccf.virtual + TARGETS ccf.snp EXPORT ccf DESTINATION lib ) - add_dependencies(ccf ccf.virtual) + add_dependencies(ccf ccf.snp) elseif(COMPILE_TARGET STREQUAL "virtual") @@ -225,12 +228,11 @@ elseif(COMPILE_TARGET STREQUAL "virtual") ccf_endpoints.host ccfcrypto.host ccf_kv.host + nghttp2.host ${OE_HOST_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ) - target_link_libraries(ccf.virtual PUBLIC nghttp2.host) - set_property(TARGET ccf.virtual PROPERTY POSITION_INDEPENDENT_CODE ON) add_san(ccf.virtual) diff --git a/cmake/ccf_app.cmake b/cmake/ccf_app.cmake index 318f0a2e0168..159157532ead 100644 --- a/cmake/ccf_app.cmake +++ b/cmake/ccf_app.cmake @@ -95,8 +95,12 @@ endfunction() function(add_ccf_app name) cmake_parse_arguments( - PARSE_ARGV 1 PARSED_ARGS "" "" - "SRCS;INCLUDE_DIRS;LINK_LIBS_ENCLAVE;LINK_LIBS_VIRTUAL;DEPS;INSTALL_LIBS" + PARSE_ARGV + 1 + PARSED_ARGS + "" + "" + "SRCS;INCLUDE_DIRS;LINK_LIBS_ENCLAVE;LINK_LIBS_VIRTUAL;LINK_LIBS_SNP;DEPS;INSTALL_LIBS" ) add_custom_target(${name} ALL) @@ -126,42 +130,42 @@ function(add_ccf_app name) endif() elseif(COMPILE_TARGET STREQUAL "snp") - # Build a virtual enclave, loaded as a shared library without OE - set(virt_name ${name}.virtual) + # Build an SNP enclave, loaded as a shared library without OE + set(snp_name ${name}.snp) - add_library(${virt_name} SHARED ${PARSED_ARGS_SRCS}) + add_library(${snp_name} SHARED ${PARSED_ARGS_SRCS}) - target_compile_definitions(${virt_name} PUBLIC PLATFORM_SNP) + target_compile_definitions(${snp_name} PUBLIC PLATFORM_SNP) target_include_directories( - ${virt_name} SYSTEM PRIVATE ${PARSED_ARGS_INCLUDE_DIRS} + ${snp_name} SYSTEM PRIVATE ${PARSED_ARGS_INCLUDE_DIRS} ) - add_warning_checks(${virt_name}) + add_warning_checks(${snp_name}) target_link_libraries( - ${virt_name} PRIVATE ${PARSED_ARGS_LINK_LIBS_VIRTUAL} ccf.virtual + ${snp_name} PRIVATE ${PARSED_ARGS_LINK_LIBS_SNP} ccf.snp ) if(NOT SAN) - target_link_options(${virt_name} PRIVATE LINKER:--no-undefined) + target_link_options(${snp_name} PRIVATE LINKER:--no-undefined) endif() target_link_options( - ${virt_name} PRIVATE + ${snp_name} PRIVATE LINKER:--undefined=enclave_create_node,--undefined=enclave_run ) - set_property(TARGET ${virt_name} PROPERTY POSITION_INDEPENDENT_CODE ON) + set_property(TARGET ${snp_name} PROPERTY POSITION_INDEPENDENT_CODE ON) - add_san(${virt_name}) + add_san(${snp_name}) - add_dependencies(${name} ${virt_name}) + add_dependencies(${name} ${snp_name}) if(PARSED_ARGS_DEPS) - add_dependencies(${virt_name} ${PARSED_ARGS_DEPS}) + add_dependencies(${snp_name} ${PARSED_ARGS_DEPS}) endif() if(${PARSED_ARGS_INSTALL_LIBS}) - install(TARGETS ${virt_name} DESTINATION lib) + install(TARGETS ${snp_name} DESTINATION lib) endif() elseif(COMPILE_TARGET STREQUAL "virtual") diff --git a/cmake/common.cmake b/cmake/common.cmake index 9edf2abf482f..08ed77b204da 100644 --- a/cmake/common.cmake +++ b/cmake/common.cmake @@ -161,9 +161,10 @@ if(COMPILE_TARGET STREQUAL "sgx") if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(DEFAULT_ENCLAVE_TYPE debug) endif() +elseif(COMPILE_TARGET STREQUAL "snp") + set(INSTALL_VIRTUAL_LIBRARIES OFF) else() set(INSTALL_VIRTUAL_LIBRARIES ON) - set(DEFAULT_ENCLAVE_TYPE virtual) endif() set(HTTP_PARSER_SOURCES @@ -310,6 +311,14 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_library(http_parser.snp "${HTTP_PARSER_SOURCES}") + set_property(TARGET http_parser.snp PROPERTY POSITION_INDEPENDENT_CODE ON) + install( + TARGETS http_parser.snp + EXPORT ccf + DESTINATION lib + ) endif() add_library(http_parser.host "${HTTP_PARSER_SOURCES}") @@ -336,7 +345,17 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_host_library(ccf_kv.snp "${CCF_KV_SOURCES}") + add_san(ccf_kv.snp) + add_warning_checks(ccf_kv.snp) + install( + TARGETS ccf_kv.snp + EXPORT ccf + DESTINATION lib + ) endif() + add_host_library(ccf_kv.host "${CCF_KV_SOURCES}") add_san(ccf_kv.host) add_warning_checks(ccf_kv.host) @@ -359,6 +378,17 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_host_library(ccf_endpoints.snp "${CCF_ENDPOINTS_SOURCES}") + target_link_libraries(ccf_endpoints.snp PUBLIC qcbor.snp) + target_link_libraries(ccf_endpoints.snp PUBLIC t_cose.snp) + add_san(ccf_endpoints.snp) + add_warning_checks(ccf_endpoints.snp) + install( + TARGETS ccf_endpoints.snp + EXPORT ccf + DESTINATION lib + ) endif() add_host_library(ccf_endpoints.host "${CCF_ENDPOINTS_SOURCES}") @@ -405,19 +435,17 @@ if(COMPILE_TARGET STREQUAL "sgx") DESTINATION lib ) elseif(COMPILE_TARGET STREQUAL "snp") - add_library(js_openenclave.virtual STATIC ${CCF_DIR}/src/js/openenclave.cpp) - add_san(js_openenclave.virtual) - target_link_libraries(js_openenclave.virtual PUBLIC ccf.virtual) - target_compile_options(js_openenclave.virtual PRIVATE ${COMPILE_LIBCXX}) + add_library(js_openenclave.snp STATIC ${CCF_DIR}/src/js/openenclave.cpp) + add_san(js_openenclave.snp) + target_link_libraries(js_openenclave.snp PUBLIC ccf.snp) + target_compile_options(js_openenclave.snp PRIVATE ${COMPILE_LIBCXX}) target_compile_definitions( - js_openenclave.virtual PUBLIC INSIDE_ENCLAVE VIRTUAL_ENCLAVE - _LIBCPP_HAS_THREAD_API_PTHREAD PLATFORM_SNP - ) - set_property( - TARGET js_openenclave.virtual PROPERTY POSITION_INDEPENDENT_CODE ON + js_openenclave.snp PUBLIC INSIDE_ENCLAVE VIRTUAL_ENCLAVE + _LIBCPP_HAS_THREAD_API_PTHREAD PLATFORM_SNP ) + set_property(TARGET js_openenclave.snp PROPERTY POSITION_INDEPENDENT_CODE ON) install( - TARGETS js_openenclave.virtual + TARGETS js_openenclave.snp EXPORT ccf DESTINATION lib ) @@ -454,22 +482,20 @@ if(COMPILE_TARGET STREQUAL "sgx") ) elseif(COMPILE_TARGET STREQUAL "snp") add_library( - js_generic_base.virtual STATIC + js_generic_base.snp STATIC ${CCF_DIR}/src/apps/js_generic/js_generic_base.cpp ) - add_san(js_generic_base.virtual) - add_warning_checks(js_generic_base.virtual) - target_link_libraries(js_generic_base.virtual PUBLIC ccf.virtual) - target_compile_options(js_generic_base.virtual PRIVATE ${COMPILE_LIBCXX}) + add_san(js_generic_base.snp) + add_warning_checks(js_generic_base.snp) + target_link_libraries(js_generic_base.snp PUBLIC ccf.snp) + target_compile_options(js_generic_base.snp PRIVATE ${COMPILE_LIBCXX}) target_compile_definitions( - js_generic_base.virtual PUBLIC INSIDE_ENCLAVE VIRTUAL_ENCLAVE - _LIBCPP_HAS_THREAD_API_PTHREAD PLATFORM_SNP - ) - set_property( - TARGET js_generic_base.virtual PROPERTY POSITION_INDEPENDENT_CODE ON + js_generic_base.snp PUBLIC INSIDE_ENCLAVE VIRTUAL_ENCLAVE + _LIBCPP_HAS_THREAD_API_PTHREAD PLATFORM_SNP ) + set_property(TARGET js_generic_base.snp PROPERTY POSITION_INDEPENDENT_CODE ON) install( - TARGETS js_generic_base.virtual + TARGETS js_generic_base.snp EXPORT ccf DESTINATION lib ) @@ -501,8 +527,8 @@ add_ccf_app( js_generic SRCS ${CCF_DIR}/src/apps/js_generic/js_generic.cpp LINK_LIBS_ENCLAVE js_generic_base.enclave js_openenclave.enclave - LINK_LIBS_VIRTUAL js_generic_base.virtual js_openenclave.virtual INSTALL_LIBS - ON + LINK_LIBS_VIRTUAL js_generic_base.virtual js_openenclave.virtual + LINK_LIBS_SNP js_generic_base.snp js_openenclave.snp INSTALL_LIBS ON ) sign_app_library( js_generic.enclave ${CCF_DIR}/src/apps/js_generic/oe_sign.conf @@ -636,6 +662,12 @@ function(add_e2e_test) PROPERTY ENVIRONMENT "DEFAULT_ENCLAVE_TYPE=${DEFAULT_ENCLAVE_TYPE}" ) endif() + + set_property( + TEST ${PARSED_ARGS_NAME} + APPEND + PROPERTY ENVIRONMENT "DEFAULT_ENCLAVE_PLATFORM=${COMPILE_TARGET}" + ) endif() endfunction() @@ -663,6 +695,7 @@ function(add_perf_test) set(TESTS_SUFFIX "") set(ENCLAVE_TYPE "") + set(ENCLAVE_PLATFORM "${COMPILE_TARGET}") if("sgx" STREQUAL COMPILE_TARGET) set(TESTS_SUFFIX "${TESTS_SUFFIX}_sgx") set(ENCLAVE_TYPE "release") @@ -689,7 +722,7 @@ function(add_perf_test) ${CCF_NETWORK_TEST_ARGS} --consensus ${CONSENSUS} ${PARSED_ARGS_CONSTITUTION} --write-tx-times ${VERIFICATION_ARG} --label ${LABEL_ARG} --snapshot-tx-interval 10000 ${PARSED_ARGS_ADDITIONAL_ARGS} - -e ${ENCLAVE_TYPE} ${NODES} + -e ${ENCLAVE_TYPE} -t ${ENCLAVE_PLATFORM} ${NODES} ) # Make python test client framework importable @@ -705,6 +738,14 @@ function(add_perf_test) PROPERTY ENVIRONMENT "DEFAULT_ENCLAVE_TYPE=${DEFAULT_ENCLAVE_TYPE}" ) endif() + if(DEFINED DEFAULT_ENCLAVE_PLATFORM) + set_property( + TEST ${TEST_NAME} + APPEND + PROPERTY ENVIRONMENT + "DEFAULT_ENCLAVE_PLATFORM=${DEFAULT_ENCLAVE_PLATFORM}" + ) + endif() set_property( TEST ${TEST_NAME} APPEND diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index 5d29200cf657..ceac340c713d 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -35,6 +35,22 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_library(ccfcrypto.snp ${CCFCRYPTO_SRC}) + add_san(ccfcrypto.snp) + target_compile_options(ccfcrypto.snp PUBLIC ${COMPILE_LIBCXX}) + target_link_options(ccfcrypto.snp PUBLIC ${LINK_LIBCXX}) + target_link_libraries(ccfcrypto.snp PUBLIC qcbor.snp) + target_link_libraries(ccfcrypto.snp PUBLIC t_cose.snp) + target_link_libraries(ccfcrypto.snp PUBLIC crypto) + target_link_libraries(ccfcrypto.snp PUBLIC ssl) + set_property(TARGET ccfcrypto.snp PROPERTY POSITION_INDEPENDENT_CODE ON) + + install( + TARGETS ccfcrypto.snp + EXPORT ccf + DESTINATION lib + ) endif() add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC}) diff --git a/cmake/nghttp2.cmake b/cmake/nghttp2.cmake index 92cd15ca05dc..b1ee5ba93ac8 100644 --- a/cmake/nghttp2.cmake +++ b/cmake/nghttp2.cmake @@ -47,6 +47,23 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_library(nghttp2.snp STATIC ${NGHTTP2_SRCS}) + target_include_directories( + nghttp2.snp PUBLIC $ + $ + ) + target_compile_definitions( + nghttp2.snp PUBLIC -DNGHTTP2_STATICLIB -DHAVE_ARPA_INET_H=1 + ) + add_san(nghttp2.snp) + set_property(TARGET nghttp2.snp PROPERTY POSITION_INDEPENDENT_CODE ON) + + install( + TARGETS nghttp2.snp + EXPORT ccf + DESTINATION lib + ) endif() add_library(nghttp2.host STATIC ${NGHTTP2_SRCS}) diff --git a/cmake/protobuf.cmake b/cmake/protobuf.cmake index 036e66eda098..77e9640bb9ee 100644 --- a/cmake/protobuf.cmake +++ b/cmake/protobuf.cmake @@ -27,6 +27,14 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_host_library(protobuf.snp ${LIBPROTOBUF_SOURCES}) + list(APPEND PROTOBUF_TARGETS "protobuf.snp") + install( + TARGETS protobuf.snp + EXPORT ccf + DESTINATION lib + ) else() install( TARGETS protobuf.virtual diff --git a/cmake/qcbor.cmake b/cmake/qcbor.cmake index 6c72449c250f..32ac9ff6a6c9 100644 --- a/cmake/qcbor.cmake +++ b/cmake/qcbor.cmake @@ -21,6 +21,21 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_library(qcbor.snp STATIC ${QCBOR_SRCS}) + + target_include_directories( + qcbor.snp PUBLIC $ + $ + ) + set_property(TARGET qcbor.snp PROPERTY POSITION_INDEPENDENT_CODE ON) + add_san(qcbor.snp) + + install( + TARGETS qcbor.snp + EXPORT ccf + DESTINATION lib + ) endif() add_library(qcbor.host STATIC ${QCBOR_SRCS}) diff --git a/cmake/quickjs.cmake b/cmake/quickjs.cmake index 212596ed4ebe..2be5dec5a337 100644 --- a/cmake/quickjs.cmake +++ b/cmake/quickjs.cmake @@ -46,6 +46,25 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_library(quickjs.snp STATIC ${QUICKJS_SRC}) + target_compile_options( + quickjs.snp + PUBLIC -DCONFIG_VERSION="${QUICKJS_VERSION}" -DCONFIG_BIGNUM + PRIVATE $<$:-DDUMP_LEAKS> + ) + add_san(quickjs.snp) + set_property(TARGET quickjs.snp PROPERTY POSITION_INDEPENDENT_CODE ON) + target_include_directories( + quickjs.snp PUBLIC $ + $ + ) + + install( + TARGETS quickjs.snp + EXPORT ccf + DESTINATION lib + ) endif() add_library(quickjs.host STATIC ${QUICKJS_SRC}) diff --git a/cmake/sss.cmake b/cmake/sss.cmake index c659456f4457..0015d7ef41f8 100644 --- a/cmake/sss.cmake +++ b/cmake/sss.cmake @@ -18,6 +18,15 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + add_library(sss.snp STATIC ${SSS_SRC}) + add_san(sss.snp) + set_property(TARGET sss.snp PROPERTY POSITION_INDEPENDENT_CODE ON) + install( + TARGETS sss.snp + EXPORT ccf + DESTINATION lib + ) endif() add_library(sss.host STATIC ${SSS_SRC}) diff --git a/cmake/t_cose.cmake b/cmake/t_cose.cmake index ac3eae3b263d..18dfc2a94c30 100644 --- a/cmake/t_cose.cmake +++ b/cmake/t_cose.cmake @@ -33,6 +33,29 @@ if(COMPILE_TARGET STREQUAL "sgx") EXPORT ccf DESTINATION lib ) +elseif(COMPILE_TARGET STREQUAL "snp") + find_package(OpenSSL REQUIRED) + add_library(t_cose.snp STATIC ${T_COSE_SRCS}) + target_compile_definitions(t_cose.snp PRIVATE ${T_COSE_DEFS}) + target_compile_options(t_cose.snp INTERFACE ${T_COSE_OPTS_INTERFACE}) + + target_include_directories(t_cose.snp PRIVATE "${T_COSE_SRC}") + + target_include_directories( + t_cose.snp + PUBLIC $ + $ + ) + + target_link_libraries(t_cose.snp PUBLIC qcbor.snp crypto) + set_property(TARGET t_cose.snp PROPERTY POSITION_INDEPENDENT_CODE ON) + add_san(t_cose.snp) + + install( + TARGETS t_cose.snp + EXPORT ccf + DESTINATION lib + ) endif() find_package(OpenSSL REQUIRED) diff --git a/doc/host_config_schema/cchost_config.json b/doc/host_config_schema/cchost_config.json index 3cb053e585fd..5913e70c3377 100644 --- a/doc/host_config_schema/cchost_config.json +++ b/doc/host_config_schema/cchost_config.json @@ -11,11 +11,17 @@ "type": "string", "description": "Path to enclave application" }, + "platform": { + "type": "string", + "enum": ["SGX", "SNP", "Virtual"], + "default": "SGX", + "description": "Trusted Execution Environment platform" + }, "type": { "type": "string", "enum": ["Release", "Debug", "Virtual"], "default": "Release", - "description": "Type of enclave application" + "description": "Type of enclave application (only if platform is SGX). \"Virtual\" is deprecated (use ``platform`` instead)" } }, "description": "This section includes configuration for the enclave application launched by this node", diff --git a/samples/config/join_config.json b/samples/config/join_config.json index aafdd7acc1d8..608a5a913c7d 100644 --- a/samples/config/join_config.json +++ b/samples/config/join_config.json @@ -1,6 +1,7 @@ { "enclave": { "file": "libjs_generic.enclave.so.signed", + "platform": "SGX", "type": "Release" }, "network": { diff --git a/samples/config/minimal_config.json b/samples/config/minimal_config.json index 029691970554..1bb2ea0c10f7 100644 --- a/samples/config/minimal_config.json +++ b/samples/config/minimal_config.json @@ -1,6 +1,7 @@ { "enclave": { "file": "libjs_generic.enclave.so.signed", + "platform": "SGX", "type": "Release" }, "network": { diff --git a/samples/config/recover_config.json b/samples/config/recover_config.json index e18a16c8ecba..03c87d2d0d53 100644 --- a/samples/config/recover_config.json +++ b/samples/config/recover_config.json @@ -1,6 +1,7 @@ { "enclave": { "file": "libjs_generic.enclave.so.signed", + "platform": "SGX", "type": "Release" }, "network": { diff --git a/samples/config/start_config.json b/samples/config/start_config.json index 64e249a47274..e782a674ca7e 100644 --- a/samples/config/start_config.json +++ b/samples/config/start_config.json @@ -1,6 +1,7 @@ { "enclave": { "file": "libjs_generic.enclave.so.signed", + "platform": "SGX", "type": "Release" }, "network": { diff --git a/src/apps/external_executor/CMakeLists.txt b/src/apps/external_executor/CMakeLists.txt index a9fb888ba5c0..0648db34a890 100644 --- a/src/apps/external_executor/CMakeLists.txt +++ b/src/apps/external_executor/CMakeLists.txt @@ -23,6 +23,8 @@ add_ccf_app( LINK_LIBS_VIRTUAL executor_registration.proto.virtual kv.proto.virtual status.proto.virtual stringops.proto.virtual protobuf.virtual + LINK_LIBS_SNP executor_registration.proto.virtual kv.proto.virtual + status.proto.virtual stringops.proto.virtual protobuf.snp ) # Generate an ephemeral signing key diff --git a/src/host/configuration.h b/src/host/configuration.h index 2b871e853759..d859235ff595 100644 --- a/src/host/configuration.h +++ b/src/host/configuration.h @@ -13,16 +13,28 @@ namespace host { enum class EnclaveType { - SGX_RELEASE, - SGX_DEBUG, - VIRTUAL, + RELEASE, + DEBUG, + VIRTUAL // Deprecated (use EnclavePlatform instead) }; DECLARE_JSON_ENUM( EnclaveType, - {{EnclaveType::SGX_RELEASE, "Release"}, - {EnclaveType::SGX_DEBUG, "Debug"}, + {{EnclaveType::RELEASE, "Release"}, + {EnclaveType::DEBUG, "Debug"}, {EnclaveType::VIRTUAL, "Virtual"}}); + enum class EnclavePlatform + { + SGX, + SNP, + VIRTUAL, + }; + DECLARE_JSON_ENUM( + EnclavePlatform, + {{EnclavePlatform::SGX, "SGX"}, + {EnclavePlatform::SNP, "SNP"}, + {EnclavePlatform::VIRTUAL, "Virtual"}}); + enum class LogFormat { TEXT, @@ -51,6 +63,7 @@ namespace host { std::string file; EnclaveType type; + EnclavePlatform platform; }; Enclave enclave = {}; @@ -150,8 +163,9 @@ namespace host Command command = {}; }; - DECLARE_JSON_TYPE(CCHostConfig::Enclave); + DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCHostConfig::Enclave); DECLARE_JSON_REQUIRED_FIELDS(CCHostConfig::Enclave, type, file); + DECLARE_JSON_OPTIONAL_FIELDS(CCHostConfig::Enclave, platform); DECLARE_JSON_TYPE_WITH_OPTIONAL_FIELDS(CCHostConfig::OutputFiles); DECLARE_JSON_REQUIRED_FIELDS(CCHostConfig::OutputFiles); diff --git a/src/host/enclave.h b/src/host/enclave.h index ad776040b4ee..981c147c6a96 100644 --- a/src/host/enclave.h +++ b/src/host/enclave.h @@ -50,7 +50,7 @@ namespace host // suggested filename auto basename = file; for (const char* suffix : - {".signed", ".debuggable", ".so", ".enclave", ".virtual"}) + {".signed", ".debuggable", ".so", ".enclave", ".virtual", ".snp"}) { if (basename.ends_with(suffix)) { @@ -100,10 +100,11 @@ namespace host * Create an uninitialized enclave hosting the given library. * * @param path Path to signed enclave library file - * @param type Type of enclave to load, influencing what flags should be - * passed to OE, or whether to dlload a virtual enclave + * @param type Type of enclave to load + * @param platform Trusted Execution Platform of enclave, influencing what + * flags should be passed to OE, or whether to dlload a virtual enclave */ - Enclave(const std::string& path, EnclaveType type) + Enclave(const std::string& path, EnclaveType type, EnclavePlatform platform) { if (!std::filesystem::exists(path)) { @@ -111,14 +112,13 @@ namespace host fmt::format("No enclave file found at {}", path)); } - switch (type) + switch (platform) { - case host::EnclaveType::SGX_RELEASE: - case host::EnclaveType::SGX_DEBUG: + case host::EnclavePlatform::SGX: { #ifdef PLATFORM_SGX uint32_t oe_flags = 0; - if (type == host::EnclaveType::SGX_DEBUG) + if (type == host::EnclaveType::DEBUG) { expect_enclave_file_suffix(path, ".enclave.so.debuggable", type); oe_flags |= OE_ENCLAVE_FLAG_DEBUG; @@ -147,19 +147,31 @@ namespace host } #else throw std::logic_error( - "SGX enclaves are not supported in current build"); + "Only SGX enclaves are supported in current build"); #endif // PLATFORM_SGX break; } - case host::EnclaveType::VIRTUAL: + case host::EnclavePlatform::SNP: { -#if defined(PLATFORM_VIRTUAL) || defined(PLATFORM_SNP) +#if defined(PLATFORM_SNP) + expect_enclave_file_suffix(path, ".snp.so", type); + virtual_handle = load_virtual_enclave(path.c_str()); +#else + throw std::logic_error( + "Only SNP enclaves are supported in current build"); +#endif // defined(PLATFORM_VIRTUAL) || defined(PLATFORM_SNP) + break; + } + + case host::EnclavePlatform::VIRTUAL: + { +#if defined(PLATFORM_VIRTUAL) expect_enclave_file_suffix(path, ".virtual.so", type); virtual_handle = load_virtual_enclave(path.c_str()); #else throw std::logic_error( - "Virtual enclaves not supported in current build"); + "Only Virtual enclaves are supported in current build"); #endif // defined(PLATFORM_VIRTUAL) || defined(PLATFORM_SNP) break; } diff --git a/src/host/main.cpp b/src/host/main.cpp index 73b51e66e728..7c33b4fc454e 100644 --- a/src/host/main.cpp +++ b/src/host/main.cpp @@ -194,7 +194,8 @@ int main(int argc, char** argv) config.slow_io_logging_threshold; // create the enclave - host::Enclave enclave(config.enclave.file, config.enclave.type); + host::Enclave enclave( + config.enclave.file, config.enclave.type, config.enclave.platform); // messaging ring buffers const auto buffer_size = config.memory.circuit_size; diff --git a/tests/code_update.py b/tests/code_update.py index 85c9aa812360..3006a0f1e9b6 100644 --- a/tests/code_update.py +++ b/tests/code_update.py @@ -28,7 +28,7 @@ @reqs.description("Verify node evidence") def test_verify_quotes(network, args): - if args.enclave_type == "virtual": + if args.enclave_platform == "virtual": LOG.warning("Skipping quote test with virtual enclave") return network elif IS_SNP: @@ -219,7 +219,7 @@ def test_add_node_with_bad_host_data(network, args): @reqs.description("Node with bad code fails to join") def test_add_node_with_bad_code(network, args): - if args.enclave_type not in ("release", "debug"): + if args.enclave_platform != "sgx": LOG.warning("Skipping test_add_node_with_bad_code with non-sgx enclave") return network @@ -230,7 +230,7 @@ def test_add_node_with_bad_code(network, args): ) new_code_id = infra.utils.get_code_id( - args.enclave_type, args.oe_binary, replacement_package + args.enclave_type, args.enclave_platform, args.oe_binary, replacement_package ) LOG.info(f"Adding a node with unsupported code id {new_code_id}") @@ -264,13 +264,13 @@ def test_update_all_nodes(network, args): primary, _ = network.find_nodes() first_code_id = infra.utils.get_code_id( - args.enclave_type, args.oe_binary, args.package + args.enclave_type, args.enclave_platform, args.oe_binary, args.package ) new_code_id = infra.utils.get_code_id( - args.enclave_type, args.oe_binary, replacement_package + args.enclave_type, args.enclave_platform, args.oe_binary, replacement_package ) - if args.enclave_type == "virtual": + if args.enclave_platform == "virtual": # Pretend this was already present network.consortium.add_new_code(primary, first_code_id) @@ -283,7 +283,7 @@ def test_update_all_nodes(network, args): {"digest": first_code_id, "status": "AllowedToJoin"}, {"digest": new_code_id, "status": "AllowedToJoin"}, ] - if args.enclave_type == "virtual": + if args.enclave_platform == "virtual": expected.insert(0, {"digest": VIRTUAL_CODE_ID, "status": "AllowedToJoin"}) versions = sorted(r.body.json()["versions"], key=lambda x: x["digest"]) @@ -298,7 +298,7 @@ def test_update_all_nodes(network, args): {"digest": first_code_id, "status": "AllowedToJoin"}, {"digest": new_code_id, "status": "AllowedToJoin"}, ] - if args.enclave_type == "virtual": + if args.enclave_platform == "virtual": expected.insert(0, {"digest": VIRTUAL_CODE_ID, "status": "AllowedToJoin"}) expected.sort(key=lambda x: x["digest"]) @@ -344,7 +344,10 @@ def test_proposal_invalidation(network, args): LOG.info("Add temporary code ID") temp_code_id = infra.utils.get_code_id( - args.enclave_type, args.oe_binary, get_replacement_package(args) + args.enclave_type, + args.enclave_platform, + args.oe_binary, + get_replacement_package(args), ) network.consortium.add_new_code(primary, temp_code_id) diff --git a/tests/config.jinja b/tests/config.jinja index 1d25eda9522e..ae66c2bfbebd 100644 --- a/tests/config.jinja +++ b/tests/config.jinja @@ -1,7 +1,8 @@ { "enclave": { "file": "{{ enclave_file }}", - "type": "{{ enclave_type }}" + "type": "{{ enclave_type }}", + "platform": "{{ enclave_platform }}" }, "network": { "node_to_node_interface": { "bind_address": "{{ node_address }}" }, diff --git a/tests/governance.py b/tests/governance.py index c1176474bfc8..83559b6b7d35 100644 --- a/tests/governance.py +++ b/tests/governance.py @@ -49,7 +49,7 @@ def test_consensus_status(network, args): @reqs.description("Test quotes") @reqs.supports_methods("/app/quotes/self", "/app/quotes") def test_quote(network, args): - if args.enclave_type == "virtual": + if args.enclave_platform == "virtual": LOG.warning("Quote test can only run in real enclaves, skipping") return network @@ -60,7 +60,9 @@ def test_quote(network, args): os.path.join(args.oe_binary, "oesign"), "dump", "-e", - infra.path.build_lib_path(args.package, args.enclave_type), + infra.path.build_lib_path( + args.package, args.enclave_type, args.enclave_platform + ), ], capture_output=True, check=True, diff --git a/tests/infra/e2e_args.py b/tests/infra/e2e_args.py index 8a289e9bb827..d48cd020f9c3 100644 --- a/tests/infra/e2e_args.py +++ b/tests/infra/e2e_args.py @@ -106,6 +106,7 @@ def cli_args(add=lambda x: None, parser=None, accept_unknown=False): action="append", default=[], ) + # "virtual" is deprecated (use enclave-platform) parser.add_argument( "-e", "--enclave-type", @@ -113,6 +114,13 @@ def cli_args(add=lambda x: None, parser=None, accept_unknown=False): default=os.getenv("TEST_ENCLAVE", os.getenv("DEFAULT_ENCLAVE_TYPE", "release")), choices=("release", "debug", "virtual"), ) + parser.add_argument( + "-t", + "--enclave-platform", + help="Enclave platform (Trusted Execution Environment)", + default=os.getenv("TEST_ENCLAVE", os.getenv("DEFAULT_ENCLAVE_PLATFORM", "sgx")), + choices=("sgx", "snp", "virtual"), + ) parser.add_argument( "--host-log-level", help="Runtime host log level", diff --git a/tests/infra/network.py b/tests/infra/network.py index 98b8352b90a6..23b99033462b 100644 --- a/tests/infra/network.py +++ b/tests/infra/network.py @@ -100,6 +100,7 @@ class Network: SHARE_SCRIPT = "submit_recovery_share.sh" node_args_to_forward = [ "enclave_type", + "enclave_platform", "host_log_level", "sig_tx_interval", "sig_ms_interval", diff --git a/tests/infra/node.py b/tests/infra/node.py index f271674ff504..dd265a98ad91 100644 --- a/tests/infra/node.py +++ b/tests/infra/node.py @@ -261,6 +261,7 @@ def _start( label, common_dir, members_info=None, + enclave_platform="sgx", **kwargs, ): """ @@ -271,7 +272,7 @@ def _start( prompt the user to do so manually. """ lib_path = infra.path.build_lib_path( - lib_name, enclave_type, library_dir=self.library_dir + lib_name, enclave_type, enclave_platform, library_dir=self.library_dir ) self.common_dir = common_dir members_info = members_info or [] @@ -297,6 +298,7 @@ def _start( version=self.version, major_version=self.major_version, node_data_json_file=self.initial_node_data_json_file, + enclave_platform=enclave_platform, **kwargs, ) self.remote.setup() diff --git a/tests/infra/path.py b/tests/infra/path.py index 54859acd347f..08e35dd1a76d 100644 --- a/tests/infra/path.py +++ b/tests/infra/path.py @@ -20,18 +20,26 @@ def mk_new(name, contents): mk(name, contents) -def build_lib_path(lib_name, enclave_type=None, library_dir="."): - if enclave_type == "virtual": +def build_lib_path( + lib_name, enclave_type=None, enclave_platform="sgx", library_dir="." +): + if enclave_platform == "virtual" or enclave_type == "virtual": ext = ".virtual.so" mode = "Virtual mode" - elif enclave_type == "debug": - ext = ".enclave.so.debuggable" - mode = "Debuggable enclave" - elif enclave_type == "release": - ext = ".enclave.so.signed" - mode = "Real enclave" + elif enclave_platform == "sgx": + if enclave_type == "debug": + ext = ".enclave.so.debuggable" + mode = "Debuggable SGX enclave" + elif enclave_type == "release": + ext = ".enclave.so.signed" + mode = "Release SGX enclave" + else: + raise ValueError(f"Invalid enclave_type {enclave_type} for SGX enclave") + elif enclave_platform == "snp": + ext = ".snp.so" + mode = "SNP enclave" else: - raise ValueError(f"Invalid enclave_type passed {enclave_type}") + raise ValueError(f"Invalid enclave_platform passed {enclave_platform}") if os.path.isfile(lib_name): if ext not in lib_name: raise ValueError(f"{mode} requires {ext} enclave image") diff --git a/tests/infra/remote.py b/tests/infra/remote.py index 29ae5ef346be..ec647706f7a7 100644 --- a/tests/infra/remote.py +++ b/tests/infra/remote.py @@ -602,6 +602,7 @@ def __init__( service_data_json_file=None, snp_endorsements_servers=None, node_pid_file="node.pid", + enclave_platform="sgx", **kwargs, ): """ @@ -714,6 +715,9 @@ def __init__( start_type=start_type.name.title(), enclave_file=self.enclave_file, enclave_type=enclave_type.title(), + enclave_platform=enclave_platform.title() + if enclave_platform == "virtual" + else enclave_platform.upper(), rpc_interfaces=infra.interfaces.HostSpec.to_json(host), node_certificate_file=self.pem, node_address_file=self.node_address_file, diff --git a/tests/infra/utils.py b/tests/infra/utils.py index 51fde8bfd60b..6e023f7ba672 100644 --- a/tests/infra/utils.py +++ b/tests/infra/utils.py @@ -6,12 +6,14 @@ import subprocess -def get_code_id(enclave_type, oe_binary_dir, package, library_dir="."): - lib_path = infra.path.build_lib_path(package, enclave_type, library_dir) +def get_code_id( + enclave_type, enclave_platform, oe_binary_dir, package, library_dir="." +): + lib_path = infra.path.build_lib_path( + package, enclave_type, enclave_platform, library_dir + ) - if enclave_type == "virtual": - return hashlib.sha384(lib_path.encode()).hexdigest() - else: + if enclave_platform == "sgx": res = subprocess.run( [os.path.join(oe_binary_dir, "oesign"), "dump", "-e", lib_path], capture_output=True, @@ -24,3 +26,6 @@ def get_code_id(enclave_type, oe_binary_dir, package, library_dir="."): ] return lines[0].split("=")[1] + else: + # Virtual and SNP + return hashlib.sha384(lib_path.encode()).hexdigest() diff --git a/tests/js-modules/modules.py b/tests/js-modules/modules.py index 8996911a753f..7f07c5ff4d3c 100644 --- a/tests/js-modules/modules.py +++ b/tests/js-modules/modules.py @@ -798,7 +798,7 @@ def test_npm_app(network, args): r = c.get("/node/quotes/self") primary_quote_info = r.body.json() - if args.enclave_type not in ("release", "debug"): + if args.enclave_platform != "sgx": LOG.info("Skipping /app/verifyOpenEnclaveEvidence test, non-sgx node") else: # See /opt/openenclave/include/openenclave/attestation/sgx/evidence.h diff --git a/tests/jwt_test.py b/tests/jwt_test.py index 606f6b45837c..d53e3472978b 100644 --- a/tests/jwt_test.py +++ b/tests/jwt_test.py @@ -556,7 +556,7 @@ def run_auto(args): network.start_and_open(args) test_jwt_endpoint(network, args) test_jwt_without_key_policy(network, args) - if args.enclave_type in ("release", "debug"): + if args.enclave_platform == "sgx": test_jwt_with_sgx_key_policy(network, args) test_jwt_with_sgx_key_filter(network, args) test_jwt_key_auto_refresh(network, args) diff --git a/tests/lts_compatibility.py b/tests/lts_compatibility.py index 93ba37ac412d..f9754afdf339 100644 --- a/tests/lts_compatibility.py +++ b/tests/lts_compatibility.py @@ -40,16 +40,6 @@ DEFAULT_NODE_CERTIFICATE_VALIDITY_DAYS = 365 -def platform_from_enclave_type(enclave_type): - if enclave_type == "virtual": - if IS_SNP: - return "snp" - else: - return "virtual" - else: - return "sgx" - - def issue_activity_on_live_service(network, args): log_capture = [] network.txs.issue( @@ -241,6 +231,7 @@ def run_code_upgrade_from( new_code_id = infra.utils.get_code_id( args.enclave_type, + args.enclave_platform, args.oe_binary, args.package, library_dir=to_library_dir, @@ -294,6 +285,7 @@ def run_code_upgrade_from( old_code_id = infra.utils.get_code_id( args.enclave_type, + args.enclave_platform, args.oe_binary, args.package, library_dir=from_library_dir, @@ -412,7 +404,7 @@ def run_live_compatibility_with_latest( lts_version, lts_install_path = repo.install_latest_lts_for_branch( os.getenv(ENV_VAR_LATEST_LTS_BRANCH_NAME, local_branch), this_release_branch_only, - platform=platform_from_enclave_type(args.enclave_type), + platform=args.enclave_platform, ) else: lts_version = infra.github.get_version_from_install(lts_install_path) @@ -468,7 +460,8 @@ def run_ledger_compatibility_since_first(args, local_branch, use_snapshot): for idx, (_, lts_release) in enumerate(lts_releases.items()): if lts_release: version, install_path = repo.install_release( - lts_release, platform_from_enclave_type(args.enclave_type) + lts_release, + platform=args.enclave_platform, ) lts_versions.append(version) set_js_args(args, install_path) @@ -624,6 +617,11 @@ def add(parser): # Hardcoded because host only accepts info log on release builds args.host_log_level = "info" + # For compatibility with <= 2.x versions as enclave platform + # was introduced in 3.x + if args.enclave_platform == "virtual": + args.enclave_type = "virtual" + repo = infra.github.Repository() local_branch = infra.github.GitEnv.local_branch() diff --git a/tests/nobuiltins.py b/tests/nobuiltins.py index f759e0dd548b..88af28509a49 100644 --- a/tests/nobuiltins.py +++ b/tests/nobuiltins.py @@ -5,7 +5,6 @@ import openapi_spec_validator from datetime import datetime, timezone import time -from infra.is_snp import IS_SNP def test_nobuiltins_endpoints(network, args): @@ -21,15 +20,14 @@ def test_nobuiltins_endpoints(network, args): body_j = r.body.json() assert body_j["committed_view"] >= tx_id.view assert body_j["committed_seqno"] >= tx_id.seqno - if args.enclave_type in ("release", "debug"): + if args.enclave_platform == "sgx": expected_format = "OE_SGX_v1" - elif args.enclave_type == "virtual": - if IS_SNP: - expected_format = "AMD_SEV_SNP_v1" - else: - expected_format = "Insecure_Virtual" + elif args.enclave_platform == "virtual": + expected_format = "Insecure_Virtual" + elif args.enclave_platform == "snp": + expected_format = "AMD_SEV_SNP_v1" else: - raise ValueError(f"Unhandled enclave_type = {args.enclave_type}") + raise ValueError(f"Unhandled enclave platform = {args.enclave_platform}") assert body_j["quote_format"] == expected_format, body_j["quote_format"] assert body_j["node_id"] == primary.node_id diff --git a/tests/reconfiguration.py b/tests/reconfiguration.py index ffffe0f6e92b..4a71ca9a2ee8 100644 --- a/tests/reconfiguration.py +++ b/tests/reconfiguration.py @@ -505,7 +505,7 @@ def test_issue_fake_join(network, args): r = c.post("/node/join", body=req) assert r.status_code == http.HTTPStatus.UNAUTHORIZED assert r.body.json()["error"]["code"] == "InvalidQuote" - if args.enclave_type not in ("release", "debug"): + if args.enclave_platform != "sgx": assert r.body.json()["error"]["message"] == "Quote could not be verified" else: assert ( @@ -520,7 +520,7 @@ def test_issue_fake_join(network, args): "endorsements": own_quote["endorsements"], } r = c.post("/node/join", body=req) - if args.enclave_type != "snp": + if args.enclave_platform != "snp": assert r.status_code == http.HTTPStatus.UNAUTHORIZED # https://github.com/microsoft/CCF/issues/4072 assert ( @@ -539,7 +539,7 @@ def test_issue_fake_join(network, args): "endorsements": "", } r = c.post("/node/join", body=req) - if args.enclave_type == "virtual" and not IS_SNP: + if args.enclave_platform == "virtual": assert r.status_code == http.HTTPStatus.OK assert r.body.json()["node_status"] == ccf.ledger.NodeStatus.PENDING.value else: diff --git a/tests/sandbox/sandbox.sh b/tests/sandbox/sandbox.sh index 54bd2899f4e6..c1dd8de65551 100755 --- a/tests/sandbox/sandbox.sh +++ b/tests/sandbox/sandbox.sh @@ -91,6 +91,7 @@ export CURL_CLIENT_USE_COSE=ON exec python "${START_NETWORK_SCRIPT}" \ --binary-dir "${BINARY_DIR}" \ --enclave-type "${enclave_type}" \ + --enclave-platform "${platform}" \ --initial-member-count 1 \ --constitution "${PATH_HERE}"/actions.js \ --constitution "${PATH_HERE}"/validate.js \ diff --git a/tests/start_network.py b/tests/start_network.py index 28e7a305c1c0..bd986e5a1443 100644 --- a/tests/start_network.py +++ b/tests/start_network.py @@ -39,7 +39,7 @@ def run(args): LOG.disable("infra") LOG.disable("ccf") - if args.enclave_type == "virtual": + if args.enclave_platform == "virtual": LOG.warning("Virtual mode enabled") LOG.info(f"Starting {len(hosts)} CCF node{'s' if len(hosts) > 1 else ''}...")