Skip to content

Commit 3b7857f

Browse files
committed
[demo] refactor the cheriot heartbleed demo
Signed-off-by: Douglas Reis <doreis@lowrisc.org>
1 parent f1c8fda commit 3b7857f

File tree

10 files changed

+1265
-1232
lines changed

10 files changed

+1265
-1232
lines changed

examples/heartbleed/cheriot/heartbleed.cc

Lines changed: 84 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Copyright lowRISC contributors.
21
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
32
// SPDX-License-Identifier: Apache-2.0
43

@@ -17,7 +16,7 @@ using namespace CHERI;
1716
using namespace sonata::lcd;
1817

1918
constexpr bool DebugDemo = true;
20-
constexpr uint32_t LengthScrollMillis = 350u;
19+
constexpr uint32_t LengthScrollMillis = 150u;
2120
constexpr Color BackgroundColor = Color::Black;
2221
constexpr Color ForegroundColor = Color::White;
2322

@@ -141,24 +140,28 @@ bool length_joystick_control(volatile SonataGpioBoard *gpio, size_t *current)
141140
* @param actual_req_len The genuine length of the `bufferMessage`. This MUST
142141
* match, or is undefined behaviour.
143142
*/
144-
void initial_lcd_write(SonataLcd *lcd,
145-
const char *bufferMessage,
146-
size_t actual_req_len)
143+
void initial_lcd_write(SonataLcd *lcd)
147144
{
148145
lcd->draw_str({5, 5},
149146
"Move Joystick to Change Length.",
150147
BackgroundColor,
151-
ForegroundColor);
152-
lcd->draw_str(
153-
{5, 15}, "Press Joystick to Send.", BackgroundColor, ForegroundColor);
154-
lcd->draw_str(
155-
{5, 30}, "Buffer Message: ", BackgroundColor, ForegroundColor);
156-
char displayMessage[actual_req_len + 1];
157-
memcpy(displayMessage, bufferMessage, actual_req_len);
158-
displayMessage[actual_req_len] = '\0';
159-
lcd->draw_str({70, 30}, displayMessage, BackgroundColor, ForegroundColor);
160-
lcd->draw_str(
161-
{5, 40}, "Request Length: ", BackgroundColor, ForegroundColor);
148+
ForegroundColor,
149+
Font::m5x7_16pt);
150+
lcd->draw_str({5, 15},
151+
"Press Joystick to Send.",
152+
BackgroundColor,
153+
ForegroundColor,
154+
Font::m5x7_16pt);
155+
lcd->draw_str({5, 30},
156+
"Request a larger buffer ",
157+
BackgroundColor,
158+
ForegroundColor,
159+
Font::m5x7_16pt);
160+
lcd->draw_str({5, 40},
161+
"Suggested Length: ",
162+
BackgroundColor,
163+
ForegroundColor,
164+
Font::m5x7_16pt);
162165
}
163166

