From 016ca89f9166d118fb489a9a9a3278b5495660f4 Mon Sep 17 00:00:00 2001
From: "Earle F. Philhower, III" <earlephilhower@yahoo.com>
Date: Wed, 3 Oct 2018 14:07:16 -0700
Subject: [PATCH 1/2] Add BearSSL::setFingerprint(char* fp)

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..faec01c020 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(_fingerprint)) {
+    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();

From 68ec6b961dc587eb9a67ab5fedecb56c8410fb5d Mon Sep 17 00:00:00 2001
From: "Earle F. Philhower, III" <earlephilhower@yahoo.com>
Date: Wed, 3 Oct 2018 18:55:48 -0700
Subject: [PATCH 2/2] Fix parsing checks

---
 libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp
index faec01c020..05f97d8cc6 100644
--- a/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp
+++ b/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp
@@ -567,7 +567,7 @@ bool WiFiClientSecure::setFingerprint(const char *fpStr) {
       fpStr++;
     }
   }
-  if ((idx != 20) || pgm_read_byte(_fingerprint)) {
+  if ((idx != 20) || pgm_read_byte(fpStr)) {
     return false; // Garbage at EOL or we didn't have enough hex digits
   }
   return setFingerprint(fp);