1

I am trying to implement a SSL client into my IoT project. I have copied the SSL_Client example I found in STM32Cube_FW_F7_V1.15.0 into my project and was able to compile succesfully. However the SSL handshake fails with -0x7780 MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE. I attach the console debug output:

  . Seeding the random number generator... ok
  . Loading the CA root certificate ... ok (1 skipped)
  . Connecting to tcp/www.google.de/443... ok
  . Setting up the SSL/TLS structure... ok
  . Performing the SSL/TLS handshake...=> handshake
client state: 0
=> flush output
<= flush output
client state: 1
=> flush output
<= flush output
=> write client hello
client hello, max version: [3:3]
dumping 'client hello, random bytes' (32 bytes)
0000:  e2 13 bf 6d 61 b6 fb a6 82 a4 59 f0 0b ef e9 03  ...ma.....Y.....
0010:  44 be de 3c 49 3d 39 56 51 60 3b b6 49 c4 17 50  D..<I=9VQ`;.I..P
client hello, session id len.: 0
dumping 'client hello, session id' (0 bytes)
client hello, add ciphersuite: c02b
client hello, got 1 ciphersuites (excluding SCSVs)
adding EMPTY_RENEGOTIATION_INFO_SCSV
client hello, compress len.: 1
client hello, compress alg.: 0
client hello, adding server name extension: www.google.de
client hello, adding signature_algorithms extension
client hello, adding supported_elliptic_curves extension
client hello, adding supported_point_formats extension
client hello, adding encrypt_then_mac extension
client hello, adding extended_master_secret extension
client hello, adding session ticket extension
client hello, total extension length: 62
=> write handshake message
=> write record
output record: msgtype = 22, version = [3:3], msglen = 111
dumping 'output record sent to network' (116 bytes)
0000:  16 03 03 00 6f 01 00 00 6b 03 03 e2 13 bf 6d 61  ....o...k.....ma
0010:  b6 fb a6 82 a4 59 f0 0b ef e9 03 44 be de 3c 49  .....Y.....D..<I
0020:  3d 39 56 51 60 3b b6 49 c4 17 50 00 00 04 c0 2b  =9VQ`;.I..P....+
0030:  00 ff 01 00 00 3e 00 00 00 12 00 10 00 00 0d 77  .....>.........w
0040:  77 77 2e 67 6f 6f 67 6c 65 2e 64 65 00 0d 00 0a  ww.google.de....
0050:  00 08 04 03 04 01 03 03 03 01 00 0a 00 04 00 02  ................
0060:  00 15 00 0b 00 02 01 00 00 16 00 00 00 17 00 00  ................
0070:  00 23 00 00                                      .#..
=> flush output
message length: 116, out_left: 116
ssl->f_send() returned 116 (-0xffffff8c)
<= flush output
<= write record
<= write handshake message
<= write client hello
client state: 2
=> flush output
<= flush output
=> parse server hello
=> read record
=> fetch input
in_left: 0, nb_want: 5
in_left: 0, nb_want: 5
ssl->f_recv(_timeout)() returned 5 (-0xfffffffb)
<= fetch input
dumping 'input record header' (5 bytes)
0000:  15 03 03 00 02                                   .....
input record: msgtype = 21, version = [3:3], msglen = 2
=> fetch input
in_left: 5, nb_want: 7
in_left: 5, nb_want: 7
ssl->f_recv(_timeout)() returned 2 (-0xfffffffe)
<= fetch input
dumping 'input record from network' (7 bytes)
0000:  15 03 03 00 02 02 28                             ......(
got an alert message, type: [2:40]
is a fatal alert message (msg 40)
mbedtls_ssl_handle_message_type() returned -30592 (-0x7780)
mbedtls_ssl_read_record() returned -30592 (-0x7780)
ERR
<= handshake
 failed
  ! mbedtls_ssl_handshake returned -0x7780

Any help is greatly appreciated!

UPDATE: The problem was the key exchange method. Only MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED was active. After i added MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ( along with the needed MBEDTLS_RSA_C, MBEDTLS_PKCS1_V21 and MBEDTLS_PKCS1_V15) the handshake took place. Thanks a lot for pointing me to the right directon Gilles

Jan
  • 47
  • 8

1 Answers1

1

The connection fails because the server decides to close the connection immediately after receiving the very first TLS message (ClientHello). It's sending the alert 40, which is “handshake failure”. Unfortunately, that's a generic “I don't like what I heard and I can't talk with you”, it doesn't give any information about what precisely it didn't like. Your TLS client is either buggy or, most likely, misconfigured and sent something that Google's server didn't accept.

Wireshark is helpful in diagnosing network protocol issues. Let's see what it says about the data sent by your client. I'm not a Wireshark expert so I did it the manual way, by starting Wireshark, telling it to listen to port 443 && host www.google.de and replaying the connection with

<clienthello.hex xxd -r -p | socket www.google.de 443 | xxd -p

Here's the dump of the ClientHello provided by Wireshark:

TLSv1.2 Record Layer: Handshake Protocol: Client Hello
    Content Type: Handshake (22)
    Version: TLS 1.2 (0x0303)
    Length: 111
    Handshake Protocol: Client Hello
        Handshake Type: Client Hello (1)
        Length: 107
        Version: TLS 1.2 (0x0303)
        Random: e213bf6d61b6fba682a459f00befe90344bede3c493d3956…
            GMT Unix Time: Mar 11, 2090 20:50:05.000000000 CET
            Random Bytes: 61b6fba682a459f00befe90344bede3c493d395651603bb6…
        Session ID Length: 0
        Cipher Suites Length: 4
        Cipher Suites (2 suites)
            Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
            Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
        Compression Methods Length: 1
        Compression Methods (1 method)
            Compression Method: null (0)
        Extensions Length: 62
        Extension: server_name (len=18)
            Type: server_name (0)
            Length: 18
            Server Name Indication extension
                Server Name list length: 16
                Server Name Type: host_name (0)
                Server Name length: 13
                Server Name: www.google.de
        Extension: signature_algorithms (len=10)
            Type: signature_algorithms (13)
            Length: 10
            Signature Hash Algorithms Length: 8
            Signature Hash Algorithms (4 algorithms)
                Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
                    Signature Hash Algorithm Hash: SHA256 (4)
                    Signature Hash Algorithm Signature: ECDSA (3)
                Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
                    Signature Hash Algorithm Hash: SHA256 (4)
                    Signature Hash Algorithm Signature: RSA (1)
                Signature Algorithm: SHA224 ECDSA (0x0303)
                    Signature Hash Algorithm Hash: SHA224 (3)
                    Signature Hash Algorithm Signature: ECDSA (3)
                Signature Algorithm: SHA224 RSA (0x0301)
                    Signature Hash Algorithm Hash: SHA224 (3)
                    Signature Hash Algorithm Signature: RSA (1)
        Extension: supported_groups (len=4)
            Type: supported_groups (10)
            Length: 4
            Supported Groups List Length: 2
            Supported Groups (1 group)
                Supported Group: secp224r1 (0x0015)
        Extension: ec_point_formats (len=2)
            Type: ec_point_formats (11)
            Length: 2
            EC point formats Length: 1
            Elliptic curves point formats (1)
                EC point format: uncompressed (0)
        Extension: encrypt_then_mac (len=0)
            Type: encrypt_then_mac (22)
            Length: 0
        Extension: extended_master_secret (len=0)
            Type: extended_master_secret (23)
            Length: 0
        Extension: session_ticket (len=0)
            Type: session_ticket (35)
            Length: 0
            Data (0 bytes)

Looking through this, most of the stuff is unsurprising except this:

            Supported Groups (1 group)
                Supported Group: secp224r1 (0x0015)

Secp224r1 is a little-used and officially deprecated curve. Very few servers accept it.

Reconfigure Mbed TLS to support secp256r1 instead. That's the de facto standard curve for resource-constrained devices for ECDH+ECDSA (either that, or Curve25519+Ed25519 for ECDH+EdDSA). In mbedtls/config.h, instead of listing MBEDTLS_ECP_DP_SECP224R1_ENABLED, list MBEDTLS_ECP_DP_SECP256R1_ENABLED. If you set MBEDTLS_ECP_MAX_BITS, make sure that it's set to 256 (or more).

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
  • Thank you so much for your great effort!! The answer is not correct though. Even after adding MBEDTLS_ECP_DP_SECP256R1_ENABLED it still would not work. The problem was the key exchange method. Only MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED was active. After i added MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED the handshake took place. Thanks a lot for pointing me in the correct direction!! – Jan Jun 30 '21 at 08:26
  • @Jan You can connect to `www.google.de` with just `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED` as a ciphersuite. – Gilles 'SO- stop being evil' Jun 30 '21 at 08:32
  • no that's not correct. It's only working when I add MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED, i double checked. It fails later on with mbedtls_x509_crt_parse_der() returned -15104 (-0x3b00) but I will ask a different question for that. Thanks a lot again! – Jan Jul 01 '21 at 08:13
  • @Jan Maybe there's something else missing in your configuration? I don't have an STM32 to test with, but I confirm that my answer works on a PC with `programs/ssl/ssl_client1.c` from the mbedtls source tree, edited to point to `www.google.de` and use the desired cipher suite. -15104 is “PK - The pubkey tag or value is invalid (only RSA and EC are supported)” which also suggests that you're trying to use a feature (algorithm or curve) that is disabled at build time. – Gilles 'SO- stop being evil' Jul 01 '21 at 08:32
  • well i found this post https://forums.mbed.com/t/mbedtls-x509-crt-parse-crt-returns-0x3b00-mbedtls-err-pk-invalid-pubkey/5508 and changed MBEDTLS_MPI_MAX_SIZE to 512 now the handshake runs until the end. Does that make sense to you? – Jan Jul 01 '21 at 10:19
  • @Jan If you're using RSA, you do need bigger numbers. `MBEDTLS_MPI_MAX_SIZE` is in bytes so 512 means you can do up to 4096-bit RSA. With ECC, with only a 256-bit curve enabled, you could have `MBEDTLS_MPI_MAX_SIZE` as small as 32, which can save a substantial amount of RAM. – Gilles 'SO- stop being evil' Jul 01 '21 at 10:33
  • i used this conig file as starting point: https://github.com/ARMmbed/mbedtls/blob/development/configs/config-suite-b.h but had to make the changes I stated in my post. Could you please explain to me why I have to activate RSA in order for it to work then? If i understand you I shouldn't need RSA right? – Jan Jul 02 '21 at 08:22