Skip to content

Commit

Permalink
added https support
Browse files Browse the repository at this point in the history
  • Loading branch information
lmarzen committed Jun 10, 2023
1 parent fb6b4ba commit 6921fd5
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 57 deletions.
132 changes: 132 additions & 0 deletions cert/cert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/usr/bin/env python3

# Script to download/update certificates and public keys
# and generate compilable source files for c++/Arduino.
# released to public domain
# Retrieved from https://github.com/esp8266/Arduino/blob/master/tools/cert.py

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)

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()
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
try:
split = server.split(':')
server = split[0]
port = int(split[1])
except:
pass
try:
port = int(args.port)
except:
pass

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 \'' + ' '.join(sys.argv) + '\'')
print()
print('// alternatively, the certificate chain can be extracted using openssl')
print('// \'openssl s_client -verify 5 -showcerts -connect api.openweathermap.org:443 < /dev/null\'')

print()
print('#ifndef __CERT_H__')
print('#define __CERT_H__')
print()
get_certificate(server, port, args.name)
print('#endif')
print()
return

if __name__ == '__main__':
sys.exit(main())
116 changes: 116 additions & 0 deletions platformio/include/cert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// this file is autogenerated - any modification will be overwritten
// unused symbols will not be linked in the final binary
// generated on 2023-06-10 03:24:21
// by 'cert.py -s api.openweathermap.org -p 443 -n openweathermap'

// alternatively, the certificate chain can be extracted using openssl
// 'openssl s_client -verify 5 -showcerts -connect api.openweathermap.org:443 < /dev/null'

#ifndef __CERT_H__
#define __CERT_H__

////////////////////////////////////////////////////////////
// certificate chain for api.openweathermap.org:443

// CN: *.openweathermap.org => name: __openweathermap_org
// not valid before: 2022-06-06 00:00:00
// not valid after: 2023-07-07 23:59:59
const char fingerprint___openweathermap_org[] PROGMEM = "42:94:24:9c:7b:e9:07:bf:b8:fc:ac:61:cb:c7:3d:12:1c:e5:16:e6";
const char pubkey___openweathermap_org[] PROGMEM = R"PUBKEY(
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2DMTq6QbiQ6N/PK6u6dv
8J1w5/w/GLm1d7J3daL80/15qRlsxUEpM78/OWmEs60kKSfyOVyxOHrVoXMfEhIx
ATdYQtRtN2JQEFYDkRauvVgr5eXQO2EJZXBZUb2C0dLFMD2WtrQGl7059kCOBlA/
vX2+uTIQwFx/qZyVKkhzgdthtoDQ5jDzx7scDM0U9c/be/aWNPzoJV1HK37luC0n
HUyT0zDpXMt82DgoCRix9z9RzDNkyjsPW2qP/pOERpXk0z49jOFqtUxTtR9HfbKo
eQ/RobxD2fG5P1cfunZ2lU3lyl5PeKbmMlSdSlci4OuileGdauTqgU254X7bB/9i
TQIDAQAB
-----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 api.openweathermap.org:443
////////////////////////////////////////////////////////////

#endif

17 changes: 15 additions & 2 deletions platformio/include/client_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,26 @@
#define __CLIENT_UTILS_H__

#include <Arduino.h>
#include "api_response.h"
#include "config.h"
#ifdef USE_HTTP
#include <WiFiClient.h>
#else
#include <WiFiClientSecure.h>
#endif

wl_status_t startWiFi(int &wifiRSSI);
void killWiFi();
bool setupTime(tm *timeInfo);
bool printLocalTime(tm *timeInfo);
int getOWMonecall(WiFiClient &client, owm_resp_onecall_t &r);
int getOWMairpollution(WiFiClient &client, owm_resp_air_pollution_t &r);
#ifdef USE_HTTP
int getOWMonecall(WiFiClient &client, owm_resp_onecall_t &r);
int getOWMairpollution(WiFiClient &client, owm_resp_air_pollution_t &r);
#else
int getOWMonecall(WiFiClientSecure &client, owm_resp_onecall_t &r);
int getOWMairpollution(WiFiClientSecure &client, owm_resp_air_pollution_t &r);
#endif


#endif

Loading

0 comments on commit 6921fd5

Please sign in to comment.