Welcome back to the Confidential Computing Chronicles.
In last post, we discussed why you should be paranoid about your cloud provider. Today, we stop philosophizing and start typing.
If you are a Python developer who complains when pip install takes more than 10 seconds, take a deep breath. Intel SGX (Software Guard Extensions) is not a library; it’s an architectural lifestyle change.
Building a "Hello World" in SGX isn't just print("Hello"). It involves:
Checking if your CPU even supports it (spoiler: it’s complicated).
Fighting with Linux Kernel drivers.
Signing cryptographic contracts. :D
Writing a "Bridge" between two worlds.
Let’s get into it.
Step 0: The Hardware Lottery (Do I have SGX?)
Here is the sad truth: Intel deprecated SGX on consumer CPUs (11th Gen Core and newer) to focus on Server CPUs (Xeon Scalable).
If you are on a new MacBook: You are on ARM. No hardware SGX for you.
If you are on AMD: Check out SEV (we'll cover that in Part I don't know).
If you are on a specialized Cloud Instance (e.g., Azure DC-series): You are golden.
"But Max, I don't have a Xeon server in my bedroom!"
Relax. Intel provides a Simulation Mode. It emulates the Enclave in software. It offers zero security guarantees (because the OS can see the emulated memory), but it lets you write and debug code. We will use Simulation Mode for this tutorial. So, yes, you can follow along on your standard Linux machine.
Step 1: Installing the SDK (The Toolkit)
We need the Intel SGX SDK for Linux. I’m assuming you are on Ubuntu 20.04 or 22.04.
Open your terminal and pretend you are a sysadmin:
# Install the prerequisites (The usual suspects)
sudo apt-get install build-essential python-is-python3
# Download the SGX SDK installer (Check 01.org for the latest version)
wget https://download.01.org/intel-sgx/sgx-linux/2.20/distro/ubuntu22.04-server/sgx_linux_x64_sdk_2.20.100.4.bin
# Make it executable and run it
chmod +x sgx_linux_x64_sdk_*.bin
./sgx_linux_x64_sdk_*.bin
It will ask you where to install. Just say "yes" to /opt/intel. Then, source the environment variables. Do not forget this, or nothing will work and you will cry.
source /opt/intel/sgxsdk/environment
Step 2: The Architecture of a "Hello World"
In a normal program, main() calls printf(). Simple.
In SGX, main() (Untrusted) cannot call printf() inside the Enclave (Trusted) because the Enclave doesn't have a screen, a keyboard, or an OS. It is a black box.
We need three files to make this happen:
- App.cpp (The Untrusted Host)
- Enclave.cpp (The Secret Logic)
- Enclave.edl (The Contract)
The Contract: Enclave.edl
This is the Enclave Definition Language. It defines what functions can cross the boundary.
- ECALL (Enclave Call): App calls Enclave (Entering).
- OCALL (Outside Call): Enclave calls App (Exiting).
Create a file named Enclave.edl:
enclave {
// Import standard C library types
from "sgx_tstdc.edl" import *;
trusted {
// ECALL: The App will call this function to say Hello
public void trusted_hello_world();
};
untrusted {
// OCALL: The Enclave will call this to print to the screen
void untrusted_print([in, string] const char* str);
};
};
See what we did? We defined a trusted_hello_world function that we can call from the outside. But since the Enclave can't print, we also defined an untrusted_print that the Enclave can call to ask the App to print for it. It's like a prisoner asking a guard to mail a letter.
The Secret: Enclave.cpp
This code runs inside the protected memory.
#include "Enclave_t.h" // Auto-generated header (we'll see this later)
#include "sgx_trts.h"
#include <string.h>
void trusted_hello_world() {
const char* secret_msg = "Hello from the Secure Enclave!";
// We cannot use printf here! We must use the OCALL.
untrusted_print(secret_msg);
}
The Host: App.cpp
This is the normal application that sets everything up.
#include <stdio.h>
#include "sgx_urts.h"
#include "Enclave_u.h" // Auto-generated header for untrusted code
// Global Enclave ID
sgx_enclave_id_t global_eid = 0;
// This is the OCALL implementation
// The Enclave calls this when it wants to print something
void untrusted_print(const char* str) {
printf("Enclave says: %s\n", str);
}
int main() {
sgx_status_t ret;
// 1. Initialize the Enclave
// "enclave.signed.so" is the signed library we will build
ret = sgx_create_enclave("enclave.signed.so", SGX_DEBUG_FLAG, NULL, NULL, &global_eid, NULL);
if (ret != SGX_SUCCESS) {
printf("Failed to create Enclave. Error: %x\n", ret);
return -1;
}
printf("App: Enclave created. Calling into the void...\n");
// 2. Make the ECALL
trusted_hello_world(global_eid);
// 3. Destroy the Enclave
sgx_destroy_enclave(global_eid);
return 0;
}
Step 3: The Build Nightmare (Edger8r)
You can't just gcc App.cpp. Oh no.
You have to use a tool called sgx_edger8r. It parses your .edl file and generates "Edge Routines" (the glue code that handles the context switching between secure and insecure worlds).
-
sgx_edger8rreadsEnclave.edl. - It generates
Enclave_t.c(Trusted proxy) andEnclave_u.c(Untrusted proxy). - You compile the Enclave code + Trusted Proxy into a library.
- You Sign the library using a private key (OpenSSL).
- You compile the App code + Untrusted Proxy.
- Link them together.
I won't paste the 50-line Makefile here because it looks like ancient hieroglyphics.
For now, just imagine running:
make SGX_MODE=SIM
Step 4: Run it!
If the gods of compilation smile upon you, you will see an executable app.
$ ./app
App: Enclave created. Calling into the void...
Enclave says: Hello from the Secure Enclave!
Victory.
Why was that so hard?
You might ask: "Max, that was 200 lines of setup for a print statement."
Yes. But think about what actually happened.
That "Hello" string was created in a region of memory that the Operating System could not read.
When untrusted_print was called, the CPU performed a hardware context switch, exited the protected mode, scrubbed the registers, and handed control back to the OS just to print those characters.
We just defied the laws of traditional OS hierarchy.
Up Next
Now that we have the environment, we need to talk about the Memory Wall.
In the next post, I will show you how to crash your Enclave by allocating too much RAM, and why "Paging" in SGX is a performance killer.
Part 3: The Memory Wall & Performance Tuning is coming soon.
Leave a Comment 👇
Did you get the SGX_ERROR_NO_DEVICE error? Or did you actually manage to run it in Simulation Mode?
Drop your error logs in the comments and let's debug this together.


Top comments (1)
If you are running this on a real Ice Lake Server, please brag about it so I can be jealous.