Security Guidelines

Security best practices for the Nexus Embedded Platform.

Overview

Security is critical in embedded systems. This guide covers:

  • Input Validation: Prevent injection attacks

  • Memory Safety: Prevent buffer overflows

  • Cryptography: Secure data and communications

  • Access Control: Protect sensitive resources

  • Secure Boot: Verify firmware integrity

  • Update Security: Secure firmware updates

Secure Coding Practices

Input Validation

Always Validate Inputs

/* Bad: No validation */
void process_data(uint8_t* buffer, size_t length) {
    memcpy(internal_buffer, buffer, length);  /* Overflow! */
}

/* Good: Validate inputs */
hal_status_t process_data(const uint8_t* buffer, size_t length) {
    if (buffer == NULL) {
        return HAL_ERROR_PARAM;
    }
    if (length == 0 || length > MAX_BUFFER_SIZE) {
        return HAL_ERROR_PARAM;
    }
    memcpy(internal_buffer, buffer, length);
    return HAL_OK;
}

Range Checking

/* Validate array indices */
hal_status_t set_value(size_t index, uint32_t value) {
    if (index >= ARRAY_SIZE) {
        return HAL_ERROR_PARAM;
    }
    array[index] = value;
    return HAL_OK;
}

Integer Overflow Checks

/* Check for overflow before allocation */
void* safe_alloc(size_t count, size_t size) {
    if (count > 0 && size > SIZE_MAX / count) {
        return NULL;  /* Would overflow */
    }
    return malloc(count * size);
}

Buffer Overflow Prevention

Use Safe String Functions

/* Bad: Unsafe string copy */
void copy_string_unsafe(char* dest, const char* src) {
    strcpy(dest, src);  /* Buffer overflow risk! */
}

/* Good: Safe string copy */
void copy_string_safe(char* dest, size_t dest_size, const char* src) {
    if (dest == NULL || src == NULL || dest_size == 0) {
        return;
    }
    strncpy(dest, src, dest_size - 1);
    dest[dest_size - 1] = '\0';
}

Bounds Checking

/* Always check buffer bounds */
hal_status_t write_buffer(uint8_t* buffer, size_t buffer_size,
                          const uint8_t* data, size_t data_size) {
    if (buffer == NULL || data == NULL) {
        return HAL_ERROR_PARAM;
    }
    if (data_size > buffer_size) {
        return HAL_ERROR_NO_MEMORY;
    }
    memcpy(buffer, data, data_size);
    return HAL_OK;
}

Memory Safety

Pointer Safety

Null Pointer Checks

/* Always check pointers */
hal_status_t process_config(const config_t* config) {
    if (config == NULL) {
        return HAL_ERROR_PARAM;
    }
    /* Use config */
    return HAL_OK;
}

Avoid Use-After-Free

/* Bad: Use after free */
void bad_example(void) {
    uint8_t* buffer = malloc(256);
    free(buffer);
    buffer[0] = 0;  /* Use after free! */
}

/* Good: Clear pointer after free */
void good_example(void) {
    uint8_t* buffer = malloc(256);
    free(buffer);
    buffer = NULL;  /* Prevent use after free */
}

Double-Free Prevention

/* Safe free macro */
#define SAFE_FREE(ptr) \
    do { \
        if (ptr != NULL) { \
            free(ptr); \
            ptr = NULL; \
        } \
    } while(0)

Stack Protection

Stack Canaries

#define STACK_CANARY 0xDEADBEEF

void protected_function(void) {
    uint32_t canary = STACK_CANARY;

    /* Function code */

    /* Check canary */
    if (canary != STACK_CANARY) {
        /* Stack overflow detected */
        handle_security_violation();
    }
}

Cryptography

Random Number Generation

Use Hardware RNG

/* Use hardware random number generator */
uint32_t get_random(void) {
    /* Enable RNG clock */
    RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;

    /* Enable RNG */
    RNG->CR |= RNG_CR_RNGEN;

    /* Wait for random data */
    while (!(RNG->SR & RNG_SR_DRDY));

    return RNG->DR;
}

Seed PRNG Properly

/* Seed with hardware RNG */
void seed_prng(void) {
    uint32_t seed = get_random();
    srand(seed);
}

Encryption

AES Encryption

/* Encrypt data with AES */
hal_status_t encrypt_data(const uint8_t* plaintext, size_t length,
                          const uint8_t* key, uint8_t* ciphertext) {
    if (plaintext == NULL || key == NULL || ciphertext == NULL) {
        return HAL_ERROR_PARAM;
    }

    /* Initialize AES */
    aes_context_t ctx;
    aes_init(&ctx, key, AES_KEY_SIZE_256);

    /* Encrypt */
    aes_encrypt(&ctx, plaintext, ciphertext, length);

    /* Clear sensitive data */
    memset(&ctx, 0, sizeof(ctx));

    return HAL_OK;
}

Secure Storage

Key Storage

Never Hardcode Keys

/* Bad: Hardcoded key */
const uint8_t encryption_key[] = {
    0x01, 0x02, 0x03, /* ... */
};

/* Good: Load from secure storage */
hal_status_t load_encryption_key(uint8_t* key, size_t key_size) {
    return secure_storage_read(KEY_ID, key, key_size);
}

Clear Sensitive Data

/* Clear sensitive data after use */
void process_password(const char* password) {
    /* Use password */
    authenticate(password);

    /* Clear from memory */
    memset((void*)password, 0, strlen(password));
}

Secure Boot

Firmware Verification

Verify Signature

/* Verify firmware signature */
bool verify_firmware(const uint8_t* firmware, size_t length,
                    const uint8_t* signature) {
    uint8_t hash[32];

    /* Calculate firmware hash */
    sha256(firmware, length, hash);

    /* Verify signature */
    return rsa_verify(hash, sizeof(hash), signature, public_key);
}

Secure Boot Flow

void secure_boot(void) {
    /* Read firmware */
    uint8_t* firmware = (uint8_t*)FIRMWARE_ADDRESS;
    size_t length = get_firmware_length();

    /* Read signature */
    uint8_t* signature = (uint8_t*)SIGNATURE_ADDRESS;

    /* Verify firmware */
    if (!verify_firmware(firmware, length, signature)) {
        /* Verification failed */
        enter_recovery_mode();
        return;
    }

    /* Jump to application */
    jump_to_application(FIRMWARE_ADDRESS);
}

Secure Communication

TLS/SSL

Use TLS for Network Communication

/* Establish secure connection */
hal_status_t connect_secure(const char* host, uint16_t port) {
    tls_context_t ctx;

    /* Initialize TLS */
    tls_init(&ctx);

    /* Set CA certificate */
    tls_set_ca_cert(&ctx, ca_cert, ca_cert_len);

    /* Connect */
    if (tls_connect(&ctx, host, port) != TLS_OK) {
        return HAL_ERROR;
    }

    return HAL_OK;
}

Access Control

Privilege Separation

Use MPU for Memory Protection

/* Configure MPU region */
void configure_mpu(void) {
    /* Disable MPU */
    MPU->CTRL = 0;

    /* Configure region 0: Flash (read-only) */
    MPU->RBAR = FLASH_BASE | MPU_RBAR_VALID_Msk | 0;
    MPU->RASR = MPU_RASR_ENABLE_Msk |
                MPU_RASR_SIZE_512KB |
                MPU_RASR_AP_RO_RO;

    /* Configure region 1: RAM (read-write) */
    MPU->RBAR = RAM_BASE | MPU_RBAR_VALID_Msk | 1;
    MPU->RASR = MPU_RASR_ENABLE_Msk |
                MPU_RASR_SIZE_128KB |
                MPU_RASR_AP_RW_RW;

    /* Enable MPU */
    MPU->CTRL = MPU_CTRL_ENABLE_Msk;
}

Security Checklist

Development Checklist

☐ All inputs validated ☐ Buffer bounds checked ☐ No hardcoded secrets ☐ Sensitive data cleared after use ☐ Secure random number generation ☐ Encryption for sensitive data ☐ Firmware signature verification ☐ TLS for network communication ☐ Memory protection enabled ☐ Stack protection enabled

Code Review Checklist

☐ No buffer overflows ☐ No integer overflows ☐ No format string vulnerabilities ☐ No SQL injection (if applicable) ☐ No command injection ☐ Proper error handling ☐ No information leakage ☐ Secure defaults

See Also

Summary

Key security practices:

  • Validate all inputs

  • Prevent buffer overflows

  • Use cryptography correctly

  • Protect sensitive data

  • Verify firmware integrity

  • Use secure communication

  • Implement access control

Security must be considered throughout the development lifecycle.