Skip to content

[Resubmssion] TLS handshake fails with tinygsm regardless of certificate #119

Description

@sadsultan

Description

I am using this fork of TinyGSM with an ESP32 and a SIMCom A7670SA module. I am attempting to make a secure HTTPS GET request using TinyGsmClient wrapped by SSLClient and ArduinoHttpClient.

I modified the TinyGSM example to include my own modem initialization and setup sequence because the original initialization code did not bring the modem into a functional state for my application. I verified the initialization sequence by sniffing the serial communication between the ESP32 and the A7670SA.

The modem initialization, network registration, GPRS connection, and time synchronization all succeed. The same server, port, and root CA certificate work successfully when I replace the TinyGSM client with an ESP32 Wi-Fi client.

The problem occurs when using ArduinoHttpClient with SSLClient and TinyGsmClient: client.get() returns -1, and responseStatusCode() returns -2.

Steps to Reproduce

Connect the module to an esp32 using Serial1 on pins 39 and 17 (RX and TX). and upload the sketch given at the end of the issue.

Expected Behavior

The HTTPS connection should be established successfully and the GET request should return a valid HTTP response, as it does when the same ESP32 uses Wi-Fi with the same server, port, and root CA certificate.

Actual Behavior

With the cellular/TinyGSM client:

Get func returned: -1
Status code: -2

I receive no HTTP response.
The modem itself successfully initializes, registers on the network, establishes GPRS, obtains an IP address.
Replacing the TinyGSM client with a Wi-Fi client allows the HTTPS GET request to succeed using the same server, port, and root CA certificate.

Environment

IDE

  • Arduino IDE 2.x
  • ESP32 Arduino core: 3.3.0

Additional Information

My modem initialization and time sync functions are included below with the main sketch.
I use the same modem initialization in my project for secure MQTT communication which works perfectly.

#define TINY_GSM_MODEM_SIM7600

#include <Arduino.h>
#include <time.h>
#include <sys/time.h>
#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>

#include "SSLClient.h"

#define gsmSerial Serial1

#define MODEM_TX 17
#define MODEM_RX 39

// ---------- CONFIG ----------
const char server[] = "example.com";
const char resource[] = "/";
const int port = 443;

String GSM_PIN = "";
String APN = "internet";
String gprsUser = "";
String gprsPass = "";

String serialBuffer;

const char* NTP_SERVER_1 = "pool.ntp.org";
const char* NTP_SERVER_2 = "time.nist.gov";
const char* NTP_SERVER_3 = "asia.pool.ntp.org";
const long GMT_OFFSET = 18000;
const int DAYLIGHT_OFFSET = 0;

const char* rootCACertificate = R"string_literal(
-----BEGIN CERTIFICATE-----
MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO
MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD
DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX
DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw
b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC
AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP
L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY
t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins
S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3
PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO
L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3
R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w
dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS
+YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS
d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG
AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f
gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z
NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt
hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM
QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf
R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ
DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW
P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy
lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq
bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w
AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q
r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji
Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU
98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA=
-----END CERTIFICATE-----
)string_literal";

TinyGsm modem(gsmSerial);
TinyGsmClient base_client(modem, 0);
SSLClient secure_layer(&base_client);

bool initGsmModule();

void setup() {
  serialBuffer.reserve(10240);
  Serial.begin(115200);

  gsmSerial.setRxBufferSize(10240);  // or larger, e.g., 16384
  gsmSerial.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
  delay(3000);

  Serial.println("Trying to configure GSM module!");
  for (int i = 0; i < 5; i++) {
    Serial.printf("Try no. %d\n", i + 1);
    if (initGsmModule()) {
      break;
    }
    delay(1000);
  }

  secure_layer.setCACert(rootCACertificate);
}

void loop() {
  HttpClient client = HttpClient(secure_layer, server, port);

  modem.sendAT(GF("+CNSMOD?"));
  int nmodec = modem.stream.readStringUntil(',').toInt() != 0;
  int nmode = modem.stream.readStringUntil('\n').toInt();
  modem.waitResponse();
  Serial.print("Network Mode:");
  Serial.println(nmode);

  IPAddress local = modem.localIP();
  Serial.print("Local IP:");
  Serial.println(local);

  Serial.println("Making GET request securely...");
  int ret = client.get(resource);
  Serial.print("Get func returned: ");
  Serial.println(ret);
  int status_code = client.responseStatusCode();
  String response = client.responseBody();

  Serial.print("Status code: ");
  Serial.println(status_code);
  Serial.print("Response: ");
  Serial.println(response);

  client.stop();

  Serial.println("Done");
  delay(1000);
}

void sendRaw(const char* format, ...) {
  char buf[256];
  va_list args;
  va_start(args, format);
  vsnprintf(buf, sizeof(buf), format, args);
  va_end(args);
  // gsmSerial.println(buf);
  gsmSerial.print(buf);
  gsmSerial.print("\r\n");
}

// to be used only when mqtt not in use, not used in normal functioning
bool waitForOK(unsigned long timeoutMs) {
  unsigned long start = millis();
  while (millis() - start < timeoutMs) {
    if (gsmSerial.available()) {
      String line = gsmSerial.readStringUntil('\n');
      line.trim();
      if (line == "OK") return true;
      if (line == "ERROR") return false;
    }
  }
  return false;
}

bool initGsmModule() {
  Serial.println("\nConfiguring GSM module. Kindly wait...");

  // Full modem restart through the library
  modem.restart();
  delay(10000);

  // Library init with retries
  int initRetries = 12;
  while (!modem.init()) {
    Serial.println("Modem init failed, retrying...");
    delay(5000);
    initRetries--;
    if (initRetries <= 0) {
      Serial.println("Modem init failed permanently");
      return false;
    }
  }

  Serial.println("Modem initialized!");
  Serial.print("Modem Name: ");
  Serial.println(modem.getModemName());

  Serial.print("Modem Info: ");
  Serial.println(modem.getModemInfo());

  // SIM unlock
  if (GSM_PIN.length() > 0 && modem.getSimStatus() != 3) {
    Serial.print("Unlocking SIM...");
    if (!modem.simUnlock(GSM_PIN.c_str())) {
      Serial.println(" Failed");
      return false;
    }
    Serial.println(" OK");
  }

  // Optional modem info
  Serial.print("CCID: ");
  Serial.println(modem.getSimCCID());

  Serial.print("IMEI: ");
  Serial.println(modem.getIMEI());

  Serial.print("IMSI: ");
  Serial.println(modem.getIMSI());

  Serial.print("Operator: ");
  Serial.println(modem.getOperator());

  Serial.print("Signal quality (CSQ): ");
  Serial.println(modem.getSignalQuality());

  // Wait for network
  Serial.print("Waiting for network...");
  int networkRetries = 12;
  while (!modem.waitForNetwork()) {
    Serial.println(" failed, retrying...");
    delay(10000);
    networkRetries--;
    if (networkRetries <= 0) {
      Serial.println(" fail");
      return false;
    }
  }
  Serial.println(" OK");

  if (!modem.isNetworkConnected()) {
    Serial.println("Network not connected");
    return false;
  }

  // Connect GPRS using the library
  Serial.print("Connecting to APN: ");
  Serial.println(APN);

  if (!modem.gprsConnect(APN.c_str(), gprsUser.c_str(), gprsPass.c_str())) {
    Serial.println("GPRS connect failed");
    return false;
  }

  Serial.println("GPRS connected");

  IPAddress local = modem.localIP();
  Serial.print("Local IP: ");
  Serial.println(local);

  Serial.println("Checking SMS notification settings...");
  gsmSerial.println("AT+CNMI?");
  waitForOK(1000);

  Serial.println("Stopping previous MQTT session...");
  gsmSerial.println("AT+CMQTTSTOP");
  waitForOK(3000);

  gsmSerial.println("AT+CMQTTREL=0");
  waitForOK(3000);

  gsmSerial.println("AT+CMQTTREL=1");
  waitForOK(3000);

  Serial.println("Modem ready!");
  return true;
}

Questions

  1. Is TinyGsmClient + SSLClient expected to work with the A7670SA in this configuration?
  2. Is there any additional configuration I am missing?
  3. Are there any recommended debugging steps for me to try?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions