Skip to content

Issue at br_sslio_flush(&_ioc) inside int BearSSLClient::connectSSL(const char* host) when using MQTT on Arduino MKRNB 1500 #92

Open
@itadminkema

Description

@itadminkema

Hello,

I am facing an issue while attempting to connect my Arduino MKR 1500 NB to an MQTT broker using a combination of NBClient, BearSSLClient, and arduinoMqttClient libraries. Despite successfully connecting to the NB IoT network and establishing a UDP connection to an NTP server, the connection to the MQTT broker fails during the inital BearSSL connect process. The failure occurs specifically during the br_sslio_flush(&_ioc) call in the BearSSLClient::connectSSL function, where the program freezes without generating a response, timeout, or error. Could this issue be related to an inconsistency in the character sequence length following the AT command issued to the NBIoT module? Or is it something else?


I am using an Arduino MKR 1500 NB client -> BearSSLClient ->arduinoMqttClient

// Initialize MQTT and SSL clients  from library
NBClient nbClient;
BearSSLClient sslClient(nbClient);
MqttClient arduinoMqttClient(sslClient);

I am able to connect to the NB IoT network and I am even able to start a UDP connection to an NTP server (which is used for
ArduinoBearSSL.onGetTime(get_time); // Required for server trusted root validation.
)

We then get ready to initialize the MQTT client, and the problem comes up when we run arduinoMqttClient.connect(address,port) link:

arduinoMqttClient.setId(client_id);
arduinoMqttClient.setUsernamePassword(username, password);
arduinoMqttClient.setCleanSession(true);
arduinoMqttClient.onMessage(on_message_received);

LogInfo("MQTT Client ID: %s", client_id);
LogInfo("MQTT Username: %s", username);
LogInfo("MQTT Password: ***");
LogInfo("MQTT client address: %s", address);
LogInfo("MQTT client port: %d", port);

bool mqtt_connected = false;
Serial.println("MQTT Connecting MQTT client...");
while (!mqtt_connected)  {
  if (arduinoMqttClient.connect(address, port)){
    Serial.println("Succesful MQTT connection to Azure broker!");
    mqtt_connected = true;
  }
  else {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(arduinoMqttClient.connectError());
    //int code = arduinoMqttClient.connectError();
    //LogError("Cannot connect. Error Code: %d", code);
    delay(5000);
  }
}

arduinoMqttClient.connect(address,port) calls, which runs until _client->connect(host, port):

