SDK Examples¶
This page provides complete, working examples demonstrating various EmbSec SDK features.
Basic Examples¶
Hello World¶
The simplest EmbSec program:
#include <embsec/embsec.h>
#include <embsec/uart.h>
int main(void) {
embsec_init();
embsec_printf("Hello, EmbSec!\n");
while (1) {
// Keep running
}
}
LED Blink¶
Classic embedded "Hello World" with LED:
#include <embsec/embsec.h>
#include <embsec/gpio.h>
int main(void) {
embsec_init();
while (1) {
embsec_led_set(EMBSEC_LED_GREEN, true);
embsec_delay_ms(500);
embsec_led_set(EMBSEC_LED_GREEN, false);
embsec_delay_ms(500);
}
}
Button Input¶
Read button presses and control LEDs:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/gpio.h>
int main(void) {
embsec_init();
embsec_printf("Press SW1 for red LED, SW2 for blue LED\n");
while (1) {
if (embsec_switch_read(EMBSEC_SW1)) {
embsec_led_set(EMBSEC_LED_RED, true);
} else {
embsec_led_set(EMBSEC_LED_RED, false);
}
if (embsec_switch_read(EMBSEC_SW2)) {
embsec_led_set(EMBSEC_LED_BLUE, true);
} else {
embsec_led_set(EMBSEC_LED_BLUE, false);
}
embsec_delay_ms(10);
}
}
Interactive Examples¶
Simple Shell¶
Basic command-line interface:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/gpio.h>
#include <string.h>
void handle_command(const char *cmd) {
if (strcmp(cmd, "help") == 0) {
embsec_printf("Commands:\n");
embsec_printf(" help - Show this help\n");
embsec_printf(" led - Toggle LED\n");
embsec_printf(" time - Show uptime\n");
}
else if (strcmp(cmd, "led") == 0) {
embsec_led_toggle(EMBSEC_LED_GREEN);
embsec_printf("LED toggled\n");
}
else if (strcmp(cmd, "time") == 0) {
uint32_t ms = embsec_get_tick_ms();
embsec_printf("Uptime: %u.%03u seconds\n", ms / 1000, ms % 1000);
}
else {
embsec_printf("Unknown command: %s\n", cmd);
}
}
int main(void) {
embsec_init();
embsec_printf("\nSimple Shell - Type 'help' for commands\n");
char buffer[64];
while (1) {
embsec_printf("> ");
if (embsec_gets(buffer, sizeof(buffer))) {
if (strlen(buffer) > 0) {
handle_command(buffer);
}
}
}
}
Menu System¶
Interactive menu with navigation:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/gpio.h>
typedef enum {
MENU_MAIN,
MENU_LED,
MENU_INFO
} menu_state_t;
void show_main_menu(void) {
embsec_printf("\n=== Main Menu ===\n");
embsec_printf("1. LED Control\n");
embsec_printf("2. System Info\n");
embsec_printf("3. Exit\n");
embsec_printf("Choice: ");
}
void show_led_menu(void) {
embsec_printf("\n=== LED Control ===\n");
embsec_printf("1. Red LED\n");
embsec_printf("2. Green LED\n");
embsec_printf("3. Blue LED\n");
embsec_printf("4. All Off\n");
embsec_printf("5. Back\n");
embsec_printf("Choice: ");
}
int main(void) {
embsec_init();
menu_state_t state = MENU_MAIN;
while (1) {
switch (state) {
case MENU_MAIN:
show_main_menu();
char choice = embsec_getchar();
embsec_printf("%c\n", choice);
switch (choice) {
case '1':
state = MENU_LED;
break;
case '2':
embsec_printf("\nDevice ID: 0x%08X\n", embsec_get_hwid());
embsec_printf("SDK Version: %s\n", embsec_get_version());
embsec_printf("Uptime: %u ms\n", embsec_get_tick_ms());
break;
case '3':
embsec_printf("Goodbye!\n");
return 0;
}
break;
case MENU_LED:
show_led_menu();
choice = embsec_getchar();
embsec_printf("%c\n", choice);
embsec_led_set(EMBSEC_LED_RED | EMBSEC_LED_GREEN | EMBSEC_LED_BLUE, false);
switch (choice) {
case '1':
embsec_led_set(EMBSEC_LED_RED, true);
break;
case '2':
embsec_led_set(EMBSEC_LED_GREEN, true);
break;
case '3':
embsec_led_set(EMBSEC_LED_BLUE, true);
break;
case '4':
// Already turned off
break;
case '5':
state = MENU_MAIN;
break;
}
break;
}
}
}
Timing Examples¶
Non-blocking Delays¶
Perform multiple tasks without blocking:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/gpio.h>
#include <embsec/timer.h>
int main(void) {
embsec_init();
uint32_t led_timer = embsec_millis();
uint32_t print_timer = embsec_millis();
uint32_t counter = 0;
while (1) {
// Toggle LED every 500ms
if (embsec_timeout(led_timer, 500)) {
led_timer = embsec_millis();
embsec_led_toggle(EMBSEC_LED_GREEN);
}
// Print counter every 2 seconds
if (embsec_timeout(print_timer, 2000)) {
print_timer = embsec_millis();
embsec_printf("Counter: %u\n", counter);
}
// Check for button press (non-blocking)
if (embsec_switch_read(EMBSEC_SW1)) {
counter++;
embsec_switch_wait(EMBSEC_SW1, 50); // Debounce
}
}
}
Performance Measurement¶
Measure execution time of functions:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/timer.h>
#include <embsec/crypto.h>
void benchmark_sha256(void) {
uint8_t data[1024];
uint8_t hash[32];
// Fill with test data
for (int i = 0; i < 1024; i++) {
data[i] = i & 0xFF;
}
// Measure single hash
uint32_t start = embsec_perf_start();
embsec_sha256(data, sizeof(data), hash);
uint32_t cycles = embsec_perf_end(start);
embsec_printf("SHA-256 (1KB): %u cycles, %u us\n",
cycles, embsec_cycles_to_us(cycles));
// Measure 100 iterations
start = embsec_perf_start();
for (int i = 0; i < 100; i++) {
embsec_sha256(data, sizeof(data), hash);
}
cycles = embsec_perf_end(start);
embsec_printf("SHA-256 (100x1KB): %u cycles, %u ms\n",
cycles, embsec_cycles_to_us(cycles) / 1000);
}
int main(void) {
embsec_init();
embsec_printf("\n=== Performance Benchmark ===\n");
benchmark_sha256();
// Measure empty loop overhead
uint32_t start = embsec_perf_start();
for (volatile int i = 0; i < 10000; i++) {
// Empty
}
uint32_t cycles = embsec_perf_end(start);
embsec_printf("Empty loop (10k): %u cycles\n", cycles);
while (1) {
// Keep running
}
}
Security Examples¶
Password Checker¶
Simple password verification with timing attack protection:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/crypto.h>
#include <string.h>
// Stored password hash (hash of "embsec123")
const uint8_t stored_hash[32] = {
0x3c, 0x9e, 0x2c, 0x8f, 0x7a, 0x1b, 0x4d, 0x6e,
0x9f, 0x8c, 0x3b, 0x2a, 0x1d, 0x0e, 0x7f, 0x8d,
0x2c, 0x4b, 0x6a, 0x9e, 0x0f, 0x3d, 0x5c, 0x8b,
0x1a, 0x2f, 0x4e, 0x7d, 0x9c, 0x0b, 0x3a, 0x69
};
bool verify_password(const char *password) {
uint8_t hash[32];
// Hash the input password
embsec_sha256((const uint8_t *)password, strlen(password), hash);
// Constant-time comparison
return embsec_crypto_memcmp(hash, stored_hash, 32) == 0;
}
int main(void) {
embsec_init();
embsec_printf("\n=== Secure Login ===\n");
char password[64];
int attempts = 0;
while (attempts < 3) {
embsec_printf("Enter password: ");
// Read password without echo
int i = 0;
while (i < sizeof(password) - 1) {
char c = embsec_getchar();
if (c == '\r' || c == '\n') {
break;
} else if (c == '\b' && i > 0) {
i--;
embsec_printf("\b \b");
} else if (c >= 32 && c < 127) {
password[i++] = c;
embsec_putchar('*');
}
}
password[i] = '\0';
embsec_printf("\n");
if (verify_password(password)) {
embsec_printf("Access granted!\n");
// Clear password from memory
embsec_secure_zero(password, sizeof(password));
// Generate access flag
embsec_flag_t flag;
embsec_generate_flag_str(&flag, "secure-login");
embsec_print_flag(&flag);
break;
} else {
attempts++;
embsec_printf("Access denied! %d attempts remaining.\n", 3 - attempts);
}
// Clear password from memory
embsec_secure_zero(password, sizeof(password));
}
if (attempts >= 3) {
embsec_printf("Too many failed attempts. System locked.\n");
}
while (1) {
// Keep running
}
}
Secure Communication¶
Example of authenticated messaging:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/crypto.h>
#include <string.h>
// Shared secret key
const uint8_t secret_key[32] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10
};
typedef struct {
uint32_t sequence;
uint16_t length;
uint8_t data[128];
uint8_t mac[32];
} secure_packet_t;
bool send_secure_message(const char *message, uint32_t seq) {
secure_packet_t packet;
packet.sequence = seq;
packet.length = strlen(message);
if (packet.length > sizeof(packet.data)) {
return false;
}
memcpy(packet.data, message, packet.length);
// Calculate MAC over sequence + length + data
uint8_t mac_data[256];
size_t mac_len = 0;
memcpy(mac_data + mac_len, &packet.sequence, sizeof(packet.sequence));
mac_len += sizeof(packet.sequence);
memcpy(mac_data + mac_len, &packet.length, sizeof(packet.length));
mac_len += sizeof(packet.length);
memcpy(mac_data + mac_len, packet.data, packet.length);
mac_len += packet.length;
embsec_hmac_sha256(secret_key, sizeof(secret_key),
mac_data, mac_len, packet.mac);
// Send packet
embsec_printf("SECURE[%u:%u:", packet.sequence, packet.length);
for (int i = 0; i < packet.length; i++) {
embsec_printf("%02x", packet.data[i]);
}
embsec_printf(":");
for (int i = 0; i < 32; i++) {
embsec_printf("%02x", packet.mac[i]);
}
embsec_printf("]\n");
return true;
}
int main(void) {
embsec_init();
embsec_printf("\n=== Secure Messaging Demo ===\n");
embsec_printf("Commands:\n");
embsec_printf(" send <message> - Send authenticated message\n");
embsec_printf(" key - Show key fingerprint\n\n");
uint32_t sequence = 0;
char buffer[256];
while (1) {
embsec_printf("> ");
if (embsec_gets(buffer, sizeof(buffer))) {
if (strncmp(buffer, "send ", 5) == 0) {
if (send_secure_message(buffer + 5, sequence++)) {
embsec_printf("Message sent (seq=%u)\n", sequence - 1);
} else {
embsec_printf("Failed to send message\n");
}
}
else if (strcmp(buffer, "key") == 0) {
uint8_t fingerprint[32];
embsec_sha256(secret_key, sizeof(secret_key), fingerprint);
embsec_printf("Key fingerprint: ");
for (int i = 0; i < 8; i++) {
embsec_printf("%02x", fingerprint[i]);
}
embsec_printf("...\n");
}
}
}
}
Lab Examples¶
Buffer Overflow Detection¶
Example vulnerable program with overflow detection:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/flag.h>
#include <string.h>
void vulnerable_function(void) {
char buffer[64];
volatile uint32_t canary = 0xDEADBEEF;
embsec_printf("Enter your name (max 63 chars): ");
// Intentionally vulnerable!
char input[256];
embsec_gets(input, sizeof(input));
// Copy without bounds checking (vulnerable!)
strcpy(buffer, input);
embsec_printf("Hello, %s!\n", buffer);
// Check if buffer was overflowed
if (canary != 0xDEADBEEF) {
embsec_printf("\n*** BUFFER OVERFLOW DETECTED! ***\n");
embsec_printf("Canary value corrupted: 0x%08X\n", canary);
// Generate flag for successful exploit
embsec_flag_t flag;
embsec_generate_flag_str(&flag, "buffer-overflow-basic");
embsec_print_flag(&flag);
}
}
int main(void) {
embsec_init();
embsec_printf("\n=== Buffer Overflow Challenge ===\n");
embsec_printf("Can you overflow the buffer?\n\n");
while (1) {
vulnerable_function();
embsec_printf("\nTry again? (y/n): ");
char c = embsec_getchar();
embsec_printf("%c\n", c);
if (c == 'n' || c == 'N') {
break;
}
}
return 0;
}
Format String Challenge¶
Example format string vulnerability:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/flag.h>
void print_user_string(void) {
char buffer[256];
volatile uint32_t secret = 0x1337BEEF;
volatile uint32_t modified = 0;
embsec_printf("Secret value at %p: 0x%08X\n", &secret, secret);
embsec_printf("Enter format string: ");
embsec_gets(buffer, sizeof(buffer));
// Vulnerable printf!
embsec_printf(buffer);
embsec_printf("\n");
if (secret != 0x1337BEEF) {
embsec_printf("\n*** SECRET MODIFIED! ***\n");
embsec_printf("New value: 0x%08X\n", secret);
modified = 1;
}
if (modified) {
embsec_flag_t flag;
embsec_generate_flag_str(&flag, "format-string-write");
embsec_print_flag(&flag);
}
}
int main(void) {
embsec_init();
embsec_printf("\n=== Format String Challenge ===\n");
embsec_printf("Can you modify the secret value?\n");
embsec_printf("Hint: Try %%x to read stack values\n\n");
while (1) {
print_user_string();
embsec_printf("\nTry again? (y/n): ");
char c = embsec_getchar();
embsec_printf("%c\n", c);
if (c == 'n' || c == 'N') {
break;
}
}
return 0;
}
Complete Application¶
Multi-Level CTF Game¶
A complete CTF application with multiple challenges:
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <embsec/gpio.h>
#include <embsec/timer.h>
#include <embsec/crypto.h>
#include <embsec/flag.h>
#include <string.h>
// Game state
typedef struct {
bool level1_complete;
bool level2_complete;
bool level3_complete;
uint32_t start_time;
uint32_t score;
} game_state_t;
game_state_t game = {0};
// Level 1: Simple password
bool level1_password(void) {
char password[32];
embsec_printf("\n=== Level 1: Password ===\n");
embsec_printf("The password is hidden in the code...\n");
embsec_printf("Enter password: ");
embsec_gets(password, sizeof(password));
// "Hidden" password
if (strcmp(password, "embedded2024") == 0) {
game.level1_complete = true;
game.score += 100;
embsec_flag_t flag;
embsec_generate_flag_str(&flag, "ctf-level1");
embsec_print_flag(&flag);
return true;
}
embsec_printf("Wrong password!\n");
return false;
}
// Level 2: Button sequence
bool level2_buttons(void) {
const uint8_t sequence[] = {EMBSEC_SW1, EMBSEC_SW2, EMBSEC_SW1, EMBSEC_SW1, EMBSEC_SW2};
int index = 0;
embsec_printf("\n=== Level 2: Button Sequence ===\n");
embsec_printf("Press the correct 5-button sequence\n");
embsec_printf("LEDs will guide you...\n\n");
// Show hint with LEDs
for (int i = 0; i < 5; i++) {
if (sequence[i] == EMBSEC_SW1) {
embsec_led_set(EMBSEC_LED_RED, true);
} else {
embsec_led_set(EMBSEC_LED_BLUE, true);
}
embsec_delay_ms(500);
embsec_led_set(EMBSEC_LED_RED | EMBSEC_LED_BLUE, false);
embsec_delay_ms(300);
}
embsec_printf("Now repeat the sequence:\n");
uint32_t timeout_start = embsec_millis();
while (index < 5) {
// Timeout after 10 seconds
if (embsec_timeout(timeout_start, 10000)) {
embsec_printf("Timeout! Try again.\n");
return false;
}
if (embsec_switch_read(EMBSEC_SW1)) {
embsec_switch_wait(EMBSEC_SW1, 50);
if (sequence[index] == EMBSEC_SW1) {
embsec_led_set(EMBSEC_LED_GREEN, true);
embsec_delay_ms(200);
embsec_led_set(EMBSEC_LED_GREEN, false);
index++;
} else {
embsec_led_set(EMBSEC_LED_RED, true);
embsec_delay_ms(500);
embsec_led_set(EMBSEC_LED_RED, false);
embsec_printf("Wrong sequence!\n");
return false;
}
}
if (embsec_switch_read(EMBSEC_SW2)) {
embsec_switch_wait(EMBSEC_SW2, 50);
if (sequence[index] == EMBSEC_SW2) {
embsec_led_set(EMBSEC_LED_GREEN, true);
embsec_delay_ms(200);
embsec_led_set(EMBSEC_LED_GREEN, false);
index++;
} else {
embsec_led_set(EMBSEC_LED_RED, true);
embsec_delay_ms(500);
embsec_led_set(EMBSEC_LED_RED, false);
embsec_printf("Wrong sequence!\n");
return false;
}
}
}
game.level2_complete = true;
game.score += 200;
embsec_printf("Correct sequence!\n");
embsec_flag_t flag;
embsec_generate_flag_str(&flag, "ctf-level2");
embsec_print_flag(&flag);
return true;
}
// Level 3: Crypto challenge
bool level3_crypto(void) {
embsec_printf("\n=== Level 3: Cryptography ===\n");
// Generate random challenge
uint8_t challenge[16];
embsec_random_bytes(challenge, sizeof(challenge));
embsec_printf("Challenge: ");
for (int i = 0; i < 16; i++) {
embsec_printf("%02x", challenge[i]);
}
embsec_printf("\n");
// Expected response is SHA256(challenge || "embsec")
uint8_t expected[32];
embsec_sha256_ctx_t ctx;
embsec_sha256_init(&ctx);
embsec_sha256_update(&ctx, challenge, sizeof(challenge));
embsec_sha256_update(&ctx, (const uint8_t *)"embsec", 6);
embsec_sha256_final(&ctx, expected);
embsec_printf("Calculate SHA256(challenge || \"embsec\")\n");
embsec_printf("Enter first 8 bytes as hex: ");
char response[17];
embsec_gets(response, sizeof(response));
// Convert response to bytes
uint8_t response_bytes[8];
for (int i = 0; i < 8; i++) {
char hex[3] = {response[i*2], response[i*2+1], '\0'};
response_bytes[i] = (uint8_t)strtol(hex, NULL, 16);
}
if (embsec_crypto_memcmp(response_bytes, expected, 8) == 0) {
game.level3_complete = true;
game.score += 300;
embsec_printf("Correct!\n");
embsec_flag_t flag;
embsec_generate_flag_str(&flag, "ctf-level3");
embsec_print_flag(&flag);
return true;
}
embsec_printf("Incorrect response!\n");
return false;
}
void show_status(void) {
embsec_printf("\n=== Game Status ===\n");
embsec_printf("Level 1: %s\n", game.level1_complete ? "COMPLETE" : "Incomplete");
embsec_printf("Level 2: %s\n", game.level2_complete ? "COMPLETE" : "Incomplete");
embsec_printf("Level 3: %s\n", game.level3_complete ? "COMPLETE" : "Incomplete");
embsec_printf("Score: %u/600\n", game.score);
if (game.score == 600) {
uint32_t elapsed = embsec_elapsed_ms(game.start_time);
embsec_printf("\n*** ALL LEVELS COMPLETE! ***\n");
embsec_printf("Time: %u seconds\n", elapsed / 1000);
// Generate master flag
embsec_flag_t flag;
char salt[64];
snprintf(salt, sizeof(salt), "ctf-master-%u", elapsed);
embsec_generate_flag(&flag, (uint8_t *)salt, strlen(salt));
embsec_printf("\nMaster ");
embsec_print_flag(&flag);
}
}
int main(void) {
embsec_init();
embsec_printf("\n");
embsec_printf(" _____ _____ _____ _____ _____ _____ \n");
embsec_printf(" | __| | __ | | |_ _| __|\n");
embsec_printf(" | __| | | | __ -| | --| | | | __|\n");
embsec_printf(" |_____|_|_|_|_____| |_____| |_| |__| \n");
embsec_printf("\n");
embsec_printf("=== EmbSec CTF Challenge ===\n");
embsec_printf("Complete all 3 levels to win!\n");
embsec_printf("Type 'help' for commands\n");
game.start_time = embsec_millis();
char cmd[32];
while (1) {
embsec_printf("\n> ");
if (embsec_gets(cmd, sizeof(cmd))) {
if (strcmp(cmd, "help") == 0) {
embsec_printf("Commands:\n");
embsec_printf(" level1 - Start level 1\n");
embsec_printf(" level2 - Start level 2\n");
embsec_printf(" level3 - Start level 3\n");
embsec_printf(" status - Show progress\n");
embsec_printf(" reset - Reset game\n");
}
else if (strcmp(cmd, "level1") == 0) {
if (!game.level1_complete) {
level1_password();
} else {
embsec_printf("Level 1 already complete!\n");
}
}
else if (strcmp(cmd, "level2") == 0) {
if (!game.level2_complete) {
level2_buttons();
} else {
embsec_printf("Level 2 already complete!\n");
}
}
else if (strcmp(cmd, "level3") == 0) {
if (!game.level3_complete) {
level3_crypto();
} else {
embsec_printf("Level 3 already complete!\n");
}
}
else if (strcmp(cmd, "status") == 0) {
show_status();
}
else if (strcmp(cmd, "reset") == 0) {
memset(&game, 0, sizeof(game));
game.start_time = embsec_millis();
embsec_printf("Game reset!\n");
}
else if (strlen(cmd) > 0) {
embsec_printf("Unknown command: %s\n", cmd);
}
}
}
}
This comprehensive example demonstrates:
- Multiple challenge types
- Game state management
- Progress tracking
- Time measurement
- Flag generation for each level
- Master flag for completion
- Interactive menu system
- LED and button integration
- Cryptographic challenges