EC200U TLS 1.2 Connection Fails with 1024-bit RSA Server Key

Hello Quectel Support Team and Community,

We are experiencing an issue with establishing a TLS 1.2 connection using an EC200U module when the target server is using a 1024-bit RSA certificate. Connections to other servers with modern 2048-bit keys work perfectly.

1. Project Goal:

Our goal is to connect the EC200U module to a legacy server via MQTT over TLS. Due to server-side constraints that are beyond our control, we are forced to connect to an endpoint that uses a 1024-bit RSA key.

2. Hardware and Firmware Details:

  • Module: Quectel EC200U-EU
  • Firmware Version: EC200UEUAAR03A02M08
  • Network Operator: [MCI, Irancell.]

3. Problem Description:

We have configured the SSL context for TLS 1.2 and loaded the correct Root CA certificate. When we attempt to open the SSL connection using AT+QSSLOPEN, the operation fails, typically with an error code. While we can successfully connect to other test servers that use 2048-bit keys, the connection to the specific server with the 1024-bit key always fails.

4. AT Command Sequence & Log:

Here is a sanitized log of the AT commands we are using to configure and open the connection.
AT+QIACT=1

OK
AT+QIACT?

+QIACT: 1,1,1,“26.166.242.32”

OK
AT+qflst=“*”

+QFLST: “UFS:boot”,15004
+QFLST: “UFS:firm”,243616
+QFLST: “UFS:Test.txt”,8
+QFLST: “UFS:CA0”,730
+QFLST: “UFS:CC0”,726
+QFLST: “UFS:CK0”,900
+QFLST: “UFS:CK1”,1700
+QFLST: “UFS:CC1”,1094
+QFLST: “UFS:CA1”,1130
+QFLST: “UFS:CK2”,932
+QFLST: “UFS:CA2”,898
+QFLST: “UFS:CC2”,878

OK
AT+QSSLCFG=“sslversion”,3,3

OK
AT+QSSLCFG=“dtls”,3,0

OK
AT+QSSLCFG=“ciphersuite”,3,0xFFFF

OK
AT+QSSLCFG=“seclevel”,3,2

OK
AT+QSSLCFG=“cacert”,3,“UFS:CA0”

OK
AT+QSSLCFG=“clientcert”,3,“UFS:CC0”

OK
AT+QSSLCFG=“clientkey”,3,“UFS:CK0”

OK
AT+QSSLCFG=“sni”,3,0

OK
AT+QSSLCFG=“ignorelocaltime”,3,0

OK
AT+QSSLCFG=“negotiatetime”,3,300

OK
AT+QSSLCFG=“ignoreinvalidcertsign”,3,0

OK
AT+QSSLCFG=“ignorecertitem”,3,0

OK
AT+QSSLCFG=“ignoremulticertchainverify”,3,0

OK
AT+QSSLCFG=“session_cache”,3,0

OK
AT+QSSLOPEN=1,3,0,“gps.try.ir”,14060,0

OK

+QSSLOPEN: 0,579

Dear @reza471,

Thank you for the detailed log.

Based on your description and the behavior you see, this is consistent with the TLS stack rejecting the server certificate because the server is using a 1024-bit RSA key. Even when TLS 1.2 is selected and the CA is correct, many embedded TLS implementations will not accept 1024-bit RSA server keys due to security policy, and the handshake is terminated during TLS session establishment. That is why connections to servers using 2048-bit RSA work normally while this specific endpoint always fails.

Please also note that you are opening to a hostname (gps.try.ir) with SNI disabled. Some servers will present a default certificate when SNI is not provided, which can also cause handshake or verification failures. So we recommend validating with SNI enabled as part of the confirmation steps below.

To confirm this conclusively, please run these two quick checks and share the outputs:

  1. Enable SNI and retry with the same SSL context
    Set SNI on the same context and retry QSSLOPEN:
    AT+QSSLCFG=sni,3,1
    AT+QSSLOPEN=1,3,0,gps.try.ir,14060,0

  2. Test-only isolation to distinguish certificate verification vs handshake rejection
    Temporarily disable certificate verification to see whether the stack still refuses the 1024-bit RSA key:
    AT+QSSLCFG=seclevel,3,0
    AT+QSSLOPEN=1,3,0,gps.try.ir,14060,0

If the connection still fails with seclevel set to 0, that confirms the failure is at the TLS handshake level due to an unsupported or rejected server key profile, and it cannot be resolved by CA file changes or SSL parameter tuning on the module.

The correct resolution is to update the server to use a modern certificate with at least a 2048-bit RSA key (or ECDSA). If the legacy server cannot be changed, the practical workaround is to deploy a TLS gateway/proxy in front of it using a modern 2048-bit certificate and have the EC200U connect to that gateway over TLS 1.2. The gateway can then connect onward to the legacy endpoint as required.

Best Regards,
Aghelan

Thank you.
this is log for section 1 SNI=1
AT+QIACT?

OK
AT+QIACT=1

OK
AT+QIACT?

+QIACT: 1,1,1,“26.121.165.10”

OK
AT+qflst=“*”

+QFLST: “UFS:CA0”,730
+QFLST: “UFS:CC0”,726
+QFLST: “UFS:CK0”,900

OK
AT+QSSLCFG=“sslversion”,3,3

OK
AT+QSSLCFG=“dtls”,3,0

OK
AT+QSSLCFG=“ciphersuite”,3,0xFFFF

OK
AT+QSSLCFG=“seclevel”,3,2

OK
AT+QSSLCFG=“cacert”,3,“UFS:CA0”

OK
AT+QSSLCFG=“clientcert”,3,“UFS:CC0”

OK
AT+QSSLCFG=“clientkey”,3,“UFS:CK0”

OK
AT+QSSLCFG=“sni”,3,1

OK
AT+QSSLCFG=“ignorelocaltime”,3,0

OK
AT+QSSLCFG=“negotiatetime”,3,300

OK
AT+QSSLCFG=“ignoreinvalidcertsign”,3,0

OK
AT+QSSLCFG=“ignorecertitem”,3,0

OK
AT+QSSLCFG=“ignoremulticertchainverify”,3,0

OK
AT+QSSLCFG=“session_cache”,3,0

OK
AT+QSSLOPEN=1,3,0,gps.try.ir,14060,0

OK

+QSSLOPEN: 0,579

and section 2 , seclevel,3,0
AT+QIACT?

+QIACT: 1,1,1,“26.121.165.10”

OK
AT+qflst=“*”

+QFLST: “UFS:CA0”,730
+QFLST: “UFS:CC0”,726
+QFLST: “UFS:CK0”,900

OK
AT+QSSLCFG=“sslversion”,3,3

OK
AT+QSSLCFG=“dtls”,3,0

OK
AT+QSSLCFG=“ciphersuite”,3,0xffff

OK
AT+QSSLCFG=“seclevel”,3,0

OK
AT+QSSLCFG=“cacert”,3,“UFS:CA0”

OK
AT+QSSLCFG=“clientcert”,3,“UFS:CC0”

OK
AT+QSSLCFG=“clientkey”,3,“UFS:CK0”

OK
AT+QSSLCFG=“sni”,3,1

OK
AT+QSSLCFG=“ignorelocaltime”,3,0

OK
AT+QSSLCFG=“negotiatetime”,3,300

OK
AT+QSSLCFG=“ignoreinvalidcertsign”,3,0

OK
AT+QSSLCFG=“ignorecertitem”,3,0

OK
AT+QSSLCFG=“ignoremulticertchainverify”,3,0

OK
AT+QSSLCFG=“session_cache”,3,0

OK
AT+QSSLOPEN=1,3,0,gps.try.ir,14060,0

OK

+QSSLOPEN: 0,0

+QSSLURC: “closed”,0

Dear @reza471 ,

Thanks for running both checks and sharing the full logs. This is a very useful result.

What your new logs prove

  1. SNI is not the root cause
    With SNI enabled (sni=1), the connection still fails at seclevel=2 with +QSSLOPEN: 0,579. So this is not simply the server presenting the wrong certificate due to missing SNI.
  2. The TLS handshake can succeed, but certificate verification is what blocks it
    When you set seclevel=0, QSSLOPEN succeeds (+QSSLOPEN: 0,0). That means the module can complete the TLS handshake with that server even in this legacy setup.
    So the failure at seclevel=2 is happening during certificate validation/policy checks (chain validation, name checks, time validity, or key-strength policy applied during verification), not because the module cannot negotiate TLS 1.2 with the server at all.

Why it closes right after connect in seclevel=0
After QSSLOPEN succeeds, the server may close the socket if no application data is sent or if it expects a specific protocol exchange immediately. That closure is separate from the seclevel=2 verification failure and does not mean the handshake failed.

What to do next (to make this conclusive and fixable)

  1. Capture the exact failure reason from the module
    Right after the seclevel=2 failure (+QSSLOPEN: 0,579), please run and paste:
    AT+QIGETERROR
  2. Rule out time/validity as a quick isolation (test only)
    If the module time is not valid, certificate validation can fail even when CA is correct. Please try (test only):
    AT+QSSLCFG=ignorelocaltime,3,1
    Then retry QSSLOPEN with seclevel=2 and share the result + AT+QIGETERROR.
  3. Confirm the CA file matches what the server actually presents
    Please confirm CA0 is the issuing CA chain for gps.try.ir (root/intermediate that signs the server certificate). If the server sends a chain that does not anchor to CA0, seclevel=2 will fail but seclevel=0 will still connect, exactly like your result.

Expected resolution based on your outcome so far
Because seclevel=0 works but seclevel=2 fails, this cannot be solved by changing TLS version or enabling SNI anymore. The fix must be one of these:

  • update the server certificate chain to a modern, verifiable chain (recommended), and ideally upgrade the server key to at least RSA 2048 as well, or
  • place a TLS gateway/proxy in front of the legacy server using a modern, verifiable certificate chain, and have EC200U connect to the gateway

Please share the AT+QIGETERROR output from the seclevel=2 failure (and the ignorelocaltime=1 re-test result if you can). With that, we can tell you exactly which verification condition is failing on the module side.

Best Regards,
Aghelan