Skip to content

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
    }
}

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);
            }
        }
    }
}

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