添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

First of all, thank you for taking the time to read my question.

Brief Intro

Our company currently is developing some IOT products based on GSM modules which are mostly not up-to-date. Unfortunately, GSM module producers don't often update their firmwares according to the latest changes to the standards. Also many useful features of TLS are disabled in these modules because of limited amount of RAM and other resources. This causes working with TLS gets difficult in many scenarios.

The problem

The GSM module which we trying to use (Simcom Sim800 series) is sending Client Hello to the server and server is throwing a fatal exception. I should mention we are using haproxy to terminate TLS connections on the front. I'am trying to open a TCP connection to the server and secure it with TLS. I've inspected the handshake using wireshark and here's what Client Hello looks like:

TLSv1.2 Record Layer: Handshake Protocol: Client Hello
    Content Type: Handshake (22)
    Version: TLS 1.2 (0x0303)
    Length: 63
    Handshake Protocol: Client Hello
        Handshake Type: Client Hello (1)
        Length: 59
        Version: TLS 1.2 (0x0303)
        Random: 3ff366e05d5db792843deb432d36a4308986842d0735aeb7bbdcdbebe560f271
            GMT Unix Time: Jan  1, 2004 03:46:32.000000000 Iran Standard Time
            Random Bytes: 5d5db792843deb432d36a4308986842d0735aeb7bbdcdbebe560f271
        Session ID Length: 0
        Cipher Suites Length: 20
        Cipher Suites (10 suites)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
            Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
            Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
            Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
        Compression Methods Length: 1
        Compression Methods (1 method)
            Compression Method: null (0)
        [JA3 Fullstring: 771,49195-49199-49187-49191-49161-49171-156-60-49172-49162,,,]
        [JA3: 9eed0872a18327d26a4f401325d75c78]

As you can see the module supports TLS1.2. Besides Client Hello doesn't provide any TLS extension at all. Here's the response from server:

TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
    Content Type: Alert (21)
    Version: TLS 1.2 (0x0303)
    Length: 2
    Alert Message
        Level: Fatal (2)
        Description: Handshake Failure (40)

What I've tried

  • I've converted all standard ciphersuite names into openssl ciphersuite names (using 'openssl ciphers -convert') and set them in haproxy configuration:
    bind X.Y.Z.W:12135 ssl crt /usr/local/full.pem ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA
  • I've limited TLS version to 1.2 in haproxy config.
  • I've tried setting minimum TLS version to 1.0 and maximum TLS version to 1.3.
  • I've tried both ecc and rsa keyfiles. We use letsencrypt to issue X.509 certificates for our domain.
  • I've tried self-signed certificates generated by openssl.
  • Actually I don't know what exactly is causing the issue. what I know is other clients can establish TLS connection to the server with those ciphersuites but GSM module can't. Is it possible that openssl is refusing client because of lack of any TLS extension support by the client? What else do you think?
    I should also mention that I've inspected a successful TLS handshake to another server (which is third party and I don't have any access to it) and If you find it useful I can post it here. I can also build openssl with any special flags or configurations if needed.

    The ClientHello is certainly unusual because it has no extensions at all which is likely to cause problems. Do you have any logs from the server that can throw more light on specifically what it doesn't like?

    What OpenSSL version are you using on the server?

    Notably the client is not sending the signature_algorithms extension. The TLSv1.2 RFC says this:

       If the client does not send the signature_algorithms extension, the
       server MUST do the following:
       -  If the negotiated key exchange algorithm is one of (RSA, DHE_RSA,
          DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), behave as if client had
          sent the value {sha1,rsa}.
       -  If the negotiated key exchange algorithm is one of (DHE…

    The ClientHello is certainly unusual because it has no extensions at all which is likely to cause problems. Do you have any logs from the server that can throw more light on specifically what it doesn't like?

    What OpenSSL version are you using on the server?

    Notably the client is not sending the signature_algorithms extension. The TLSv1.2 RFC says this:

       If the client does not send the signature_algorithms extension, the
       server MUST do the following:
       -  If the negotiated key exchange algorithm is one of (RSA, DHE_RSA,
          DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), behave as if client had
          sent the value {sha1,rsa}.
       -  If the negotiated key exchange algorithm is one of (DHE_DSS,
          DH_DSS), behave as if the client had sent the value {sha1,dsa}.
       -  If the negotiated key exchange algorithm is one of (ECDH_ECDSA,
          ECDHE_ECDSA), behave as if the client had sent value {sha1,ecdsa}.
    

    So, in all cases it attempts to fall back to a sigalg based on SHA1. However, SHA1 is not allowed in the default security level in OpenSSL 3.x - so this could well be the problem. I'm not familiar with haproxy configuration so I don't know how to set the security level using it. When passing a ciphersuite list direct to OpenSSL you can add @SECLEVEL=0 onto the end of the list to set the default security level to 0.

    What OpenSSL version are you using on the server?

    The output of haproxy -vv shows that I'm using OpenSSL 3.0.2:

    Built with OpenSSL version : OpenSSL 3.0.2 15 Mar 2022
    Running on OpenSSL version : OpenSSL 3.0.2 15 Mar 2022
    OpenSSL library supports TLS extensions : yes
    OpenSSL library supports SNI : yes
    OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
    OpenSSL providers loaded : default
    

    I will check the solution and report the result back.

    @mattcaswell I've tried to add @SECLEVEL=0 onto the end of ciphersuite list in haproxy configuration and it seems haproxy passes the whole list + @SECLEVEL=0 to the openssl. The good news is it had worked and everything seems ok to me.
    After two weeks of trial and error I cannot imagine that it is working! Now I can sleep well at night thanks to your guidance.
    Wish you the best.

    @mattcaswell By the way I've noticed the server decided to handle TLS handshake using TLS_RSA_WITH_AES_128_GCM_SHA256 :

    Transport Layer Security
        TLSv1.2 Record Layer: Handshake Protocol: Server Hello
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 74
            Handshake Protocol: Server Hello
                Handshake Type: Server Hello (2)
                Length: 70
                Version: TLS 1.2 (0x0303)
                Random: 94d192c296e26b3877708aec8cfa4a30c34eae0fca6cca6d444f574e47524401
                    GMT Unix Time: Feb 12, 2049 20:39:22.000000000 Iran Standard Time
                    Random Bytes: 96e26b3877708aec8cfa4a30c34eae0fca6cca6d444f574e47524401
                Session ID Length: 32
                Session ID: 833f60b0d36afa37f08e6bb3802bebe1682a865766e1c1aa3960b128fa4c7ca9
                Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
                Compression Method: null (0)
                [JA3S Fullstring: 771,156,]
                [JA3S: ac4776ae2f7042ea107581e2be63ffa1]
        TLSv1.2 Record Layer: Handshake Protocol: Certificate
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 3961
            Handshake Protocol: Certificate
                Handshake Type: Certificate (11)
                Length: 3957
                Certificates Length: 3954
                Certificates (3954 bytes)
        TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 4
            Handshake Protocol: Server Hello Done
                Handshake Type: Server Hello Done (14)
                Length: 0
    

    When I limit the ciphersuites to TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 & TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 on the server, handshake fails again (Handshake Failure (40)). Why I cannot use ECDHE as key exchange algorithm?
    I've also noticed that changing key type from RSA to ECDSA will cause handshake failure even without limiting ciphersuites. Why this is happening?

    Is there anyway to preset an EC group and enforce client to use it?

    Not with OpenSSL. Actually it appears OpenSSL is being a bit restrictive here.

    RFC8422 introduced the elliptic_curves extension (which was later renamed to "supported_groups" in a subsequent RFC). It says this about it:

        A TLS client that proposes ECC cipher suites in its ClientHello
       message SHOULD include these extensions.
    

    So, the TLS client here is technically conformant with the RFC because the above statement is a SHOULD but not a MUST.

    Subsequently the RFC says:

    A client that proposes ECC cipher suites may choose not to include these extensions.  In this case, the server is free to choose any one of the elliptic curves or point formats listed in [Section 5](https://datatracker.ietf.org/doc/html/rfc8422#section-5).
    

    So, this allows OpenSSL to just pick a curve if the client hasn't provided a list to choose from. There aren't any MUSTs here, so I think OpenSSL is also conformant in deciding to fail the handshake in this case. But it would be possible for us to add the ability to choose an arbitrary one and that would also be ok.

    Could other SSL implementations like libreSSL / WolfSSL accept this ClientHello to use EC based ciphersuites?

    Yes, that is possible.

    In my opinion, It might be good to have that feature if it is not against security constraints of OpenSSL. GSM modules really become tricky and difficult when it comes to TLS. I think this can help our project a lot and also improves security of connection of GSM modules to the servers. Thank you by the way, you've helped me a lot.

    @mattcaswell Shall I open a feature-request issue for that purpose or this discussion is enough by the way?
    Sorry for asking, I'm newbie to openssl community.