Intel-SGX TEE
Amit Nadiger
Polyglot(Rust??, C++ 11,14,17,20, C, Kotlin, Java) Android TV, Cas, Blockchain, Polkadot, UTXO, Substrate, Wasm, Proxy-wasm,AndroidTV, Dvb, STB, Linux, Engineering management.
Intel SGX (Software Guard Extensions) is a set of hardware-based security features that enable applications to run in a secure enclave, protected from the rest of the system. SGX provides a trusted execution environment (TEE) for applications, ensuring that sensitive data and processes are protected from potential attacks.
SGX is designed to protect code and data from being accessed or modified by unauthorized users, even if the operating system, hypervisor, or other system components are compromised. SGX achieves this by creating a secure enclave in memory, which is a protected area of memory that is inaccessible to the rest of the system.
In this article, we will discuss the architecture and features of Intel SGX, as well as its advantages and limitations.
Architecture of Intel SGX:
The architecture of Intel SGX consists of three main components:
- Enclave(General meaning Territorial discontinuity): An enclave is a protected area of memory that is created by the application and is isolated from the rest of the system. The enclave can only be accessed by the application and is protected from other applications, the operating system, and even the hypervisor.
- Enclave Page Cache (EPC): The Enclave Page Cache is a section of memory that is used to store the code and data of the enclave. The EPC is protected from other applications and the operating system, ensuring that the enclave is secure.
- Processor: The processor is responsible for creating and managing the enclave and the EPC. The processor ensures that the enclave is protected from unauthorized access and that the code and data in the EPC are secure.
Features of Intel SGX:
Intel SGX provides several features that enable applications to run securely in an enclave:
- Confidentiality: SGX ensures that data in the enclave is kept confidential and cannot be accessed by unauthorized users.
- Integrity: SGX ensures that code and data in the enclave are protected from modification by unauthorized users.
- Authentication: SGX provides a mechanism for authenticating the enclave, ensuring that it is trusted and has not been tampered with.
- Remote attestation: SGX provides a mechanism for remote attestation, which enables a remote party to verify the identity and integrity of an enclave.
Enclave execution flow:
The execution flow for a secure enclave in a Trusted Execution Environment (TEE) typically involves the following steps:
- Enclave creation: The enclave is created by the trusted system software, which sets up the initial environment for the enclave to run in. The system software also provides a secure channel for the enclave to communicate with the outside world.
- Enclave initialization: The enclave initializes its own environment, setting up memory allocation and other resources as necessary. During this stage, the enclave can also establish its own secure channels for communicating with other enclaves or with the outside world.
- Enclave execution: The enclave runs its own code within the secure environment provided by the TEE. The TEE provides strong isolation and protection for the enclave, ensuring that its code and data cannot be accessed by untrusted software or hardware.
- Enclave exit: When the enclave is done executing, it exits and returns control to the trusted system software. The system software can then perform any necessary cleanup and securely delete any sensitive data that the enclave was using.
Throughout the entire execution flow, the TEE ensures that the enclave is running in a secure environment, protecting its code and data from any potential attacks or compromises. The TEE also provides a mechanism for the enclave to securely communicate with the outside world, allowing it to perform useful work while still maintaining a high level of security.
(Copied from overview-of-intel-sgx-enclave-637284.pdf )
High-level overview of the steps involved in using an Intel SGX enclave:
- Install the Intel SGX SDK and related software on your development machine.
- Write the enclave code in a language supported by the SGX SDK (currently C, C++, or Rust).
- Compile the enclave code into a signed binary using the SGX SDK tools.
- Write the application code that will interact with the enclave, using the SGX SDK APIs to load and communicate with the enclave.
- Compile the application code using the SGX SDK tools, linking against the SGX runtime libraries.
- Run the application on an Intel SGX-enabled system, ensuring that the system is properly configured to support SGX.
Here's an example of how you might write an Intel SGX enclave and a simple application that interacts with it. This example assumes that you're using C and the SGX SDK.
Below is enclave code that defines an enclave function that takes an input string and returns a modified version of the string:
#include "sgx_tcrypto.h"
#include "sgx_trts.h"
#include "sgx_utils.h"
#define MAX_BUF_LEN 1024 sgx_status_t SGX_CDECL ecall_modify_string(char* input, char* output, size_t max_output_len) {
sgx_status_t ret = SGX_SUCCESS;
// Verify that the input buffer is within the enclave's address space
if (!sgx_is_within_enclave(input, strlen(input) + 1)) {
ret = SGX_ERROR_INVALID_PARAMETER;
goto cleanup;
}
// Verify that the output buffer is within the enclave's address space
if (!sgx_is_within_enclave(output, max_output_len)) {
ret = SGX_ERROR_INVALID_PARAMETER;
goto cleanup;
}
// Modify the input string
snprintf(output, max_output_len, "Modified: %s", input);
cleanup:
return ret;
}
This function takes two char pointers, one for the input string and one for the output string, and a size_t value indicating the maximum length of the output string. Inside the function, we use SGX SDK APIs to verify that the input and output buffers are within the enclave's address space (to prevent potential buffer overflow attacks), and then we modify the input string and write the result to the output buffer.
Next, we need to compile the enclave code into a signed binary. We can do this using the SGX SDK tools. Assuming that we've saved the above code in a file called enclave.c, we can compile it as follows:
sgx_edger8r --trusted enclave.edl --trusted-dir . --untrusted-dir . --untrusted enclave_u.c
sgx-gcc -c enclave.c -o enclave.o -I. -I/opt/intel/sgxsdk/include
sgx-gcc -c enclave_u.c -o enclave_u.o -I. -I/opt/intel/sgxsdk/include
sgx-ld -m elf_x86_64 -s enclave.lds enclave.o enclave_u.o -o enclave.so -L/opt/intel/sgxsdk/lib64 -lsgx_tstdc -lsgx_tcrypto -lsgx_trts
sgx_sign sign -key Enclave_private.pem -enclave enclave.so -out enclave.signed.so -config Enclave.config.xml
These commands generate a signed binary called enclave.signed.so, which we can load and run inside the enclave.
Below is application code that loads the enclave and calls the `ecall_modify' function
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "enclave_u.h"
#include <sgx_urts.h>
#define ENCLAVE_FILE "enclave.signed.so"
int main(int argc, char const *argv[])
{
sgx_enclave_id_t eid;
sgx_status_t ret;
/* Initialize the enclave */
ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, NULL, NULL, &eid, NULL);
if (ret != SGX_SUCCESS) {
printf("Failed to create enclave: %d\n", ret);
return 1;
}
/* Call the ecall_modify() function */
const char* message = "Hello, Enclave!";
size_t message_len = strlen(message);
char* encrypted_message = NULL;
size_t encrypted_len = 0;
ret = ecall_modify(eid, message, message_len, &encrypted_message, &encrypted_len);
if (ret != SGX_SUCCESS) {
printf("Failed to call ecall_modify(): %d\n", ret);
goto cleanup;
}
/* Print the encrypted message */
printf("Encrypted message: ");
for (int i = 0; i < encrypted_len; i++) {
printf("%02x", encrypted_message[i]);
}
printf("\n");
/* Destroy the enclave */
ret = sgx_destroy_enclave(eid);
if (ret != SGX_SUCCESS) {
printf("Failed to destroy enclave: %d\n", ret);
return 1;
}
return 0;
cleanup:
sgx_destroy_enclave(eid);
return 1;
}
The above code initializes the enclave, calls the ecall_modify function inside the enclave, prints the encrypted message returned by the function, and destroys the enclave.
To compile the application, we need to link the libsgx_urts.so library and include the enclave_u.h header file, which contains the generated ecall and ocall functions. Here's an example of how to compile the application:
$ gcc -o app app.c enclave_u.c -L/opt/intel/sgxsdk/lib64 -lsgx_urts
Note that we're linking against the libsgx_urts.so library that's installed as part of the SGX SDK.
Finally, to run the application, we need to set the LD_LIBRARY_PATH environment variable to point to the location of the SGX libraries. Here's an example of how to run the application:
$ LD_LIBRARY_PATH=/opt/intel/sgxsdk/lib64 ./app
This will output the encrypted message returned by the enclave.
How to Implement the pallets based on Substrate and inside Intel SGX
Substrate is a blockchain development framework that allows developers to create their own blockchain using a modular design. The framework is built in Rust and provides a set of libraries, tools, and primitives that can be used to build a customized blockchain solution.
Implementing pallets based on Substrate inside Intel SGX can provide additional security to the blockchain application by ensuring the confidentiality and integrity of the sensitive data stored inside the enclave. Here are the steps to implement pallets based on Substrate inside Intel SGX:
- Set up the development environment for Intel SGX by installing the SGX SDK and the Rust SGX SDK.
- Create a new Substrate-based blockchain project using the Substrate CLI.
- Implement the pallets that need to be executed inside the SGX enclave using the Rust SGX SDK. The implementation of the pallets should use the APIs provided by the SGX SDK to securely access the data inside the enclave.
- Build the SGX enclave binary using the Rust SGX SDK.
- Integrate the SGX enclave binary with the Substrate runtime by implementing the necessary runtime APIs that allow the runtime to interact with the SGX enclave.
- Deploy the blockchain network with the modified runtime and the SGX-enabled pallets.
To implement pallets based on Substrate inside Intel SGX, we can follow the steps below:
- Set up a Substrate node: To set up a Substrate node, we can follow the instructions provided by the Substrate documentation. This involves installing Rust, initializing a new Substrate node using the Substrate CLI, and running the node.
- Define a new pallet: In Substrate, a pallet is a module that can be added to the blockchain. To define a new pallet, we can create a new Rust module and define the necessary functions and data structures.
- Create an SGX enclave: To create an SGX enclave, we can use the SGX SDK and follow the instructions provided by Intel. This involves writing the enclave code in C or C++, defining the enclave configuration, and compiling the enclave code.
- Integrate the enclave with Substrate: To integrate the enclave with Substrate, we need to create a new runtime module that interfaces with the SGX enclave. This module should define functions that can be called by the Substrate node and that invoke the functions defined in the SGX enclave.
- Test the implementation: Once the integration is complete, we can test the implementation by running the Substrate node and interacting with the pallets defined in the SGX enclave.
Here is an example code that demonstrates how to implement a simple pallet using SGX enclave inside Substrate:
- Define the pallet in Rust:
// Define the storage for the pallet
pub trait Trait: frame_system::Trait {}
impl pallet_example::Trait for Runtime {
type Event = Event;
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
// Define the functions for the pallet
#[weight = 0]
pub fn multiply_numbers(origin, num1: u32, num2: u32) -> dispatch::DispatchResult {
let _sender = ensure_signed(origin)?;
// Invoke the SGX enclave to multiply the numbers
let mut result = [0u8; 4];
let input1 = &num1.to_le_bytes()[..];
let input2 = &num2.to_le_bytes()[..];
let input = [input1, input2].concat();
let mut command = TEEC_Operation::new(0, input.as_ptr() as *mut _, input.len() as u32, result.as_mut_ptr() as *mut _, result.len() as u32);
let mut context = TEEC_Context::new();
let mut session = TEEC_Session::new();
let res = unsafe {
TEEC_InitializeContext(ptr::null_mut(), &mut context);
TEEC_OpenSession(&mut context, &mut session, &UUID, TEEC_LOGIN_PUBLIC, ptr::null_mut(), ptr::null_mut(), ptr::null_mut());
TEEC_InvokeCommand(&mut session, TA_MULTIPLY, &mut command, ptr::null_mut());
TEEC_CloseSession(&mut session);
TEEC_FinalizeContext(&mut context);
result[0] as u32 + (result[1] as u32) << 8 + (result[2] as u32) << 16 + (result[3] as u32) << 24
};
Ok(())
}
}
}
领英推è
Explanation of the above code:
- pub trait Trait: frame_system::Trait {}: This is a trait definition that defines the requirements for the runtime configuration for the pallet. In this case, it requires frame_system::Trait to be implemented by the runtime.
- impl pallet_example::Trait for Runtime: This implements the Trait for the Runtime struct, where pallet_example is the name of the pallet.
- decl_module!: This is a macro that generates the module implementation for the pallet. It takes a generic type parameter T which implements the Trait.
- pub struct Module<T: Trait> for enum Call where origin: T::Origin: This defines the Module struct which holds the functions and storage for the pallet. It takes a generic type parameter T which implements the Trait and also specifies that the Call enum is used for function dispatch and that the origin type is T::Origin.
- #[weight = 0]: This is an attribute macro that defines the weight of the function for runtime resource allocation.
- pub fn multiply_numbers(origin, num1: u32, num2: u32) -> dispatch::DispatchResult: This is a public function that takes in three parameters: origin of type T::Origin, num1 of type u32, and num2 of type u32. It returns a dispatch::DispatchResult which indicates if the function was successful or not.
- let _sender = ensure_signed(origin)?;: This ensures that the origin is signed and assigns it to _sender.
- let mut result = [0u8; 4];: This creates a mutable array of size 4 bytes and initializes it with 0.
- let input1 = &num1.to_le_bytes()[..];: This converts num1 to little-endian byte order and assigns it to input1.
- let input2 = &num2.to_le_bytes()[..];: This converts num2 to little-endian byte order and assigns it to input2.
- let input = [input1, input2].concat();: This concatenates input1 and input2 arrays into a single array input.
- let mut command = TEEC_Operation::new(0, input.as_ptr() as *mut _, input.len() as u32, result.as_mut_ptr() as *mut _, result.len() as u32);: This creates a new TEEC_Operation object with input and output parameters.
- let mut context = TEEC_Context::new();: This creates a new TEEC_Context object.
- let mut session = TEEC_Session::new();: This creates a new TEEC_Session object.
- TEEC_InitializeContext(ptr::null_mut(), &mut context);: This initializes the context with default values.
- TEEC_OpenSession(&mut context, &mut session, &UUID, TEEC_LOGIN_PUBLIC, ptr::null_mut(), ptr::null_mut(), ptr::null_mut());: This opens a new session with the SGX enclave using the public login type.
- TEEC_InvokeCommand(&mut session, TA_MULTIPLY, &mut command, ptr::null_mut());: This invokes the command with ID TA_MULTIPLY using the session and command objects.
- TEEC_CloseSession(&mut session);: This closes the session.
- `TEEC_FinalizeContext(&mut context);
2. Define the enclave function in C:
#include <stdio.h>
#include<stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <tee_internal_api.h>
#include <tee_internal_api_extensions.h>
#include <utee_defines.h>
#include "enclave_ta.h"
static TEE_Result multiply(TEE_Param p[4])
{
if (p[0].value.a != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
TEE_PARAM_TYPE_VALUE_INPUT,
TEE_PARAM_TYPE_VALUE_OUTPUT,
TEE_PARAM_TYPE_NONE))
return TEE_ERROR_BAD_PARAMETERS;
TEE_Param *in = &p[1];
TEE_Param *out = &p[2];
out->value.a = in->value.a * in->value.b;
return TEE_SUCCESS;
}
TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext,
uint32_t commandID,
uint32_t paramTypes,
TEE_Param params[4])
{
(void)&sessionContext; /* unused parameter */
switch (commandID)
{
case TA_MULTIPLY:
return multiply(params);
default:
return TEE_ERROR_BAD_PARAMETERS;
}
}
This defines a function multiply that multiplies the two input values a and b, and stores the result in the output value c. The function is called by the enclave when the TA_MULTIPLY command is invoked by the client application.
The TA_InvokeCommandEntryPoint function is the entry point for the Trusted Application, and it routes commands to the appropriate function based on the command ID. In this case, it calls the multiply function if the command ID is TA_MULTIPLY.
SGX SDK is available and can be run on your local machine. However, note that SGX requires specific hardware features that not all processors have, so you'll need to ensure that your processor supports SGX before attempting to use it.
Steps involved in the flow between an untrusted application and an enclave application:
- First, the untrusted application is loaded and executes in the normal application memory space.
- Next, the untrusted application establishes a secure channel with the Intel SGX Enclave.
- To establish a secure channel, the untrusted application calls the sgx_create_enclave() function, which loads the enclave into a protected memory area.
- After the enclave is loaded, the untrusted application can call functions within the enclave, known as Enclave Calls (ECALLs), by passing parameters and control to the enclave using the secure channel established in step 2.
- The enclave executes the requested ECALL and returns any output or results to the untrusted application using the secure channel.
- Finally, when the untrusted application is done communicating with the enclave, it calls the sgx_destroy_enclave() function to unload the enclave and free the associated memory.
Here is an example code snippet for establishing a secure channel between an untrusted application and an enclave using the sgx_create_enclave() function:
sgx_enclave_id_t enclave_id = 0;
sgx_launch_token_t launch_token = {0};
int token_updated = 0;
// Step 2: Establish a secure channel with the enclave
sgx_status_t ret = sgx_create_enclave("enclave.signed.so",
SGX_DEBUG_FLAG,
&launch_token,
&token_updated,
&enclave_id,
NULL);
if (ret != SGX_SUCCESS) {
// Handle error
}
// Step 4: Call an ECALL within the enclave
int input = 5;
int output = 0;
ret = ecall_modify_value(enclave_id, input, &output);
if (ret != SGX_SUCCESS) {
// Handle error
}
// Step 5: Retrieve output from the enclave
printf("Enclave returned %d\n", output);
// Step 6: Unload the enclave
sgx_destroy_enclave(enclave_id);
Note that this is a simplified example and the actual implementation may involve additional steps depending on the specific requirements of the application.
Regarding your question about the availability of the Intel SGX SDK, yes, it is available for download on the official Intel website and can be used on a local machine. However, it requires specific hardware support for Intel SGX, such as an Intel SGX-enabled processor, and may not be supported on all systems.
How to confirm whether your processor supports Intel SGX by checking its specifications. Here are the steps to do so:
- Identify the model of your processor. You can find this information by going to your computer's System Information or Device Manager, or by running a tool like CPU-Z.
- Look up the specifications of your processor on the Intel website. You can search for your processor by name or by using Intel's processor specification tool.
- Check whether the processor supports Intel SGX. This information will be listed under the Security and Reliability section of the processor's specifications. If the processor supports Intel SGX, it will be listed as "Intel Software Guard Extensions (Intel SGX)" or something similar.
If your processor does not support Intel SGX, you will not be able to use it to develop or run applications that require SGX support.
Note that even if your processor does support Intel SGX, you may need to enable it in your computer's BIOS settings. Additionally, some processors may only support certain versions of Intel SGX, so you should check the exact specifications to ensure compatibility with your intended use case.
To set up an Intel SGX development environment, you'll need the following:
- An Intel processor that supports SGX technology. You can check if your processor supports SGX by referring to the Intel website.
- A compatible operating system, such as Windows 10, Linux, or macOS. SGX development is typically done on Linux, so we'll assume you're using a Linux-based OS for the rest of this answer.
- The Intel SGX SDK and the Intel SGX PSW (Platform Software). You can download these from the Intel website. => Intel? Software Guard Extensions
- A text editor or integrated development environment (IDE) for writing your SGX code.
Once you have these components installed, you can start developing SGX applications. Intel provides several sample applications with the SGX SDK to help you get started.
Intel provide a software simulator called the Intel SGX SDK Simulator, which can be used to simulate some aspects of SGX behavior on a non-SGX system.
The Intel SGX SDK Simulator is free to download and use. It is included as part of the Intel SGX SDK, which is available for download from the Intel website.
The SGX SDK Simulator is a software-based simulator that emulates some aspects of SGX hardware behavior on a non-SGX system. It allows you to test and debug SGX applications without needing an actual SGX-enabled processor. However, it is important to note that the simulator does not provide a complete emulation of the SGX hardware, so some aspects of SGX behavior may not be fully simulated.
Overall, the SGX SDK Simulator can be a useful tool for SGX developers who do not have access to an SGX-enabled processor or who want to test their applications in a controlled environment before running them on real hardware.
Advantages of Intel SGX:
- Security: Intel SGX provides a high level of security, ensuring that sensitive data and processes are protected from potential attacks.
- Flexibility: SGX is designed to be flexible and can be used in a wide range of applications, including cloud computing, financial services, and healthcare.
- Scalability: SGX can scale to support multiple enclaves on a single system, enabling multiple applications to run securely on the same hardware.
- Compatibility: SGX is compatible with existing software and hardware, making it easy to integrate into existing systems.
From Intel sgx site:
Limitations of Intel SGX:
- Performance: Running code in an enclave can have an impact on performance, as it requires additional processing and overhead to ensure the security of the system. This can lead to slower execution times and increased power consumption.
- Limited hardware support: While SGX is supported on many Intel processors, it may not be compatible with all hardware configurations. This can limit its use in certain applications or devices.
- Integration challenges: Integrating SGX into an existing system can be challenging, as it requires modifications to the underlying hardware and software infrastructure. This can be time-consuming and expensive, particularly in complex systems.
- Limited ecosystem: The use of SGX is still relatively new, and there is a limited ecosystem of tools and resources available for developing and deploying SGX-based applications. This can make it challenging for developers to adopt and use SGX in their projects.
Application in Litentry:
Litentry is a blockchain platform that focuses on decentralized identity and user data management. It aims to provide users with control over their personal data by allowing them to manage and share it securely and anonymously.
Intel SGX is used in Litentry to provide secure execution environments for sensitive operations like cryptographic key management and user data storage. This is achieved by creating SGX enclaves that can be used to securely store and process sensitive data and operations. For example, the private keys used to sign transactions and authenticate users can be securely stored and processed within an SGX enclave, preventing unauthorized access and ensuring confidentiality.
Polkadot is a blockchain platform that aims to provide interoperability between different blockchain networks. It allows different blockchain networks to communicate and exchange data with each other, creating a network of interconnected blockchains.
Intel SGX can be used in Polkadot to provide secure and private communication between different blockchain networks. For example, SGX enclaves can be used to securely process and exchange data between blockchains, ensuring that sensitive information like transaction details and private keys remain confidential and secure.
In both Litentry and Polkadot, SGX is used to provide a secure and trusted environment for executing sensitive operations and managing user data. This can help address some of the security and privacy challenges faced by traditional blockchain networks, making these platforms more secure and trustworthy for users.
Thanks for reading till end , please comment of you have any.
Reference:
Good Reads: