Преглед изворни кода

added GxEPD2_WiFi_CertStore_Loader

initial version of GxEPD2_WiFi_CertStore_Loader
ZinggJM пре 4 година
родитељ
комит
3bfa0f30d6

+ 377 - 0
examples/GxEPD2_WiFi_CertStore_Loader/GxEPD2_WiFi_CertStore_Loader.ino

@@ -0,0 +1,377 @@
+// GxEPD2_WiFi_CertStore_Loader : Display Library example for SPI e-paper panels from Dalian Good Display and boards from Waveshare.
+// Requires HW SPI and Adafruit_GFX. Caution: the e-paper panels require 3.3V supply AND data lines!
+//
+// Display Library based on Demo Example from Good Display: http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
+//
+// Author: Jean-Marc Zingg
+//
+// Version: see library.properties
+//
+// Library: https://github.com/ZinggJM/GxEPD2
+
+// Supporting Arduino Forum Topics:
+// Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0
+// Good Display ePaper for Arduino : https://forum.arduino.cc/index.php?topic=436411.0
+//
+// This example is used to download the https certificate archive to LittleFS for ESP8266 WiFiClientSecure cert store
+//
+// See also https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi/examples/BearSSL_CertStore
+//
+// If you need an updated certs.ar, take a look at subdirectory update_certs
+// update_certs needs an openssl commandline tool. I downloaded it from https://kb.firedaemon.com/support/solutions/articles/4000121705
+//
+// NOTE: this utility example is only useful for ESP8266
+
+#if defined(ESP32)
+#include "SPIFFS.h"
+// set formatOnFail = true for initial format of ESP32 SPIFFS (e.g. if error occured)
+const bool formatOnFail = false;
+#endif
+
+#include <FS.h>
+
+#if defined (ESP8266)
+#include <LittleFS.h>
+#include <ESP8266WiFi.h>
+#endif
+
+#include <WiFiClient.h>
+#include <WiFiClientSecure.h>
+
+const char* ssid     = "........";
+const char* password = "........";
+const int httpPort  = 80;
+const int httpsPort = 443;
+
+// http://cacerts.digicert.com/DigiCertTLSRSASHA2562020CA1-1.crt
+// CN: DigiCert TLS RSA SHA256 2020 CA1 => name: DigiCert_TLS_RSA_SHA256_2020_CA1
+// not valid before: 2021-04-14 00:00:00
+// not valid after:  2031-04-13 23:59:59
+const char cert_DigiCert_TLS_RSA_SHA256_2020_CA1 [] PROGMEM = R"CERT(
+-----BEGIN CERTIFICATE-----
+MIIEvjCCA6agAwIBAgIQBtjZBNVYQ0b2ii+nVCJ+xDANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaME8xCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBS
+U0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6a
+qXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddn
+g9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuW
+raKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGB
+Afr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21r
+eacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBgjCCAX4wEgYDVR0TAQH/BAgwBgEB
+/wIBADAdBgNVHQ4EFgQUt2ui6qiqhIx56rTaD5iyxZV2ufQwHwYDVR0jBBgwFoAU
+A95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
+CCsGAQUFBwMBBggrBgEFBQcDAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGG
+GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2Nh
+Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDBCBgNV
+HR8EOzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRH
+bG9iYWxSb290Q0EuY3JsMD0GA1UdIAQ2MDQwCwYJYIZIAYb9bAIBMAcGBWeBDAEB
+MAgGBmeBDAECATAIBgZngQwBAgIwCAYGZ4EMAQIDMA0GCSqGSIb3DQEBCwUAA4IB
+AQCAMs5eC91uWg0Kr+HWhMvAjvqFcO3aXbMM9yt1QP6FCvrzMXi3cEsaiVi6gL3z
+ax3pfs8LulicWdSQ0/1s/dCYbbdxglvPbQtaCdB73sRD2Cqk3p5BJl+7j5nL3a7h
+qG+fh/50tx8bIKuxT8b1Z11dmzzp/2n3YWzW2fP9NsarA4h20ksudYbj/NhVfSbC
+EXffPgK2fPOre3qGNm+499iTcc+G33Mw+nur7SpZyEKEOxEXGlLzyQ4UfaJbcme6
+ce1XR2bFuAJKZTRei9AqPCCcUZlM51Ke92sRKw2Sfh3oius2FkOH6ipjv3U/697E
+A7sKPPcw7+uvTPyLNhBzPvOk
+-----END CERTIFICATE-----
+)CERT";
+
+// https://raw.githubusercontent.com
+// issued by DigiCert Inc : DigiCert TLS RSA SHA256 2020 CA1
+// not valid before: Fri, 18 Mar 2022 00:00:00 GMT
+// not valid after:  Tue, 21 Mar 2023 23:59:59 GMT
+const char github_io_chain_pem_first [] PROGMEM = R"CERT(
+-----BEGIN CERTIFICATE-----
+MIIHEzCCBfugAwIBAgIQC44ztdGGen6l0VAu1+MWiTANBgkqhkiG9w0BAQsFADBP
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSkwJwYDVQQDEyBE
+aWdpQ2VydCBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTAeFw0yMjAzMTgwMDAwMDBa
+Fw0yMzAzMjEyMzU5NTlaMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9y
+bmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxHaXRIdWIsIElu
+Yy4xFDASBgNVBAMMCyouZ2l0aHViLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxgDppBtMFl4zNvBbWAdr21IwcskxdMU/SkxYK/ZAXFrRIPcoZR15
+5DCrzTevHMUNLhCJqL8mMFidKOz4cZjhPn5sxjUCe/sPNvaiXm8cGUwzFlAYK1MY
+dM+wepJKcT/qK8RegSIEbk/6qU5Bmh558RSCGuIJj3E85C0fRVdA+zXHP5GkuuB4
+VEXYzM2oz5KmgXIdBYFydjyK9LNO5nc/Z2Bc7JppCripRHfht3OR1Bf4JFYBuEJE
+vE4E1FGxwhZzqA/F6ZTRNb+qhQgRfY3HNdbhv5/HRRQZY4H5V6F9MsO0RAHrz30A
+QtB10paU9KOvxZqA/CEJTAdiYDQKAADitwIDAQABo4ID0TCCA80wHwYDVR0jBBgw
+FoAUt2ui6qiqhIx56rTaD5iyxZV2ufQwHQYDVR0OBBYEFNPlHIi+YXl95r64oS2D
+0v2+1mFkMHsGA1UdEQR0MHKCCyouZ2l0aHViLmlvggpnaXRodWIuY29tggwqLmdp
+dGh1Yi5jb22CDnd3dy5naXRodWIuY29tgglnaXRodWIuaW+CFWdpdGh1YnVzZXJj
+b250ZW50LmNvbYIXKi5naXRodWJ1c2VyY29udGVudC5jb20wDgYDVR0PAQH/BAQD
+AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjCBjwYDVR0fBIGHMIGE
+MECgPqA8hjpodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUTFNSU0FT
+SEEyNTYyMDIwQ0ExLTQuY3JsMECgPqA8hjpodHRwOi8vY3JsNC5kaWdpY2VydC5j
+b20vRGlnaUNlcnRUTFNSU0FTSEEyNTYyMDIwQ0ExLTQuY3JsMD4GA1UdIAQ3MDUw
+MwYGZ4EMAQICMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29t
+L0NQUzB/BggrBgEFBQcBAQRzMHEwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp
+Z2ljZXJ0LmNvbTBJBggrBgEFBQcwAoY9aHR0cDovL2NhY2VydHMuZGlnaWNlcnQu
+Y29tL0RpZ2lDZXJ0VExTUlNBU0hBMjU2MjAyMENBMS0xLmNydDAJBgNVHRMEAjAA
+MIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdgDoPtDaPvUGNTLnVyi8iWvJA9PL
+0RFr7Otp4Xd9bQa9bgAAAX+dgO+dAAAEAwBHMEUCIQDOV8Qe7mebG+hhf+MfzEEF
+2i0lNIO83vUTxkMREz/eMwIgKp3ZLFVMP2hz+1DAYPhmKvdWT3kTKWeeZxSHUEtm
+f88AdgA1zxkbv7FsV78PrUxtQsu7ticgJlHqP+Eq76gDwzvWTAAAAX+dgO/rAAAE
+AwBHMEUCIDAKos+w1Y1esfHWzcjREKA0m/fEoyMxA8Cj5EZETZziAiEAkxIcc6ZB
+3d7pHTI2w1yuRp1s6uciDTU/ICZ5yEvuFtwAdwC3Pvsk35xNunXyOcW6WPRsXfxC
+z3qfNcSeHQmBJe20mQAAAX+dgO/PAAAEAwBIMEYCIQDDYK04bMarexB4cqaAhnUF
+FItaejcjp7CeW+YtF70CzAIhAK5Fy7ARpPdjNoaSWuG1NzNZbj6DPfwdsFOZnoBq
+4GLhMA0GCSqGSIb3DQEBCwUAA4IBAQBokieSf5eLa7o62sPf9ihHuvIPoligvH1r
+gxFf6+kgsz+EwtF80Tb0ZR2DC7O2HSi0JGiihPgKO/3bXHZUc9cc4NkL7J842yFI
+rRwPHABMq2nLq7LCuGdJn+2tG76DAOXCtHMQ6XfuAq1FoPbtxXdWzynOJdDelPC6
+Qv3v3sMH6gJML1vW3OmeSUIncu686uDTs6E95BIuZ8eOjBjxZ7GfQv54RQU6oiMf
+bYVRSYaNfnS0VkPlwcR9Ubhx9wEuG4GuDus7OWItwFqm2c3peKQQK8+2CDMUHDUC
+QafDHvXcWeRdqQouCQC1tDlRAzPLKTcLD6EVltnPR5HQITRvHVgm
+-----END CERTIFICATE-----
+)CERT";
+const char github_io_chain_pem_second [] PROGMEM = R"CERT(
+-----BEGIN CERTIFICATE-----
+MIIEvjCCA6agAwIBAgIQBtjZBNVYQ0b2ii+nVCJ+xDANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaME8xCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxKTAnBgNVBAMTIERpZ2lDZXJ0IFRMUyBS
+U0EgU0hBMjU2IDIwMjAgQ0ExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAwUuzZUdwvN1PWNvsnO3DZuUfMRNUrUpmRh8sCuxkB+Uu3Ny5CiDt3+PE0J6a
+qXodgojlEVbbHp9YwlHnLDQNLtKS4VbL8Xlfs7uHyiUDe5pSQWYQYE9XE0nw6Ddn
+g9/n00tnTCJRpt8OmRDtV1F0JuJ9x8piLhMbfyOIJVNvwTRYAIuE//i+p1hJInuW
+raKImxW8oHzf6VGo1bDtN+I2tIJLYrVJmuzHZ9bjPvXj1hJeRPG/cUJ9WIQDgLGB
+Afr5yjK7tI4nhyfFK3TUqNaX3sNk+crOU6JWvHgXjkkDKa77SU+kFbnO8lwZV21r
+eacroicgE7XQPUDTITAHk+qZ9QIDAQABo4IBgjCCAX4wEgYDVR0TAQH/BAgwBgEB
+/wIBADAdBgNVHQ4EFgQUt2ui6qiqhIx56rTaD5iyxZV2ufQwHwYDVR0jBBgwFoAU
+A95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
+CCsGAQUFBwMBBggrBgEFBQcDAjB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGG
+GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2Nh
+Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNydDBCBgNV
+HR8EOzA5MDegNaAzhjFodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRH
+bG9iYWxSb290Q0EuY3JsMD0GA1UdIAQ2MDQwCwYJYIZIAYb9bAIBMAcGBWeBDAEB
+MAgGBmeBDAECATAIBgZngQwBAgIwCAYGZ4EMAQIDMA0GCSqGSIb3DQEBCwUAA4IB
+AQCAMs5eC91uWg0Kr+HWhMvAjvqFcO3aXbMM9yt1QP6FCvrzMXi3cEsaiVi6gL3z
+ax3pfs8LulicWdSQ0/1s/dCYbbdxglvPbQtaCdB73sRD2Cqk3p5BJl+7j5nL3a7h
+qG+fh/50tx8bIKuxT8b1Z11dmzzp/2n3YWzW2fP9NsarA4h20ksudYbj/NhVfSbC
+EXffPgK2fPOre3qGNm+499iTcc+G33Mw+nur7SpZyEKEOxEXGlLzyQ4UfaJbcme6
+ce1XR2bFuAJKZTRei9AqPCCcUZlM51Ke92sRKw2Sfh3oius2FkOH6ipjv3U/697E
+A7sKPPcw7+uvTPyLNhBzPvOk
+-----END CERTIFICATE-----
+)CERT";
+const char github_io_chain_pem_third [] PROGMEM = R"CERT(
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+)CERT";
+
+const char* host_rawcontent  = "raw.githubusercontent.com";
+const char* path_certstore_raw   = "/ZinggJM/GxEPD2/master/examples/GxEPD2_WiFi_CertStore_Loader/";
+const char* fp_github_io     = "8F 0E 79 24 71 C5 A7 D2 A7 46 76 30 C1 3C B7 2A 13 B0 01 B2"; // as of 29.7.2022
+
+void setup()
+{
+  Serial.begin(115200);
+  Serial.println();
+  Serial.println("GxEPD2_WiFi_CertStore_Loader");
+
+#ifdef RE_INIT_NEEDED
+  WiFi.persistent(true);
+  WiFi.mode(WIFI_STA); // switch off AP
+  WiFi.setAutoConnect(true);
+  WiFi.setAutoReconnect(true);
+  WiFi.disconnect();
+#endif
+
+  if (!WiFi.getAutoConnect() || ( WiFi.getMode() != WIFI_STA) || ((WiFi.SSID() != ssid) && String(ssid) != "........"))
+  {
+    Serial.println();
+    Serial.print("WiFi.getAutoConnect()=");
+    Serial.println(WiFi.getAutoConnect());
+    Serial.print("WiFi.SSID()=");
+    Serial.println(WiFi.SSID());
+    WiFi.mode(WIFI_STA); // switch off AP
+    Serial.print("Connecting to ");
+    Serial.println(ssid);
+    WiFi.begin(ssid, password);
+  }
+  int ConnectTimeout = 30; // 15 seconds
+  while (WiFi.status() != WL_CONNECTED)
+  {
+    delay(500);
+    Serial.print(".");
+    Serial.print(WiFi.status());
+    if (--ConnectTimeout <= 0)
+    {
+      Serial.println();
+      Serial.println("WiFi connect timeout");
+      return;
+    }
+  }
+  Serial.println();
+  Serial.println("WiFi connected");
+
+  // Print the IP address
+  Serial.println(WiFi.localIP());
+
+  setClock();
+
+#if defined (ESP8266)
+  LittleFS.begin();
+  Serial.println("LittleFS started");
+  //LittleFS.remove("certs_list.txt"); // was used for test
+  LittleFS.remove("certs.ar");
+  LittleFS.remove("certs.idx");
+#elif defined (ESP32)
+  SPIFFS.begin();
+  Serial.println("SPIFFS started");
+  //SPIFFS.remove("certs_list.txt"); // was used for test
+  SPIFFS.remove("certs.ar");
+  SPIFFS.remove("certs.idx");
+#endif
+  listFiles();
+  //downloadFile_HTTPS(host_rawcontent, path_certstore_raw, "certs_list.txt", "certs_list.txt"); // was used for test
+  downloadFile_HTTPS(host_rawcontent, path_certstore_raw, "certs.ar", "certs.ar");
+  listFiles();
+}
+
+void loop()
+{
+}
+
+void downloadFile_HTTPS(const char* host, const char* path, const char* filename, const char* target)
+{
+  // Use WiFiClientSecure class to create TLS connection
+#if defined (ESP8266)
+  BearSSL::WiFiClientSecure client;
+  BearSSL::X509List cert(cert_DigiCert_TLS_RSA_SHA256_2020_CA1);
+  BearSSL::X509List cert_pem_first(github_io_chain_pem_first);
+  BearSSL::X509List cert_pem_second(github_io_chain_pem_second);
+  BearSSL::X509List cert_pem_third(github_io_chain_pem_third);
+#else
+  WiFiClientSecure client;
+#endif
+  Serial.println(); Serial.print("downloading file \""); Serial.print(filename);  Serial.println("\"");
+  Serial.print("connecting to "); Serial.println(host);
+#if defined (ESP8266)
+  //client.setInsecure(); // fallback, currently still works with BearSSL
+  //client.setFingerprint(fp_github_io); // maybe would work until Tue, 21 Mar 2023 23:59:59 GMT
+  //client.setTrustAnchors(&cert_pem_first); // should work until Tue, 21 Mar 2023 23:59:59 GMT
+  //client.setTrustAnchors(&cert_pem_second); // should work until Tue, 21 Mar 2023 23:59:59 GMT
+  //client.setTrustAnchors(&cert_pem_third); // should work until Tue, 21 Mar 2023 23:59:59 GMT
+  client.setTrustAnchors(&cert); // should work until 2031-04-13 23:59:59
+#elif defined (ESP32)
+  client.setCACert(cert_DigiCert_TLS_RSA_SHA256_2020_CA1);
+#endif
+  if (!client.connect(host, httpsPort))
+  {
+    Serial.println("connection failed");
+    return;
+  }
+  Serial.print("requesting URL: ");
+  Serial.println(String("https://") + host + path + filename);
+  client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
+               "Host: " + host + "\r\n" +
+               "User-Agent: GxEPD2_WiFi_CertStore_Loader\r\n" +
+               "Connection: close\r\n\r\n");
+  Serial.println("request sent");
+  bool ok = false;
+  while (client.connected() || client.available())
+  {
+    String line = client.readStringUntil('\n');
+    if (!ok)
+    {
+      ok = line.startsWith("HTTP/1.1 200 OK");
+      if (ok) Serial.println(line);
+      //if (!ok) Serial.println(line);
+    }
+    if (!ok) Serial.println(line);
+    //Serial.println(line);
+    if (line == "\r")
+    {
+      Serial.println("headers received");
+      break;
+    }
+  }
+  if (!ok) return;
+  uint8_t buffer[512];
+  size_t total = 0;
+#if defined (ESP8266)
+  fs::File file = LittleFS.open(target, "w+");
+#elif defined(ESP32)
+  fs::File file = SPIFFS.open(String("/") + target, "w+");
+#endif
+  if (!file)
+  {
+    Serial.print(target); Serial.println(" open failed");
+    return;
+  }
+  while (client.connected() || client.available())
+  {
+    // this doesn't work as expected, but it helps for long downloads
+    int32_t start = millis();
+    for (int16_t t = 0, dly = 50; t < 20; t++, dly += 50)
+    {
+      if (!(client.connected() || client.available())) break;
+      if (client.available()) break; // read would not recover after having returned 0
+      delay(dly);
+    }
+    if (!(client.connected() || client.available())) break;
+    int32_t elapsed = millis() - start;
+    if (elapsed > 250)
+    {
+      Serial.print("waited for available "); Serial.print(millis() - start); Serial.print(" ms @ "); Serial.println(total);
+    }
+    size_t available = client.available();
+    if (0 == available)
+    {
+      Serial.print("download error: timeout on available() after "); Serial.print(total); Serial.println(" bytes");
+      break; // don't hang forever
+    }
+    size_t fetch = available <= sizeof(buffer) ? available : sizeof(buffer);
+    if (fetch > 0)
+    {
+      size_t got = client.read(buffer, fetch);
+      file.write(buffer, got);
+      total += got;
+    }
+    delay(1); // yield();
+    if (total > 30000) delay(250); // helps for long downloads
+  }
+  file.close();
+  Serial.print("done, "); Serial.print(total); Serial.println(" bytes transferred");
+}
+
+// Set time via NTP, as required for x.509 validation
+void setClock() 
+{
+  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");
+
+  Serial.print("Waiting for NTP time sync: ");
+  time_t now = time(nullptr);
+  while (now < 8 * 3600 * 2) 
+  {
+    delay(500);
+    Serial.print(".");
+    now = time(nullptr);
+  }
+  Serial.println("");
+  struct tm timeinfo;
+  gmtime_r(&now, &timeinfo);
+  Serial.print("Current time: ");
+  Serial.print(asctime(&timeinfo));
+}

+ 94 - 0
examples/GxEPD2_WiFi_CertStore_Loader/SPIFFS_Support.ino

@@ -0,0 +1,94 @@
+#if defined(ESP32)
+
+#include "FS.h"
+
+void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
+  Serial.printf("Listing directory: %s\r\n", dirname);
+
+  File root = fs.open(dirname);
+  if (!root) {
+    Serial.println("- failed to open directory");
+    return;
+  }
+  if (!root.isDirectory()) {
+    Serial.println(" - not a directory");
+    return;
+  }
+
+  File file = root.openNextFile();
+  while (file) {
+    if (file.isDirectory()) {
+      Serial.print("  DIR : ");
+      Serial.println(file.name());
+      if (levels) {
+        listDir(fs, file.name(), levels - 1);
+      }
+    } else {
+      Serial.print("  FILE: ");
+      Serial.print(file.name());
+      Serial.print("\tSIZE: ");
+      Serial.println(file.size());
+    }
+    file = root.openNextFile();
+  }
+}
+
+void listFiles()
+{
+  listDir(LittleFS, "/", 0);
+}
+
+#elif defined(ESP8266)
+
+#include <FS.h>
+#include <LittleFS.h>
+
+/*====================================================================================
+  This sketch contains support functions for the ESP6266 LittleFS filing system
+
+  Created by Bodmer 15th Jan 2017
+  ==================================================================================*/
+
+//====================================================================================
+//                 Print a LittleFS directory list (root directory)
+//====================================================================================
+
+void listFiles(void) {
+  Serial.println();
+  Serial.println("LittleFS files found:");
+
+  fs::Dir dir = LittleFS.openDir(""); // Root directory
+  String  line = "=====================================";
+  uint32_t totalBytes = 0;
+
+  Serial.println(line);
+  Serial.println("  File name               Size");
+  Serial.println(line);
+
+  while (dir.next()) {
+    String fileName = dir.fileName();
+    Serial.print(fileName);
+    int spaces = 25 - fileName.length(); // Tabulate nicely
+    while (spaces--) Serial.print(" ");
+    fs::File f = dir.openFile("r");
+    Serial.print(f.size()); Serial.println(" bytes");
+    totalBytes += f.size();
+  }
+  Serial.println(); Serial.print("Total = ");
+  int spaces = 25 - 8; // Tabulate nicely
+  while (spaces--) Serial.print(" ");
+  Serial.print(totalBytes); Serial.println(" bytes");
+
+  Serial.println(line);
+  Serial.println();
+  delay(1000);
+}
+//====================================================================================
+
+#else
+
+void listFiles()
+{
+  Serial.println("LittleFS listFiles() not implemented");
+}
+#endif

BIN
examples/GxEPD2_WiFi_CertStore_Loader/certs.ar.txt


BIN
examples/GxEPD2_WiFi_CertStore_Loader/certs.bmp


+ 81 - 0
examples/GxEPD2_WiFi_CertStore_Loader/update_certs/certs-from-mozilla.py

@@ -0,0 +1,81 @@
+#!/usr/bin/env python3
+
+# This script pulls the list of Mozilla trusted certificate authorities
+# from the web at the "mozurl" below, parses the file to grab the PEM
+# for each cert, and then generates DER files in a new ./data directory
+# Upload these to an on-chip filesystem and use the CertManager to parse
+# and use them for your outgoing SSL connections.
+#
+# Script by Earle F. Philhower, III.  Released to the public domain.
+from __future__ import print_function
+import csv
+import os
+import sys
+from shutil import which
+
+from subprocess import Popen, PIPE, call
+try:
+    from urllib.request import urlopen
+except Exception:
+    from urllib2 import urlopen
+try:
+    from StringIO import StringIO
+except Exception:
+    from io import StringIO
+
+# check if ar and openssl are available
+if which('ar') is None and not os.path.isfile('./ar') and not os.path.isfile('./ar.exe'):
+    raise Exception("You need the program 'ar' from xtensa-lx106-elf found here: (esp8266-arduino-core)/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/xtensa-lx106-elf/bin/ar")
+if which('openssl') is None and not os.path.isfile('./openssl') and not os.path.isfile('./openssl.exe'):
+    raise Exception("You need to have openssl in PATH, installable e.g. from https://download.firedaemon.com/FireDaemon-OpenSSL/FireDaemon-OpenSSL-x64-3.0.7.exe")
+    
+# Mozilla's URL for the CSV file with included PEM certs
+mozurl = "https://ccadb-public.secure.force.com/mozilla/IncludedCACertificateReportPEMCSV"
+
+# Load the names[] and pems[] array from the URL
+names = []
+pems = []
+response = urlopen(mozurl)
+csvData = response.read()
+if sys.version_info[0] > 2:
+    csvData = csvData.decode('utf-8')
+csvFile = StringIO(csvData)
+csvReader = csv.reader(csvFile)
+for row in csvReader:
+    names.append(row[0]+":"+row[1]+":"+row[2])
+    for item in row:
+        if item.startswith("'-----BEGIN CERTIFICATE-----"):
+            pems.append(item)
+del names[0] # Remove headers
+del pems[0] # Remove headers
+
+# Try and make ./data, skip if present
+try:
+    os.mkdir("data")
+except Exception:
+    pass
+
+derFiles = []
+idx = 0
+# Process the text PEM using openssl into DER files
+for i in range(0, len(pems)):
+    certName = "data/ca_%03d.der" % (idx);
+    thisPem = pems[i].replace("'", "")
+    print(names[i] + " -> " + certName)
+    ssl = Popen(['openssl','x509','-inform','PEM','-outform','DER','-out', certName], shell = False, stdin = PIPE)
+    pipe = ssl.stdin
+    pipe.write(thisPem.encode('utf-8'))
+    pipe.close()
+    ssl.wait()
+    if os.path.exists(certName):
+        derFiles.append(certName)
+        idx = idx + 1
+
+if os.path.exists("data/certs.ar"):
+    os.unlink("data/certs.ar");
+
+arCmd = ['ar', 'q', 'data/certs.ar'] + derFiles;
+call( arCmd )
+
+for der in derFiles:
+    os.unlink(der)

+ 13 - 0
examples/GxEPD2_WiFi_CertStore_Loader/update_certs/update_certs.cmd

@@ -0,0 +1,13 @@
+ECHO OFF
+REM update_certs.cmd : update certs.ar with actual pems retrieved from mozilla
+REM
+REM see also %LOCALAPPDATA%\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\libraries\ESP8266WiFi\examples\BearSSL_CertStore
+REM
+REM you may need to install openssl e.g. from https://kb.firedaemon.com/support/solutions/articles/4000121705
+REM windows installer here: https://download.firedaemon.com/FireDaemon-OpenSSL/FireDaemon-OpenSSL-x64-3.0.7.exe
+REM
+SET PATH=%LOCALAPPDATA%\Arduino15\packages\esp8266\tools\python3\3.7.2-post1;%LOCALAPPDATA%\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\3.0.4-gcc10.3-1757bed\xtensa-lx106-elf\bin;%PATH%
+python3 certs-from-mozilla.py
+REM
+REM copy certs.ar manually to parent directory
+REM