GuideInternet of ThingsIoT Security

IoT Security for Embedded Systems

A comprehensive guide to implementing security measures for IoT embedded systems, covering threat models, encryption, authentication, secure boot, and practical implementation examples.

IoT Security for Embedded Systems

Security is a critical concern for IoT embedded systems, which often operate in uncontrolled environments and handle sensitive data. This guide explores security threats, protection mechanisms, and practical implementation strategies for securing IoT devices.

Threat Models

Understanding potential threats is the first step in developing effective security measures.

Security Architecture

A comprehensive security architecture addresses threats at multiple layers.

Hardware security measures include:

  • Secure Elements: Dedicated hardware for cryptographic operations
  • Trusted Platform Modules (TPM): Hardware-based security for key storage and attestation
  • Secure Boot: Hardware-verified boot process
  • Memory Protection: Hardware-based memory isolation
  • Anti-Tamper Mechanisms: Detect and respond to physical tampering
  • Random Number Generators: Hardware-based entropy sources

Hardware security provides a foundation that cannot be compromised by software alone.

Cryptographic Fundamentals

Cryptography is essential for securing IoT communications and data.

Symmetric Encryption

// Example of AES-128 encryption
void encryptData(uint8_t *plaintext, size_t plaintextLen, 
                 uint8_t *key, uint8_t *iv, uint8_t *ciphertext) {
    // Initialize AES context
    mbedtls_aes_context aes;
    mbedtls_aes_init(&aes);
    
    // Set encryption key
    mbedtls_aes_setkey_enc(&aes, key, 128);
    
    // Encrypt data in CBC mode
    uint8_t iv_copy[16];
    memcpy(iv_copy, iv, 16);
    
    for (size_t i = 0; i < plaintextLen; i += 16) {
        mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, 16, 
                              iv_copy, &plaintext[i], &ciphertext[i]);
    }
    
    // Clean up
    mbedtls_aes_free(&aes);
}

Asymmetric Encryption

// Example of RSA encryption
bool encryptWithRSA(uint8_t *data, size_t dataLen, 
                    uint8_t *publicKey, size_t keyLen, 
                    uint8_t *encrypted, size_t *encryptedLen) {
    // Initialize RSA context
    mbedtls_rsa_context rsa;
    mbedtls_rsa_init(&rsa);
    
    // Parse public key
    int ret = mbedtls_pk_parse_public_key(&rsa, publicKey, keyLen);
    if (ret != 0) {
        mbedtls_rsa_free(&rsa);
        return false;
    }
    
    // Encrypt data
    ret = mbedtls_rsa_pkcs1_encrypt(&rsa, mbedtls_ctr_drbg_random, NULL,
                                    MBEDTLS_RSA_PRIVATE, dataLen, data, encrypted);
    
    // Get encrypted length
    *encryptedLen = mbedtls_mpi_size(&rsa.N);
    
    // Clean up
    mbedtls_rsa_free(&rsa);
    
    return (ret == 0);
}

Hash Functions

// Example of SHA-256 hashing
void computeHash(uint8_t *data, size_t dataLen, uint8_t *hash) {
    // Initialize SHA-256 context
    mbedtls_sha256_context sha256;
    mbedtls_sha256_init(&sha256);
    mbedtls_sha256_starts(&sha256, 0); // 0 = SHA-256, 1 = SHA-224
    
    // Update with data
    mbedtls_sha256_update(&sha256, data, dataLen);
    
    // Finalize hash
    mbedtls_sha256_finish(&sha256, hash);
    
    // Clean up
    mbedtls_sha256_free(&sha256);
}

Authentication and Authorization

Ensuring that only authorized entities can access IoT devices and their data.

Device authentication methods include:

  • Certificate-Based Authentication: Using X.509 certificates
  • Pre-Shared Keys: Symmetric keys established during provisioning
  • Device Identity: Unique identifiers with cryptographic proof
  • Attestation: Verifying device integrity and configuration

Example certificate-based authentication:

// Example of TLS client authentication with certificates
bool setupSecureConnection(const char *server, int port, 
                           const char *caCert, const char *clientCert, 
                           const char *clientKey) {
    // Initialize TLS context
    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    mbedtls_x509_crt cacert;
    mbedtls_x509_crt clientCert;
    mbedtls_pk_context clientKey;
    
    mbedtls_ssl_init(&ssl);
    mbedtls_ssl_config_init(&conf);
    mbedtls_x509_crt_init(&cacert);
    mbedtls_x509_crt_init(&clientCert);
    mbedtls_pk_init(&clientKey);
    
    // Load CA certificate
    int ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *)caCert, 
                                     strlen(caCert) + 1);
    if (ret != 0) {
        goto cleanup;
    }
    
    // Load client certificate and key
    ret = mbedtls_x509_crt_parse(&clientCert, (const unsigned char *)clientCert, 
                                 strlen(clientCert) + 1);
    if (ret != 0) {
        goto cleanup;
    }
    
    ret = mbedtls_pk_parse_key(&clientKey, (const unsigned char *)clientKey, 
                               strlen(clientKey) + 1, NULL, 0);
    if (ret != 0) {
        goto cleanup;
    }
    
    // Set up SSL configuration
    ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT,
                                      MBEDTLS_SSL_TRANSPORT_STREAM, 
                                      MBEDTLS_SSL_PRESET_DEFAULT);
    if (ret != 0) {
        goto cleanup;
    }
    
    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
    mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
    mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, NULL);
    
    ret = mbedtls_ssl_conf_own_cert(&conf, &clientCert, &clientKey);
    if (ret != 0) {
        goto cleanup;
    }
    
    // Set up SSL context
    ret = mbedtls_ssl_setup(&ssl, &conf);
    if (ret != 0) {
        goto cleanup;
    }
    
    // Connect to server
    ret = mbedtls_net_connect(&ssl, server, port, MBEDTLS_NET_PROTO_TCP);
    if (ret != 0) {
        goto cleanup;
    }
    
    // Perform SSL handshake
    while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
        if (ret != MBEDTLS_ERR_SSL_WANT_READ && 
            ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
            goto cleanup;
        }
    }
    
    // Verify server certificate
    uint32_t flags = mbedtls_ssl_get_verify_result(&ssl);
    if (flags != 0) {
        goto cleanup;
    }
    
    // Connection established successfully
    return true;
    