int MqttClient::connect(IPAddress ip, const char* host, uint16_t port)
{
  Serial.println("MQTTClient : Start connect");
  if (clientConnected()) {
    _client->stop();
  }
  _rxState = MQTT_CLIENT_RX_STATE_READ_TYPE;
  _connected = false;
  _txPacketId = 0x0000;

  if (host) {
    Serial.println("MQTTClient : Connecting by host");
    if (!_client->connect(host, port)) {
      _connectError = MQTT_CONNECTION_REFUSED;
      Serial.println("MQTTClient : 0 - host connection refused");
      return 0;
    }
}

_client->connect(host, port) seems to trigger a call to two functions:

  1. First it calls int NBClient::connect() link which executes successfully and creates a TCP socket with "global.azure-devices-provisioning.net",8883:
  2. After that in triggers int BearSSLClient::connectSSL(const char* host) which is where the failure occurs, specifically on the call to br_sslio_flush(&_ioc); function:
  • At that time there is an AT command issued to the NBIoT module and after that the program doesn't genereate any reposnse or timeout or error return. It just freezes.

  • One thing that I did note is that the character sequence following the AT+USOWR command is not of the same length as specified in the start of the AT command (178 vs the 242 supposed to be sent). But I don't know if this is just an issue with MAX number of characters in arduino's Serial.println()

-Here are the Serial.print() statments I am using for debugging aling with the AT commands sent by MKRNB module:

14:03:39.127 -> MQTTClient : Start connect
14:03:39.127 -> MQTTClient : Connecting by host
14:03:39.127 -> NBC : Starting NB connect
14:03:39.127 -> 1
14:03:39.218 -> AT+USOCR=6

14:03:39.218 -> +USOCR: 1
14:03:39.218 -> 
14:03:39.252 -> OK
14:03:39.428 -> AT+USOCO=1,"global.azure-devices-provisioning.net",8883

14:03:43.042 -> OK
14:03:43.042 -> NBC : 1 - success END

14:03:43.042 -> BSSL : Starting BSSL connect
14:03:43.168 -> AT+USOST=0,"129.6.15.28",123,48,"E30006EC0000000000000000314E31340000000000000000000000000000000000000000000000000000000000000000"

14:03:43.168 -> +USOST: 0,48
14:03:43.214 -> 
14:03:43.214 -> OK
14:03:43.214 -> 1 - Waiting for time packet....
14:03:44.199 -> +UUSORF: 0,48
14:03:44.199 -> AT+USORF=0,512

14:03:44.240 -> 
14:03:44.240 -> +USORF: 0,"129.6.15.28",123,48,"1C010DE300000010000000204E495354EA60F480000000000000000000000000EA60F4A027DB0056EA60F4A027DB15F6"
14:03:44.240 -> OK
14:03:44.240 ->  NTP packet received
14:03:44.240 -> BSSL : Finish random - get_time()
14:03:44.240 -> BSSL : Begin socket init
14:03:44.240 -> BSSL : socketflush
14:03:44.240 -> AT+USORD=1,512

14:03:44.240 -> +USORD: 1,""
14:03:44.240 -> 
14:03:44.240 -> OK
14:03:44.308 -> AT+USOWR=1,242,"16030100ED010000E9030300000000D7C94A75B33CD7C36976D1E83A101F715E653FA3017151659FDD639900005ACCA9CCA8C02BC02FC02CC030C0ACC0ADC0AEC0AFC023C027C024C028C009C013C00AC014C02DC031C02EC032C025C029C026C02AC004C00EC005C00F009C009DC09CC09DC0A0C0A1003C003D002F0035C008C012C003C00D000A01000066FF010001000000002A0028000025676C6F62616C2E617A7572652D646576696365732D70726F

Additional int BearSSLClient::connectSSL(const char* host) reference code with debug Serial.println() statements added:

int BearSSLClient::connectSSL(const char* host)
{
  Serial.println("BSSL : Starting BSSL connect");
  if (!_br_ssl_client_init_function) {
    return 0;
  }

  // initialize client context with enabled algorithms and trust anchors
  _br_ssl_client_init_function(&_sc, &_xc, _TAs, _numTAs);

  br_ssl_engine_set_buffers_bidi(&_sc.eng, _ibuf, sizeof(_ibuf), _obuf, sizeof(_obuf));

  // inject entropy in engine
  unsigned char entropy[32];

#ifndef ARDUINO_DISABLE_ECCX08
  if (!ECCX08.begin() || !ECCX08.locked() || !ECCX08.random(entropy, sizeof(entropy))) {
#endif
    // no ECCX08 or random failed, fallback to pseudo random
    for (size_t i = 0; i < sizeof(entropy); i++) {
      entropy[i] = random(0, 255);
    }
#ifndef ARDUINO_DISABLE_ECCX08
  }
#endif
  br_ssl_engine_inject_entropy(&_sc.eng, entropy, sizeof(entropy));

  // add custom ECDSA vfry and EC sign
  br_ssl_engine_set_ecdsa(&_sc.eng, _ecVrfy);
  br_x509_minimal_set_ecdsa(&_xc, br_ssl_engine_get_ec(&_sc.eng), br_ssl_engine_get_ecdsa(&_sc.eng));

  // enable client auth
  if (_ecCert[0].data_len) {
#ifndef ARDUINO_BEARSSL_DISABLE_KEY_DECODER
    if (_skeyDecoder) {
      int skeyType = br_skey_decoder_key_type(_skeyDecoder);

      if (skeyType == BR_KEYTYPE_EC) {
        br_ssl_client_set_single_ec(&_sc, _ecCert, _ecChainLen, br_skey_decoder_get_ec(_skeyDecoder), BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), br_ecdsa_sign_asn1_get_default());
      } else if (skeyType == BR_KEYTYPE_RSA) {
        br_ssl_client_set_single_rsa(&_sc, _ecCert, _ecChainLen, br_skey_decoder_get_rsa(_skeyDecoder), br_rsa_pkcs1_sign_get_default());
      }
    } else {
#endif
      br_ssl_client_set_single_ec(&_sc, _ecCert, _ecChainLen, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), _ecSign);
#ifndef ARDUINO_BEARSSL_DISABLE_KEY_DECODER
    }
#endif
  }

  // set the hostname used for SNI
  br_ssl_client_reset(&_sc, host, 0);

  // get the current time and set it for X.509 validation
  uint32_t now = ArduinoBearSSL.getTime();
  uint32_t days = now / 86400 + 719528;
  uint32_t sec = now % 86400;
  Serial.println("BSSL : Finish random - get_time()");

  br_x509_minimal_set_time(&_xc, days, sec);

  Serial.println("BSSL : Begin socket init");
  // use our own socket I/O operations
  br_sslio_init(&_ioc, &_sc.eng, BearSSLClient::clientRead, _client, BearSSLClient::clientWrite, _client);

  Serial.println("BSSL : socketflush");
  br_sslio_flush(&_ioc);
  Serial.println("BSSL : PROBLEM HERE!");

  while (1) {
    Serial.println("BSSL : get state, on loop");
    unsigned state = br_ssl_engine_current_state(&_sc.eng);

    Serial.println("BSSL : run ifs");
    if (state & BR_SSL_SENDAPP) {
      break;
    } else if (state & BR_SSL_CLOSED) {
      return 0;
    }
    Serial.println("BSSL : help, trap");
  }

  Serial.println("BSSL : 1 - success END");
  return 1;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: imperfectionPerceived defect in any part of project

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions