Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disabled TLS secure renegotiation prevents mutual auth from succeeding #9170

Open
5 tasks done
randomdude opened this issue Jul 23, 2024 · 1 comment
Open
5 tasks done

Comments

@randomdude
Copy link

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • [ N/A ] If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: [ESP8266]
  • Core Version: [7e0d20e]
  • Development Env: [VSMicro]
  • Operating System: [Windows]

Settings in IDE

  • Module: [nodemcu]
  • Flash Mode: [idk]
  • Flash Size: [4MB]
  • lwip Variant: [v2 Lower Memory]
  • Reset Method: [nodemcu]
  • Flash Frequency: [40MHz]
  • CPU Frequency: [160MHz]
  • Upload Using: [SERIAL]
  • Upload Speed: [115200] (serial upload only)

Problem Description

It seems that #6165 has broken mutual TLS authentication, with the esp8266 acting as a client, in some scenarios.

I'm attempting to connect to a TLS1.2-enabled apache server from an esp8266 via HTTPS. The server is configured such that it requires that the esp8266 presents a client certificate (ie, I call WiFiClientSecure.setClientRSACert with an appropriately-authorized certificate prior to connection). However, I found that requests would fail, even when a similar request, with the same keys, would succeed when attempted from my Windows desktop.

I observed the following in my Arduino sketch:

  • HTTPClient.GET returning -5, ('connection lost')
  • WiFiClientSecure.getLastSSLError returning 40 ('SSL received fatal alert - Decoding error: extraneous element.')

And in my server (apache) logs:

[Tue Jul 23 15:12:57.102589 2024] [ssl:info] [pid 2206:tid 139638655448832] [client 172.17.0.1:59408] AH01964: Connection to child 16 established (server localhost:443)
[Tue Jul 23 15:12:57.102766 2024] [ssl:debug] [pid 2206:tid 139638655448832] ssl_engine_kernel.c(2372): [client 172.17.0.1:59408] AH02043: SSL virtual host for servername dev.home.gamesfairy.co.uk found
[Tue Jul 23 15:12:57.400923 2024] [ssl:debug] [pid 2206:tid 139638655448832] ssl_engine_kernel.c(2254): [client 172.17.0.1:59408] AH02041: Protocol: TLSv1.2, Cipher: AES128-SHA256 (128/128 bits)
[Tue Jul 23 15:12:58.422204 2024] [ssl:debug] [pid 2206:tid 139638655448832] ssl_engine_kernel.c(415): [client 172.17.0.1:59408] AH02034: Initial (No.1) HTTPS request received for child 16 (server dev.home.gamesfairy.co.uk:443)
[Tue Jul 23 15:12:58.422284 2024] [ssl:debug] [pid 2206:tid 139638655448832] ssl_engine_kernel.c(782): [client 172.17.0.1:59408] AH02255: Changed client verification type will force renegotiation
[Tue Jul 23 15:12:58.479827 2024] [ssl:info] [pid 2206:tid 139638655448832] [client 172.17.0.1:59408] AH02221: Requesting connection re-negotiation
[Tue Jul 23 15:12:58.479887 2024] [ssl:debug] [pid 2206:tid 139638655448832] ssl_engine_kernel.c(984): [client 172.17.0.1:59408] AH02260: Performing full renegotiation: complete handshake protocol (client does support secure renegotiation)
[Tue Jul 23 15:12:58.479969 2024] [ssl:debug] [pid 2206:tid 139638655448832] ssl_engine_kernel.c(2254): [client 172.17.0.1:59408] AH02041: Protocol: TLSv1.2, Cipher: AES128-SHA256 (128/128 bits)
[Tue Jul 23 15:12:58.479976 2024] [ssl:info] [pid 2206:tid 139638655448832] [client 172.17.0.1:59408] AH02226: Awaiting re-negotiation handshake
[Tue Jul 23 15:12:58.491621 2024] [ssl:error] [pid 2206:tid 139638655448832] [client 172.17.0.1:59408] AH02261: Re-negotiation handshake failed
[Tue Jul 23 15:12:58.491652 2024] [ssl:error] [pid 2206:tid 139638655448832] SSL Library Error: error:14094153:SSL routines:ssl3_read_bytes:no renegotiation
[Tue Jul 23 15:12:58.491673 2024] [ssl:debug] [pid 2206:tid 139638655448832] ssl_engine_io.c(1368): [client 172.17.0.1:59408] AH02007: SSL handshake interrupted by system [Hint: Stop button pressed in browser?!]
[Tue Jul 23 15:12:58.491678 2024] [ssl:info] [pid 2206:tid 139638655448832] [client 172.17.0.1:59408] AH01998: Connection closed to child 16 with abortive shutdown (server dev.home.gamesfairy.co.uk:443)

(please forgive my verbosity here - I'm trying to maximise discoverability in case any one else encounters the same issue).

After much troubleshooting, I found this to be a consequence of the linked PR. I am no TLS guru, but I believe that the server will trigger a secure renegotiation once the HTTP headers are received, once it has determined the appropriate vhost to route to. This means it can request the client to authenticate on a per-vhost basis. The linked PR, however, disables renegotiation, and thus the handshake fails. I found this by dumping (and decrypting) the TLS traffic:

image

As you can see, the esp8266 (172.17.0.1) sends the HTTP headers, and then sends a warning to the server, stating that renegotiation is not supported. The server then terminates the connection.

Reverting #6165 and relevant parts of #6065 appeared to resolve my issue on my install of esp8266 v3.1.2, as the secure renegotiation succeeded, the client is authenticated correctly, and the HTTP request is performed with no problem.

However, in the process of filing this bug, I attempted the same 'dirty hack' on the current git branch (see version hash above), where I was unfortunately met with a stack overflow deep within BearSSL. My TLS/BearSSL skills aren't enough for me to progress this any further.

state: 0 -> 2 (b0)
.state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 1
cnt 

connected with stripysocks, channel 11
dhcp client start...
ip:192.168.90.170,mask:255.255.255.0,gw:192.168.90.251
.Waiting for NTP time sync: ...................pm open,type:2 0
............
Current time: Tue Jul 23 16:24:17 2024
BSSL:_connectSSL: start connection
BSSL:Connected!
[HTTP-Client][sendRequest] type: 'GET' redirCount: 0
BSSL:_connectSSL: start connection
BSSL:Connected!
[HTTP-Client] connected to dev.home.gamesfairy.co.uk:443
[HTTP-Client] sending request header
-----
GET / HTTP/1.1
Host: dev.home.gamesfairy.co.uk
User-Agent: ESP8266HTTPClient
Accept-Encoding: identity;q=1,chunked;q=0.1,*;q=0
Connection: keep-alive
Content-Length: 0

-----

To make this dump useful, DECODE IT - https://tinyurl.com/8266dcdr
--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Stack overflow detected

>>>stack>>>

ctx: bearssl
sp: 3fff1768 end: 3fff2200 offset: 0000
3fff1768:  00000001 40100184 00000000 00000000  
3fff1778:  3ffe8654 4020821d 3fff1946 3fff18ba  
3fff1788:  3fff182e 40222602 00000396 3fff1c72  
3fff1798:  00000002 4022fbdd 04440002 73733d0b  
3fff17a8:  193508c3 0a513d9b 4ef70260 6ffe1723  
3fff17b8:  13062e0a 15437d64 0bf301af 313f473a  
3fff17c8:  595d010d 3e557911 2a727687 14e57786  
3fff17d8:  6d33680a 288a25b3 422b79e9 7f516f5e  
3fff17e8:  10a251a2 2e2d6201 5d4712b3 657d455b  
3fff17f8:  104116d7 5fdf02a3 41003d1b 6904478f  
3fff1808:  76c02c6f 5ded01a8 448c208d 28eb69cb  
3fff1818:  4aff5f91 034517a4 2d465f0c 297b0cf8  
3fff1828:  1afe266d 0444000c 04a9288b 4f1a4aa8  
3fff1838:  05306950 381e0bf7 3e491b66 04bc1bca  
3fff1848:  428a6ee2 759e3ff3 42fb7558 61564464  
3fff1858:  5c142d5d 198336f1 0d27105b 65534b1c  
3fff1868:  6b7f44ff 2e761abf 67c9470a 16e03b2a  
3fff1878:  43ea45cb 62cb2324 0e172d9e 7a782d8b  
3fff1888:  3986093a 7a537e82 37a457d4 0fba01b8  
3fff1898:  3d8c5cf6 30e434f9 444c4199 3b2d47d8  
3fff18a8:  22a856c1 65fa3ca6 534971c4 310f2799  
3fff18b8:  04440007 59943a49 22267934 203b3dfa  
3fff18c8:  676e72a2 6dff1144 0e4d09ce 50cb03d1  
3fff18d8:  51cf08f9 1f5f34e6 4a7d680e 7dee5e7f  
3fff18e8:  0cca766d 0a641b42 406a5bad 387606b7  
3fff18f8:  142d1ab8 61ff1614 1fc965c2 252760f5  
3fff1908:  302d663d 6b363353 010f7ace 27d3169f  
3fff1918:  3f8235a0 01094260 492853f2 107b6c01  
3fff1928:  5949584f 046a71c8 79df390e 407c03dc  
3fff1938:  523a31a0 12de46c7 2f25715e 0444000e  
3fff1948:  747634bf 179626e1 61c919fc 3ba35d43  
3fff1958:  27353093 4ac01984 7ec352b1 673e47b0  
3fff1968:  5d5158fe 1d9170f3 19c8375e 1aad6fe9  
3fff1978:  4f5812e3 740b32a5 58ee4fb5 738434c9  
3fff1988:  1e7c21d3 6f304fbb 6bae0643 7cb96a5a  
3fff1998:  27d722cb 5f9f7f1b 3d5d4a6a 28c013b7  
3fff19a8:  23244ec4 38fd6c4c 5e7d0787 02447e9d  
3fff19b8:  64ea2079 43753018 05e52256 4cfe63b8  
3fff19c8:  176850b9 78b669d2 04440003 207a521a  
3fff19d8:  434432ad 6b58346c 0ecc42dc 2f4e7545  
3fff19e8:  4b8c1b9d 64245f3f 3d595901 64d606d1  
3fff19f8:  32eb5589 172d77d5 03093c60 5fd60744  
3fff1a08:  5a534c67 788a3700 26a059ce 7aa03716  
3fff1a18:  487f36d7 6da95fdd 0aa771e6 38f51f05  
3fff1a28:  6a0c72c9 78d52244 01057405 15494d35  
3fff1a38:  0de97538 6aa91a38 0ab37fef 2c764651  
3fff1a48:  6335682c 60aa4044 3b447a5b 368a2c52  
3fff1a58:  06b136d7 04440002 207a521a 434432ad  
3fff1a68:  6b58346c 0ecc42dc 2f4e7545 4b8c1b9d  
3fff1a78:  64245f3f 3d595901 64d606d1 32eb5589  
3fff1a88:  172d77d5 03093c60 5fd60744 5a534c67  
3fff1a98:  788a3700 26a059ce 7aa03716 487f36d7  
3fff1aa8:  6da95fdd 0aa771e6 38f51f05 6a0c72c9  
3fff1ab8:  78d52244 01057405 15494d35 0de97538  
3fff1ac8:  6aa91a38 0ab37fef 2c764651 6335682c  
3fff1ad8:  60aa4044 3b447a5b 368a2c52 06b136d7  
3fff1ae8:  04440002 3f7e3a25 64cf508f 137f015b  
3fff1af8:  62641e67 0514750c 718e3ca2 0b2479db  
3fff1b08:  11cb13d9 14e82d66 641912d1 6f84215b  
3fff1b18:  016e4c1a 36aa173d 6cec2bb7 33aa0b3f  
3fff1b28:  79e874fb 26567745 0bfe07df 1ab76c3a  
3fff1b38:  43db5bde 180378e0 0148494a 4f8418e3  
3fff1b48:  19be4adc 2db92d1b 6c5a69ec 02220ce7  
3fff1b58:  5a740837 6dc47373 74a6183b 3bf900a5  
3fff1b68:  61bc735d 28d4782b 63020eb6 0444000a  
3fff1b78:  44682bec 158b79c2 4dff553d 7c0f7ee1  
3fff1b88:  1a331e27 335941e5 42a17351 1cb92b3b  
3fff1b98:  65797592 278609c1 7a985a4c 0ecf5fdf  
3fff1ba8:  025329d8 10923f7c 21f07a2c 04d76f30  
3fff1bb8:  051428de 3ad1587d 6fe62fa6 7a932004  
3fff1bc8:  550512d8 7cb11fff 21770e47 1b2a1c30  
3fff1bd8:  02100fcb 61491751 243533f6 72f906c9  
3fff1be8:  71c15870 29db6ca3 098a5afc 49783bbd  
3fff1bf8:  524d0f84 5f224b90 04440003 70830617  
3fff1c08:  79404d67 4c577841 176d5312 6a1d3e56  
3fff1c18:  2a6f0464 20bd3365 02a35f28 32113a67  
3fff1c28:  0ee36bfd 1e355df0 7aad0565 37ca6819  
3fff1c38:  3fc1038d 1753194c 5fb11507 4a253f71  
3fff1c48:  297a6ae4 6fb104c6 788311ca 5df80691  
3fff1c58:  041b4d53 3b9a54d3 66b93f5c 69e32ca6  
3fff1c68:  7dfe7b29 1eb41f34 71ee5cc1 7f7069d6  
3fff1c78:  556965a7 5dc04e0f 40472b4b 465060e3  
3fff1c88:  6fa95dc0 04440008 6ebf23f4 3145410f  
3fff1c98:  665321fa 25b87d72 15464f57 7ed57f9d  
3fff1ca8:  67c02155 5f737b4f 1329581c 49c07327  
3fff1cb8:  18b069a0 2be14d3f 4e0322bf 11750cb7  
3fff1cc8:  0d00487b 4bfb36f2 421d1dfe 54140988  
3fff1cd8:  63971e79 4a0e13fc 508b1bcc 70af3603  
3fff1ce8:  6e5a45be 04eb7364 7b2f149f 30221e36  
3fff1cf8:  5f0a104d 535d34a5 384d212a 0a4c2e00  
3fff1d08:  35af783b 2c481855 783b1bb4 152b1ccf  
3fff1d18:  04440001 6d391f3f 470a3b58 7cfc66dc  
3fff1d28:  30ea00b0 35e449aa 26e64b3a 05fd3635  
3fff1d38:  4ae478d3 33fc3861 34a02e1d 273d4160  
3fff1d48:  66c56645 68274b49 76ea2b31 3b5f3a10  
3fff1d58:  05197258 2147344f 154a3b45 35170e85  
3fff1d68:  72a54339 55192314 415e7a93 60422a48  
3fff1d78:  564b3996 35626716 21376ee9 446062f4  
3fff1d88:  17df36e1 34bc5d6f 012a61a7 74405928  
3fff1d98:  1e6a0fbe 18fc4117 6dd012dd 04440008  
3fff1da8:  70fa61e4 5a5e7598 174643ba 24a579ca  
3fff1db8:  07ec1805 7ec6669e 57c61c6a 793e3e39  
3fff1dc8:  60b95edd 6f287276 09e85186 03b626d7  
3fff1dd8:  5aa14342 6ec10c24 58890f01 4fc838e4  
3fff1de8:  477112d2 0a2c2e66 338234c4 49076eee  
3fff1df8:  16323000 3eb74ae7 5c7859a4 74ba2422  
3fff1e08:  3862432e 79ba6c4f 47a95638 6b7e08b1  
3fff1e18:  1e7b50b2 23ee241a 12d4164a 1e2f7ae9  
3fff1e28:  3e024704 7f570617 43a70000 ab70030e  
3fff1e38:  d58bc6be 901f42df 8405f761 9957a561  
3fff1e48:  2d5b8023 065e5ea0 de3ec2d4 d8803303  
3fff1e58:  eab106a2 044ada94 08a9793e 91af373f  
3fff1e68:  f004b044 2efdf680 00000000 00000000  
3fff1e78:  00000000 00006778 4ef56c53 6ca86210  
3fff1e88:  4f7961a0 467e02c9 8b98a305 b2d83fe8  
3fff1e98:  ce96d0a6 8eb2401e c89f535d 05497667  
3fff1ea8:  f29c7c17 5094c9d5 648ddfea cc5af810  
3fff1eb8:  cca1a9df e030b8dc 6bee6214 bbac8b80  
3fff1ec8:  b851dc4a b24fcbf4 f63a559e 7c888a73  
3fff1ed8:  cbd54400 c55f3d13 2238e610 65696c59  
3fff1ee8:  a775c7f9 92301d16 c2587e66 71b7d8a9  
3fff1ef8:  4ec164d0 d6f6a484 a51c53da df71d5aa  
3fff1f08:  fc118513 fb4cb613 25fb93aa e32c7222  
3fff1f18:  4edab9b9 3f70dd5c f31499db 6ce3707a  
3fff1f28:  bad487ee 58ab0397 23a8f862 92b3bdc5  
3fff1f38:  abba0e2f 28a931da 3fff1f40 40258478  
3fff1f48:  9bfff35d 3fff2000 13be8140 8cc70208  
3fff1f58:  90befffa a4506ceb bef9a3f7 c67178f2  
3fff1f68:  3fff1f40 01394007 a7d54ca7 a5994620  
3fff1f78:  ff94faae 4f0332f4 6b519bf3 abb96cb8  
3fff1f88:  a51b0ea5 62c0db16 23a8f862 abba0e2f  
3fff1f98:  ffb7453f 3fff2090 37b20138 8cc70208  
3fff1fa8:  90befffa 3fff2040 3fffa6dc 3fffa6dc  
3fff1fb8:  00000030 40221863 61f70584 61a55799  
3fff1fc8:  23805b2d a05e5e06 d4c23ede 033380d8  
3fff1fd8:  a206b1ea 94da4a04 3e79a908 3f37af91  
3fff1fe8:  44b004f0 80f6fd2e 00000000 00000000  
3fff1ff8:  00000000 78670000 ab114060 f7d5674f  
3fff2008:  5b178f7c d0669861 61ed350f ea45937e  
3fff2018:  8fd8b304 4ad406d5 00000200 00000003  
3fff2028:  3fffa931 3fffa8cc 00000008 3fffa4bc  
3fff2038:  40258340 40232156 00000005 61f70584  
3fff2048:  61a55799 23805b2d a05e5e06 d4c23ede  
3fff2058:  033380d8 a206b1ea 94da4a04 3e79a908  
3fff2068:  3f37af91 44b004f0 9cf6fd2e 604828c1  
3fff2078:  acd01bbc bce2919a 00000100 3fff1a5e  
3fff2088:  0000595d 00000396 00000350 3fff19d2  
3fff2098:  0000008c 3fff24a8 00000001 3fffa4bc  
3fff20a8:  abb96cb8 3fffa4bc 00000020 3fff24a8  
3fff20b8:  3fffa4bc 3fffa4bc 00000020 00000200  
3fff20c8:  00000100 40222d49 604011ab 4f67d5f7  
3fff20d8:  7c8f175b 619866d0 0f35ed61 7e9345ea  
3fff20e8:  04b3d88f d506d44a 5cef6801 3b475f0e  
3fff20f8:  8fde38c7 7a047bca aaa9128e 45bd83d5  
3fff2108:  d0df2d90 a4d1965b 3fffa8f0 3fffa4bc  
3fff2118:  3fff9bcc 40223ba4 00004bc6 00000000  
3fff2128:  3fffab17 3fff9bcc 3fffa3bc 3fffa44c  
3fff2138:  3fffa3b0 40224647 00000000 00000000  
3fff2148:  3ffefb28 00000030 402590b4 78988a00  
3fff2158:  3fff23dc 00000001 00000016 00000010  
3fff2168:  00000003 3fffa92c 3fff21b0 00000000  
3fff2178:  00000000 00000000 00000000 00000010  
3fff2188:  402590b5 00000004 3fffa3c4 3fffa3c0  
3fff2198:  00000303 3fff9bb0 fffff81c 0000007e  
3fff21a8:  3fffa6b0 0000007e 00000245 deadbeef  
3fff21b8:  deadbeef 3fffa6cc 00000000 3fffa5cc  
3fff21c8:  3fff9bcc 40222f30 3fffa3b0 00000000  
3fff21d8:  3fff9bcc 40223332 0000005a deadbeef  
3fff21e8:  deadbeef 3ffefb24 00000000 3fffab17  
3fff21f8:  3fff08ec 402017a0 deadbeef a5a5a5a5  

ctx: cont
sp: 3ffffe30 end: 3fffffd0 offset: 0000
3ffffe30:  00000000 3fffab17 00001388 402047b2  
3ffffe40:  0000005a 00001388 40208222 00001388  
3ffffe50:  00000010 000051e2 00000001 40204789  
3ffffe60:  00000000 00000020 3fff9a2c 00000000  
3ffffe70:  000050da fffffffc 3fff08ec 40204be3  
3ffffe80:  00000000 fffffffc 3fff08ec 40204d9c  
3ffffe90:  000050da 00000000 3ffef9f8 4020b476  
3ffffea0:  000050da fffffffc 3ffef9f8 40205801  
3ffffeb0:  000000b0 00000000 00b000bf 00000000  
3ffffec0:  3ffefa28 3ffe9a15 00000019 00000094  
3ffffed0:  3ffefa10 00000000 3fff3634 00000000  
3ffffee0:  4025cff8 3ffe9a15 3fffff00 00000000  
3ffffef0:  3ffefaec 3ffe9a15 3ffef9f8 402061cb  
3fffff00:  00000000 000e000f 00000000 401007ca  
3fffff10:  3ffe9a0f 00000000 0000063f 40100b80  
3fffff20:  000031f8 00000000 3ffe8658 00000000  
3fffff30:  00000000 3fff08ec 00000000 00000000  
3fffff40:  00000000 00000020 3fff3614 40100d06  
3fffff50:  4024cc02 3ffe8888 3fffff7c 3ffefa7c  
3fffff60:  3ffe88a2 3ffe8888 3ffef9f8 40201376  
3fffff70:  00000000 0010001f 00000000 00000000  
3fffff80:  0019001f 00000000 00000002 3ffefc88  
3fffff90:  3fff2424 3ffefaec 3fff2424 3ffefc88  
3fffffa0:  3fff2424 3ffefa7c 3fff2e94 3ffefc88  
3fffffb0:  3fffdad0 00000000 3ffefc5c 402083c0  
3fffffc0:  feefeffe feefeffe 3fffdab0 40101039  
<<<stack<<<

To make this dump useful, DECODE IT - https://tinyurl.com/8266dcdr
--------------- CUT HERE FOR EXCEPTION DECODER ---------------

The decoded stack trace:

0x40100158: ets_post at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\core_esp8266_main.cpp:243
0x40207a2d: esp_suspend_within_cont at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\core_esp8266_main.cpp:121
0x40207a2d: __yield at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\core_esp8266_main.cpp:193
0x40220a3a: br_rsa_i15_private at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/rsa/rsa_i15_priv.c:160
0x4022e015: br_i15_modpow_opt at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/int/i15_modpow2.c:159
0x4021fc9b: sha2small_out at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/hash/sha2small.c:249
0x4023058e: br_multihash_out at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/hash/multihash.c:165
0x40221181: cc_do_sign at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/ssl/ssl_ccert_single_rsa.c:130
0x40221fdc: make_client_sign at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/ssl/ssl_hs_client.c:384
0x40222a7f: br_ssl_hs_client_run at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/ssl/ssl_hs_client.c:1279
0x40221368: br_ssl_engine_closed at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/inner.h:2211
0x40221368: jump_handshake at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/ssl/ssl_engine.c:1081
0x4022176a: br_ssl_engine_sendrec_ack at /home/earle/src/esp-quick-toolchain/arduino/tools/sdk/ssl/bearssl/src/ssl/ssl_engine.c:1168
0x402046c2: BearSSL::WiFiClientSecureCtx::_run_until(unsigned int, bool) at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:542
0x40207a32: esp_get_cycle_count at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\core_esp8266_features.h:64
0x40207a32: EspClass::getCycleCount() at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\Esp.h:237
0x40207a32: esp_suspend_within_cont at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\core_esp8266_main.cpp:122
0x40207a32: __yield at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\core_esp8266_main.cpp:193
0x40204699: BearSSL::WiFiClientSecureCtx::_run_until(unsigned int, bool) at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:516
0x40204a07: BearSSL::WiFiClientSecureCtx::_pollRecvBuffer() at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:426
0x40204b84: BearSSL::WiFiClientSecureCtx::connected() at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:270
0x40204b84: BearSSL::WiFiClientSecureCtx::connected() at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266WiFi\src\WiFiClientSecureBearSSL.cpp:264
0x4020acaa: HTTPClient::connected() at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266HTTPClient\src\ESP8266HTTPClient.cpp:245
0x4020550e: HTTPClient::handleHeaderResponse() at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266HTTPClient\src\ESP8266HTTPClient.cpp:896
0x40205cff: HTTPClient::sendRequest(char const*, unsigned char const*, unsigned int) at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\libraries\ESP8266HTTPClient\src\ESP8266HTTPClient.cpp:486
0x40206c69: String::copy(char const*, unsigned int) at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\WString.cpp:274
0x40206e14: String::operator=(char const*) at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\WString.cpp:319
0x40100944: free at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\umm_malloc\umm_malloc.cpp:688
0x40100944: free at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\umm_malloc\umm_malloc.cpp:667
0x402014c2: loop at C:\Users\aliz\Desktop\temp\temp\temp.ino:157
0x401005fc: umm_free_core at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\umm_malloc\umm_malloc.cpp:642
0x40100979: malloc at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\umm_malloc\umm_malloc.cpp:914
0x40207bd0: loop_wrapper at C:\Users\aliz\Documents\Arduino\hardware\esp8266com\esp8266\cores\esp8266\core_esp8266_main.cpp:263

MCVE Sketch

Here's a minimised sketch to repro. I don't know if anything specific in my apache setup is triggering this, let me know if you have trouble reproducing and I'll investigate.

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
#include <time.h>

const char *ssid = "...";
const char *pass = "...";

const char* server_cert = R"EOF(-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
)EOF";

const char* server_private_key = R"EOF(
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

)EOF";

const char* ca_cert = R"EOF(
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
)EOF";

// Note there are no client certificates required here in the server.
// That is because all clients will send a certificate that can be
// proven to be signed by the public CA certificate included at the
// head of the app.

WiFiClientSecure https;
HTTPClient http;

// Set time via NTP, as required for x.509 validation
void setClock() {
  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

  Serial.print("Waiting for NTP time sync: ");
  time_t now = time(nullptr);
  while (now < 8 * 3600 * 2) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));
}

void setup()
{
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  setClock();

  BearSSL::X509List *serverCertList = new BearSSL::X509List(server_cert);
  BearSSL::PrivateKey *serverPrivKey = new BearSSL::PrivateKey(server_private_key);
  https.setClientRSACert(serverCertList, serverPrivKey);

  BearSSL::X509List *serverTrustedCA = new BearSSL::X509List(ca_cert);
  https.setTrustAnchors(serverTrustedCA);
}

void loop()
{
  ESP.wdtDisable();
  *((volatile uint32_t*)0x60000900) &= ~(1); // Hardware WDT OFF

  if (!https.connect("dev.home.gamesfairy.co.uk", 443))
  {
    char* errMsg = (char*)malloc(101);
    memset(errMsg, 0, 100);
    int errCode = https.getLastSSLError(errMsg, 100);
    Serial.printf("Failed to set active scene, connecting to host failed: %d ('%s')\n", errCode, errMsg);
    free(errMsg);

    return;
  }

  http.addHeader("Content-Type", "application/json");
  http.begin(https, "dev.home.gamesfairy.co.uk", 443, "/", true);

  int respCode = http.POST((const uint8_t*)"foo",3);

  if (respCode < 0)
  {
    Serial.printf("Failed to set scene, error %d: %s\n", respCode, http.errorToString(respCode).c_str());

    char* errMsg = (char*)malloc(101);
    memset(errMsg, 0, 100);
    int errCode = https.getLastSSLError(errMsg, 100);
    Serial.printf("Failed to set active scene, connecting to host failed: %d ('%s')\n", errCode, errMsg);
    free(errMsg);
  }
  else
  {
    if (respCode != HTTP_CODE_OK)
    {
      Serial.printf("Failed to set scene, get HTTP status %d for URL %s;\n response body:\n%s\n", respCode, "/", http.getString().c_str());
    }
  }
  http.end();

  Serial.printf("All done.\n");
  delay(60 * 1000);
}

To summarise:

  • TLS mutual auth is failing when an esp8266 client attempts to connect to a server requesting a client cert, at least in my environment
  • This is because TLS renegotiation is disabled
  • Re-enabling renegotiation is a dirty hack to 'fix' the issue in esp8266 3.1.2, but when attempted in current git, BearSSL crashes.

I can see the benefit of disabling renegotiation, in terms of resource usage, for the majority of users. However, it seems it is required in some scenarios, such as mine. Would it be possible to enable re-negotiation, as an opt-in feature?

mcspr added a commit to mcspr/esp8266-Arduino that referenced this issue Jul 25, 2024
@mcspr
Copy link
Collaborator

mcspr commented Jul 25, 2024

TLS mutual auth is failing when an esp8266 client attempts to connect to a server requesting a client cert, at least in my environment
This is because TLS renegotiation is disabled

I would guess that would be adding something like 'WiFiClientSecure::setPreserveX509Context(bool)'. We do care only about client though, not server side when WiFiSecureServer is used?

Re-enabling renegotiation is a dirty hack to 'fix' the issue in esp8266 3.1.2, but when attempted in current git, BearSSL crashes.

Right, this is because of #9083. I'd say it is really justified, since bearssl funcs apparently try to yield while still using a separate stack. That stack is not within the original task struct, hence the overflow detection trigger.

master...mcspr:esp8266-Arduino:bssl/9170-thunk does another dirty hack to stop cont_suspend from crashing (referenced through esp_suspend_within_cont in the stack dump above). Instead of optimistic_yield(10000), there is a separate func to swap stack pointer before and after yield() is executed.

Maybe not the best solution, but idk what we can do here besides rewriting StackThunk through normal tasks instead of what it is doing right now.

mcspr added a commit to mcspr/bearssl-esp8266 that referenced this issue Aug 1, 2024
cont_suspend() wants stack pointer to be within cont.stack and panic()s otherwise
esp8266/Arduino#9170 (comment)

stack_thunk_yield() func then gets added from the Core side,
which should do 'SP store -> yield() -> SP restore' with known stack thunk values
esp8266/Arduino@master...mcspr:esp8266-Arduino:bssl/9170-thunk
mcspr added a commit to mcspr/esp8266-Arduino that referenced this issue Sep 2, 2024
only rememember a1, yield handles the rest of the registers
see esp8266#9170, should no longer crash when using client keys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants