├── .bazelrc ├── AUTHORS ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── WORKSPACE ├── grpc_server ├── BUILD ├── README.md ├── grpc_server_config.proto ├── grpc_server_driver.cc ├── grpc_server_enclave.cc ├── grpc_server_test.cc ├── grpc_server_util.cc ├── grpc_server_util.h ├── translator_client.cc ├── translator_client.h ├── translator_server.proto ├── translator_server_impl.cc └── translator_server_impl.h ├── hello_world ├── BUILD ├── hello.proto ├── hello_driver.cc └── hello_enclave.cc ├── java └── quickstart_client │ ├── BUILD │ ├── README.md │ └── src │ └── main │ └── java │ └── com │ └── example │ └── DemoDriver.java ├── quickstart ├── BUILD ├── README.md ├── demo.proto ├── demo_driver.cc ├── demo_enclave.cc └── solution │ ├── BUILD │ ├── demo.proto │ ├── demo_driver.cc │ └── demo_enclave.cc ├── redis ├── BUILD ├── README.md ├── redis_enclave_config.cc └── redis_test.cc ├── remote ├── bouncing_circles │ ├── BUILD │ ├── README.md │ ├── build.sh │ ├── circle_client.cc │ ├── circle_client.h │ ├── circle_enclave.cc │ ├── circles.proto │ ├── web_application.cc │ ├── web_server.cc │ ├── web_server.h │ └── web_server_test.cc ├── grpc_server │ ├── BUILD │ └── grpc_server_driver.cc ├── provision_server │ ├── BUILD │ ├── README.md │ ├── base64_server_cert │ ├── base64_server_key │ └── build.sh └── quickstart │ ├── BUILD │ ├── README.md │ ├── build.sh │ ├── demo.proto │ ├── demo_driver.cc │ ├── demo_enclave.cc │ └── demo_enclave_remote_test.cc ├── secure_grpc ├── BUILD ├── README.md ├── acl_isvprodid_2.textproto ├── acl_isvprodid_3.textproto ├── acl_non_debug.textproto ├── attestation_domain.cc ├── attestation_domain.h ├── grpc_client_enclave.cc ├── grpc_client_enclave.h ├── grpc_client_enclave.proto ├── grpc_client_main.cc ├── grpc_client_util.cc ├── grpc_client_util.h ├── grpc_server_config.proto ├── grpc_server_enclave.cc ├── grpc_server_main.cc ├── grpc_server_util.cc ├── grpc_server_util.h ├── secure_grpc_test.cc ├── translator_server_impl.cc └── translator_server_impl.h ├── sgx_release_enclaves └── README.md └── sqlite └── README.md /.bazelrc: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | build:asylo --crosstool_top=@com_google_asylo_toolchain//toolchain:crosstool 18 | build:asylo --dynamic_mode=off 19 | build:asylo --host_crosstool_top=@bazel_tools//tools/cpp:toolchain 20 | build:asylo --fission=no 21 | build:asylo --custom_malloc=@com_google_asylo_toolchain//toolchain:malloc 22 | build:asylo --define=grpc_no_ares=true 23 | 24 | build:sgx --config=asylo 25 | build:sgx --define=ASYLO_SGX=1 26 | build:sgx --define=SGX_SIM=0 27 | 28 | build:sgx-sim --config=asylo 29 | build:sgx-sim --define=ASYLO_SGX=1 30 | build:sgx-sim --define=SGX_SIM=1 31 | 32 | # The enclave simulation backend currently makes use of the SGX simulator. 33 | # However, this is subject to change and users of this config should not 34 | # make assumptions about it being related to SGX. 35 | build:enc-sim --config=sgx-sim 36 | 37 | build:asylo-dlopen --config=asylo 38 | build:asylo-dlopen --define=ASYLO_DLOPEN=1 39 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the list of Asylo's significant contributors. 2 | # 3 | # This does not necessarily list everyone who has contributed code, 4 | # especially since many employees of one corporation may be contributing. 5 | # To see the full list of contributors, see the revision history in 6 | # source control. 7 | Google LLC 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | workspace(name = "asylo_examples") 2 | 3 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 4 | 5 | # Download and use the Asylo SDK. 6 | http_archive( 7 | name = "com_google_asylo", 8 | sha256 = "21e2798a345d4d508c4f09c4b92c7cdc06a445d8fca4094e3751cde48d1d27c9", 9 | strip_prefix = "asylo-0.6.3", 10 | urls = ["https://github.com/google/asylo/archive/v0.6.3.tar.gz"], 11 | ) 12 | 13 | load( 14 | "@com_google_asylo//asylo/bazel:asylo_deps.bzl", 15 | "asylo_deps", 16 | "asylo_testonly_deps", 17 | ) 18 | 19 | asylo_deps() 20 | 21 | asylo_testonly_deps() 22 | 23 | # sgx_deps is only needed if @linux_sgx is used. 24 | load("@com_google_asylo//asylo/bazel:sgx_deps.bzl", "sgx_deps") 25 | 26 | sgx_deps() 27 | 28 | # remote_deps is only needed if remote backend is used. 29 | load("@com_google_asylo//asylo/bazel:remote_deps.bzl", "remote_deps") 30 | 31 | remote_deps() 32 | 33 | # grpc_deps is only needed if gRPC is used. Projects using gRPC as an external 34 | # dependency must call both grpc_deps() and grpc_extra_deps(). 35 | load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps") 36 | 37 | grpc_deps() 38 | 39 | load("@com_github_grpc_grpc//bazel:grpc_extra_deps.bzl", "grpc_extra_deps") 40 | 41 | grpc_extra_deps() 42 | -------------------------------------------------------------------------------- /grpc_server/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library") 18 | load("@linux_sgx//:sgx_sdk.bzl", "sgx") 19 | load("@rules_cc//cc:defs.bzl", "cc_library", "cc_proto_library") 20 | load("@rules_proto//proto:defs.bzl", "proto_library") 21 | load( 22 | "@com_google_asylo//asylo/bazel:asylo.bzl", 23 | "ASYLO_ALL_BACKEND_TAGS", 24 | "cc_unsigned_enclave", 25 | "debug_sign_enclave", 26 | "enclave_loader", 27 | "enclave_test", 28 | ) 29 | 30 | licenses(["notice"]) # Apache v2.0 31 | 32 | # Example demonstrating gRPC in Asylo. 33 | 34 | package( 35 | default_visibility = ["//visibility:public"], 36 | ) 37 | 38 | # The generated code for the translator server (and client). 39 | proto_library( 40 | name = "translator_server_proto", 41 | srcs = ["translator_server.proto"], 42 | tags = ASYLO_ALL_BACKEND_TAGS, 43 | ) 44 | 45 | cc_proto_library( 46 | name = "translator_server_cc_proto", 47 | tags = ASYLO_ALL_BACKEND_TAGS, 48 | deps = [":translator_server_proto"], 49 | ) 50 | 51 | cc_grpc_library( 52 | name = "translator_server", 53 | srcs = [":translator_server_proto"], 54 | grpc_only = True, 55 | tags = ASYLO_ALL_BACKEND_TAGS, 56 | deps = [":translator_server_cc_proto"], 57 | ) 58 | 59 | # The implementation of the translation server. 60 | cc_library( 61 | name = "translator_server_impl", 62 | srcs = ["translator_server_impl.cc"], 63 | hdrs = ["translator_server_impl.h"], 64 | tags = ASYLO_ALL_BACKEND_TAGS, 65 | deps = [ 66 | ":translator_server", 67 | "@com_github_grpc_grpc//:grpc++", 68 | "@com_google_absl//absl/base:core_headers", 69 | "@com_google_absl//absl/container:flat_hash_map", 70 | "@com_google_absl//absl/strings", 71 | "@com_google_absl//absl/synchronization", 72 | ], 73 | ) 74 | 75 | # Contains extensions to enclave protos. 76 | proto_library( 77 | name = "grpc_server_config_proto", 78 | srcs = ["grpc_server_config.proto"], 79 | deps = ["@com_google_asylo//asylo:enclave_proto"], 80 | ) 81 | 82 | cc_proto_library( 83 | name = "grpc_server_config_cc_proto", 84 | deps = [":grpc_server_config_proto"], 85 | ) 86 | 87 | # The enclave hosting the translation server. 88 | cc_unsigned_enclave( 89 | name = "grpc_server_enclave_unsigned.so", 90 | srcs = ["grpc_server_enclave.cc"], 91 | backends = sgx.backend_labels, 92 | deps = [ 93 | ":grpc_server_config_cc_proto", 94 | ":translator_server_impl", 95 | "@com_github_grpc_grpc//:grpc++", 96 | "@com_github_grpc_grpc//:grpc++_reflection", 97 | "@com_google_absl//absl/base:core_headers", 98 | "@com_google_absl//absl/memory", 99 | "@com_google_absl//absl/status", 100 | "@com_google_absl//absl/strings", 101 | "@com_google_absl//absl/synchronization", 102 | "@com_google_absl//absl/time", 103 | "@com_google_asylo//asylo:enclave_runtime", 104 | "@com_google_asylo//asylo/util:status", 105 | ], 106 | ) 107 | 108 | debug_sign_enclave( 109 | name = "grpc_server_enclave.so", 110 | backends = sgx.backend_labels, 111 | config = "@com_google_asylo//asylo/grpc/util:grpc_enclave_config", 112 | unsigned = "grpc_server_enclave_unsigned.so", 113 | ) 114 | 115 | # The driver for the gRPC server enclave. 116 | enclave_loader( 117 | name = "grpc_server", 118 | srcs = ["grpc_server_driver.cc"], 119 | enclaves = {"enclave": ":grpc_server_enclave.so"}, 120 | loader_args = ["--enclave_path='{enclave}'"], 121 | deps = [ 122 | ":grpc_server_util", 123 | "@com_google_absl//absl/flags:flag", 124 | "@com_google_absl//absl/flags:parse", 125 | "@com_google_absl//absl/time", 126 | "@com_google_asylo//asylo:enclave_client", 127 | "@com_google_asylo//asylo/util:logging", 128 | "@com_google_asylo//asylo/util:status", 129 | ], 130 | ) 131 | 132 | cc_library( 133 | name = "grpc_server_util", 134 | srcs = ["grpc_server_util.cc"], 135 | hdrs = ["grpc_server_util.h"], 136 | deps = [ 137 | ":grpc_server_config_cc_proto", 138 | "@com_google_absl//absl/strings", 139 | "@com_google_asylo//asylo:enclave_cc_proto", 140 | "@com_google_asylo//asylo:enclave_client", 141 | "@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto", 142 | "@com_google_asylo//asylo/util:status", 143 | "@com_google_protobuf//:protobuf", 144 | ], 145 | ) 146 | 147 | # A test of the example using the server enclave. 148 | enclave_test( 149 | name = "grpc_server_test", 150 | srcs = ["grpc_server_test.cc"], 151 | backend_dependent_data = [":grpc_server_host_loader"], 152 | backends = sgx.backend_labels, 153 | enclaves = {"server_enclave": ":grpc_server_enclave.so"}, 154 | test_args = [ 155 | "--server_enclave_path='{server_enclave}'", 156 | ], 157 | deps = [ 158 | ":grpc_server_util", 159 | ":translator_client", 160 | ":translator_server_impl", 161 | "@com_github_grpc_grpc//:grpc++", 162 | "@com_google_absl//absl/base:core_headers", 163 | "@com_google_absl//absl/flags:flag", 164 | "@com_google_absl//absl/memory", 165 | "@com_google_absl//absl/strings", 166 | "@com_google_asylo//asylo:enclave_client", 167 | "@com_google_asylo//asylo/test/util:status_matchers", 168 | "@com_google_asylo//asylo/test/util:test_main", 169 | "@com_google_asylo//asylo/util:path", 170 | "@com_google_asylo//asylo/util:status", 171 | "@com_google_googletest//:gtest", 172 | ], 173 | ) 174 | 175 | cc_library( 176 | name = "translator_client", 177 | testonly = 1, 178 | srcs = ["translator_client.cc"], 179 | hdrs = ["translator_client.h"], 180 | deps = [ 181 | ":translator_server", 182 | ":translator_server_cc_proto", 183 | "@com_github_grpc_grpc//:grpc", 184 | "@com_github_grpc_grpc//:grpc++", 185 | "@com_google_absl//absl/memory", 186 | "@com_google_absl//absl/status", 187 | "@com_google_absl//absl/strings", 188 | "@com_google_absl//absl/time", 189 | "@com_google_asylo//asylo/util:status", 190 | "@com_google_asylo//asylo/util:status_helpers", 191 | ], 192 | ) 193 | -------------------------------------------------------------------------------- /grpc_server/grpc_server_config.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2018 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package examples.grpc_server; 20 | 21 | import "asylo/enclave.proto"; 22 | 23 | extend asylo.EnclaveConfig { 24 | // The address that the gRPC server inside the enclave will be hosted on. 25 | // Required. 26 | optional string server_address = 205739939; 27 | 28 | // The port that the gRPC server should listen to. May be 0 to request that 29 | // the server let the operating system choose an unused port. 30 | optional int32 port = 253106740; 31 | } 32 | 33 | extend asylo.EnclaveOutput { 34 | // The Translator server's port. 35 | optional int32 actual_server_port = 285084421; 36 | } 37 | -------------------------------------------------------------------------------- /grpc_server/grpc_server_driver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/flags/flag.h" 23 | #include "absl/flags/parse.h" 24 | #include "absl/time/clock.h" 25 | #include "asylo/enclave_manager.h" 26 | #include "asylo/util/logging.h" 27 | #include "asylo/util/status.h" 28 | #include "asylo/util/statusor.h" 29 | #include "grpc_server/grpc_server_util.h" 30 | 31 | ABSL_FLAG(std::string, enclave_path, "", "Path to enclave to load"); 32 | 33 | // By default, let the server run for five minutes. 34 | ABSL_FLAG(int32_t, server_max_lifetime, 300, 35 | "The longest amount of time (in seconds) that the server should be " 36 | "allowed to run"); 37 | 38 | // Default value 0 is used to indicate that the system should choose an 39 | // available port. 40 | ABSL_FLAG(int32_t, port, 0, "Port that the server listens to"); 41 | ABSL_FLAG(bool, debug, true, "Whether to use a debug enclave"); 42 | 43 | int main(int argc, char *argv[]) { 44 | // Parse command-line arguments. 45 | absl::ParseCommandLine(argc, argv); 46 | 47 | std::string enclave_path = absl::GetFlag(FLAGS_enclave_path); 48 | LOG_IF(QFATAL, enclave_path.empty()) << "--enclave_path cannot be empty"; 49 | 50 | asylo::Status status = 51 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions()); 52 | LOG_IF(QFATAL, !status.ok()) 53 | << "Failed to configure EnclaveManager: " << status; 54 | 55 | status = examples::grpc_server::LoadGrpcServerEnclave( 56 | enclave_path, absl::GetFlag(FLAGS_port), absl::GetFlag(FLAGS_debug)); 57 | LOG_IF(QFATAL, !status.ok()) 58 | << "Loading " << enclave_path << " failed: " << status; 59 | 60 | asylo::StatusOr port_result = 61 | examples::grpc_server::GrpcServerEnclaveGetPort(); 62 | LOG_IF(QFATAL, !port_result.ok()) 63 | << "Retrieving port failed: " << port_result.status(); 64 | 65 | std::cout << "Server started on port " << port_result.value() << std::endl; 66 | 67 | absl::SleepFor(absl::Seconds(absl::GetFlag(FLAGS_server_max_lifetime))); 68 | 69 | status = examples::grpc_server::DestroyGrpcServerEnclave(); 70 | LOG_IF(QFATAL, !status.ok()) 71 | << "Destroy " << enclave_path << " failed: " << status; 72 | 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /grpc_server/grpc_server_enclave.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/base/thread_annotations.h" 23 | #include "absl/status/status.h" 24 | #include "absl/strings/str_cat.h" 25 | #include "absl/synchronization/mutex.h" 26 | #include "absl/synchronization/notification.h" 27 | #include "absl/time/time.h" 28 | #include "asylo/trusted_application.h" 29 | #include "asylo/util/status.h" 30 | #include "asylo/util/status_macros.h" 31 | #include "grpc_server/grpc_server_config.pb.h" 32 | #include "grpc_server/translator_server_impl.h" 33 | #include "include/grpcpp/grpcpp.h" 34 | #include "include/grpcpp/security/server_credentials.h" 35 | #include "include/grpcpp/server.h" 36 | #include "include/grpcpp/server_builder.h" 37 | 38 | namespace examples { 39 | namespace grpc_server { 40 | 41 | // An enclave that runs a TranslatorServerImpl. We override the methods of 42 | // TrustedApplication as follows: 43 | // 44 | // * Initialize starts the gRPC server. 45 | // * Run retrieves the server port. 46 | // * Finalize shuts down the server. 47 | class GrpcServerEnclave final : public asylo::TrustedApplication { 48 | public: 49 | asylo::Status Initialize(const asylo::EnclaveConfig &enclave_config) 50 | ABSL_LOCKS_EXCLUDED(server_mutex_) override; 51 | 52 | asylo::Status Run(const asylo::EnclaveInput &enclave_input, 53 | asylo::EnclaveOutput *enclave_output) override; 54 | 55 | asylo::Status Finalize(const asylo::EnclaveFinal &enclave_final) 56 | ABSL_LOCKS_EXCLUDED(server_mutex_) override; 57 | 58 | private: 59 | // Guards the |server_| member. 60 | absl::Mutex server_mutex_; 61 | 62 | // A gRPC server hosting |service_|. 63 | std::unique_ptr<::grpc::Server> server_ ABSL_GUARDED_BY(server_mutex_); 64 | 65 | // The translation service. 66 | std::unique_ptr service_; 67 | 68 | // The server's selected port. 69 | int selected_port_; 70 | }; 71 | 72 | asylo::Status GrpcServerEnclave::Initialize( 73 | const asylo::EnclaveConfig &enclave_config) 74 | ABSL_LOCKS_EXCLUDED(server_mutex_) { 75 | // Fail if there is no server_address available. 76 | if (!enclave_config.HasExtension(server_address)) { 77 | return absl::InvalidArgumentError( 78 | "Expected a server_address extension on config."); 79 | } 80 | 81 | if (!enclave_config.HasExtension(port)) { 82 | return absl::InvalidArgumentError("Expected a port extension on config."); 83 | } 84 | 85 | // Lock |server_mutex_| so that we can start setting up the server. 86 | absl::MutexLock lock(&server_mutex_); 87 | 88 | // Check that the server is not already running. 89 | if (server_) { 90 | return absl::AlreadyExistsError("Server is already started"); 91 | } 92 | 93 | // Create a ServerBuilder object to set up the server. 94 | ::grpc::ServerBuilder builder; 95 | 96 | std::shared_ptr<::grpc::ServerCredentials> server_credentials = 97 | ::grpc::InsecureServerCredentials(); 98 | 99 | // Add a listening port to the server. 100 | builder.AddListeningPort( 101 | absl::StrCat(enclave_config.GetExtension(server_address), ":", 102 | enclave_config.GetExtension(port)), 103 | server_credentials, &selected_port_); 104 | 105 | // Instantiate the translator service. 106 | service_ = absl::make_unique(); 107 | 108 | // Add the translator service to the server. 109 | builder.RegisterService(service_.get()); 110 | 111 | // Start the server. 112 | server_ = builder.BuildAndStart(); 113 | if (!server_) { 114 | return absl::InternalError("Failed to start server"); 115 | } 116 | 117 | return absl::OkStatus(); 118 | } 119 | 120 | asylo::Status GrpcServerEnclave::Run(const asylo::EnclaveInput &enclave_input, 121 | asylo::EnclaveOutput *enclave_output) { 122 | enclave_output->SetExtension(actual_server_port, selected_port_); 123 | return absl::OkStatus(); 124 | } 125 | 126 | asylo::Status GrpcServerEnclave::Finalize( 127 | const asylo::EnclaveFinal &enclave_final) 128 | ABSL_LOCKS_EXCLUDED(server_mutex_) { 129 | // Lock |server_mutex_| so that we can start shutting down the server. 130 | absl::MutexLock lock(&server_mutex_); 131 | 132 | // If the server exists, then shut it down. Also delete the Server object to 133 | // indicate that it is no longer valid. 134 | if (server_) { 135 | LOG(INFO) << "Server shutting down"; 136 | 137 | // Give all outstanding RPC calls 500 milliseconds to complete. 138 | server_->Shutdown(std::chrono::system_clock::now() + 139 | std::chrono::milliseconds(500)); 140 | server_.reset(nullptr); 141 | } 142 | 143 | return absl::OkStatus(); 144 | } 145 | 146 | } // namespace grpc_server 147 | } // namespace examples 148 | 149 | namespace asylo { 150 | 151 | // Registers an instance of GrpcServerEnclave as the TrustedApplication. See 152 | // trusted_application.h for more information. 153 | TrustedApplication *BuildTrustedApplication() { 154 | return new examples::grpc_server::GrpcServerEnclave; 155 | } 156 | 157 | } // namespace asylo 158 | -------------------------------------------------------------------------------- /grpc_server/grpc_server_test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include "absl/flags/flag.h" 25 | #include "absl/memory/memory.h" 26 | #include "absl/strings/str_cat.h" 27 | #include "absl/strings/string_view.h" 28 | #include "asylo/enclave_manager.h" 29 | #include "asylo/test/util/status_matchers.h" 30 | #include "asylo/util/path.h" 31 | #include "asylo/util/status.h" 32 | #include "asylo/util/status_macros.h" 33 | #include "grpc_server/grpc_server_util.h" 34 | #include "grpc_server/translator_client.h" 35 | 36 | ABSL_FLAG(std::string, server_enclave_path, "", 37 | "The path to the server enclave to pass to the enclave loader"); 38 | 39 | ABSL_FLAG(bool, debug_enclave, true, 40 | "Whether to load the server as a debug enclave"); 41 | 42 | namespace examples { 43 | namespace grpc_server { 44 | namespace { 45 | 46 | using asylo::IsOkAndHolds; 47 | using asylo::StatusIs; 48 | 49 | class GrpcServerTest : public ::testing::Test { 50 | public: 51 | static void SetUpTestSuite() { 52 | ASYLO_ASSERT_OK( 53 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions())); 54 | } 55 | 56 | void SetUp() override { 57 | ASSERT_NE(absl::GetFlag(FLAGS_server_enclave_path), ""); 58 | server_port_ = 0; 59 | } 60 | 61 | void StartServer() { 62 | ASYLO_ASSERT_OK(LoadGrpcServerEnclave( 63 | absl::GetFlag(FLAGS_server_enclave_path), server_port_, 64 | absl::GetFlag(FLAGS_debug_enclave))); 65 | 66 | // Retrieve the server's port. 67 | ASYLO_ASSERT_OK_AND_ASSIGN(server_port_, GrpcServerEnclaveGetPort()); 68 | ASSERT_NE(server_port_, 0); 69 | } 70 | 71 | void TearDown() override { ASYLO_ASSERT_OK(DestroyGrpcServerEnclave()); } 72 | 73 | // Sends a GetTranslation RPC to the server via the client. Returns 74 | // the same grpc::Status as the stub function call. If the RPC is successful, 75 | // returns the translated word, else returns a non-OK status. 76 | asylo::StatusOr MakeRpc(const std::string &input_word) { 77 | std::unique_ptr client; 78 | ASYLO_ASSIGN_OR_RETURN(client, TranslatorClient::Create(absl::StrCat( 79 | "localhost:", server_port_))); 80 | return client->GrpcGetTranslation(input_word); 81 | } 82 | 83 | private: 84 | int server_port_; 85 | }; 86 | 87 | TEST_F(GrpcServerTest, KnownTranslations) { 88 | ASSERT_NO_FATAL_FAILURE(StartServer()); 89 | 90 | EXPECT_THAT(MakeRpc("asylo"), IsOkAndHolds("sanctuary")); 91 | EXPECT_THAT(MakeRpc("istio"), IsOkAndHolds("sail")); 92 | EXPECT_THAT(MakeRpc("kubernetes"), IsOkAndHolds("helmsman")); 93 | } 94 | 95 | TEST_F(GrpcServerTest, UnknownTranslation) { 96 | ASSERT_NO_FATAL_FAILURE(StartServer()); 97 | 98 | EXPECT_THAT(MakeRpc("orkut"), StatusIs(asylo::error::INVALID_ARGUMENT, 99 | "No known translation for \"orkut\"")); 100 | } 101 | 102 | } // namespace 103 | } // namespace grpc_server 104 | } // namespace examples 105 | -------------------------------------------------------------------------------- /grpc_server/grpc_server_util.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/strings/str_cat.h" 23 | #include "asylo/client.h" 24 | #include "asylo/enclave.pb.h" 25 | #include "asylo/platform/primitives/sgx/loader.pb.h" 26 | #include "asylo/util/status.h" 27 | #include "asylo/util/status_macros.h" 28 | #include "grpc_server/grpc_server_config.pb.h" 29 | 30 | namespace examples { 31 | namespace grpc_server { 32 | namespace { 33 | 34 | constexpr char kServerAddress[] = "localhost"; 35 | constexpr char kEnclaveName[] = "grpc_server"; 36 | 37 | } // namespace 38 | 39 | asylo::Status LoadGrpcServerEnclave(const std::string &enclave_path, 40 | int server_port, bool debug_enclave) { 41 | // The EnclaveLoadConfig contains all configurations passed to the enclave for 42 | // initialization. 43 | asylo::EnclaveLoadConfig load_config; 44 | load_config.set_name(kEnclaveName); 45 | 46 | // The EnclaveConfig contains the address that the gRPC server will run on. 47 | asylo::EnclaveConfig *config = load_config.mutable_config(); 48 | config->SetExtension(server_address, kServerAddress); 49 | config->SetExtension(port, server_port); 50 | 51 | // The SgxLoadConfig sets up configuration specific to an SGX enclave, 52 | // including the location of the enclave binary and whether to run in debug 53 | // mode. 54 | asylo::SgxLoadConfig *sgx_config = 55 | load_config.MutableExtension(asylo::sgx_load_config); 56 | sgx_config->mutable_file_enclave_config()->set_enclave_path(enclave_path); 57 | sgx_config->set_debug(debug_enclave); 58 | 59 | asylo::EnclaveManager *manager = nullptr; 60 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 61 | 62 | // Load the enclave. Calling LoadEnclave() triggers a call to the Initialize() 63 | // method of the TrustedApplication. 64 | return manager->LoadEnclave(load_config); 65 | } 66 | 67 | asylo::StatusOr GrpcServerEnclaveGetPort() { 68 | asylo::EnclaveManager *manager = nullptr; 69 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 70 | 71 | asylo::EnclaveClient *client = manager->GetClient(kEnclaveName); 72 | if (!client) { 73 | return asylo::Status(asylo::error::FAILED_PRECONDITION, 74 | absl::StrCat(kEnclaveName, " not running")); 75 | } 76 | 77 | asylo::EnclaveInput enclave_input; 78 | asylo::EnclaveOutput enclave_output; 79 | ASYLO_RETURN_IF_ERROR(client->EnterAndRun(enclave_input, &enclave_output)); 80 | if (!enclave_output.HasExtension(actual_server_port)) { 81 | return asylo::Status(asylo::error::INTERNAL, 82 | "Server output missing server_port extension"); 83 | } 84 | return enclave_output.GetExtension(actual_server_port); 85 | } 86 | 87 | asylo::Status DestroyGrpcServerEnclave() { 88 | asylo::EnclaveManager *manager = nullptr; 89 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 90 | 91 | asylo::EnclaveClient *client = manager->GetClient(kEnclaveName); 92 | if (!client) { 93 | return asylo::Status(asylo::error::FAILED_PRECONDITION, 94 | absl::StrCat(kEnclaveName, " not running")); 95 | } 96 | 97 | asylo::EnclaveFinal final_input; 98 | return manager->DestroyEnclave(client, final_input); 99 | } 100 | 101 | } // namespace grpc_server 102 | } // namespace examples 103 | -------------------------------------------------------------------------------- /grpc_server/grpc_server_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_GRPC_SERVER_GRPC_SERVER_UTIL_H_ 20 | #define ASYLO_EXAMPLES_GRPC_SERVER_GRPC_SERVER_UTIL_H_ 21 | 22 | #include 23 | 24 | #include "asylo/util/status.h" 25 | #include "asylo/util/statusor.h" 26 | 27 | namespace examples { 28 | namespace grpc_server { 29 | 30 | // Each of the following functions assume that the asylo::EnclaveManager 31 | // instance has been configured using asylo::EnclaveManager::Configure(). 32 | 33 | // Loads the GrpcServerEnclave from |enclave_path|. If |debug_enclave| is true, 34 | // then the enclave is started in debug mode. Starts the enclave's server on 35 | // |server_port| and configures the server to refer requests to the 36 | // GetTranslation RPC. 37 | asylo::Status LoadGrpcServerEnclave(const std::string &enclave_path, 38 | int server_port, bool debug_enclave); 39 | 40 | // Retrieves the port of the server inside the GrpcServerEnclave. Returns a 41 | // non-OK Status if the GrpcServerEnclave is not running. 42 | asylo::StatusOr GrpcServerEnclaveGetPort(); 43 | 44 | // Destroys the GrpcServerEnclave and returns its finalization Status. Returns a 45 | // non-OK Status if the GrpcServerEnclave is not running. 46 | asylo::Status DestroyGrpcServerEnclave(); 47 | 48 | } // namespace grpc_server 49 | } // namespace examples 50 | 51 | #endif // ASYLO_EXAMPLES_GRPC_SERVER_GRPC_SERVER_UTIL_H_ 52 | -------------------------------------------------------------------------------- /grpc_server/translator_client.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include "grpc_server/translator_client.h" 20 | 21 | #include 22 | #include 23 | 24 | #include "absl/memory/memory.h" 25 | #include "absl/status/status.h" 26 | #include "absl/strings/string_view.h" 27 | #include "absl/time/time.h" 28 | #include "asylo/util/status.h" 29 | #include "asylo/util/status_helpers.h" 30 | #include "asylo/util/status_macros.h" 31 | #include "asylo/util/statusor.h" 32 | #include "grpc_server/translator_server.grpc.pb.h" 33 | #include "grpc_server/translator_server.pb.h" 34 | #include "include/grpc/impl/codegen/gpr_types.h" 35 | #include "include/grpc/support/time.h" 36 | #include "include/grpcpp/create_channel.h" 37 | #include "include/grpcpp/grpcpp.h" 38 | #include "include/grpcpp/security/credentials.h" 39 | 40 | namespace examples { 41 | namespace grpc_server { 42 | namespace { 43 | 44 | const absl::Duration kChannelDeadline = absl::Seconds(5); 45 | 46 | // Makes a GetTranslation RPC with |request| to the server backed by *|stub|. 47 | asylo::StatusOr GetTranslation( 48 | const GetTranslationRequest &request, Translator::Stub *stub) { 49 | GetTranslationResponse response; 50 | 51 | ::grpc::ClientContext context; 52 | ASYLO_RETURN_IF_ERROR(asylo::ConvertStatus( 53 | stub->GetTranslation(&context, request, &response))); 54 | return response; 55 | } 56 | 57 | } // namespace 58 | 59 | asylo::StatusOr> TranslatorClient::Create( 60 | absl::string_view address) { 61 | if (address.empty()) { 62 | return asylo::Status(absl::StatusCode::kInvalidArgument, 63 | "Must provide a non-empty server address"); 64 | } 65 | std::shared_ptr<::grpc::ChannelCredentials> channel_credentials = 66 | ::grpc::InsecureChannelCredentials(); 67 | 68 | // Connect a gRPC channel to the server. 69 | std::shared_ptr<::grpc::Channel> channel = 70 | ::grpc::CreateChannel(std::string(address), channel_credentials); 71 | 72 | gpr_timespec absolute_deadline = gpr_time_add( 73 | gpr_now(GPR_CLOCK_REALTIME), 74 | gpr_time_from_micros(absl::ToInt64Microseconds(kChannelDeadline), 75 | GPR_TIMESPAN)); 76 | if (!channel->WaitForConnected(absolute_deadline)) { 77 | return asylo::Status(absl::StatusCode::kInternal, 78 | "Failed to connect to server"); 79 | } 80 | 81 | return absl::WrapUnique(new TranslatorClient(Translator::NewStub(channel))); 82 | } 83 | 84 | asylo::StatusOr TranslatorClient::GrpcGetTranslation( 85 | absl::string_view word_to_translate) { 86 | if (word_to_translate.empty()) { 87 | return asylo::Status(absl::StatusCode::kInvalidArgument, 88 | "Must provide a non-empty RPC input"); 89 | } 90 | 91 | GetTranslationRequest request; 92 | request.set_input_word(std::string(word_to_translate)); 93 | GetTranslationResponse response; 94 | ASYLO_ASSIGN_OR_RETURN(response, GetTranslation(request, stub_.get())); 95 | 96 | return response.translated_word(); 97 | } 98 | 99 | } // namespace grpc_server 100 | } // namespace examples 101 | -------------------------------------------------------------------------------- /grpc_server/translator_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_GRPC_SERVER_TRANSLATOR_CLIENT_H_ 20 | #define ASYLO_EXAMPLES_GRPC_SERVER_TRANSLATOR_CLIENT_H_ 21 | 22 | #include 23 | #include 24 | 25 | #include "absl/strings/string_view.h" 26 | #include "asylo/util/status.h" 27 | #include "asylo/util/statusor.h" 28 | #include "grpc_server/translator_server.grpc.pb.h" 29 | #include "grpc_server/translator_server.pb.h" 30 | #include "include/grpcpp/grpcpp.h" 31 | 32 | namespace examples { 33 | namespace grpc_server { 34 | 35 | // A gRPC client connected to a TranslationServer. Can only be instantiated 36 | // by the factory method TranslatorClient::Create. 37 | class TranslatorClient { 38 | public: 39 | // Factory method that returns a client connected to a TranslatorServer 40 | // at |address|. In case of error, returns a non-OK status. 41 | static asylo::StatusOr> Create( 42 | absl::string_view address); 43 | 44 | // Non-copyable, non-movable. 45 | TranslatorClient(const TranslatorClient &other) = delete; 46 | TranslatorClient &operator=(const TranslatorClient &other) = delete; 47 | TranslatorClient(TranslatorClient &&other) = delete; 48 | TranslatorClient &operator=(TranslatorClient &&other) = delete; 49 | 50 | // Makes a GetTranslation RPC for |word_to_translate| to the server and 51 | // returns the translated word on success, or a non-OK Status if the RPC 52 | // fails. 53 | asylo::StatusOr GrpcGetTranslation( 54 | absl::string_view word_to_translate); 55 | 56 | private: 57 | explicit TranslatorClient(std::unique_ptr stub) 58 | : stub_(std::move(stub)) {} 59 | 60 | std::unique_ptr stub_; 61 | }; 62 | 63 | } // namespace grpc_server 64 | } // namespace examples 65 | 66 | #endif // ASYLO_EXAMPLES_GRPC_SERVER_TRANSLATOR_CLIENT_H_ 67 | -------------------------------------------------------------------------------- /grpc_server/translator_server.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2018 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package examples.grpc_server; 20 | 21 | // A request message containing a word to be translated. 22 | message GetTranslationRequest { 23 | optional string input_word = 1; 24 | } 25 | 26 | // A response message containing the translation of a GetTranslationRequest's 27 | // input_word. 28 | message GetTranslationResponse { 29 | optional string translated_word = 1; 30 | } 31 | 32 | service Translator { 33 | // Translates the given word. 34 | rpc GetTranslation(GetTranslationRequest) returns (GetTranslationResponse) { 35 | // errors: no input word, no translation available 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /grpc_server/translator_server_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2018 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include "grpc_server/translator_server_impl.h" 20 | 21 | #include "absl/strings/ascii.h" 22 | #include "absl/strings/str_cat.h" 23 | #include "include/grpcpp/grpcpp.h" 24 | 25 | namespace examples { 26 | namespace grpc_server { 27 | 28 | TranslatorServerImpl::TranslatorServerImpl() 29 | : Service(), 30 | // Initialize the translation map with a few known translations. 31 | translation_map_({{"asylo", "sanctuary"}, 32 | {"istio", "sail"}, 33 | {"kubernetes", "helmsman"}}) {} 34 | 35 | ::grpc::Status TranslatorServerImpl::GetTranslation( 36 | ::grpc::ServerContext *context, const GetTranslationRequest *request, 37 | GetTranslationResponse *response) { 38 | // Confirm that |*request| has an |input_word| field. 39 | if (!request->has_input_word()) { 40 | return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, 41 | "No input word given"); 42 | } 43 | 44 | // Confirm that the translation map has a translation for the input word. 45 | auto response_iterator = 46 | translation_map_.find(absl::AsciiStrToLower(request->input_word())); 47 | if (response_iterator == translation_map_.end()) { 48 | return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, 49 | absl::StrCat("No known translation for \"", 50 | request->input_word(), "\"")); 51 | } 52 | 53 | // Return the translation. 54 | response->set_translated_word(response_iterator->second); 55 | return ::grpc::Status::OK; 56 | } 57 | 58 | } // namespace grpc_server 59 | } // namespace examples 60 | -------------------------------------------------------------------------------- /grpc_server/translator_server_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2018 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_GRPC_SERVER_TRANSLATOR_SERVER_IMPL_H_ 20 | #define ASYLO_EXAMPLES_GRPC_SERVER_TRANSLATOR_SERVER_IMPL_H_ 21 | 22 | #include 23 | 24 | #include "absl/base/thread_annotations.h" 25 | #include "absl/container/flat_hash_map.h" 26 | #include "absl/synchronization/mutex.h" 27 | #include "absl/synchronization/notification.h" 28 | #include "grpc_server/translator_server.grpc.pb.h" 29 | #include "include/grpcpp/grpcpp.h" 30 | #include "include/grpcpp/server.h" 31 | 32 | namespace examples { 33 | namespace grpc_server { 34 | 35 | class TranslatorServerImpl final : public Translator::Service { 36 | public: 37 | // Configure the server. 38 | explicit TranslatorServerImpl(); 39 | 40 | private: 41 | ::grpc::Status GetTranslation(::grpc::ServerContext *context, 42 | const GetTranslationRequest *request, 43 | GetTranslationResponse *response) override; 44 | 45 | // A map from words to their translations. 46 | absl::flat_hash_map translation_map_; 47 | }; 48 | 49 | } // namespace grpc_server 50 | } // namespace examples 51 | 52 | #endif // ASYLO_EXAMPLES_GRPC_SERVER_TRANSLATOR_SERVER_IMPL_H_ 53 | -------------------------------------------------------------------------------- /hello_world/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # Hello World project for Asylo. 18 | 19 | load("@linux_sgx//:sgx_sdk.bzl", "sgx") 20 | load("@rules_cc//cc:defs.bzl", "cc_proto_library") 21 | load("@rules_proto//proto:defs.bzl", "proto_library") 22 | load("@com_google_asylo//asylo/bazel:asylo.bzl", "cc_unsigned_enclave", "debug_sign_enclave", "enclave_loader") 23 | 24 | licenses(["notice"]) 25 | 26 | package( 27 | default_visibility = ["//visibility:public"], 28 | ) 29 | 30 | # Example for using the Asylo framework. 31 | 32 | proto_library( 33 | name = "hello_proto", 34 | srcs = ["hello.proto"], 35 | deps = ["@com_google_asylo//asylo:enclave_proto"], 36 | ) 37 | 38 | cc_proto_library( 39 | name = "hello_cc_proto", 40 | deps = [":hello_proto"], 41 | ) 42 | 43 | cc_unsigned_enclave( 44 | name = "hello_enclave_unsigned.so", 45 | srcs = ["hello_enclave.cc"], 46 | deps = [ 47 | ":hello_cc_proto", 48 | "@com_google_absl//absl/strings", 49 | "@com_google_asylo//asylo:enclave_runtime", 50 | "@com_google_asylo//asylo/util:logging", 51 | "@com_google_asylo//asylo/util:status", 52 | ], 53 | ) 54 | 55 | debug_sign_enclave( 56 | name = "hello_enclave.so", 57 | unsigned = "hello_enclave_unsigned.so", 58 | ) 59 | 60 | enclave_loader( 61 | name = "hello_world", 62 | srcs = ["hello_driver.cc"], 63 | backends = sgx.backend_labels, # Has SGX loader dependencies 64 | enclaves = {"enclave": ":hello_enclave.so"}, 65 | loader_args = ["--enclave_path='{enclave}'"], 66 | deps = [ 67 | ":hello_cc_proto", 68 | "@com_google_absl//absl/flags:flag", 69 | "@com_google_absl//absl/flags:parse", 70 | "@com_google_absl//absl/strings", 71 | "@com_google_asylo//asylo:enclave_cc_proto", 72 | "@com_google_asylo//asylo:enclave_client", 73 | "@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto", 74 | "@com_google_asylo//asylo/util:logging", 75 | ], 76 | ) 77 | -------------------------------------------------------------------------------- /hello_world/hello.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2018 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package hello_world; 20 | 21 | import "asylo/enclave.proto"; 22 | 23 | // Extension to EnclaveInput for use with HelloWorld enclave. 24 | message HelloInput { 25 | optional string to_greet = 1; 26 | } 27 | 28 | message HelloOutput { 29 | optional string greeting_message = 1; 30 | } 31 | 32 | extend asylo.EnclaveInput { 33 | optional HelloInput enclave_input_hello = 8086; 34 | } 35 | 36 | extend asylo.EnclaveOutput { 37 | optional HelloOutput enclave_output_hello = 8087; 38 | } 39 | -------------------------------------------------------------------------------- /hello_world/hello_driver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2018 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "absl/flags/flag.h" 24 | #include "absl/flags/parse.h" 25 | #include "absl/strings/str_split.h" 26 | #include "asylo/client.h" 27 | #include "asylo/enclave.pb.h" 28 | #include "asylo/platform/primitives/sgx/loader.pb.h" 29 | #include "asylo/util/logging.h" 30 | #include "hello_world/hello.pb.h" 31 | 32 | ABSL_FLAG(std::string, enclave_path, "", "Path to enclave to load"); 33 | ABSL_FLAG(std::string, names, "", 34 | "A comma-separated list of names to pass to the enclave"); 35 | 36 | int main(int argc, char *argv[]) { 37 | // Part 0: Setup 38 | absl::ParseCommandLine(argc, argv); 39 | 40 | if (absl::GetFlag(FLAGS_names).empty()) { 41 | LOG(QFATAL) << "Must supply a non-empty list of names with --names"; 42 | } 43 | 44 | std::vector names = 45 | absl::StrSplit(absl::GetFlag(FLAGS_names), ','); 46 | 47 | // Part 1: Initialization 48 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions()); 49 | auto manager_result = asylo::EnclaveManager::Instance(); 50 | if (!manager_result.ok()) { 51 | LOG(QFATAL) << "EnclaveManager unavailable: " << manager_result.status(); 52 | } 53 | asylo::EnclaveManager *manager = manager_result.value(); 54 | std::cout << "Loading " << absl::GetFlag(FLAGS_enclave_path) << std::endl; 55 | 56 | // Create an EnclaveLoadConfig object. 57 | asylo::EnclaveLoadConfig load_config; 58 | load_config.set_name("hello_enclave"); 59 | 60 | // Create an SgxLoadConfig object. 61 | asylo::SgxLoadConfig sgx_config; 62 | asylo::SgxLoadConfig::FileEnclaveConfig file_enclave_config; 63 | file_enclave_config.set_enclave_path(absl::GetFlag(FLAGS_enclave_path)); 64 | *sgx_config.mutable_file_enclave_config() = file_enclave_config; 65 | sgx_config.set_debug(true); 66 | 67 | // Set an SGX message extension to load_config. 68 | *load_config.MutableExtension(asylo::sgx_load_config) = sgx_config; 69 | asylo::Status status = manager->LoadEnclave(load_config); 70 | if (!status.ok()) { 71 | LOG(QFATAL) << "Load " << absl::GetFlag(FLAGS_enclave_path) 72 | << " failed: " << status; 73 | } 74 | 75 | // Part 2: Secure execution 76 | 77 | asylo::EnclaveClient *client = manager->GetClient("hello_enclave"); 78 | 79 | for (const auto &name : names) { 80 | asylo::EnclaveInput input; 81 | input.MutableExtension(hello_world::enclave_input_hello) 82 | ->set_to_greet(name); 83 | 84 | asylo::EnclaveOutput output; 85 | status = client->EnterAndRun(input, &output); 86 | if (!status.ok()) { 87 | LOG(QFATAL) << "EnterAndRun failed: " << status; 88 | } 89 | 90 | if (!output.HasExtension(hello_world::enclave_output_hello)) { 91 | LOG(QFATAL) << "Enclave did not assign an ID for " << name; 92 | } 93 | 94 | std::cout << "Message from enclave: " 95 | << output.GetExtension(hello_world::enclave_output_hello) 96 | .greeting_message() 97 | << std::endl; 98 | } 99 | 100 | // Part 3: Finalization 101 | 102 | asylo::EnclaveFinal final_input; 103 | status = manager->DestroyEnclave(client, final_input); 104 | if (!status.ok()) { 105 | LOG(QFATAL) << "Destroy " << absl::GetFlag(FLAGS_enclave_path) 106 | << " failed: " << status; 107 | } 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /hello_world/hello_enclave.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2018 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | 21 | #include "absl/status/status.h" 22 | #include "absl/strings/str_cat.h" 23 | #include "asylo/trusted_application.h" 24 | #include "asylo/util/logging.h" 25 | #include "asylo/util/status.h" 26 | #include "hello_world/hello.pb.h" 27 | 28 | class HelloApplication : public asylo::TrustedApplication { 29 | public: 30 | HelloApplication() : visitor_count_(0) {} 31 | 32 | asylo::Status Run(const asylo::EnclaveInput &input, 33 | asylo::EnclaveOutput *output) override { 34 | if (!input.HasExtension(hello_world::enclave_input_hello)) { 35 | return absl::InvalidArgumentError( 36 | "Expected a HelloInput extension on input."); 37 | } 38 | std::string visitor = 39 | input.GetExtension(hello_world::enclave_input_hello).to_greet(); 40 | 41 | LOG(INFO) << "Hello " << visitor; 42 | if (output) { 43 | LOG(INFO) << "Incrementing visitor count..."; 44 | output->MutableExtension(hello_world::enclave_output_hello) 45 | ->set_greeting_message( 46 | absl::StrCat("Hello ", visitor, "! You are visitor #", 47 | ++visitor_count_, " to this enclave.")); 48 | } 49 | return absl::OkStatus(); 50 | } 51 | 52 | private: 53 | uint64_t visitor_count_; 54 | }; 55 | 56 | namespace asylo { 57 | 58 | TrustedApplication *BuildTrustedApplication() { return new HelloApplication; } 59 | 60 | } // namespace asylo 61 | -------------------------------------------------------------------------------- /java/quickstart_client/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | load("@rules_java//java:defs.bzl", "java_binary", "java_proto_library") 18 | 19 | licenses(["notice"]) 20 | 21 | java_binary( 22 | name = "quickstart", 23 | srcs = [ 24 | "src/main/java/com/example/DemoDriver.java", 25 | ], 26 | main_class = "com.example.DemoDriver", 27 | deps = [ 28 | ":demo_java_proto", 29 | "@com_google_asylo//asylo:enclave_client_java", 30 | "@com_google_protobuf//:protobuf_java", 31 | ], 32 | ) 33 | 34 | java_proto_library( 35 | name = "demo_java_proto", 36 | deps = [ 37 | "//quickstart/solution:demo_proto", 38 | ], 39 | ) 40 | -------------------------------------------------------------------------------- /java/quickstart_client/README.md: -------------------------------------------------------------------------------- 1 | 21 | 22 | This guide describes how to use Java to run an Asylo enclave that was written in 23 | C++. This guide assumes that the reader is familiar with 24 | [Asylo quickstart guide](https://asylo.dev/docs/guides/quickstart.html). 25 | 26 | ## Introduction 27 | 28 | There are two parts in an enclave application written using Asylo framework, 29 | _untrusted application_ and _trusted application (enclave)_. Asylo release 0.5.2 30 | and older required both trusted and untrusted components to be written in C++. 31 | 32 | With the introduction of Asylo Java client, untrusted application can now be 33 | written in Java as well. An Asylo Java client can load and run an enclave 34 | written in C++. This model enables users to write their enclave once and then 35 | reuse it in an untrusted application written in C++ or Java. 36 | 37 | ## Using a Java client 38 | 39 | An enclave can be loaded using an 40 | [`EnclaveManager`](https://github.com/google/asylo/blob/master/asylo/binding/java/src/main/java/com/asylo/client/EnclaveManager.java). 41 | It is a singleton class which can load an enclave from the file system by 42 | providing the path to the enclave binary using the 43 | [`EnclaveLoadConfig`](https://github.com/google/asylo/blob/master/asylo/enclave.proto) proto. 44 | 45 | Users may interact with a loaded enclave through an 46 | [`EnclaveClient`](https://github.com/google/asylo/blob/master/asylo/binding/java/src/main/java/com/asylo/client/EnclaveClient.java). 47 | The `EnclaveManager` returns a loaded and named `EnclaveClient` with the method 48 | `getEnclaveClient`. 49 | 50 | Most of the configurations, inputs, and outputs in a Java client are passed 51 | using 52 | [protocol-buffer messages](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message#Message). 53 | 54 | One major difference between the Java and C++ APIs is that in Java, errors are 55 | thrown as exceptions derived from 56 | [`EnclaveException`](https://github.com/google/asylo/blob/master/asylo/binding/java/src/main/java/com/asylo/client/EnclaveException.java), 57 | rather returned through a `StatusOr` type. 58 | 59 | The following snippet is a small example of a Java client that interacts with an 60 | enclave written in C++. 61 | 62 | ```java 63 | public static void main(String[] args) { 64 | 65 | if (args.length != 1) { 66 | System.err.println("Expecting a single argument which is the filepath of an enclave."); 67 | System.exit(1); 68 | } 69 | 70 | String enclavePath = args[0]; 71 | String enclaveName = "demo_enclave"; 72 | 73 | // Part 1: Initialization 74 | // Specify the enclave file. 75 | FileEnclaveConfig fileEnclaveConfig = 76 | FileEnclaveConfig.newBuilder().setEnclavePath(enclavePath).build(); 77 | 78 | // Specify that the enclave uses SGX, and configure the SGX loader with the 79 | // path to the enclave binary. 80 | SgxLoadConfig sgxLoadConfig = 81 | SgxLoadConfig.newBuilder().setDebug(true).setFileEnclaveConfig(fileEnclaveConfig).build(); 82 | 83 | // Specify the enclave name and inject the SGX configuration. 84 | EnclaveLoadConfig enclaveLoadConfig = 85 | EnclaveLoadConfig.newBuilder() 86 | .setName(enclaveName) 87 | .setExtension(EnclaveLoadConfigSgxExtension.sgxLoadConfig, sgxLoadConfig) 88 | .build(); 89 | 90 | EnclaveManager.getInstance().loadEnclave(enclaveLoadConfig); 91 | 92 | // Part 2: Secure execution 93 | // Get user input. 94 | String plainText = getMessage(); 95 | 96 | // Prepare input for enclave. 97 | Demo demoInput = Demo.newBuilder().setValue(plainText).setAction(Demo.Action.ENCRYPT).build(); 98 | EnclaveInput enclaveInput = 99 | EnclaveInput.newBuilder() 100 | .setExtension(EnclaveDemoExtension.quickstartInput, demoInput) 101 | .build(); 102 | 103 | // Register protobuf extension for output. 104 | ExtensionRegistry registry = ExtensionRegistry.newInstance(); 105 | registry.add(EnclaveDemoExtension.quickstartOutput); 106 | 107 | EnclaveClient client = EnclaveManager.getInstance().getEnclaveClient(enclaveName); 108 | EnclaveOutput output = client.enterAndRun(enclaveInput, registry); 109 | Demo encryptedText = output.getExtension(EnclaveDemoExtension.quickstartOutput); 110 | 111 | System.out.println("Encrypted message:" + encryptedText.getValue()); 112 | 113 | // Part 3: Finalization 114 | EnclaveFinal finalInput = EnclaveFinal.getDefaultInstance(); 115 | EnclaveManager.getInstance().destroyEnclaveClient(client, finalInput); 116 | } 117 | ``` 118 | 119 | The above snippet is conceptually the same as the one mentioned in 120 | [enclave lifecycle](https://asylo.dev/docs/guides/quickstart.html#enclave-lifecycle) 121 | 122 | ## Building and running an enclave Java application 123 | 124 | The Java library `//asylo:enclave_client_java` provides the API to load C++ 125 | enclaves in Java. 126 | 127 | ```python 128 | java_binary( 129 | name = "quickstart", 130 | srcs = [ 131 | "src/main/java/com/example/DemoDriver.java", 132 | ], 133 | main_class = "com.example.DemoDriver", 134 | deps = [ 135 | ":demo_java_proto", 136 | "//java/com/google/protobuf", 137 | "@com_google_asylo//asylo:enclave_client_java", 138 | ], 139 | ) 140 | 141 | java_proto_library( 142 | name = "demo_java_proto", 143 | deps = [ 144 | "//quickstart:demo_proto", 145 | ], 146 | ) 147 | ``` 148 | 149 | The [Bazel](https://bazel.build) BUILD file shown above has untrusted java code 150 | in the target `:quickstart`, which contains the code to handle logic of 151 | initializing, running, and finalizing the enclave. 152 | 153 | To run this example first we need an enclave. The following workflow uses the 154 | enclave from 155 | [Asylo quickstart guide](https://asylo.dev/docs/guides/quickstart.html#building-and-running-an-enclave-application) 156 | by running: 157 | 158 | ```bash 159 | bazel build //quickstart:demo_enclave_sgx_sim.so 160 | ``` 161 | 162 | Copy the generated file to some location: 163 | 164 | ```bash 165 | cp $(bazel info bazel-bin)/quickstart/demo_enclave_sgx_sim.so /tmp/demo_enclave_sgx_sim.so 166 | ``` 167 | 168 | Now, untrusted Java client can be run as: 169 | 170 | ```bash 171 | bazel run //java/quickstart_client:quickstart /tmp/demo_enclave_sgx_sim.so 172 | ``` 173 | 174 | You should then see a prompt for a message to encrypt, similar to the quickstart 175 | guide. 176 | -------------------------------------------------------------------------------- /java/quickstart_client/src/main/java/com/example/DemoDriver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | package com.example; 20 | 21 | import static java.nio.charset.StandardCharsets.UTF_8; 22 | 23 | import com.asylo.EnclaveFinal; 24 | import com.asylo.EnclaveInput; 25 | import com.asylo.EnclaveLoadConfig; 26 | import com.asylo.EnclaveLoadConfigSgxExtension; 27 | import com.asylo.EnclaveOutput; 28 | import com.asylo.SgxLoadConfig; 29 | import com.asylo.SgxLoadConfig.FileEnclaveConfig; 30 | import com.asylo.client.EnclaveClient; 31 | import com.asylo.client.EnclaveManager; 32 | import com.google.protobuf.ExtensionRegistry; 33 | import java.util.Scanner; 34 | 35 | /** 36 | * Class to demonstrate usage of Asylo Java client. This class uses the enclave created by the C++ 37 | * quickstart example, which can be found in asylo/examples/quickstart. 38 | */ 39 | public class DemoDriver { 40 | public static void main(String[] args) { 41 | 42 | if (args.length != 1) { 43 | System.err.println("Expecting a single argument which is the filepath of an enclave."); 44 | System.exit(1); 45 | } 46 | 47 | String enclavePath = args[0]; 48 | String enclaveName = "demo_enclave"; 49 | 50 | // Part 1: Initialization 51 | // Specify enclave file. 52 | FileEnclaveConfig fileEnclaveConfig = 53 | FileEnclaveConfig.newBuilder().setEnclavePath(enclavePath).build(); 54 | 55 | // Specify that the enclave uses SGX, and configure the SGX loader with the 56 | // path to the enclave binary. 57 | SgxLoadConfig sgxLoadConfig = 58 | SgxLoadConfig.newBuilder().setDebug(true).setFileEnclaveConfig(fileEnclaveConfig).build(); 59 | 60 | // Specify enclave load config. 61 | EnclaveLoadConfig enclaveLoadConfig = 62 | EnclaveLoadConfig.newBuilder() 63 | .setName(enclaveName) 64 | .setExtension(EnclaveLoadConfigSgxExtension.sgxLoadConfig, sgxLoadConfig) 65 | .build(); 66 | 67 | EnclaveManager.getInstance().loadEnclave(enclaveLoadConfig); 68 | 69 | // Part 2: Secure execution 70 | // Get user input. 71 | String plainText = getMessage(); 72 | 73 | // Prepare input for enclave. 74 | Demo demoInput = Demo.newBuilder().setValue(plainText).setAction(Demo.Action.ENCRYPT).build(); 75 | EnclaveInput enclaveInput = 76 | EnclaveInput.newBuilder() 77 | .setExtension(EnclaveDemoExtension.quickstartInput, demoInput) 78 | .build(); 79 | 80 | // Register protobuf extension for output. 81 | ExtensionRegistry registry = ExtensionRegistry.newInstance(); 82 | registry.add(EnclaveDemoExtension.quickstartOutput); 83 | 84 | EnclaveClient client = EnclaveManager.getInstance().getEnclaveClient(enclaveName); 85 | EnclaveOutput output = client.enterAndRun(enclaveInput, registry); 86 | Demo encryptedText = output.getExtension(EnclaveDemoExtension.quickstartOutput); 87 | 88 | System.out.println("Encrypted message:" + encryptedText.getValue()); 89 | 90 | // Part 3: Finalization 91 | EnclaveFinal finalInput = EnclaveFinal.getDefaultInstance(); 92 | EnclaveManager.getInstance().destroyEnclaveClient(client, finalInput); 93 | } 94 | 95 | public static String getMessage() { 96 | String plainText = null; 97 | try (Scanner scanner = new Scanner(System.in, UTF_8.name())) { 98 | System.out.println("Please enter a message to encrypt: "); 99 | plainText = scanner.nextLine(); 100 | } 101 | 102 | if (plainText == null || plainText.length() == 0) { 103 | System.out.println("No input provided."); 104 | System.exit(1); 105 | } 106 | 107 | return plainText; 108 | } 109 | 110 | private DemoDriver() {} 111 | } 112 | -------------------------------------------------------------------------------- /quickstart/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | load("@linux_sgx//:sgx_sdk.bzl", "sgx") 18 | load("@rules_cc//cc:defs.bzl", "cc_proto_library") 19 | load("@rules_proto//proto:defs.bzl", "proto_library") 20 | load("@com_google_asylo//asylo/bazel:asylo.bzl", "cc_unsigned_enclave", "debug_sign_enclave", "enclave_loader") 21 | 22 | licenses(["notice"]) 23 | 24 | package( 25 | default_visibility = [ 26 | "@com_google_asylo//asylo:implementation", 27 | ], 28 | ) 29 | 30 | # Example and exercise for using Asylo toolkits. 31 | proto_library( 32 | name = "demo_proto", 33 | srcs = ["demo.proto"], 34 | deps = ["@com_google_asylo//asylo:enclave_proto"], 35 | ) 36 | 37 | cc_proto_library( 38 | name = "demo_cc_proto", 39 | deps = [":demo_proto"], 40 | ) 41 | 42 | cc_unsigned_enclave( 43 | name = "demo_enclave_unsigned.so", 44 | srcs = ["demo_enclave.cc"], 45 | deps = [ 46 | ":demo_cc_proto", 47 | "@com_google_absl//absl/base:core_headers", 48 | "@com_google_absl//absl/strings", 49 | "@com_google_asylo//asylo:enclave_runtime", 50 | "@com_google_asylo//asylo/crypto:aead_cryptor", 51 | "@com_google_asylo//asylo/util:cleansing_types", 52 | "@com_google_asylo//asylo/util:status", 53 | ], 54 | ) 55 | 56 | debug_sign_enclave( 57 | name = "demo_enclave.so", 58 | unsigned = "demo_enclave_unsigned.so", 59 | ) 60 | 61 | enclave_loader( 62 | name = "quickstart", 63 | srcs = ["demo_driver.cc"], 64 | backends = sgx.backend_labels, # Has SGX loader dependencies 65 | enclaves = {"enclave": ":demo_enclave.so"}, 66 | loader_args = ["--enclave_path='{enclave}'"], 67 | deps = [ 68 | ":demo_cc_proto", 69 | "@com_google_absl//absl/flags:flag", 70 | "@com_google_absl//absl/flags:parse", 71 | "@com_google_asylo//asylo:enclave_cc_proto", 72 | "@com_google_asylo//asylo:enclave_client", 73 | "@com_google_asylo//asylo/util:logging", 74 | ] + select( 75 | { 76 | "@linux_sgx//:sgx_hw": ["@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto"], 77 | "@linux_sgx//:sgx_sim": ["@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto"], 78 | }, 79 | no_match_error = "quickstart is only configured to use the SGX backends", 80 | ), 81 | ) 82 | -------------------------------------------------------------------------------- /quickstart/demo.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2018 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package guide.asylo; 20 | 21 | import "asylo/enclave.proto"; 22 | 23 | // A custom message to pass in and out of our enclave. 24 | message Demo { 25 | // This string value is used for both user input and enclave output. 26 | optional string value = 1; 27 | } 28 | 29 | // The EnclaveInput message that is passed to the enclave can be extended with 30 | // a Demo message to communicate a value our enclave knows to expect. 31 | extend .asylo.EnclaveInput { 32 | optional Demo quickstart_input = 9001; 33 | } 34 | 35 | // The EnclaveOutput message that is passed out of the enclave can be extended 36 | // with a Demo message to communicate a value our driver knows to expect. 37 | extend .asylo.EnclaveOutput { 38 | optional Demo quickstart_output = 9001; 39 | } 40 | -------------------------------------------------------------------------------- /quickstart/demo_driver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2018 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/flags/flag.h" 23 | #include "absl/flags/parse.h" 24 | #include "asylo/client.h" 25 | #include "asylo/platform/primitives/sgx/loader.pb.h" 26 | #include "asylo/util/logging.h" 27 | #include "quickstart/demo.pb.h" 28 | 29 | ABSL_FLAG(std::string, enclave_path, "", 30 | "Path to enclave binary image to load"); 31 | ABSL_FLAG(std::string, message, "", "Message to encrypt"); 32 | 33 | // Populates |enclave_input|->value() with |user_message|. 34 | void SetEnclaveUserMessage(asylo::EnclaveInput *enclave_input, 35 | const std::string &user_message) { 36 | guide::asylo::Demo *user_input = 37 | enclave_input->MutableExtension(guide::asylo::quickstart_input); 38 | user_input->set_value(user_message); 39 | } 40 | 41 | // Retrieves encrypted message from |output|. Intended to be used by the reader 42 | // for completing the exercise. 43 | const std::string GetEnclaveOutputMessage(const asylo::EnclaveOutput &output) { 44 | return output.GetExtension(guide::asylo::quickstart_output).value(); 45 | } 46 | 47 | int main(int argc, char *argv[]) { 48 | absl::ParseCommandLine(argc, argv); 49 | 50 | constexpr char kEnclaveName[] = "demo_enclave"; 51 | 52 | const std::string message = absl::GetFlag(FLAGS_message); 53 | LOG_IF(QFATAL, message.empty()) << "Empty --message flag."; 54 | 55 | const std::string enclave_path = absl::GetFlag(FLAGS_enclave_path); 56 | LOG_IF(QFATAL, enclave_path.empty()) << "Empty --enclave_path flag."; 57 | 58 | // Part 1: Initialization 59 | 60 | // Prepare |EnclaveManager| with default |EnclaveManagerOptions| 61 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions()); 62 | auto manager_result = asylo::EnclaveManager::Instance(); 63 | LOG_IF(QFATAL, !manager_result.ok()) << "Could not obtain EnclaveManager"; 64 | 65 | // Prepare |load_config| message. 66 | asylo::EnclaveLoadConfig load_config; 67 | load_config.set_name(kEnclaveName); 68 | 69 | // Prepare |sgx_config| message. 70 | auto sgx_config = load_config.MutableExtension(asylo::sgx_load_config); 71 | sgx_config->set_debug(true); 72 | auto file_enclave_config = sgx_config->mutable_file_enclave_config(); 73 | file_enclave_config->set_enclave_path(enclave_path); 74 | 75 | // Load Enclave with prepared |EnclaveManager| and |load_config| message. 76 | asylo::EnclaveManager *manager = manager_result.value(); 77 | auto status = manager->LoadEnclave(load_config); 78 | LOG_IF(QFATAL, !status.ok()) << "LoadEnclave failed with: " << status; 79 | 80 | // Part 2: Secure execution 81 | 82 | // Prepare |input| with |message| and create |output| to retrieve response 83 | // from enclave. 84 | asylo::EnclaveInput input; 85 | SetEnclaveUserMessage(&input, message); 86 | asylo::EnclaveOutput output; 87 | 88 | // Get |EnclaveClient| for loaded enclave and execute |EnterAndRun|. 89 | asylo::EnclaveClient *const client = manager->GetClient(kEnclaveName); 90 | status = client->EnterAndRun(input, &output); 91 | LOG_IF(QFATAL, !status.ok()) << "EnterAndRun failed with: " << status; 92 | 93 | // Part 3: Finalization 94 | 95 | // |DestroyEnclave| before exiting program. 96 | asylo::EnclaveFinal empty_final_input; 97 | status = manager->DestroyEnclave(client, empty_final_input); 98 | LOG_IF(QFATAL, !status.ok()) << "DestroyEnclave failed with: " << status; 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /quickstart/demo_enclave.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2018 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/base/macros.h" 23 | #include "absl/status/status.h" 24 | #include "absl/strings/escaping.h" 25 | #include "absl/strings/str_cat.h" 26 | #include "asylo/crypto/aead_cryptor.h" 27 | #include "asylo/crypto/util/byte_container_view.h" 28 | #include "asylo/trusted_application.h" 29 | #include "asylo/util/cleansing_types.h" 30 | #include "asylo/util/status_macros.h" 31 | #include "asylo/util/statusor.h" 32 | #include "quickstart/demo.pb.h" 33 | 34 | namespace asylo { 35 | namespace { 36 | 37 | // Example 128-bit AES key. 38 | constexpr uint8_t kAesKey128[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 39 | 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 40 | 0x12, 0x13, 0x14, 0x15}; 41 | 42 | // Helper function that adapts absl::BytesToHexString, allowing it to be used 43 | // with ByteContainerView. 44 | std::string BytesToHexString(ByteContainerView bytes) { 45 | return absl::BytesToHexString(absl::string_view( 46 | reinterpret_cast(bytes.data()), bytes.size())); 47 | } 48 | 49 | // Encrypts a message against `kAesKey128` and returns a 12-byte nonce followed 50 | // by authenticated ciphertext, encoded as a hex string. 51 | const StatusOr EncryptMessage(const std::string &message) { 52 | std::unique_ptr cryptor; 53 | ASYLO_ASSIGN_OR_RETURN(cryptor, 54 | AeadCryptor::CreateAesGcmSivCryptor(kAesKey128)); 55 | 56 | std::vector additional_authenticated_data; 57 | std::vector nonce(cryptor->NonceSize()); 58 | std::vector ciphertext(message.size() + cryptor->MaxSealOverhead()); 59 | size_t ciphertext_size; 60 | 61 | ASYLO_RETURN_IF_ERROR(cryptor->Seal( 62 | message, additional_authenticated_data, absl::MakeSpan(nonce), 63 | absl::MakeSpan(ciphertext), &ciphertext_size)); 64 | 65 | return absl::StrCat(BytesToHexString(nonce), BytesToHexString(ciphertext)); 66 | } 67 | 68 | // Decrypts a message using `kAesKey128`. Expects `nonce_and_ciphertext` to be 69 | // encoded as a hex string, and lead with a 12-byte nonce. Intended to be 70 | // used by the reader for completing the exercise. 71 | const StatusOr DecryptMessage( 72 | const std::string &nonce_and_ciphertext) { 73 | std::string input_bytes = absl::HexStringToBytes(nonce_and_ciphertext); 74 | 75 | std::unique_ptr cryptor; 76 | ASYLO_ASSIGN_OR_RETURN(cryptor, 77 | AeadCryptor::CreateAesGcmSivCryptor(kAesKey128)); 78 | 79 | if (input_bytes.size() < cryptor->NonceSize()) { 80 | return Status( 81 | absl::StatusCode::kInvalidArgument, 82 | absl::StrCat("Input too short: expected at least ", 83 | cryptor->NonceSize(), " bytes, got ", input_bytes.size())); 84 | } 85 | 86 | std::vector additional_authenticated_data; 87 | std::vector nonce = {input_bytes.begin(), 88 | input_bytes.begin() + cryptor->NonceSize()}; 89 | std::vector ciphertext = {input_bytes.begin() + cryptor->NonceSize(), 90 | input_bytes.end()}; 91 | 92 | // The plaintext is always smaller than the ciphertext, so use 93 | // `ciphertext.size()` as an upper bound on the plaintext buffer size. 94 | CleansingVector plaintext(ciphertext.size()); 95 | size_t plaintext_size; 96 | 97 | ASYLO_RETURN_IF_ERROR(cryptor->Open(ciphertext, additional_authenticated_data, 98 | nonce, absl::MakeSpan(plaintext), 99 | &plaintext_size)); 100 | 101 | return CleansingString(plaintext.begin(), plaintext.end()); 102 | } 103 | 104 | } // namespace 105 | 106 | class EnclaveDemo : public TrustedApplication { 107 | public: 108 | EnclaveDemo() = default; 109 | 110 | Status Run(const EnclaveInput &input, EnclaveOutput *output) { 111 | std::string user_message = GetEnclaveUserMessage(input); 112 | 113 | std::string result; 114 | ASYLO_ASSIGN_OR_RETURN(result, EncryptMessage(user_message)); 115 | 116 | std::cout << "Encrypted message:" << std::endl << result << std::endl; 117 | 118 | return absl::OkStatus(); 119 | } 120 | 121 | // Retrieves user message from |input|. 122 | const std::string GetEnclaveUserMessage(const EnclaveInput &input) { 123 | return input.GetExtension(guide::asylo::quickstart_input).value(); 124 | } 125 | 126 | // Populates |enclave_output|->value() with |output_message|. Intended to be 127 | // used by the reader for completing the exercise. 128 | void SetEnclaveOutputMessage(EnclaveOutput *enclave_output, 129 | const std::string &output_message) { 130 | guide::asylo::Demo *output = 131 | enclave_output->MutableExtension(guide::asylo::quickstart_output); 132 | output->set_value(output_message); 133 | } 134 | }; 135 | 136 | TrustedApplication *BuildTrustedApplication() { return new EnclaveDemo; } 137 | 138 | } // namespace asylo 139 | -------------------------------------------------------------------------------- /quickstart/solution/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | load("@linux_sgx//:sgx_sdk.bzl", "sgx") 18 | load("@rules_cc//cc:defs.bzl", "cc_proto_library") 19 | load("@rules_proto//proto:defs.bzl", "proto_library") 20 | load("@com_google_asylo//asylo/bazel:asylo.bzl", "cc_unsigned_enclave", "debug_sign_enclave", "enclave_loader") 21 | 22 | licenses(["notice"]) 23 | 24 | package( 25 | default_visibility = ["//visibility:public"], 26 | ) 27 | 28 | # Example and exercise for using Asylo toolkits. 29 | proto_library( 30 | name = "demo_proto", 31 | srcs = ["demo.proto"], 32 | deps = ["@com_google_asylo//asylo:enclave_proto"], 33 | ) 34 | 35 | cc_proto_library( 36 | name = "demo_cc_proto", 37 | deps = [":demo_proto"], 38 | ) 39 | 40 | cc_unsigned_enclave( 41 | name = "demo_enclave_unsigned.so", 42 | srcs = ["demo_enclave.cc"], 43 | deps = [ 44 | ":demo_cc_proto", 45 | "@com_google_absl//absl/base:core_headers", 46 | "@com_google_absl//absl/strings", 47 | "@com_google_asylo//asylo:enclave_runtime", 48 | "@com_google_asylo//asylo/crypto:aead_cryptor", 49 | "@com_google_asylo//asylo/util:cleansing_types", 50 | "@com_google_asylo//asylo/util:status", 51 | ], 52 | ) 53 | 54 | debug_sign_enclave( 55 | name = "demo_enclave.so", 56 | unsigned = "demo_enclave_unsigned.so", 57 | ) 58 | 59 | enclave_loader( 60 | name = "quickstart", 61 | srcs = ["demo_driver.cc"], 62 | backends = sgx.backend_labels, # Has SGX loader dependencies 63 | enclaves = {"enclave": ":demo_enclave.so"}, 64 | loader_args = ["--enclave_path='{enclave}'"], 65 | deps = [ 66 | ":demo_cc_proto", 67 | "@com_google_absl//absl/flags:flag", 68 | "@com_google_absl//absl/flags:parse", 69 | "@com_google_asylo//asylo:enclave_cc_proto", 70 | "@com_google_asylo//asylo:enclave_client", 71 | "@com_google_asylo//asylo/util:logging", 72 | ] + select( 73 | { 74 | "@linux_sgx//:sgx_hw": ["@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto"], 75 | "@linux_sgx//:sgx_sim": ["@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto"], 76 | }, 77 | no_match_error = "quickstart is only configured to use the SGX backends", 78 | ), 79 | ) 80 | -------------------------------------------------------------------------------- /quickstart/solution/demo.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2018 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package guide.asylo; 20 | 21 | import "asylo/enclave.proto"; 22 | 23 | option java_package = "com.example"; 24 | option java_multiple_files = true; 25 | option java_outer_classname = "EnclaveDemoExtension"; 26 | 27 | // A custom message to pass in and out of our enclave. 28 | message Demo { 29 | // This string value is used for both user input and enclave output. 30 | optional string value = 1; 31 | enum Action { 32 | UNKNOWN = 0; 33 | ENCRYPT = 1; 34 | DECRYPT = 2; 35 | } 36 | optional Action action = 2; 37 | } 38 | 39 | // The EnclaveInput message that is passed to the enclave can be extended with 40 | // a Demo message to communicate a value our enclave knows to expect. 41 | extend .asylo.EnclaveInput { 42 | optional Demo quickstart_input = 9001; 43 | } 44 | 45 | // The EnclaveOutput message that is passed out of the enclave can be extended 46 | // with a Demo message to communicate a value our driver knows to expect. 47 | extend .asylo.EnclaveOutput { 48 | optional Demo quickstart_output = 9001; 49 | } 50 | -------------------------------------------------------------------------------- /quickstart/solution/demo_driver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2018 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/flags/flag.h" 23 | #include "absl/flags/parse.h" 24 | #include "asylo/client.h" 25 | #include "asylo/enclave.pb.h" 26 | #include "asylo/platform/primitives/sgx/loader.pb.h" 27 | #include "asylo/util/logging.h" 28 | #include "quickstart/solution/demo.pb.h" 29 | 30 | ABSL_FLAG(std::string, enclave_path, "", "Path to enclave to load"); 31 | ABSL_FLAG(std::string, message1, "", "The first message to encrypt"); 32 | ABSL_FLAG(std::string, message2, "", "The second message to encrypt"); 33 | ABSL_FLAG(std::string, ciphertext, "", "The ciphertext message to decrypt"); 34 | 35 | // Populates |enclave_input|->value() with |user_message|. 36 | void SetEnclaveUserMessage(asylo::EnclaveInput *enclave_input, 37 | const std::string &user_message, 38 | guide::asylo::Demo::Action action) { 39 | guide::asylo::Demo *user_input = 40 | enclave_input->MutableExtension(guide::asylo::quickstart_input); 41 | user_input->set_value(user_message); 42 | user_input->set_action(action); 43 | } 44 | 45 | // Retrieves encrypted message from |output|. Intended to be used by the reader 46 | // for completing the exercise. 47 | const std::string GetEnclaveOutputMessage(const asylo::EnclaveOutput &output) { 48 | return output.GetExtension(guide::asylo::quickstart_output).value(); 49 | } 50 | 51 | int main(int argc, char *argv[]) { 52 | absl::ParseCommandLine(argc, argv); 53 | 54 | LOG_IF(QFATAL, absl::GetFlag(FLAGS_message1).empty() && 55 | absl::GetFlag(FLAGS_message2).empty() && 56 | absl::GetFlag(FLAGS_ciphertext).empty()) 57 | << "Must specify at least one of --message1, --message2, or --ciphertext " 58 | "flag values"; 59 | 60 | // Part 1: Initialization 61 | 62 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions()); 63 | auto manager_result = asylo::EnclaveManager::Instance(); 64 | LOG_IF(QFATAL, !manager_result.ok()) << "Could not obtain EnclaveManager"; 65 | 66 | // Create an EnclaveLoadConfig object. 67 | asylo::EnclaveLoadConfig load_config; 68 | load_config.set_name("demo_enclave"); 69 | 70 | // Create an SgxLoadConfig object. 71 | asylo::SgxLoadConfig sgx_config; 72 | asylo::SgxLoadConfig::FileEnclaveConfig file_enclave_config; 73 | file_enclave_config.set_enclave_path(absl::GetFlag(FLAGS_enclave_path)); 74 | *sgx_config.mutable_file_enclave_config() = file_enclave_config; 75 | sgx_config.set_debug(true); 76 | 77 | // Set an SGX message extension to load_config. 78 | *load_config.MutableExtension(asylo::sgx_load_config) = sgx_config; 79 | 80 | asylo::EnclaveManager *manager = manager_result.value(); 81 | asylo::Status status = manager->LoadEnclave(load_config); 82 | LOG_IF(QFATAL, !status.ok()) << "LoadEnclave failed with: " << status; 83 | 84 | // Part 2: Secure execution 85 | 86 | asylo::EnclaveClient *client = manager->GetClient("demo_enclave"); 87 | asylo::EnclaveInput input; 88 | asylo::EnclaveOutput output; 89 | 90 | if (!absl::GetFlag(FLAGS_message1).empty()) { 91 | SetEnclaveUserMessage(&input, absl::GetFlag(FLAGS_message1), 92 | guide::asylo::Demo::ENCRYPT); 93 | status = client->EnterAndRun(input, &output); 94 | LOG_IF(QFATAL, !status.ok()) << "EnterAndRun failed with: " << status; 95 | std::cout << "Encrypted message1 from driver:" << std::endl 96 | << GetEnclaveOutputMessage(output) << std::endl; 97 | } 98 | 99 | if (!absl::GetFlag(FLAGS_message2).empty()) { 100 | SetEnclaveUserMessage(&input, absl::GetFlag(FLAGS_message2), 101 | guide::asylo::Demo::ENCRYPT); 102 | status = client->EnterAndRun(input, &output); 103 | LOG_IF(QFATAL, !status.ok()) << "EnterAndRun failed with: " << status; 104 | std::cout << "Encrypted message2 from driver:" << std::endl 105 | << GetEnclaveOutputMessage(output) << std::endl; 106 | } 107 | 108 | if (!absl::GetFlag(FLAGS_ciphertext).empty()) { 109 | SetEnclaveUserMessage(&input, absl::GetFlag(FLAGS_ciphertext), 110 | guide::asylo::Demo::DECRYPT); 111 | status = client->EnterAndRun(input, &output); 112 | LOG_IF(QFATAL, !status.ok()) << "EnterAndRun failed with: " << status; 113 | std::cout << "Decrypted ciphertext from driver:" << std::endl 114 | << GetEnclaveOutputMessage(output) << std::endl; 115 | } 116 | 117 | // Part 3: Finalization 118 | 119 | asylo::EnclaveFinal empty_final_input; 120 | status = manager->DestroyEnclave(client, empty_final_input); 121 | LOG_IF(QFATAL, !status.ok()) << "DestroyEnclave failed with: " << status; 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /quickstart/solution/demo_enclave.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2018 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | 21 | #include "absl/base/macros.h" 22 | #include "absl/status/status.h" 23 | #include "absl/strings/escaping.h" 24 | #include "absl/strings/str_cat.h" 25 | #include "asylo/crypto/aead_cryptor.h" 26 | #include "asylo/crypto/util/byte_container_view.h" 27 | #include "asylo/trusted_application.h" 28 | #include "asylo/util/cleansing_types.h" 29 | #include "asylo/util/status_macros.h" 30 | #include "asylo/util/statusor.h" 31 | #include "quickstart/solution/demo.pb.h" 32 | 33 | namespace asylo { 34 | namespace { 35 | 36 | // Example 128-bit AES key. 37 | constexpr uint8_t kAesKey128[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 38 | 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 39 | 0x12, 0x13, 0x14, 0x15}; 40 | 41 | // Helper function that adapts absl::BytesToHexString, allowing it to be used 42 | // with ByteContainerView. 43 | std::string BytesToHexString(ByteContainerView bytes) { 44 | return absl::BytesToHexString(absl::string_view( 45 | reinterpret_cast(bytes.data()), bytes.size())); 46 | } 47 | 48 | // Encrypts a message against `kAesKey128` and returns a 12-byte nonce followed 49 | // by authenticated ciphertext, encoded as a hex string. 50 | const StatusOr EncryptMessage(const std::string &message) { 51 | std::unique_ptr cryptor; 52 | ASYLO_ASSIGN_OR_RETURN(cryptor, 53 | AeadCryptor::CreateAesGcmSivCryptor(kAesKey128)); 54 | 55 | std::vector additional_authenticated_data; 56 | std::vector nonce(cryptor->NonceSize()); 57 | std::vector ciphertext(message.size() + cryptor->MaxSealOverhead()); 58 | size_t ciphertext_size; 59 | 60 | ASYLO_RETURN_IF_ERROR(cryptor->Seal( 61 | message, additional_authenticated_data, absl::MakeSpan(nonce), 62 | absl::MakeSpan(ciphertext), &ciphertext_size)); 63 | 64 | return absl::StrCat(BytesToHexString(nonce), BytesToHexString(ciphertext)); 65 | } 66 | 67 | // Decrypts a message using `kAesKey128`. Expects `nonce_and_ciphertext` to be 68 | // encoded as a hex string, and lead with a 12-byte nonce. Intended to be 69 | // used by the reader for completing the exercise. 70 | const StatusOr DecryptMessage( 71 | const std::string &nonce_and_ciphertext) { 72 | std::string input_bytes = absl::HexStringToBytes(nonce_and_ciphertext); 73 | 74 | std::unique_ptr cryptor; 75 | ASYLO_ASSIGN_OR_RETURN(cryptor, 76 | AeadCryptor::CreateAesGcmSivCryptor(kAesKey128)); 77 | 78 | if (input_bytes.size() < cryptor->NonceSize()) { 79 | return Status( 80 | absl::StatusCode::kInvalidArgument, 81 | absl::StrCat("Input too short: expected at least ", 82 | cryptor->NonceSize(), " bytes, got ", input_bytes.size())); 83 | } 84 | 85 | std::vector additional_authenticated_data; 86 | std::vector nonce = {input_bytes.begin(), 87 | input_bytes.begin() + cryptor->NonceSize()}; 88 | std::vector ciphertext = {input_bytes.begin() + cryptor->NonceSize(), 89 | input_bytes.end()}; 90 | 91 | // The plaintext is always smaller than the ciphertext, so use 92 | // `ciphertext.size()` as an upper bound on the plaintext buffer size. 93 | CleansingVector plaintext(ciphertext.size()); 94 | size_t plaintext_size; 95 | 96 | ASYLO_RETURN_IF_ERROR(cryptor->Open(ciphertext, additional_authenticated_data, 97 | nonce, absl::MakeSpan(plaintext), 98 | &plaintext_size)); 99 | 100 | return CleansingString(plaintext.begin(), plaintext.end()); 101 | } 102 | 103 | } // namespace 104 | 105 | class EnclaveDemo : public TrustedApplication { 106 | public: 107 | EnclaveDemo() = default; 108 | 109 | Status Run(const EnclaveInput &input, EnclaveOutput *output) { 110 | std::string user_message = GetEnclaveUserMessage(input); 111 | 112 | switch (GetEnclaveUserAction(input)) { 113 | case guide::asylo::Demo::ENCRYPT: { 114 | std::string result; 115 | ASYLO_ASSIGN_OR_RETURN(result, EncryptMessage(user_message)); 116 | SetEnclaveOutputMessage(output, result); 117 | break; 118 | } 119 | case guide::asylo::Demo::DECRYPT: { 120 | CleansingString result; 121 | ASYLO_ASSIGN_OR_RETURN(result, DecryptMessage(user_message)); 122 | SetEnclaveOutputMessage(output, result); 123 | break; 124 | } 125 | default: 126 | return absl::InvalidArgumentError("Action unspecified"); 127 | } 128 | 129 | return absl::OkStatus(); 130 | } 131 | 132 | // Retrieves user message from |input|. 133 | const std::string GetEnclaveUserMessage(const EnclaveInput &input) { 134 | return input.GetExtension(guide::asylo::quickstart_input).value(); 135 | } 136 | 137 | // Retrieves user action from |input|. 138 | guide::asylo::Demo::Action GetEnclaveUserAction(const EnclaveInput &input) { 139 | return input.GetExtension(guide::asylo::quickstart_input).action(); 140 | } 141 | 142 | // Populates |enclave_output|->value() with |output_message|. Intended to be 143 | // used by the reader for completing the exercise. 144 | void SetEnclaveOutputMessage(EnclaveOutput *enclave_output, 145 | absl::string_view output_message) { 146 | guide::asylo::Demo *output = 147 | enclave_output->MutableExtension(guide::asylo::quickstart_output); 148 | output->set_value(std::string(output_message)); 149 | } 150 | }; 151 | 152 | TrustedApplication *BuildTrustedApplication() { return new EnclaveDemo; } 153 | 154 | } // namespace asylo 155 | -------------------------------------------------------------------------------- /redis/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | load("@linux_sgx//:sgx_sdk.bzl", "sgx", "sgx_enclave_configuration") 18 | load("@rules_cc//cc:defs.bzl", "cc_library") 19 | load( 20 | "@com_google_asylo//asylo/bazel:asylo.bzl", 21 | "cc_enclave_binary", 22 | "enclave_test", 23 | ) 24 | load("@com_google_asylo//asylo/bazel:copts.bzl", "ASYLO_DEFAULT_COPTS") 25 | 26 | licenses(["notice"]) 27 | 28 | # An implementation of ApplicationConfig() that returns an EnclaveConfig with 29 | # an SGX local assertion authority config. 30 | cc_library( 31 | name = "redis_enclave_config", 32 | srcs = ["redis_enclave_config.cc"], 33 | visibility = ["//visibility:public"], 34 | deps = [ 35 | "@com_google_asylo//asylo:enclave_cc_proto", 36 | "@com_google_asylo//asylo/identity:descriptions", 37 | "@com_google_asylo//asylo/identity:enclave_assertion_authority_config_cc_proto", 38 | "@com_google_asylo//asylo/identity/attestation/sgx:sgx_local_assertion_authority_config_cc_proto", 39 | "@com_google_asylo//asylo/util:logging", 40 | ], 41 | ) 42 | 43 | # The SGX configuration to run Redis Server inside an enclave. 44 | sgx_enclave_configuration( 45 | name = "redis_enclave_configuration", 46 | heap_max_size = "0x1000000", 47 | stack_max_size = "0x400000", 48 | ) 49 | 50 | # The whole application wrapper target that runs Redis server inside an enclave. 51 | cc_enclave_binary( 52 | name = "asylo_redis", 53 | application_enclave_config = ":redis_enclave_config", 54 | enclave_build_config = ":redis_enclave_configuration", 55 | deps = ["@com_github_antirez_redis//:redis_main"], 56 | ) 57 | 58 | enclave_test( 59 | name = "redis_test", 60 | srcs = ["redis_test.cc"], 61 | backend_dependent_data = [ 62 | ":asylo_redis_host_loader", 63 | ], 64 | backends = sgx.backend_labels, 65 | data = ["@com_github_antirez_redis//:redis_cli_bin"], 66 | tags = ["exclusive"], 67 | test_args = [ 68 | "--server_path=$(rootpath :asylo_redis_host_loader)", 69 | "--client_path=$(rootpath @com_github_antirez_redis//:redis_cli_bin)", 70 | ], 71 | deps = [ 72 | "@bazel_tools//tools/cpp/runfiles", 73 | "@com_google_absl//absl/base:core_headers", 74 | "@com_google_absl//absl/flags:flag", 75 | "@com_google_absl//absl/memory", 76 | "@com_google_absl//absl/strings", 77 | "@com_google_absl//absl/synchronization", 78 | "@com_google_asylo//asylo/test/util:exec_tester", 79 | "@com_google_asylo//asylo/test/util:status_matchers", 80 | "@com_google_asylo//asylo/test/util:test_flags", 81 | "@com_google_asylo//asylo/test/util:test_main", 82 | "@com_google_asylo//asylo/util:status", 83 | "@com_google_googletest//:gtest", 84 | ], 85 | ) 86 | -------------------------------------------------------------------------------- /redis/redis_enclave_config.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include "asylo/enclave.pb.h" 20 | #include "asylo/identity/attestation/sgx/sgx_local_assertion_authority_config.pb.h" 21 | #include "asylo/identity/descriptions.h" 22 | #include "asylo/identity/enclave_assertion_authority_config.pb.h" 23 | #include "asylo/util/logging.h" 24 | 25 | // The attestation domain is expected to be a 16-byte unique identifier. 26 | constexpr char kAttestationDomain[] = "A 16-byte string"; 27 | 28 | extern "C" asylo::EnclaveConfig GetApplicationConfig() { 29 | asylo::EnclaveAssertionAuthorityConfig assertion_authority_config; 30 | asylo::SetSgxLocalAssertionDescription( 31 | assertion_authority_config.mutable_description()); 32 | 33 | asylo::SgxLocalAssertionAuthorityConfig sgx_local_assertion_authority_config; 34 | sgx_local_assertion_authority_config.set_attestation_domain( 35 | kAttestationDomain); 36 | CHECK(sgx_local_assertion_authority_config.SerializeToString( 37 | assertion_authority_config.mutable_config())); 38 | 39 | asylo::EnclaveConfig enclave_config; 40 | *enclave_config.add_enclave_assertion_authority_configs() = 41 | std::move(assertion_authority_config); 42 | 43 | return enclave_config; 44 | } 45 | -------------------------------------------------------------------------------- /remote/bouncing_circles/README.md: -------------------------------------------------------------------------------- 1 | 21 | 22 | ## Introduction 23 | 24 | This guide demonstrates more elaborate usage of Asylo with a Remote Backend. It 25 | assumes the reader has knowledge introduced in the 26 | [Remote Quickstart Guide](https://asylo.dev/docs/guides/remote_quickstart.html). 27 | 28 | The bouncing circles web application uses four separate enclaves to track four 29 | circles. A simple web server accesses each enclave via the remote enclave 30 | backend. Each enclave, once initialized, holds color, location, radius and speed 31 | of the circle it owns, rendering them isolated from the outer world. The web 32 | application makes an EnterAndRun call to each of the 4 enclaves, gets back 33 | color, location and radius and draws the circle. 34 | 35 | This example provides two frameworks that are accessed identically by the remote 36 | backend: local and remote. Both of them provision RemoteEnclaveProxyServer, but 37 | do it differently: 38 | 39 | - local version runs the enclaves on the same machine as the application 40 | 41 | - remote version runs the enclaves on an SGX-enabled machine while the Web 42 | Application can be run on a non-SGX machine. 43 | 44 | ## Local version - still remote backend, but both running on the same machine 45 | 46 | ### Building 47 | 48 | To build the application and the enclaves: 49 | 50 | ```bash 51 | export CONFIG_TYPE=sgx # Or sgx-sim if not running on SGX-enabled hardware. 52 | bazel build :web_application --config=${CONFIG_TYPE} --define=ASYLO_REMOTE=1 53 | ``` 54 | 55 | Note: The `CONFIG_TYPE=sgx` flag selects our enclave cross compiler toolchain, 56 | which builds code to run inside enclaves. To run on non-SGX hardware, specify 57 | simulated SGX flag `CONFIG_TYPE=sgx-sim`. 58 | 59 | ### Running 60 | 61 | To run the program, invoke the application binary (from bazel-bin): 62 | 63 | ```bash 64 | $(bazel info bazel-bin)/remote/bouncing_circles/web_application \ 65 | --remote_proxy="$(bazel info bazel-bin)/remote/bouncing_circles/web_application" 66 | ``` 67 | 68 | and then open a browser window at `http://:8888/` and follow the 69 | link named "circles". 70 | 71 | ## Remote backend running enclaves on another machine than the application 72 | 73 | The previous demo launched the application with local provisioning. 74 | 75 | To make it truly remote, we will now now utilize remote provisioning with our 76 | example remote 77 | [provision server](/remote/provision_server) 78 | and run the same application with enclaves deployed on another docker image. 79 | 80 | First, if you haven't already done so, download the Asylo SDK and Examples 81 | repos: 82 | 83 | ```bash 84 | export ASYLO_SDK=~/asylo-sdk 85 | git clone https://github.com/google/asylo.git "${ASYLO_SDK}" 86 | export MY_PROJECT=~/asylo-examples 87 | mkdir -p "${MY_PROJECT}" 88 | wget -q -O - https://github.com/google/asylo-examples/archive/master.tar.gz | \ 89 | tar -zxv --strip 1 --directory "${MY_PROJECT}" 90 | ``` 91 | 92 | Next, run the provision server: 93 | 94 | ```bash 95 | docker run -it --net=host \ 96 | -v ${ASYLO_SDK}:/opt/asylo/sdk \ 97 | -v ${MY_PROJECT}:/opt/asylo/examples \ 98 | -w /opt/asylo/examples/remote/provision_server \ 99 | gcr.io/asylo-framework/asylo:latest \ 100 | ./build.sh 101 | ``` 102 | 103 | Once the provisioning server reports that it is listening to port `4321` 104 | (configurable), run the container with the following command: 105 | 106 | ```bash 107 | export CONFIG_TYPE=sgx # Or sgx-sim if Remote Provision server isn't running on SGX-enabled hardware. 108 | docker run -it --net=host \ 109 | -v ${ASYLO_SDK}:/opt/asylo/sdk \ 110 | -v ${MY_PROJECT}:/opt/asylo/examples \ 111 | -w /opt/asylo/examples/remote/bouncing_circles \ 112 | gcr.io/asylo-framework/asylo:latest \ 113 | ./build.sh ${CONFIG_TYPE} 114 | ``` 115 | 116 | After the application started, open a browser window at `http://:8888/` and follow the link named "circles". 118 | -------------------------------------------------------------------------------- /remote/bouncing_circles/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Script for building the bouncing circles example. 4 | # 5 | # Asylo toolchain has difficulties building with two --config types. This script 6 | # allows users to build the example enclaves with --config=sgx or sgx-sim, and 7 | # the rest of the application without the --config= designation. 8 | # 9 | # Instructions for use: 10 | # Set environment variables ASYLO_SDK, MY_PROJECT, and CONFIG_TYPE. 11 | # -- ASYLO_SDK: Path to the Asylo sdk. 12 | # -- MY_PROJECT: Path to the Examples repo. 13 | # -- CONFIG_TYPE: One of {sgx, sgx-sim} 14 | # Start the provision server with the directions given at asylo/examples/remote/provision_server. 15 | # ```bash 16 | # docker run --it --net=host \ 17 | # -v ${ASYLO_SDK}:/opt/asylo/sdk \ 18 | # -v ${MY_PROJECT}:/opt/asylo/examples \ 19 | # -w /opt/asylo/examples/remote/bouncing_circles \ 20 | # gcr.io/asylo-framework/asylo:latest \ 21 | # ./build.sh ${CONFIG_TYPE} 22 | # ``` 23 | # 24 | # then open a browser window at 25 | # http://:8888/ 26 | # and follow the link 27 | 28 | # If any command fails exit. 29 | set -e 30 | 31 | # Export all variables as environment variables. 32 | set -a 33 | 34 | 35 | # Default configuration for CONFIG_TYPE. 36 | CONFIG_TYPE_DEFAULT=sgx 37 | 38 | # Command line argument: Allows selection of local backend, if one is not 39 | # selected it defaults to $CONFIG_DEFAULT 40 | CONFIG_TYPE=${1:-$CONFIG_TYPE_DEFAULT} 41 | 42 | # Set the ENCLAVE_TAG based on the CONFIG_TYPE. ENCLAVE_TAG is used as part of 43 | # the ENCLAVE_TARGET. 44 | if [ "$CONFIG_TYPE" == "sgx" ]; then 45 | ENCLAVE_TAG="sgx_hw"; 46 | elif [ "$CONFIG_TYPE" == "sgx-sim" ]; then 47 | ENCLAVE_TAG="sgx_sim"; 48 | fi 49 | 50 | if [ -z "$ENCLAVE_TAG" ]; then 51 | echo "CONFIG_TYPE must be one of sgx or sgx-sim"; 52 | exit; 53 | fi 54 | bazel clean 55 | 56 | # Build the circle enclaves. 57 | for ENCLAVE_NUM in {0..3} 58 | do 59 | bazel build --config=${CONFIG_TYPE} \ 60 | //remote/bouncing_circles:circle_enclave_${ENCLAVE_NUM}_debug.so 61 | done 62 | 63 | BAZEL_BIN_PATH=$(bazel info bazel-bin) 64 | CIRCLES_PATH=${BAZEL_BIN_PATH}/remote/bouncing_circles 65 | 66 | # Path where bazel puts generated files - can be but not always the same as 67 | # bazel-bin. 68 | BAZEL_GEN_PATH=$(bazel info bazel-genfiles) 69 | PROVISION_PATH=${BAZEL_GEN_PATH}/remote/provision_server 70 | bazel run //remote/bouncing_circles:web_application_remote -- \ 71 | --port=8888 \ 72 | --security_type=ssl \ 73 | --ssl_key=${PROVISION_PATH}/server.key \ 74 | --ssl_cert=${PROVISION_PATH}/server.crt \ 75 | --enclave_binary_paths=${CIRCLES_PATH}/circle_enclave_0_debug_${CONFIG_TYPE}.so,${CIRCLES_PATH}/circle_enclave_1_debug_${CONFIG_TYPE}.so,${CIRCLES_PATH}/circle_enclave_2_debug_${CONFIG_TYPE}.so,${CIRCLES_PATH}/circle_enclave_3_debug_${CONFIG_TYPE}.so \ 76 | --remote_provision_server=[::1]:4321 \ 77 | --local_client_name=[::1] 78 | -------------------------------------------------------------------------------- /remote/bouncing_circles/circle_client.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_REMOTE_BOUNCING_CIRCLES_CIRCLE_CLIENT_H_ 20 | #define ASYLO_EXAMPLES_REMOTE_BOUNCING_CIRCLES_CIRCLE_CLIENT_H_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "absl/strings/string_view.h" 29 | 30 | namespace asylo { 31 | 32 | class CircleStatus { 33 | public: 34 | CircleStatus() = default; 35 | virtual ~CircleStatus() = default; 36 | 37 | virtual std::tuple Update() = 0; 38 | 39 | static void InitializeGlobal(size_t n, absl::string_view enclave_prefix, 40 | int32_t width, int32_t height); 41 | static std::vector> *circles(); 42 | }; 43 | 44 | } // namespace asylo 45 | 46 | #endif // ASYLO_EXAMPLES_REMOTE_BOUNCING_CIRCLES_CIRCLE_CLIENT_H_ 47 | -------------------------------------------------------------------------------- /remote/bouncing_circles/circle_enclave.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | 21 | #include "absl/memory/memory.h" 22 | #include "absl/status/status.h" 23 | #include "absl/strings/str_cat.h" 24 | #include "absl/strings/string_view.h" 25 | #include "asylo/trusted_application.h" 26 | #include "asylo/util/logging.h" 27 | #include "asylo/util/status.h" 28 | #include "remote/bouncing_circles/circles.pb.h" 29 | 30 | namespace asylo { 31 | namespace { 32 | 33 | class CircleStatus { 34 | public: 35 | CircleStatus(int32_t width, int32_t height) 36 | : width_(width), 37 | height_(height), 38 | x_(std::min((CENTER_X) < 0 ? width + (CENTER_X) : (CENTER_X), width)), 39 | y_(std::min((CENTER_Y) < 0 ? height + (CENTER_Y) : (CENTER_Y), height)), 40 | radius_(std::max(2, (CIRCLE_RADIUS))), 41 | color_(CIRCLE_COLOR) {} 42 | 43 | void Update() { 44 | if (x_ <= width_ / 10) { 45 | step_x_ = +(SPEED_X); 46 | } else if (x_ >= width_ * 9 / 10) { 47 | step_x_ = -(SPEED_X); 48 | } 49 | if (y_ <= height_ / 10) { 50 | step_y_ = +(SPEED_Y); 51 | } else if (y_ >= height_ * 9 / 10) { 52 | step_y_ = -(SPEED_Y); 53 | } 54 | x_ += step_x_; 55 | y_ += step_y_; 56 | if (radius_ <= 10) { 57 | step_radius_ = +2; 58 | } else if (radius_ >= 50) { 59 | step_radius_ = -2; 60 | } 61 | radius_ += step_radius_; 62 | } 63 | 64 | int32_t width() const { return width_; } 65 | int32_t height() const { return height_; } 66 | int32_t x() const { return x_; } 67 | int32_t y() const { return y_; } 68 | int32_t radius() const { return radius_; } 69 | std::string color() const { return color_; } 70 | 71 | private: 72 | const int32_t width_; 73 | const int32_t height_; 74 | 75 | int32_t x_; 76 | int32_t y_; 77 | int32_t radius_; 78 | std::string color_; 79 | 80 | int32_t step_x_ = (SPEED_X); 81 | int32_t step_y_ = (SPEED_Y); 82 | int32_t step_radius_ = 10; 83 | }; 84 | 85 | class CirclesEnclave : public TrustedApplication { 86 | public: 87 | CirclesEnclave() = default; 88 | 89 | asylo::Status Run(const asylo::EnclaveInput &input, 90 | asylo::EnclaveOutput *output) override { 91 | if (input.HasExtension(bouncing_circles::enclave_setup_input)) { 92 | // Output attached and left empty. 93 | output->MutableExtension(bouncing_circles::enclave_setup_output); 94 | return HandleSetup( 95 | input.GetExtension(bouncing_circles::enclave_setup_input)); 96 | } 97 | 98 | if (input.HasExtension(bouncing_circles::enclave_update_position_input)) { 99 | // Input unused. 100 | return HandleUpdate(output->MutableExtension( 101 | bouncing_circles::enclave_update_position_output)); 102 | } 103 | 104 | return absl::InvalidArgumentError("Missing extension on EnclaveInput."); 105 | } 106 | 107 | private: 108 | Status HandleSetup(const bouncing_circles::CirclesSetupInput &input) { 109 | if (input.height() >= input.width()) { 110 | return absl::FailedPreconditionError( 111 | absl::StrCat("Height=", input.height(), " weight=", input.width())); 112 | } 113 | if (managed_circle_) { 114 | return absl::AlreadyExistsError("Circle already created"); 115 | } 116 | managed_circle_ = 117 | absl::make_unique(input.width(), input.height()); 118 | return absl::OkStatus(); 119 | } 120 | 121 | Status HandleUpdate(bouncing_circles::CirclesUpdatePositionOutput *output) { 122 | if (!managed_circle_) { 123 | return absl::NotFoundError("Calling Update before Setup"); 124 | } 125 | managed_circle_->Update(); 126 | output->set_x(managed_circle_->x()); 127 | output->set_y(managed_circle_->y()); 128 | output->set_radius(managed_circle_->radius()); 129 | output->set_color(managed_circle_->color()); 130 | return absl::OkStatus(); 131 | } 132 | 133 | std::unique_ptr managed_circle_; 134 | }; 135 | 136 | } // namespace 137 | 138 | TrustedApplication *BuildTrustedApplication() { return new CirclesEnclave(); } 139 | 140 | } // namespace asylo 141 | -------------------------------------------------------------------------------- /remote/bouncing_circles/circles.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package bouncing_circles; 20 | 21 | import "asylo/enclave.proto"; 22 | 23 | // Extensions to EnclaveInput for use with Circles enclave. 24 | 25 | message CirclesSetupInput { 26 | optional int32 width = 1; 27 | optional int32 height = 2; 28 | } 29 | 30 | message CirclesSetupOutput {} 31 | 32 | message CirclesUpdatePositionInput {} 33 | 34 | message CirclesUpdatePositionOutput { 35 | optional int32 x = 1; 36 | optional int32 y = 2; 37 | optional int32 radius = 3; 38 | optional string color = 4; 39 | } 40 | 41 | extend asylo.EnclaveInput { 42 | optional CirclesSetupInput enclave_setup_input = 9080; 43 | optional CirclesUpdatePositionInput enclave_update_position_input = 9090; 44 | } 45 | 46 | extend asylo.EnclaveOutput { 47 | optional CirclesSetupOutput enclave_setup_output = 9081; 48 | optional CirclesUpdatePositionOutput enclave_update_position_output = 9091; 49 | } 50 | -------------------------------------------------------------------------------- /remote/bouncing_circles/web_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_REMOTE_BOUNCING_CIRCLES_WEB_SERVER_H_ 20 | #define ASYLO_EXAMPLES_REMOTE_BOUNCING_CIRCLES_WEB_SERVER_H_ 21 | 22 | // Based on NWEB.C (see https://github.com/ankushagarwal/nweb) 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "absl/container/flat_hash_map.h" 31 | #include "asylo/util/mutex_guarded.h" 32 | 33 | namespace asylo { 34 | 35 | // Test web server that can only be used in tests. 36 | // It only serves requests that are registered; does not serve any files. 37 | class WebServer { 38 | public: 39 | // In a request '/uri?p1=v1&p2=v2&...' uri determines the handler and 40 | // everything after '?' is parsed into WebRequest as parms['p1'] = 'v1' etc. 41 | // If there is no '?', parms is empty. 42 | struct WebRequest { 43 | absl::flat_hash_map parms; 44 | }; 45 | 46 | // Response and its type 47 | struct WebResponse { 48 | std::string contents; 49 | std::string type = "text/html"; 50 | }; 51 | 52 | // Type used for handler callbacks. 53 | typedef std::function UriHandler; 54 | 55 | // Factory method; the only one allowed to create the server. 56 | static std::unique_ptr Create(int port, size_t max_worker_threads); 57 | 58 | ~WebServer() = default; 59 | 60 | WebServer(const WebServer &other) = delete; 61 | WebServer &operator=(const WebServer &other) = delete; 62 | 63 | // Blocks until server stops, returns immediately if server is not running. 64 | void Wait(); 65 | 66 | void StartServer(); 67 | void StopServer(); 68 | 69 | void RegisterHandler(absl::string_view uri_pattern, UriHandler handler); 70 | void UnregisterHandler(absl::string_view uri_pattern); 71 | 72 | // Returns the handler for the given uri. Requires a handler is registered. 73 | const UriHandler GetHandler(absl::string_view uri_pattern) const; 74 | 75 | // Assign request to an available worker (block if none is available). 76 | void AssignRequest(int socket_fd); 77 | 78 | // Actually assigned port. Valid only after call to StartServer(). 79 | int port() const { return port_; } 80 | 81 | private: 82 | // Worker thread. 83 | struct WorkerThread { 84 | WorkerThread() : state(State()) {} 85 | struct State { 86 | bool must_exit = false; 87 | int socket_fd = -1; // Negative if no request is assigned. 88 | }; 89 | void WorkerThreadRunner(WebServer *server); 90 | MutexGuarded state; 91 | std::unique_ptr thread; // Assigned once, under workers lock. 92 | }; 93 | 94 | // Constructor is private, so that only factory method can create the server. 95 | WebServer(int port, size_t max_worker_threads); 96 | 97 | // Server status. 98 | int port_; 99 | const size_t max_worker_threads_; 100 | const absl::Time start_time_; 101 | 102 | // Registered request handlers. 103 | MutexGuarded> handlers_; 104 | 105 | // Worker threads (no more than max_worker_threads_ at any time). 106 | MutexGuarded> workers_; 107 | }; 108 | 109 | } // namespace asylo 110 | 111 | #endif // ASYLO_EXAMPLES_REMOTE_BOUNCING_CIRCLES_WEB_SERVER_H_ 112 | -------------------------------------------------------------------------------- /remote/bouncing_circles/web_server_test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include "remote/bouncing_circles/web_server.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "absl/container/flat_hash_map.h" 32 | #include "absl/strings/str_cat.h" 33 | #include "absl/strings/str_split.h" 34 | #include "absl/strings/string_view.h" 35 | #include "asylo/util/logging.h" 36 | 37 | using ::testing::Eq; 38 | using ::testing::StrEq; 39 | 40 | namespace asylo { 41 | namespace { 42 | 43 | class WebServerTest : public ::testing::Test { 44 | protected: 45 | void SetUp() override { 46 | web_server_ = WebServer::Create(/*port=*/0, /*max_worker_threads=*/1); 47 | web_server_->StartServer(); 48 | 49 | web_client_fd_ = socket(AF_INET6, SOCK_STREAM, 0); 50 | CHECK_GE(web_client_fd_, 0) 51 | << "Socket failed to create, " << strerror(errno); 52 | 53 | web_server_addr_.sin6_family = AF_INET6; 54 | web_server_addr_.sin6_port = htons(web_server_->port()); 55 | web_server_addr_.sin6_addr = IN6ADDR_LOOPBACK_INIT; 56 | CHECK_GE(connect(web_client_fd_, 57 | reinterpret_cast(&web_server_addr_), 58 | sizeof(web_server_addr_)), 59 | 0) 60 | << "Failed to connect, " << strerror(errno); 61 | } 62 | 63 | void TearDown() override { 64 | web_server_->StopServer(); 65 | web_server_->Wait(); 66 | } 67 | 68 | void RegisterHandler(absl::string_view uri_pattern, 69 | const WebServer::UriHandler &handler) { 70 | web_server_->RegisterHandler(uri_pattern, handler); 71 | } 72 | 73 | // Sends request suffix (something like '/req?a=1&b=2') to the web server, 74 | // reads back response and parses it, verifying the headers. 75 | // Returns pair from the web server response. 76 | std::pair Get(absl::string_view suffix) { 77 | // Send request. 78 | std::string request = absl::StrCat("GET ", suffix, " HTTP/1.1"); 79 | ssize_t ret = send(web_client_fd_, request.data(), request.size(), 0); 80 | CHECK_GE(ret, 0) << "Failed to send request, " << strerror(errno); 81 | 82 | // Get raw response. 83 | static constexpr size_t kBufSize = 1024; 84 | auto buffer = absl::make_unique(kBufSize); 85 | memset(buffer.get(), '\0', kBufSize); 86 | ret = read(web_client_fd_, buffer.get(), kBufSize); 87 | CHECK_GE(ret, 0) << "Failed to read response, " << strerror(errno); 88 | CHECK_LT(ret, kBufSize) << "Response too long, " << strerror(errno); 89 | absl::string_view raw_response(buffer.get(), ret); 90 | 91 | // Retrieve and parse headers. 92 | auto header_end_pos = raw_response.find("\n\n"); 93 | CHECK_NE(header_end_pos, std::string::npos) 94 | << "Response has no headers, '" << raw_response << "'"; 95 | absl::flat_hash_map headers; 96 | for (const auto &h : 97 | absl::StrSplit(raw_response.substr(0, header_end_pos), '\n')) { 98 | if (absl::StartsWith(h, "HTTP/")) { 99 | // There must be OK status at the beginning. 100 | CHECK_EQ(h, "HTTP/1.1 200 OK") << "Status: '" << h << "'"; 101 | continue; 102 | } 103 | auto pos = h.find(": "); 104 | CHECK_NE(pos, std::string::npos) 105 | << "Malformed response header, '" << h << "'"; 106 | CHECK(headers.emplace(h.substr(0, pos), h.substr(pos + 1 + 1)).second) 107 | << "Duplicate header '" << h << "'"; 108 | } 109 | std::string contents_type = headers.find("Content-Type")->second; 110 | int64_t contents_length; 111 | CHECK(absl::SimpleAtoi(headers.find("Content-Length")->second, 112 | &contents_length)); 113 | 114 | // Retrieve data and compose result. 115 | auto contents_data = 116 | raw_response.substr(header_end_pos + 1 + 1, contents_length); 117 | return {std::string(contents_data), contents_type}; 118 | } 119 | 120 | private: 121 | std::unique_ptr web_server_; 122 | struct sockaddr_in6 web_server_addr_; 123 | int web_client_fd_ = -1; 124 | }; 125 | 126 | TEST_F(WebServerTest, HtmlTest) { 127 | constexpr absl::string_view kTestUri("/test"); 128 | constexpr absl::string_view kTestResponse("Hello World!\r\n"); 129 | 130 | WebServer::UriHandler handler = 131 | [&kTestResponse](const WebServer::WebRequest &request) { 132 | WebServer::WebResponse response; 133 | response.contents = std::string(kTestResponse); 134 | return response; 135 | }; 136 | 137 | RegisterHandler(kTestUri, handler); 138 | auto response = Get(kTestUri); 139 | EXPECT_THAT(response.first, Eq(kTestResponse)); 140 | EXPECT_THAT(response.second, StrEq("text/html")); 141 | } 142 | 143 | TEST_F(WebServerTest, XmlTest) { 144 | constexpr absl::string_view kTestUri("/test"); 145 | constexpr absl::string_view kTestResponse("Hello World!\r\n"); 146 | 147 | WebServer::UriHandler handler = 148 | [&kTestResponse](const WebServer::WebRequest &request) { 149 | WebServer::WebResponse response; 150 | response.contents = std::string(kTestResponse); 151 | response.type = "text/xml"; 152 | return response; 153 | }; 154 | 155 | RegisterHandler(kTestUri, handler); 156 | auto response = Get(kTestUri); 157 | EXPECT_THAT(response.first, Eq(kTestResponse)); 158 | EXPECT_THAT(response.second, StrEq("text/xml")); 159 | } 160 | 161 | TEST_F(WebServerTest, HtmlWithParemetersTest) { 162 | constexpr absl::string_view kTestRoot("/test"); 163 | constexpr absl::string_view kTestUri("/test?x1=s1&x2&=a3&xyz=abc"); 164 | constexpr absl::string_view kTestResponse(".4/:a3/x1:s1/x2:/xyz:abc"); 165 | 166 | WebServer::UriHandler handler = [](const WebServer::WebRequest &request) { 167 | // Make parameters ordered. 168 | std::map ordered_parms; 169 | for (const auto &p : request.parms) { 170 | ordered_parms.emplace(p.first, p.second); 171 | } 172 | WebServer::WebResponse response; 173 | response.contents = absl::StrCat(".", request.parms.size()); 174 | for (const auto &p : ordered_parms) { 175 | absl::StrAppend(&response.contents, "/", p.first, ":", p.second); 176 | } 177 | return response; 178 | }; 179 | 180 | RegisterHandler(kTestRoot, handler); 181 | auto response = Get(kTestUri); 182 | EXPECT_THAT(response.first, Eq(kTestResponse)); 183 | EXPECT_THAT(response.second, StrEq("text/html")); 184 | } 185 | 186 | } // namespace 187 | } // namespace asylo 188 | -------------------------------------------------------------------------------- /remote/grpc_server/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | load("@linux_sgx//:sgx_sdk.bzl", "sgx") 18 | load( 19 | "@com_google_asylo//asylo/bazel:asylo.bzl", 20 | "enclave_loader", 21 | ) 22 | 23 | licenses(["notice"]) 24 | 25 | # Example demonstrating gRPC in Asylo for remote SGX backend. 26 | 27 | package( 28 | default_visibility = ["//visibility:public"], 29 | ) 30 | 31 | # The driver for the gRPC server enclave. 32 | enclave_loader( 33 | name = "grpc_server", 34 | srcs = ["grpc_server_driver.cc"], 35 | backends = sgx.backend_labels, # Has SGX loader dependencies 36 | enclaves = {"enclave": "//grpc_server:grpc_server_enclave.so"}, 37 | loader_args = ["--enclave_path='{enclave}'"], 38 | remote_proxy = "@com_google_asylo//asylo/util/remote:sgx_remote_proxy", 39 | deps = [ 40 | "//grpc_server:grpc_server_config_cc_proto", 41 | "@com_google_absl//absl/flags:flag", 42 | "@com_google_absl//absl/flags:parse", 43 | "@com_google_asylo//asylo:enclave_client", 44 | "@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto", 45 | "@com_google_asylo//asylo/util:logging", 46 | "@com_google_asylo//asylo/util:status", 47 | "@com_google_asylo//asylo/util/remote:local_provision", 48 | "@com_google_asylo//asylo/util/remote:provision", 49 | "@com_google_asylo//asylo/util/remote:remote_loader_cc_proto", 50 | "@com_google_asylo//asylo/util/remote:remote_proxy_config", 51 | ], 52 | ) 53 | -------------------------------------------------------------------------------- /remote/grpc_server/grpc_server_driver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/flags/flag.h" 23 | #include "absl/flags/parse.h" 24 | #include "asylo/client.h" 25 | #include "asylo/platform/primitives/sgx/loader.pb.h" 26 | #include "asylo/util/logging.h" 27 | #include "asylo/util/remote/provision.h" 28 | #include "asylo/util/remote/remote_loader.pb.h" 29 | #include "asylo/util/remote/remote_proxy_config.h" 30 | #include "asylo/util/status.h" 31 | #include "grpc_server/grpc_server_config.pb.h" 32 | 33 | ABSL_FLAG(std::string, enclave_path, "", "Path to enclave to load"); 34 | 35 | // By default, let the server run for five minutes. 36 | ABSL_FLAG(int32_t, server_max_lifetime, 300, 37 | "The longest amount of time (in seconds) that the server should be " 38 | "allowed to run"); 39 | 40 | // Default value 0 is used to indicate that the system should choose an 41 | // available port. 42 | ABSL_FLAG(int32_t, port, 0, "Port that the server listens to"); 43 | 44 | using ::asylo::RemoteProvision; 45 | using ::asylo::RemoteProxyClientConfig; 46 | using ::asylo::Status; 47 | 48 | constexpr char kServerAddress[] = "[::1]"; 49 | 50 | int main(int argc, char *argv[]) { 51 | // Parse command-line arguments. 52 | absl::ParseCommandLine(argc, argv); 53 | constexpr char kEnclaveName[] = "grpc_server_enclave"; 54 | 55 | const std::string enclave_path = absl::GetFlag(FLAGS_enclave_path); 56 | LOG_IF(QFATAL, enclave_path.empty()) << "Empty --enclave_path flag."; 57 | 58 | // Configure and retrieve the EnclaveManager. 59 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions()); 60 | auto manager_result = asylo::EnclaveManager::Instance(); 61 | LOG_IF(QFATAL, !manager_result.ok()) 62 | << "Failed to retrieve EnclaveManager instance: " 63 | << manager_result.status(); 64 | 65 | // Build an EnclaveConfig object with the address that the gRPC server will 66 | // run on. 67 | asylo::EnclaveConfig config; 68 | config.SetExtension(examples::grpc_server::server_address, kServerAddress); 69 | config.SetExtension(examples::grpc_server::port, absl::GetFlag(FLAGS_port)); 70 | 71 | // Prepare |load_config| message. 72 | asylo::EnclaveLoadConfig load_config; 73 | load_config.set_name(kEnclaveName); 74 | load_config.set_allocated_config(&config); 75 | 76 | // Prepare |remote_config| message. 77 | auto proxy_config_result = RemoteProxyClientConfig::DefaultsWithProvision( 78 | RemoteProvision::Instantiate()); 79 | LOG_IF(QFATAL, !proxy_config_result.ok()) 80 | << "Could not build RemoteProxyClientConfig"; 81 | 82 | auto remote_config = load_config.MutableExtension(asylo::remote_load_config); 83 | remote_config->set_remote_proxy_config( 84 | reinterpret_cast(proxy_config_result.value().release())); 85 | 86 | // Prepare |sgx_config| message. 87 | auto sgx_config = remote_config->mutable_sgx_load_config(); 88 | sgx_config->set_debug(true); 89 | auto file_enclave_config = sgx_config->mutable_file_enclave_config(); 90 | file_enclave_config->set_enclave_path(enclave_path); 91 | 92 | // Load Enclave with prepared |EnclaveManager| and |load_config| message. 93 | asylo::EnclaveManager *manager = manager_result.value(); 94 | auto status = manager->LoadEnclave(load_config); 95 | LOG_IF(QFATAL, !status.ok()) 96 | << "Load " << absl::GetFlag(FLAGS_enclave_path) << " failed: " << status; 97 | 98 | // Wait up to FLAGS_server_max_lifetime seconds or for the server to receive 99 | // the shutdown RPC, whichever happens first. 100 | asylo::EnclaveClient *client = manager->GetClient(kEnclaveName); 101 | asylo::EnclaveInput input; 102 | status = client->EnterAndRun(input, nullptr); 103 | LOG_IF(QFATAL, !status.ok()) 104 | << "Running " << absl::GetFlag(FLAGS_enclave_path) 105 | << " failed: " << status; 106 | 107 | // Destroy the enclave. 108 | asylo::EnclaveFinal final_input; 109 | status = manager->DestroyEnclave(client, final_input); 110 | LOG_IF(QFATAL, !status.ok()) 111 | << "Destroy " << absl::GetFlag(FLAGS_enclave_path) 112 | << " failed: " << status; 113 | 114 | return 0; 115 | } 116 | -------------------------------------------------------------------------------- /remote/provision_server/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | licenses(["notice"]) # Apache v2.0 17 | 18 | genrule( 19 | name = "decoded_certs", 20 | testonly = True, 21 | srcs = [ 22 | ":base64_server_cert", 23 | ":base64_server_key", 24 | ], 25 | outs = [ 26 | "server.crt", 27 | "server.key", 28 | ], 29 | cmd = """ 30 | base64 -d $(location base64_server_cert) > $(location server.crt) 31 | base64 -d $(location base64_server_key) > $(location server.key) 32 | """, 33 | ) 34 | 35 | filegroup( 36 | name = "certs", 37 | srcs = [ 38 | "server.crt", 39 | "server.key", 40 | ], 41 | visibility = ["//visibility:public"], 42 | ) 43 | -------------------------------------------------------------------------------- /remote/provision_server/README.md: -------------------------------------------------------------------------------- 1 | # RemoteProxyProvisionServer Launching Guide 2 | 3 | ## Introduction 4 | 5 | This launching guide assumes that it is being used to setup a 6 | `RemoteProxyProvisionServer` for other examples: 7 | 8 | * [Remote quickstart](https://asylo.dev/docs/guides/remote_quickstart.html) 9 | 10 | * [Bouncing circles](https://asylo.dev/docs/guides/bouncing_circles.html) 11 | 12 | For more details please refer to: 13 | 14 | * [Asylo Remote Backend](https://asylo.dev/docs/concepts/remote-backend.html) 15 | 16 | ## Building and launching RemoteProxyProvisionServer 17 | 18 | First, if you haven't already done so, download the Asylo SDK and Examples 19 | repos: 20 | 21 | ```bash 22 | export ASYLO_SDK=~/asylo-sdk 23 | git clone https://github.com/google/asylo.git "${ASYLO_SDK}" 24 | export MY_PROJECT=~/asylo-examples 25 | mkdir -p "${MY_PROJECT}" 26 | wget -q -O - https://github.com/google/asylo-examples/archive/master.tar.gz | \ 27 | tar -zxv --strip 1 --directory "${MY_PROJECT}" 28 | ``` 29 | 30 | Finally, launch the `RemoteProxyProvisionServer` in the Asylo docker container: 31 | 32 | ```bash 33 | docker run -it --net=host \ 34 | -v ${ASYLO_SDK}:/opt/asylo/sdk \ 35 | -v ${MY_PROJECT}:/opt/asylo/examples \ 36 | -w /opt/asylo/examples/remote/provision_server \ 37 | gcr.io/asylo-framework/asylo:latest \ 38 | ./build.sh 39 | ``` 40 | 41 | After that, applications can be run and rely on this server to deploy enclaves 42 | remotely. The default listening port is `4321`. 43 | -------------------------------------------------------------------------------- /remote/provision_server/base64_server_cert: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRakNDQWlvQ0NRQ3cwTk9ISmtMTlFqQU5C 2 | Z2txaGtpRzl3MEJBUXNGQURCak1Rc3dDUVlEVlFRR0V3SlQKVURFTk1Bc0dBMVVFQ0F3RVZHVnpk 3 | REVOTUFzR0ExVUVCd3dFVkdWemRERU5NQXNHQTFVRUNnd0VWR1Z6ZERFTgpNQXNHQTFVRUN3d0VW 4 | R1Z6ZERFWU1CWUdBMVVFQXd3UFkyOXRiVzl1WDNOemJGOXVZVzFsTUI0WERURTVNVEF3Ck56RTFN 5 | akF6TWxvWERUSXdNVEF3TmpFMU1qQXpNbG93WXpFTE1Ba0dBMVVFQmhNQ1UxQXhEVEFMQmdOVkJB 6 | Z00KQkZSbGMzUXhEVEFMQmdOVkJBY01CRlJsYzNReERUQUxCZ05WQkFvTUJGUmxjM1F4RFRBTEJn 7 | TlZCQXNNQkZSbApjM1F4R0RBV0JnTlZCQU1NRDJOdmJXMXZibDl6YzJ4ZmJtRnRaVENDQVNJd0RR 8 | WUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBTHNUMVdrOVZOZldqc3FUQk01NWRY 9 | SmFwNWhCd0E1WDFVQnZpcDVlQkwvQ1huREQKTmc1TjJybnVrQXFzZ1ZVMDdUVStsZUFURkU5MHJ2 10 | UDBuYUdVK252UTQ3TXZSRVhGL01VUlZnRDhwN1lPKzQwTgpyODVuTWRaRitvQjdYdm5tMzhmNFB0 11 | RldyaFJZU2FqZFcrUGkrbW1rTDAwQXZSWVJtUGM5NjU5VHN3cEkraGZUCkcyd1B5dDZJNWZiZFZZ 12 | MzJhMEttUGIwR0ZQMmg1eFdqaWcxSDN3dGdiSTFCWTF3N2RDbE05bTBvcmozZVRwOEkKQ0ZTSmhN 13 | SGkrUzZUUlZmWFFScTU1RzdnTmhEeHJZYy9aMVdTVHYxQy9zLzFhUW5wdERHMDIzNThrUmgrTUFz 14 | YwpXZmVuaFRSWUR1Ulp1V3BFdFVMQnduemtkUzR3M21PSjJESlVDNzBDQXdFQUFUQU5CZ2txaGtp 15 | Rzl3MEJBUXNGCkFBT0NBUUVBVWRvbnJwQkJaeW5uM3ErMjQxSjRNODBEVForcnRGSHBnWER3VXV4 16 | aUZNd1dVZVAzN0FleVluSWwKaEtWdXRWRDdoTlVFejBzOUtoN1ZwWEtuSXVwMURTL1hVYmh5cWVW 17 | cGhKZHZkdXJab084RTFRSzBqTDNxb2RzVQpRSlpxS0JTVVJLT2E1bzc0YnhFS3AzU1FFd0pjWVlS 18 | bmhvQUoyamE1ZHJHRU1RK2cvY1YxbSsrRmh6cTVkenhmCklWMzY2RDBKdUl2L0h0dlI1NytpY3pp 19 | azVLVzByYlhnUUxOdWhrN2cxYit3dzdRa2xJRDdWTGhTYktVamFCSk4KSGtHenJpdXpkR2NRSTAv 20 | VVArN29mZ3VLc1ZvbnFQQkk1NVo3RzZwcUlPd1hpc0FSbTJQaTBhcEN1bWVwOTRtYQppbVJsWUdS 21 | dnFCaGw3SFJQVkN5RU00Z2lwcXV1V0E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 22 | -------------------------------------------------------------------------------- /remote/provision_server/base64_server_key: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZB 2 | QVNDQktjd2dnU2pBZ0VBQW9JQkFRQzdFOVZwUFZUWDFvN0sKa3dUT2VYVnlXcWVZUWNBT1Y5VkFi 3 | NHFlWGdTL3dsNXd3ellPVGRxNTdwQUtySUZWTk8wMVBwWGdFeFJQZEs3ego5SjJobFBwNzBPT3pM 4 | MFJGeGZ6RkVWWUEvS2UyRHZ1TkRhL09aekhXUmZxQWUxNzU1dC9IK0Q3UlZxNFVXRW1vCjNWdmo0 5 | dnBwcEM5TkFMMFdFWmozUGV1ZlU3TUtTUG9YMHh0c0Q4cmVpT1gyM1ZXTjltdENwajI5QmhUOW9l 6 | Y1YKbzRvTlI5OExZR3lOUVdOY08zUXBUUFp0S0s0OTNrNmZDQWhVaVlUQjR2a3VrMFZYMTBFYXVl 7 | UnU0RFlROGEySApQMmRWa2s3OVF2N1A5V2tKNmJReHROdCtmSkVZZmpBTEhGbjNwNFUwV0E3a1di 8 | bHFSTFZDd2NKODVIVXVNTjVqCmlkZ3lWQXU5QWdNQkFBRUNnZ0VBY29EOFFiTGhhRTZTRFptWStv 9 | dkxBQmhPdGxtZ0pPZEx4bW0vTFptY1RJYTYKYVVpQ29KUzBpTk5rNUxPYllieklaNnVMN3ArZThk 10 | Y1ljb2RKcUNuWWVzcHJaRFJORkd2UGdBdFJXYjlMSTVyZQpDd0xTbFlJQ05nV1ZBdWtBUS9NMUMx 11 | OTlpNElEZ0w1ZEwzZDFrL0ZNbGphQklSK1BuSjlld2czclZ4VFM1RHFqCno5aWR0SkNIcUhhQmRl 12 | UVUwZXVvSThZSm5IcjBCeXZMcmF1cnU2bnJNR05OVFJDdEpKQnIrbkdsbnRRK28yRVIKWXVHNlVs 13 | RW9zS2YxelZFRHhiUlhNRnQrYkxRaUttL3F5UnpmZUttUVhwRzMzckovSmgyeE4xVnFXTjBNVkdI 14 | KwprRGlJMDlDOEdIc0g2MFdrdUd0UDdNdzZNdmNtbHQweTFlZDVlM2wwSFFLQmdRRHR2L1dUY1NL 15 | dmhuc0hRN3oyCmVjV1Vzek4vN2w4ZDBCd2lJOHl3YlFCV1g3dE43eGlaMkplN1A2YUNoMU1HeU01 16 | L25yblFoMENocGFDeUt3ZWsKZ2toTmJWM2NMWkpPNko1ZlBIMEl6QmlIeGhPTkJ6YllpVE45TTFC 17 | S0c1SXo0Y3RhOEpzdkN4dUVqSTVhcFc1ZApQSmFsblJQQ01maGxCNnVENUZxV3NjWkVhd0tCZ1FE 18 | SmNCdVVYYzZVbHJSM0l3NXUrNVF2bGdvbXQ1Y3QvNGRmClJVRjZQVEJVZUd1UUJlbENlNklJdFJQ 19 | eW9tSm56L0ZoZittTnlURFlvZU1IcWlYZm9OTE9QN1RkUWl6UjFPczkKYitLbTVoV1Jlb0IxOWpI 20 | SGQzOUtHZWJJQTZmWm1IU2RiUVExVi9JTFlkUHpjMjA0Y0dKUzlxallNeXd0NEtwTApWU1VDcFg0 21 | NmR3S0JnUURDdHRZL25RYlZUb1J3SExBa0JQTW1wK1Zqdnl3elZIL1dEZy9UNWxIQ2E4RVJRT0ti 22 | CkRXS25QcWYyZXpJcWVrZDFDZUFRd3RUU0RyNGZiVkpqRHpoOEFUZy8zU3JZYVhkYmRFVEs4YXlk 23 | ZGtJSTNJRzAKc2hselRwVlJQR2R2Q2x2cjdPYUxqc05JdVh6VkRHdm8vSGc4eHZxcHJ4ZEtWdy9I 24 | Z3p3Vjh4NzRaUUtCZ0RSeQpHc3dqTEZEbGQvRDQwSjQycEJ0TG5qTDhZOEVYSVlDOWdGRzZNcVli 25 | Z0MzTVRESUNER3JsOGw2ZXhxNHVwckx5CjRiVUhwODhQUHhQVXllMlNhckJHUittL2Uvblp6TEYv 26 | T3V5blJRQk9lN202c3JVek9KSHJjbm1xOGYybVF0NWwKN3MyUXF6VXBjRXlYUmQyRzdTS2FrOVZP 27 | WlhkQVlqWWc0ZlR4YjQ3N0FvR0FNUVRnSy9Nb0Nsd1Z6MHlZc0JhbgpmL1pNeUhRanlNQVVmcWJn 28 | MytuUUVidm1LL1FYRUkwd2toMDdQemlaWG0zVmd0ZklDQzFOZlVpN29ySTZWa3lnCkFtNi9Uc0NE 29 | YXgvUVN6bmJnMGZSaFNHRlR4K2JXbEhmdnhiUXlSVmxaSG94WW9YVUEvUGR6YXlMOEtqUXBSemYK 30 | cW1ydTMzZ21Rc0NCYW9NN2Uwc0NGUlU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K 31 | -------------------------------------------------------------------------------- /remote/provision_server/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Script for building the Provision Server Container 5 | # 6 | # Instructions for use: 7 | # Set environment variables ASYLO_SDK and MY_PROJECT. 8 | # -- ASYLO_SDK: Path to the Asylo sdk. 9 | # -- MY_PROJECT: Path to the Examples repo. 10 | # docker run -it --net=host \ 11 | # -v ${ASYLO_SDK}:/opt/asylo/sdk \ 12 | # -v ${MY_PROJECT}:/opt/asylo/examples \ 13 | # -w /opt/asylo/examples/remote/provision_server \ 14 | # gcr.io/asylo-framework/asylo:latest \ 15 | # ./build.sh 16 | # Build the provision server and remote proxy. 17 | TMP_BUILD_FOLDER=/tmp/asylo/build 18 | mkdir -p ${TMP_BUILD_FOLDER} 19 | 20 | pushd /opt/asylo/sdk 21 | bazel build //asylo/util/remote:remote_provision_host_server 22 | bazel build //asylo/util/remote:sgx_remote_proxy 23 | bazel build //asylo/util/remote:remote_provision_host_server_host_loader 24 | BAZEL_BIN_PATH=$(bazel info bazel-bin) 25 | cp -r ${BAZEL_BIN_PATH}/asylo/util/remote/* ${TMP_BUILD_FOLDER} 26 | popd 27 | 28 | # Decode the certs. 29 | bazel build //remote/provision_server:certs 30 | 31 | BAZEL_GEN_PATH=$(bazel info bazel-genfiles) 32 | cp -r ${BAZEL_GEN_PATH}/remote/provision_server/* ${TMP_BUILD_FOLDER} 33 | 34 | ${TMP_BUILD_FOLDER}/remote_provision_host_server_host_loader \ 35 | --security_type=ssl \ 36 | --ssl_key=${TMP_BUILD_FOLDER}/server.key \ 37 | --ssl_cert=${TMP_BUILD_FOLDER}/server.crt \ 38 | --port=4321 \ 39 | --remote_proxy=${TMP_BUILD_FOLDER}/sgx_remote_proxy 40 | -------------------------------------------------------------------------------- /remote/quickstart/BUILD: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2019 Asylo authors 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | load("@linux_sgx//:sgx_sdk.bzl", "sgx") 18 | load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_proto_library") 19 | load("@rules_proto//proto:defs.bzl", "proto_library") 20 | load( 21 | "@com_google_asylo//asylo/bazel:asylo.bzl", 22 | "cc_unsigned_enclave", 23 | "debug_sign_enclave", 24 | "enclave_loader", 25 | "enclave_test", 26 | ) 27 | load("@com_google_asylo//asylo/bazel:copts.bzl", "ASYLO_DEFAULT_COPTS") 28 | 29 | licenses(["notice"]) # Apache v2.0 30 | 31 | # Example and exercise for using Asylo toolkits. 32 | proto_library( 33 | name = "demo_proto", 34 | srcs = ["demo.proto"], 35 | deps = ["@com_google_asylo//asylo:enclave_proto"], 36 | ) 37 | 38 | cc_proto_library( 39 | name = "demo_cc_proto", 40 | deps = [":demo_proto"], 41 | ) 42 | 43 | cc_unsigned_enclave( 44 | name = "demo_enclave_unsigned.so", 45 | srcs = ["demo_enclave.cc"], 46 | deps = [ 47 | ":demo_cc_proto", 48 | "@com_google_absl//absl/base:core_headers", 49 | "@com_google_absl//absl/strings", 50 | "@com_google_asylo//asylo:enclave_runtime", 51 | "@com_google_asylo//asylo/crypto:aead_cryptor", 52 | "@com_google_asylo//asylo/util:cleansing_types", 53 | "@com_google_asylo//asylo/util:status", 54 | ], 55 | ) 56 | 57 | debug_sign_enclave( 58 | name = "demo_enclave_debug.so", 59 | unsigned = ":demo_enclave_unsigned.so", 60 | ) 61 | 62 | enclave_loader( 63 | name = "quickstart", 64 | srcs = ["demo_driver.cc"], 65 | backends = sgx.backend_labels, 66 | enclaves = {"enclave": ":demo_enclave_debug.so"}, 67 | loader_args = [ 68 | "--enclave_path='{enclave}'", 69 | "--message='FooBar'", 70 | ], 71 | remote_proxy = "@com_google_asylo//asylo/util/remote:sgx_remote_proxy", 72 | deps = [ 73 | ":demo_cc_proto", 74 | "@com_google_absl//absl/flags:flag", 75 | "@com_google_absl//absl/flags:parse", 76 | "@com_google_asylo//asylo:enclave_client", 77 | "@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto", 78 | "@com_google_asylo//asylo/util:logging", 79 | "@com_google_asylo//asylo/util:status", 80 | "@com_google_asylo//asylo/util/remote:local_provision", 81 | "@com_google_asylo//asylo/util/remote:provision", 82 | "@com_google_asylo//asylo/util/remote:remote_loader_cc_proto", 83 | "@com_google_asylo//asylo/util/remote:remote_proxy_config", 84 | ], 85 | ) 86 | 87 | cc_binary( 88 | name = "quickstart_remote", 89 | testonly = True, 90 | srcs = ["demo_driver.cc"], 91 | data = [ 92 | "//remote/provision_server:certs", 93 | ], 94 | deps = [ 95 | ":demo_cc_proto", 96 | "@com_google_absl//absl/flags:flag", 97 | "@com_google_absl//absl/flags:parse", 98 | "@com_google_asylo//asylo:enclave_client", 99 | "@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto", 100 | "@com_google_asylo//asylo/util:logging", 101 | "@com_google_asylo//asylo/util:status", 102 | "@com_google_asylo//asylo/util/remote:provision", 103 | "@com_google_asylo//asylo/util/remote:remote_loader_cc_proto", 104 | "@com_google_asylo//asylo/util/remote:remote_provision_client", 105 | "@com_google_asylo//asylo/util/remote:remote_proxy_config", 106 | ], 107 | ) 108 | 109 | enclave_test( 110 | name = "demo_enclave_remote_test", 111 | size = "small", 112 | srcs = ["demo_enclave_remote_test.cc"], 113 | backends = sgx.backend_labels, 114 | enclaves = {"enclave": ":demo_enclave_debug.so"}, 115 | remote_proxy = "@com_google_asylo//asylo/util/remote:sgx_remote_proxy", 116 | tags = [ 117 | "asylo-remote", 118 | "noregression", 119 | ], 120 | test_args = [ 121 | "--enclave_path='{enclave}'", 122 | ], 123 | deps = [ 124 | ":demo_cc_proto", 125 | "@com_google_absl//absl/flags:flag", 126 | "@com_google_absl//absl/flags:parse", 127 | "@com_google_absl//absl/memory", 128 | "@com_google_asylo//asylo:enclave_client", 129 | "@com_google_asylo//asylo/platform/primitives/sgx:loader_cc_proto", 130 | "@com_google_asylo//asylo/test/util:status_matchers", 131 | "@com_google_asylo//asylo/test/util:test_main", 132 | "@com_google_asylo//asylo/util:status", 133 | "@com_google_asylo//asylo/util/remote:local_provision", 134 | "@com_google_asylo//asylo/util/remote:provision", 135 | "@com_google_asylo//asylo/util/remote:remote_loader_cc_proto", 136 | "@com_google_asylo//asylo/util/remote:remote_proxy_config", 137 | "@com_google_googletest//:gtest", 138 | ], 139 | ) 140 | -------------------------------------------------------------------------------- /remote/quickstart/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Script for building the remote quickstart example. 3 | # 4 | # Instructions for use: 5 | # Set environment variables ASYLO_SDK, MY_PROJECT, MESSAGE, and CONFIG_TYPE. 6 | # -- ASYLO_SDK: Path to the Asylo sdk. 7 | # -- MY_PROJECT: Path to the Examples repo. 8 | # -- MESSAGE: Message you'd like to be encrypted 9 | # -- CONFIG_TYPE: One of {sgx, sgx-sim} 10 | # Start the provision server with the directions given at asylo/examples/remote/provision_server. 11 | # ```bash 12 | # export ASYLO_SDK=/opt/asylo/sdk 13 | # export MY_PROJECT=/opt/asylo/examples 14 | # export MESSAGE="Asylo Rocks" 15 | # export CONFIG_TYPE=sgx-sim 16 | # docker run -it --net=host \ 17 | # -v ${ASYLO_SDK}:/opt/asylo/sdk \ 18 | # -v ${MY_PROJECT}:/opt/asylo/examples \ 19 | # -w /opt/asylo/examples/remote/quickstart \ 20 | # gcr.io/asylo-framework/asylo:latest \ 21 | # ./build.sh ${CONFIG_TYPE} "${MESSAGE}" 22 | # ``` 23 | 24 | # If any command fails exit. 25 | set -e 26 | 27 | # Export all variables as environment variables. 28 | set -a 29 | 30 | # Default configuration for CONFIG_TYPE. 31 | CONFIG_TYPE_DEFAULT=sgx 32 | 33 | # Command line argument: Allows selection of local backend, if one is not 34 | # selected it defaults to $CONFIG_DEFAULT 35 | CONFIG_TYPE=${1:-$CONFIG_TYPE_DEFAULT} 36 | 37 | # Set the ENCLAVE_TAG based on the CONFIG_TYPE. ENCLAVE_TAG is used as part of 38 | # the ENCLAVE_TARGET. 39 | if [ "$CONFIG_TYPE" == "sgx" ]; then 40 | ENCLAVE_TAG="sgx_hw"; 41 | elif [ "$CONFIG_TYPE" == "sgx-sim" ]; then 42 | ENCLAVE_TAG="sgx_sim"; 43 | fi 44 | 45 | if [ -z "$ENCLAVE_TAG" ]; then 46 | echo "CONFIG_TYPE must be one of sgx or sgx-sim"; 47 | exit; 48 | fi 49 | 50 | # Enclave to be used in the example. 51 | ENCLAVE_TARGET=demo_enclave_debug_${ENCLAVE_TAG}.so 52 | 53 | bazel build //remote/quickstart:${ENCLAVE_TARGET} 54 | 55 | # Path where bazel puts built objects. 56 | BAZEL_BIN_PATH=$(bazel info bazel-bin) 57 | QUICK_PATH=${BAZEL_BIN_PATH}/remote/quickstart 58 | 59 | # Path where bazel puts generated files - can be but not always the same as 60 | # bazel-bin. 61 | BAZEL_GEN_PATH=$(bazel info bazel-genfiles) 62 | PROVISION_PATH=${BAZEL_GEN_PATH}/remote/provision_server 63 | 64 | # Run the quickstart_remote example. 65 | bazel run --define=ASYLO_REMOTE=1 //remote/quickstart:quickstart_remote -- \ 66 | --message="$2" \ 67 | --security_type=ssl \ 68 | --ssl_key=${PROVISION_PATH}/server.key \ 69 | --ssl_cert=${PROVISION_PATH}/server.crt \ 70 | --enclave_path=${QUICK_PATH}/${ENCLAVE_TARGET} \ 71 | --remote_provision_server=[::1]:4321 \ 72 | --local_client_name=[::1] 73 | -------------------------------------------------------------------------------- /remote/quickstart/demo.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package guide.asylo; 20 | 21 | import "asylo/enclave.proto"; 22 | 23 | // A custom message to pass in and out of our enclave. 24 | message Demo { 25 | // This string value is used for both user input and enclave output. 26 | optional string value = 1; 27 | } 28 | 29 | // The EnclaveInput message that is passed to the enclave can be extended with 30 | // a Demo message to communicate a value our enclave knows to expect. 31 | extend .asylo.EnclaveInput { 32 | optional Demo quickstart_input = 9001; 33 | } 34 | 35 | // The EnclaveOutput message that is passed out of the enclave can be extended 36 | // with a Demo message to communicate a value our driver knows to expect. 37 | extend .asylo.EnclaveOutput { 38 | optional Demo quickstart_output = 9001; 39 | } 40 | -------------------------------------------------------------------------------- /remote/quickstart/demo_driver.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "absl/flags/flag.h" 27 | #include "absl/flags/parse.h" 28 | #include "asylo/client.h" 29 | #include "asylo/platform/primitives/sgx/loader.pb.h" 30 | #include "asylo/util/logging.h" 31 | #include "asylo/util/remote/provision.h" 32 | #include "asylo/util/remote/remote_loader.pb.h" 33 | #include "asylo/util/remote/remote_proxy_config.h" 34 | #include "asylo/util/status.h" 35 | #include "asylo/util/status_macros.h" 36 | #include "remote/quickstart/demo.pb.h" 37 | 38 | ABSL_FLAG(std::string, enclave_path, "", 39 | "Path to enclave binary image to load"); 40 | ABSL_FLAG(std::string, message, "", "Message to encrypt"); 41 | 42 | using ::asylo::RemoteProvision; 43 | using ::asylo::RemoteProxyClientConfig; 44 | using ::asylo::Status; 45 | 46 | // Populates |enclave_input|->value() with |user_message|. 47 | void SetEnclaveUserMessage(asylo::EnclaveInput *enclave_input, 48 | const std::string &user_message) { 49 | guide::asylo::Demo *user_input = 50 | enclave_input->MutableExtension(guide::asylo::quickstart_input); 51 | user_input->set_value(user_message); 52 | } 53 | 54 | // Retrieves encrypted message from |output|. Intended to be used by the reader 55 | // for completing the exercise. 56 | const std::string GetEnclaveOutputMessage(const asylo::EnclaveOutput &output) { 57 | return output.GetExtension(guide::asylo::quickstart_output).value(); 58 | } 59 | 60 | int main(int argc, char *argv[]) { 61 | absl::ParseCommandLine(argc, argv); 62 | 63 | constexpr char kEnclaveName[] = "demo_enclave"; 64 | 65 | const std::string message = absl::GetFlag(FLAGS_message); 66 | LOG_IF(QFATAL, message.empty()) << "Empty --message flag."; 67 | 68 | const std::string enclave_path = absl::GetFlag(FLAGS_enclave_path); 69 | LOG_IF(QFATAL, enclave_path.empty()) << "Empty --enclave_path flag."; 70 | 71 | // Part 1: Initialization 72 | 73 | // Prepare |EnclaveManager| with default |EnclaveManagerOptions| 74 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions()); 75 | auto manager_result = asylo::EnclaveManager::Instance(); 76 | LOG_IF(QFATAL, !manager_result.ok()) << "Could not obtain EnclaveManager"; 77 | 78 | // Prepare |load_config| message. 79 | asylo::EnclaveLoadConfig load_config; 80 | load_config.set_name(kEnclaveName); 81 | 82 | // Prepare |remote_config| message. 83 | auto proxy_config_result = RemoteProxyClientConfig::DefaultsWithProvision( 84 | RemoteProvision::Instantiate()); 85 | LOG_IF(QFATAL, !proxy_config_result.ok()) 86 | << "Could not build RemoteProxyClientConfig"; 87 | 88 | auto remote_config = load_config.MutableExtension(asylo::remote_load_config); 89 | remote_config->set_remote_proxy_config( 90 | reinterpret_cast(proxy_config_result.value().release())); 91 | 92 | // Prepare |sgx_config| message. 93 | auto sgx_config = remote_config->mutable_sgx_load_config(); 94 | sgx_config->set_debug(true); 95 | auto file_enclave_config = sgx_config->mutable_file_enclave_config(); 96 | file_enclave_config->set_enclave_path(enclave_path); 97 | 98 | // Load Enclave with prepared |EnclaveManager| and |load_config| message. 99 | asylo::EnclaveManager *manager = manager_result.value(); 100 | auto status = manager->LoadEnclave(load_config); 101 | LOG_IF(QFATAL, !status.ok()) << "LoadEnclave failed with: " << status; 102 | 103 | // Part 2: Secure execution 104 | 105 | // Prepare |input| with |message| and create |output| to retrieve response 106 | // from enclave. 107 | asylo::EnclaveInput input; 108 | SetEnclaveUserMessage(&input, message); 109 | asylo::EnclaveOutput output; 110 | 111 | // Get |EnclaveClient| for loaded enclave and execute |EnterAndRun|. 112 | asylo::EnclaveClient *const client = manager->GetClient(kEnclaveName); 113 | status = client->EnterAndRun(input, &output); 114 | LOG_IF(QFATAL, !status.ok()) << "EnterAndRun failed with: " << status; 115 | 116 | // Print the encyrpted message locally. 117 | std::cout << "Encrypted message:" << std::endl 118 | << output.GetExtension(guide::asylo::quickstart_output).value() 119 | << std::endl; 120 | 121 | // Part 3: Finalization 122 | 123 | // |DestroyEnclave| before exiting program. 124 | asylo::EnclaveFinal empty_final_input; 125 | status = manager->DestroyEnclave(client, empty_final_input, false); 126 | LOG_IF(QFATAL, !status.ok()) << "DestroyEnclave failed with: " << status; 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /remote/quickstart/demo_enclave.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | 21 | #include "absl/base/macros.h" 22 | #include "absl/status/status.h" 23 | #include "absl/strings/escaping.h" 24 | #include "absl/strings/str_cat.h" 25 | #include "asylo/crypto/aead_cryptor.h" 26 | #include "asylo/trusted_application.h" 27 | #include "asylo/util/cleansing_types.h" 28 | #include "asylo/util/status_macros.h" 29 | #include "asylo/util/statusor.h" 30 | #include "remote/quickstart/demo.pb.h" 31 | 32 | namespace asylo { 33 | namespace { 34 | 35 | // Set to accept absurdly large user input. 36 | constexpr size_t kMaxMessageSize = 1 << 16; 37 | 38 | // Example 128-bit AES key. 39 | constexpr uint8_t kAesKey128[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 40 | 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 41 | 0x12, 0x13, 0x14, 0x15}; 42 | 43 | // Helper function that adapts absl::BytesToHexString, allowing it to be used 44 | // with ByteContainerView. 45 | std::string BytesToHexString(ByteContainerView bytes) { 46 | return absl::BytesToHexString(absl::string_view( 47 | reinterpret_cast(bytes.data()), bytes.size())); 48 | } 49 | 50 | // Encrypts a message against `kAesKey128` and returns a 12-byte nonce followed 51 | // by authenticated ciphertext, encoded as a hex string. 52 | const StatusOr EncryptMessage(const std::string &message) { 53 | std::unique_ptr cryptor; 54 | ASYLO_ASSIGN_OR_RETURN(cryptor, 55 | AeadCryptor::CreateAesGcmSivCryptor(kAesKey128)); 56 | 57 | std::vector additional_authenticated_data; 58 | std::vector nonce(cryptor->NonceSize()); 59 | std::vector ciphertext(message.size() + cryptor->MaxSealOverhead()); 60 | size_t ciphertext_size; 61 | 62 | ASYLO_RETURN_IF_ERROR(cryptor->Seal( 63 | message, additional_authenticated_data, absl::MakeSpan(nonce), 64 | absl::MakeSpan(ciphertext), &ciphertext_size)); 65 | 66 | return absl::StrCat(BytesToHexString(nonce), BytesToHexString(ciphertext)); 67 | } 68 | 69 | // Decrypts a message using `kAesKey128`. Expects `nonce_and_ciphertext` to be 70 | // encoded as a hex string, and lead with a 12-byte nonce. Intended to be 71 | // used by the reader for completing the exercise. 72 | const StatusOr DecryptMessage( 73 | const std::string &nonce_and_ciphertext) { 74 | std::string input_bytes = absl::HexStringToBytes(nonce_and_ciphertext); 75 | 76 | std::unique_ptr cryptor; 77 | ASYLO_ASSIGN_OR_RETURN(cryptor, 78 | AeadCryptor::CreateAesGcmSivCryptor(kAesKey128)); 79 | 80 | if (input_bytes.size() < cryptor->NonceSize()) { 81 | return Status( 82 | absl::StatusCode::kInvalidArgument, 83 | absl::StrCat("Input too short: expected at least ", 84 | cryptor->NonceSize(), " bytes, got ", input_bytes.size())); 85 | } 86 | 87 | std::vector additional_authenticated_data; 88 | std::vector nonce = {input_bytes.begin(), 89 | input_bytes.begin() + cryptor->NonceSize()}; 90 | std::vector ciphertext = {input_bytes.begin() + cryptor->NonceSize(), 91 | input_bytes.end()}; 92 | 93 | // The plaintext is always smaller than the ciphertext, so use 94 | // `ciphertext.size()` as an upper bound on the plaintext buffer size. 95 | CleansingVector plaintext(ciphertext.size()); 96 | size_t plaintext_size; 97 | 98 | ASYLO_RETURN_IF_ERROR(cryptor->Open(ciphertext, additional_authenticated_data, 99 | nonce, absl::MakeSpan(plaintext), 100 | &plaintext_size)); 101 | 102 | return CleansingString(plaintext.begin(), plaintext.end()); 103 | } 104 | 105 | } // namespace 106 | 107 | class EnclaveDemo : public TrustedApplication { 108 | public: 109 | EnclaveDemo() = default; 110 | 111 | Status Run(const EnclaveInput &input, EnclaveOutput *output) override { 112 | std::string user_message = GetEnclaveUserMessage(input); 113 | 114 | std::string result; 115 | ASYLO_ASSIGN_OR_RETURN(result, EncryptMessage(user_message)); 116 | 117 | SetEnclaveOutputMessage(output, result); 118 | 119 | return absl::OkStatus(); 120 | } 121 | 122 | // Retrieves user message from |input|. 123 | const std::string GetEnclaveUserMessage(const EnclaveInput &input) { 124 | return input.GetExtension(guide::asylo::quickstart_input).value(); 125 | } 126 | 127 | // Populates |enclave_output|->value() with |output_message|. Intended to be 128 | // used by the reader for completing the exercise. 129 | void SetEnclaveOutputMessage(EnclaveOutput *enclave_output, 130 | const std::string &output_message) { 131 | guide::asylo::Demo *output = 132 | enclave_output->MutableExtension(guide::asylo::quickstart_output); 133 | output->set_value(output_message); 134 | } 135 | }; 136 | 137 | TrustedApplication *BuildTrustedApplication() { return new EnclaveDemo; } 138 | 139 | } // namespace asylo 140 | -------------------------------------------------------------------------------- /remote/quickstart/demo_enclave_remote_test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include "absl/flags/flag.h" 25 | #include "absl/memory/memory.h" 26 | #include "asylo/client.h" 27 | #include "asylo/platform/primitives/sgx/loader.pb.h" 28 | #include "asylo/test/util/status_matchers.h" 29 | #include "asylo/util/remote/provision.h" 30 | #include "asylo/util/remote/remote_loader.pb.h" 31 | #include "asylo/util/remote/remote_proxy_config.h" 32 | #include "asylo/util/status.h" 33 | #include "remote/quickstart/demo.pb.h" 34 | 35 | ABSL_FLAG(std::string, enclave_path, "", 36 | "Path to enclave binary image to load"); 37 | 38 | using ::testing::IsEmpty; 39 | using ::testing::IsTrue; 40 | using ::testing::Not; 41 | using ::testing::NotNull; 42 | using ::testing::StrNe; 43 | 44 | namespace asylo { 45 | namespace { 46 | 47 | constexpr char kEnclaveName[] = "DemoEnclave"; 48 | 49 | class DemoEnclaveRemoteTest : public ::testing::Test { 50 | public: 51 | void SetUp() override { 52 | const std::string enclave_path = absl::GetFlag(FLAGS_enclave_path); 53 | ASSERT_THAT(enclave_path, Not(IsEmpty())); 54 | 55 | EnclaveManager::Configure(EnclaveManagerOptions()); 56 | ASYLO_ASSERT_OK_AND_ASSIGN(enclave_manager_, EnclaveManager::Instance()); 57 | ASSERT_THAT(enclave_manager_, NotNull()); 58 | 59 | std::unique_ptr proxy_config; 60 | ASYLO_ASSERT_OK_AND_ASSIGN(proxy_config, 61 | RemoteProxyClientConfig::DefaultsWithProvision( 62 | RemoteProvision::Instantiate())); 63 | 64 | EnclaveLoadConfig load_config; 65 | load_config.set_name(kEnclaveName); 66 | 67 | auto remote_config = load_config.MutableExtension(remote_load_config); 68 | remote_config->set_remote_proxy_config( 69 | reinterpret_cast(proxy_config.release())); 70 | 71 | auto sgx_config = remote_config->mutable_sgx_load_config(); 72 | sgx_config->set_debug(true); 73 | auto file_enclave_config = sgx_config->mutable_file_enclave_config(); 74 | file_enclave_config->set_enclave_path(enclave_path); 75 | 76 | ASYLO_ASSERT_OK(enclave_manager_->LoadEnclave(load_config)); 77 | enclave_client_ = enclave_manager_->GetClient(kEnclaveName); 78 | ASSERT_THAT(enclave_client_, NotNull()); 79 | } 80 | 81 | void TearDown() override { 82 | EnclaveFinal empty_final_input; 83 | ASYLO_ASSERT_OK(enclave_manager_->DestroyEnclave(enclave_client_, 84 | empty_final_input, false)); 85 | } 86 | 87 | protected: 88 | EnclaveManager *enclave_manager_; 89 | EnclaveClient *enclave_client_; 90 | }; 91 | 92 | TEST_F(DemoEnclaveRemoteTest, EnclaveEncryptsMessage) { 93 | constexpr char kMessage[] = "FooBar"; 94 | EnclaveInput input; 95 | auto user_input = input.MutableExtension(guide::asylo::quickstart_input); 96 | user_input->set_value(kMessage); 97 | EnclaveOutput output; 98 | 99 | ASYLO_ASSERT_OK(enclave_client_->EnterAndRun(input, &output)); 100 | ASSERT_THAT(output.HasExtension(guide::asylo::quickstart_output), IsTrue()); 101 | const std::string encrypted_message = 102 | output.GetExtension(guide::asylo::quickstart_output).value(); 103 | EXPECT_THAT(encrypted_message, Not(IsEmpty())); 104 | EXPECT_THAT(encrypted_message, StrNe(kMessage)); 105 | } 106 | 107 | } // namespace 108 | } // namespace asylo 109 | -------------------------------------------------------------------------------- /secure_grpc/acl_isvprodid_2.textproto: -------------------------------------------------------------------------------- 1 | # Message type: asylo.SgxIdentityExpectation 2 | reference_identity: { 3 | code_identity: { 4 | signer_assigned_identity: { 5 | mrsigner: { 6 | # This value corresponds to the Asylo debug signing key. 7 | hash: "\x83\xd7\x19\xe7\x7d\xea\xca\x14\x70\xf6\xba\xf6\x2a\x4d\x77\x43\x03\xc8\x99\xdb\x69\x02\x0f\x9c\x70\xee\x1d\xfc\x08\xc7\xce\x9e" 8 | } 9 | isvprodid: 2 10 | isvsvn: 1 11 | } 12 | miscselect: 0 13 | attributes: { 14 | flags: 0x0 15 | xfrm: 0x0 16 | } 17 | } 18 | } 19 | match_spec: { 20 | machine_configuration_match_spec: { 21 | is_cpu_svn_match_required: false 22 | is_sgx_type_match_required: false 23 | } 24 | code_identity_match_spec: { 25 | is_mrenclave_match_required: false 26 | is_mrsigner_match_required: true 27 | miscselect_match_mask: 0x0 28 | attributes_match_mask: { 29 | flags: 0x0 30 | xfrm: 0x0 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /secure_grpc/acl_isvprodid_3.textproto: -------------------------------------------------------------------------------- 1 | # Message type: asylo.SgxIdentityExpectation 2 | reference_identity: { 3 | code_identity: { 4 | signer_assigned_identity: { 5 | mrsigner: { 6 | # This value corresponds to the Asylo debug signing key. 7 | hash: "\x83\xd7\x19\xe7\x7d\xea\xca\x14\x70\xf6\xba\xf6\x2a\x4d\x77\x43\x03\xc8\x99\xdb\x69\x02\x0f\x9c\x70\xee\x1d\xfc\x08\xc7\xce\x9e" 8 | } 9 | isvprodid: 3 10 | isvsvn: 1 11 | } 12 | miscselect: 0 13 | attributes: { 14 | flags: 0x0 15 | xfrm: 0x0 16 | } 17 | } 18 | } 19 | match_spec: { 20 | machine_configuration_match_spec: { 21 | is_cpu_svn_match_required: false 22 | is_sgx_type_match_required: false 23 | } 24 | code_identity_match_spec: { 25 | is_mrenclave_match_required: false 26 | is_mrsigner_match_required: true 27 | miscselect_match_mask: 0x0 28 | attributes_match_mask: { 29 | flags: 0x0 30 | xfrm: 0x0 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /secure_grpc/acl_non_debug.textproto: -------------------------------------------------------------------------------- 1 | # Message type: asylo.SgxIdentityExpectation 2 | # 3 | # This configuration enforces that the caller is a non-debug enclave. 4 | # 5 | # DEBUG is bit 1 of ATTRIBUTES. We set the corresponding bit in attributes_match_mask.flags to indicate that it should match the value of attributes.flags[1]. 6 | reference_identity: { 7 | code_identity: { 8 | signer_assigned_identity: { 9 | mrsigner: { 10 | # This value corresponds to the Asylo debug signing key. 11 | hash: "\x83\xd7\x19\xe7\x7d\xea\xca\x14\x70\xf6\xba\xf6\x2a\x4d\x77\x43\x03\xc8\x99\xdb\x69\x02\x0f\x9c\x70\xee\x1d\xfc\x08\xc7\xce\x9e" 12 | } 13 | isvprodid: 2 14 | isvsvn: 1 15 | } 16 | miscselect: 0 17 | attributes: { 18 | flags: 0x0 19 | xfrm: 0x0 20 | } 21 | } 22 | } 23 | match_spec: { 24 | machine_configuration_match_spec: { 25 | is_cpu_svn_match_required: false 26 | is_sgx_type_match_required: false 27 | } 28 | code_identity_match_spec: { 29 | is_mrenclave_match_required: false 30 | is_mrsigner_match_required: true 31 | miscselect_match_mask: 0 32 | attributes_match_mask: { 33 | flags: 0x2 34 | xfrm: 0x0 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /secure_grpc/attestation_domain.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include "secure_grpc/attestation_domain.h" 20 | 21 | namespace examples { 22 | namespace secure_grpc { 23 | 24 | const char *const kAttestationDomain = "A 16-byte string"; 25 | 26 | } // namespace secure_grpc 27 | } // namespace examples 28 | -------------------------------------------------------------------------------- /secure_grpc/attestation_domain.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_SECURE_GRPC_ATTESTATION_DOMAIN_H_ 20 | #define ASYLO_EXAMPLES_SECURE_GRPC_ATTESTATION_DOMAIN_H_ 21 | 22 | namespace examples { 23 | namespace secure_grpc { 24 | 25 | // Typically, the attestation domain value should be extracted from the system 26 | // configuration (e.g., a file on the machine). For simplicity, it is hardcoded 27 | // to the same value in the client and the server. 28 | extern const char *const kAttestationDomain; 29 | 30 | } // namespace secure_grpc 31 | } // namespace examples 32 | 33 | #endif // ASYLO_EXAMPLES_SECURE_GRPC_ATTESTATION_DOMAIN_H_ 34 | -------------------------------------------------------------------------------- /secure_grpc/grpc_client_enclave.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include "secure_grpc/grpc_client_enclave.h" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "absl/status/status.h" 26 | #include "absl/time/time.h" 27 | #include "asylo/enclave.pb.h" 28 | #include "asylo/grpc/auth/enclave_channel_credentials.h" 29 | #include "asylo/grpc/auth/sgx_local_credentials_options.h" 30 | #include "asylo/trusted_application.h" 31 | #include "asylo/util/status.h" 32 | #include "asylo/util/status_macros.h" 33 | #include "asylo/util/statusor.h" 34 | #include "grpc_server/translator_server.grpc.pb.h" 35 | #include "include/grpc/impl/codegen/gpr_types.h" 36 | #include "include/grpc/support/time.h" 37 | #include "include/grpcpp/grpcpp.h" 38 | #include "secure_grpc/grpc_client_enclave.pb.h" 39 | 40 | namespace examples { 41 | namespace secure_grpc { 42 | namespace { 43 | 44 | using grpc_server::Translator; 45 | 46 | const absl::Duration kChannelDeadline = absl::Seconds(5); 47 | 48 | // Makes a GetTranslation RPC with |request| to the server backed by *|stub|. 49 | asylo::StatusOr GetTranslation( 50 | const grpc_server::GetTranslationRequest &request, Translator::Stub *stub) { 51 | grpc_server::GetTranslationResponse response; 52 | 53 | ::grpc::ClientContext context; 54 | ASYLO_RETURN_IF_ERROR( 55 | asylo::Status(stub->GetTranslation(&context, request, &response))); 56 | return response; 57 | } 58 | 59 | } // namespace 60 | 61 | asylo::Status GrpcClientEnclave::Run(const asylo::EnclaveInput &input, 62 | asylo::EnclaveOutput *output) { 63 | if (!input.HasExtension(client_enclave_input)) { 64 | return absl::InvalidArgumentError("Input missing client_input extension"); 65 | } 66 | const GrpcClientEnclaveInput &client_input = 67 | input.GetExtension(client_enclave_input); 68 | 69 | const std::string &address = client_input.server_address(); 70 | if (address.empty()) { 71 | return absl::InvalidArgumentError( 72 | "Input must provide a non-empty server address"); 73 | } 74 | if (client_input.translation_request().input_word().empty()) { 75 | return absl::InvalidArgumentError( 76 | "Input must provide a non-empty RPC input"); 77 | } 78 | 79 | // The ::grpc::ChannelCredentials object configures the channel authentication 80 | // mechanisms used by the client and server. This particular configuration 81 | // enforces that both the client and server authenticate using SGX local 82 | // attestation. 83 | std::shared_ptr<::grpc::ChannelCredentials> channel_credentials = 84 | EnclaveChannelCredentials( 85 | asylo::BidirectionalSgxLocalCredentialsOptions()); 86 | 87 | // Connect a gRPC channel to the server specified in the EnclaveInput. 88 | std::shared_ptr<::grpc::Channel> channel = 89 | ::grpc::CreateChannel(address, channel_credentials); 90 | 91 | gpr_timespec absolute_deadline = gpr_time_add( 92 | gpr_now(GPR_CLOCK_REALTIME), 93 | gpr_time_from_micros(absl::ToInt64Microseconds(kChannelDeadline), 94 | GPR_TIMESPAN)); 95 | if (!channel->WaitForConnected(absolute_deadline)) { 96 | return absl::InternalError("Failed to connect to server"); 97 | } 98 | 99 | GrpcClientEnclaveOutput *client_output = 100 | output->MutableExtension(client_enclave_output); 101 | 102 | std::unique_ptr stub = Translator::NewStub(channel); 103 | ASYLO_ASSIGN_OR_RETURN( 104 | *client_output->mutable_translation_response(), 105 | GetTranslation(client_input.translation_request(), stub.get())); 106 | 107 | return absl::OkStatus(); 108 | } 109 | 110 | } // namespace secure_grpc 111 | } // namespace examples 112 | 113 | namespace asylo { 114 | 115 | // Registers an instance of GrpcClientEnclave as the TrustedApplication. See 116 | // trusted_application.h for more information. 117 | TrustedApplication *BuildTrustedApplication() { 118 | return new examples::secure_grpc::GrpcClientEnclave(); 119 | } 120 | 121 | } // namespace asylo 122 | -------------------------------------------------------------------------------- /secure_grpc/grpc_client_enclave.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_SECURE_GRPC_GRPC_CLIENT_ENCLAVE_H_ 20 | #define ASYLO_EXAMPLES_SECURE_GRPC_GRPC_CLIENT_ENCLAVE_H_ 21 | 22 | #include 23 | #include 24 | 25 | #include "asylo/enclave.pb.h" 26 | #include "asylo/trusted_application.h" 27 | #include "asylo/util/status.h" 28 | 29 | namespace examples { 30 | namespace secure_grpc { 31 | 32 | // An enclave that makes RPCs to a MessengerServer. 33 | class GrpcClientEnclave : public asylo::TrustedApplication { 34 | public: 35 | // This method expects a GrpcClientEnclaveInput proto extension in |input|. 36 | // 37 | // Makes an RPC to the TranslatorServer running at the address specified in 38 | // |input|. It uses the connection deadline specified in |input| to form the 39 | // channel. The RPC result is returned through a |rpc_result| extension in 40 | // |output|. 41 | asylo::Status Run(const asylo::EnclaveInput &input, 42 | asylo::EnclaveOutput *output) override; 43 | }; 44 | 45 | } // namespace secure_grpc 46 | } // namespace examples 47 | 48 | #endif // ASYLO_EXAMPLES_SECURE_GRPC_GRPC_CLIENT_ENCLAVE_H_ 49 | -------------------------------------------------------------------------------- /secure_grpc/grpc_client_enclave.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package examples.secure_grpc; 20 | 21 | import "asylo/enclave.proto"; 22 | import "grpc_server/translator_server.proto"; 23 | 24 | extend asylo.EnclaveInput { 25 | optional GrpcClientEnclaveInput client_enclave_input = 277829866; 26 | } 27 | 28 | extend asylo.EnclaveOutput { 29 | optional GrpcClientEnclaveOutput client_enclave_output = 277829866; 30 | } 31 | 32 | // Input for a GrpcClientEnclave. 33 | message GrpcClientEnclaveInput { 34 | // The address of the server to contact. 35 | optional string server_address = 1; 36 | 37 | // The request for the GetTranslation RPC. 38 | optional examples.grpc_server.GetTranslationRequest translation_request = 2; 39 | } 40 | 41 | // Output for a GrpcClientEnclave. 42 | message GrpcClientEnclaveOutput { 43 | // The response from the GetTranslation RPC. 44 | optional examples.grpc_server.GetTranslationResponse translation_response = 1; 45 | } 46 | -------------------------------------------------------------------------------- /secure_grpc/grpc_client_main.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/flags/flag.h" 23 | #include "absl/flags/parse.h" 24 | #include "absl/strings/str_cat.h" 25 | #include "asylo/enclave_manager.h" 26 | #include "asylo/util/logging.h" 27 | #include "asylo/util/status.h" 28 | #include "secure_grpc/grpc_client_util.h" 29 | 30 | constexpr char kServerAddress[] = "localhost"; 31 | 32 | ABSL_FLAG(std::string, enclave_path, "", "Path to enclave to load"); 33 | ABSL_FLAG(int32_t, port, 0, "Port that the server listens to"); 34 | ABSL_FLAG(std::string, word_to_translate, "", "Word to be translated"); 35 | ABSL_FLAG(bool, debug, true, "Whether to use a debug enclave"); 36 | 37 | int main(int argc, char *argv[]) { 38 | // Parse command-line arguments. 39 | absl::ParseCommandLine(argc, argv); 40 | 41 | std::string word_to_translate = absl::GetFlag(FLAGS_word_to_translate); 42 | LOG_IF(QFATAL, word_to_translate.empty()) 43 | << "--word_to_translate cannot be empty"; 44 | 45 | std::string enclave_path = absl::GetFlag(FLAGS_enclave_path); 46 | LOG_IF(QFATAL, enclave_path.empty()) << "--enclave_path cannot be empty"; 47 | 48 | int32_t port = absl::GetFlag(FLAGS_port); 49 | LOG_IF(QFATAL, port == 0) << "--port cannot be 0"; 50 | 51 | asylo::Status status = 52 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions()); 53 | LOG_IF(QFATAL, !status.ok()) 54 | << "Failed to configure EnclaveManager: " << status; 55 | 56 | status = examples::secure_grpc::LoadGrpcClientEnclave( 57 | enclave_path, absl::GetFlag(FLAGS_debug)); 58 | LOG_IF(QFATAL, !status.ok()) 59 | << "Loading " << enclave_path << " failed: " << status; 60 | 61 | asylo::StatusOr run_result = 62 | examples::secure_grpc::GrpcClientEnclaveGetTranslation( 63 | absl::StrCat(kServerAddress, ":", port), word_to_translate); 64 | LOG_IF(QFATAL, !run_result.ok()) 65 | << "Getting translation for " << word_to_translate 66 | << " failed: " << run_result.status(); 67 | 68 | std::cout << "Translation for \"" << word_to_translate << "\" is \"" 69 | << run_result.value() << "\"" << std::endl; 70 | 71 | status = examples::secure_grpc::DestroyGrpcClientEnclave(); 72 | LOG_IF(QFATAL, !status.ok()) 73 | << "Destroy " << enclave_path << " failed: " << status; 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /secure_grpc/grpc_client_util.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/status/status.h" 23 | #include "absl/strings/str_cat.h" 24 | #include "asylo/client.h" 25 | #include "asylo/enclave.pb.h" 26 | #include "asylo/identity/enclave_assertion_authority_config.pb.h" 27 | #include "asylo/identity/enclave_assertion_authority_configs.h" 28 | #include "asylo/platform/primitives/sgx/loader.pb.h" 29 | #include "asylo/util/status.h" 30 | #include "asylo/util/status_macros.h" 31 | #include "asylo/util/statusor.h" 32 | #include "grpc_server/translator_server.grpc.pb.h" 33 | #include "secure_grpc/attestation_domain.h" 34 | #include "secure_grpc/grpc_client_enclave.pb.h" 35 | 36 | namespace examples { 37 | namespace secure_grpc { 38 | namespace { 39 | 40 | constexpr char kEnclaveName[] = "secure_grpc_client"; 41 | 42 | } // namespace 43 | 44 | asylo::Status LoadGrpcClientEnclave(const std::string &enclave_path, 45 | bool debug_enclave) { 46 | // The EnclaveLoadConfig contains all configurations passed to the enclave for 47 | // initialization. 48 | asylo::EnclaveLoadConfig load_config; 49 | load_config.set_name(kEnclaveName); 50 | 51 | // Create a config that initializes the SGX assertion authority. 52 | ASYLO_ASSIGN_OR_RETURN( 53 | *load_config.mutable_config()->add_enclave_assertion_authority_configs(), 54 | asylo::CreateSgxLocalAssertionAuthorityConfig(kAttestationDomain)); 55 | 56 | // The SgxLoadConfig sets up configuration specific to an SGX enclave, 57 | // including the location of the enclave binary and whether to run in debug 58 | // mode. 59 | asylo::SgxLoadConfig *sgx_config = 60 | load_config.MutableExtension(asylo::sgx_load_config); 61 | sgx_config->mutable_file_enclave_config()->set_enclave_path(enclave_path); 62 | sgx_config->set_debug(debug_enclave); 63 | 64 | asylo::EnclaveManager *manager = nullptr; 65 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 66 | ASYLO_RETURN_IF_ERROR(manager->LoadEnclave(load_config)); 67 | return absl::OkStatus(); 68 | } 69 | 70 | asylo::StatusOr GrpcClientEnclaveGetTranslation( 71 | const std::string &address, const std::string &word_to_translate) { 72 | asylo::EnclaveManager *manager = nullptr; 73 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 74 | 75 | asylo::EnclaveClient *client = manager->GetClient(kEnclaveName); 76 | if (!client) { 77 | return asylo::Status(asylo::error::FAILED_PRECONDITION, 78 | absl::StrCat(kEnclaveName, " not running")); 79 | } 80 | 81 | // Make the client request a translation from the server. 82 | asylo::EnclaveInput enclave_input; 83 | GrpcClientEnclaveInput *input = 84 | enclave_input.MutableExtension(client_enclave_input); 85 | input->set_server_address(address); 86 | input->mutable_translation_request()->set_input_word(word_to_translate); 87 | 88 | asylo::EnclaveOutput enclave_output; 89 | ASYLO_RETURN_IF_ERROR(client->EnterAndRun(enclave_input, &enclave_output)); 90 | 91 | if (!enclave_output.HasExtension(client_enclave_output)) { 92 | return asylo::Status( 93 | absl::StatusCode::kInternal, 94 | "EnclaveOutput missing expected client_enclave_output extension"); 95 | } 96 | const GrpcClientEnclaveOutput &output = 97 | enclave_output.GetExtension(client_enclave_output); 98 | if (output.translation_response().translated_word().empty()) { 99 | return asylo::Status(absl::StatusCode::kInternal, 100 | "GrpcClientEnclaveOutput is missing a translation"); 101 | } 102 | return output.translation_response().translated_word(); 103 | } 104 | 105 | asylo::Status DestroyGrpcClientEnclave() { 106 | asylo::EnclaveManager *manager = nullptr; 107 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 108 | 109 | asylo::EnclaveClient *client = manager->GetClient(kEnclaveName); 110 | if (!client) { 111 | return asylo::Status(asylo::error::FAILED_PRECONDITION, 112 | absl::StrCat(kEnclaveName, " not running")); 113 | } 114 | 115 | asylo::EnclaveFinal final_input; 116 | return manager->DestroyEnclave(client, final_input); 117 | } 118 | 119 | } // namespace secure_grpc 120 | } // namespace examples 121 | -------------------------------------------------------------------------------- /secure_grpc/grpc_client_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_SECURE_GRPC_GRPC_CLIENT_UTIL_H_ 20 | #define ASYLO_EXAMPLES_SECURE_GRPC_GRPC_CLIENT_UTIL_H_ 21 | 22 | #include 23 | 24 | #include "asylo/util/status.h" 25 | #include "asylo/util/statusor.h" 26 | 27 | namespace examples { 28 | namespace secure_grpc { 29 | 30 | // Each of the following functions assume that the asylo::EnclaveManager 31 | // instance has been configured using asylo::EnclaveManager::Configure(). 32 | 33 | // Loads the GrpcClientEnclave from |enclave_path|. If |debug_enclave| is true, 34 | // loads the enclave in debug mode. 35 | asylo::Status LoadGrpcClientEnclave(const std::string &enclave_path, 36 | bool debug_enclave); 37 | 38 | // Makes the GrpcClientEnclave issue a GetTranslation RPC for 39 | // |word_to_translate| to the server running at |address|, and returns the 40 | // translated word on success. |channel_deadline| is the channel-establishment 41 | // deadline. Returns a non-OK Status if the GrpcClientEnclave is not running. 42 | asylo::StatusOr GrpcClientEnclaveGetTranslation( 43 | const std::string &address, const std::string &word_to_translate); 44 | 45 | // Destroys the GrpcClientEnclave and returns its finalization Status. Returns a 46 | // non-OK Status if the GrpcClientEnclave is not running. 47 | asylo::Status DestroyGrpcClientEnclave(); 48 | 49 | } // namespace secure_grpc 50 | } // namespace examples 51 | 52 | #endif // ASYLO_EXAMPLES_SECURE_GRPC_GRPC_CLIENT_UTIL_H_ 53 | -------------------------------------------------------------------------------- /secure_grpc/grpc_server_config.proto: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2019 Asylo authors 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | syntax = "proto2"; 18 | 19 | package examples.secure_grpc; 20 | 21 | import "asylo/enclave.proto"; 22 | import "asylo/identity/platform/sgx/sgx_identity.proto"; 23 | 24 | extend asylo.EnclaveConfig { 25 | // An SGX identity expectation to enforce as the ACL in the Translator 26 | // server. Required. 27 | optional asylo.SgxIdentityExpectation identity_expectation = 264217773; 28 | } 29 | 30 | extend asylo.EnclaveOutput { 31 | // The Translator server's port. 32 | optional int32 server_port = 264217773; 33 | } 34 | -------------------------------------------------------------------------------- /secure_grpc/grpc_server_enclave.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/base/thread_annotations.h" 23 | #include "absl/status/status.h" 24 | #include "absl/strings/str_cat.h" 25 | #include "absl/synchronization/mutex.h" 26 | #include "absl/synchronization/notification.h" 27 | #include "absl/time/time.h" 28 | #include "asylo/grpc/auth/enclave_server_credentials.h" 29 | #include "asylo/grpc/auth/sgx_local_credentials_options.h" 30 | #include "asylo/identity/identity_acl.pb.h" 31 | #include "asylo/identity/platform/sgx/sgx_identity.pb.h" 32 | #include "asylo/identity/platform/sgx/sgx_identity_util.h" 33 | #include "asylo/trusted_application.h" 34 | #include "asylo/util/status.h" 35 | #include "asylo/util/status_macros.h" 36 | #include "grpc_server/grpc_server_config.pb.h" 37 | #include "include/grpcpp/grpcpp.h" 38 | #include "include/grpcpp/security/server_credentials.h" 39 | #include "include/grpcpp/server.h" 40 | #include "include/grpcpp/server_builder.h" 41 | #include "secure_grpc/grpc_server_config.pb.h" 42 | #include "secure_grpc/translator_server_impl.h" 43 | 44 | namespace examples { 45 | namespace secure_grpc { 46 | 47 | // An enclave that runs a TranslatorServerImpl. We override the methods of 48 | // TrustedApplication as follows: 49 | // 50 | // * Initialize starts the gRPC server. 51 | // * Run retrieves the server port. 52 | // * Finalize shuts down the server. 53 | class GrpcServerEnclave final : public asylo::TrustedApplication { 54 | public: 55 | asylo::Status Initialize(const asylo::EnclaveConfig &enclave_config) 56 | ABSL_LOCKS_EXCLUDED(server_mutex_) override; 57 | 58 | asylo::Status Run(const asylo::EnclaveInput &enclave_input, 59 | asylo::EnclaveOutput *enclave_output) override; 60 | 61 | asylo::Status Finalize(const asylo::EnclaveFinal &enclave_final) 62 | ABSL_LOCKS_EXCLUDED(server_mutex_) override; 63 | 64 | private: 65 | // Guards the |server_| member. 66 | absl::Mutex server_mutex_; 67 | 68 | // A gRPC server hosting |service_|. 69 | std::unique_ptr<::grpc::Server> server_ ABSL_GUARDED_BY(server_mutex_); 70 | 71 | // The translation service. 72 | std::unique_ptr service_; 73 | 74 | // The server's selected port. 75 | int selected_port_; 76 | }; 77 | 78 | asylo::Status GrpcServerEnclave::Initialize( 79 | const asylo::EnclaveConfig &enclave_config) 80 | ABSL_LOCKS_EXCLUDED(server_mutex_) { 81 | // Fail if there is no server_address available. 82 | if (!enclave_config.HasExtension(grpc_server::server_address)) { 83 | return absl::InvalidArgumentError( 84 | "Expected a server_address extension on config."); 85 | } 86 | 87 | if (!enclave_config.HasExtension(grpc_server::port)) { 88 | return absl::InvalidArgumentError("Expected a port extension on config."); 89 | } 90 | 91 | if (!enclave_config.HasExtension(identity_expectation)) { 92 | return absl::InvalidArgumentError( 93 | "Expected an identity_expectation extension on config."); 94 | } 95 | 96 | // Lock |server_mutex_| so that we can start setting up the server. 97 | absl::MutexLock lock(&server_mutex_); 98 | 99 | // Check that the server is not already running. 100 | if (server_) { 101 | return absl::AlreadyExistsError("Server is already started"); 102 | } 103 | 104 | // Create a ServerBuilder object to set up the server. 105 | ::grpc::ServerBuilder builder; 106 | 107 | // Use SGX local credentials to ensure that only local SGX enclaves can 108 | // connect to the server. 109 | std::shared_ptr<::grpc::ServerCredentials> server_credentials = 110 | asylo::EnclaveServerCredentials( 111 | asylo::BidirectionalSgxLocalCredentialsOptions()); 112 | 113 | // Add a listening port to the server. 114 | builder.AddListeningPort( 115 | absl::StrCat(enclave_config.GetExtension(grpc_server::server_address), 116 | ":", enclave_config.GetExtension(grpc_server::port)), 117 | server_credentials, &selected_port_); 118 | 119 | // Extract the SgxIdentityExpectation from the enclave's configuration. This 120 | // is used as the basis of the server's ACL. 121 | asylo::SgxIdentityExpectation sgx_expectation = 122 | enclave_config.GetExtension(identity_expectation); 123 | 124 | // Construct an ACL based from the SgxIdentityExpectation. 125 | asylo::IdentityAclPredicate acl; 126 | ASYLO_ASSIGN_OR_RETURN( 127 | *acl.mutable_expectation(), 128 | asylo::SerializeSgxIdentityExpectation(sgx_expectation)); 129 | 130 | // Build the service with the configured ACL. 131 | service_ = absl::make_unique(std::move(acl)); 132 | 133 | // Add the translator service to the server. 134 | builder.RegisterService(service_.get()); 135 | 136 | // Start the server. 137 | server_ = builder.BuildAndStart(); 138 | if (!server_) { 139 | return absl::InternalError("Failed to start server"); 140 | } 141 | 142 | return absl::OkStatus(); 143 | } 144 | 145 | asylo::Status GrpcServerEnclave::Run(const asylo::EnclaveInput &enclave_input, 146 | asylo::EnclaveOutput *enclave_output) { 147 | enclave_output->SetExtension(server_port, selected_port_); 148 | return absl::OkStatus(); 149 | } 150 | 151 | asylo::Status GrpcServerEnclave::Finalize( 152 | const asylo::EnclaveFinal &enclave_final) 153 | ABSL_LOCKS_EXCLUDED(server_mutex_) { 154 | // Lock |server_mutex_| so that we can start shutting down the server. 155 | absl::MutexLock lock(&server_mutex_); 156 | 157 | // If the server exists, then shut it down. Also delete the Server object to 158 | // indicate that it is no longer valid. 159 | if (server_) { 160 | LOG(INFO) << "Server shutting down"; 161 | 162 | // Give all outstanding RPC calls 500 milliseconds to complete. 163 | server_->Shutdown(std::chrono::system_clock::now() + 164 | std::chrono::milliseconds(500)); 165 | server_.reset(nullptr); 166 | } 167 | 168 | return absl::OkStatus(); 169 | } 170 | 171 | } // namespace secure_grpc 172 | } // namespace examples 173 | 174 | namespace asylo { 175 | 176 | // Registers an instance of GrpcServerEnclave as the TrustedApplication. See 177 | // trusted_application.h for more information. 178 | TrustedApplication *BuildTrustedApplication() { 179 | return new examples::secure_grpc::GrpcServerEnclave; 180 | } 181 | 182 | } // namespace asylo 183 | -------------------------------------------------------------------------------- /secure_grpc/grpc_server_main.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #include "absl/flags/flag.h" 26 | #include "absl/flags/parse.h" 27 | #include "absl/time/clock.h" 28 | #include "asylo/enclave_manager.h" 29 | #include "asylo/identity/platform/sgx/sgx_identity.pb.h" 30 | #include "asylo/util/logging.h" 31 | #include "asylo/util/proto_flag.h" 32 | #include "asylo/util/status.h" 33 | #include "asylo/util/statusor.h" 34 | #include "secure_grpc/grpc_server_util.h" 35 | 36 | ABSL_FLAG(std::string, enclave_path, "", "Path to enclave to load"); 37 | 38 | // By default, let the server run for five minutes. 39 | ABSL_FLAG(int32_t, server_max_lifetime, 300, 40 | "The longest amount of time (in seconds) that the server should be " 41 | "allowed to run"); 42 | 43 | // Default value 0 is used to indicate that the system should choose an 44 | // available port. 45 | ABSL_FLAG(int32_t, port, 0, "Port that the server listens to"); 46 | ABSL_FLAG(bool, debug, true, "Whether to use a debug enclave"); 47 | 48 | ABSL_FLAG(asylo::SgxIdentityExpectation, acl, {}, 49 | "The ACL to enforce within the server"); 50 | 51 | int main(int argc, char *argv[]) { 52 | // Parse command-line arguments. 53 | absl::ParseCommandLine(argc, argv); 54 | 55 | std::string enclave_path = absl::GetFlag(FLAGS_enclave_path); 56 | LOG_IF(QFATAL, enclave_path.empty()) << "--enclave_path cannot be empty"; 57 | 58 | asylo::Status status = 59 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions()); 60 | LOG_IF(QFATAL, !status.ok()) 61 | << "Failed to configure EnclaveManager: " << status; 62 | 63 | status = examples::secure_grpc::LoadGrpcServerEnclave( 64 | enclave_path, absl::GetFlag(FLAGS_port), absl::GetFlag(FLAGS_acl), 65 | absl::GetFlag(FLAGS_debug)); 66 | LOG_IF(QFATAL, !status.ok()) 67 | << "Loading " << enclave_path << " failed: " << status; 68 | 69 | asylo::StatusOr port_result = 70 | examples::secure_grpc::GrpcServerEnclaveGetPort(); 71 | LOG_IF(QFATAL, !port_result.ok()) 72 | << "Retrieving port failed: " << port_result.status(); 73 | 74 | std::cout << "Server started on port " << port_result.value() << std::endl; 75 | 76 | absl::SleepFor(absl::Seconds(absl::GetFlag(FLAGS_server_max_lifetime))); 77 | 78 | status = examples::secure_grpc::DestroyGrpcServerEnclave(); 79 | LOG_IF(QFATAL, !status.ok()) 80 | << "Destroy " << enclave_path << " failed: " << status; 81 | 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /secure_grpc/grpc_server_util.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "absl/strings/str_cat.h" 23 | #include "asylo/client.h" 24 | #include "asylo/enclave.pb.h" 25 | #include "asylo/identity/enclave_assertion_authority_config.pb.h" 26 | #include "asylo/identity/enclave_assertion_authority_configs.h" 27 | #include "asylo/identity/platform/sgx/sgx_identity.pb.h" 28 | #include "asylo/platform/primitives/sgx/loader.pb.h" 29 | #include "asylo/util/status.h" 30 | #include "asylo/util/status_macros.h" 31 | #include "grpc_server/grpc_server_config.pb.h" 32 | #include "secure_grpc/attestation_domain.h" 33 | #include "secure_grpc/grpc_server_config.pb.h" 34 | 35 | namespace examples { 36 | namespace secure_grpc { 37 | namespace { 38 | 39 | constexpr char kServerAddress[] = "localhost"; 40 | constexpr char kEnclaveName[] = "secure_grpc_server"; 41 | 42 | } // namespace 43 | 44 | asylo::Status LoadGrpcServerEnclave( 45 | const std::string &enclave_path, int port, 46 | const asylo::SgxIdentityExpectation &expectation, bool debug_enclave) { 47 | // The EnclaveLoadConfig contains all configurations passed to the enclave for 48 | // initialization. 49 | asylo::EnclaveLoadConfig load_config; 50 | load_config.set_name(kEnclaveName); 51 | 52 | // The EnclaveConfig contains the address that the gRPC server will run on, 53 | // the ACL to enforce in the server, and its configuration for the SGX local 54 | // assertion authority. 55 | asylo::EnclaveConfig *config = load_config.mutable_config(); 56 | config->SetExtension(examples::grpc_server::server_address, kServerAddress); 57 | config->SetExtension(examples::grpc_server::port, port); 58 | *config->MutableExtension(examples::secure_grpc::identity_expectation) = 59 | expectation; 60 | ASYLO_ASSIGN_OR_RETURN( 61 | *config->add_enclave_assertion_authority_configs(), 62 | asylo::CreateSgxLocalAssertionAuthorityConfig(kAttestationDomain)); 63 | 64 | // The SgxLoadConfig sets up configuration specific to an SGX enclave, 65 | // including the location of the enclave binary and whether to run in debug 66 | // mode. 67 | asylo::SgxLoadConfig *sgx_config = 68 | load_config.MutableExtension(asylo::sgx_load_config); 69 | sgx_config->mutable_file_enclave_config()->set_enclave_path(enclave_path); 70 | sgx_config->set_debug(debug_enclave); 71 | 72 | asylo::EnclaveManager *manager = nullptr; 73 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 74 | 75 | // Load the enclave. Calling LoadEnclave() triggers a call to the Initialize() 76 | // method of the TrustedApplication. 77 | return manager->LoadEnclave(load_config); 78 | } 79 | 80 | asylo::StatusOr GrpcServerEnclaveGetPort() { 81 | asylo::EnclaveManager *manager = nullptr; 82 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 83 | 84 | asylo::EnclaveClient *client = manager->GetClient(kEnclaveName); 85 | if (!client) { 86 | return asylo::Status(asylo::error::FAILED_PRECONDITION, 87 | absl::StrCat(kEnclaveName, " not running")); 88 | } 89 | 90 | asylo::EnclaveInput enclave_input; 91 | asylo::EnclaveOutput enclave_output; 92 | ASYLO_RETURN_IF_ERROR(client->EnterAndRun(enclave_input, &enclave_output)); 93 | if (!enclave_output.HasExtension(server_port)) { 94 | return asylo::Status(asylo::error::INTERNAL, 95 | "Server output missing server_port extension"); 96 | } 97 | return enclave_output.GetExtension(server_port); 98 | } 99 | 100 | asylo::Status DestroyGrpcServerEnclave() { 101 | asylo::EnclaveManager *manager = nullptr; 102 | ASYLO_ASSIGN_OR_RETURN(manager, asylo::EnclaveManager::Instance()); 103 | 104 | asylo::EnclaveClient *client = manager->GetClient(kEnclaveName); 105 | if (!client) { 106 | return asylo::Status(asylo::error::FAILED_PRECONDITION, 107 | absl::StrCat(kEnclaveName, " not running")); 108 | } 109 | 110 | asylo::EnclaveFinal final_input; 111 | return manager->DestroyEnclave(client, final_input); 112 | } 113 | 114 | } // namespace secure_grpc 115 | } // namespace examples 116 | -------------------------------------------------------------------------------- /secure_grpc/grpc_server_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_SECURE_GRPC_GRPC_SERVER_UTIL_H_ 20 | #define ASYLO_EXAMPLES_SECURE_GRPC_GRPC_SERVER_UTIL_H_ 21 | 22 | #include 23 | 24 | #include "asylo/identity/platform/sgx/sgx_identity.pb.h" 25 | #include "asylo/util/status.h" 26 | #include "asylo/util/statusor.h" 27 | 28 | namespace examples { 29 | namespace secure_grpc { 30 | 31 | // Each of the following functions assume that the asylo::EnclaveManager 32 | // instance has been configured using asylo::EnclaveManager::Configure(). 33 | 34 | // Loads the GrpcServerEnclave from |enclave_path|. If |debug_enclave| is true, 35 | // then the enclave is started in debug mode. Starts the enclave's server on 36 | // |port| and configures the server to enforce |expectation| as the ACL in the 37 | // GetTranslation RPC. 38 | asylo::Status LoadGrpcServerEnclave( 39 | const std::string &enclave_path, int port, 40 | const asylo::SgxIdentityExpectation &expectation, bool debug_enclave); 41 | 42 | // Retrieves the port of the server inside the GrpcServerEnclave. Returns a 43 | // non-OK Status if the GrpcServerEnclave is not running. 44 | asylo::StatusOr GrpcServerEnclaveGetPort(); 45 | 46 | // Destroys the GrpcServerEnclave and returns its finalization Status. Returns a 47 | // non-OK Status if the GrpcServerEnclave is not running. 48 | asylo::Status DestroyGrpcServerEnclave(); 49 | 50 | } // namespace secure_grpc 51 | } // namespace examples 52 | 53 | #endif // ASYLO_EXAMPLES_SECURE_GRPC_GRPC_SERVER_UTIL_H_ 54 | -------------------------------------------------------------------------------- /secure_grpc/secure_grpc_test.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "absl/flags/flag.h" 32 | #include "absl/memory/memory.h" 33 | #include "absl/strings/str_cat.h" 34 | #include "absl/strings/string_view.h" 35 | #include "asylo/enclave_manager.h" 36 | #include "asylo/identity/platform/sgx/sgx_identity.pb.h" 37 | #include "asylo/test/util/status_matchers.h" 38 | #include "asylo/util/status.h" 39 | #include "asylo/util/status_macros.h" 40 | #include "secure_grpc/grpc_client_util.h" 41 | #include "secure_grpc/grpc_server_util.h" 42 | 43 | ABSL_FLAG(std::string, server_enclave_path, "", 44 | "The path to the server enclave to pass to the enclave loader"); 45 | 46 | ABSL_FLAG(std::string, client_enclave_path, "", 47 | "The path to the client enclave to pass to the enclave loader"); 48 | 49 | ABSL_FLAG(std::string, acl_isvprodid_2_path, "", 50 | "Path to acl_isvprodid_2.textproto"); 51 | 52 | ABSL_FLAG(std::string, acl_isvprodid_3_path, "", 53 | "Path to acl_isvprodid_3.textproto"); 54 | 55 | ABSL_FLAG(std::string, acl_non_debug_path, "", 56 | "Path to acl_non_debug_2.textproto"); 57 | 58 | ABSL_FLAG(bool, debug_enclave, true, "Whether to debug enclaves"); 59 | 60 | constexpr char kAuthorizationFailureMessage[] = 61 | "Peer is unauthorized for GetTranslation: ACL failed to match"; 62 | 63 | namespace examples { 64 | namespace secure_grpc { 65 | namespace { 66 | 67 | using asylo::IsOkAndHolds; 68 | using asylo::StatusIs; 69 | using ::testing::AllOf; 70 | using ::testing::HasSubstr; 71 | 72 | class GrpcServerTest : public ::testing::Test { 73 | public: 74 | static void SetUpTestSuite() { 75 | ASYLO_ASSERT_OK( 76 | asylo::EnclaveManager::Configure(asylo::EnclaveManagerOptions())); 77 | } 78 | 79 | void SetUp() override { 80 | ASSERT_NE(absl::GetFlag(FLAGS_server_enclave_path), ""); 81 | ASSERT_NE(absl::GetFlag(FLAGS_client_enclave_path), ""); 82 | ASSERT_NE(absl::GetFlag(FLAGS_acl_isvprodid_2_path), ""); 83 | ASSERT_NE(absl::GetFlag(FLAGS_acl_isvprodid_3_path), ""); 84 | ASSERT_NE(absl::GetFlag(FLAGS_acl_non_debug_path), ""); 85 | server_port_ = 0; 86 | } 87 | 88 | void StartServer(const std::string &acl_path) { 89 | int fd = open(acl_path.c_str(), O_RDONLY); 90 | ASSERT_GT(fd, -1) << strerror(errno); 91 | google::protobuf::io::FileInputStream stream(fd); 92 | stream.SetCloseOnDelete(true); 93 | 94 | asylo::SgxIdentityExpectation expectation; 95 | ASSERT_TRUE(google::protobuf::TextFormat::Parse(&stream, &expectation)); 96 | 97 | ASYLO_ASSERT_OK(LoadGrpcServerEnclave( 98 | absl::GetFlag(FLAGS_server_enclave_path), server_port_, expectation, 99 | absl::GetFlag(FLAGS_debug_enclave))); 100 | 101 | // Retrieve the server's port. 102 | ASYLO_ASSERT_OK_AND_ASSIGN(server_port_, GrpcServerEnclaveGetPort()); 103 | ASSERT_NE(server_port_, 0); 104 | } 105 | 106 | void TearDown() override { ASYLO_ASSERT_OK(DestroyGrpcServerEnclave()); } 107 | 108 | asylo::Status LoadGrpcClientEnclave() { 109 | return examples::secure_grpc::LoadGrpcClientEnclave( 110 | absl::GetFlag(FLAGS_client_enclave_path), 111 | absl::GetFlag(FLAGS_debug_enclave)); 112 | } 113 | 114 | // Sends a GetTranslation RPC to the server via the client enclave. Returns 115 | // the same grpc::Status as the stub function call. If the RPC is successful, 116 | // returns the translated word, else returns a non-OK status. 117 | asylo::StatusOr MakeRpc(const std::string &input_word) { 118 | return GrpcClientEnclaveGetTranslation( 119 | absl::StrCat("localhost:", server_port_), input_word); 120 | } 121 | 122 | private: 123 | int server_port_; 124 | }; 125 | 126 | TEST_F(GrpcServerTest, AuthorizationSuccess) { 127 | ASSERT_NO_FATAL_FAILURE( 128 | StartServer(absl::GetFlag(FLAGS_acl_isvprodid_2_path))); 129 | 130 | ASYLO_ASSERT_OK(LoadGrpcClientEnclave()); 131 | 132 | EXPECT_THAT(MakeRpc("asylo"), IsOkAndHolds("sanctuary")); 133 | EXPECT_THAT(MakeRpc("istio"), IsOkAndHolds("sail")); 134 | EXPECT_THAT(MakeRpc("kubernetes"), IsOkAndHolds("helmsman")); 135 | 136 | ASYLO_ASSERT_OK(DestroyGrpcClientEnclave()); 137 | } 138 | 139 | TEST_F(GrpcServerTest, Isvprodid3AuthorizationFailure) { 140 | ASSERT_NO_FATAL_FAILURE( 141 | StartServer(absl::GetFlag(FLAGS_acl_isvprodid_3_path))); 142 | 143 | ASYLO_ASSERT_OK(LoadGrpcClientEnclave()); 144 | EXPECT_THAT(MakeRpc("asylo"), 145 | StatusIs(asylo::error::PERMISSION_DENIED, 146 | AllOf(HasSubstr(kAuthorizationFailureMessage), 147 | HasSubstr("ISVPRODID")))); 148 | ASYLO_ASSERT_OK(DestroyGrpcClientEnclave()); 149 | } 150 | 151 | TEST_F(GrpcServerTest, NonDebugAuthorizationFailure) { 152 | ASSERT_NO_FATAL_FAILURE(StartServer(absl::GetFlag(FLAGS_acl_non_debug_path))); 153 | 154 | ASYLO_ASSERT_OK(LoadGrpcClientEnclave()); 155 | EXPECT_THAT(MakeRpc("asylo"), 156 | StatusIs(asylo::error::PERMISSION_DENIED, 157 | AllOf(HasSubstr(kAuthorizationFailureMessage), 158 | HasSubstr("DEBUG")))); 159 | ASYLO_ASSERT_OK(DestroyGrpcClientEnclave()); 160 | } 161 | 162 | } // namespace 163 | } // namespace secure_grpc 164 | } // namespace examples 165 | -------------------------------------------------------------------------------- /secure_grpc/translator_server_impl.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #include "secure_grpc/translator_server_impl.h" 20 | 21 | #include 22 | 23 | #include "absl/strings/ascii.h" 24 | #include "absl/strings/str_cat.h" 25 | #include "asylo/grpc/auth/enclave_auth_context.h" 26 | #include "include/grpcpp/grpcpp.h" 27 | 28 | namespace examples { 29 | namespace secure_grpc { 30 | 31 | TranslatorServerImpl::TranslatorServerImpl(asylo::IdentityAclPredicate acl) 32 | : Service(), 33 | // Initialize the translation map with a few known translations. 34 | translation_map_({{"asylo", "sanctuary"}, 35 | {"istio", "sail"}, 36 | {"kubernetes", "helmsman"}}), 37 | acl_(std::move(acl)) {} 38 | 39 | ::grpc::Status TranslatorServerImpl::GetTranslation( 40 | ::grpc::ServerContext *context, 41 | const grpc_server::GetTranslationRequest *request, 42 | grpc_server::GetTranslationResponse *response) { 43 | // First, access the authentication properties of the connection through 44 | // EnclaveAuthContext. 45 | auto auth_context_result = asylo::EnclaveAuthContext::CreateFromAuthContext( 46 | *context->auth_context()); 47 | if (!auth_context_result.ok()) { 48 | LOG(ERROR) << "Failed to access authentication context: " 49 | << auth_context_result.status(); 50 | return ::grpc::Status(::grpc::StatusCode::INTERNAL, 51 | "Failed to access authentication context"); 52 | } 53 | 54 | asylo::EnclaveAuthContext auth_context = auth_context_result.value(); 55 | 56 | // Now, check whether the peer is authorized to call this RPC. 57 | std::string explanation; 58 | auto authorized_result = auth_context.EvaluateAcl(acl_, &explanation); 59 | if (!authorized_result.ok()) { 60 | LOG(INFO) << authorized_result.status(); 61 | return ::grpc::Status(::grpc::StatusCode::INTERNAL, 62 | "Error occurred while evaluating ACL"); 63 | } 64 | 65 | if (!authorized_result.value()) { 66 | std::string combined_error = 67 | absl::StrCat("Peer is unauthorized for GetTranslation: ", explanation); 68 | std::cout << combined_error << std::endl; 69 | return ::grpc::Status(::grpc::StatusCode::PERMISSION_DENIED, 70 | combined_error); 71 | } 72 | 73 | std::cout << "The peer is authorized for GetTranslation" << std::endl; 74 | 75 | // Confirm that |*request| has an |input_word| field. 76 | if (!request->has_input_word()) { 77 | return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, 78 | "No input word given"); 79 | } 80 | 81 | // Confirm that the translation map has a translation for the input word. 82 | auto response_iterator = 83 | translation_map_.find(absl::AsciiStrToLower(request->input_word())); 84 | if (response_iterator == translation_map_.end()) { 85 | return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, 86 | absl::StrCat("No known translation for \"", 87 | request->input_word(), "\"")); 88 | } 89 | 90 | // Return the translation. 91 | response->set_translated_word(response_iterator->second); 92 | return ::grpc::Status::OK; 93 | } 94 | 95 | } // namespace secure_grpc 96 | } // namespace examples 97 | -------------------------------------------------------------------------------- /secure_grpc/translator_server_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright 2019 Asylo authors 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | #ifndef ASYLO_EXAMPLES_SECURE_GRPC_TRANSLATOR_SERVER_IMPL_H_ 20 | #define ASYLO_EXAMPLES_SECURE_GRPC_TRANSLATOR_SERVER_IMPL_H_ 21 | 22 | #include 23 | 24 | #include "absl/base/thread_annotations.h" 25 | #include "absl/container/flat_hash_map.h" 26 | #include "absl/synchronization/mutex.h" 27 | #include "absl/synchronization/notification.h" 28 | #include "asylo/identity/identity_acl.pb.h" 29 | #include "grpc_server/translator_server.grpc.pb.h" 30 | #include "include/grpcpp/grpcpp.h" 31 | #include "include/grpcpp/server.h" 32 | 33 | namespace examples { 34 | namespace secure_grpc { 35 | 36 | using grpc_server::Translator; 37 | 38 | class TranslatorServerImpl final : public Translator::Service { 39 | public: 40 | // Configure the server with an ACL to enforce at the GetTranslation() RPC. 41 | explicit TranslatorServerImpl(asylo::IdentityAclPredicate acl); 42 | 43 | private: 44 | ::grpc::Status GetTranslation( 45 | ::grpc::ServerContext *context, 46 | const grpc_server::GetTranslationRequest *request, 47 | grpc_server::GetTranslationResponse *response) override; 48 | 49 | // A map from words to their translations. 50 | absl::flat_hash_map translation_map_; 51 | 52 | // An ACL that is enforced on the GetTranslation RPC. 53 | asylo::IdentityAclPredicate acl_; 54 | }; 55 | 56 | } // namespace secure_grpc 57 | } // namespace examples 58 | 59 | #endif // ASYLO_EXAMPLES_SECURE_GRPC_TRANSLATOR_SERVER_IMPL_H_ 60 | --------------------------------------------------------------------------------