Cert issue when connecting to Cloud Hive instance

Trying to connect a SIM7600 to xxxx.s1.eu.hivemq.cloud instance on 8883.

Successfully connect on 1883 and works as expected.

Code portion below which is similar to here

boolean mqttConnect() //boolean true or false
{
  SerialMon.print("Connecting to ");
  SerialMon.println(broker);
  SerialMon.println("");  //add CR

  // Connect to MQTT Broker
  //boolean status = mqtt.connect("xxxx");                    //works 1883
  // Or, if you want to authenticate MQTT:
  // boolean status = mqtt.connect("xxxx", "xxxx", "xxxx");   //doesnt work 8883

  //List files in SPIFFS e.g., isrgrootx1.pem
  ListFilesSPIFFS(); //Only list when booting

  String serverAddress = "xxxx.s1.eu.hivemq.cloud";
  int serverPort = 8883;
  int keepAliveSeconds = 60;
  int cleanSession = 1;
  String username = "xxxx";
  String password = "xxxxx";
  
  // Set SSL version and authentication mode
  modem.sendAT("+CSSLCFG=\"sslversion\",0,4"); //ALL Set the SSL version of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG command failed");
    return false;
  }
  
  modem.sendAT("+CSSLCFG=\"authmode\",0,1"); //Server authentication. It needs the root CA of the serverSet the authentication mode(verify server) of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG command failed");
    return false;
  }

//  modem.sendAT("+CSSLCFG=\"ignoreltime\",0,1"); //1 – ignore time check for certification default is 1
//  if (!modem.waitResponse(1000)) {
//    Serial.println("CSSLCFG command failed");
//    return false;
//  }
  
  // Set server root CA
  modem.sendAT("+CSSLCFG=\"cacert\",0,\"isrgrootx1.pem\""); //Set the server root CA of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG command failed");
    return false;
  }
/*
  // Set client cert
  modem.sendAT("+CSSLCFG=\"clientcert\",0,\"clientcert.pem\""); //Set the client cert
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG command failed");
    return false;
  }

  // Set client cert
  modem.sendAT("+CSSLCFG=\"clientkey\",0,\"clientkey.pem\""); //Set the clientkey
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG command failed");
    return false;
  }
*/ 
  // Set client cert
  modem.sendAT("+CSSLCFG?"); 
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG command failed");
    return false;
  }
 
  // Start MQTT service and activate PDP context
  modem.sendAT("+CMQTTSTART");
  if (!modem.waitResponse(1000)) {
    Serial.println("MQTT START command failed");
    return false;
  }
  
  // Acquire a client
  modem.sendAT("+CMQTTACCQ=0,\"client1\",1,4"); //1 MQTT server with SSL/TLS 4 MQTT version 3.1.1
  if (!modem.waitResponse(1000)) {
    Serial.println("MQTT ACCQ command failed");
    return false;
  }
  
  // Set the first SSL context to be used in the SSL connection
  modem.sendAT("+CMQTTSSLCFG=0,0");
  if (!modem.waitResponse(1000)) {
    Serial.println("MQTT SSLCFG command failed");
    return false;
  }
  
  // Connect to MQTT server
  //String mqttConnectCommand = "AT+CMQTTCONNECT=0,\"ssl://" + serverAddress + ":" + String(serverPort) + "\"," + String(keepAliveSeconds) + "," + String(cleanSession) + ",\"" + username + "\",\"" + password + "\"";
  String mqttConnectCommand = "AT+CMQTTCONNECT=0,\"tcp://" + serverAddress + ":" + String(serverPort) + "\"," + String(keepAliveSeconds) + "," + String(cleanSession) + ",\"" + username + "\",\"" + password + "\"";
  boolean status = SerialAT.print(mqttConnectCommand);
  
  if (status == false) {
    SerialMon.println("MQTT Connect fail");
    return false;
  }
  SerialMon.println("MQTT Connect success");

Logs

17:52:41.500 -> AT+NETOPEN?
17:52:41.500 -> 
17:52:41.547 -> +NETOPEN: 1
17:52:41.547 -> 
17:52:41.547 -> OK
17:52:41.547 -> AT+IPADDR
17:52:41.594 -> 
17:52:41.594 -> +IPADDR: xx.xx.xx.xx
17:52:41.641 -> 
17:52:41.641 -> OK
17:52:41.641 -> Connecting to xxxx.s1.eu.hivemq.cloud
17:52:41.641 -> 
17:52:41.830 -> File: /isrgrootx1.pem
17:52:41.877 -> AT+CSSLCFG="sslversion",0,4
17:52:41.877 -> 
17:52:41.877 -> OK
17:52:41.877 -> AT+CSSLCFG="authmode",0,1
17:52:41.924 -> 
17:52:41.924 -> OK
17:52:41.924 -> AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
17:52:41.924 -> 
17:52:41.924 -> ERROR
17:52:41.972 -> AT+CSSLCFG?
17:52:41.972 -> 
17:52:41.972 -> +CSSLCFG: 0,4,1,1,300,"","","",0,"",0x0
17:52:42.067 -> +CSSLCFG: 1,4,0,1,300,"","","",0,"",0x0
17:52:42.160 -> +CSSLCFG: 2,4,0,1,300,"","","",0,"",0x0
17:52:42.207 -> +CSSLCFG: 3,4,0,1,300,"","","",0,"",0x0
17:52:42.300 -> +CSSLCFG: 4,4,0,1,300,"","","",0,"",0x0
17:52:42.393 -> +CSSLCFG: 5,4,0,1,300,"","","",0,"",0x0
17:52:42.488 -> +CSSLCFG: 6,4,0,10,1,CSSLCFG command failed
17:52:43.074 -> AT+CGREG?
17:52:43.074 -> 
17:52:43.074 -> +CGREG: 0,1
17:52:43.074 -> 
17:52:43.118 -> OK
17:52:43.118 -> AT+CIPRXGET=4,0
17:52:43.118 -> 
17:52:43.118 -> +CIPRXGET: 4,0,0
17:52:43.161 -> 
17:52:43.161 -> OK
17:52:43.161 -> AT+CIPCLOSE?
17:52:43.161 -> 
17:52:43.161 -> +CIPCLOSE: 0,0,0,0,0,0,0,0,0,0
17:52:43.208 -> 
17:52:43.208 -> OK
17:52:43.208 -> MQTT NOT CONNECTED! 
17:52:43.208 -> Disconnecting from: xxxx.s1.eu.hivemq.cloud
17:52:43.208 -> AT+CIPSEND=0,2

So using MQTT explorer with the isrgrootx1.pem cert added (server cert) detailed here
isrgrootx1.pem”, which you can use as “Server Certiciate

When compiling and writing the sketch to the ESP32/SIM7600 (combined on one board) uploaded the /data/isrgrootx1.pem file which you can see listed as /isrgrootx1.pem in the logs confirming its located on SPIFFS.

So the logs show it failing on AT+CSSLCFG="cacert",0,"isrgrootx1.pem"

Any advice on what I am missing here?

Revised code and got further

