diff --git a/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino b/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino index 8d9a176c2..975fe13ef 100644 --- a/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino +++ b/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino @@ -20,6 +20,10 @@ const char* password = "........"; const char* host = "api.github.com"; const int httpsPort = 443; +// Use web browser to view and copy +// SHA1 fingerprint of the certificate +const char* fingerprint = "CF 05 98 89 CA FF 8E D8 5E 5C E0 C2 E4 F7 E6 C3 C7 50 DD 5C"; + void setup() { Serial.begin(115200); Serial.println(); @@ -35,9 +39,7 @@ void setup() { Serial.println("IP address: "); Serial.println(WiFi.localIP()); - // Use WiFiClientSecure class to create TLS connection - WiFiClientSecure client; Serial.print("connecting to "); Serial.println(host); @@ -46,6 +48,12 @@ void setup() { return; } + if (client.verify(fingerprint, host)) { + Serial.println("certificate matches"); + } else { + Serial.println("certificate doesn't match"); + } + String url = "/repos/esp8266/Arduino/commits/esp8266/status"; Serial.print("requesting URL: "); Serial.println(url); diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp index 053bf27e4..d5dd9c638 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp @@ -242,6 +242,50 @@ void WiFiClientSecure::stop() { return WiFiClient::stop(); } +static bool parseHexNibble(char pb, uint8_t* res) { + if (pb >= '0' && pb <= '9') { + *res = (uint8_t) (pb - '0'); return true; + } + else if (pb >= 'a' && pb <= 'f') { + *res = (uint8_t) (pb - 'a' + 10); return true; + } + else if (pb >= 'A' && pb <= 'F') { + *res = (uint8_t) (pb - 'A' + 10); return true; + } + return false; +} + +bool WiFiClientSecure::verify(const char* fp, const char* url) { + uint8_t sha1[20]; + int len = strlen(fp); + int pos = 0; + for (int i = 0; i < sizeof(sha1); ++i) { + while (pos < len && fp[pos] == ' ') { + ++pos; + } + DEBUGV("pos:%d ", pos); + if (pos > len - 2) { + DEBUGV("fingerprint too short\r\n"); + return false; + } + uint8_t high, low; + if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos+1], &low)) { + DEBUGV("invalid hex sequence: %c%c\r\n", fp[pos], fp[pos+1]); + return false; + } + pos += 2; + sha1[i] = low | (high << 4); + } + if (ssl_match_fingerprint(*_ssl, sha1) != 0) { + DEBUGV("fingerprint doesn't match\r\n"); + return false; + } + + //TODO: check URL against certificate + + return true; +} + extern "C" int ax_port_read(int fd, uint8_t* buffer, size_t count) { ClientContext* _client = reinterpret_cast(fd); if (_client->state() != ESTABLISHED && !_client->getSize()) { diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecure.h b/libraries/ESP8266WiFi/src/WiFiClientSecure.h index 02fed84e6..3b3d2907c 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecure.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecure.h @@ -38,6 +38,8 @@ public: int connect(IPAddress ip, uint16_t port) override; int connect(const char* name, uint16_t port) override; + bool verify(const char* fingerprint, const char* url); + size_t write(const uint8_t *buf, size_t size) override; int read(uint8_t *buf, size_t size) override; int available() override; diff --git a/libraries/ESP8266WiFi/src/include/ssl.h b/libraries/ESP8266WiFi/src/include/ssl.h index ef93886df..60e4d7e62 100644 --- a/libraries/ESP8266WiFi/src/include/ssl.h +++ b/libraries/ESP8266WiFi/src/include/ssl.h @@ -375,6 +375,15 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code); */ EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl); +/** + * @brief Check if certificate fingerprint (SHA1) matches the one given. + * + * @param ssl [in] An SSL object reference. + * @param fp [in] SHA1 fingerprint to match against + * @return SSL_OK if the certificate is verified. + */ +EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp); + /** * @brief Retrieve an X.509 distinguished name component. * diff --git a/tools/sdk/lib/libaxtls.a b/tools/sdk/lib/libaxtls.a index 806bdbbf4..7da3c1c1c 100644 Binary files a/tools/sdk/lib/libaxtls.a and b/tools/sdk/lib/libaxtls.a differ