h2zero / NimBLE-Arduino

A fork of the NimBLE library structured for compilation with Arduino, for use with ESP32, nRF5x.
https://h2zero.github.io/NimBLE-Arduino/
Apache License 2.0
670 stars 138 forks source link

Authenticated Write not working #613

Closed Tjulni closed 7 months ago

Tjulni commented 7 months ago

Hi, I have been trying this for the last few days and cannot get it to work... I would like to send and receive secure messages from a client to my secure server on an ESP32C3, but as soon as I add the property WRITE_AUTHEN the program stops receiving messages. What am I doing wrong?

Also the onAuthenticationComplete function is never called when I connect to the server...

Here is my code for my secure server:

#include <NimBLEDevice.h>

#define NAME "TESTING"
#define SERVICE_UUID "af78372c-9215-11ee-b9d1-0242ac120002"
#define RX_UUID "af783b0a-9215-11ee-b9d1-0242ac120002"
#define TX_UUID "af783c36-9215-11ee-b9d1-0242ac120002"

static NimBLEServer* pServer;

class ServerCallbacks: public NimBLEServerCallbacks{    
    void onConnect(NimBLEServer *pServer){
        Serial.println("Connected");

        setPin("8=0");
    };

    void onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
        Serial.print("Client address: ");
        Serial.println(NimBLEAddress(desc->peer_ota_addr).toString().c_str());

        NimBLEDevice::startSecurity(desc->conn_handle);

        pServer->updateConnParams(desc->conn_handle, 0x10, 0x20, 0, 600);

    };

    void onDisconnect(NimBLEServer *pServer){
        Serial.println("Disconnected");
        setPin("8=1");
    };

    void onAuthenticationComplete(ble_gap_conn_desc* desc){
        Serial.println("what the hell");
        if(!desc->sec_state.encrypted) {
            NimBLEDevice::getServer()->disconnect(desc->conn_handle);
            Serial.println("Encrypt connection failed - disconnecting client");
            return;
        }
        Serial.println("Starting BLE work!");
    };
};

class CharacteristicCallbacks: public NimBLECharacteristicCallbacks {
    void onRead(NimBLECharacteristic* pCharacteristic){
        Serial.print(pCharacteristic->getUUID().toString().c_str());
        Serial.print(": onRead(), value: ");
        Serial.println(pCharacteristic->getValue().c_str());
    };

    void onWrite(NimBLECharacteristic* pCharacteristic) {
        Serial.print(pCharacteristic->getUUID().toString().c_str());
        Serial.print(": onWrite(), value: ");
        Serial.println(pCharacteristic->getValue().c_str());
    };

    void onNotify(NimBLECharacteristic* pCharacteristic) {
        //Serial.println("Sending notification to clients");
    };

    void onStatus(NimBLECharacteristic* pCharacteristic, Status status, int code) {
        String str = ("Notf/Ind stscode: ");
        str += status;
        str += ", retcode: ";
        str += code;
        str += ", "; 
        str += NimBLEUtils::returnCodeToString(code);
        //Serial.print(str);
    };

    void onSubscribe(NimBLECharacteristic* pCharacteristic, ble_gap_conn_desc* desc, uint16_t subValue) {
        String str = "Client ID: ";
        str += desc->conn_handle;
        str += " Address: ";
        str += std::string(NimBLEAddress(desc->peer_ota_addr)).c_str();
        if(subValue == 0) {
            str += " Unsubscribed to ";
        }else if(subValue == 1) {
            str += " Subscribed to notfications for ";
        } else if(subValue == 2) {
            str += " Subscribed to indications for ";
        } else if(subValue == 3) {
            str += " Subscribed to notifications and indications for ";
        }
        str += std::string(pCharacteristic->getUUID()).c_str();

        Serial.println(str);
    };
};

static CharacteristicCallbacks chrCallbacks;

void initBLE()
{
    NimBLEDevice::init(NAME);
    NimBLEDevice::setPower(ESP_PWR_LVL_P9);
    NimBLEDevice::setSecurityAuth(false, true, true);
    NimBLEDevice::setSecurityPasskey(123456);
    NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
    NimBLEDevice::setSecurityInitKey(BLE_SM_PAIR_KEY_DIST_ENC);

    pServer = NimBLEDevice::createServer();
    pServer->setCallbacks(new ServerCallbacks());
    pServer->advertiseOnDisconnect(true);

    NimBLEService* pService = pServer->createService(SERVICE_UUID);

    NimBLECharacteristic *pTX = pService->createCharacteristic( TX_UUID,
                                                                NIMBLE_PROPERTY::READ |
                                                                NIMBLE_PROPERTY::READ_ENC |
                                                                NIMBLE_PROPERTY::READ_AUTHEN |
                                                                NIMBLE_PROPERTY::NOTIFY);
    pTX->setCallbacks(&chrCallbacks);

    NimBLECharacteristic *pRX = pService->createCharacteristic( RX_UUID,
                                                                NIMBLE_PROPERTY::WRITE |
                                                                NIMBLE_PROPERTY::WRITE_ENC |
                                                                NIMBLE_PROPERTY::WRITE_AUTHEN);
    pRX->setCallbacks(&chrCallbacks);

    pService->start();
    pTX->setValue("TX");

    NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
    pAdvertising->addServiceUUID(SERVICE_UUID);
    pAdvertising->start();
}
h2zero commented 7 months ago

Can you provide a log at debug level? Also what is the setPin function doing and what is the client device?

Tjulni commented 7 months ago

The setPin function is a simple function that sets a pin to high or low depending on the input, so in this case it sets pin 8 (builtin led) to high (led is off) and low (led is on) if the client is connected. A client is any device that can communicate over ble... I got this workin in the end but had to implement my own symmetric encrytpion and no authentication, so that I can communicate with the server over a python script on my laptop.

Since I figured it out I will close this issue.