164167
/**
@@ -175,7 +178,8 @@ void draw_request_length(SonataLcd *lcd,
175178
constexpr size_t ReqLenStrLen = 15u;
176179
char req_len_s[ReqLenStrLen];
177180
size_t_to_str_base10(req_len_s, request_length);
178-
lcd->draw_str({70, 40}, req_len_s, BackgroundColor, ForegroundColor);
181+
lcd->draw_str(
182+
{110, 40}, req_len_s, BackgroundColor, ForegroundColor, Font::m5x7_16pt);
179183
}
180184

181185
/**
@@ -206,67 +210,75 @@ void get_request_length(SonataLcd *lcd,
206210
{
207211
continue; // Only re-draw when changed
208212
}
209-
lcd->draw_str({70, 40}, " ", BackgroundColor, ForegroundColor);
213+
lcd->draw_str({110, 40},
214+
" ",
215+
BackgroundColor,
216+
ForegroundColor,
217+
Font::m5x7_16pt);
210218
draw_request_length(lcd, gpio, *request_length);
211219
}
212220

213221
Debug::log("Heartbeat submitted with length {}", (int)(*request_length));
214222
}
215223

216224
/**
217-
* @brief This function contains the logic for writing the heartbeat/bleed
218-
* response message to the LCD, breaking the message across lines where it is
219-
* necessary.
225+
* @brief This function mocks the network and show the package on the lcd
226+
* instead.
220227
*
221-
* @param lcd The Sonata LCD driver to use.
222-
* @param request_length The length of the heartbeat request. May not be the
223-
* actual message length.
224-
* @param result The heartbeat response to reply with. This should not be
225-
* null-terminated.
228+
* @param lcd A handle to Sonata's LCD
229+
* @param package The package to be sent.
230+
* @param len The length of the package .
226231
*/
227-
void draw_heartbleed_response(SonataLcd *lcd,
228-
size_t request_length,
229-
const char *result)
232+
void network_send(void *handle, const char *package, size_t len)
230233
{
231-
constexpr uint32_t CharsPerLine = 50u;
234+
constexpr uint32_t CharsPerLine = 29;
235+
SonataLcd *lcd = (SonataLcd *)handle;
232236

233-
// Format the result message for LCD display as a null-terminated string.
234-
constexpr size_t PrefixLen = 10u;
235-
constexpr char ResponsePrefix[PrefixLen + 1] = "Response: ";
236-
char result_s[PrefixLen + request_length + 1];
237-
memcpy(result_s, ResponsePrefix, PrefixLen);
238-
memcpy(&result_s[PrefixLen], result, request_length);
239-
result_s[PrefixLen + request_length] = '\0';
237+
size_t w_boarder = 2;
238+
lcd->fill_rect({w_boarder, 50, 160 - w_boarder, 128}, Color::Grey);
240239

241240
// Break the result message into several lines if it is too long to fit on
242241
// one line.
243-
char result_line[CharsPerLine + 1];
244-
const char *result_char = result_s;
242+
char line_content[CharsPerLine + 1];
243+
const char *cursor = package;
245244
size_t line_length = 0u;
246245
size_t line_num = 0u;
247-
while (*result_char != '\0')
246+
while (len-- != 0)
248247
{
249-
result_line[line_length++] = *result_char;
250-
result_char++;
248+
if (*cursor == 0)
249+
{
250+
line_content[line_length++] = '`';
251+
}
252+
else if (isprint((int)(*cursor)) == 0)
253+
{
254+
line_content[line_length++] = '%';
255+
}
256+
else
257+
{
258+
line_content[line_length++] = *cursor;
259+
}
260+
cursor++;
251261
if (line_length == CharsPerLine)
252262
{
253-
result_line[line_length] = '\0';
263+
line_content[line_length] = '\0';
254264
lcd->draw_str({5, 55 + 10 * line_num},
255-
result_line,
256-
BackgroundColor,
257-
ForegroundColor);
265+
line_content,
266+
Color::Grey,
267+
Color::Black,
268+
Font::m5x7_16pt);
258269
line_length = 0;
259270
line_num++;
260271
}
261272
}
262273
// Write the final line containing the remainder of the message.
263274
if (line_length)
264275
{
265-
result_line[line_length] = '\0';
276+
line_content[line_length] = '\0';
266277
lcd->draw_str({5, 55 + 10 * line_num},
267-
result_line,
268-
BackgroundColor,
269-
ForegroundColor);
278+
line_content,
279+
Color::Grey,
280+
Color::Black,
281+
Font::m5x7_16pt);
270282
}
271283
}
272284

@@ -277,24 +289,35 @@ void draw_heartbleed_response(SonataLcd *lcd,
277289
Size displaySize = lcd->resolution();
278290
Point centre = {displaySize.width / 2, displaySize.height / 2};
279291
lcd->clean(BackgroundColor);
292+
size_t w_boarder = 2;
293+
lcd->fill_rect({w_boarder, 50, 160 - w_boarder, 128}, Color::Grey);
280294

281295
// Initialise GPIO driver to interact with the Joystick
282296
auto gpio = MMIO_CAPABILITY(SonataGpioBoard, gpio_board);
283297

284-
// We represent the heartbeat message as a small array of incoming bytes,
285-
// and initialise with its actual size.
286-
constexpr size_t actual_req_len = 4;
287-
const char bufferMessage[actual_req_len] = {'B', 'i', 'r', 'd'};
288-
289-
size_t req_len = actual_req_len;
298+
size_t req_len = 8;
290299
while (true)
291300
{
292-
initial_lcd_write(lcd, bufferMessage, actual_req_len);
301+
// We allocate a big chunck of memory to temporary store a json file
302+
// with sensitive information. Then we free the buffer without cleaning
303+
// the content.
304+
const size_t DbSize = 128;
305+
char *ptr = (char *)malloc(DbSize);
306+
read_file("clients.db", ptr, DbSize);
307+
free(ptr);
308+
309+
initial_lcd_write(lcd);
310+
311+
// Wait for the request.
293312
get_request_length(lcd, gpio, &req_len);
294-
const char *result = heartbleed(bufferMessage, req_len);
295-
lcd->fill_rect({5, 55, displaySize.width, displaySize.height},
296-
BackgroundColor);
297-
draw_heartbleed_response(lcd, req_len, result);
313+
314+
const char *result =
315+
run_query("SELECT name FROM animal WHERE can_fly=yes LIMIT 1");
316+
317+
// We send back the response to the request without checking that the
318+
// requested length exeeds the needed size, which can leek information.
319+
heartbleed(lcd, result, req_len);
320+
298321
free((void *)result);
299322
}
300323

examples/heartbleed/cheriot/xmake.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
-- Compartments used for the automotive demo firmware
55
compartment("heartbleed")
6-
add_deps("lcd", "debug")
6+
add_deps("lcd", "debug", "string")
77
add_files("heartbleed.cc", "../common.c")
88

99
-- CHERIoT version of Heartbleed Demo Firmware

examples/heartbleed/common.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ static const char *json =
2727

2828
// We represent the heartbeat message as a small array of incoming bytes,
2929
// and initialise with its actual size.
30-
static const char *QueryResponse = "Bird";
30+
static const char *QueryResponse = "Sparrow";
3131

3232
// We don't have filesystem so we mock it.
3333
void read_file(const char *filename, char *buffer, size_t buffer_size)
@@ -44,7 +44,6 @@ static const char *json =
4444
return buff;
4545
}
4646