boolean mqttConnect() //boolean true or false
{
  SerialMon.print("Connecting to ");
  SerialMon.println(broker);
  SerialMon.println("");  //add CR

  // Connect to MQTT Broker
  //boolean status = mqtt.connect("xxx");                  //works
  // Or, if you want to authenticate MQTT:
  // boolean status = mqtt.connect("xxx", "xxx", "xxx");   //not working 8883

  String serverAddress = "xxx.s1.eu.hivemq.cloud";
  int serverPort = 8883;
  int keepAliveSeconds = 60;
  int cleanSession = 1;
  String username = "xxx";
  String password = "xxx";
  
  // Set SSL version and authentication mode
  // 0 SSL3.0, 1 TLS1.0, 2 TLS1.1, 3 TLS1.2, 4 All
  modem.sendAT("+CSSLCFG=\"sslversion\",0,4"); //ALL Set the SSL version of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG SSLVersion command failed");
    return false;
  }
  // 0 no authentication
  // 1 server authentication needs the root CA of the server
  // 2 server and client authentication. It needs the root CA of the server, the cert and key of the client
  // 3 client authentication and no server authentication. It needs the cert and key of the client
  modem.sendAT("+CSSLCFG=\"authmode\",0,1"); //Server authentication. It needs the root CA of the serverSet the authentication mode(verify server) of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG Authmode command failed");
    return false;
  }

  //Did this via Tera Term AT+CCERTDOWN="isrgrootx1.pem", 1939 then AT+CCERTLIST shows cert returns OK
  // Download the server root CA AT+CCERTDOWN=”isrgrootx1.pem”,1939
  //modem.sendAT("+CCERTDOWN=\"isrgrootx1.pem\"",1939); //Download the root CA of the first SSL context
  //if (!modem.waitResponse(1000)) {
  //  Serial.println("CSSLCFG CCERTDOWN command failed");
  //  return false;
  //}

  // List downloaded certs
  modem.sendAT("+CCERTLIST"); //List the downloaded root CA of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG CCERTLIST command failed");
    return false;
  }

  // Set server root CA
  modem.sendAT("+CSSLCFG=\"cacert\",0,\"isrgrootx1.pem\""); //Set the server root CA of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG CACert command failed");
    return false;
  }
 
  // Check Cert Configuration result is +CSSLCFG: 0,4,2,1,300,"isrgrootx1.pem","","",0,"",0x0
  //modem.sendAT("+CSSLCFG?"); 
  //if (!modem.waitResponse(1000)) {
  //  Serial.println("CSSLCFG query command failed");
  //  return false;
  //}

  //result is +CSSLCFG: 0,4,2,1,300,"isrgrootx1.pem","","",0,"",0x0
  //0: The SSL/TLS context ID. In this case, it is the default context, which is ID 0
  //4: The SSL/TLS protocol version. In this case, it is TLS 1.2
  //2: The SSL/TLS cipher suite. In this case, it is AES_128_CBC_SHA256
  //1: The SSL/TLS authentication mode. In this case, it is server authentication only
  //300: The SSL/TLS timeout in seconds
  //"isrgrootx1.pem": The filename of the CA certificate
  //"": The filename of the client certificate
  //"": The filename of the client private key
  //0: The SSL/TLS verify mode
  //"": The domain name used for server verification
  //0x0: Reserved

  // Start MQTT service and activate PDP context
  modem.sendAT("+CMQTTSTART");
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTSTART START command failed");
    return false;
  }
  
  // Acquire a client
  modem.sendAT("+CMQTTACCQ=0,\"Client1\",1,4"); //1 MQTT server with SSL/TLS 4 MQTT version 3.1.1
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTSTART ACCQ command failed");
    return false;
  }
  
  // Set the first SSL context to be used in the SSL connection
  modem.sendAT("+CMQTTSSLCFG=0,0");
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTSTART SSLCFG command failed");
    return false;
  }
  
  // Connect to MQTT server
  //String mqttConnectCommand = "AT+CMQTTCONNECT=0,\"ssl://" + serverAddress + ":" + String(serverPort) + "\"," + String(keepAliveSeconds) + "," + String(cleanSession) + ",\"" + username + "\",\"" + password + "\"";
  String mqttConnectCommand = "AT+CMQTTCONNECT=0,\"tcp://" + serverAddress + ":" + String(serverPort) + "\"," + String(keepAliveSeconds) + "," + String(cleanSession) + ",\"" + username + "\",\"" + password + "\"";
  //String mqttConnectCommand = "AT+CMQTTCONNECT=0,\"tcp://" + serverAddress + ":" + String(serverPort) + "\",0,0,\"" + username + "\",\"" + password + "\""; //Username and password

  //Command needs to be AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883"

  boolean status = SerialAT.print(mqttConnectCommand);
  
  if (status == false) {
    SerialMon.println("MQTT Connect fail");
    return false;
  }
  SerialMon.println("MQTT Connect success");

Result logs

09:42:21.211 -> AT+IPADDR
09:42:21.211 -> 
09:42:21.211 -> +IPADDR: xx.xx.xx.xx
09:42:21.258 -> 
09:42:21.305 -> OK
09:42:21.305 -> Connecting to xxx.s1.eu.hivemq.cloud
09:42:21.305 -> 
09:42:21.305 -> AT+CSSLCFG="sslversion",0,4
09:42:21.305 -> 
09:42:21.305 -> OK
09:42:21.305 -> AT+CSSLCFG="authmode",0,1
09:42:21.351 -> 
09:42:21.351 -> OK
09:42:21.351 -> AT+CCERTLIST
09:42:21.351 -> 
09:42:21.351 -> +CCERTLIST: "isrgrootx1.pem"
09:42:21.445 -> 
09:42:21.445 -> OK
09:42:21.445 -> AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
09:42:21.445 -> 
09:42:21.445 -> OK
09:42:21.445 -> AT+CMQTTSTART
09:42:21.492 -> 
09:42:21.492 -> +CMQTTSTART: 23  //means network is opened
09:42:21.540 -> 
09:42:21.540 -> ERROR   //<------------------------???
09:42:21.540 -> AT+CMQTTACCQ=0,"Client1",1
09:42:21.540 -> 
09:42:21.540 -> +CMQTTACCQ: 0,19 //means client is used
09:42:21.586 -> 
09:42:21.586 -> ERROR
09:42:21.632 -> AT+CMQTTSSLCFG=0,0
09:42:21.632 -> 
09:42:21.632 -> OK
09:42:21.632 -> MQTT Connect success
09:42:21.632 -> AT+NETOPEN?

Revised code

Result error is +CMQTTCONNECT: 0,12 which ‘invalid parameter’

10:39:37.199 -> AT+IPADDR
10:39:37.199 -> 
10:39:37.199 -> +IPADDR: xx.xx.xx.xx
10:39:37.245 -> 
10:39:37.245 -> OK
10:39:37.245 -> 1
10:39:37.245 -> AT+NETOPEN?
10:39:37.292 -> 
10:39:37.292 -> +NETOPEN: 1
10:39:37.292 -> 
10:39:37.292 -> OK
10:39:37.339 -> AT+IPADDR
10:39:37.339 -> 
10:39:37.339 -> +IPADDR: xx.xx.xx.xx
10:39:37.385 -> 
10:39:37.385 -> OK
10:39:37.385 -> Connecting to xxx.s1.eu.hivemq.cloud
10:39:37.431 -> 
10:39:37.431 -> AT+CNSMOD
10:39:37.431 -> 
10:39:37.431 -> ERROR
10:39:37.431 -> AT+CSSLCFG="sslversion",0,4
10:39:37.431 -> 
10:39:37.431 -> OK
10:39:37.479 -> AT+CSSLCFG="authmode",0,1
10:39:37.479 -> 
10:39:37.479 -> OK
10:39:37.479 -> AT+CCERTLIST
10:39:37.479 -> 
10:39:37.526 -> +CCERTLIST: "isrgrootx1.pem"
10:39:37.573 -> 
10:39:37.573 -> OK
10:39:37.573 -> AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
10:39:37.573 -> 
10:39:37.573 -> OK
10:39:37.619 -> AT+CMQTTREL=0
10:39:37.619 -> 
10:39:37.619 -> OK
10:39:37.619 -> AT+CMQTTSTOP
10:39:37.666 -> 
10:39:37.666 -> +CMQTTSTOP: 0
10:39:37.666 -> 
10:39:37.666 -> OK
10:39:37.712 -> AT+CMQTTSTART
10:39:37.712 -> 
10:39:37.712 -> +CMQTTSTART: 0
10:39:37.760 -> 
10:39:37.760 -> OK
10:39:37.760 -> AT+CMQTTACCQ=0,"Client1",1,4
10:39:37.760 -> 
10:39:37.760 -> OK
10:39:37.808 -> AT+CMQTTSSLCFG=0,0
10:39:37.808 -> 
10:39:37.808 -> OK
10:39:37.808 -> AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud",8883,60,1,"xxx","xxx"
10:39:38.789 -> MQTT Connect success
10:39:38.789 -> AT+NETOPEN?
10:39:38.836 -> 
10:39:38.836 -> +CMQTTCONNECT: 0,12
10:39:38.883 -> 
10:39:38.883 -> ERROR
10:39:38.883 -> AT+CIPRXGET=4,0
10:39:38.929 -> 
10:39:38.929 -> +CIPRXGET: 4,0,0
10:39:38.929 -> 
10:39:38.929 -> OK
10:39:38.976 -> AT+CIPCLOSE?
10:39:38.976 -> 
10:39:38.976 -> +CIPCLOSE: 0,0,0,0,0,0,0,0,0,0
10:39:39.023 -> 
10:39:39.023 -> OK
10:39:39.116 -> AT+CGREG?
10:39:39.162 -> 
10:39:39.162 -> +CGREG: 0,1
10:39:39.162 -> 
10:39:39.162 -> OK
10:39:39.162 -> MQTT NOT CONNECTED! 
10:39:39.162 -> Disconnecting from: xxx.s1.eu.hivemq.cloud
10:39:39.208 -> AT+CIPSEND=0,2

Q. Do I need to send a AT+CMQTTWILLTOPIC and then AT+CMQTTWILLMSG prior to the AT+CMQTTCONNECT?

Added

  // Set the first SSL context to be used in the SSL connection
  modem.sendAT("+CMQTTSSLCFG=0,0");
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTSTART SSLCFG command failed");
    return false;
  }

  // Send AT+CMQTTWILLTOPIC=0,20 test/temperature
  modem.sendAT("+CMQTTWILLTOPIC=0,28,\"test/temperature\"");
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTWILLTOPIC command failed");
    return false;
  }

  // Send AT+CMQTTWILLMSG=0,17,1  
  modem.sendAT("+CMQTTWILLMSG=0,2,1");
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTWILLMSG command failed");
    return false;
  }

Result

  // Send AT+CMQTTWILLTOPIC=0,20 test/temperature
  modem.sendAT("+CMQTTWILLTOPIC=0,28,\"test/temperature\"");
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTWILLTOPIC command failed");
    return false;
  }

  // Send AT+CMQTTWILLMSG=0,17,1  
  modem.sendAT("+CMQTTWILLMSG=0,2,1");
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTWILLMSG command failed");
    return false;
  }
11:11:38.110 -> +NETOPEN: 1
11:11:38.110 -> 
11:11:38.158 -> OK
11:11:38.158 -> AT+IPADDR
11:11:38.158 -> 
11:11:38.158 -> +IPADDR: xx.xx.xx.xx
11:11:38.206 -> 
11:11:38.206 -> OK
11:11:38.206 -> Connecting to xxx.s1.eu.hivemq.cloud
11:11:38.252 -> 
11:11:38.252 -> AT+CNSMOD?
11:11:38.252 -> 
11:11:38.252 -> +CNSMOD: 0,8
11:11:38.252 -> 
11:11:38.252 -> OK
11:11:38.299 -> AT+CSSLCFG="sslversion",0,4
11:11:38.299 -> 
11:11:38.299 -> OK
11:11:38.299 -> AT+CSSLCFG="authmode",0,1
11:11:38.299 -> 
11:11:38.346 -> OK
11:11:38.346 -> AT+CCERTLIST
11:11:38.346 -> 
11:11:38.346 -> +CCERTLIST: "isrgrootx1.pem"
11:11:38.395 -> 
11:11:38.395 -> OK
11:11:38.440 -> AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
11:11:38.440 -> 
11:11:38.440 -> OK
11:11:38.440 -> AT+CMQTTREL=0
11:11:38.440 -> 
11:11:38.487 -> OK
11:11:38.487 -> AT+CMQTTSTOP
11:11:38.487 -> 
11:11:38.487 -> +CMQTTSTOP: 0
11:11:38.533 -> 
11:11:38.533 -> OK
11:11:38.533 -> AT+CMQTTSTART
11:11:38.580 -> 
11:11:38.580 -> +CMQTTSTART: 0
11:11:38.580 -> 
11:11:38.580 -> OK
11:11:38.628 -> AT+CMQTTACCQ=0,"Client1",1,4
11:11:38.628 -> 
11:11:38.628 -> OK
11:11:38.628 -> AT+CMQTTSSLCFG=0,0
11:11:38.628 -> 
11:11:38.674 -> OK
11:11:38.674 -> AT+CMQTTWILLTOPIC=0,28,"test/temperature"
11:11:38.674 -> 
11:11:38.674 -> +CMQTTWILLTOPIC: 0,12
11:11:38.722 -> 
11:11:38.722 -> ERROR
11:11:38.770 -> AT+CMQTTWILLMSG=0,2,1
11:11:38.770 -> 
11:11:38.770 -> >CMQTTWILLMSG command failed
11:11:39.844 -> AT+CGREG?
11:11:39.844 -> 
11:11:39.844 -> OK
11:11:40.874 -> Network disconnected
11:11:40.874 -> AT+CSQ
11:11:40.874 -> 
11:11:40.874 -> +CSQ: 24,99
11:11:40.874 -> 
11:11:40.874 -> OK
11:11:40.922 -> AT+CGREG?
11:11:40.922 -> 
11:11:40.922 -> +CGREG: 0,1
11:11:40.922 -> 
11:11:40.968 -> OK
11:11:40.968 -> AT+CGREG?
11:11:40.968 -> 
11:11:40.968 -> +CGREG: 0,1
11:11:41.014 -> 
11:11:41.014 -> OK
11:11:41.014 -> Network re-connected
11:11:41.014 -> AT+NETOPEN?

Revised code to

// modem.sendAT("+CMQTTWILLTOPIC=0,17,\"temp/temperature\"");
 // if (!modem.waitResponse(1000)) {
 //   Serial.println("CMQTTWILLTOPIC command failed with /");
 //   return false;
 // }

 
  modem.sendAT("+CMQTTWILLTOPIC=0,17\r\n");
  modem.waitResponse(1000);
  SerialAT.println("temp/temperature\r\n");
  modem.waitResponse(1000);
  
  if (!modem.waitResponse(1000)) {
      Serial.println("CMQTTWILLTOPIC command failed");
      return false;
  }


  // Send AT+CMQTTWILLMSG=0,25 temp/temperature then 29
  modem.sendAT("+CMQTTWILLMSG=0,2,1,\"17\"");
  if (!modem.waitResponse(1000)) {
    Serial.println("CMQTTWILLMSG command failed");
    return false;
  }

Log output with this code

18:36:39.526 -> AT+IPADDR
18:36:39.526 -> 
18:36:39.526 -> +IPADDR: xxx.xxx.xxx.xxx
18:36:39.574 -> 
18:36:39.574 -> OK
18:36:39.621 -> Connecting to xxx.s1.eu.hivemq.cloud
18:36:39.621 -> 
18:36:39.621 -> AT+CNSMOD?
18:36:39.621 -> 
18:36:39.621 -> +CNSMOD: 0,8
18:36:39.621 -> 
18:36:39.668 -> OK
18:36:39.668 -> AT+CSSLCFG="sslversion",0,4
18:36:39.668 -> 
18:36:39.668 -> OK
18:36:39.668 -> AT+CSSLCFG="authmode",0,1
18:36:39.668 -> 
18:36:39.715 -> OK
18:36:39.715 -> AT+CCERTLIST
18:36:39.715 -> 
18:36:39.715 -> +CCERTLIST: "isrgrootx1.pem"
18:36:39.761 -> 
18:36:39.808 -> OK
18:36:39.808 -> AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
18:36:39.808 -> 
18:36:39.808 -> OK
18:36:39.808 -> AT+CMQTTREL=0
18:36:39.853 -> 
18:36:39.853 -> OK
18:36:39.853 -> AT+CMQTTSTOP
18:36:39.853 -> 
18:36:39.853 -> +CMQTTSTOP: 0
18:36:39.901 -> 
18:36:39.901 -> OK
18:36:39.901 -> AT+CMQTTSTART
18:36:39.949 -> 
18:36:39.949 -> +CMQTTSTART: 0
18:36:39.949 -> 
18:36:39.949 -> OK
18:36:39.995 -> AT+CMQTTACCQ=0,"Client1",1,4
18:36:39.995 -> 
18:36:39.995 -> OK
18:36:39.995 -> AT+CMQTTSSLCFG=0,0
18:36:39.995 -> 
18:36:40.041 -> OK
18:36:40.041 -> AT+CMQTTWILLTOPIC=0,25
18:36:40.041 -> 
18:36:40.041 -> 
18:36:40.041 -> >temp/temperature
18:36:41.033 -> 
18:36:42.015 -> AT+CMQTTWILLMSG=0,2,1,"29"
18:36:42.062 -> 
18:36:42.062 -> OK
18:36:43.037 -> AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"
18:36:44.063 -> MQTT Connect success
18:36:44.063 -> AT+NETOPEN?
18:36:44.063 -> 
18:36:44.110 -> +CMQTTCONNECT: 0,12

Write command is AT+CMQTTCONNECT AT+CMQTTCONNECT=<client_index>,<server_addr>,<keepalive_time>,<clean_session>[,<user_name>[,<pass_word>]

Return should be +CMQTTCONNECT: 0,0 not +CMQTTCONNECT: 0,12 which is ‘invalid format’

Documents say AT+CMQTTCONNECT is used to connect to a MQTT server.
Note: If you don’t set the SSL context by AT+CMQTTSSLCFG before connecting a SSL/TLS MQTT server
by AT+CMQTTCONNECT, it will use the <client_index> (the 1st parameter of AT+CMQTTCONNNECT)
SSL context when connecting to the server

and

AT+CMQTTSSLCFG is used to set the SSL context which to be used in the SSL connection when it will
connect to a SSL/TLS MQTT server. It must be called before AT+CMQTTCONNECT and after
AT+CMQTTSTART. The setting will be cleared after AT+CMQTTCONNECT failed or AT+CMQTTDISC.
Note: If you don’t set the SSL context by this command before connecting to server by
AT+CMQTTCONNECT, the CMQTTCONNECT operation will use the SSL context as same as index
<session_id> (the 1st parameter of AT+CMQTTCONNECT) when connecting to the server

So the Write Command AT+CMQTTSSLCFG=<session_id>,<ssl_ctx_index>

Any advice please as I must be close…

Hello @droidblast ,

Thank you for the outreach and interest in HiveMQ!

Could you clarify which client library you are currently using for this project?

Best,
Aaron from HiveMQ Team

Thanks

Tiny_GSM GitHub - vshymanskyy/TinyGSM: A small Arduino library for GSM modules, that just works
Pub_Sub GitHub - knolleary/pubsubclient: A client library for the Arduino Ethernet Shield that provides support for MQTT.

Device is a T-SIM7600G-H which is a modem and ESP32 together.

As the Tiny_GSM doesnt support TLS 8883 I am using the native modem commands.
T-SIM7600X/Manual at master · Xinyuan-LilyGO/T-SIM7600X · GitHub

To date this is the log and where I am up to.

Downloaded the isrgrootx1.pem from Hive’s FAQ’s, can we confirm the expiration length please?

From my readings I only need the root certificate for TLS then set this with the command AT+CSSLCFG="authmode",0,1

Do I need to send the CMQTTWILLTOPIC and CMQTTWILLMSG pre AT+CMQTTCONNECT ?

10:23:25.955 -> AT+CSSLCFG="sslversion",0,4  //4 is all cert versions 1,1.1,1.2, SSL3.0 
10:23:25.955 -> 
10:23:25.955 -> OK
10:23:26.001 -> AT+CSSLCFG="authmode",0,1 //1  server authentication. It needs the root CA of the server
10:23:26.001 -> 
10:23:26.001 -> OK
10:23:26.001 -> AT+CCERTLIST  //list certs on modem
10:23:26.001 -> 
10:23:26.048 -> +CCERTLIST: "isrgrootx1.pem"  //found cert on modem

18:42:55.116 -> AT+CSSLCFG="cacert",0,"isrgrootx1.pem" //using cert on modem
18:42:55.116 -> 
18:42:55.116 -> OK
18:42:55.116 -> AT+CMQTTREL=0 //release client
18:42:55.163 -> 
18:42:55.163 -> OK
18:42:55.163 -> AT+CMQTTSTOP //stop MQTT
18:42:55.163 -> 
18:42:55.163 -> +CMQTTSTOP: 0
18:42:55.210 -> 
18:42:55.210 -> OK
18:42:55.210 -> AT+CMQTTSTART //start MQTT
18:42:55.256 -> 
18:42:55.256 -> +CMQTTSTART: 0
18:42:55.303 -> 
18:42:55.303 -> OK
18:42:55.303 -> AT+CMQTTACCQ=0,"Client1",1,4 //TLS content 0 Client1 4 is MQTT version 3.1.1
18:42:55.303 -> 
18:42:55.303 -> OK
18:42:55.303 -> AT+CMQTTSSLCFG=0,0 //session_id 0 ,ssl_ctx_index 0
18:42:55.350 -> 
18:42:55.350 -> OK
18:42:55.350 -> AT+CMQTTWILLTOPIC=0,16 //0 client index, lenght 16
18:42:55.350 -> 
18:42:55.350 -> 
18:42:55.350 -> >temp/temperature //will topic which is 16 characters - note there is no OK response from the modem here and it is expected
18:42:56.332 -> 
18:43:00.351 -> AT+CMQTTWILLMSG=0,2,0 //0 client index, lenght 2, QOS 0
18:43:00.351 -> 
18:43:00.351 -> 
18:43:00.351 -> OK //this is expected
18:43:00.396 -> 29 //value is 29 for temp/temperature topic
18:43:00.396 -> 
18:43:04.398 -> AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"
18:43:05.373 -> MQTT Connect success
18:43:05.373 -> AT+NETOPEN?
18:43:05.419 -> 
18:43:05.419 -> +CMQTTCONNECT: 0,12 //error 12 is invalid format

Hello @droidblast ,

Querying the server cert with OpenSSL, the expiration is currently reported as Jun 4 11:04:38 2035 GMT.

The MQTT Will Topic and Will Message are optional components of a connect message, and are not required for a successful connection. More specific details about this packet components are available in our learning series here.

To confirm, the error being presented indicates a failure in reading the ‘Connect’ packet for the connecting client, correct?

Best,
Aaron from HiveMQ Team

Yes - failure in reading the ‘Connect’ packet for the connecting client, correct?

Syntax
AT+CMQTTCONNECT=<client_index>,<server_addr>,<keepalive_time>,<clean_session>[,<user_name>[,<pass_word>]]

Expected Response

OK
+CMQTTCONNECT: <client_index>,<err>
or
+CMQTTCONNECT: <client_index>,<err>
ERROR
or
ERROR

Code

  String serverAddress = "xxx.s1.eu.hivemq.cloud";
  int serverPort = 8883;
  int keepAliveSeconds = 60;
  int cleanSession = 1;
  String username = "xxx";
  String password = "xxx";

String mqttConnectCommand = "AT+CMQTTCONNECT=0,\"tcp://" + serverAddress + ":" + String(serverPort) + "\"," + String(keepAliveSeconds) + "," + String(cleanSession) + ",\"" + username + "\",\"" + password + "\"";

Logs out put

18:42:55.116 -> AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
18:42:55.116 -> 
18:42:55.116 -> OK
18:42:55.116 -> AT+CMQTTREL=0
18:42:55.163 -> 
18:42:55.163 -> OK
18:42:55.163 -> AT+CMQTTSTOP
18:42:55.163 -> 
18:42:55.163 -> +CMQTTSTOP: 0
18:42:55.210 -> 
18:42:55.210 -> OK
18:42:55.210 -> AT+CMQTTSTART
18:42:55.256 -> 
18:42:55.256 -> +CMQTTSTART: 0
18:42:55.303 -> 
18:42:55.303 -> OK
18:42:55.303 -> AT+CMQTTACCQ=0,"Client1",1,4
18:42:55.303 -> 
18:42:55.303 -> OK
18:42:55.303 -> AT+CMQTTSSLCFG=0,0
18:42:55.350 -> 
18:42:55.350 -> OK
18:42:55.350 -> AT+CMQTTWILLTOPIC=0,25
18:42:55.350 -> 
18:42:55.350 -> 
18:42:55.350 -> >temp/temperature
18:42:56.332 -> 
18:43:00.351 -> AT+CMQTTWILLMSG=0,2,0
18:43:00.351 -> 
18:43:00.351 -> 
18:43:00.351 -> OK
18:43:00.396 -> 29
18:43:00.396 -> 
18:43:04.398 -> AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"
18:43:05.373 -> MQTT Connect success
18:43:05.373 -> AT+NETOPEN?
18:43:05.419 -> 
18:43:05.419 -> +CMQTTCONNECT: 0,12

Error is 12 ‘invalid format’ on the CMQTTCONNECT command

Found my code error for +CMQTTCONNECT: 0,12 was a extra AT so removed and minimized the code and variables.

Command AT+CMQTTCONNECT returns ok but not +CMQTTCONNECT: 0,0 as per the manual? IS there a way to see logs from Hivemq?

Code

  // Show current network system mode
  modem.sendAT("+CNSMOD?");
  if (!modem.waitResponse(1000)) {
    Serial.println("CNSMOD network system mode command failed");
    return false;
  }
  
  // Set SSL version and authentication mode
  modem.sendAT("+CSSLCFG=\"sslversion\",0,4"); //ALL Set the SSL version of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG SSLVersion command failed");
    return false;
  }

  modem.sendAT("+CSSLCFG=\"authmode\",0,1"); //Server authentication. It needs the root CA of the serverSet the authentication mode(verify server) of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG Authmode command failed");
    return false;
  }


  // Set server root CA
  modem.sendAT("+CSSLCFG=\"cacert\",0,\"isrgrootx1.pem\""); //Set the server root CA of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG CACert command failed");
    return false;
  }
 

  modem.sendAT("+CMQTTSSLCFG?");
  modem.waitResponse(1000);

   
  // Connect to MQTT server
  modem.sendAT("+CMQTTCONNECT=0,\"tcp://xxx.s1.eu.hivemq.cloud:8883\",60,1,\"xxx\",\"xxx\"");
  if (!modem.waitResponse(120000)) {
    Serial.println("CMQTTCONNECT command failed");
    return false;
  }

  modem.sendAT("+CMQTTCONNECT?");
  modem.waitResponse(1000);


  delay(5000); //Allow sufficient time for the SSL handshake to finish
  Serial.println("done!");

Logs

18:03:34.127 -> AT+NETOPEN?
18:03:34.174 -> 
18:03:34.174 -> +NETOPEN: 1
18:03:34.174 -> 
18:03:34.174 -> OK
18:03:34.221 -> AT+IPADDR
18:03:34.221 -> 
18:03:34.221 -> +IPADDR: xx.xx.xx.xx
18:03:34.268 -> 
18:03:34.268 -> OK
18:03:34.268 -> Connecting to xxx.s1.eu.hivemq.cloud
18:03:34.268 -> 
18:03:34.268 -> AT+CNSMOD?
18:03:34.316 -> 
18:03:34.316 -> +CNSMOD: 0,8
18:03:34.316 -> 
18:03:34.316 -> OK
18:03:34.361 -> AT+CSSLCFG="sslversion",0,4
18:03:34.361 -> 
18:03:34.361 -> OK
18:03:34.361 -> AT+CSSLCFG="authmode",0,1
18:03:34.361 -> 
18:03:34.361 -> OK
18:03:34.408 -> AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
18:03:34.408 -> 
18:03:34.408 -> OK
18:03:34.408 -> AT+CMQTTSSLCFG=0,0
18:03:34.408 -> 
18:03:34.455 -> OK
18:03:34.455 -> AT+CMQTTSSLCFG?
18:03:34.455 -> 
18:03:34.455 -> +CMQTTSSLCFG: 0,0
18:03:34.502 -> +CMQTTSSLCFG: 1,
18:03:34.548 -> 
18:03:34.548 -> 
18:03:34.548 -> OK
18:03:34.548 -> AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"
18:03:34.594 -> 
18:03:34.594 -> OK
18:03:39.600 -> done!
18:03:39.600 -> AT+CIPRXGET=4,0
18:03:39.600 -> 
18:03:39.600 -> +CIPRXGET: 4,0,0
18:03:39.649 -> 
18:03:39.649 -> OK
18:03:39.649 -> AT+CIPCLOSE?
18:03:39.649 -> 
18:03:39.694 -> +CIPCLOSE: 0,0,0,0,0,0,0,0,0,0
18:03:39.694 -> 
18:03:39.694 -> OK
18:03:39.838 -> AT+CGREG?
18:03:39.838 -> 
18:03:39.838 -> +CGREG: 0,1
18:03:39.887 -> 
18:03:39.887 -> OK
18:03:39.887 -> MQTT NOT CONNECTED! 
18:03:39.887 -> Disconnecting from: xxx.s1.eu.hivemq.cloud
18:03:39.887 -> AT+CIPSEND=0,2

