Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

certificate and public keys automatic updater #8218

Merged
merged 11 commits into from
Jul 17, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include <ESP8266WiFi.h>
#include <time.h>
#include "certs.h"

#ifndef STASSID
#define STASSID "your-ssid"
Expand All @@ -14,8 +15,6 @@
const char *ssid = STASSID;
const char *pass = STAPSK;

const char * host = "api.github.com";
const uint16_t port = 443;
const char * path = "/";

void setup() {
Expand Down Expand Up @@ -97,39 +96,14 @@ void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_


void loop() {
static const char digicert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
)EOF";
uint32_t start, finish;
BearSSL::WiFiClientSecure client;
BearSSL::X509List cert(digicert);
BearSSL::X509List cert(cert_DigiCert_High_Assurance_EV_Root_CA);

Serial.printf("Connecting without sessions...");
start = millis();
client.setTrustAnchors(&cert);
fetchURL(&client, host, port, path);
fetchURL(&client, github_host, github_port, path);
finish = millis();
Serial.printf("Total time: %dms\n", finish - start);

Expand All @@ -138,21 +112,21 @@ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
Serial.printf("Connecting with an uninitialized session...");
start = millis();
client.setTrustAnchors(&cert);
fetchURL(&client, host, port, path);
fetchURL(&client, github_host, github_port, path);
finish = millis();
Serial.printf("Total time: %dms\n", finish - start);

Serial.printf("Connecting with the just initialized session...");
start = millis();
client.setTrustAnchors(&cert);
fetchURL(&client, host, port, path);
fetchURL(&client, github_host, github_port, path);
finish = millis();
Serial.printf("Total time: %dms\n", finish - start);

Serial.printf("Connecting again with the initialized session...");
start = millis();
client.setTrustAnchors(&cert);
fetchURL(&client, host, port, path);
fetchURL(&client, github_host, github_port, path);
finish = millis();
Serial.printf("Total time: %dms\n", finish - start);

Expand Down
2 changes: 2 additions & 0 deletions libraries/ESP8266WiFi/examples/BearSSL_Sessions/certUpdate
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cd ${0%/*} 2>/dev/null
python3 ../../../../tools/cert.py -s api.github.com -n github > certs.h
90 changes: 90 additions & 0 deletions libraries/ESP8266WiFi/examples/BearSSL_Sessions/certs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@

// this file is autogenerated - any modification will be overwritten
// unused symbols will not be linked in the final binary
// generated on 2021-07-16 02:12:55
// by ['../../../../tools/cert.py', '-s', 'api.github.com', '-n', 'github']

#pragma once

////////////////////////////////////////////////////////////
// certificate chain for api.github.com:443

const char* github_host = "api.github.com";
const uint16_t github_port = 443;

// CN: *.github.com => name: __github_com
// not valid before: 2021-03-25 00:00:00
// not valid after: 2022-03-30 23:59:59
const char fingerprint___github_com [] PROGMEM = "96:84:07:df:0b:1c:f6:58:14:df:d7:33:35:57:51:9b:15:4d:8c:e7";
const char pubkey___github_com [] PROGMEM = R"PUBKEY(
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElL9/+0TidTIALPfU/tiS6pI8zAIk
rU4pohUldVc0bb6O3FARl3cnqIDK9SoF65z3xiR6XsnFS8F0Oy/chXR/kQ==
-----END PUBLIC KEY-----
)PUBKEY";

// http://cacerts.digicert.com/DigiCertHighAssuranceTLSHybridECCSHA2562020CA1.crt
// CN: DigiCert High Assurance TLS Hybrid ECC SHA256 2020 CA1 => name: DigiCert_High_Assurance_TLS_Hybrid_ECC_SHA256_2020_CA1
// not valid before: 2020-12-17 00:00:00
// not valid after: 2030-12-16 23:59:59
const char cert_DigiCert_High_Assurance_TLS_Hybrid_ECC_SHA256_2020_CA1 [] PROGMEM = R"CERT(
-----BEGIN CERTIFICATE-----
MIIEGzCCAwOgAwIBAgIQBmcDW7sU/WOvwNaoU07+FjANBgkqhkiG9w0BAQsFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTIwMTIxNzAwMDAwMFoXDTMwMTIxNjIzNTk1OVowZzEL
MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMT8wPQYDVQQDEzZE
aWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBUTFMgSHlicmlkIEVDQyBTSEEyNTYgMjAy
MCBDQTEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARnvW/xPOudvtC252wTq9ef
6fbdFeWPkOscfpRTkciuHj7UcumQSH3lzkPEIx0KpesWa8epsks7QwkZ4fU/Tkf9
o4IBhzCCAYMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUUGGmoNI1xBEq
II0fD6xC8M0pz0swHwYDVR0jBBgwFoAUsT7DaQP4v0cB1JgmGggC72NkK8MwDgYD
VR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB/Bggr
BgEFBQcBAQRzMHEwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNv
bTBJBggrBgEFBQcwAoY9aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lD
ZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNydDBLBgNVHR8ERDBCMECgPqA8hjpo
dHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZS
b290Q0EuY3JsMDAGA1UdIAQpMCcwCAYGZ4EMAQICMAgGBmeBDAECAzAHBgVngQwB
ATAIBgZngQwBAgEwDQYJKoZIhvcNAQELBQADggEBAHMQH8hhiBfNbxwEwxbbTAnu
jPyUh/oi0JrfZI3u9JuiLqca720D6foS/AB5+4EIxpm7CMG4MdN/l7oAiDipaCPv
mOmpYUpnT7A63Cr0q4g84rI1ZmdqA40lVUUf6qC6E34tC73qDQF8TJSrfscWFdCl
RXR9J4QGrkZ2VNMSDzlDRzWCaA95MfO8x01l+ZdopdE8FvM78gGd4zxeWb8v991+
mBxTDepqKuy/jF5Rm6Bhfxr33ADRs60s1t16dtZ3pOYLALBTPD5KhZ6a+/dk5dnh
6c4PaeZQYBUAh+GuxfaBlU4qQ8EtjBMCQHreMIwXHYHW5FRYGjgR4NMuaIw2jD0=
-----END CERTIFICATE-----
)CERT";

// http://cacerts.digicert.com/DigiCertHighAssuranceEVRootCA.crt
// CN: DigiCert High Assurance EV Root CA => name: DigiCert_High_Assurance_EV_Root_CA
// not valid before: 2006-11-10 00:00:00
// not valid after: 2031-11-10 00:00:00
const char cert_DigiCert_High_Assurance_EV_Root_CA [] PROGMEM = R"CERT(
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
)CERT";


// end of certificate chain for api.github.com:443
////////////////////////////////////////////////////////////

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <WiFiClientSecure.h>
#include <StackThunk.h>
#include <time.h>
#include "certs.h"

#ifndef STASSID
#define STASSID "your-ssid"
Expand All @@ -17,8 +18,6 @@
const char *ssid = STASSID;
const char *pass = STAPSK;

const char * host = "api.github.com";
const uint16_t port = 443;
const char * path = "/";

// Set time via NTP, as required for x.509 validation
Expand Down Expand Up @@ -92,7 +91,7 @@ If there are no CAs or insecure options specified, BearSSL will not connect.
Expect the following call to fail as none have been configured.
)EOF");
BearSSL::WiFiClientSecure client;
fetchURL(&client, host, port, path);
fetchURL(&client, gitlab_host, gitlab_port, path);
}

void fetchInsecure() {
Expand All @@ -103,7 +102,7 @@ which is subject to man-in-the-middle (MITM) attacks.
)EOF");
BearSSL::WiFiClientSecure client;
client.setInsecure();
fetchURL(&client, host, port, path);
fetchURL(&client, gitlab_host, gitlab_port, path);
}

void fetchFingerprint() {
Expand All @@ -116,9 +115,8 @@ fingerprints will change if anything changes in the certificate chain
the root authorities, etc.).
)EOF");
BearSSL::WiFiClientSecure client;
static const char fp[] PROGMEM = "59:74:61:88:13:CA:12:34:15:4D:11:0A:C1:7F:E6:67:07:69:42:F5";
client.setFingerprint(fp);
fetchURL(&client, host, port, path);
client.setFingerprint(fingerprint_gitlab_com);
fetchURL(&client, gitlab_host, gitlab_port, path);
}

void fetchSelfSigned() {
Expand All @@ -142,51 +140,13 @@ needs to be paired with the private key of the site, which is obviously
private and not shared. A MITM without the private key would not be
able to establish communications.
)EOF");
// Extracted by: openssl x509 -pubkey -noout -in servercert.pem
static const char pubkey[] PROGMEM = R"KEY(
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy+3Up8qBkIn/7S9AfWlH
Od8SdXmnWx+JCIHvnWzjFcLeLvQb2rMqqCDL5XDlvkyC5SZ8ZyLITemej5aJYuBv
zcKPzyZ0QfYZiskU9nzL2qBQj8alzJJ/Cc32AWuuWrPrzVxBmOEW9gRCGFCD3m0z
53y6GjcmBS2wcX7RagqbD7g2frEGko4G7kmW96H6dyh2j9Rou8TwAK6CnbiXPAM/
5Q6dyfdYlHOCgP75F7hhdKB5gpprm9A/OnQsmZjUPzy4u0EKCxE8MfhBerZrZdod
88ZdDG3CvTgm050bc+lGlbsT+s09lp0dgxSZIeI8+syV2Owt4YF/PdjeeymtzQdI
wQIDAQAB
-----END PUBLIC KEY-----
)KEY";
BearSSL::WiFiClientSecure client;
BearSSL::PublicKey key(pubkey);
BearSSL::PublicKey key(pubkey_gitlab_com);
client.setKnownKey(&key);
fetchURL(&client, host, port, path);
fetchURL(&client, gitlab_host, gitlab_port, path);
}

void fetchCertAuthority() {
static const char digicert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
)EOF";

Serial.printf(R"EOF(
A specific certification authority can be passed in and used to validate
a chain of certificates from a given server. These will be validated
Expand All @@ -197,14 +157,14 @@ BearSSL does verify the notValidBefore/After fields.
)EOF");

BearSSL::WiFiClientSecure client;
BearSSL::X509List cert(digicert);
BearSSL::X509List cert(cert_USERTrust_RSA_Certification_Authority);
client.setTrustAnchors(&cert);
Serial.printf("Try validating without setting the time (should fail)\n");
fetchURL(&client, host, port, path);
fetchURL(&client, gitlab_host, gitlab_port, path);

Serial.printf("Try again after setting NTP time (should pass)\n");
setClock();
fetchURL(&client, host, port, path);
fetchURL(&client, gitlab_host, gitlab_port, path);
}

void fetchFaster() {
Expand All @@ -217,18 +177,18 @@ may make sense
BearSSL::WiFiClientSecure client;
client.setInsecure();
uint32_t now = millis();
fetchURL(&client, host, port, path);
fetchURL(&client, gitlab_host, gitlab_port, path);
uint32_t delta = millis() - now;
client.setInsecure();
client.setCiphersLessSecure();
now = millis();
fetchURL(&client, host, port, path);
fetchURL(&client, gitlab_host, gitlab_port, path);
uint32_t delta2 = millis() - now;
std::vector<uint16_t> myCustomList = { BR_TLS_RSA_WITH_AES_256_CBC_SHA256, BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA };
client.setInsecure();
client.setCiphers(myCustomList);
now = millis();
fetchURL(&client, host, port, path);
fetchURL(&client, gitlab_host, gitlab_port, path);
uint32_t delta3 = millis() - now;
Serial.printf("Using more secure: %dms\nUsing less secure ciphers: %dms\nUsing custom cipher list: %dms\n", delta, delta2, delta3);
}
Expand Down
2 changes: 2 additions & 0 deletions libraries/ESP8266WiFi/examples/BearSSL_Validation/certUpdate
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cd ${0%/*} 2>/dev/null
python3 ../../../../tools/cert.py -s www.gitlab.com -n gitlab > certs.h
Loading