Encrypted Files
We show how to transparently encrypt files.
SCONE CAS manages the keys of an application. The keys are under complete control of the application: only services given explicit control by the application get access to the keys.
Prerequisites
We assume that you already
- started a LAS instance on the local host.
Writing a file
Let us start a crosscompiler container. We first determine which SGX device to mount with function determine_sgx_device.
determine_sgx_device
docker run $MOUNT_SGXDEVICE --network=host -it -v `pwd`:/work registry.scontain.com/sconecuratedimages/crosscompilers bash
We create a simple C program to store arguments passed via environment variables into a file:
cd /work
cat > fprint-arg-env.c <<EOF
#include <stdio.h>
#include <stdlib.h>
extern char **__environ;
int main (int argc, char **argv) {
FILE *fp = fopen("/volume/output.txt", "w");
fprintf(fp, "argv:");
for (int i = 0; i < argc; i++) {
fprintf(fp, " %s", argv[i]);
}
fprintf(fp, "\n");
char** envp = __environ;
fprintf(fp, "environ:\n");
while (*envp != NULL) {
fprintf(fp, "%s\n", *envp);
envp++;
}
fclose(fp);
return 0;
}
EOF
Let us now compile the program:
scone-gcc fprint-arg-env.c -g -O3 -o fprint-arg-env
We can execute the program as follows:
mkdir -p /volume
./fprint-arg-env
This creates file: /volume/output.txt
. We can look into this file an
see that this file is not encrpted:
cat /volume/output.txt
argv: ./fprint-arg-env
environ:
SCONE_LAS_ADDR=172.30.0.1
...
While this program runs inside of an enclave, it does not encrypt files by default. We need to enable this via a policy.
Creating a policy
Our objective is to create a policy that encrypts the written file. We assign this policy the following name:
export SESSION=fprint-arg-env-$RANDOM-$RANDOM
echo $SESSION
export MRENCLAVE=`SCONE_HASH=1 ./fprint-arg-env`
echo $MRENCLAVE
We protect the execution of this program with a OTP (One Time Password). We store the secret in environment variable OTP
:
export OTPSECRET=... # base32 encoded without trailing =
cat > session.yaml <<EOF
name: $SESSION
version: 0.3
security:
attestation:
tolerate: [debug-mode, hyperthreading, outdated-tcb]
ignore_advisories: "*"
one_time_password_shared_secret: $OTPSECRET
volumes:
- name: my_encrypted_volume
images:
- name: my_image
volumes:
- name: my_encrypted_volume
path: /volume
services:
- name: fprint-arg-env
image_name: my_image
mrenclaves: [$MRENCLAVE]
command: ./fprint-arg-env need to pass your OTP
environment:
SCONE_MODE: hw
env1: version
env2: 3
env3: otp-variant
pwd: /
EOF
Set the CAS and LAS host names / IP addresses:
export SCONE_CAS_ADDR=scone-cas.cf
export SCONE_LAS_ADDR=172.30.0.1
We first need to attest CAS:
scone cas attest $SCONE_CAS_ADDR --only_for_testing-trust-any --only_for_testing-debug --only_for_testing-ignore-signer -C -G -S
before we can create the session:
export PREDECESSOR=$(scone session create session.yaml)
echo $PREDECESSOR
We can now execute the program as follows - note this requires access to an authenticator to compute the OTP:
export OTP=...
before we can actually start the program. We need to set the policy name that guides this execution. This is specified with
environment variable SCONE_CONFIG_ID
:
SCONE_CONFIG_ID=$SESSION/fprint-arg-env@$OTP ./fprint-arg-env
The output will contain some warnings
[SCONE|WARN] src/enclave/dispatch.c:197:print_version(): Application runs in SGX debug mode.
Its memory can be read from outside the enclave with a debugger! This is not secure!
[SCONE|WARN] src/syscall/syscall.c:31:__scone_ni_syscall(): system call: membarrier, number 324 is not supported
[SCONE|WARN] src/process/init.c:722:__scone_apply_secure_config(): Ignoring `SCONE_PWD` environment variable and host provided process working directory.
Applying process working directory from service's session configuration (/)
since we do not run in production mode.
We can now try to dump the file /volume/output.txt
and see that the file is now encrypted:
cat /volume/output.txt
?f˭??Y?B?ľ|?yڥxK?{??I?d????k??!>??3T"????D"S??V??.?:D??????}?!?+I...
Reading the encrypted file
We can now try to decrypt the file with a second program:
cd /work
cat > print_file.c <<EOF
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fp = fopen("/volume/output.txt", "rb");
fseek(fp, 0, SEEK_END);
long fsize = ftell(fp);
fseek(fp, 0, SEEK_SET); /* same as rewind(f); */
char *string = malloc(fsize + 1);
fread(string, fsize, 1, fp);
fclose(fp);
string[fsize] = 0;
printf("File content:\n%s", string);
}
EOF
We can compile the program
scone-gcc print_file.c -g -O3 -o print_file
and run it and we will only see encrypted content:
?f˭??Y?B?ľ|?yڥxK?{??I?d????k??!>??3T"????D"S??V??.?:D??????}?!?+I...
Extending the Policy
We need to grant the program access to the policy. Let us extend the policy accordingly:
export MRENCLAVE2=`SCONE_HASH=1 ./print_file`
echo $MRENCLAVE2
We can now define the extended policy:
cat > session2.yaml <<EOF
name: $SESSION
version: 0.3
predecessor: $PREDECESSOR
security:
attestation:
tolerate: [debug-mode, hyperthreading, outdated-tcb]
ignore_advisories: "*"
one_time_password_shared_secret: $OTPSECRET
volumes:
- name: my_encrypted_volume
images:
- name: my_image
volumes:
- name: my_encrypted_volume
path: /volume
services:
- name: fprint-arg-env
image_name: my_image
mrenclaves: [$MRENCLAVE]
command: ./fprint-arg-env need to pass your OTP
environment:
SCONE_MODE: hw
env1: version
env2: 3
env3: otp-variant
pwd: /
- name: print_file
image_name: my_image
mrenclaves: [$MRENCLAVE2]
command: ./print_file
pwd: /
EOF
We update the session:
export PREDECESSOR2=$(scone session update session2.yaml)
echo $PREDECESSOR2
and can now execute print_file
with the correct OPT:
export OTP=...
SCONE_CONFIG_ID=$SESSION/print_file@$OTP ./print_file
The output will look as follows:
File content:
argv: ./fprint-arg-env need to pass your OTP
environ:
env3=otp-variant
SCONE_MODE=hw
env1=version
env2=3
Running without attestation
In case you do not have access to a SGX-capable CPU, you can run this code also in simulation mode. For this to work, we need to change our policy to say that we do not want to perform the attestation of the CPU and the code:
cat > session3.yaml <<EOF
name: $SESSION
version: 0.3
predecessor: $PREDECESSOR2
security:
attestation:
mode: none
one_time_password_shared_secret: $OTPSECRET
volumes:
- name: my_encrypted_volume
images:
- name: my_image
volumes:
- name: my_encrypted_volume
path: /volume
services:
- name: fprint-arg-env
image_name: my_image
command: ./fprint-arg-env need to pass your OTP
environment:
SCONE_MODE: hw
env1: version
env2: 3
env3: otp-variant
pwd: /
- name: print_file
image_name: my_image
command: ./print_file
pwd: /
EOF
We update the session:
export PREDECESSOR3=$(scone session update session2.yaml)
echo $PREDECESSOR3
And we can now run the code in simulation mode:
export OTP=...
SCONE_MODE=SIM SCONE_CONFIG_ID=$SESSION/print_file@$OTP ./print_file