Client certs removed from connection when setInsecure
called, causing SSL connect failure. · Issue #7455 · esp8266/Arduino (original) (raw)
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.
- [NA] If there is a stack dump, I have decoded it.
- I have filled out all fields below.
Platform
- Hardware: ESP8266 device
- Core Version: 2.7.2, 39c79d9
- Development Env: Arduino IDE via VSCode + Visual Studio Code extension for Arduino
- Operating System: Ubuntu 18.04
Settings in IDE
- Module: NodeMCU v1.0 (ESP-12E Module)
- Flash Mode: unknown
- Flash Size: 4MB
- lwip Variant: v2 Higher Bandwidth, also tried v1.4 Higher Bandwidth
- Reset Method: unknown
- Flash Frequency: unknown
- CPU Frequency: tried both 80Mhz and 160MHz
- Upload Using: SERIAL
- Upload Speed: 115200
Problem Description
I am attempting to publish a "hello world" MQTT message over WiFi to an Amazon Web Services (AWS) IoT endpoint, which requires SSL encryption. I have been issued a CA cert, device cert and device public & private keys, plus my account-specific AWS endpoint to publish against.
I have configured my sketch to use these credentials (but not currently using PROGMEM to store them), and I populate the WifiClientSecure
with my device certificate and private key. For now I am ignoring server certificate verification using WifiClientSecure::setInsecure
.
my troubleshooting has included:
- verified I am able to use a non-SSL
WifiClient
and successfully publish "hello worlds" to an unencrypted public MQTT broker. - reviewed the SSL client docs and example sketches
- based on googling the error, I've variously tried the CPU at 80 Mhz and 160 MHz, SSL support at "All SSL ciphers" and "Basic SSL ciphers", lwIP variant v2 (Higher Bandwidth) and v1.4 (Higher Bandwidth) to no avail.
- I am able to successfully authenticate from a computer on the same WiFi network for the same endpoint using the same certs using
openssl s_client
CLI helper (output provided in debug section)
The TLS handshake fails around BSSL:_wait_for_handshake: failed
; please see debug output.
Further troubleshooting advice greatly appreciated.
MCVE Sketch
#include <Arduino.h> #include <ESP8266WiFi.h> #include <PubSubClient.h>
namespace Secrets { const char wifiSsid[] = "myssid"; const char wifiPassword[] = "mypass"; const char awsIotEndpoint[] = "redacted.iot.eu-west-1.amazonaws.com";
const char awsCentralAuthorityCertificate[] = R"EOF( -----BEGIN CERTIFICATE----- redacted -----END CERTIFICATE----- )EOF"; const char awsDeviceCertificate[] = R"EOF( -----BEGIN CERTIFICATE----- redacted -----END CERTIFICATE----- )EOF"; const char awsDevicePrivateKey[] = R"EOF( -----BEGIN RSA PRIVATE KEY----- redacted -----END RSA PRIVATE KEY----- )EOF"; } // namespace Secrets
void wifiConnect() { WiFi.mode(WIFI_STA);
WiFi.begin(Secrets::wifiSsid, Secrets::wifiPassword);
if (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.printf("WiFi connection failed (status=[%s])"); } else { Serial.println("WiFi connected. IP address: "); Serial.println(WiFi.localIP()); } }
PubSubClient mqttClient; WiFiClientSecure wifiClient;
void mqttSetup() { wifiClient.setClientRSACert(new X509List(Secrets::awsDeviceCertificate), new PrivateKey(Secrets::awsDevicePrivateKey)); wifiClient.setInsecure(); // TODO: verify server identity using CA cert
mqttClient.setServer(Secrets::awsIotEndpoint, 8883); mqttClient.setClient(wifiClient); }
void mqttReconnect() { while (!mqttClient.connected()) { Serial.printf("Connecting to MQTT broker... (MQTT client state: %d)\n", mqttClient.state()); if (!mqttClient.connect("test-client-id")) { char errorMessage[128]; wifiClient.getLastSSLError(errorMessage, 128); Serial.printf( "Connecting to MQTT broker failed. (MQTT client state: %d, SSL " "error: %s)\n", mqttClient.state(), errorMessage); }; delay(2500); } Serial.println("MQTT client connected to broker."); }
void setup() { Serial.begin(115200); Serial.println("Booting");
wifiConnect(); mqttSetup(); }
void loop() { delay(5000); mqttReconnect();
if (mqttClient.publish("testTopic", "hello world")) { Serial.println("MQTT message published successfully!"); } else { Serial.println("MQTT message publish failed."); }
Serial.println("Finished loop"); }
Debug Messages
[Info] Opened the serial port - /dev/ttyUSB0
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 2
cnt
connected with MyWifiSSID, channel 11
dhcp client start...
wifi evt: 0
ip:192.168.86.249,mask:255.255.255.0,gw:192.168.86.1
wifi evt: 3
WiFi connected. IP address:
192.168.86.249
Connecting to MQTT broker... (MQTT client state: -1)
[hostByName] request IP for: redacted.iot.eu-west-1.amazonaws.com
[hostByName] Host: redacted.iot.eu-west-1.amazonaws.com IP: 52.31.xxx.xx
:ref 1
BSSL:_connectSSL: start connection
:wr 251 0
:wrc 251 251 0
:ack 251
:rn 1414
:rd 5, 1414, 0
:rdi 1414, 5
:rd 1409, 1414, 5
:rdi 1409, 1409
:c0 1409, 1414
BSSL:CERT: aa bb cc etc. REDACTED
BSSL:CERT: aa bb cc etc. REDACTED
BSSL:CERT: aa bb cc etc. REDACTED
BSSL:CERT: aa bb cc etc. REDACTED
BSSL:CERT: aa bb cc etc. REDACTED
:rn 1414
:rch 1414, 1414
:rch 2828, 1108
:rd 3936, 3936, 0
:rdi 1414, 1414
:c 1414, 1414, 3936
:rdi 1414, 1414
:c 1414, 1414, 2522
:rdi 1108, 1108
:c0 1108, 1108
BSSL:CERT: aa bb cc etc. REDACTED
:wr 82 0
:wrc 82 82 0
:wr 6 0
:wrc 6 6 0
:wr 45 0
:wrc 45 45 0
:ack 82
:rn 7
:rcl pb=0x3fff88cc sz=7
:rd 5, 7, 0
:rdi 7, 5
:rd 2, 7, 5
:rdi 2, 2
:c0 2, 7
BSSL:_wait_for_handshake: failed
BSSL:Couldn't connect. Error = 'Unknown error code.'
Connecting to MQTT broker failed. (MQTT client state: -2, SSL error: Unknown error code.)
:ack 51
Connecting to MQTT broker... (MQTT client state: -2)
<repeats>
From a terminal, I can connect successfully using the same certificates:
(the certificates redacted in the sketch above are a copy-paste of the files referenced below)
openssl s_client -connect redacted.iot.eu-west-1.amazonaws.com:8443 -CAfile AmazonRootCA1.pem -cert redacted-certificate.pem.crt -key redacted-private.pem.key
And receive successful output:
CONNECTED(00000005)
depth=2 C = US, O = Amazon, CN = Amazon Root CA 1
verify return:1
depth=1 C = US, O = Amazon, OU = Server CA 1B, CN = Amazon
verify return:1
depth=0 CN = *.iot.eu-west-1.amazonaws.com
verify return:1
---
Certificate chain
0 s:CN = *.iot.eu-west-1.amazonaws.com
i:C = US, O = Amazon, OU = Server CA 1B, CN = Amazon
1 s:C = US, O = Amazon, OU = Server CA 1B, CN = Amazon
i:C = US, O = Amazon, CN = Amazon Root CA 1
2 s:C = US, O = Amazon, CN = Amazon Root CA 1
i:C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
3 s:C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
i:C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
redacted
-----END CERTIFICATE-----
subject=CN = *.iot.eu-west-1.amazonaws.com
issuer=C = US, O = Amazon, OU = Server CA 1B, CN = Amazon
---
No client certificate CA names sent
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: ECDSA+SHA512:RSA+SHA512:ECDSA+SHA384:RSA+SHA384:ECDSA+SHA256:RSA+SHA256:DSA+SHA256:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:ECDSA+SHA1:RSA+SHA1:DSA+SHA1
Shared Requested Signature Algorithms: ECDSA+SHA512:RSA+SHA512:ECDSA+SHA384:RSA+SHA384:ECDSA+SHA256:RSA+SHA256:DSA+SHA256:ECDSA+SHA224:RSA+SHA224:DSA+SHA224:ECDSA+SHA1:RSA+SHA1:DSA+SHA1
Peer signing digest: SHA256
Peer signature type: RSA
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5400 bytes and written 1620 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: redacted
Session-ID-ctx:
Master-Key: redacted
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1594729814
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: yes
---