cleanup:
    mbedtls_ssl_free(&ssl);
    mbedtls_ssl_config_free(&conf);
    mbedtls_x509_crt_free(&cacert);
    mbedtls_x509_crt_free(&clientCert);
    mbedtls_pk_free(&clientKey);
    return false;
}

Secure Boot and Firmware Updates

Ensuring the integrity of device firmware from boot through updates.

Practical Implementation

Let's look at a practical example of implementing security in an IoT temperature sensor.

Hardware Setup

// Pin definitions
#define TEMP_SENSOR_PIN     GPIO_NUM_4  // I2C temperature sensor
#define WIFI_ENABLE_PIN     GPIO_NUM_5  // WiFi enable pin
#define LED_STATUS_PIN      GPIO_NUM_2  // Status LED
#define SECURE_ELEMENT_PIN  GPIO_NUM_15 // Secure element chip select

Security Initialization

// Initialize security components
bool initializeSecurity() {
    // Initialize secure element
    if (!initSecureElement(SECURE_ELEMENT_PIN)) {
        return false;
    }
    
    // Generate device identity if not already present
    if (!hasDeviceIdentity()) {
        if (!generateDeviceIdentity()) {
            return false;
        }
    }
    
    // Initialize TLS
    if (!initTLS()) {
        return false;
    }
    
    return true;
}

Secure Communication

// Establish secure connection to server
bool connectToServer(const char *server, int port) {
    // Load certificates and keys from secure element
    uint8_t caCert[2048];
    uint8_t clientCert[2048];
    uint8_t clientKey[2048];
    size_t caCertLen, clientCertLen, clientKeyLen;
    
    if (!loadCertificatesFromSecureElement(caCert, &caCertLen,
                                          clientCert, &clientCertLen,
                                          clientKey, &clientKeyLen)) {
        return false;
    }
    
    // Set up secure connection
    return setupSecureConnection(server, port, 
                                (char *)caCert, (char *)clientCert, (char *)clientKey);
}

Main Loop

// Main application loop
void app_main() {
    // Initialize GPIO
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << WIFI_ENABLE_PIN) | (1ULL << LED_STATUS_PIN),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    gpio_config(&io_conf);
    
    // Initialize security
    if (!initializeSecurity()) {
        // Blink LED rapidly to indicate security failure
        while (1) {
            gpio_set_level(LED_STATUS_PIN, 1);
            vTaskDelay(pdMS_TO_TICKS(100));
            gpio_set_level(LED_STATUS_PIN, 0);
            vTaskDelay(pdMS_TO_TICKS(100));
        }
    }
    
    // Enable WiFi
    gpio_set_level(WIFI_ENABLE_PIN, 1);
    
    // Connect to WiFi network
    if (!connectToWiFi("MySecureNetwork", "MyPassword")) {
        // Handle WiFi connection failure
        return;
    }
    
    // Connect to server securely
    if (!connectToServer("iot.example.com", 8883)) {
        // Handle server connection failure
        return;
    }
    
    // Initialize temperature sensor
    if (!initTemperatureSensor(TEMP_SENSOR_PIN)) {
        // Handle sensor initialization failure
        return;
    }
    
    while (1) {
        // Read temperature
        float temperature;
        if (readTemperature(&temperature)) {
            // Encrypt temperature data
            uint8_t plaintext[32];
            uint8_t ciphertext[64];
            size_t plaintextLen = snprintf((char *)plaintext, sizeof(plaintext), 
                                          "{\"temp\": %.2f}", temperature);
            
            // Generate random IV
            uint8_t iv[16];
            generateRandomBytes(iv, 16);
            
            // Encrypt data
            encryptData(plaintext, plaintextLen, ENCRYPTION_KEY, iv, ciphertext);
            
            // Send encrypted data
            sendEncryptedData(ciphertext, plaintextLen + 16 + 16); // Data + IV + padding
            
            // Blink LED to indicate activity
            gpio_set_level(LED_STATUS_PIN, 1);
            vTaskDelay(pdMS_TO_TICKS(100));
            gpio_set_level(LED_STATUS_PIN, 0);
        }
        
        // Wait before next reading
        vTaskDelay(pdMS_TO_TICKS(300000)); // 5 minutes
    }
}

Next Steps

Now that you understand IoT security for embedded systems, you can explore: