Secure BLE on ESP32-C3

Hello there, I spent almost a week on trying to get what I want, but to na avail, so please somebody with experience with security in BLE on ESP32(-C3) help...

So, as a part of a bigger project, I want my ESP32-C3 to run a BLE server, and a phone to connect to it.

Since my device has no UI, I need a fixed PIN.

I want no bonding, that is everytime the phone connects the device should not let it in without prior the fixed PIN authentification (does not apply to data exchange, only to connecting)

I have sketch below, and it behaves strange - if I try to connect through system settings of the phone I am asked for PIN, but applications like nRF connect and BLE scanner simply bypass the authentification.

With so many options in the BLE, I believe I am missing something, ot want to achieve something impossible, yet looking basic

Many thanks in advance, here is my sketch

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLESecurity.h>

// Custom Security Callbacks to handle passkey request, confirmation, and security request
class MySecurityCallbacks : public BLESecurityCallbacks {
public:
    uint32_t onPassKeyRequest() override {
        Serial.println("Passkey request, providing static passkey...");
        return 123456;  // Static passkey
    }

    void onPassKeyNotify(uint32_t pass_key) override {
        Serial.print("Passkey Notify: ");
        Serial.println(pass_key);
    }

    bool onSecurityRequest() override {
        Serial.println("Security request received, proceeding with authentication...");
        return true;  // Allow the security request
    }

    bool onConfirmPIN(uint32_t pin) override {
        Serial.print("PIN confirmation: ");
        Serial.println(pin);
        return true;  // Accept the PIN
    }

    void onAuthenticationComplete(esp_ble_auth_cmpl_t auth_cmpl) override {
        if (auth_cmpl.success) {
            Serial.println("Authentication successful!");
        } else {
            Serial.println("Authentication failed.");
        }
    }
};

// BLE Server Callbacks
class MyServerCallbacks : public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
        Serial.println("Device connected");
    }

    void onDisconnect(BLEServer* pServer) {
        Serial.println("Device disconnected");
        // Restart advertising
        pServer->getAdvertising()->start();
    }
};

void setup() {
    Serial.begin(115200);

    // Initialize BLE Device
    BLEDevice::init("ESP32_Secure_Device");
    BLEDevice::setSecurityCallbacks(new MySecurityCallbacks());

    // Create BLE server and set callbacks
    BLEServer* pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks());

    // Create BLE service and characteristic
    BLEService* pService = pServer->createService(BLEUUID("12345678-1234-1234-1234-123456789abc"));
    BLECharacteristic* pCharacteristic = pService->createCharacteristic(
        BLEUUID("87654321-4321-4321-4321-cba987654321"),
        BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE
    );
    pCharacteristic->setValue("Secure Data");

    // Set up BLE Security
    BLESecurity* pSecurity = new BLESecurity();
    pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM);  // Require MITM with secure connections
    pSecurity->setCapability(ESP_IO_CAP_IO);  // Requires passkey or numeric comparison
    pSecurity->setStaticPIN(123456);          // Set static passkey
    pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);

    // Start BLE service
    pService->start();

    // Start advertising
    BLEAdvertising* pAdvertising = pServer->getAdvertising();
    pAdvertising->start();
    Serial.println("BLE server with enforced passkey authentication started...");
}

void loop() {
    // Main loop logic (if any)
}

Is it an app cache issue?
I just had to go deep into settings to force clear cache for something..

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.