47-
4847
void heartbleed(void *handle, const char *buffer, size_t len)
4948
{
5049
const size_t headerLen = 7u;

examples/heartbleed/common.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,25 @@ extern "C"
1414
extern void network_send(void *handle, const char *package, size_t len);
1515

1616
/**
17-
* @brief Run a query and allocate a buffer with the response, the buffer should be deallocated by the caller.
18-
*
19-
* @param query The query to be executed.
17+
* @brief Run a query and allocate a buffer with the response, the buffer
18+
* should be deallocated by the caller.
19+
*
20+
* @param query The query to be executed.
2021
* @return A heap-allocated copy of the message. Simulates a response
2122
* packet.
2223
*/
2324
char *run_query(const char *query);
2425

2526
/**
26-
* @brief Format the response package, the buffer is copied to the response package based on teh len,
27-
* if the is larger than the buffer, sensitive information can be leaked throught the network.
28-
*
29-
* This function requires that the caller implements the function `network_send`.
30-
*
31-
* @param handle A pointer to a handle that will be forward to the network_send.
27+
* @brief Format the response package, the buffer is copied to the response
28+
* package based on teh len, if the is larger than the buffer, sensitive
29+
* information can be leaked throught the network.
30+
*
31+
* This function requires that the caller implements the function
32+
* `network_send`.
33+
*
34+
* @param handle A pointer to a handle that will be forward to the
35+
* network_send.
3236
* @param buffer The buffer to be sent.
3337
* @param buffer_size The of the buffer.
3438
* @return A heap-allocated copy of the message. Simulates a response

examples/heartbleed/legacy/heartbleed.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,12 @@ void get_request_length(St7735Context *lcd, size_t *request_length)
221221
}
222222

223223
/**
224-
* @brief This function contains the logic for writing the heartbeat/bleed
225-
* response message to the LCD, breaking the message across lines where it is
226-
* necessary.
224+
* @brief This function mocks the network and show the package on the lcd
225+
* instead.
227226
*
228227
* @param lcd A handle to Sonata's LCD
229-
* @param request_length The length of the heartbeat request. May not be the
230-
* actual message length.
231-
* @param result The heartbeat response to reply with. This should not be
232-
* null-terminated.
228+
* @param package The package to be sent.
229+
* @param len The length of the package .
233230
*/
234231
void network_send(void *handle, const char *package, size_t len)
235232
{
@@ -311,7 +308,7 @@ int main()
311308
pwm_t lcd_bl = PWM_FROM_ADDR_AND_INDEX(PWM_BASE, PWM_LCD);
312309
set_pwm(lcd_bl, 1, 255);
313310

314-
size_t req_len = 4;
311+
size_t req_len = 8;
315312
while (true)
316313
{
317314
// We allocate a big chunck of memory to temporary store a json file

libraries/lcd.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ void __cheri_libcall SonataLcd::draw_str(Point point,
141141
case Font::LucidaConsole_12pt:
142142
internalFont = &internal::lucidaConsole_12ptFont;
143143
break;
144+
case Font::m5x7_16pt:
145+
internalFont = &internal::m5x7_16ptFont;
146+
break;
144147
default:
145148
internalFont = &internal::m3x6_16ptFont;
146149
}

libraries/lcd.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ namespace sonata::lcd
1919
#include "../third_party/display_drivers/core/lucida_console_12pt.h"
2020
#include "../third_party/display_drivers/core/m3x6_16pt.h"
2121
#include "../third_party/display_drivers/st7735/lcd_st7735.h"
22+
#include "m5x7_16pt.h"
2223
}
2324
void __cheri_libcall lcd_init(LCD_Interface *,
2425
St7735Context *,
@@ -92,6 +93,7 @@ namespace sonata::lcd
9293
M3x6_16pt, // NOLINT Removing _ from these names can make them
9394
LucidaConsole_10pt, // NOLINT harder to read as they end and start with
9495
LucidaConsole_12pt, // NOLINT numbers (e.g. M3x616pt).
96+
m5x7_16pt,
9597
};
9698

9799
class SonataLcd

0 commit comments

Comments
 (0)