Command AT+CMQTTCONNECT returns ok but not +CMQTTCONNECT: 0,0 as per the manual?

AT+CMQTTCONNECT=0,"tcp://hooleeping.com:8883",60,1
OK
+CMQTTCONNECT: 0,0
20:22:47.382 -> 
20:22:47.382 -> 
20:22:47.382 -> OK
20:22:47.382 -> AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"
20:22:47.428 -> 
20:22:47.428 -> OK
20:22:47.428 -> AT+CMQTTCONNECT?
20:22:47.428 -> 
20:22:47.428 -> +CMQTTCONNECT: 0
20:22:47.476 -> +CMQTTCONNECT: 1
20:22:47.523 -> 
20:22:47.523 -> OK
20:22:52.554 -> done!

Also continuing reading enabled TLS-SNI extension in the code.

modem.sendAT("+CSSLCFG=\"enableSNI\",0,1");

Still no improvement.

Now trying to use AT commands direct to the modem so there is not code involved.

AT+CPIN?
AT+CSQ
AT+CGREG?
AT+COPS?
AT+NETOPEN
AT+NETOPEN?
AT+IPADDR

All return OK network operator connected with IP

AT+CSSLCFG="sslversion",0,4
AT+CSSLCFG="authmode",0,1
AT+CSSLCFG="ignorelocaltime",0,1
AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
AT+CSSLCFG="enableSNI",0,1
AT+CMQTTSTART
AT+CMQTTACCQ=0,"test",1,4
AT+CMQTTSSLCFG=0,0

All return OK

AT+CMQTTCONNECT=0,“tcp://xxx.s1.eu.hivemq.cloud:8883”,60,1,“xxx”,“xxx”

Fails

+CMQTTCONNECT: 0,32

Used this process to upload the CERT PEM

https://www.hackster.io/victorffs/connecting-sim7600x-h-to-aws-using-mqtt-and-at-commands-2a693c

Issue seems it stalls when loading to the modem, reboot check file is there with AT+CCERTLIST and the PEM is there, but connection string returns +CMQTTCONNECT: 0,34 which is open SSL session failed

So tried to upload via Teraterm Paste CR which returns OK connection string returns +CMQTTCONNECT: 0,32 which is handshake fail - I copy the CERT details from file here

So what am I missing? What is the process used to upload a CERT to a modem?

So providing that I am getting there by not using the I get error or +CMQTTCONNECT: 0,31 connection refused: not authorized

AT+CSSLCFG="enableSNI",0,1

Using the command error changes to +CMQTTCONNECT: 0,32 handshake fail

SO AaronTLFranz does this mean the CERT or am I calling the TLS handshake incorrectly?

AT+CSSLCFG="sslversion",0,4 returns OK

0 – SSL3.0
1 – TLS1.0
2 – TLS1.1
3 – TLS1.2
4 – All

AT+CSSLCFG="authmode",0,1 returns OK

The authentication mode, the default value is 0.
0 – no authentication.
1 – server authentication. It needs the root CA of the server.
2 – server and client authentication. It needs the root CA of the
server, the cert and key of the client.
3 – client authentication and no server authentication. It needs
the cert and key of the client

AT+CSSLCFG="cacert",0,"isrgrootx1.pem" returns OK

The client cert file name of SSL context. The file name must have type
like “.pem” or “.der”. The length of filename is from 5 to 128 bytes.
If the filename contains non-ASCII characters, the file path parameter
should contain a prefix of {non-ascii} and the quotation mark (The
string in the quotation mark should be hexadecimal of the filename’s
UTF8 code).
There are two ways to download certificate files to module:

  1. By AT+CCERTDOWN.
  2. By FTPS or HTTPS commands

AT+CSSLCFG="enableSNI",0,1 returns OK

The flag to indicate that enable the SNI flag or not, the default value is
0.
0 – not enable SNI.
1 – enable SNI

AT+CMQTTSTART returns OK

AT+CMQTTACCQ=0,"test3",1,4

<client_index> A numeric parameter that identifies a client. The range of permitted
values is 0 to 1.
The UTF-encoded string. It specifies a unique identifier for the client.
The string length is from 1 to 128 bytes.
<server_type> A numeric parameter that identifies the server type. The default value
is 0.
0 – MQTT server with TCP
1 – MQTT server with SSL/TLS
<mqtt_version> A numeric parameter that identifies the MQTT protocol version. The
permitted value is 3 or 4.
3 – MQTT version 3.1
4 – MQTT version 3.1.1

AT+CMQTTSSLCFG=0,0 returns OK

<session_id> A numeric parameter that identifies a client. The range of permitted
values is 0 to 1.
<ssl_ctx_index> The SSL context ID which will be used in the SSL connection. Refer to
the <ssl_ctx_index> of AT+CSSLCFG

AT+CMQTTCONNECT=0,“tcp://xxx.s1.eu.hivemq.cloud:8883”,60,1,“xxx”,“xxx”

Dependant on how I upload the PEM to the modem

`+CMQTTCONNECT: 0,31` handshake fail
`+CMQTTCONNECT: 0,34`  open SSL session failed

Hello, @droidblast

To confirm, is it possible to query the certificate on the modem once it has been uploaded to ensure that it is valid and complete once placed on the modem?

From the HiveMQ Cloud side, all that should be required is that the server cert is utilized for the connection, and standard TLS protocol is observed. Based on the details provided, it’s sounding like there may either be an issue with the cert once read from the modem, or with the TLS connection pathway, so I’d like to narrow this down further.

Best,
Aaron from HiveMQ Team

Struggling to move forward.

documentation states AT+CSSLCFG with the result below

Logs which shows the SSL session 0 and its settings

result is +CSSLCFG: 0,4,2,1,300,“isrgrootx1.pem”,“”,“”,0,“”,0x0
0: The SSL/TLS context ID. In this case, it is the default context, which is ID 0
4: The SSL/TLS protocol version. In this case, it is TLS ALL
1: The SSL/TLS cipher suite. In this case, it is Support all
1: The SSL/TLS authentication mode. In this case, it is server authentication only
300: The SSL/TLS timeout in seconds
“isrgrootx1.pem”: The filename of the CA certificate
“”: The filename of the client certificate
“”: The filename of the client private key
0: The SSL/TLS verify mode
“”: The domain name used for server verification
0x0: Reserved

