mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
Certificate and public keys automatic updater (#8218)
This commit is contained in:
parent
c9f27410f7
commit
69f8cd6934
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "certs.h"
|
||||||
|
|
||||||
#ifndef STASSID
|
#ifndef STASSID
|
||||||
#define STASSID "your-ssid"
|
#define STASSID "your-ssid"
|
||||||
@ -14,8 +15,6 @@
|
|||||||
const char *ssid = STASSID;
|
const char *ssid = STASSID;
|
||||||
const char *pass = STAPSK;
|
const char *pass = STAPSK;
|
||||||
|
|
||||||
const char * host = "api.github.com";
|
|
||||||
const uint16_t port = 443;
|
|
||||||
const char * path = "/";
|
const char * path = "/";
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
@ -97,39 +96,14 @@ void fetchURL(BearSSL::WiFiClientSecure *client, const char *host, const uint16_
|
|||||||
|
|
||||||
|
|
||||||
void loop() {
|
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;
|
uint32_t start, finish;
|
||||||
BearSSL::WiFiClientSecure client;
|
BearSSL::WiFiClientSecure client;
|
||||||
BearSSL::X509List cert(digicert);
|
BearSSL::X509List cert(cert_DigiCert_High_Assurance_EV_Root_CA);
|
||||||
|
|
||||||
Serial.printf("Connecting without sessions...");
|
Serial.printf("Connecting without sessions...");
|
||||||
start = millis();
|
start = millis();
|
||||||
client.setTrustAnchors(&cert);
|
client.setTrustAnchors(&cert);
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, github_host, github_port, path);
|
||||||
finish = millis();
|
finish = millis();
|
||||||
Serial.printf("Total time: %dms\n", finish - start);
|
Serial.printf("Total time: %dms\n", finish - start);
|
||||||
|
|
||||||
@ -138,21 +112,21 @@ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
|||||||
Serial.printf("Connecting with an uninitialized session...");
|
Serial.printf("Connecting with an uninitialized session...");
|
||||||
start = millis();
|
start = millis();
|
||||||
client.setTrustAnchors(&cert);
|
client.setTrustAnchors(&cert);
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, github_host, github_port, path);
|
||||||
finish = millis();
|
finish = millis();
|
||||||
Serial.printf("Total time: %dms\n", finish - start);
|
Serial.printf("Total time: %dms\n", finish - start);
|
||||||
|
|
||||||
Serial.printf("Connecting with the just initialized session...");
|
Serial.printf("Connecting with the just initialized session...");
|
||||||
start = millis();
|
start = millis();
|
||||||
client.setTrustAnchors(&cert);
|
client.setTrustAnchors(&cert);
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, github_host, github_port, path);
|
||||||
finish = millis();
|
finish = millis();
|
||||||
Serial.printf("Total time: %dms\n", finish - start);
|
Serial.printf("Total time: %dms\n", finish - start);
|
||||||
|
|
||||||
Serial.printf("Connecting again with the initialized session...");
|
Serial.printf("Connecting again with the initialized session...");
|
||||||
start = millis();
|
start = millis();
|
||||||
client.setTrustAnchors(&cert);
|
client.setTrustAnchors(&cert);
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, github_host, github_port, path);
|
||||||
finish = millis();
|
finish = millis();
|
||||||
Serial.printf("Total time: %dms\n", finish - start);
|
Serial.printf("Total time: %dms\n", finish - start);
|
||||||
|
|
||||||
|
2
libraries/ESP8266WiFi/examples/BearSSL_Sessions/certUpdate
Executable file
2
libraries/ESP8266WiFi/examples/BearSSL_Sessions/certUpdate
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
cd ${0%/*} 2>/dev/null
|
||||||
|
python3 ../../../../tools/cert.py -s api.github.com -n github > certs.h
|
90
libraries/ESP8266WiFi/examples/BearSSL_Sessions/certs.h
Normal file
90
libraries/ESP8266WiFi/examples/BearSSL_Sessions/certs.h
Normal file
@ -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
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
@ -8,6 +8,7 @@
|
|||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
#include <StackThunk.h>
|
#include <StackThunk.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "certs.h"
|
||||||
|
|
||||||
#ifndef STASSID
|
#ifndef STASSID
|
||||||
#define STASSID "your-ssid"
|
#define STASSID "your-ssid"
|
||||||
@ -17,8 +18,6 @@
|
|||||||
const char *ssid = STASSID;
|
const char *ssid = STASSID;
|
||||||
const char *pass = STAPSK;
|
const char *pass = STAPSK;
|
||||||
|
|
||||||
const char * host = "api.github.com";
|
|
||||||
const uint16_t port = 443;
|
|
||||||
const char * path = "/";
|
const char * path = "/";
|
||||||
|
|
||||||
// Set time via NTP, as required for x.509 validation
|
// Set time via NTP, as required for x.509 validation
|
||||||
@ -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.
|
Expect the following call to fail as none have been configured.
|
||||||
)EOF");
|
)EOF");
|
||||||
BearSSL::WiFiClientSecure client;
|
BearSSL::WiFiClientSecure client;
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, gitlab_host, gitlab_port, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetchInsecure() {
|
void fetchInsecure() {
|
||||||
@ -103,7 +102,7 @@ which is subject to man-in-the-middle (MITM) attacks.
|
|||||||
)EOF");
|
)EOF");
|
||||||
BearSSL::WiFiClientSecure client;
|
BearSSL::WiFiClientSecure client;
|
||||||
client.setInsecure();
|
client.setInsecure();
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, gitlab_host, gitlab_port, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetchFingerprint() {
|
void fetchFingerprint() {
|
||||||
@ -116,9 +115,8 @@ fingerprints will change if anything changes in the certificate chain
|
|||||||
the root authorities, etc.).
|
the root authorities, etc.).
|
||||||
)EOF");
|
)EOF");
|
||||||
BearSSL::WiFiClientSecure client;
|
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(fingerprint_gitlab_com);
|
||||||
client.setFingerprint(fp);
|
fetchURL(&client, gitlab_host, gitlab_port, path);
|
||||||
fetchURL(&client, host, port, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetchSelfSigned() {
|
void fetchSelfSigned() {
|
||||||
@ -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
|
private and not shared. A MITM without the private key would not be
|
||||||
able to establish communications.
|
able to establish communications.
|
||||||
)EOF");
|
)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::WiFiClientSecure client;
|
||||||
BearSSL::PublicKey key(pubkey);
|
BearSSL::PublicKey key(pubkey_gitlab_com);
|
||||||
client.setKnownKey(&key);
|
client.setKnownKey(&key);
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, gitlab_host, gitlab_port, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetchCertAuthority() {
|
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(
|
Serial.printf(R"EOF(
|
||||||
A specific certification authority can be passed in and used to validate
|
A specific certification authority can be passed in and used to validate
|
||||||
a chain of certificates from a given server. These will be validated
|
a chain of certificates from a given server. These will be validated
|
||||||
@ -197,14 +157,14 @@ BearSSL does verify the notValidBefore/After fields.
|
|||||||
)EOF");
|
)EOF");
|
||||||
|
|
||||||
BearSSL::WiFiClientSecure client;
|
BearSSL::WiFiClientSecure client;
|
||||||
BearSSL::X509List cert(digicert);
|
BearSSL::X509List cert(cert_USERTrust_RSA_Certification_Authority);
|
||||||
client.setTrustAnchors(&cert);
|
client.setTrustAnchors(&cert);
|
||||||
Serial.printf("Try validating without setting the time (should fail)\n");
|
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");
|
Serial.printf("Try again after setting NTP time (should pass)\n");
|
||||||
setClock();
|
setClock();
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, gitlab_host, gitlab_port, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fetchFaster() {
|
void fetchFaster() {
|
||||||
@ -217,18 +177,18 @@ may make sense
|
|||||||
BearSSL::WiFiClientSecure client;
|
BearSSL::WiFiClientSecure client;
|
||||||
client.setInsecure();
|
client.setInsecure();
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, gitlab_host, gitlab_port, path);
|
||||||
uint32_t delta = millis() - now;
|
uint32_t delta = millis() - now;
|
||||||
client.setInsecure();
|
client.setInsecure();
|
||||||
client.setCiphersLessSecure();
|
client.setCiphersLessSecure();
|
||||||
now = millis();
|
now = millis();
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, gitlab_host, gitlab_port, path);
|
||||||
uint32_t delta2 = millis() - now;
|
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 };
|
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.setInsecure();
|
||||||
client.setCiphers(myCustomList);
|
client.setCiphers(myCustomList);
|
||||||
now = millis();
|
now = millis();
|
||||||
fetchURL(&client, host, port, path);
|
fetchURL(&client, gitlab_host, gitlab_port, path);
|
||||||
uint32_t delta3 = millis() - now;
|
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);
|
Serial.printf("Using more secure: %dms\nUsing less secure ciphers: %dms\nUsing custom cipher list: %dms\n", delta, delta2, delta3);
|
||||||
}
|
}
|
||||||
|
2
libraries/ESP8266WiFi/examples/BearSSL_Validation/certUpdate
Executable file
2
libraries/ESP8266WiFi/examples/BearSSL_Validation/certUpdate
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
cd ${0%/*} 2>/dev/null
|
||||||
|
python3 ../../../../tools/cert.py -s www.gitlab.com -n gitlab > certs.h
|
115
libraries/ESP8266WiFi/examples/BearSSL_Validation/certs.h
Normal file
115
libraries/ESP8266WiFi/examples/BearSSL_Validation/certs.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
// this file is autogenerated - any modification will be overwritten
|
||||||
|
// unused symbols will not be linked in the final binary
|
||||||
|
// generated on 2021-07-18 00:02:22
|
||||||
|
// by ['../../../../tools/cert.py', '-s', 'www.gitlab.com', '-n', 'gitlab']
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
// certificate chain for www.gitlab.com:443
|
||||||
|
|
||||||
|
const char* gitlab_host = "www.gitlab.com";
|
||||||
|
const uint16_t gitlab_port = 443;
|
||||||
|
|
||||||
|
// CN: gitlab.com => name: gitlab_com
|
||||||
|
// not valid before: 2021-04-12 00:00:00
|
||||||
|
// not valid after: 2022-05-11 23:59:59
|
||||||
|
const char fingerprint_gitlab_com [] PROGMEM = "71:55:5e:29:68:99:43:98:c8:85:35:bd:4c:10:4c:f5:cf:17:09:e6";
|
||||||
|
const char pubkey_gitlab_com [] PROGMEM = R"PUBKEY(
|
||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1eeFy86Xbz3ygyCVprHp
|
||||||
|
sPP3zyg0yldkIfqwjsXPH0b+KwQ85s3pzI/5+MVrR2/BGY4ed6mTZ6hvNwQJ2B0E
|
||||||
|
sJrsTb2nuUsXQ0UVO4hvnZ7Dnx8r/bT1cndqa+Mn+bms8/TS4etP72+TLaORBRCz
|
||||||
|
O4L1Hi8r61+zZLnP3DqqHeHAgl5wKHNYpx7yFFl2I71LuLH/pk2ICDBjaHwCIbRW
|
||||||
|
u484no9s1c4VROxqMrQQ/wDMl80MiO9YeNQ5rBHfnabh4rFe9eb2Sd0H/DWBj3SO
|
||||||
|
YBD0kiLI6b5CWYfA76pBSlZg7G3ledvQ+n9FEcS3EOCPKBBZqMDCzEahvHqwJ/r6
|
||||||
|
pwIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
|
)PUBKEY";
|
||||||
|
|
||||||
|
// http://crt.sectigo.com/SectigoRSADomainValidationSecureServerCA.crt
|
||||||
|
// CN: Sectigo RSA Domain Validation Secure Server CA => name: Sectigo_RSA_Domain_Validation_Secure_Server_CA
|
||||||
|
// not valid before: 2018-11-02 00:00:00
|
||||||
|
// not valid after: 2030-12-31 23:59:59
|
||||||
|
const char cert_Sectigo_RSA_Domain_Validation_Secure_Server_CA [] PROGMEM = R"CERT(
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
|
||||||
|
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
|
||||||
|
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
|
||||||
|
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
|
||||||
|
MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBjzELMAkGA1UEBhMCR0IxGzAZBgNV
|
||||||
|
BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE
|
||||||
|
ChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFJTQSBEb21haW4g
|
||||||
|
VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
||||||
|
AQ8AMIIBCgKCAQEA1nMz1tc8INAA0hdFuNY+B6I/x0HuMjDJsGz99J/LEpgPLT+N
|
||||||
|
TQEMgg8Xf2Iu6bhIefsWg06t1zIlk7cHv7lQP6lMw0Aq6Tn/2YHKHxYyQdqAJrkj
|
||||||
|
eocgHuP/IJo8lURvh3UGkEC0MpMWCRAIIz7S3YcPb11RFGoKacVPAXJpz9OTTG0E
|
||||||
|
oKMbgn6xmrntxZ7FN3ifmgg0+1YuWMQJDgZkW7w33PGfKGioVrCSo1yfu4iYCBsk
|
||||||
|
Haswha6vsC6eep3BwEIc4gLw6uBK0u+QDrTBQBbwb4VCSmT3pDCg/r8uoydajotY
|
||||||
|
uK3DGReEY+1vVv2Dy2A0xHS+5p3b4eTlygxfFQIDAQABo4IBbjCCAWowHwYDVR0j
|
||||||
|
BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFI2MXsRUrYrhd+mb
|
||||||
|
+ZsF4bgBjWHhMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
|
||||||
|
A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAbBgNVHSAEFDASMAYGBFUdIAAw
|
||||||
|
CAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0
|
||||||
|
LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2Bggr
|
||||||
|
BgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNv
|
||||||
|
bS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDov
|
||||||
|
L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMr9hvQ5Iw0/H
|
||||||
|
ukdN+Jx4GQHcEx2Ab/zDcLRSmjEzmldS+zGea6TvVKqJjUAXaPgREHzSyrHxVYbH
|
||||||
|
7rM2kYb2OVG/Rr8PoLq0935JxCo2F57kaDl6r5ROVm+yezu/Coa9zcV3HAO4OLGi
|
||||||
|
H19+24rcRki2aArPsrW04jTkZ6k4Zgle0rj8nSg6F0AnwnJOKf0hPHzPE/uWLMUx
|
||||||
|
RP0T7dWbqWlod3zu4f+k+TY4CFM5ooQ0nBnzvg6s1SQ36yOoeNDT5++SR2RiOSLv
|
||||||
|
xvcRviKFxmZEJCaOEDKNyJOuB56DPi/Z+fVGjmO+wea03KbNIaiGCpXZLoUmGv38
|
||||||
|
sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
|
||||||
|
l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
|
||||||
|
6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
|
||||||
|
LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
|
||||||
|
yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
|
||||||
|
00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
)CERT";
|
||||||
|
|
||||||
|
// http://crt.usertrust.com/USERTrustRSAAddTrustCA.crt
|
||||||
|
// CN: USERTrust RSA Certification Authority => name: USERTrust_RSA_Certification_Authority
|
||||||
|
// not valid before: 2019-03-12 00:00:00
|
||||||
|
// not valid after: 2028-12-31 23:59:59
|
||||||
|
const char cert_USERTrust_RSA_Certification_Authority [] PROGMEM = R"CERT(
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFgTCCBGmgAwIBAgIQOXJEOvkit1HX02wQ3TE1lTANBgkqhkiG9w0BAQwFADB7
|
||||||
|
MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
|
||||||
|
VQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UE
|
||||||
|
AwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTE5MDMxMjAwMDAwMFoXDTI4
|
||||||
|
MTIzMTIzNTk1OVowgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5
|
||||||
|
MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBO
|
||||||
|
ZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0
|
||||||
|
aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgBJlFzYOw9sI
|
||||||
|
s9CsVw127c0n00ytUINh4qogTQktZAnczomfzD2p7PbPwdzx07HWezcoEStH2jnG
|
||||||
|
vDoZtF+mvX2do2NCtnbyqTsrkfjib9DsFiCQCT7i6HTJGLSR1GJk23+jBvGIGGqQ
|
||||||
|
Ijy8/hPwhxR79uQfjtTkUcYRZ0YIUcuGFFQ/vDP+fmyc/xadGL1RjjWmp2bIcmfb
|
||||||
|
IWax1Jt4A8BQOujM8Ny8nkz+rwWWNR9XWrf/zvk9tyy29lTdyOcSOk2uTIq3XJq0
|
||||||
|
tyA9yn8iNK5+O2hmAUTnAU5GU5szYPeUvlM3kHND8zLDU+/bqv50TmnHa4xgk97E
|
||||||
|
xwzf4TKuzJM7UXiVZ4vuPVb+DNBpDxsP8yUmazNt925H+nND5X4OpWaxKXwyhGNV
|
||||||
|
icQNwZNUMBkTrNN9N6frXTpsNVzbQdcS2qlJC9/YgIoJk2KOtWbPJYjNhLixP6Q5
|
||||||
|
D9kCnusSTJV882sFqV4Wg8y4Z+LoE53MW4LTTLPtW//e5XOsIzstAL81VXQJSdhJ
|
||||||
|
WBp/kjbmUZIO8yZ9HE0XvMnsQybQv0FfQKlERPSZ51eHnlAfV1SoPv10Yy+xUGUJ
|
||||||
|
5lhCLkMaTLTwJUdZ+gQek9QmRkpQgbLevni3/GcV4clXhB4PY9bpYrrWX1Uu6lzG
|
||||||
|
KAgEJTm4Diup8kyXHAc/DVL17e8vgg8CAwEAAaOB8jCB7zAfBgNVHSMEGDAWgBSg
|
||||||
|
EQojPpbxB+zirynvgqV/0DCktDAdBgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rID
|
||||||
|
ZsswDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAG
|
||||||
|
BgRVHSAAMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29t
|
||||||
|
L0FBQUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggr
|
||||||
|
BgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUA
|
||||||
|
A4IBAQAYh1HcdCE9nIrgJ7cz0C7M7PDmy14R3iJvm3WOnnL+5Nb+qh+cli3vA0p+
|
||||||
|
rvSNb3I8QzvAP+u431yqqcau8vzY7qN7Q/aGNnwU4M309z/+3ri0ivCRlv79Q2R+
|
||||||
|
/czSAaF9ffgZGclCKxO/WIu6pKJmBHaIkU4MiRTOok3JMrO66BQavHHxW/BBC5gA
|
||||||
|
CiIDEOUMsfnNkjcZ7Tvx5Dq2+UUTJnWvu6rvP3t3O9LEApE9GQDTF1w52z97GA1F
|
||||||
|
zZOFli9d31kWTz9RvdVFGD/tSo7oBmF0Ixa1DVBzJ0RHfxBdiSprhTEUxOipakyA
|
||||||
|
vGp4z7h/jnZymQyd/teRCBaho1+V
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
)CERT";
|
||||||
|
|
||||||
|
|
||||||
|
// end of certificate chain for www.gitlab.com:443
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#include <WiFiClientSecure.h>
|
#include <WiFiClientSecure.h>
|
||||||
|
#include "certs.h"
|
||||||
|
|
||||||
#ifndef STASSID
|
#ifndef STASSID
|
||||||
#define STASSID "your-ssid"
|
#define STASSID "your-ssid"
|
||||||
@ -22,42 +23,7 @@
|
|||||||
const char* ssid = STASSID;
|
const char* ssid = STASSID;
|
||||||
const char* password = STAPSK;
|
const char* password = STAPSK;
|
||||||
|
|
||||||
const char* host = "api.github.com";
|
X509List cert(cert_DigiCert_High_Assurance_EV_Root_CA);
|
||||||
const int httpsPort = 443;
|
|
||||||
|
|
||||||
// DigiCert High Assurance EV Root CA
|
|
||||||
const char trustRoot[] PROGMEM = R"EOF(
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIE6zCCBHGgAwIBAgIQAtX25VXj+RoJlA3D2bWkgzAKBggqhkjOPQQDAzBWMQsw
|
|
||||||
CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTAwLgYDVQQDEydEaWdp
|
|
||||||
Q2VydCBUTFMgSHlicmlkIEVDQyBTSEEzODQgMjAyMCBDQTEwHhcNMjEwMzA0MDAw
|
|
||||||
MDAwWhcNMjIwMzA5MjM1OTU5WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
|
|
||||||
aWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHVi
|
|
||||||
LCBJbmMuMRUwEwYDVQQDDAwqLmdpdGh1Yi5jb20wWTATBgcqhkjOPQIBBggqhkjO
|
|
||||||
PQMBBwNCAAQf8SePhtD7JeGm0YuTQ4HihyeENuvsNFdYPPIxIx6Lj9iOu2ECkgy4
|
|
||||||
52UR+mhIF24OvPizDveyCFOqmG/MI7kwo4IDDTCCAwkwHwYDVR0jBBgwFoAUCrwI
|
|
||||||
KReMpTlteg7OM8cus+37w3owHQYDVR0OBBYEFP5TUYtiCp+N3FISu3CqxMlJhdG1
|
|
||||||
MCMGA1UdEQQcMBqCDCouZ2l0aHViLmNvbYIKZ2l0aHViLmNvbTAOBgNVHQ8BAf8E
|
|
||||||
BAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIGXBgNVHR8EgY8w
|
|
||||||
gYwwRKBCoECGPmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRMU0h5
|
|
||||||
YnJpZEVDQ1NIQTM4NDIwMjBDQTEuY3JsMESgQqBAhj5odHRwOi8vY3JsNC5kaWdp
|
|
||||||
Y2VydC5jb20vRGlnaUNlcnRUTFNIeWJyaWRFQ0NTSEEzODQyMDIwQ0ExLmNybDA+
|
|
||||||
BgNVHSAENzA1MDMGBmeBDAECAjApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRp
|
|
||||||
Z2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQcwAYYYaHR0
|
|
||||||
cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2FjZXJ0
|
|
||||||
cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUTFNIeWJyaWRFQ0NTSEEzODQyMDIwQ0Ex
|
|
||||||
LmNydDAMBgNVHRMBAf8EAjAAMIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDvAHUAKXm+
|
|
||||||
8J45OSHwVnOfY6V35b5XfZxgCvj5TV0mXCVdx4QAAAF3/bWc4AAABAMARjBEAiBm
|
|
||||||
IdofaKj+XfeISM/2tjap1nQY1afFSBAcdw/YtgjmSQIgMqWoDyfO66suyk2VFcld
|
|
||||||
1C+WHUNGvXsCRPof5HG5QQgAdgAiRUUHWVUkVpY/oS/x922G4CMmY63AS39dxoNc
|
|
||||||
buIPAgAAAXf9tZ0CAAAEAwBHMEUCIQCJzwZRfAvv0izotFx2KE0sgV8O+NfuHUpa
|
|
||||||
1866RqKEtwIgc65P+xToSqPbp/J1gSFBJgySI/a1YoB+3p8xXTYaDsAwCgYIKoZI
|
|
||||||
zj0EAwMDaAAwZQIxAL8fIlMNWdeKHalpm9z+ksCuYT4tSN1ubXeNvDywr56me+yT
|
|
||||||
+fr42MnEcBdUtLOVOAIwPNC9fAJjyHHTL2vaRW1JRnrovLKDQVbZpZNIZnlY3WFu
|
|
||||||
kmxiBWDOpyfJrG9vQ25K
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
)EOF";
|
|
||||||
X509List cert(trustRoot);
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
@ -94,12 +60,12 @@ void setup() {
|
|||||||
// Use WiFiClientSecure class to create TLS connection
|
// Use WiFiClientSecure class to create TLS connection
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
Serial.print("Connecting to ");
|
Serial.print("Connecting to ");
|
||||||
Serial.println(host);
|
Serial.println(github_host);
|
||||||
|
|
||||||
Serial.printf("Using certificate: %s\n", trustRoot);
|
Serial.printf("Using certificate: %s\n", cert_DigiCert_High_Assurance_EV_Root_CA);
|
||||||
client.setTrustAnchors(&cert);
|
client.setTrustAnchors(&cert);
|
||||||
|
|
||||||
if (!client.connect(host, httpsPort)) {
|
if (!client.connect(github_host, github_port)) {
|
||||||
Serial.println("Connection failed");
|
Serial.println("Connection failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -109,7 +75,7 @@ void setup() {
|
|||||||
Serial.println(url);
|
Serial.println(url);
|
||||||
|
|
||||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||||
"Host: " + host + "\r\n" +
|
"Host: " + github_host + "\r\n" +
|
||||||
"User-Agent: BuildFailureDetectorESP8266\r\n" +
|
"User-Agent: BuildFailureDetectorESP8266\r\n" +
|
||||||
"Connection: close\r\n\r\n");
|
"Connection: close\r\n\r\n");
|
||||||
|
|
||||||
|
2
libraries/ESP8266WiFi/examples/HTTPSRequest/certUpdate
Executable file
2
libraries/ESP8266WiFi/examples/HTTPSRequest/certUpdate
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
cd ${0%/*} 2>/dev/null
|
||||||
|
python3 ../../../../tools/cert.py -s api.github.com -n github > certs.h
|
90
libraries/ESP8266WiFi/examples/HTTPSRequest/certs.h
Normal file
90
libraries/ESP8266WiFi/examples/HTTPSRequest/certs.h
Normal file
@ -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:54
|
||||||
|
// 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
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
@ -457,6 +457,7 @@ namespace brssl {
|
|||||||
}
|
}
|
||||||
memcpy(pk->key.ec.q, ek->q, ek->qlen);
|
memcpy(pk->key.ec.q, ek->q, ek->qlen);
|
||||||
pk->key.ec.qlen = ek->qlen;
|
pk->key.ec.qlen = ek->qlen;
|
||||||
|
pk->key.ec.curve = ek->curve;
|
||||||
return pk;
|
return pk;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -112,7 +112,10 @@ The following points assume work in a direct clone of the repository, and not in
|
|||||||
* [platform.txt](https://github.com/esp8266/Arduino/blob/master/platform.txt) and [package.json](https://github.com/esp8266/Arduino/blob/master/package.json): update `version` to the release E.g. `3.0.0`,
|
* [platform.txt](https://github.com/esp8266/Arduino/blob/master/platform.txt) and [package.json](https://github.com/esp8266/Arduino/blob/master/package.json): update `version` to the release E.g. `3.0.0`,
|
||||||
|
|
||||||
* [cores/esp8266/TZ.h](https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h): import the latest database with the following shell command:\
|
* [cores/esp8266/TZ.h](https://github.com/esp8266/Arduino/blob/master/cores/esp8266/TZ.h): import the latest database with the following shell command:\
|
||||||
`$ cd tools; sh TZupdate.sh`.
|
`$ cd tools; sh TZupdate.sh`
|
||||||
|
|
||||||
|
* Update SSL/TLS certificates and public keys in examples:\
|
||||||
|
`$ cd tools; sh certsUpdate.sh`
|
||||||
|
|
||||||
5. Wait until the release notes have been checked by other maintainers
|
5. Wait until the release notes have been checked by other maintainers
|
||||||
|
|
||||||
|
125
tools/cert.py
Executable file
125
tools/cert.py
Executable file
@ -0,0 +1,125 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Script to download/update certificates and public keys
|
||||||
|
# and generate compilable source files for c++/Arduino.
|
||||||
|
# released to public domain
|
||||||
|
|
||||||
|
import urllib.request
|
||||||
|
import re
|
||||||
|
import ssl
|
||||||
|
import sys
|
||||||
|
import socket
|
||||||
|
import argparse
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from cryptography import x509
|
||||||
|
from cryptography.hazmat.primitives import hashes
|
||||||
|
from cryptography.hazmat.primitives.serialization import pkcs7
|
||||||
|
from cryptography.hazmat.primitives.serialization import Encoding
|
||||||
|
from cryptography.hazmat.primitives.serialization import PublicFormat
|
||||||
|
|
||||||
|
def printData(data, showPub = True):
|
||||||
|
try:
|
||||||
|
xcert = x509.load_der_x509_certificate(data)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
xcert = x509.load_pem_x509_certificate(data)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
xcert = pkcs7.load_der_pkcs7_certificates(data)
|
||||||
|
except:
|
||||||
|
xcert = pkcs7.load_pem_pkcs7_certificates(data)
|
||||||
|
if len(xcert) > 1:
|
||||||
|
print('// Warning: TODO: pkcs7 has {} entries'.format(len(xcert)))
|
||||||
|
xcert = xcert[0]
|
||||||
|
|
||||||
|
cn = ''
|
||||||
|
for dn in xcert.subject.rfc4514_string().split(','):
|
||||||
|
keyval = dn.split('=')
|
||||||
|
if keyval[0] == 'CN':
|
||||||
|
cn += keyval[1]
|
||||||
|
name = re.sub('[^a-zA-Z0-9_]', '_', cn)
|
||||||
|
print('// CN: {} => name: {}'.format(cn, name))
|
||||||
|
|
||||||
|
print('// not valid before:', xcert.not_valid_before)
|
||||||
|
print('// not valid after: ', xcert.not_valid_after)
|
||||||
|
|
||||||
|
if showPub:
|
||||||
|
|
||||||
|
fingerprint = xcert.fingerprint(hashes.SHA1()).hex(':')
|
||||||
|
print('const char fingerprint_{} [] PROGMEM = "{}";'.format(name, fingerprint))
|
||||||
|
|
||||||
|
pem = xcert.public_key().public_bytes(Encoding.PEM, PublicFormat.SubjectPublicKeyInfo).decode('utf-8')
|
||||||
|
print('const char pubkey_{} [] PROGMEM = R"PUBKEY('.format(name))
|
||||||
|
print(pem + ')PUBKEY";')
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
cert = xcert.public_bytes(Encoding.PEM).decode('utf-8')
|
||||||
|
print('const char cert_{} [] PROGMEM = R"CERT('.format(name))
|
||||||
|
print(cert + ')CERT";')
|
||||||
|
|
||||||
|
cas = []
|
||||||
|
for ext in xcert.extensions:
|
||||||
|
if ext.oid == x509.ObjectIdentifier("1.3.6.1.5.5.7.1.1"):
|
||||||
|
for desc in ext.value:
|
||||||
|
if desc.access_method == x509.oid.AuthorityInformationAccessOID.CA_ISSUERS:
|
||||||
|
cas.append(desc.access_location.value)
|
||||||
|
for ca in cas:
|
||||||
|
with urllib.request.urlopen(ca) as crt:
|
||||||
|
print()
|
||||||
|
print('// ' + ca)
|
||||||
|
printData(crt.read(), False)
|
||||||
|
print()
|
||||||
|
|
||||||
|
def get_certificate(hostname, port, name):
|
||||||
|
context = ssl.create_default_context()
|
||||||
|
context.check_hostname = False
|
||||||
|
context.verify_mode = ssl.CERT_NONE
|
||||||
|
with socket.create_connection((hostname, port)) as sock:
|
||||||
|
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
|
||||||
|
print('////////////////////////////////////////////////////////////')
|
||||||
|
print('// certificate chain for {}:{}'.format(hostname, port))
|
||||||
|
print()
|
||||||
|
if name:
|
||||||
|
print('const char* {}_host = "{}";'.format(name, hostname));
|
||||||
|
print('const uint16_t {}_port = {};'.format(name, port));
|
||||||
|
print()
|
||||||
|
printData(ssock.getpeercert(binary_form=True))
|
||||||
|
print('// end of certificate chain for {}:{}'.format(hostname, port))
|
||||||
|
print('////////////////////////////////////////////////////////////')
|
||||||
|
print()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='download certificate chain and public keys under a C++/Arduino compilable form')
|
||||||
|
parser.add_argument('-s', '--server', action='store', required=True, help='TLS server dns name')
|
||||||
|
parser.add_argument('-p', '--port', action='store', required=False, help='TLS server port')
|
||||||
|
parser.add_argument('-n', '--name', action='store', required=False, help='variable name')
|
||||||
|
port = 443
|
||||||
|
args = parser.parse_args()
|
||||||
|
server = args.server
|
||||||
|
port = 443
|
||||||
|
try:
|
||||||
|
split = server.split(':')
|
||||||
|
server = split[0]
|
||||||
|
port = int(split[1])
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
port = int(args.port)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
print()
|
||||||
|
print('// this file is autogenerated - any modification will be overwritten')
|
||||||
|
print('// unused symbols will not be linked in the final binary')
|
||||||
|
print('// generated on {}'.format(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
|
||||||
|
print('// by {}'.format(sys.argv))
|
||||||
|
print()
|
||||||
|
print('#pragma once')
|
||||||
|
print()
|
||||||
|
return get_certificate(server, port, args.name)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
6
tools/certsUpdate.sh
Executable file
6
tools/certsUpdate.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
# find `certUpdate` scripts in libraries, and execute them
|
||||||
|
|
||||||
|
cd ${0%/*} 2>/dev/null
|
||||||
|
find ../libraries -name certUpdate -exec bash -c "echo 'updating {}...'; {};" \;
|
||||||
|
echo done
|
Loading…
x
Reference in New Issue
Block a user