diff --git a/libraries/ESP8266HTTPClient/examples/SSLCertificateVerification/SSLCertificateVerification.ino b/libraries/ESP8266HTTPClient/examples/SSLCertificateVerification/SSLCertificateVerification.ino new file mode 100644 index 0000000000..3f92736ad5 --- /dev/null +++ b/libraries/ESP8266HTTPClient/examples/SSLCertificateVerification/SSLCertificateVerification.ino @@ -0,0 +1,155 @@ + /** + * SSLCertificateVerification.ino + * + * Created on: 04.28.2017 + * + */ + +#include +#include +#include + +//WiFi +const char wifissid[] = "WiFi"; +const char wifipsk[] = "Password"; + +// This is a binary dump of the root CA. +// You can also choose to load the cert via a file stream. +// Here are steps one can use to dump the CA: +// 1) openssl s_client -connect google.com:443 +// The output has a "Certificate chain" section. Your root CA is the bottom line. +// In the case of google.com, this line is +// "i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority" +// This means we need to validate with the Equifax Secure CA +// 2) Open Keychain Access. In the Search bar type "Equifax" and press Enter. +// 3) Right-click the cert and click Export and save it as a .cer. +// 4) In the terminal, type xxd -i +unsigned char Equifax_cer[] = { + 0x30, 0x82, 0x03, 0x20, 0x30, 0x82, 0x02, 0x89, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x04, 0x35, 0xde, 0xf4, 0xcf, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x4e, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, + 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x31, 0x2d, 0x30, 0x2b, 0x06, + 0x03, 0x55, 0x04, 0x0b, 0x13, 0x24, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, + 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x38, + 0x30, 0x38, 0x32, 0x32, 0x31, 0x36, 0x34, 0x31, 0x35, 0x31, 0x5a, 0x17, + 0x0d, 0x31, 0x38, 0x30, 0x38, 0x32, 0x32, 0x31, 0x36, 0x34, 0x31, 0x35, + 0x31, 0x5a, 0x30, 0x4e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x0a, 0x13, 0x07, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x31, + 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x24, 0x45, 0x71, + 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x81, + 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, + 0x81, 0x81, 0x00, 0xc1, 0x5d, 0xb1, 0x58, 0x67, 0x08, 0x62, 0xee, 0xa0, + 0x9a, 0x2d, 0x1f, 0x08, 0x6d, 0x91, 0x14, 0x68, 0x98, 0x0a, 0x1e, 0xfe, + 0xda, 0x04, 0x6f, 0x13, 0x84, 0x62, 0x21, 0xc3, 0xd1, 0x7c, 0xce, 0x9f, + 0x05, 0xe0, 0xb8, 0x01, 0xf0, 0x4e, 0x34, 0xec, 0xe2, 0x8a, 0x95, 0x04, + 0x64, 0xac, 0xf1, 0x6b, 0x53, 0x5f, 0x05, 0xb3, 0xcb, 0x67, 0x80, 0xbf, + 0x42, 0x02, 0x8e, 0xfe, 0xdd, 0x01, 0x09, 0xec, 0xe1, 0x00, 0x14, 0x4f, + 0xfc, 0xfb, 0xf0, 0x0c, 0xdd, 0x43, 0xba, 0x5b, 0x2b, 0xe1, 0x1f, 0x80, + 0x70, 0x99, 0x15, 0x57, 0x93, 0x16, 0xf1, 0x0f, 0x97, 0x6a, 0xb7, 0xc2, + 0x68, 0x23, 0x1c, 0xcc, 0x4d, 0x59, 0x30, 0xac, 0x51, 0x1e, 0x3b, 0xaf, + 0x2b, 0xd6, 0xee, 0x63, 0x45, 0x7b, 0xc5, 0xd9, 0x5f, 0x50, 0xd2, 0xe3, + 0x50, 0x0f, 0x3a, 0x88, 0xe7, 0xbf, 0x14, 0xfd, 0xe0, 0xc7, 0xb9, 0x02, + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x09, 0x30, 0x82, 0x01, 0x05, + 0x30, 0x70, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x69, 0x30, 0x67, 0x30, + 0x65, 0xa0, 0x63, 0xa0, 0x61, 0xa4, 0x5f, 0x30, 0x5d, 0x31, 0x0b, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x07, 0x45, 0x71, 0x75, + 0x69, 0x66, 0x61, 0x78, 0x31, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x04, + 0x0b, 0x13, 0x24, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x13, 0x04, 0x43, 0x52, 0x4c, 0x31, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x1d, + 0x10, 0x04, 0x13, 0x30, 0x11, 0x81, 0x0f, 0x32, 0x30, 0x31, 0x38, 0x30, + 0x38, 0x32, 0x32, 0x31, 0x36, 0x34, 0x31, 0x35, 0x31, 0x5a, 0x30, 0x0b, + 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x48, 0xe6, 0x68, 0xf9, 0x2b, 0xd2, 0xb2, 0x95, 0xd7, 0x47, 0xd8, 0x23, + 0x20, 0x10, 0x4f, 0x33, 0x98, 0x90, 0x9f, 0xd4, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x48, 0xe6, 0x68, 0xf9, 0x2b, + 0xd2, 0xb2, 0x95, 0xd7, 0x47, 0xd8, 0x23, 0x20, 0x10, 0x4f, 0x33, 0x98, + 0x90, 0x9f, 0xd4, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf6, 0x7d, 0x07, 0x41, 0x00, 0x04, 0x0d, 0x30, 0x0b, 0x1b, 0x05, + 0x56, 0x33, 0x2e, 0x30, 0x63, 0x03, 0x02, 0x06, 0xc0, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, + 0x03, 0x81, 0x81, 0x00, 0x58, 0xce, 0x29, 0xea, 0xfc, 0xf7, 0xde, 0xb5, + 0xce, 0x02, 0xb9, 0x17, 0xb5, 0x85, 0xd1, 0xb9, 0xe3, 0xe0, 0x95, 0xcc, + 0x25, 0x31, 0x0d, 0x00, 0xa6, 0x92, 0x6e, 0x7f, 0xb6, 0x92, 0x63, 0x9e, + 0x50, 0x95, 0xd1, 0x9a, 0x6f, 0xe4, 0x11, 0xde, 0x63, 0x85, 0x6e, 0x98, + 0xee, 0xa8, 0xff, 0x5a, 0xc8, 0xd3, 0x55, 0xb2, 0x66, 0x71, 0x57, 0xde, + 0xc0, 0x21, 0xeb, 0x3d, 0x2a, 0xa7, 0x23, 0x49, 0x01, 0x04, 0x86, 0x42, + 0x7b, 0xfc, 0xee, 0x7f, 0xa2, 0x16, 0x52, 0xb5, 0x67, 0x67, 0xd3, 0x40, + 0xdb, 0x3b, 0x26, 0x58, 0xb2, 0x28, 0x77, 0x3d, 0xae, 0x14, 0x77, 0x61, + 0xd6, 0xfa, 0x2a, 0x66, 0x27, 0xa0, 0x0d, 0xfa, 0xa7, 0x73, 0x5c, 0xea, + 0x70, 0xf1, 0x94, 0x21, 0x65, 0x44, 0x5f, 0xfa, 0xfc, 0xef, 0x29, 0x68, + 0xa9, 0xa2, 0x87, 0x79, 0xef, 0x79, 0xef, 0x4f, 0xac, 0x07, 0x77, 0x38 +}; +unsigned int Equifax_cer_len = 804; + +void intializeClock() { + configTime(0, 0, "pool.ntp.org", "time.nist.gov"); + Serial.println("\nWaiting for time"); + while (!time(nullptr)) { + Serial.print("."); + delay(1000); + } + Serial.println(""); + + time_t now = time(nullptr); + Serial.print("Clock initialized to (UTC): "); + Serial.println(ctime(&now)); +} + +void runTest() { + intializeClock(); // We must initialize sntp in order to verify certs + + HTTPClient http; + http.begin("https://www.google.com", 443); + http.setRootCA(Equifax_cer, Equifax_cer_len); + int result = http.GET(); + if (result < 0) { + Serial.printf("Failed to connect. Error code %d\n", result); + } + else { + http.writeToStream(&Serial); + } + http.end(); + Serial.println(); +} + +void connectWiFi() { + Serial.println("Connecting to: " + String(wifissid)); + WiFi.mode(WIFI_STA); + + WiFi.begin(wifissid,wifipsk); + + while (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.println("Connection Failed! Rebooting..."); + delay(5000); + ESP.restart(); + } + Serial.println("WiFi Connected"); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); +} + +void setup() { + // put your setup code here, to run once: + Serial.begin(115200); + Serial.println("Booting"); + connectWiFi(); + runTest(); + Serial.println("Complete"); +} + +void loop() { +} diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index ef4c551573..043a6ffd85 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -51,6 +51,11 @@ class TransportTraits class TLSTraits : public TransportTraits { public: + TLSTraits() : + _fingerprint("") + { + } + TLSTraits(const String& fingerprint) : _fingerprint(fingerprint) { @@ -64,7 +69,16 @@ class TLSTraits : public TransportTraits bool verify(WiFiClient& client, const char* host) override { auto wcs = static_cast(client); - return wcs.verify(_fingerprint.c_str(), host); + if (_fingerprint == "") + { + DEBUG_HTTPCLIENT("[HTTP-Client] Performing verify with Certificate Authority\n"); + return wcs.verifyCertChain(host); + } + else + { + DEBUG_HTTPCLIENT("[HTTP-Client] Performing verify with fingerprint\n"); + return wcs.verify(_fingerprint.c_str(), host); + } } protected: @@ -110,7 +124,13 @@ bool HTTPClient::begin(String url, String httpsFingerprint) return false; } _transportTraits = TransportTraitsPtr(new TLSTraits(httpsFingerprint)); - DEBUG_HTTPCLIENT("[HTTP-Client][begin] httpsFingerprint: %s\n", httpsFingerprint.c_str()); + _tcp = _transportTraits->create(); + + if(!_tcp->connect(_host.c_str(), _port)) { + DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u\n", _host.c_str(), _port); + return false; + } + DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u\n", _host.c_str(), _port); return true; } @@ -121,11 +141,25 @@ bool HTTPClient::begin(String url, String httpsFingerprint) bool HTTPClient::begin(String url) { _transportTraits.reset(nullptr); - _port = 80; - if (!beginInternal(url, "http")) { + if (!beginInternal(url, nullptr)) { return false; } - _transportTraits = TransportTraitsPtr(new TransportTraits()); + if (_protocol == "https" || _port == 443) { + _port = 443; + _transportTraits = TransportTraitsPtr(new TLSTraits()); + } + else { + _port = 80; + _transportTraits = TransportTraitsPtr(new TransportTraits()); + } + _tcp = _transportTraits->create(); + + if(!_tcp->connect(_host.c_str(), _port)) { + DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u\n", _host.c_str(), _port); + return false; + } + DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u\n", _host.c_str(), _port); + return true; } @@ -167,7 +201,7 @@ bool HTTPClient::beginInternal(String url, const char* expectedProtocol) _host = host; } _uri = url; - if (_protocol != expectedProtocol) { + if (expectedProtocol != nullptr && _protocol != expectedProtocol) { DEBUG_HTTPCLIENT("[HTTP-Client][begin] unexpected protocol: %s, expected %s\n", _protocol.c_str(), expectedProtocol); return false; } @@ -177,12 +211,31 @@ bool HTTPClient::beginInternal(String url, const char* expectedProtocol) bool HTTPClient::begin(String host, uint16_t port, String uri) { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d uri: %s\n", host.c_str(), port, uri.c_str()); clear(); + + // Remove protocol if any + int index = host.indexOf(':'); + if(index >= 0) { + _protocol = host.substring(0, index); + host.remove(0, (index + 3)); // remove http:// or https:// + } + _host = host; _port = port; _uri = uri; - _transportTraits = TransportTraitsPtr(new TransportTraits()); - DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d uri: %s\n", host.c_str(), port, uri.c_str()); + if (_protocol == "https" || _port == 443) { + _transportTraits = TransportTraitsPtr(new TLSTraits()); + } + else { + _transportTraits = TransportTraitsPtr(new TransportTraits()); + } + _tcp = _transportTraits->create(); + if(!_tcp->connect(_host.c_str(), _port)) { + DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u\n", _host.c_str(), _port); + return false; + } + DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u\n", _host.c_str(), _port); return true; } @@ -197,6 +250,7 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, bool https, Strin bool HTTPClient::begin(String host, uint16_t port, String uri, String httpsFingerprint) { + DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d url: %s httpsFingerprint: %s\n", host.c_str(), port, uri.c_str(), httpsFingerprint.c_str()); clear(); _host = host; _port = port; @@ -206,7 +260,13 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, String httpsFinge return false; } _transportTraits = TransportTraitsPtr(new TLSTraits(httpsFingerprint)); - DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d url: %s httpsFingerprint: %s\n", host.c_str(), port, uri.c_str(), httpsFingerprint.c_str()); + _tcp = _transportTraits->create(); + + if(!_tcp->connect(_host.c_str(), _port)) { + DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u\n", _host.c_str(), _port); + return false; + } + DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u\n", _host.c_str(), _port); return true; } @@ -303,6 +363,48 @@ void HTTPClient::setTimeout(uint16_t timeout) } } +bool HTTPClient::setRootCA(const uint8_t * cert, size_t size) +{ + bool result = false; + if(_tcp && (_protocol == "https" || _port == 443)) { + auto client = static_cast(_tcp.get()); + if(client) { + result = client->setCACert(cert, size); + } + } + DEBUG_HTTPCLIENT("[HTTP-Client][setRootCA] Result: %d\n", (int) result); + return result; +} + +bool HTTPClient::setRootCA_P(PGM_VOID_P * cert, size_t size) +{ + bool result = false; + if(_tcp && (_protocol == "https" || _port == 443)) { + auto client = static_cast(_tcp.get()); + if(client) { + uint8_t* buf = new uint8_t[size]; + memcpy_P(buf, cert, size); + result = client->setCACert(buf, size); + delete[] buf; + } + } + DEBUG_HTTPCLIENT("[HTTP-Client][setRootCA_P] Result: %d\n", (int) result); + return result; +} + +bool HTTPClient::setRootCA(Stream& cert, size_t size) +{ + bool result = false; + if(_tcp && (_protocol == "https" || _port == 443)) { + auto client = static_cast(_tcp.get()); + if(client) { + result = client->loadCACert(cert, size); + } + } + DEBUG_HTTPCLIENT("[HTTP-Client][setRootCA] Result: %d\n", (int) result); + return result; +} + /** * use HTTP1.0 * @param timeout @@ -385,6 +487,7 @@ int HTTPClient::sendRequest(const char * type, String payload) */ int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest][%s] with payload size %d\n", type, size); // connect to server if(!connect()) { return returnError(HTTPC_ERROR_CONNECTION_REFUSED); @@ -419,7 +522,7 @@ int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) */ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { - + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest][%s] with streaming with size %d\n", type, size); if(!stream) { return returnError(HTTPC_ERROR_NO_STREAM); } @@ -623,6 +726,7 @@ int HTTPClient::writeToStream(Stream * stream) String chunkHeader = _tcp->readStringUntil('\n'); if(chunkHeader.length() <= 0) { + DEBUG_HTTPCLIENT("[HTTP-Client] chunkHeader length invalid\n"); return returnError(HTTPC_ERROR_READ_TIMEOUT); } @@ -659,6 +763,7 @@ int HTTPClient::writeToStream(Stream * stream) char buf[2]; auto trailing_seq_len = _tcp->readBytes((uint8_t*)buf, 2); if (trailing_seq_len != 2 || buf[0] != '\r' || buf[1] != '\n') { + DEBUG_HTTPCLIENT("[HTTP-Client] Didn't trail as expected\n"); return returnError(HTTPC_ERROR_READ_TIMEOUT); } @@ -822,33 +927,24 @@ bool HTTPClient::hasHeader(const char* name) */ bool HTTPClient::connect(void) { - - if(connected()) { - DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, try reuse!\n"); - while(_tcp->available() > 0) { - _tcp->read(); - } - return true; - } - if (!_transportTraits) { DEBUG_HTTPCLIENT("[HTTP-Client] connect: HTTPClient::begin was not called or returned error\n"); return false; } - _tcp = _transportTraits->create(); - - if(!_tcp->connect(_host.c_str(), _port)) { - DEBUG_HTTPCLIENT("[HTTP-Client] failed connect to %s:%u\n", _host.c_str(), _port); + if (!_verified && !_transportTraits->verify(*_tcp, _host.c_str())) { + DEBUG_HTTPCLIENT("[HTTP-Client] transport level verify failed for host %s\n", _host.c_str()); + _tcp->stop(); return false; } + _verified = true; - DEBUG_HTTPCLIENT("[HTTP-Client] connected to %s:%u\n", _host.c_str(), _port); - - if (!_transportTraits->verify(*_tcp, _host.c_str())) { - DEBUG_HTTPCLIENT("[HTTP-Client] transport level verify failed\n"); - _tcp->stop(); - return false; + if(connected()) { + DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, try reuse!\n"); + while(_tcp->available() > 0) { + _tcp->read(); + } + return true; } // set Timeout for readBytesUntil and readStringUntil @@ -986,13 +1082,14 @@ int HTTPClient::handleHeaderResponse() if(_returnCode) { return _returnCode; } else { - DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] Remote host is not an HTTP Server!"); + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] Remote host is not an HTTP Server!\n"); return HTTPC_ERROR_NO_HTTP_SERVER; } } } else { if((millis() - lastDataTime) > _tcpTimeout) { + DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] Tcp timeout %d\n", (millis() - lastDataTime)); return HTTPC_ERROR_READ_TIMEOUT; } delay(0); diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 02e4ca5cc5..3b56f6018c 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -150,6 +150,13 @@ class HTTPClient void setAuthorization(const char * auth); void setTimeout(uint16_t timeout); + // Set the root certificate authority to authorize SSL connections with. Must initialize SNTP first. + bool setRootCA(const uint8_t * cert, size_t size); + // Set the root certificate authority to authorize SSL connections with. Must initialize SNTP first. + bool setRootCA_P(PGM_VOID_P * cert, size_t size); + // Set the root certificate authority to authorize SSL connections with. Must initialize SNTP first. + bool setRootCA(Stream& cert, size_t size); + void useHTTP10(bool usehttp10 = true); /// request handling @@ -222,6 +229,7 @@ class HTTPClient int _returnCode = 0; int _size = -1; bool _canReuse = false; + bool _verified = false; transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY; }; diff --git a/tools/sdk/lib/libaxtls.a b/tools/sdk/lib/libaxtls.a index 0d3a3f67af..0eb8c33100 100644 Binary files a/tools/sdk/lib/libaxtls.a and b/tools/sdk/lib/libaxtls.a differ