20:53:33.948 -> OK
20:53:33.948 -> AT+CSSLCFG?
20:53:33.995 -> 
20:53:33.995 -> +CSSLCFG: 0,4,1,1,300,"isrgrootx1.pem","","",1,"",0x0
20:53:34.121 -> +CSSLCFG: 1,4,0,1,300,"","","",0,"",0x0
20:53:34.166 -> +CSSLCFG: 2,4,0,1,300,"","","",0,"",0x0
20:53:34.260 -> +CSSLCFG: 3,4,0,1,300,"","","",0,"",0x0
20:53:34.356 -> +CSSLCFG: 4,4,0,1,300,"","","",0,"",0x0
20:53:34.447 -> +CSSLCFG: 5,4,0,1,300,"","","",0,"",0x0
20:53:34.494 -> +CS+CSSAT+CSSLCFG="enableSNI",0,1

Set to 4 to all certs

The SSL version, the default value is 4.
0 – SSL3.0
1 – TLS1.0
2 – TLS1.1
3 – TLS1.2
4 – All

Set 1 at Server auth CA only needed

The authentication mode, the default value is 0.
0 – no authentication.
1 – server authentication. It needs the root CA of the server.
2 – server and client authentication. It needs the root CA of the
server, the cert and key of the client.
3 – client authentication and no server authentication. It needs
the cert and key of the client.

Set to 1 ignore

The flag to indicate how to deal with expired certificate, the default
value is 1.
0 – care about time check for certification.
1 – ignore time check for certification
When set the value to 0, it need to set the right current date and time
by AT+CCLK when need SSL certification

Uploaded cert pem to my FTP host with WINSCP then AT+CFTPSGETFILE to retrieve the pem via the SIM7600 Modem using only AT commands

AT+CFTPSGETFILE="isrgrootx1.pem",4

This saves the file to the modem location of /mssl_cert/isrgrootx1.pem

If I do a CCERTLIST not certs unless option 4 below is used

  • Complete the GETFILE option 3, OK then CCERTLIST no files as its on EFS
  • Complete the GETFILE option 4, OK then CCERTLIST shows the correct PEM
The directory to save the downloaded file.Numeric type, range is 1-4,
default is 1(/cache)
1 – F:/ (/cache)
2 – D:/(sd card)
3 – E:/ (/data/media/)
4 – /mssl_cert/(this is for CA file downloading)
AT+CFTPSSTART
OK
AT+CFTPSLOGIN="xxx.com",21,"xxx","xxxx",0
OK
AT+CFTPSLIST="/"
OK
AT+CFTPSCWD="xxx.com"
OK
AT+CFTPSPWD
OK
AT+CFTPSGETFILE="isrgrootx1.pem",4
OK
AT+CFTPSGETFILE="isrgrootx1.der",4
OK
AT+CFTPSLOGOUT
OK
The client cert file name of SSL context. The file name must have type
like “.pem” or “.der”. The length of filename is from 5 to 128 bytes.
If the filename contains non-ASCII characters, the file path parameter
should contain a prefix of {non-ascii} and the quotation mark (The
string in the quotation mark should be hexadecimal of the filename’s
UTF8 code).
There are two ways to download certificate files to module:
1. By AT+CCERTDOWN.
2. By FTPS or HTTPS commands. Please refer to chapter 12 and 13.

So I can get and list the files being a pem or converted der
openssl x509 -in isrgrootx1.pem -out isrgrootx1.der -outform DER

Logs with AT direct no code commands

AT+CCERTLIST
OK
AT+CFTPSGETFILE="isrgrootx1.pem",4
OK
+CFTPSGETFILE: 0
AT+CFTPSGETFILE="isrgrootx1.der",4
OK
+CFTPSGETFILE: 0
OK
AT+CCERTLIST
+CCERTLIST: "isrgrootx1.der"
+CCERTLIST: "isrgrootx1.pem"
OK
AT+CSSLCFG="sslversion",0,4
OK
AT+CSSLCFG="authmode",0,1
OK
AT+CSSLCFG="ignorelocaltime",0,1
OK
AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
OK
AT+CSSLCFG="enableSNI",0,1
OK
AT+CMQTTSTART
OK
AT+CMQTTACCQ=0,"xxx",1,4
OK
AT+CMQTTSSLCFG=0,0
OK
+CMQTTSTART: 0
OK
AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"
OK
+CMQTTCONNECT: 0,32

So rather than a AT+CCERTDOWN I have completed a AT+CFTPSGETFILE to get both the pem and converted der end result is +CMQTTCONNECT: 0,32 handshake fail

To confirm, is it possible to query the certificate on the modem once it has been uploaded to ensure that it is valid and complete once placed on the modem?

Can only to a CCERTLIST which returns the pem cert but I cant confirm if it intact, cant do a file size

Commands are…

AT+CCHSTARTStart SSL service
AT+CCHSTOP |Stop SSL service
AT+CCHOPEN |Connect to SSL server
AT+CCHCLOSEDisconnect from SSL server
AT+CCHSEND Send data to SSL server
AT+CCHRECVRead the cached data that received from the SSL server
AT+CCHCFG Configure the client context
AT+CCHSSLCFGSet the SSL context
AT+CCHSET Configure the report mode of sending and receiving data
AT+CCHMODE Configure the mode of sending and receiving data
AT+CCHADDR Get the IPV4 address
AT+CSSLCFG Configure the SSL context
AT+CCERTDOWN Download certificate into the module
AT+CCERTLIST List certificates
AT+CCERTDELE Delete certificates

MQTT commands

AT+CMQTTSTART Start MQTT service
AT+CMQTTSTOP STOP MQTT service
AT+CMQTTACCQ Acquire a client
AT+CMQTTREL Release a client
AT+CMQTTSSLCFG Set the SSL context
AT+CMQTTWILLTOPIC Input the will topic
AT+CMQTTWILLMSG Input the will message
AT+CMQTTDISC Disconnect from server
AT+CMQTTCONNECT Connect to MQTT server
AT+CMQTTTOPIC Input the publish message topic
AT+CMQTTPAYLOAD Input the publish message body
AT+CMQTTPUB Publish a message to server
AT+CMQTTSUBTOPIC Input a subscribe message topic
AT+CMQTTSUB Subscribe a message to server
AT+CMQTTUNSUBTOPIC Input a unsubscribe message topic
AT+CMQTTUNSUB Unsubscribe a message to server
AT+CMQTTCFG Configure the MQTT Context

From the HiveMQ Cloud side, all that should be required is that the server cert is utilized for the connection, and standard TLS protocol is observed. Based on the details provided, it’s sounding like there may either be an issue with the cert once read from the modem, or with the TLS connection pathway, so I’d like to narrow this down further.

Can you please confirm the cert type 1.x-3.0

Hello @droidblast ,

One item I spotted in the details provided above is the following :

The authentication mode, the default value is 0.
0 – no authentication.
1 – server authentication. It needs the root CA of the server.
2 – server and client authentication. It needs the root CA of the
server, the cert and key of the client.
3 – client authentication and no server authentication. It needs
the cert and key of the client.

