Security Pada ESP32 – TLS/DTLS

Pendahuluan

Pada dasarnya, Transport Layer Security (TLS) digunakan untuk enkripsi data yang akan ditransmisikan melalui network, termasuk internet. Tujuannya untuk memastikan komunikasi aman.

Untuk mengamankan koneksi TLS menggunakan asymmetric keys dan symmetric keys. Ketika client melakukan koneksi ke server, terjadi proses TLS handshake. Berikut tahapan yang terjadi saat TLS handshake:

  • Pertukaran algoritma enkripsi yang didukung antar party, yang kemudian digunakan untuk komunikasi.
  • Client akan memeriksa certficate server, untuk memastikan diterbitkan oleh Certificate Authority (CA). Langkah ini penting, agar client tahu, server legitimate atau tidak.
  • Symetric key di generate untuk sesi komunikasi. Kedua belah pihak akan menggunakan symetric key yang sama untuk melakukan encrypt/decryp message.

Ketika TLS handshake berhasil, kedua pihak dapat berkomunikasi melalui application layer protocol, seperti HTTPS, secure-MQTT, atau websockets over TLS (WSS).

Untuk datagram protocols, seperti UDP, digunakan Datagram Transport Layer
Security (DTLS) protocol untuk menyediakan communication security. Cara kerjanya sama dengan TLS. Diatas DTLS, sebagai contoh, kita dapat jalankan Constrained Application Protocol
(CoAP) untuk pertukaran UDP messages antara wireless sensor nodes.

Mari kita lihat contoh penggunaan TLS pada aplikasi. Misalnya, kita ingin mengirim HTTP GET request ke online REST API HTTPS server dan membaca response. Pendekatannya seperti berikut:

  • Kita memerlukan secure server untuk dihubungi. Kita akan gunakan https://reqbin.com, site ini adalah online REST dan SOAP API testing tool yang menyediakan berbagai endpoints untuk keperluan testing. Kita send request ke endpoint /echo/get/json.
  • Kita perlu server’s certificate pada ESP32 untuk TLS connection. Kita akan download secara manual menggunakan openssl dan embed kedalam firmware.
  • Pada firmware, kita buka TLS connection ke the server dengan menggunakan certificate tersebut. Kemudian kita kirim GET request diatas diatas TLS connection. Kita akan mendapatkan reply berisi sample JSON data, yang akan kita tampilkan pada serial monitor, kemudian close connection.

Persiapan Project

Buat project baru, lalu ubah platformio.ini

[env:az-delivery-devkit-v4]
platform = espressif32
board = az-delivery-devkit-v4
framework = espidf
monitor_speed = 115200
build_flags =
-DWIFI_SSID=${sysenv.WIFI_SSID}
-DWIFI_PASS=${sysenv.WIFI_PASS}
board_build.embed_txtfiles = server/server_cert.pem

Update src/CMakeList.txt

FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)
idf_component_register(SRCS ${app_sources})
target_add_binary_data(${COMPONENT_TARGET} "../server/server_cert.pem" TEXT)

Buat folder dengan nama server, untuk menyimpan server certificate. Kita akan download certificate dari server pada langkah selanjutnya. Certificate akan kita gunakan dalam aplikasi untuk berkomunikasi dengan server:

$ mkdir server 
$ cd server

Buka openssl, untuk download server certificate. Setelah certifacate didownload, kita perlu lakukan editing. Terdapat 2 certificate dan informasi lainnya didalam file tersebut. Yang perlu kita simpan dalam file adalah hanya informasi certificate kedua saja.

$ openssl s_client -showcerts -connect reqbin.com:443 > server_cert.pem

Copy wifi_connect library kedalam lib folder yang telah kita gunakan pada modul sebelumnya.

Code

Buka file main.c, gunakan code berikut:

//import library
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_tls.h"
#include "wifi_connect.h"
#include "private_include/esp_tls_mbedtls.h"
static const char *TAG = "tls_ex";
static const char REQUEST[] = "GET /echo/get/json HTTP/1.1\r\n"
"Host: reqbin.com\r\n"
"User-Agent: esp32\r\n"
"Accept: */*\r\n"
"\r\n";
extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_cert_pem_start");
extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_cert_pem_end");

//fungsi http get
static void do_https_get(void *arg)
{
    char buf[512];
    int ret, len;
    esp_tls_cfg_t cfg = {
    .cacert_buf = server_root_cert_pem_start,
    .cacert_bytes = server_root_cert_pem_end - server_root_cert_pem_start,
    };
    struct esp_tls *tls = esp_tls_conn_http_new("https://reqbin.com", &cfg);
    if (tls == NULL)
    {
        ESP_LOGE(TAG, "esp_tls_conn_http_new failed");
        vTaskDelete(NULL);
        return;
    }

    ret = esp_mbedtls_write(tls, REQUEST, strlen(REQUEST));
    if (ret > 0)
    {
        while (1)
        {
            len = sizeof(buf) - 1;
            ret = esp_mbedtls_read(tls, (char *)buf, len);
            if (ret > 0)
            {
                buf[ret] = 0;
                ESP_LOGI(TAG, "%s", buf);
            }
            else
            {
                break;
            }
        }
    }
    esp_tls_conn_delete(tls);
    vTaskDelete(NULL);
}

// wifi connect
void wifi_conn_cb(void)
{
    xTaskCreate(&do_https_get, "https", 8192, NULL, 5, NULL);
}

// wifi failed
void wifi_failed_cb(void)
{
    ESP_LOGE(TAG, "wifi failed");
}

//main funct
void app_main(void)
{
    connect_wifi_params_t p = {
    .on_connected = wifi_conn_cb,
    .on_failed = wifi_failed_cb};
    connect_wifi(p);
}

Penjelasan Code

Bagian Fungsi http get

Fungsi do_https_get melakukan proses connects ke server, mengirim request dan menerima respons.

Pertama kita membuat TLS connection dengan memanggil fungsi calling esp_tls_conn_http_new. Kemudian kita panggil esp_mbedtls_write untuk mengirim REQUEST.

Jika operasi write berhasil, kita gunakan while loop untuk membaca response.

Setelah mengirim request, kita baca response menggunakan perintah esp_mbedtls_read. Baca response kedalam buffer sampai selesai.

Sebelum keluar dari fungsi, kita tutup TLS connection.

Fungsi esp_tls_conn_delete akan membersikan semua resources yang digunakan oleh TLS library.

Compile Dan Upload

Buka platformio CLI.


(penv)$ export WIFI_SSID='\"<local_wifi_ssid>\"'
(penv)$ export WIFI_PASS='\"<local_wifi_password>\"'
(penv)$ pio run && pio run -t upload
(penv)$ pio device monitor

Kita lihat HTTP response dari REST API server pada serial output dari EPS32.

{"success":"true"}

Pada modul selanjutnya kita akan membahas penggunaan secure element.

Sharing is caring:

Leave a Comment