diff --git a/libraries/ESP8266WiFi/keywords.txt b/libraries/ESP8266WiFi/keywords.txt index 83485d6ae..7e7819f11 100644 --- a/libraries/ESP8266WiFi/keywords.txt +++ b/libraries/ESP8266WiFi/keywords.txt @@ -130,9 +130,14 @@ verify KEYWORD2 verifyCertChain KEYWORD2 setCertificate KEYWORD2 setPrivateKey KEYWORD2 +setCACert KEYWORD2 +setCertificate_P KEYWORD2 +setPrivateKey_P KEYWORD2 +setCACert_P KEYWORD2 loadCertificate KEYWORD2 loadPrivateKey KEYWORD2 loadCACert KEYWORD2 +allowSelfSignedCerts KEYWORD2 #WiFiServer hasClient KEYWORD2 diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp index 2fbd1897b..e7bcb1a4e 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp @@ -110,6 +110,7 @@ public: uint8_t* data; int rc = ssl_read(_ssl, &data); if (rc < SSL_OK) { + ssl_display_error(rc); break; } } @@ -227,6 +228,25 @@ public: return true; } + bool verifyCert() + { + int rc = ssl_verify_cert(_ssl); + if (_allowSelfSignedCerts && rc == SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED)) { + DEBUGV("Allowing self-signed certificate\n"); + return true; + } else if (rc != SSL_OK) { + DEBUGV("ssl_verify_cert returned %d\n", rc); + ssl_display_error(rc); + return false; + } + return true; + } + + void allowSelfSignedCerts() + { + _allowSelfSignedCerts = true; + } + operator SSL*() { return _ssl; @@ -268,6 +288,7 @@ protected: int _refcnt = 0; const uint8_t* _read_ptr = nullptr; size_t _available = 0; + bool _allowSelfSignedCerts = false; static ClientContext* s_io_ctx; }; @@ -559,96 +580,80 @@ bool WiFiClientSecure::verifyCertChain(const char* domain_name) if (!_ssl) { return false; } - int rc = ssl_verify_cert(*_ssl); - if (rc != SSL_OK) { - DEBUGV("ssl_verify_cert returned %d\n", rc); + if (!_ssl->verifyCert()) { return false; } - return _verifyDN(domain_name); } -bool WiFiClientSecure::setCACert(const uint8_t* pk, size_t size) +void WiFiClientSecure::_initSSLContext() { if (!_ssl) { _ssl = new SSLContext; _ssl->ref(); } +} + +bool WiFiClientSecure::setCACert(const uint8_t* pk, size_t size) +{ + _initSSLContext(); return _ssl->loadObject(SSL_OBJ_X509_CACERT, pk, size); } bool WiFiClientSecure::setCertificate(const uint8_t* pk, size_t size) { - if (!_ssl) { - _ssl = new SSLContext; - _ssl->ref(); - } + _initSSLContext(); return _ssl->loadObject(SSL_OBJ_X509_CERT, pk, size); } bool WiFiClientSecure::setPrivateKey(const uint8_t* pk, size_t size) { - if (!_ssl) { - _ssl = new SSLContext; - _ssl->ref(); - } + _initSSLContext(); return _ssl->loadObject(SSL_OBJ_RSA_KEY, pk, size); } bool WiFiClientSecure::setCACert_P(PGM_VOID_P pk, size_t size) { - if (!_ssl) { - _ssl = new SSLContext; - _ssl->ref(); - } + _initSSLContext(); return _ssl->loadObject_P(SSL_OBJ_X509_CACERT, pk, size); } bool WiFiClientSecure::setCertificate_P(PGM_VOID_P pk, size_t size) { - if (!_ssl) { - _ssl = new SSLContext; - _ssl->ref(); - } + _initSSLContext(); return _ssl->loadObject_P(SSL_OBJ_X509_CERT, pk, size); } bool WiFiClientSecure::setPrivateKey_P(PGM_VOID_P pk, size_t size) { - if (!_ssl) { - _ssl = new SSLContext; - _ssl->ref(); - } + _initSSLContext(); return _ssl->loadObject_P(SSL_OBJ_RSA_KEY, pk, size); } bool WiFiClientSecure::loadCACert(Stream& stream, size_t size) { - if (!_ssl) { - _ssl = new SSLContext; - _ssl->ref(); - } + _initSSLContext(); return _ssl->loadObject(SSL_OBJ_X509_CACERT, stream, size); } bool WiFiClientSecure::loadCertificate(Stream& stream, size_t size) { - if (!_ssl) { - _ssl = new SSLContext; - _ssl->ref(); - } + _initSSLContext(); return _ssl->loadObject(SSL_OBJ_X509_CERT, stream, size); } bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size) { - if (!_ssl) { - _ssl = new SSLContext; - _ssl->ref(); - } + _initSSLContext(); return _ssl->loadObject(SSL_OBJ_RSA_KEY, stream, size); } +void WiFiClientSecure::allowSelfSignedCerts() +{ + _initSSLContext(); + _ssl->allowSelfSignedCerts(); +} + extern "C" int __ax_port_read(int fd, uint8_t* buffer, size_t count) { ClientContext* _client = SSLContext::getIOContext(fd); diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.h b/libraries/ESP8266WiFi/src/WiFiClientSecure.h index 8a7c60259..afffbdb4e 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.h @@ -62,6 +62,8 @@ public: bool loadCertificate(Stream& stream, size_t size); bool loadPrivateKey(Stream& stream, size_t size); + void allowSelfSignedCerts(); + template bool loadCertificate(TFile& file) { return loadCertificate(file, file.size()); @@ -79,6 +81,7 @@ public: protected: + void _initSSLContext(); int _connectSSL(const char* hostName); bool _verifyDN(const char* name); diff --git a/libraries/ESP8266WiFi/src/include/ssl.h b/libraries/ESP8266WiFi/src/include/ssl.h index a10e9dfb7..8879e4cb9 100644 --- a/libraries/ESP8266WiFi/src/include/ssl.h +++ b/libraries/ESP8266WiFi/src/include/ssl.h @@ -113,6 +113,19 @@ typedef struct SSL_EXTENSIONS_ SSL_EXTENSIONS; #define SSL_X509_OFFSET -512 #define SSL_X509_ERROR(A) (SSL_X509_OFFSET+A) +#define X509_OK 0 +#define X509_NOT_OK -1 +#define X509_VFY_ERROR_NO_TRUSTED_CERT -2 +#define X509_VFY_ERROR_BAD_SIGNATURE -3 +#define X509_VFY_ERROR_NOT_YET_VALID -4 +#define X509_VFY_ERROR_EXPIRED -5 +#define X509_VFY_ERROR_SELF_SIGNED -6 +#define X509_VFY_ERROR_INVALID_CHAIN -7 +#define X509_VFY_ERROR_UNSUPPORTED_DIGEST -8 +#define X509_INVALID_PRIV_KEY -9 +#define X509_MAX_CERTS -10 +#define X509_VFY_ERROR_BASIC_CONSTRAINT -11 + /* alert types that are recognized */ #define SSL_ALERT_TYPE_WARNING 1 #define SLL_ALERT_TYPE_FATAL 2