The cert that was obtained is just the root CA of the server, and should be able to be used with the authentication method specified in the “1” option here. Would it be possible to give this configuration an attempt? This tends to be the connection type that many other modules have success with.

The cert info can be validated using openssl with the following command :
openssl x509 -in isrgrootx1.pem -text or opened with an application such as Keychain.

Best,
Aaron from HiveMQ Team

Revised my previous post

  // 0 no authentication
  // 1 server authentication needs the root CA of the server
  // 2 server and client authentication. It needs the root CA of the server, the cert and key of the client
  // 3 client authentication and no server authentication. It needs the cert and key of the client
  modem.sendAT("+CSSLCFG=\"authmode\",0,1"); //Server authentication. It needs the root CA of the serverSet the authentication mode(verify server) of the first SSL context
  if (!modem.waitResponse(1000)) {
    Serial.println("CSSLCFG Authmode command failed");
    return false;
  }

AT commands used below with the auth set to server hence isrgrootx1.pem

AT+CSSLCFG="sslversion",0,4
AT+CSSLCFG="authmode",0,1
AT+CSSLCFG="ignorelocaltime",0,1
AT+CSSLCFG="cacert",0,"isrgrootx1.pem"
AT+CSSLCFG="enableSNI",0,1
AT+CMQTTSTART
AT+CMQTTACCQ=0,"xxx",1,4
AT+CMQTTSSLCFG=0,0
AT+CCERTLIST
AT+CCERTDOWN="isrgrootx1.pem",1939
AT+CSSLCFG="enableSNI",0,1

Hello @droidblast ,

Thank you for the follow-up! I was doing some review of the documentation provided, specifically the MQTT note page available here. Our configuration here looks to match this setup, and we should only require the .pem file for the server-only authentication connection.

The documentation also looks to specify that the username and password are bracketed when using the AT+CMQTTCONNECT command, if I am reading the documentation correctly.

At this time, are other clients such as the HiveMQ Websocket client able to successfully connect to the broker with the configured credentials?

Best,
Aaron from HiveMQ Team

Link to the documentation is correct and what I have been following.

I have used MQTT Explorer as well as HiveMQ Cloud to check the user/password which is accepted.

Cert

And successfully connected to the websocket client

I note the following which may be a issue during the SSL handshake.

In the document most but not all sections state

if not declared x is default

In saying that section 10.2.12 AT+CSSLCFG Configure the SSL Context does not set a default.

Section details this…

Ciphersuites
Numeric type, SSL ciphersuites

0X002F TLS_RSA_WITH_AES_128_CBC_SHA
0XFFFF Support all

AT+CSSLCFG: “ciphersuites”,(0-9),(0x002F,0Xffff)

Running the commmand AT+CSSLCFG? returns these logs we see the SSL context is session 0

20:53:33.948 -> AT+CSSLCFG?
20:53:33.995 -> 
20:53:33.995 -> +CSSLCFG: 0,4,1,1,300,"isrgrootx1.pem","","",1,"",0x0
20:53:34.121 -> +CSSLCFG: 1,4,0,1,300,"","","",0,"",0x0
20:53:34.166 -> +CSSLCFG: 2,4,0,1,300,"","","",0,"",0x0
20:53:34.260 -> +CSSLCFG: 3,4,0,1,300,"","","",0,"",0x0
20:53:34.356 -> +CSSLCFG: 4,4,0,1,300,"","","",0,"",0x0
20:53:34.447 -> +CSSLCFG: 5,4,0,1,300,"","","",0,"",0x0
20:53:34.494 -> +CS+CSSAT+CSSLCFG="enableSNI",0,1

Note:

  //result is +CSSLCFG: 0,4,2,1,300,"isrgrootx1.pem","","",0,"",0x0
  //0: The SSL/TLS context ID. In this case, it is the default context, which is ID 0
  //4: The SSL/TLS protocol version. In this case, it is TLS 1.2
  //2: The SSL/TLS cipher suite. In this case, it is AES_128_CBC_SHA256
  //1: The SSL/TLS authentication mode. In this case, it is server authentication only
  //300: The SSL/TLS timeout in seconds
  //"isrgrootx1.pem": The filename of the CA certificate
  //"": The filename of the client certificate
  //"": The filename of the client private key
  //0: The SSL/TLS verify mode
  //"": The domain name used for server verification
  //0x0: Reserved

So if my thinking is correct I should set Support All which will complete the handshake?

AT+CSSLCFG="ciphersuites",0,0xFFFF  //TLS_RSA_WITH_AES_128_CBC_SHA
AT+CSSLCFG="ciphersuites",0,0x002F  //Support all

Connect code

  // Connect to MQTT server
  modem.sendAT("+CMQTTCONNECT=0,\"tcp://xxx.s1.eu.hivemq.cloud:8883\",60,1,\"xxx\",\"xxx\"");
  if (!modem.waitResponse(120000)) {
    Serial.println("CMQTTCONNECT command failed");
    return false;
  }
Connect AT command
AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"

Note that the AT+CMQTTCONNECT returns

18:43:04.398 -> AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"
18:43:05.373 -> MQTT Connect success
18:43:05.373 -> AT+NETOPEN?
18:43:05.419 -> 
18:43:05.419 -> +CMQTTCONNECT: 0,32

Error 0,32 is SSL session 0 code 32 handshake fail

Hello @droidblast ,

Thank you for the thorough notes here - the handshake failure is definitely curious.

This may seem redundant, but I wanted to be thorough here - as this is a SIM device, have we verified that the configuration for network for this device has port 8883 open? I believe that with our connection successful message, it likely means that this connection is already open, but I wanted to verify that there is nothing interacting with port 8883 that could be causing disruption when attempting to complete the handshake.

To clarify from the above, the last “handshake fail” message was after setting "Support All’ for the SLL contect, correct?

Best,
Aaron from HiveMQ Team

Thanks

configuration for network for this device has port 8883 open

Assume so as I get a network operator IP and see no reason that this wouldn’t work.

Steps power modem off/on and wait till modem’s network light is registered (flashing 800ms)

Commands

AT+CPIN?             //no pin set
AT+CSQ                //signal strength
AT+CGREG?        //is registered? Yes
AT+COPS?           //which network operator
AT+NETOPEN      //open network
AT+NETOPEN?   //is network open? Yes
AT+IPADDR        //set network operator IP address

then

AT+CSSLCFG="sslversion",0,4          //Support all but HiveMQ cert is TLS 1.2
AT+CSSLCFG="authmode",0,1          //Server CA only no client cert of key needed
AT+CSSLCFG="ignorelocaltime",0,1  //ignore time
AT+CSSLCFG="cacert",0,"isrgrootx1.pem"  //Set CA Server cert

Now tried

AT+CSSLCFG="ciphersuites",0,0xFFFF //All Support all

then

AT+CSSLCFG="enableSNI",0,1
AT+CMQTTSTART
AT+CMQTTACCQ=0,"client",1,4
AT+CMQTTSSLCFG=0,0

then

AT+CMQTTCONNECT=0,"tcp://xxx.s1.eu.hivemq.cloud:8883",60,1,"xxx","xxx"

Result handshake fail

+CMQTTCONNECT: 0,32