├── .gitignore ├── .gitmodules ├── Cargo.toml ├── LICENSE ├── README.md ├── build-script ├── Cargo.toml ├── build.rs └── src │ ├── builders.rs │ ├── cutils.rs │ ├── env.rs │ ├── lib.rs │ ├── sgx_app.rs │ └── std_app.rs ├── build_dep.rs ├── docker ├── docker-compose.yaml ├── ubuntu-20.04.Dockerfile └── ubuntu-22.04.Dockerfile ├── edl └── sgx_dcap.edl ├── rust-toolchain ├── rustfmt.toml ├── src ├── app │ ├── enclave.rs │ ├── mod.rs │ └── untrusted.rs ├── dcap │ ├── mod.rs │ ├── trusted.rs │ └── untrusted.rs ├── lib.rs ├── patch.rs ├── sgxlib.rs ├── tse │ ├── api_trusted.rs │ ├── api_untrusted.rs │ └── mod.rs └── types.rs └── sysroot ├── Cargo.toml ├── build.rs └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # RustRover 17 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 18 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 19 | # and can be added to the global gitignore or merged into this file. For a more nuclear 20 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 21 | #.idea/ 22 | 23 | .DS_Store 24 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/automata-network/automata-sgx-sdk/939894eae22d14200318c021e9c3b89f976eb2ca/.gitmodules -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "automata-sgx-sdk" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Automata Team"] 6 | homepage = "https://www.ata.network/" 7 | 8 | [package.metadata] 9 | rust-toolchain = "nightly-2024-02-01" 10 | target = "x86_64-automata-linux-sgx" 11 | intel-sgx-sdk = "2.24.100" 12 | 13 | [features] 14 | default = ["sgx_types"] 15 | tstd_enclave = ["dcap", "sgx_trts", "sgx_types", "sgx_libc_pthread", "patch_rand", "patch_assert_fail", "tse"] 16 | tstd_app = ["dcap", "sgx_types", "sgx_urts", "app"] 17 | builder = ["dep:automata-build-script"] 18 | sysroot = [] 19 | dcap = ["dep:sgx-dcap-ql-rs"] 20 | tse = ["sgx_tse"] 21 | app = [] 22 | patch_rand = ["dummy_pthread_atfork"] 23 | patch_assert_fail = ["sgx_libc"] 24 | dummy_pthread_atfork = [] 25 | 26 | sgx_libc = ["dep:sgx_libc"] 27 | sgx_libc_pthread = ["sgx_libc", "sgx_libc/pthread"] 28 | sgx_urts = ["dep:sgx_urts"] 29 | sgx_alloc = ["dep:sgx_alloc"] 30 | sgx_crypto = ["dep:sgx_crypto"] 31 | sgx_demangle = ["dep:sgx_demangle"] 32 | sgx_edl = ["dep:sgx_edl"] 33 | sgx_ffi = ["dep:sgx_ffi"] 34 | sgx_rand = ["dep:sgx_rand"] 35 | sgx_types = [] 36 | sgx_trts = [] 37 | sgx_tse = ["dep:sgx_tse"] 38 | sgx_unwind = ["dep:sgx_unwind"] 39 | 40 | [dependencies] 41 | cc = { version = "1.1.5" } 42 | serde = { version = "=1.0.197", features = ["derive"] } 43 | serde_json = "1" 44 | ctor = "0.2" 45 | automata-build-script = { path = "build-script", optional = true } 46 | base = { git = "https://github.com/automata-network/base-rs" } 47 | 48 | sgx_libc = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 49 | sgx_urts = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 50 | sgx_alloc = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 51 | sgx_crypto = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 52 | sgx_demangle = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 53 | sgx_edl = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 54 | sgx_ffi = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 55 | sgx_rand = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 56 | sgx_unwind = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 57 | sgx_tse = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01", optional = true } 58 | sgx-dcap-ql-rs = { git = "https://github.com/automata-network/SGXDataCenterAttestationPrimitives.git", branch = "automata_sgx_builder", optional = true } 59 | 60 | [target.'cfg(not(target_vendor = "teaclave"))'.dependencies] 61 | automata-sgx-sdk-sysroot = { path = "sysroot" } 62 | sgx_types = { git = "https://github.com/automata-network/incubator-teaclave-sgx-sdk", branch = "2.24_nightly_2024-02-01" } 63 | 64 | [workspace] 65 | resolver = "2" 66 | members = [ 67 | "sysroot", 68 | "build-script" 69 | ] 70 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | # Automata SGX SDK 10 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) 11 | 12 | This repository contains the source code for the Automata SGX SDK, which is a software development kit for building secure enclaves on the Intel SGX platform. The SDK provides a set of APIs and tools to help developers build secure applications that run within an SGX enclave. 13 | 14 | | | Type | Build System | DCAP attestation | Rust toolchain | Intel SGX SDK | 15 | | ----------------------- | ------------ | ---------------- | ---------------------- | ------------------ | ------------- | 16 | | Automata SGX SDK | Rust SGX SDK | Cargo | High-level abstraction | nightly-2024-02-01 | 2.24 | 17 | | Apache Teaclave SGX SDK | Rust SGX SDK | Makefile & Cargo | Low-level abstraction | nightly-2023-11-17 | 2.17 | 18 | | Gramine | LibOS | Makefile | High-level abstraction | - | - | 19 | 20 | Compared to Gramine, the Automata SGX SDK provides developers with greater flexibility to design custom enclave interfaces and selectively place critical components inside the enclave. This capability enables more precise memory management and offers opportunities for performance optimization. With the help of Rust, developers can build robust, high-performance SGX applications that benefit from Rust’s strong safety guarantees and efficient memory management. 21 | 22 | In contrast to the Apache Teaclave SGX SDK, the Automata SGX SDK simplifies the development process by removing the need for manual maintenance of Makefiles. All builds are managed through Cargo, Rust’s package manager and build system. Additionally, it supports newer versions of both the Intel SGX SDK and the Rust toolchain. 23 | 24 | 25 | ## Overview 26 | 27 | The Automata SGX SDK contains the following features which makes it easier for beginners to get started with building SGX applications: 28 | 29 | - **Build System**: The SDK provides a build system for building SGX applications with Rust, on top of the build system, we provide the [cargo-sgx](https://crates.io/crates/cargo-sgx) tool which greatly simplifies the process of building SGX applications. 30 | - **Remote Attestation**: The SDK implements the workflow of DCAP Remote Attestation and provides a simple interface to be integrated into your application. 31 | 32 | ### Build System 33 | 34 | The workflow of building SGX APP in the [teaclave](https://github.com/apache/incubator-teaclave-sgx-sdk/blob/v2.0.0-preview-11-17/samplecode/template/Makefile) is complicated. Overall, it includes the following steps: 35 | * Build tstd sysroot from incubator-teaclave-sgx-sdk. 36 | * Build the edl(Enclave Definition Language) file and generate the bridge codes. 37 | * Build the enclave crate with custom tstd. 38 | * Link the enclave crate with other crates and generated `.so`. 39 | * Sign the shared object with signing key, generated `.signed.so`. 40 | 41 | In Automata SGX SDK, we combine these steps on top of the cargo building system automatically, so you can get rid of the hassle of modifying the Makefile. 42 | 43 | ### DCAP Remote Attestation 44 | 45 | As the most important feature of the SGX APP, we have built the DCAP attestation generation function based on [SGXDataCenterAttestationPrimitives](https://github.com/automata-network/SGXDataCenterAttestationPrimitives). 46 | Users do not need to understand what's the ocalls during this process. 47 | 48 | ## Supported Environment 49 | 50 | | Operator System | Intel SGX SDK | Rust Toolchain | Status | 51 | | ---------------- | ------------- | ------------------ | ------ | 52 | | Ubuntu 20.04 LTS | 2.24 | nightly-2024-02-01 | ✅ | 53 | | Ubuntu 22.04 LTS | 2.24 | nightly-2024-02-01 | ✅ | 54 | 55 | ## Getting Started 56 | 57 | To build your first enclave, please refer to the [sgx-scaffold](https://github.com/automata-network/sgx-scaffold/tree/main) project. It is a good starting point to get familiar with the SDK. 58 | 59 | ### Building applications 60 | Let's take the project structure below as an example. The `app` crate is the entrypoint and untrusted part of the application, while the `enclave` crate is the SGX enclave implementation, trusted part of the application. 61 |
 62 | ├── app: Entrypoint and untrusted part of the application
 63 | │ ├── sgx/*: Configurations for the enclave
 64 | │ ├── src/main.rs: Main entrypoint for the application
 65 | │ ├── build.rs: Builder code using the build system of Automata SGX SDK
 66 | │ └── Cargo.toml: Cargo.toml of the app crate
 67 | ├── enclave: The SGX enclave implementation, trusted part of the application
 68 | │ ├── src/lib.rs: Main library file for the enclave implementation
 69 | │ └── Cargo.toml: Cargo.toml of the enclave crate
 70 | └── Cargo.toml: Cargo.toml of the workspace
 71 | 
72 | 73 | Follow the steps below to use Automata SGX SDK: 74 | 75 | 1. Specify the rust-toolchain, please ensure that the Rust version used aligns with the [Automata SGX SDK](Cargo.toml#L10). We will use `nightly-2024-02-01` in this case. 76 | 77 | ```bash 78 | echo 'nightly-2024-02-01' > rust-toolchain 79 | ``` 80 | 81 | 2. Update the `Cargo.toml` of the workspace to include the following dependencies, here we choose the `main` branch. 82 | ```toml 83 | [workspace.dependencies] 84 | automata-sgx-sdk = { git = "https://github.com/automata-network/automata-sgx-sdk", branch = "main" } 85 | automata-build-script = { git = "https://github.com/automata-network/automata-sgx-sdk", branch = "main" } 86 | ``` 87 | 88 | 3. Update the `app/Cargo.toml` file as follows. 89 | 90 | Explanation for the avaibale options of `package.metadata.sgx`: 91 | - `path`: (required) Path to the enclave crate. 92 | - `config`: (required) Path to the enclave configuration file. 93 | - `edl`: (required) Path to the enclave EDL file. 94 | - `lds`: (required) Path to the enclave LDS file. 95 | - `key`: (required) Path to the enclave developer key. 96 | - `env`: (optional) Environment variables to be passed to the enclave builder. 97 | 98 | ```toml 99 | [features] 100 | tstd_app = ["automata-sgx-sdk/tstd_app"] 101 | 102 | [package.metadata.sgx] 103 | my_enclave = { path = "../enclave", config = "sgx/config.xml", edl = "sgx/enclave.edl", lds = "sgx/enclave.lds", key = "sgx/private.pem", env = ["MY_ENV_VAR=1"] } 104 | 105 | [dependencies] 106 | automata-sgx-sdk = { workspace = true } 107 | ``` 108 | 109 | 4. Update the `app/src/main.rs` file to include the following code, which will call the build script to build the application. 110 | ```rust 111 | fn main() { 112 | automata_build_script::build_app(); 113 | } 114 | ``` 115 | 116 | 5. Update the `app/src/main.rs` file and add the `enclave!` macro. 117 | 118 | The `enclave!` macro is used to define the enclave and helps to initialize the enclave, it takes two arguments: 119 | - `name`: The name of the enclave. **The name needs to align with `package.metadata.sgx`, but it should be converted from snake_case to CamelCase with the first letter capitalized**. In this case we use `MyEnclave` instead of `my_enclave`. 120 | - `ecall`: The ecalls of the enclave. 121 | 122 | ```rust 123 | automata_sgx_sdk::enclave! { 124 | name: MyEnclave, 125 | ecall: { 126 | fn trusted_execution() -> SgxStatus; 127 | } 128 | } 129 | ``` 130 | 131 | 6. Update the `enclave/Cargo.toml` file and add the following dependencies. The `lib.name` should be same as the name defined on `package.metadata.sgx`. 132 | 133 | ```toml 134 | [lib] 135 | name = "my_enclave" 136 | crate-type = ["staticlib"] 137 | 138 | [features] 139 | tstd_enclave = ["automata-sgx-sdk/tstd_enclave"] 140 | 141 | [dependencies] 142 | automata-sgx-sdk = { workspace = true } 143 | ``` 144 | 145 | 146 | ### Generating remote attestation report 147 | Use the `dcap_quote` function in your enclave implementation to generate a DCAP attestation report. 148 | 149 | The `data` is the report data provided by the application, it is a 64-byte byte array, and will be included in the attestation report. 150 | ```rust 151 | let attestation = automata_sgx_sdk::dcap::dcap_quote(data); 152 | ``` 153 | 154 | Refer to the [Automata DCAP Attestation](https://github.com/automata-network/automata-dcap-attestation) repo for more details about verification of the DCAP attestation. 155 | 156 | ## Projects using Automata SGX SDK 157 | 158 | * [sgx-prover](https://github.com/automata-network/sgx-prover): A prover that supports to execute Scroll and Linea blocks in SGX enclave and generate the PoE (Proof of Execution). 159 | * [sgx-scaffold](https://github.com/automata-network/sgx-scaffold): A scaffold for creating an SGX enclave with Rust. 160 | * [sgx-revm](https://github.com/automata-network/revm-sgx): A PoC that embedded revm inside Intel SGX enclave. 161 | 162 | ## Acknowledgements 163 | - [incubator-teaclave-sgx-sdk](https://github.com/apache/incubator-teaclave-sgx-sdk): The Automata SGX SDK is built on top of [https://github.com/automata-network/incubator-teaclave-sgx-sdk](https://github.com/automata-network/incubator-teaclave-sgx-sdk), which is a fork of `incubator-teaclave-sgx-sdk` and updated to work with the latest version of the Rust toolchain and Intel SGX SDK. 164 | 165 | ## Disclaimer 166 | This project is under development. All source code and features are not production ready. 167 | -------------------------------------------------------------------------------- /build-script/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "automata-build-script" 3 | version = "0.1.0" 4 | edition = "2021" 5 | authors = ["Automata Team"] 6 | homepage = "https://www.ata.network/" 7 | 8 | [features] 9 | tstd_app = [] 10 | 11 | [dependencies] 12 | cc = { version = "1.1.5" } 13 | serde = { version = "1", features = ["derive"] } 14 | serde_json = "1" 15 | toml = "0.8.19" -------------------------------------------------------------------------------- /build-script/build.rs: -------------------------------------------------------------------------------- 1 | include!("../build_dep.rs"); 2 | 3 | fn main() { 4 | let root_dir = std::path::PathBuf::new().join(std::env::var("CARGO_MANIFEST_DIR").unwrap()); 5 | let root_dir = root_dir.parent().unwrap(); 6 | let teaclave_sdk_path = get_teaclave_sdk_path().expect("unable to locate teaclave_sdk"); 7 | println!( 8 | "cargo:rustc-env=AUTOMATA_SGX_BUILDER_DIR={}", 9 | root_dir.display() 10 | ); 11 | println!( 12 | "cargo:rustc-env=TEACLAVE_SGX_SDK_ROOT_DIR={}", 13 | teaclave_sdk_path.display() 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /build-script/src/builders.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | io::Write, 3 | path::{Path, PathBuf}, 4 | process::Command, 5 | }; 6 | 7 | use cc::Build; 8 | 9 | use crate::{cutils::Cutils, Env}; 10 | 11 | #[derive(Debug, Clone, Copy)] 12 | pub enum BuildMode { 13 | BuildScript, 14 | Shell, 15 | } 16 | 17 | impl BuildMode { 18 | pub fn apply_build(&self, b: &mut Build) { 19 | match self { 20 | BuildMode::BuildScript => { 21 | b.opt_level(2); 22 | } 23 | BuildMode::Shell => { 24 | b.target("test") 25 | .host("test") 26 | .opt_level(2) 27 | .shared_flag(false) 28 | .cargo_metadata(false); 29 | } 30 | } 31 | } 32 | 33 | pub fn trace_file>(&self, p: P) { 34 | if !matches!(self, BuildMode::BuildScript) { 35 | return; 36 | } 37 | println!("cargo:rerun-if-changed={}", p.as_ref().display()); 38 | } 39 | } 40 | 41 | pub struct UntrustedProxyBuilder { 42 | mode: BuildMode, 43 | } 44 | 45 | impl UntrustedProxyBuilder { 46 | pub fn new(mode: BuildMode) -> Self { 47 | Self { mode } 48 | } 49 | 50 | pub fn build(&self, source: &PathBuf, output: &PathBuf) { 51 | let includes = vec![ 52 | Env::sdk_path().join("include"), 53 | Env::sdk_root_dir().join("common").join("inc"), 54 | Env::sdk_root_dir().join("sgx_edl").join("edl"), 55 | ]; 56 | 57 | let mut build = cc::Build::new(); 58 | self.mode.apply_build(&mut build); 59 | apply_flags(&mut build, &Cutils::cflags()); 60 | apply_flags(&mut build, &["-fPIC", "-Wno-attributes"]); 61 | if Env::is_64bits() { 62 | build.flag_if_supported("-m64"); 63 | } else { 64 | build.flag_if_supported("-m32"); 65 | } 66 | build.includes(includes); 67 | build.out_dir(parent_path(output)); 68 | build.file(source).compile(&link_name(output)); 69 | // self.mode.trace_file(source); 70 | } 71 | } 72 | 73 | pub struct TrustedProxyBuilder { 74 | mode: BuildMode, 75 | } 76 | 77 | impl TrustedProxyBuilder { 78 | pub fn new(mode: BuildMode) -> Self { 79 | Self { mode } 80 | } 81 | 82 | pub fn build(&self, source: &PathBuf, output: &PathBuf) { 83 | let includes = vec![ 84 | Env::sdk_root_dir().join("common").join("inc"), 85 | Env::sdk_root_dir().join("common").join("inc").join("tlibc"), 86 | Env::sdk_root_dir().join("sgx_edl").join("edl"), 87 | ]; 88 | let mut build = cc::Build::new(); 89 | self.mode.apply_build(&mut build); 90 | apply_flags(&mut build, &Cutils::cflags()); 91 | apply_flags(&mut build, &Cutils::enclave_cflags()); 92 | if Env::is_64bits() { 93 | build.flag_if_supported("-m64"); 94 | } else { 95 | build.flag_if_supported("-m32"); 96 | } 97 | build.includes(includes); 98 | 99 | let mut cmd = build.get_compiler().to_command(); 100 | cmd.args(["-c", &format!("{}", source.display())]); 101 | cmd.args(["-o", &format!("{}", output.display())]); 102 | run_cmd(cmd); 103 | } 104 | } 105 | 106 | pub struct EnclaveSharedObjectBuilder { 107 | mode: BuildMode, 108 | } 109 | 110 | impl EnclaveSharedObjectBuilder { 111 | pub fn new(mode: BuildMode) -> Self { 112 | Self { mode } 113 | } 114 | 115 | pub fn build( 116 | &self, 117 | trusted_proxy: &PathBuf, 118 | enclave_object: &PathBuf, 119 | lds: &PathBuf, 120 | output: &PathBuf, 121 | ) { 122 | // self.mode.trace_file(trusted_proxy); 123 | // self.mode.trace_file(enclave_object); 124 | self.mode.trace_file(lds); 125 | 126 | let mut build = cc::Build::new(); 127 | self.mode.apply_build(&mut build); 128 | let mut cmd = build.get_compiler().to_command(); 129 | cmd.args([ 130 | &format!("{}", trusted_proxy.display()), 131 | "-o", 132 | &format!("{}", output.display()), 133 | ]); 134 | cmd.args(Cutils::enclave_ldflags()); 135 | cmd.args([ 136 | "-Wl,--no-undefined", 137 | "-nostdlib", 138 | "-nodefaultlibs", 139 | "-nostartfiles", 140 | ]); 141 | cmd.arg(format!("-Wl,--version-script={}", lds.display())); 142 | cmd.args([ 143 | "-Wl,--start-group", 144 | &format!("-L{}", parent_path(enclave_object)), 145 | &format!("-l{}", link_name(enclave_object)), 146 | // &format!("-L/usr/lib/x86_64-linux-gnu"), 147 | // "-lssl", "-lcrypto", 148 | "-Wl,--end-group", 149 | ]); 150 | 151 | run_cmd(cmd) 152 | } 153 | } 154 | 155 | fn link_name(p: &PathBuf) -> String { 156 | let n = p.file_name().unwrap().to_str().unwrap(); 157 | n.trim_end_matches(".o") 158 | .trim_end_matches(".a") 159 | .trim_start_matches("lib") 160 | .into() 161 | } 162 | 163 | fn parent_path(p: &PathBuf) -> String { 164 | let p = p.parent().unwrap(); 165 | let p_str = format!("{}", p.display()); 166 | if p_str == "" { 167 | ".".into() 168 | } else { 169 | p_str 170 | } 171 | } 172 | 173 | pub struct Edger8r { 174 | mode: BuildMode, 175 | path: PathBuf, 176 | search_path: Vec, 177 | } 178 | 179 | impl Edger8r { 180 | pub fn new(mode: BuildMode) -> Self { 181 | let bin = Env::sgx_bin_path().join("sgx_edger8r"); 182 | let search_path = vec![ 183 | Env::custom_edl_path(), 184 | Env::sgx_builder_path().join("edl"), 185 | Env::custom_common_path().join("inc"), 186 | ]; 187 | 188 | Self { 189 | mode, 190 | path: bin, 191 | search_path, 192 | } 193 | } 194 | 195 | pub fn add_search_path(&mut self, path: PathBuf) { 196 | self.search_path.push(path); 197 | } 198 | 199 | pub fn build(&self, edl: &PathBuf, trusted: bool, dir: &PathBuf) -> PathBuf { 200 | self.mode.trace_file(edl); 201 | 202 | let mut cmd = Command::new(&self.path); 203 | // let current_dir = std::env::current_dir().unwrap(); 204 | // let edl = current_dir.join(edl); 205 | if format!("{}", dir.parent().unwrap().display()) != "" { 206 | cmd.current_dir(dir.parent().unwrap()); 207 | } 208 | 209 | if trusted { 210 | cmd.args(["--trusted", &format!("{}", edl.display())]); 211 | cmd.args(["--trusted-dir", &format!("{}", dir.display())]); 212 | } else { 213 | cmd.args(["--untrusted", &format!("{}", edl.display())]); 214 | cmd.args(["--untrusted-dir", &format!("{}", dir.display())]); 215 | } 216 | for s in &self.search_path { 217 | cmd.args(["--search-path", s.to_str().unwrap()]); 218 | } 219 | 220 | run_cmd(cmd); 221 | 222 | let name = edl.file_stem().unwrap(); 223 | dir.join(format!( 224 | "{}_{}.c", 225 | name.to_string_lossy(), 226 | match trusted { 227 | true => "t", 228 | false => "u", 229 | } 230 | )) 231 | } 232 | } 233 | 234 | pub struct LdsBuilder {} 235 | 236 | impl LdsBuilder { 237 | pub fn new() -> Self { 238 | LdsBuilder {} 239 | } 240 | 241 | pub fn generate(&self, shared_lib: &str, out: &PathBuf) { 242 | let mut data = vec![0_u8; 0]; 243 | writeln!(data, "{}\n{{", shared_lib).unwrap(); 244 | writeln!(data, "\tglobal:").unwrap(); 245 | let segs = [ 246 | "g_global_data_hyper", 247 | "g_global_data_sim", 248 | "g_global_data", 249 | "enclave_entry", 250 | "g_peak_heap_used", 251 | "g_peak_rsrv_mem_committed", 252 | ]; 253 | for seg in segs { 254 | writeln!(data, "\t\t{};", seg).unwrap(); 255 | } 256 | writeln!(data, "\tlocal:\n\t\t*;").unwrap(); 257 | writeln!(data, "}};").unwrap(); 258 | std::fs::write(out, data).unwrap(); 259 | } 260 | } 261 | 262 | pub struct SgxSigner { 263 | mode: BuildMode, 264 | bin: PathBuf, 265 | } 266 | 267 | impl SgxSigner { 268 | pub fn new(mode: BuildMode) -> Self { 269 | let bin = Env::sgx_bin_path().join("sgx_sign"); 270 | Self { mode, bin } 271 | } 272 | 273 | pub fn generate_config(&self, out: &PathBuf) { 274 | let cfg = r#" 275 | 0 276 | 0 277 | 0x80000 278 | 0x40000000 279 | 33 280 | 0 281 | 0 282 | 0 283 | 0xFFFFFFFF 284 | "#; 285 | std::fs::write(out, cfg.as_bytes()).unwrap(); 286 | } 287 | 288 | pub fn sign(&self, cfg: &PathBuf, out: &PathBuf, enclave: &PathBuf, pem: &PathBuf) { 289 | self.mode.trace_file(cfg); 290 | // self.mode.trace_file(enclave); 291 | self.mode.trace_file(pem); 292 | 293 | let mut cmd = Command::new(&self.bin); 294 | cmd.arg("sign"); 295 | cmd.args(["-config", &format!("{}", cfg.display())]); 296 | cmd.args(["-out", &format!("{}", out.display())]); 297 | cmd.args(["-enclave", &format!("{}", enclave.display())]); 298 | cmd.args(["-key", &format!("{}", pem.display())]); 299 | run_cmd(cmd); 300 | } 301 | } 302 | 303 | pub struct EdlBuilder { 304 | imports: Vec, 305 | trusted: Vec, 306 | } 307 | 308 | impl EdlBuilder { 309 | pub fn new() -> Self { 310 | Self { 311 | imports: Vec::new(), 312 | trusted: Vec::new(), 313 | } 314 | } 315 | 316 | pub fn preset_imports(&mut self) -> &mut Self { 317 | self.add_import("sgx_env.edl"); 318 | self.add_import("sgx_sync.edl"); 319 | self.add_import("sgx_stdio.edl"); 320 | self.add_import("sgx_net.edl"); 321 | self.add_import("sgx_fs.edl"); 322 | self.add_import("sgx_thread.edl"); 323 | self.add_import("sgx_process.edl"); 324 | self.add_import("sgx_tstd.edl"); 325 | self.add_import("sgx_cpuid.edl"); 326 | self 327 | } 328 | 329 | pub fn add_import(&mut self, name: &str) -> &mut Self { 330 | self.imports.push(name.into()); 331 | self 332 | } 333 | 334 | pub fn add_trusted(&mut self, data: &str) -> &mut Self { 335 | self.trusted.push(data.into()); 336 | self 337 | } 338 | 339 | pub fn generate(&self, path: &PathBuf) { 340 | let mut data = vec![0_u8; 0]; 341 | writeln!(data, "enclave {{").unwrap(); 342 | for import in &self.imports { 343 | writeln!(data, "\tfrom {:?} import *;", import).unwrap(); 344 | } 345 | writeln!(data, "\ttrusted {{").unwrap(); 346 | for line in &self.trusted { 347 | writeln!(data, "\t\t{}", line).unwrap(); 348 | } 349 | writeln!(data, "\t}};").unwrap(); 350 | writeln!(data, "}};").unwrap(); 351 | 352 | std::fs::write(path, data).unwrap(); 353 | } 354 | } 355 | 356 | fn apply_flags(b: &mut cc::Build, flags: &[&'static str]) { 357 | for flag in flags { 358 | b.flag_if_supported(flag); 359 | } 360 | } 361 | 362 | fn run_cmd(mut cmd: Command) { 363 | match cmd.status() { 364 | Ok(status) => { 365 | if !status.success() { 366 | panic!("exec {:?} failed: {:?}", cmd, status); 367 | } 368 | } 369 | Err(err) => { 370 | panic!("exec {:?} failed: {:?}", cmd, err); 371 | } 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /build-script/src/cutils.rs: -------------------------------------------------------------------------------- 1 | pub struct Cutils {} 2 | 3 | impl Cutils { 4 | pub fn cflags() -> Vec<&'static str> { 5 | let flags = "-Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants -ffunction-sections -fdata-sections -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type -Waddress -Wsequence-point -Wformat-security -Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow -Wcast-align -Wconversion -Wredundant-decls".split(" "); 6 | 7 | let mut cond = vec![ 8 | "-fstack-protector-strong", 9 | "-DITT_fARCH_IA64", 10 | "-fcf-protection", 11 | ]; 12 | cond.extend(flags); 13 | cond 14 | } 15 | 16 | pub fn enclave_cflags() -> Vec<&'static str> { 17 | "-ffreestanding -nostdinc -fvisibility=hidden -fpie -fno-strict-overflow -fno-delete-null-pointer-checks".split(" ").collect() 18 | } 19 | 20 | pub fn enclave_ldflags() -> Vec<&'static str> { 21 | "-Wl,-z,relro,-z,now,-z,noexecstack -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined -Wl,-pie -Wl,--export-dynamic -Wl,--gc-sections".split(" ").collect() 22 | } 23 | } 24 | 25 | pub(crate) fn snake_to_camel(snake: &str) -> String { 26 | let mut camel = String::new(); 27 | let mut upper_next = true; 28 | 29 | for c in snake.chars() { 30 | if c == '_' { 31 | upper_next = true; 32 | } else { 33 | if upper_next { 34 | camel.push(c.to_ascii_uppercase()); 35 | upper_next = false; 36 | } else { 37 | camel.push(c); 38 | } 39 | } 40 | } 41 | 42 | camel 43 | } 44 | -------------------------------------------------------------------------------- /build-script/src/env.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use serde::{Serialize, Deserialize}; 3 | 4 | pub struct Env {} 5 | 6 | #[derive(Debug, Serialize, Deserialize)] 7 | pub struct CargoSgxOutput { 8 | pub version: String, 9 | pub metadata: Vec, 10 | pub std_mode: bool, 11 | } 12 | 13 | #[derive(Debug, Serialize, Deserialize)] 14 | pub struct CargoSgxOutputMetadata { 15 | pub edl: PathBuf, 16 | pub lds: PathBuf, 17 | pub key: PathBuf, 18 | pub config: PathBuf, 19 | pub enclave_archive: PathBuf, 20 | pub output_signed_so: PathBuf, 21 | } 22 | 23 | impl Env { 24 | // run in cargo-sgx 25 | pub fn cargo_sgx_output() -> Option { 26 | let data = get_env("CARGO_SGX_OUTPUT", ""); 27 | if data.is_empty() { 28 | return None; 29 | } 30 | serde_json::from_str(&data).unwrap() 31 | } 32 | 33 | pub fn sgx_builder_path() -> PathBuf { 34 | PathBuf::new().join(env!("AUTOMATA_SGX_BUILDER_DIR")) 35 | } 36 | 37 | pub fn is_64bits() -> bool { 38 | match std::env::var("CARGO_CFG_TARGET_ARCH") { 39 | Ok(n) => n.contains("64"), 40 | Err(_) => cfg!(target_pointer_width = "64"), 41 | } 42 | } 43 | 44 | pub fn sgx_bin_path() -> PathBuf { 45 | Self::sdk_path().join("bin").join(match Env::is_64bits() { 46 | true => "x64", 47 | false => "x86", 48 | }) 49 | } 50 | 51 | pub fn sdk_path() -> PathBuf { 52 | PathBuf::new().join(get_env("SGX_SDK", "/opt/intel/sgxsdk")) 53 | } 54 | 55 | pub fn sdk_root_dir() -> PathBuf { 56 | PathBuf::new().join(env!("TEACLAVE_SGX_SDK_ROOT_DIR")) 57 | } 58 | 59 | pub fn out_dir() -> PathBuf { 60 | PathBuf::new().join(std::env::var("OUT_DIR").unwrap()) 61 | } 62 | 63 | pub fn pkg_name() -> String { 64 | std::env::var("CARGO_PKG_NAME").unwrap() 65 | } 66 | 67 | pub fn sgx_lib_path() -> PathBuf { 68 | let sdk_path = Self::sdk_path(); 69 | match Env::is_64bits() { 70 | true => sdk_path.join("lib64"), 71 | false => sdk_path.join("lib"), 72 | } 73 | } 74 | 75 | pub fn sgx_mode() -> String { 76 | get_env("SGX_MODE", "HW") 77 | } 78 | 79 | pub fn rust_target_path() -> PathBuf { 80 | Self::sdk_root_dir().join("rustlib") 81 | } 82 | 83 | pub fn sgx_target_name() -> String { 84 | "x86_64-automata-linux-sgx".into() 85 | } 86 | 87 | pub fn sgx_target_json() -> PathBuf { 88 | Self::rust_target_path().join(format!("{}.json", Self::sgx_target_name())) 89 | } 90 | 91 | pub fn sgx_common_cflags() -> Vec<&'static str> { 92 | vec![match Env::is_64bits() { 93 | true => "-m64", 94 | false => "-m32", 95 | }] 96 | } 97 | 98 | pub fn custom_edl_path() -> PathBuf { 99 | Self::sdk_root_dir().join("sgx_edl").join("edl") 100 | } 101 | 102 | pub fn custom_common_path() -> PathBuf { 103 | Self::sdk_root_dir().join("common") 104 | } 105 | } 106 | 107 | #[allow(dead_code)] 108 | pub(crate) fn must_get_env(key: &str) -> String { 109 | println!("cargo:rerun-if-env-changed={}", key); 110 | match std::env::var(key) { 111 | Ok(n) => n, 112 | Err(_) => panic!("missing env: {}", key), 113 | } 114 | } 115 | 116 | pub(crate) fn get_env(key: &str, def: &str) -> String { 117 | println!("cargo:rerun-if-env-changed={}", key); 118 | match std::env::var(key) { 119 | Ok(n) => n, 120 | Err(_) => def.into(), 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /build-script/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod builders; 2 | pub use builders::*; 3 | 4 | mod env; 5 | pub use env::*; 6 | 7 | mod cutils; 8 | pub use cutils::*; 9 | 10 | mod sgx_app; 11 | pub use sgx_app::*; 12 | mod std_app; 13 | pub use std_app::*; 14 | 15 | pub fn build_app() { 16 | match Env::cargo_sgx_output() { 17 | Some(n) if !n.std_mode => build_sgx_app(), 18 | _ => build_std_app(), 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /build-script/src/sgx_app.rs: -------------------------------------------------------------------------------- 1 | use crate::{snake_to_camel, BuildMode, Edger8r, EnclaveSharedObjectBuilder, Env, SgxSigner, TrustedProxyBuilder, UntrustedProxyBuilder}; 2 | 3 | pub fn build_sgx_app() { 4 | build_enclave_objs(); 5 | println!( 6 | "cargo:rustc-link-search=native={}", 7 | Env::sgx_lib_path().display() 8 | ); 9 | match Env::sgx_mode().as_str() { 10 | "SIM" | "SW" => println!("cargo:rustc-link-lib=dylib=sgx_urts_sim"), 11 | "HYPER" => println!("cargo:rustc-link-lib=dylib=sgx_urts_hyper"), 12 | "HW" => println!("cargo:rustc-link-lib=dylib=sgx_urts"), 13 | _ => println!("cargo:rustc-link-lib=dylib=sgx_urts"), 14 | } 15 | } 16 | 17 | pub fn build_enclave_objs() { 18 | let pkg_name = std::env::var("CARGO_PKG_NAME").unwrap(); 19 | let cargo_sgx_output = match Env::cargo_sgx_output() { 20 | Some(n) => n, 21 | None => { 22 | println!("cargo:warning={} is intended to build from `cargo sgx build`, please try install it by `cargo install cargo-sgx`", pkg_name); 23 | return; 24 | } 25 | }; 26 | let mode = BuildMode::BuildScript; 27 | let out_dir = Env::out_dir(); 28 | let proxy_trusted_dir = out_dir.join("proxy_trusted"); 29 | let proxy_untrusted_dir = out_dir.join("proxy_untrusted"); 30 | for enclave in &cargo_sgx_output.metadata { 31 | mode.trace_file(&enclave.enclave_archive); 32 | let edl_name = enclave.edl.file_stem().unwrap().to_str().unwrap(); 33 | let enclave_name = enclave 34 | .enclave_archive 35 | .file_stem() 36 | .unwrap() 37 | .to_str() 38 | .unwrap(); 39 | println!( 40 | "cargo:rustc-env=ENCLAVE_{}=1", 41 | snake_to_camel(enclave_name.trim_start_matches("lib")) 42 | ); 43 | let proxy_trusted_source = Edger8r::new(mode).build(&enclave.edl, true, &proxy_trusted_dir); 44 | let proxy_untrusted_source = 45 | Edger8r::new(mode).build(&enclave.edl, false, &proxy_untrusted_dir); 46 | 47 | UntrustedProxyBuilder::new(mode).build( 48 | &proxy_untrusted_source, 49 | &proxy_untrusted_dir.join(format!("{}_u.o", edl_name)), 50 | ); 51 | TrustedProxyBuilder::new(mode).build( 52 | &proxy_trusted_source, 53 | &proxy_trusted_dir.join(format!("{}_t.o", edl_name)), 54 | ); 55 | EnclaveSharedObjectBuilder::new(mode).build( 56 | &proxy_trusted_dir.join(format!("{}_t.o", edl_name)), 57 | &enclave.enclave_archive, 58 | &enclave.lds, 59 | &out_dir.join(format!("{}.so", enclave_name)), 60 | ); 61 | SgxSigner::new(mode).sign( 62 | &enclave.config, 63 | &enclave.output_signed_so, 64 | &out_dir.join(format!("{}.so", enclave_name)), 65 | &enclave.key, 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /build-script/src/std_app.rs: -------------------------------------------------------------------------------- 1 | use crate::Env; 2 | 3 | 4 | pub fn build_std_app() { 5 | use std::{os::unix::fs::symlink, process::Command}; 6 | 7 | let pkg_name = std::env::var("CARGO_PKG_NAME").unwrap(); 8 | let out_dir = Env::out_dir(); 9 | let search_path = out_dir 10 | .parent() 11 | .unwrap() 12 | .parent() 13 | .unwrap() 14 | .parent() 15 | .unwrap(); 16 | 17 | match Env::cargo_sgx_output() { 18 | Some(cargo_sgx_output) => { 19 | println!("cargo:rustc-link-search=native={}", search_path.display()); 20 | for enclave in &cargo_sgx_output.metadata { 21 | let enclave_name = enclave 22 | .enclave_archive 23 | .file_stem() 24 | .unwrap() 25 | .to_str() 26 | .unwrap() 27 | .trim_start_matches("lib"); 28 | 29 | println!( 30 | "cargo:rerun-if-changed={}", 31 | search_path.join(format!("lib{}.a", enclave_name)).display() 32 | ); 33 | println!("cargo:rustc-link-lib={}", enclave_name); 34 | } 35 | } 36 | None => { 37 | println!( 38 | "cargo:warning={} is intended to build from `cargo sgx build`, please try install it by `cargo install cargo-sgx`, now will goto compatibility mode (rebuild everytime)", 39 | pkg_name 40 | ); 41 | // println!("cargo:rerun-if-env-changed=CARGO_BUILD"); 42 | // if std::env::var("CARGO_BUILD") != Ok("1".to_owned()) { 43 | // let note = ["set CARGO_BUILD=1 to enable compatibility mode.", "or you can add automata_sgx_builder::enalbe_compatibility_mode(); to the build script."]; 44 | // println!("cargo:warning=NOTICE:\n\nset CARGO_BUILD=1 to enable compatibility mode. \n\n\n", "=".repeat(80)); 45 | // } 46 | println!("cargo:rerun-if-changed=compatibility mode"); 47 | 48 | let profile = std::env::var("PROFILE").unwrap(); 49 | let origin_target_dir = search_path.parent().unwrap(); 50 | let new_target_dir = origin_target_dir.join("tmp-target"); 51 | let _ = std::fs::create_dir_all(&new_target_dir.join(&profile)); 52 | 53 | let _ = symlink( 54 | &origin_target_dir.join(&profile).join("build"), 55 | new_target_dir.join(&profile).join("build"), 56 | ); 57 | let _ = symlink( 58 | &origin_target_dir.join(&profile).join("deps"), 59 | new_target_dir.join(&profile).join("deps"), 60 | ); 61 | 62 | println!( 63 | "cargo:rustc-link-search=native={}", 64 | new_target_dir.join(&profile).display() 65 | ); 66 | for (lib_name, pkg_name) in get_metadata_pkgs() { 67 | let mut cmd = Command::new(std::env::var("CARGO").unwrap()); 68 | cmd.arg("build"); 69 | if profile == "release" { 70 | cmd.arg("--release"); 71 | } 72 | cmd.arg("--target-dir").arg(&new_target_dir); 73 | cmd.arg("-p").arg(&pkg_name).arg("--color").arg("never"); 74 | assert!(cmd.status().unwrap().success()); 75 | println!("cargo:rustc-link-lib={}", lib_name); 76 | } 77 | return; 78 | } 79 | }; 80 | } 81 | 82 | pub fn get_metadata_pkgs() -> Vec<(String, String)> { 83 | use std::path::PathBuf; 84 | let cwd = std::env::current_dir().unwrap(); 85 | let data = std::fs::read_to_string(PathBuf::new().join(cwd).join("Cargo.toml")).unwrap(); 86 | 87 | let cargo_metadata: toml::Value = toml::from_str(&data).unwrap(); 88 | match cargo_metadata.get("package") { 89 | Some(pkg) => match pkg.get("metadata") { 90 | Some(md) => match md.get("sgx") { 91 | Some(sgx) => { 92 | if let Some(table) = sgx.as_table() { 93 | let mut out = Vec::new(); 94 | for (lib_name, t) in table { 95 | let path = 96 | PathBuf::new().join(t.get("path").unwrap().as_str().unwrap()); 97 | let pkg_name = path.file_stem().unwrap().to_str().unwrap().to_owned(); 98 | out.push((lib_name.clone(), pkg_name)); 99 | } 100 | return out; 101 | } 102 | } 103 | None => {} 104 | }, 105 | None => {} 106 | }, 107 | None => {} 108 | } 109 | Vec::new() 110 | } 111 | 112 | -------------------------------------------------------------------------------- /build_dep.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use std::process::Command; 3 | 4 | pub fn get_teaclave_sdk_path() -> Option { 5 | println!("cargo:rerun-if-env-changed=TEACLAVE_SGX_SDK"); 6 | if let Ok(n) = std::env::var("TEACLAVE_SGX_SDK") { 7 | return Some(PathBuf::new().join(n)); 8 | } 9 | 10 | let mut cmd = Command::new(std::env::var("CARGO").unwrap()); 11 | cmd.args(["metadata"]); 12 | let output = cmd.output().unwrap(); 13 | let output = String::from_utf8_lossy(&output.stdout); 14 | let github_name = "incubator-teaclave-sgx-sdk-9a654826af166474/"; 15 | let idx = output.find(github_name)?; 16 | let start_idx = output[..idx].rfind('"')? + 1; 17 | let output = &output[start_idx..]; 18 | 19 | let start_idx = idx - start_idx + github_name.len(); 20 | let end_idx = output[start_idx..].find("/")? + start_idx; 21 | return Some(PathBuf::new().join(&output[..end_idx])); 22 | } 23 | -------------------------------------------------------------------------------- /docker/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | ubuntu-20.04-image: 3 | image: ghcr.io/automata-network/automata-sgx-sdk:v0.2_ubuntu-20.04 4 | build: 5 | dockerfile: ./ubuntu-20.04.Dockerfile 6 | 7 | ubuntu-22.04-image: 8 | image: ghcr.io/automata-network/automata-sgx-sdk:v0.2_ubuntu-22.04 9 | build: 10 | dockerfile: ./ubuntu-22.04.Dockerfile 11 | -------------------------------------------------------------------------------- /docker/ubuntu-20.04.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 as builder 2 | 3 | LABEL automata.rust_toolchain="nightly-2024-02-01" 4 | LABEL automata.intel_sgx_sdk="2.24.100.3" 5 | LABEL org.opencontainers.image.description="Automata SGX SDK Base Image for Ubuntu 20.04" 6 | 7 | ENV DEBIAN_FRONTEND=noninteractive 8 | 9 | RUN chmod 1777 /tmp && \ 10 | apt update && \ 11 | apt install -y \ 12 | unzip lsb-release debhelper cmake reprepro autoconf automake bison build-essential curl dpkg-dev expect flex gcc-8 gdb \ 13 | git git-core gnupg kmod libboost-system-dev libboost-thread-dev libcurl4-openssl-dev libiptcdata0-dev libjsoncpp-dev \ 14 | liblog4cpp5-dev libprotobuf-dev libssl-dev libtool libxml2-dev ocaml ocamlbuild protobuf-compiler python-is-python3 \ 15 | texinfo uuid-dev vim wget software-properties-common clang perl pkgconf libboost-dev libsystemd0 nlohmann-json3-dev 16 | 17 | RUN rm -rf /var/lib/apt/lists/* 18 | 19 | ENV rust_toolchain nightly-2024-02-01 20 | RUN cd /root && \ 21 | curl 'https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init' --output /root/rustup-init && \ 22 | chmod +x /root/rustup-init && \ 23 | echo '1' | /root/rustup-init --default-toolchain ${rust_toolchain} --profile minimal && \ 24 | echo 'source /root/.cargo/env' >> /root/.bashrc && \ 25 | rm /root/rustup-init && rm -rf /root/.cargo/registry && rm -rf /root/.cargo/git 26 | 27 | ENV VERSION 2.24.100.3-focal1 28 | ENV DCAP_VERSION 1.21.100.3-focal1 29 | ENV SDK_URL="https://download.01.org/intel-sgx/sgx-linux/2.24/distro/ubuntu20.04-server/sgx_linux_x64_sdk_2.24.100.3.bin" 30 | ENV LOCAL_REPO="https://download.01.org/intel-sgx/sgx-linux/2.24/distro/ubuntu20.04-server/sgx_debian_local_repo.tgz" 31 | 32 | RUN cd /root && \ 33 | wget https://download.01.org/intel-sgx/sgx-linux/2.24/as.ld.objdump.r4.tar.gz && \ 34 | tar xzf as.ld.objdump.r4.tar.gz && \ 35 | cp -r external/toolset/ubuntu20.04/* /usr/bin/ && \ 36 | rm -rf ./external ./as.ld.objdump.r4.tar.gz 37 | 38 | RUN cd /opt && \ 39 | curl -LO $LOCAL_REPO && \ 40 | tar zxvf sgx_debian_local_repo.tgz && \ 41 | echo "deb [trusted=yes] file:/opt/sgx_debian_local_repo focal main" | tee /etc/apt/sources.list.d/intel-sgx.list 42 | 43 | RUN cd /root && \ 44 | curl -o sdk.sh $SDK_URL && \ 45 | chmod a+x /root/sdk.sh && \ 46 | echo -e 'no\n/opt' | ./sdk.sh && \ 47 | echo 'source /opt/sgxsdk/environment' >> /root/.bashrc && \ 48 | cd /root && \ 49 | rm ./sdk.sh 50 | 51 | RUN apt-get update && \ 52 | apt-get install -y \ 53 | libsgx-headers=$VERSION \ 54 | libsgx-ae-epid=$VERSION \ 55 | libsgx-ae-le=$VERSION \ 56 | libsgx-ae-pce=$VERSION \ 57 | libsgx-aesm-ecdsa-plugin=$VERSION \ 58 | libsgx-aesm-epid-plugin=$VERSION \ 59 | libsgx-aesm-launch-plugin=$VERSION \ 60 | libsgx-aesm-pce-plugin=$VERSION \ 61 | libsgx-aesm-quote-ex-plugin=$VERSION \ 62 | libsgx-enclave-common=$VERSION \ 63 | libsgx-enclave-common-dev=$VERSION \ 64 | libsgx-epid=$VERSION \ 65 | libsgx-epid-dev=$VERSION \ 66 | libsgx-launch=$VERSION \ 67 | libsgx-launch-dev=$VERSION \ 68 | libsgx-quote-ex=$VERSION \ 69 | libsgx-quote-ex-dev=$VERSION \ 70 | libsgx-uae-service=$VERSION \ 71 | libsgx-urts=$VERSION \ 72 | sgx-aesm-service=$VERSION \ 73 | libsgx-dcap-ql=$DCAP_VERSION \ 74 | libsgx-dcap-ql-dev=$DCAP_VERSION \ 75 | libsgx-dcap-quote-verify=$DCAP_VERSION \ 76 | libsgx-dcap-quote-verify-dev=$DCAP_VERSION \ 77 | libsgx-dcap-default-qpl=$DCAP_VERSION \ 78 | libsgx-dcap-default-qpl-dev=$DCAP_VERSION \ 79 | libsgx-ae-qve=$DCAP_VERSION \ 80 | libsgx-ae-qe3=$DCAP_VERSION \ 81 | libsgx-pce-logic=$DCAP_VERSION \ 82 | libsgx-qe3-logic=$DCAP_VERSION \ 83 | libsgx-ra-network=$DCAP_VERSION \ 84 | libsgx-ra-uefi=$DCAP_VERSION && \ 85 | mkdir /var/run/aesmd && \ 86 | rm -rf /var/lib/apt/lists/* && \ 87 | rm -rf /var/cache/apt/archives/* 88 | 89 | RUN cd /root && \ 90 | git clone https://github.com/automata-network/Azure-DCAP-Client -b 20.04_1.12.3 && \ 91 | cd Azure-DCAP-Client/src/Linux && \ 92 | ./configure && \ 93 | make && \ 94 | make install && \ 95 | rm -f /usr/lib/x86_64-linux-gnu/libdcap_quoteprov.so* && cp /usr/local/lib/libdcap_quoteprov.so /usr/lib/x86_64-linux-gnu 96 | 97 | ENV SGX_SDK='/opt/sgxsdk' 98 | ENV LD_LIBRARY_PATH=/usr/lib:/usr/local/lib 99 | ENV LD_RUN_PATH=/usr/lib:/usr/local/lib 100 | ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/sgxsdk/sdk_libs" 101 | ENV RUSTFLAGS='-L $SGX_SDK/lib64/' 102 | ENV PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.cargo/bin' 103 | ENV PKG_CONFIG_PATH='$SGX_SDK/pkgconfig' 104 | 105 | RUN --mount=type=cache,target=/root/.cargo/registry/index \ 106 | --mount=type=cache,target=/root/.cargo/registry/cache \ 107 | --mount=type=cache,target=/root/.cargo/git \ 108 | rustup component add rust-src --toolchain ${rust_toolchain}-x86_64-unknown-linux-gnu -------------------------------------------------------------------------------- /docker/ubuntu-22.04.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 as builder 2 | 3 | LABEL automata.rust_toolchain="nightly-2024-02-01" 4 | LABEL automata.intel_sgx_sdk="2.24.100.3" 5 | LABEL org.opencontainers.image.description="Automata SGX SDK Base Image for Ubuntu 22.04" 6 | 7 | ENV DEBIAN_FRONTEND=noninteractive 8 | 9 | RUN chmod 1777 /tmp && \ 10 | apt update && \ 11 | apt install -y \ 12 | unzip lsb-release debhelper cmake reprepro autoconf automake bison build-essential curl dpkg-dev expect flex gdb \ 13 | git git-core gnupg kmod libboost-system-dev libboost-thread-dev openssl libcurl4-openssl-dev libiptcdata0-dev libjsoncpp-dev \ 14 | liblog4cpp5-dev libprotobuf-dev libssl-dev libtool libxml2-dev ocaml ocamlbuild protobuf-compiler python-is-python3 \ 15 | texinfo uuid-dev vim wget software-properties-common clang perl pkgconf libboost-dev libsystemd0 nlohmann-json3-dev 16 | 17 | RUN rm -rf /var/lib/apt/lists/* 18 | 19 | ENV rust_toolchain nightly-2024-02-01 20 | RUN cd /root && \ 21 | curl 'https://static.rust-lang.org/rustup/dist/x86_64-unknown-linux-gnu/rustup-init' --output /root/rustup-init && \ 22 | chmod +x /root/rustup-init && \ 23 | echo '1' | /root/rustup-init --default-toolchain ${rust_toolchain} --profile minimal && \ 24 | echo 'source /root/.cargo/env' >> /root/.bashrc && \ 25 | rm /root/rustup-init && rm -rf /root/.cargo/registry && rm -rf /root/.cargo/git 26 | 27 | ENV VERSION 2.24.100.3-jammy1 28 | ENV DCAP_VERSION 1.21.100.3-jammy1 29 | ENV SDK_URL="https://download.01.org/intel-sgx/sgx-linux/2.24/distro/ubuntu22.04-server/sgx_linux_x64_sdk_2.24.100.3.bin" 30 | ENV LOCAL_REPO="https://download.01.org/intel-sgx/sgx-linux/2.24/distro/ubuntu22.04-server/sgx_debian_local_repo.tgz" 31 | 32 | RUN cd /root && \ 33 | wget https://download.01.org/intel-sgx/sgx-linux/2.24/as.ld.objdump.r4.tar.gz && \ 34 | tar xzf as.ld.objdump.r4.tar.gz && \ 35 | cp -r external/toolset/ubuntu20.04/* /usr/bin/ && \ 36 | rm -rf ./external ./as.ld.objdump.r4.tar.gz 37 | 38 | RUN cd /opt && \ 39 | curl -LO $LOCAL_REPO && \ 40 | tar zxvf sgx_debian_local_repo.tgz && \ 41 | echo "deb [trusted=yes] file:/opt/sgx_debian_local_repo jammy main" | tee /etc/apt/sources.list.d/intel-sgx.list 42 | 43 | RUN cd /root && \ 44 | curl -o sdk.sh $SDK_URL && \ 45 | chmod a+x /root/sdk.sh && \ 46 | echo -e 'no\n/opt' | ./sdk.sh && \ 47 | echo 'source /opt/sgxsdk/environment' >> /root/.bashrc && \ 48 | cd /root && \ 49 | rm ./sdk.sh 50 | 51 | RUN apt-get update && \ 52 | apt-get install -y \ 53 | libsgx-headers=$VERSION \ 54 | libsgx-ae-le=$VERSION \ 55 | libsgx-ae-pce=$VERSION \ 56 | libsgx-enclave-common=$VERSION \ 57 | libsgx-enclave-common-dev=$VERSION \ 58 | libsgx-urts=$VERSION \ 59 | libsgx-dcap-ql=$DCAP_VERSION \ 60 | libsgx-dcap-ql-dev=$DCAP_VERSION \ 61 | libsgx-dcap-quote-verify=$DCAP_VERSION \ 62 | libsgx-dcap-quote-verify-dev=$DCAP_VERSION \ 63 | libsgx-dcap-default-qpl=$DCAP_VERSION \ 64 | libsgx-dcap-default-qpl-dev=$DCAP_VERSION \ 65 | libsgx-ae-qve=$DCAP_VERSION \ 66 | libsgx-ae-qe3=$DCAP_VERSION \ 67 | libsgx-pce-logic=$DCAP_VERSION \ 68 | libsgx-qe3-logic=$DCAP_VERSION \ 69 | libsgx-ra-network=$DCAP_VERSION \ 70 | libsgx-ra-uefi=$DCAP_VERSION && \ 71 | mkdir /var/run/aesmd && \ 72 | rm -rf /var/lib/apt/lists/* && \ 73 | rm -rf /var/cache/apt/archives/* 74 | 75 | RUN curl -LO http://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb && dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb 76 | RUN cd /root && \ 77 | git clone https://github.com/automata-network/Azure-DCAP-Client -b 22.04_1.12.3 && \ 78 | cd Azure-DCAP-Client/src/Linux && \ 79 | ./configure && \ 80 | make && \ 81 | make install && \ 82 | rm -f /usr/lib/x86_64-linux-gnu/libdcap_quoteprov.so* && cp /usr/local/lib/libdcap_quoteprov.so /usr/lib/x86_64-linux-gnu 83 | 84 | ENV SGX_SDK='/opt/sgxsdk' 85 | ENV LD_LIBRARY_PATH=/usr/lib:/usr/local/lib 86 | ENV LD_RUN_PATH=/usr/lib:/usr/local/lib 87 | ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/opt/sgxsdk/sdk_libs" 88 | ENV RUSTFLAGS='-L $SGX_SDK/lib64/' 89 | ENV PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.cargo/bin' 90 | ENV PKG_CONFIG_PATH='$SGX_SDK/pkgconfig' 91 | 92 | RUN --mount=type=cache,target=/root/.cargo/registry/index \ 93 | --mount=type=cache,target=/root/.cargo/registry/cache \ 94 | --mount=type=cache,target=/root/.cargo/git \ 95 | rustup component add rust-src --toolchain ${rust_toolchain}-x86_64-unknown-linux-gnu 96 | 97 | WORKDIR /workspace -------------------------------------------------------------------------------- /edl/sgx_dcap.edl: -------------------------------------------------------------------------------- 1 | enclave { 2 | include "sgx_dcap_key_exchange.h" 3 | include "sgx_ql_lib_common.h" 4 | 5 | untrusted { 6 | quote3_error_t dcap_get_target([out] sgx_target_info_t *target); 7 | quote3_error_t dcap_get_quote([in] sgx_report_t *report, size_t out_size, [out, size=25600] uint8_t *msg_out, [out] size_t *filled); 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly-2024-02-01 -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | imports_granularity="Crate" -------------------------------------------------------------------------------- /src/app/enclave.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | use std::sync::Mutex; 3 | 4 | use crate::sgxlib::{sgx_types, sgx_urts}; 5 | 6 | pub use sgx_types::error::SgxStatus; 7 | 8 | pub struct SgxEnclave { 9 | pub debug: bool, 10 | name: String, 11 | enclave: Mutex>>, 12 | } 13 | 14 | impl SgxEnclave { 15 | pub fn new(name: &str) -> Self { 16 | Self { 17 | name: name.to_string(), 18 | debug: std::env::var("SGX_DEBUG").unwrap_or_default() != "".to_string(), 19 | enclave: Mutex::new(None), 20 | } 21 | } 22 | 23 | pub fn camel_to_snake(s: &str) -> String { 24 | let mut snake_case = String::new(); 25 | for (i, c) in s.chars().enumerate() { 26 | if c.is_uppercase() { 27 | if i != 0 { 28 | snake_case.push('_'); 29 | } 30 | for lower in c.to_lowercase() { 31 | snake_case.push(lower); 32 | } 33 | } else { 34 | snake_case.push(c); 35 | } 36 | } 37 | snake_case 38 | } 39 | 40 | pub fn eid(&self) -> Result { 41 | let mut enclave = self.enclave.lock().unwrap(); 42 | match enclave.as_ref() { 43 | None => { 44 | let args = std::env::args().collect::>(); 45 | let enclave_path = PathBuf::new().join(&args[0]).parent().unwrap().join(&self.name); 46 | let result = sgx_urts::enclave::SgxEnclave::create(&enclave_path, self.debug) 47 | .map_err(super::AppError::CreateEnclave(&enclave_path)); 48 | *enclave = Some(result); 49 | match enclave.as_ref().unwrap() { 50 | Ok(result) => Ok(result.eid()), 51 | Err(err) => Err(err.clone()), 52 | } 53 | } 54 | Some(enclave) => match enclave { 55 | Ok(result) => Ok(result.eid()), 56 | Err(err) => Err(err.clone()), 57 | }, 58 | } 59 | } 60 | } 61 | 62 | #[macro_export] 63 | macro_rules! enclave { 64 | ( 65 | name: $enclave_name:ident, 66 | ecall: { 67 | $( 68 | fn $fn_name:ident ( $($arg_name:ident : $arg_type:ty),* ) $(-> $ret_type:ty)?; 69 | )* 70 | } 71 | ) => { 72 | pub struct $enclave_name($crate::app::SgxEnclave); 73 | 74 | extern "C" { 75 | $( 76 | fn $fn_name(eid: $crate::types::EnclaveId, $($arg_name: $arg_type,)* retval: *mut $crate::types::SgxStatus) $(-> $ret_type)?; 77 | )* 78 | } 79 | 80 | impl $enclave_name { 81 | pub fn new() -> Self { 82 | let name = $crate::app::SgxEnclave::camel_to_snake(stringify!($enclave_name)); 83 | env!(concat!("ENCLAVE_", stringify!($enclave_name)), concat!("the enclave ", stringify!($enclave_name) ," is not defined in Cargo.toml")); 84 | 85 | let name = format!("lib{}.signed.so", name); 86 | let enclave = $crate::app::SgxEnclave::new(&name); 87 | Self(enclave) 88 | } 89 | 90 | $( 91 | pub fn $fn_name(&self, $($arg_name: $arg_type),*) -> $crate::app::AppResult<$($ret_type)?> { 92 | use $crate::app::AppError; 93 | let eid = self.0.eid().map_err(AppError::OnEcall(&stringify!($fn_name)))?; 94 | let mut retval = $crate::types::SgxStatus::Success; 95 | let ret = unsafe { 96 | $fn_name(eid, $($arg_name,)* &mut retval) 97 | }; 98 | if retval != $crate::types::SgxStatus::Success { 99 | return Err(retval).map_err(AppError::OnEcall(&stringify!($fn_name))); 100 | } 101 | Ok(ret) 102 | } 103 | )* 104 | } 105 | }; 106 | } 107 | -------------------------------------------------------------------------------- /src/app/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "tstd_app")] 2 | mod enclave; 3 | use std::path::PathBuf; 4 | 5 | #[cfg(feature = "tstd_app")] 6 | pub use enclave::*; 7 | 8 | #[cfg(not(feature = "tstd_app"))] 9 | mod untrusted; 10 | #[cfg(not(feature = "tstd_app"))] 11 | #[allow(unused_imports)] 12 | pub use untrusted::*; 13 | 14 | pub type AppResult = std::result::Result; 15 | 16 | base::stack_error! { 17 | #[derive(Debug, Clone)] 18 | name: AppError, 19 | stack_name: AppErrorStack, 20 | error: { 21 | 22 | }, 23 | wrap: { 24 | Sgx(crate::types::SgxStatus), 25 | }, 26 | stack: { 27 | CreateEnclave(path: PathBuf), 28 | OnEcall(name: &'static str), 29 | } 30 | } -------------------------------------------------------------------------------- /src/app/untrusted.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! enclave { 3 | ( 4 | name: $enclave_name:ident, 5 | ecall: { 6 | $( 7 | fn $fn_name:ident ( $($arg_name:ident : $arg_type:ty),* ) $(-> $ret_type:ty)?; 8 | )* 9 | } 10 | ) => { 11 | pub struct $enclave_name(); 12 | 13 | extern "C" { 14 | $( 15 | fn $fn_name($($arg_name: $arg_type,)* retval: *mut $crate::types::SgxStatus) $(-> $ret_type)?; 16 | )* 17 | } 18 | 19 | impl $enclave_name { 20 | pub fn new() -> Self { 21 | $enclave_name() 22 | } 23 | 24 | $( 25 | pub fn $fn_name(&self, $($arg_name: $arg_type),*) -> $crate::app::AppResult<$($ret_type)?> { 26 | eprintln!("{}", "=".repeat(80)); 27 | eprintln!("WARNING: Currently running in untrusted mode, for development use only"); 28 | eprintln!("{}", "=".repeat(80)); 29 | let mut retval = $crate::types::SgxStatus::Success; 30 | let ret = unsafe { 31 | $fn_name($($arg_name,)* &mut retval) 32 | }; 33 | if retval != $crate::types::SgxStatus::Success { 34 | return Err(retval.into()); 35 | } 36 | Ok(ret) 37 | } 38 | )* 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/dcap/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(all(feature = "dcap", not(target_vendor = "teaclave")))] 2 | mod untrusted; 3 | #[cfg(all(feature = "dcap", not(target_vendor = "teaclave")))] 4 | pub use untrusted::*; 5 | 6 | #[cfg(all(feature = "dcap", target_vendor = "teaclave"))] 7 | mod trusted; 8 | #[cfg(all(feature = "dcap", target_vendor = "teaclave"))] 9 | pub use trusted::*; 10 | 11 | pub type Result = core::result::Result; 12 | 13 | base::stack_error! { 14 | name: DcapError, 15 | stack_name: DcapErrorStack, 16 | error: { 17 | Quote3(String), 18 | Unsupported, 19 | }, 20 | stack: { 21 | GetTarget(), 22 | CreateReport(), 23 | GetQuote(), 24 | } 25 | } 26 | 27 | #[cfg(all(feature = "dcap", target_vendor = "teaclave"))] 28 | mod api { 29 | // trusted 30 | use super::*; 31 | 32 | impl From for DcapError { 33 | fn from(err: sgx_dcap_ql_rs::quote3_error_t) -> DcapError { 34 | DcapError::Quote3(format!("{:?}", err)) 35 | } 36 | } 37 | 38 | pub fn dcap_quote(data: [u8; 64]) -> Result> { 39 | let target = Dcap::get_target().map_err(DcapError::GetTarget())?; 40 | let report = Dcap::create_report(target, data).map_err(DcapError::CreateReport())?; 41 | let quote = Dcap::get_quote(&report).map_err(DcapError::GetQuote())?; 42 | Ok(quote) 43 | } 44 | } 45 | 46 | #[cfg(any( 47 | not(feature = "dcap"), 48 | all(feature = "dcap", not(target_vendor = "teaclave")) 49 | ))] 50 | mod api { 51 | // untrusted 52 | use super::*; 53 | 54 | pub fn dcap_quote(_data: [u8; 64]) -> Result> { 55 | Err(DcapError::Unsupported) 56 | } 57 | } 58 | 59 | pub use api::*; 60 | -------------------------------------------------------------------------------- /src/dcap/trusted.rs: -------------------------------------------------------------------------------- 1 | use sgx_dcap_ql_rs::{quote3_error_t, sgx_report_t, sgx_target_info_t}; 2 | use super::Result; 3 | 4 | extern "C" { 5 | fn dcap_get_target(retval: &mut quote3_error_t, target: &mut sgx_target_info_t); 6 | fn dcap_get_quote( 7 | retval: &mut quote3_error_t, 8 | target: &sgx_report_t, 9 | out_size: usize, 10 | out: *mut u8, 11 | filled: *mut usize, 12 | ); 13 | } 14 | 15 | pub struct Dcap {} 16 | 17 | impl Dcap { 18 | pub fn get_target() -> Result { 19 | let mut target = sgx_target_info_t::default(); 20 | let mut ret = quote3_error_t::SGX_QL_SUCCESS; 21 | unsafe { dcap_get_target(&mut ret, &mut target) }; 22 | 23 | if ret == quote3_error_t::SGX_QL_SUCCESS { 24 | Ok(target) 25 | } else { 26 | Err(ret.into()) 27 | } 28 | } 29 | 30 | pub fn create_report(target: sgx_target_info_t, data: [u8; 64]) -> Result { 31 | use crate::sgxlib::sgx_trts::se::{AlignReport, AlignReportData, AlignTargetInfo}; 32 | 33 | let target = AlignTargetInfo(unsafe { std::mem::transmute(target) }); 34 | let report_data = { AlignReportData(unsafe { std::mem::transmute(data) }) }; 35 | let result = AlignReport::for_target(&target, &report_data).unwrap(); 36 | Ok(unsafe { std::mem::transmute(result.0) }) 37 | } 38 | 39 | pub fn get_quote(report: &sgx_report_t) -> Result> { 40 | let mut out = vec![0_u8; 25600]; 41 | let mut ret = quote3_error_t::SGX_QL_SUCCESS; 42 | let mut filled = 0; 43 | unsafe { dcap_get_quote(&mut ret, report, out.len(), out.as_mut_ptr(), &mut filled) }; 44 | 45 | if ret == quote3_error_t::SGX_QL_SUCCESS { 46 | out.truncate(filled); 47 | Ok(out) 48 | } else { 49 | Err(ret.into()) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/dcap/untrusted.rs: -------------------------------------------------------------------------------- 1 | use sgx_dcap_ql_rs::{ 2 | quote3_error_t, sgx_qe_get_quote, sgx_qe_get_target_info, sgx_report_t, sgx_target_info_t, 3 | }; 4 | 5 | #[no_mangle] 6 | pub unsafe extern "C" fn dcap_get_target(target: *mut sgx_target_info_t) -> quote3_error_t { 7 | sgx_qe_get_target_info(target.as_mut().unwrap()) 8 | } 9 | 10 | #[no_mangle] 11 | pub unsafe extern "C" fn dcap_get_quote( 12 | report: *const sgx_report_t, 13 | out_size: usize, 14 | out: *mut u8, 15 | fill_out_len: *mut usize, 16 | ) -> quote3_error_t { 17 | let (err, quote) = sgx_qe_get_quote(report.as_ref().unwrap()); 18 | let quote = quote.unwrap_or_default(); 19 | if quote.len() > out_size { 20 | println!("buffer too small"); 21 | panic!(); 22 | } 23 | *fill_out_len = quote.len(); 24 | let msg_out = std::slice::from_raw_parts_mut(out, quote.len()); 25 | msg_out.copy_from_slice("e); 26 | err 27 | } 28 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(target_vendor = "teaclave", feature(rustc_private))] 2 | #![feature(panic_unwind)] 3 | 4 | pub mod sgxlib; 5 | pub mod types; 6 | 7 | mod patch; 8 | 9 | pub mod app; 10 | pub mod dcap; 11 | pub mod tse; 12 | 13 | pub use ctor::ctor; 14 | 15 | #[cfg(feature = "builder")] 16 | pub use automata_build_script::*; -------------------------------------------------------------------------------- /src/patch.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "dummy_pthread_atfork")] 2 | #[no_mangle] 3 | pub unsafe extern "C" fn pthread_atfork( 4 | _: Option, 5 | _: Option, 6 | _: Option, 7 | ) -> std::ffi::c_int { 8 | 0 9 | } 10 | 11 | #[cfg(feature = "patch_assert_fail")] 12 | #[no_mangle] 13 | pub extern "C" fn __assert_fail( 14 | __assertion: *const u8, 15 | __file: *const u8, 16 | __line: u32, 17 | __function: *const u8, 18 | ) -> ! { 19 | use std::ffi::CStr; 20 | use crate::sgxlib::sgx_libc::abort; 21 | 22 | let assertion = unsafe { CStr::from_ptr(__assertion as *const _).to_str() } 23 | .expect("__assertion is not a valid c-string!"); 24 | let file = unsafe { CStr::from_ptr(__file as *const _).to_str() } 25 | .expect("__file is not a valid c-string!"); 26 | let line = unsafe { CStr::from_ptr(__line as *const _).to_str() } 27 | .expect("__line is not a valid c-string!"); 28 | let function = unsafe { CStr::from_ptr(__function as *const _).to_str() } 29 | .expect("__function is not a valid c-string!"); 30 | println!("{}:{}:{}:{}", file, line, function, assertion); 31 | 32 | unsafe { abort() } 33 | } 34 | -------------------------------------------------------------------------------- /src/sgxlib.rs: -------------------------------------------------------------------------------- 1 | 2 | #[cfg(all(feature = "sgx_trts", target_vendor = "teaclave"))] 3 | pub extern crate sgx_trts; 4 | 5 | #[cfg(feature = "sgx_types")] 6 | pub extern crate sgx_types; 7 | 8 | #[cfg(feature = "sgx_libc")] 9 | pub extern crate sgx_libc; 10 | 11 | #[cfg(all(feature = "sgx_urts", not(target_vendor = "teaclave")))] 12 | pub use sgx_urts; 13 | 14 | #[cfg(feature = "sgx_alloc")] 15 | pub use sgx_alloc; 16 | 17 | #[cfg(feature = "sgx_crypto")] 18 | pub use sgx_crypto; 19 | 20 | #[cfg(feature = "sgx_dcap")] 21 | pub use sgx_dcap; 22 | 23 | #[cfg(feature = "sgx_dcap_ra_msg")] 24 | pub use sgx_dcap_ra_msg; 25 | 26 | #[cfg(feature = "sgx_dcap_tkey_exchange")] 27 | pub use sgx_dcap_tkey_exchange; 28 | 29 | #[cfg(feature = "sgx_dcap_tvl")] 30 | pub use sgx_dcap_tvl; 31 | 32 | #[cfg(feature = "sgx_demangle")] 33 | pub use sgx_demangle; 34 | 35 | #[cfg(feature = "sgx_edl")] 36 | pub use sgx_edl; 37 | 38 | #[cfg(feature = "sgx_ffi")] 39 | pub use sgx_ffi; 40 | 41 | #[cfg(feature = "sgx_ukey_exchange")] 42 | pub use sgx_ukey_exchange; 43 | 44 | #[cfg(feature = "sgx_tkey_exchange")] 45 | pub use sgx_tkey_exchange; 46 | 47 | #[cfg(feature = "sgx_ra_msg")] 48 | pub use sgx_ra_msg; 49 | 50 | #[cfg(feature = "sgx_no_tstd")] 51 | pub use sgx_no_tstd; 52 | 53 | #[cfg(feature = "sgx_rand")] 54 | pub use sgx_rand; 55 | 56 | #[cfg(feature = "sgx_tse")] 57 | pub use sgx_tse; 58 | 59 | #[cfg(feature = "sgx_unwind")] 60 | pub use sgx_unwind; -------------------------------------------------------------------------------- /src/tse/api_trusted.rs: -------------------------------------------------------------------------------- 1 | use crate::sgxlib::{ 2 | sgx_tse::EnclaveKey, 3 | sgx_types::{error::SgxResult, types::KeyRequest}, 4 | }; 5 | 6 | pub fn get_key(key_request: &KeyRequest) -> SgxResult<[u8; 16]> { 7 | key_request.get_key() 8 | } 9 | -------------------------------------------------------------------------------- /src/tse/api_untrusted.rs: -------------------------------------------------------------------------------- 1 | use crate::sgxlib::sgx_types::{ 2 | error::{SgxResult, SgxStatus}, 3 | types::KeyRequest, 4 | }; 5 | 6 | pub fn get_key(key_request: &KeyRequest) -> SgxResult<[u8; 16]> { 7 | Err(SgxStatus::UnsupportedFeature) 8 | } 9 | -------------------------------------------------------------------------------- /src/tse/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(all(feature = "tse", target_vendor = "teaclave"))] 2 | mod api_trusted; 3 | #[cfg(all(feature = "tse", target_vendor = "teaclave"))] 4 | pub use api_trusted::*; 5 | 6 | 7 | #[cfg(any( 8 | not(feature = "tse"), 9 | all(feature = "tse", not(target_vendor = "teaclave")) 10 | ))] 11 | mod api_untrusted; 12 | #[cfg(any( 13 | not(feature = "tse"), 14 | all(feature = "tse", not(target_vendor = "teaclave")) 15 | ))] 16 | pub use api_untrusted::*; 17 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | pub use crate::sgxlib::sgx_types::{ 2 | error::{SgxResult, SgxStatus}, 3 | types::EnclaveId, 4 | }; 5 | -------------------------------------------------------------------------------- /sysroot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "automata-sgx-sdk-sysroot" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | -------------------------------------------------------------------------------- /sysroot/build.rs: -------------------------------------------------------------------------------- 1 | include!("../build_dep.rs"); 2 | 3 | fn main() { 4 | #[cfg(not(target_vendor = "teaclave"))] 5 | build_sysroot(); 6 | } 7 | 8 | fn build_sysroot() { 9 | let sgx_target = "x86_64-automata-linux-sgx"; 10 | 11 | let out_dir = PathBuf::new().join(std::env::var("OUT_DIR").unwrap()); 12 | if out_dir.as_os_str().to_str().unwrap().contains(sgx_target) { 13 | return; 14 | } 15 | 16 | println!("cargo:rerun-if-env-changed=SGX_MODE"); 17 | 18 | let sdk_path = get_teaclave_sdk_path().expect("unable to locate teaclave_sdk"); 19 | let rust_target_path = sdk_path.join("rustlib"); 20 | std::fs::write( 21 | out_dir.join("TEACLAVE_SGX_SDK_ROOT_DIR"), 22 | sdk_path.to_str().unwrap(), 23 | ) 24 | .unwrap(); 25 | let target = rust_target_path.join(format!("{}.json", sgx_target)); 26 | 27 | let sysroot = PathBuf::new() 28 | .join(std::env::var("OUT_DIR").unwrap()) 29 | .join("sysroot"); 30 | println!( 31 | "cargo:warning=building enclave sysroot to {:?}, source={:?}", 32 | sysroot.display(), 33 | sdk_path.display(), 34 | ); 35 | // may cause deadlock when called by cargo-sgx 36 | let mut cmd = Command::new(std::env::var("CARGO").unwrap()); 37 | cmd.args(["build", "--manifest-path"]); 38 | cmd.arg(format!("{}/std/Cargo.toml", rust_target_path.display())); 39 | cmd.args([ 40 | "-Z", 41 | "build-std=core,alloc", 42 | "--release", 43 | "--features", 44 | "env,net,thread,untrusted_time,untrusted_fs,unsupported_process,capi,backtrace", 45 | "--target-dir", 46 | &format!("{}", sysroot.join("target").display()), 47 | ]); 48 | cmd.arg("--target"); 49 | cmd.arg(format!("{}", target.display())); 50 | assert!(cmd.status().unwrap().success()); 51 | 52 | let std_target_path = PathBuf::new() 53 | .join(std::env::var("OUT_DIR").unwrap()) 54 | .join("sysroot") 55 | .join("target") 56 | .join(sgx_target) 57 | .join("release") 58 | .join("deps"); 59 | 60 | let sysroot = PathBuf::new() 61 | .join(std::env::var("OUT_DIR").unwrap()) 62 | .join("sysroot") 63 | .join("lib") 64 | .join("rustlib") 65 | .join(sgx_target) 66 | .join("lib"); 67 | let _ = std::fs::remove_file(&sysroot); 68 | std::fs::create_dir_all(sysroot.parent().unwrap()).unwrap(); 69 | std::os::unix::fs::symlink(std_target_path, &sysroot).unwrap(); 70 | } 71 | -------------------------------------------------------------------------------- /sysroot/src/main.rs: -------------------------------------------------------------------------------- 1 | pub fn main() { 2 | println!("dummy lib"); 3 | } --------------------------------------------------------------------------------