Skip to content

Commit ba35c5c

Browse files
pqcfoxalevy
authored andcommitted
tutorial: root_of_trust: add milestone two for encryption service
1 parent 00ad7e9 commit ba35c5c

File tree

6 files changed

+208
-6
lines changed

6 files changed

+208
-6
lines changed

examples/tutorials/root_of_trust/encryption_service_milestone_one/main.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,25 @@ static int log_to_screen(const char* message) {
7979
}
8080

8181
int main(void) {
82+
returncode_t ret;
83+
8284
// Wait to receive the signal to start from the app selector.
8385
wait_for_start();
8486

8587
// Set up logging service.
86-
setup_logging();
88+
ret = setup_logging();
89+
if (ret < 0) {
90+
printf("ERROR: cannot set up logging");
91+
}
8792

8893
// Test logging to screen over IPC.
8994
char message_buf[32];
9095
for (int i = 0; i < 10; i++) {
9196
sprintf(message_buf, "Test message #%i...", i);
92-
log_to_screen(message_buf);
97+
ret = log_to_screen(message_buf);
98+
if (ret < 0) {
99+
printf("ERROR: cannot log to screen");
100+
}
93101
}
94102

95103
return 0;

examples/tutorials/root_of_trust/encryption_service_milestone_three/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
Hardware Root of Trust (HWRoT) Demo Encryption Service Application
22
------------------------------------------------------------------
33

4-
This application implements a basic UART encryption service for a mock hardware root of trust (HWRoT) which inputs
4+
This application implements a basic UART encryption service for a mock hardware
5+
root of trust (HWRoT) which inputs user-provided plaintext and encrypts it using
6+
a fixed key stored in a kernel driver, returning the ciphertext to the user.
57

68
This is part of a tutorial which improves the application in multiple steps. A
79
writeup for the tutorial is available at https://book.tockos.org/.

examples/tutorials/root_of_trust/encryption_service_milestone_three/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static size_t request_plaintext(uint8_t* plaintext, size_t size) {
8585
char c;
8686
int number_read, number_written;
8787

88-
printf("Enter a secret to encrypt:\n");
88+
printf("Enter plaintext to encrypt:\n");
8989

9090
// Clear all leading whitespace left in the buffer.
9191
do {
@@ -137,7 +137,7 @@ int main(void) {
137137
// Set up logging service.
138138
setup_logging();
139139

140-
// Prepare single-block buffers for encryption.
140+
// Prepare buffers for encryption.
141141
uint8_t plaintext[4 * AES_BLOCK_SIZE];
142142
uint8_t output[4 * AES_BLOCK_SIZE];
143143
char output_hex[33];
@@ -154,7 +154,7 @@ int main(void) {
154154
ret = oracle_encrypt(plaintext, plaintext_len, output, sizeof(output), iv);
155155
if (ret < 0) {
156156
printf("ERROR(%i): %s.\r\n", ret, tock_strrcode(ret));
157-
printf("ERROR cannot encrypt key\r\n");
157+
printf("ERROR cannot encrypt plaintext\r\n");
158158
return ret;
159159
}
160160

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Makefile for user application
2+
3+
# Specify this directory relative to the current application.
4+
TOCK_USERLAND_BASE_DIR = ../../../../
5+
6+
PACKAGE_NAME = org.tockos.tutorials.attestation.encryption
7+
8+
# Which files to compile.
9+
C_SRCS := $(wildcard *.c)
10+
11+
# Include userland master makefile. Contains rules and flags for actually
12+
# building the application.
13+
include $(TOCK_USERLAND_BASE_DIR)/AppMakefile.mk
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Hardware Root of Trust (HWRoT) Demo Encryption Service Application
2+
------------------------------------------------------------------
3+
4+
This application implements a basic UART encryption service for a mock hardware
5+
root of trust (HWRoT) which inputs user-provided plaintext and encrypts it using
6+
a fixed key stored in a kernel driver, returning the ciphertext to the user.
7+
8+
This is part of a tutorial which improves the application in multiple steps. A
9+
writeup for the tutorial is available at https://book.tockos.org/.
10+
11+
Specific abilities of this version:
12+
13+
* Allows logging to screen over IPC
14+
* Allows prompting for plaintext over returning results in hex over UART
15+
* Does NOT allow for encryping user-provided plaintext using an encryption oracle driver
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#include "libtock/tock.h"
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
5+
#include <libtock-sync/interface/console.h>
6+
#include <libtock/kernel/ipc.h>
7+
8+
#define LOG_WIDTH 32
9+
10+
bool started = false;
11+
bool log_done = false;
12+
size_t screen_service = -1;
13+
char log_buf[LOG_WIDTH] __attribute__((aligned(LOG_WIDTH)));
14+
15+
const char SCREEN_SERVICE_NAME[] = "org.tockos.tutorials.attestation.screen";
16+
17+
static void ipc_callback(__attribute__ ((unused)) int pid,
18+
__attribute__ ((unused)) int len,
19+
__attribute__ ((unused)) int arg2,
20+
__attribute__ ((unused)) void* ud) {
21+
started = true;
22+
}
23+
24+
static void log_done_callback(__attribute__ ((unused)) int pid,
25+
__attribute__ ((unused)) int len,
26+
__attribute__ ((unused)) int arg2,
27+
__attribute__ ((unused)) void* ud) {
28+
log_done = true;
29+
}
30+
31+
static void wait_for_start(void) {
32+
// Register an IPC callback and wait for it to be called by the
33+
// screen app based on the user's app selection.
34+
ipc_register_service_callback("org.tockos.tutorials.attestation.encryption", ipc_callback,
35+
NULL);
36+
yield_for(&started);
37+
}
38+
39+
static int setup_logging() {
40+
returncode_t ret;
41+
42+
// Find the PID of the screen logging service
43+
ret = ipc_discover(SCREEN_SERVICE_NAME, &screen_service);
44+
if (ret != RETURNCODE_SUCCESS) {
45+
printf("Screen logging service not found.\n");
46+
return ret;
47+
}
48+
49+
// Set up a callback and share so we can supply log messages
50+
// and know when they've been completely logged.
51+
ipc_register_client_callback(screen_service, log_done_callback, NULL);
52+
ipc_share(screen_service, log_buf, LOG_WIDTH);
53+
54+
return 0;
55+
}
56+
57+
static int log_to_screen(const char* message) {
58+
returncode_t ret;
59+
60+
// Copy up to the log buffer's size of the message, with room for a null byte.
61+
uint16_t len = strnlen(message, sizeof(log_buf) - 1);
62+
memcpy(log_buf, message, len);
63+
64+
// Add the null byte.
65+
log_buf[len] = '\0';
66+
67+
// Start the logging process.
68+
ret = ipc_notify_service(screen_service);
69+
if (ret != RETURNCODE_SUCCESS) {
70+
printf("Failed to request a log to screen.\n");
71+
return ret;
72+
}
73+
74+
// Wait for the log to complete.
75+
yield_for(&log_done);
76+
log_done = false;
77+
78+
return 0;
79+
}
80+
81+
static size_t request_plaintext(uint8_t* plaintext, size_t size) {
82+
char c;
83+
int number_read, number_written;
84+
85+
printf("Enter plaintext to encrypt:\n");
86+
87+
// Clear all leading whitespace left in the buffer.
88+
do {
89+
libtocksync_console_read((uint8_t*)&c, 1, &number_read);
90+
} while (c == '\n' || c == '\r');
91+
92+
for (uint8_t i = 0; i < size; i++) {
93+
// Break on enter.
94+
if (c == '\n' || c == '\r') {
95+
libtocksync_console_write((uint8_t*)"\n", 1, &number_written);
96+
return i;
97+
}
98+
99+
// Otherwise, echo the character.
100+
libtocksync_console_write((uint8_t*)&c, 1, &number_written);
101+
102+
// Record the output.
103+
plaintext[i] = c;
104+
105+
// Fetch a new character from input to add.
106+
libtocksync_console_read((uint8_t*)&c, 1, &number_read);
107+
}
108+
109+
return size;
110+
}
111+
112+
static void bytes_to_hex(char* hex_chars, uint8_t* bytes, size_t bytes_len) {
113+
char hex_byte[3];
114+
115+
for (uint8_t i = 0; i < bytes_len; i++) {
116+
// Convert the current byte into hex
117+
sprintf(hex_byte, "%02X", bytes[i]);
118+
119+
// Load that serialized byte into the destination string.
120+
hex_chars[2 * i] = hex_byte[0];
121+
hex_chars[2 * i + 1] = hex_byte[1];
122+
}
123+
124+
// Add a null-terminator.
125+
hex_chars[2 * bytes_len] = '\0';
126+
}
127+
128+
int main(void) {
129+
returncode_t ret;
130+
131+
// Wait to receive the signal to start from the app selector.
132+
wait_for_start();
133+
134+
// Set up logging service.
135+
ret = setup_logging();
136+
if (ret < 0) {
137+
printf("ERROR: cannot set up logging\n");
138+
}
139+
140+
// Prepare buffers for receiving plaintext
141+
uint8_t plaintext[512];
142+
char plaintext_hex[1024];
143+
144+
while (1) {
145+
// Request a plaintext.
146+
ret = log_to_screen("Requesting plaintext...");
147+
if (ret < 0) {
148+
printf("ERROR: cannot log to screen\n");
149+
}
150+
size_t plaintext_len = request_plaintext(plaintext, sizeof(plaintext));
151+
152+
// Convert first 16 bytes of plaintext to hex.
153+
bytes_to_hex(plaintext_hex, plaintext, plaintext_len);
154+
155+
// Display the resulting hex.
156+
ret = log_to_screen("Returning plaintext...");
157+
if (ret < 0) {
158+
printf("ERROR: cannot log to screen\n");
159+
}
160+
printf("Received plaintext: %s\n", plaintext_hex);
161+
}
162+
163+
return 0;
164+
}

0 commit comments

Comments
 (0)