From 18612c97d88095eeca2eb55c8f1b450e295fa6eb Mon Sep 17 00:00:00 2001 From: "Earle F. Philhower, III" Date: Wed, 3 Oct 2018 19:32:47 -0700 Subject: [PATCH] Add BearSSL::setFingerprint(char* fp) (#5204) Add a method allowing a user to send in a character string for the fingerprint, like axTLS supported. Implements part of PR #4833 from @d-a-v with changes requested in discussion. --- .../BearSSL_Validation/BearSSL_Validation.ino | 2 +- .../src/WiFiClientSecureBearSSL.cpp | 36 +++++++++++++++++++ .../ESP8266WiFi/src/WiFiClientSecureBearSSL.h | 4 ++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino b/libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino index 6d016f702e..87de0ab791 100644 --- a/libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino +++ b/libraries/ESP8266WiFi/examples/BearSSL_Validation/BearSSL_Validation.ino @@ -102,7 +102,7 @@ instead of the while certificate. This is not nearly as secure as real X.509 validation, but is better than nothing. )EOF"); BearSSL::WiFiClientSecure client; - const uint8_t fp[20] = {0x5F, 0xF1, 0x60, 0x31, 0x09, 0x04, 0x3E, 0xF2, 0x90, 0xD2, 0xB0, 0x8A, 0x50, 0x38, 0x04, 0xE8, 0x37, 0x9F, 0xBC, 0x76}; + static const char fp[] PROGMEM = "5F:F1:60:31:09:04:3E:F2:90:D2:B0:8A:50:38:04:E8:37:9F:BC:76"; client.setFingerprint(fp); fetchURL(&client, host, port, path); } diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp index 3fc7ff0930..05f97d8cc6 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp @@ -536,6 +536,42 @@ bool WiFiClientSecure::_wait_for_handshake() { return _handshake_done; } +static uint8_t htoi (unsigned char c) +{ + if (c>='0' && c <='9') return c - '0'; + else if (c>='A' && c<='F') return 10 + c - 'A'; + else if (c>='a' && c<='f') return 10 + c - 'a'; + else return 255; +} + +// Set a fingerprint by parsing an ASCII string +bool WiFiClientSecure::setFingerprint(const char *fpStr) { + int idx = 0; + uint8_t c, d; + uint8_t fp[20]; + + while (idx < 20) { + c = pgm_read_byte(fpStr++); + if (!c) break; // String ended, done processing + d = pgm_read_byte(fpStr++); + if (!d) return false; // Only half of the last hex digit, error + c = htoi(c); + d = htoi(d); + if ((c>15) || (d>15)) { + return false; // Error in one of the hex characters + } + fp[idx++] = (c<<4)|d; + + // Skip 0 or more spaces or colons + while ( pgm_read_byte(fpStr) && (pgm_read_byte(fpStr)==' ' || pgm_read_byte(fpStr)==':') ) { + fpStr++; + } + } + if ((idx != 20) || pgm_read_byte(fpStr)) { + return false; // Garbage at EOL or we didn't have enough hex digits + } + return setFingerprint(fp); +} extern "C" { diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h index 143258276a..c5af2ebfa8 100644 --- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h +++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h @@ -73,11 +73,13 @@ class WiFiClientSecure : public WiFiClient { _knownkey_usages = usages; } // Only check SHA1 fingerprint of certificate - void setFingerprint(const uint8_t fingerprint[20]) { + bool setFingerprint(const uint8_t fingerprint[20]) { _clearAuthenticationSettings(); _use_fingerprint = true; memcpy_P(_fingerprint, fingerprint, 20); + return true; } + bool setFingerprint(const char *fpStr); // Accept any certificate that's self-signed void allowSelfSignedCerts() { _clearAuthenticationSettings();