Added TLS CA validation option as an alternative to Fingerprint validation

This commit is contained in:
Stephan Hadinger 2019-06-10 19:58:57 +02:00
parent 006462f17e
commit 844840a851
6 changed files with 311 additions and 271 deletions

View File

@ -38,7 +38,7 @@ uint32_t *stack_thunk_light_save = NULL; /* Saved A1 while in BearSSL */
uint32_t stack_thunk_light_refcnt = 0; uint32_t stack_thunk_light_refcnt = 0;
//#define _stackSize (5600/4) //#define _stackSize (5600/4)
#define _stackSize (4600/4) // using a light version of bearssl we can save 1KB #define _stackSize (4800/4) // using a light version of bearssl we can save 1KB
#define _stackPaint 0xdeadbeef #define _stackPaint 0xdeadbeef
/* Add a reference, and allocate the stack if necessary */ /* Add a reference, and allocate the stack if necessary */

View File

@ -45,7 +45,7 @@ extern "C" {
#include "my_user_config.h" #include "my_user_config.h"
//#define DEBUG_TLS #define DEBUG_TLS
#ifdef DEBUG_TLS #ifdef DEBUG_TLS
#include "coredecls.h" #include "coredecls.h"
@ -182,6 +182,9 @@ void WiFiClientSecure_light::_clear() {
_fingerprint_any = true; // by default accept all fingerprints _fingerprint_any = true; // by default accept all fingerprints
_fingerprint1 = nullptr; _fingerprint1 = nullptr;
_fingerprint2 = nullptr; _fingerprint2 = nullptr;
_chain_P = nullptr;
_sk_ec_P = nullptr;
_ta_P = nullptr;
} }
// Constructor // Constructor
@ -218,16 +221,15 @@ void WiFiClientSecure_light::allocateBuffers(void) {
void WiFiClientSecure_light::setClientECCert(const br_x509_certificate *cert, const br_ec_private_key *sk, void WiFiClientSecure_light::setClientECCert(const br_x509_certificate *cert, const br_ec_private_key *sk,
unsigned allowed_usages, unsigned cert_issuer_key_type) { unsigned allowed_usages, unsigned cert_issuer_key_type) {
_chain_P = cert; _chain_P = cert;
_chain.data_len = _chain_P->data_len;
_chain.data = nullptr;
_sk_ec_P = sk; _sk_ec_P = sk;
_sk_ec.curve = _sk_ec_P->curve;
_sk_ec.xlen = _sk_ec_P->xlen;
_sk_ec.x = nullptr;
_allowed_usages = allowed_usages; _allowed_usages = allowed_usages;
_cert_issuer_key_type = cert_issuer_key_type; _cert_issuer_key_type = cert_issuer_key_type;
} }
void WiFiClientSecure_light::setTrustAnchor(const br_x509_trust_anchor *ta) {
_ta_P = ta;
}
void WiFiClientSecure_light::setBufferSizes(int recv, int xmit) { void WiFiClientSecure_light::setBufferSizes(int recv, int xmit) {
// Following constants taken from bearssl/src/ssl/ssl_engine.c (not exported unfortunately) // Following constants taken from bearssl/src/ssl/ssl_engine.c (not exported unfortunately)
const int MAX_OUT_OVERHEAD = 85; const int MAX_OUT_OVERHEAD = 85;
@ -781,121 +783,160 @@ extern "C" {
// Returns if the SSL handshake succeeded. // Returns if the SSL handshake succeeded.
bool WiFiClientSecure_light::_connectSSL(const char* hostName) { bool WiFiClientSecure_light::_connectSSL(const char* hostName) {
#ifdef USE_MQTT_AWS_IOT #ifdef USE_MQTT_AWS_IOT
br_ec_private_key sk_ec; br_ec_private_key sk_ec = {0, nullptr, 0};
br_x509_certificate chain; br_x509_certificate chain = {nullptr, 0};
#ifdef USE_MQTT_AWS_IOT_SKEY_ON_STACK if ((!_chain_P) || (!_sk_ec_P)) {
unsigned char chain_data[_chain_P->data_len]; setLastError(ERR_MISSING_EC_KEY);
unsigned char sk_data[_sk_ec_P->xlen]; return false;
#endif }
#endif #endif
// Validation context, either full CA validation or checking only fingerprints
#ifdef USE_MQTT_TLS_CA_CERT
br_x509_minimal_context *x509_minimal;
br_x509_trust_anchor ta; // = {{nullptr,0},0,{0,{.rsa={nullptr,0,nullptr,0}}}};
memset(&ta, 0, sizeof(ta));
if (!_ta_P) {
setLastError(ERR_MISSING_CA);
return false;
}
#else
br_x509_pubkeyfingerprint_context *x509_insecure; br_x509_pubkeyfingerprint_context *x509_insecure;
#endif
LOG_HEAP_SIZE("_connectSSL.start"); LOG_HEAP_SIZE("_connectSSL.start");
do { // used to exit on Out of Memory error and keep all cleanup code at the same place
// ============================================================
// allocate Thunk stack, move to alternate stack and initialize
stack_thunk_light_add_ref(); stack_thunk_light_add_ref();
LOG_HEAP_SIZE("Thunk allocated"); LOG_HEAP_SIZE("Thunk allocated");
DEBUG_BSSL("_connectSSL: start connection\n"); DEBUG_BSSL("_connectSSL: start connection\n");
_freeSSL(); _freeSSL();
clearLastError(); clearLastError();
if (!stack_thunk_light_get_stack_bot()) break;
// ============================================================
// Copy server CA from PROGMEM to RAM
#ifdef USE_MQTT_TLS_CA_CERT
memcpy_P(&ta, _ta_P, sizeof(ta)); // copy the whole structure first
unsigned char rsa_e[_ta_P->pkey.key.rsa.elen]; // it's only 3 bytes long, spare the malloc
ta.pkey.key.rsa.e = rsa_e;
ta.dn.data = (unsigned char *) malloc(ta.dn.len);
if (!ta.dn.data) break;
ta.pkey.key.rsa.n = (unsigned char *) malloc(ta.pkey.key.rsa.nlen);
if (!ta.pkey.key.rsa.n) break;
memcpy_P(ta.dn.data, _ta_P->dn.data, ta.dn.len);
memcpy_P(ta.pkey.key.rsa.n, _ta_P->pkey.key.rsa.n, ta.pkey.key.rsa.nlen);
memcpy_P(rsa_e, _ta_P->pkey.key.rsa.e, ta.pkey.key.rsa.elen);
#endif
_ctx_present = true; _ctx_present = true;
_eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr _eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
br_ssl_client_base_init(_sc.get()); br_ssl_client_base_init(_sc.get());
// ============================================================
// Allocatte and initialize Decoder Context
LOG_HEAP_SIZE("_connectSSL before DecoderContext allocation"); LOG_HEAP_SIZE("_connectSSL before DecoderContext allocation");
// Only failure possible in the installation is OOM // Only failure possible in the installation is OOM
#ifdef USE_MQTT_TLS_CA_CERT
x509_minimal = (br_x509_minimal_context*) malloc(sizeof(br_x509_minimal_context));
if (!x509_minimal) break;
br_x509_minimal_init(x509_minimal, &br_sha256_vtable, &ta, 1);
br_x509_minimal_set_rsa(x509_minimal, br_ssl_engine_get_rsavrfy(_eng));
br_x509_minimal_set_hash(x509_minimal, br_sha256_ID, &br_sha256_vtable);
br_ssl_engine_set_x509(_eng, &x509_minimal->vtable);
#else
x509_insecure = (br_x509_pubkeyfingerprint_context*) malloc(sizeof(br_x509_pubkeyfingerprint_context)); x509_insecure = (br_x509_pubkeyfingerprint_context*) malloc(sizeof(br_x509_pubkeyfingerprint_context));
//x509_insecure = std::unique_ptr<br_x509_pubkeyfingerprint_context>(new br_x509_pubkeyfingerprint_context);
br_x509_pubkeyfingerprint_init(x509_insecure, _fingerprint1, _fingerprint2, if (!x509_insecure) break;
_recv_fingerprint, _fingerprint_any); br_x509_pubkeyfingerprint_init(x509_insecure, _fingerprint1, _fingerprint2, _recv_fingerprint, _fingerprint_any);
br_ssl_engine_set_x509(_eng, &x509_insecure->vtable); br_ssl_engine_set_x509(_eng, &x509_insecure->vtable);
#endif
LOG_HEAP_SIZE("_connectSSL after DecoderContext allocation");
// ============================================================
// Set send/receive buffers
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size); br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
LOG_HEAP_SIZE("_connectSSL after PrivKey allocation"); // ============================================================
#ifdef USE_MQTT_AWS_IOT // allocate Private key if needed, only if USE_MQTT_AWS_IOT
LOG_HEAP_SIZE("_connectSSL before PrivKey allocation");
#ifdef USE_MQTT_AWS_IOT
// allocate Private key and client certificate // allocate Private key and client certificate
chain.data_len = _chain_P->data_len; chain.data_len = _chain_P->data_len;
#ifdef USE_MQTT_AWS_IOT_SKEY_ON_STACK // allocate on stack
chain.data = &chain_data[0];
#else // allocate with malloc
chain.data = (unsigned char *) malloc(chain.data_len); chain.data = (unsigned char *) malloc(chain.data_len);
#endif if (!chain.data) break;
if (chain.data) memcpy_P(chain.data, _chain_P->data, chain.data_len); memcpy_P(chain.data, _chain_P->data, chain.data_len);
sk_ec.curve = _sk_ec_P->curve; sk_ec.curve = _sk_ec_P->curve;
sk_ec.xlen = _sk_ec_P->xlen; sk_ec.xlen = _sk_ec_P->xlen;
#ifdef USE_MQTT_AWS_IOT_SKEY_ON_STACK
sk_ec.x = &sk_data[0];
#else // USE_MQTT_AWS_IOT_SKEY_ON_STACK
sk_ec.x = (unsigned char *) malloc(sk_ec.xlen); sk_ec.x = (unsigned char *) malloc(sk_ec.xlen);
#endif // USE_MQTT_AWS_IOT_SKEY_ON_STACK if (!sk_ec.x) break;
if (sk_ec.x) memcpy_P(sk_ec.x, _sk_ec_P->x, sk_ec.xlen); memcpy_P(sk_ec.x, _sk_ec_P->x, sk_ec.xlen);
LOG_HEAP_SIZE("_connectSSL after PrivKey allocation"); LOG_HEAP_SIZE("_connectSSL after PrivKey allocation");
#endif // USE_MQTT_AWS_IOT
// check if memory was correctly allocated // ============================================================
#ifdef USE_MQTT_AWS_IOT // Set the EC Private Key, only USE_MQTT_AWS_IOT
if ((!stack_thunk_light_get_stack_bot()) || (!x509_insecure) ||
(!chain.data) || (!sk_ec.x)) {
#ifndef USE_MQTT_AWS_IOT_SKEY_ON_STACK
free(chain.data);
free(sk_ec.x);
#endif // USE_MQTT_AWS_IOT_SKEY_ON_STACK
#else
if ((!stack_thunk_light_get_stack_bot()) || (!x509_insecure)) {
#endif // USE_MQTT_AWS_IOT
// memory allocation problem
setLastError(ERR_OOM);
free(x509_insecure);
stack_thunk_light_del_ref();
DEBUG_BSSL("_connectSSL: Out of memory\n");
return false;
}
#ifdef USE_MQTT_AWS_IOT
// limited to P256 curve // limited to P256 curve
br_ssl_client_set_single_ec(_sc.get(), &chain, 1, br_ssl_client_set_single_ec(_sc.get(), &chain, 1,
&sk_ec, _allowed_usages, &sk_ec, _allowed_usages,
_cert_issuer_key_type, &br_ec_p256_m15, br_ecdsa_sign_asn1_get_default()); _cert_issuer_key_type, &br_ec_p256_m15, br_ecdsa_sign_asn1_get_default());
#endif #endif // USE_MQTT_AWS_IOT
if (!br_ssl_client_reset(_sc.get(), hostName, 0)) { // ============================================================
#ifdef USE_MQTT_AWS_IOT // Start TLS connection, ALL
#ifndef USE_MQTT_AWS_IOT_SKEY_ON_STACK if (!br_ssl_client_reset(_sc.get(), hostName, 0)) break;
free(chain.data);
free(sk_ec.x);
#endif
#endif
free(x509_insecure);
stack_thunk_light_del_ref();
_freeSSL();
DEBUG_BSSL("_connectSSL: Can't reset client\n");
return false;
}
auto ret = _wait_for_handshake(); auto ret = _wait_for_handshake();
#ifdef DEBUG_ESP_SSL #ifdef DEBUG_ESP_SSL
if (!ret) { if (!ret) {
DEBUG_BSSL("Couldn't connect. Error = %d\n", getLastError()); DEBUG_BSSL("Couldn't connect. Error = %d\n", getLastError());
} else { } else {
DEBUG_BSSL("Connected! MFLNStatus = %d\n", getMFLNStatus()); DEBUG_BSSL("Connected! MFLNStatus = %d\n", getMFLNStatus());
} }
#endif #endif
LOG_HEAP_SIZE("_connectSSL.end"); LOG_HEAP_SIZE("_connectSSL.end");
stack_thunk_light_del_ref(); stack_thunk_light_del_ref();
//stack_thunk_light_repaint(); //stack_thunk_light_repaint();
LOG_HEAP_SIZE("_connectSSL.end, freeing StackThunk"); LOG_HEAP_SIZE("_connectSSL.end, freeing StackThunk");
#if defined(USE_MQTT_AWS_IOT)
free(chain.data);
free(sk_ec.x);
#endif
#ifdef USE_MQTT_TLS_CA_CERT
free(x509_minimal);
free(ta.dn.data);
free(ta.pkey.key.rsa.n);
#else
free(x509_insecure);
#endif
LOG_HEAP_SIZE("_connectSSL after release of Priv Key");
return ret;
} while (0);
// ============================================================
// if we arrived here, this means we had an OOM error, cleaning up
setLastError(ERR_OOM);
DEBUG_BSSL("_connectSSL: Out of memory\n");
stack_thunk_light_del_ref();
#ifdef USE_MQTT_AWS_IOT #ifdef USE_MQTT_AWS_IOT
#ifndef USE_MQTT_AWS_IOT_SKEY_ON_STACK
free(chain.data); free(chain.data);
free(sk_ec.x); free(sk_ec.x);
#endif #endif
#endif #ifdef USE_MQTT_TLS_CA_CERT
free(x509_minimal);
free(ta.dn.data);
free(ta.pkey.key.rsa.n);
#else
free(x509_insecure); free(x509_insecure);
LOG_HEAP_SIZE("_connectSSL after release of Priv Key"); #endif
return ret; LOG_HEAP_SIZE("_connectSSL clean_on_error");
return false;
} }
}; };

View File

@ -74,6 +74,8 @@ class WiFiClientSecure_light : public WiFiClient {
void setClientECCert(const br_x509_certificate *cert, const br_ec_private_key *sk, void setClientECCert(const br_x509_certificate *cert, const br_ec_private_key *sk,
unsigned allowed_usages, unsigned cert_issuer_key_type); unsigned allowed_usages, unsigned cert_issuer_key_type);
void setTrustAnchor(const br_x509_trust_anchor *ta);
// Sets the requested buffer size for transmit and receive // Sets the requested buffer size for transmit and receive
void setBufferSizes(int recv, int xmit); void setBufferSizes(int recv, int xmit);
@ -128,10 +130,9 @@ class WiFiClientSecure_light : public WiFiClient {
bool _wait_for_handshake(); // Sets and return the _handshake_done after connecting bool _wait_for_handshake(); // Sets and return the _handshake_done after connecting
// Optional client certificate // Optional client certificate
br_x509_certificate _chain; // local RAM copy
const br_x509_certificate *_chain_P; // PROGMEM certificate const br_x509_certificate *_chain_P; // PROGMEM certificate
br_ec_private_key _sk_ec;
const br_ec_private_key *_sk_ec_P; // PROGMEM private key const br_ec_private_key *_sk_ec_P; // PROGMEM private key
const br_x509_trust_anchor *_ta_P; // PROGMEM server CA
unsigned _allowed_usages; unsigned _allowed_usages;
unsigned _cert_issuer_key_type; unsigned _cert_issuer_key_type;
@ -140,6 +141,72 @@ class WiFiClientSecure_light : public WiFiClient {
#define ERR_OOM -1000 #define ERR_OOM -1000
#define ERR_CANT_RESOLVE_IP -1001 #define ERR_CANT_RESOLVE_IP -1001
#define ERR_TCP_CONNECT -1002 #define ERR_TCP_CONNECT -1002
#define ERR_MISSING_EC_KEY -1003
#define ERR_MISSING_CA -1004
// For reference, BearSSL error codes:
// #define BR_ERR_OK 0
// #define BR_ERR_BAD_PARAM 1
// #define BR_ERR_BAD_STATE 2
// #define BR_ERR_UNSUPPORTED_VERSION 3
// #define BR_ERR_BAD_VERSION 4
// #define BR_ERR_BAD_LENGTH 5
// #define BR_ERR_TOO_LARGE 6
// #define BR_ERR_BAD_MAC 7
// #define BR_ERR_NO_RANDOM 8
// #define BR_ERR_UNKNOWN_TYPE 9
// #define BR_ERR_UNEXPECTED 10
// #define BR_ERR_BAD_CCS 12
// #define BR_ERR_BAD_ALERT 13
// #define BR_ERR_BAD_HANDSHAKE 14
// #define BR_ERR_OVERSIZED_ID 15
// #define BR_ERR_BAD_CIPHER_SUITE 16
// #define BR_ERR_BAD_COMPRESSION 17
// #define BR_ERR_BAD_FRAGLEN 18
// #define BR_ERR_BAD_SECRENEG 19
// #define BR_ERR_EXTRA_EXTENSION 20
// #define BR_ERR_BAD_SNI 21
// #define BR_ERR_BAD_HELLO_DONE 22
// #define BR_ERR_LIMIT_EXCEEDED 23
// #define BR_ERR_BAD_FINISHED 24
// #define BR_ERR_RESUME_MISMATCH 25
// #define BR_ERR_INVALID_ALGORITHM 26
// #define BR_ERR_BAD_SIGNATURE 27
// #define BR_ERR_WRONG_KEY_USAGE 28
// #define BR_ERR_NO_CLIENT_AUTH 29
// #define BR_ERR_IO 31
// #define BR_ERR_RECV_FATAL_ALERT 256
// #define BR_ERR_SEND_FATAL_ALERT 512
// #define BR_ERR_X509_OK 32
// #define BR_ERR_X509_INVALID_VALUE 33
// #define BR_ERR_X509_TRUNCATED 34
// #define BR_ERR_X509_EMPTY_CHAIN 35
// #define BR_ERR_X509_INNER_TRUNC 36
// #define BR_ERR_X509_BAD_TAG_CLASS 37
// #define BR_ERR_X509_BAD_TAG_VALUE 38
// #define BR_ERR_X509_INDEFINITE_LENGTH 39
// #define BR_ERR_X509_EXTRA_ELEMENT 40
// #define BR_ERR_X509_UNEXPECTED 41
// #define BR_ERR_X509_NOT_CONSTRUCTED 42
// #define BR_ERR_X509_NOT_PRIMITIVE 43
// #define BR_ERR_X509_PARTIAL_BYTE 44
// #define BR_ERR_X509_BAD_BOOLEAN 45
// #define BR_ERR_X509_OVERFLOW 46
// #define BR_ERR_X509_BAD_DN 47
// #define BR_ERR_X509_BAD_TIME 48
// #define BR_ERR_X509_UNSUPPORTED 49
// #define BR_ERR_X509_LIMIT_EXCEEDED 50
// #define BR_ERR_X509_WRONG_KEY_TYPE 51
// #define BR_ERR_X509_BAD_SIGNATURE 52
// #define BR_ERR_X509_TIME_UNKNOWN 53
// #define BR_ERR_X509_EXPIRED 54
// #define BR_ERR_X509_DN_MISMATCH 55
// #define BR_ERR_X509_BAD_SERVER_NAME 56
// #define BR_ERR_X509_CRITICAL_EXTENSION 57
// #define BR_ERR_X509_NOT_CA 58
// #define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59
// #define BR_ERR_X509_WEAK_PUBLIC_KEY 60
// #define BR_ERR_X509_NOT_TRUSTED 62
}; };

View File

@ -264,12 +264,12 @@
// -- MQTT - TLS - AWS IoT ---------------------------------- // -- MQTT - TLS - AWS IoT ----------------------------------
//#define USE_MQTT_TLS // Use TLS for MQTT connection (+56.7k code, +6.0k mem and +6.6k additional during connection handshake) //#define USE_MQTT_TLS // Use TLS for MQTT connection (+56.7k code, +6.0k mem and +6.6k additional during connection handshake)
//#define USE_MQTT_TLS_CA_CERT // Force full CA validation instead of fingerprints, uses more memory and slower, but simpler to use
//#define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+56.7k code, +6.0k mem and +6.6k additional during connection handshake) //#define USE_MQTT_AWS_IOT // Enable MQTT for AWS IoT - requires a private key (+56.7k code, +6.0k mem and +6.6k additional during connection handshake)
// note: enabling USE_MQTT_AWS_IOT autoamtically enables USE_MQTT_TLS // note: enabling USE_MQTT_AWS_IOT autoamtically enables USE_MQTT_TLS
// you need to generate a private key + certificate per device // you need to generate a private key + certificate per device
// and update 'sonoff/sonoff_aws_iot.cpp' // and update 'sonoff/sonoff_aws_iot.cpp'
// Full documentation here: https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT // Full documentation here: https://github.com/arendst/Sonoff-Tasmota/wiki/AWS-IoT
#define USE_MQTT_AWS_IOT_SKEY_ON_STACK // copy private key+cert on stack rather than on heap, don't disable unless you see crashes during connections
// -- KNX IP Protocol ----------------------------- // -- KNX IP Protocol -----------------------------

View File

@ -22,39 +22,30 @@
// However, the CA are available below for future use if it appears to be useful // However, the CA are available below for future use if it appears to be useful
#ifdef USE_MQTT_TLS_CA_CERT #ifdef USE_MQTT_TLS_CA_CERT
#ifndef USE_MQTT_AWS_IOT
/*********************************************************************************************\ /*********************************************************************************************\
* LetsEncrypt IdenTrust DST Root CA X3 certificate, RSA 2048 bits SHA 256, valid until 20210417 * LetsEncrypt IdenTrust DST Root CA X3 certificate, RSA 2048 bits SHA 256, valid until 20210417
* *
* https://letsencrypt.org/certificates/ * https://letsencrypt.org/certificates/
* Downloaded from https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt * Downloaded from https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt
* *
* to convert do: bearssl chain lets-encrypt-x3-cross-signed.pem.txt * to convert do: bearssl ta lets-encrypt-x3-cross-signed.pem.txt
* then copy and paste below, chain the generic names to the same as below * then copy and paste below, chain the generic names to the same as below
* remove static and add PROGMEM * remove static and add PROGMEM
\*********************************************************************************************/ \*********************************************************************************************/
const unsigned char PROGMEM LetsencryptRootCA3[] = { static const unsigned char PROGMEM TA0_DN[] = {
0x30, 0x82, 0x04, 0x92, 0x30, 0x82, 0x03, 0x7A, 0xA0, 0x03, 0x02, 0x01, 0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x02, 0x10, 0x0A, 0x01, 0x41, 0x42, 0x00, 0x00, 0x01, 0x53, 0x85, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x73, 0x6A, 0x0B, 0x85, 0xEC, 0xA7, 0x08, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x13, 0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72,
0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x3F, 0x79, 0x70, 0x74, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03,
0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x44, 0x13, 0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72,
0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20, 0x53, 0x69, 0x67, 0x6E, 0x61, 0x79, 0x70, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74,
0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x79, 0x20, 0x58, 0x33
0x6F, 0x2E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, };
0x0E, 0x44, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41,
0x20, 0x58, 0x33, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x30, 0x33, 0x31, static const unsigned char PROGMEM TA0_RSA_N[] = {
0x37, 0x31, 0x36, 0x34, 0x30, 0x34, 0x36, 0x5A, 0x17, 0x0D, 0x32, 0x31,
0x30, 0x33, 0x31, 0x37, 0x31, 0x36, 0x34, 0x30, 0x34, 0x36, 0x5A, 0x30,
0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13,
0x0D, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, 0x79,
0x70, 0x74, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x1A, 0x4C, 0x65, 0x74, 0x27, 0x73, 0x20, 0x45, 0x6E, 0x63, 0x72, 0x79,
0x70, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79,
0x20, 0x58, 0x33, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A,
0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00,
0x9C, 0xD3, 0x0C, 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, 0x37, 0x9C, 0xD3, 0x0C, 0xF0, 0x5A, 0xE5, 0x2E, 0x47, 0xB7, 0x72, 0x5D, 0x37,
0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, 0x35, 0x26, 0x19, 0x25, 0xE1, 0x83, 0xB3, 0x68, 0x63, 0x30, 0xEA, 0xD7, 0x35, 0x26, 0x19, 0x25, 0xE1,
0xBD, 0xBE, 0x35, 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, 0x05, 0xBD, 0xBE, 0x35, 0xF1, 0x70, 0x92, 0x2F, 0xB7, 0xB8, 0x4B, 0x41, 0x05,
@ -76,71 +67,28 @@ const unsigned char PROGMEM LetsencryptRootCA3[] = {
0xC3, 0x30, 0x7F, 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, 0xE3, 0xC3, 0x30, 0x7F, 0xA2, 0x79, 0x31, 0x13, 0x3D, 0x2D, 0x36, 0xF8, 0xE3,
0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, 0xC5, 0xAF, 0xC4, 0x8D, 0x0D, 0xFC, 0xF2, 0x33, 0x6A, 0xB9, 0x39, 0x31, 0xC5, 0xAF, 0xC4, 0x8D, 0x0D,
0x1D, 0x64, 0x16, 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, 0xC0, 0x1D, 0x64, 0x16, 0x33, 0xAA, 0xFA, 0x84, 0x29, 0xB6, 0xD4, 0x0B, 0xC0,
0xD8, 0x7D, 0xC3, 0x93, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0xD8, 0x7D, 0xC3, 0x93
0x7D, 0x30, 0x82, 0x01, 0x79, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13,
0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01,
0x00, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04,
0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x7F, 0x06, 0x08, 0x2B, 0x06, 0x01,
0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x32, 0x06,
0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x26, 0x68,
0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x69, 0x73, 0x72, 0x67, 0x2E, 0x74,
0x72, 0x75, 0x73, 0x74, 0x69, 0x64, 0x2E, 0x6F, 0x63, 0x73, 0x70, 0x2E,
0x69, 0x64, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x63, 0x6F,
0x6D, 0x30, 0x3B, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
0x02, 0x86, 0x2F, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x61, 0x70,
0x70, 0x73, 0x2E, 0x69, 0x64, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74,
0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x72, 0x6F, 0x6F, 0x74, 0x73, 0x2F, 0x64,
0x73, 0x74, 0x72, 0x6F, 0x6F, 0x74, 0x63, 0x61, 0x78, 0x33, 0x2E, 0x70,
0x37, 0x63, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30,
0x16, 0x80, 0x14, 0xC4, 0xA7, 0xB1, 0xA4, 0x7B, 0x2C, 0x71, 0xFA, 0xDB,
0xE1, 0x4B, 0x90, 0x75, 0xFF, 0xC4, 0x15, 0x60, 0x85, 0x89, 0x10, 0x30,
0x54, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x4D, 0x30, 0x4B, 0x30, 0x08,
0x06, 0x06, 0x67, 0x81, 0x0C, 0x01, 0x02, 0x01, 0x30, 0x3F, 0x06, 0x0B,
0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xDF, 0x13, 0x01, 0x01, 0x01, 0x30,
0x30, 0x30, 0x2E, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02,
0x01, 0x16, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x70,
0x73, 0x2E, 0x72, 0x6F, 0x6F, 0x74, 0x2D, 0x78, 0x31, 0x2E, 0x6C, 0x65,
0x74, 0x73, 0x65, 0x6E, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2E, 0x6F, 0x72,
0x67, 0x30, 0x3C, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x35, 0x30, 0x33,
0x30, 0x31, 0xA0, 0x2F, 0xA0, 0x2D, 0x86, 0x2B, 0x68, 0x74, 0x74, 0x70,
0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x69, 0x64, 0x65, 0x6E, 0x74,
0x72, 0x75, 0x73, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x44, 0x53, 0x54,
0x52, 0x4F, 0x4F, 0x54, 0x43, 0x41, 0x58, 0x33, 0x43, 0x52, 0x4C, 0x2E,
0x63, 0x72, 0x6C, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16,
0x04, 0x14, 0xA8, 0x4A, 0x6A, 0x63, 0x04, 0x7D, 0xDD, 0xBA, 0xE6, 0xD1,
0x39, 0xB7, 0xA6, 0x45, 0x65, 0xEF, 0xF3, 0xA8, 0xEC, 0xA1, 0x30, 0x0D,
0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05,
0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xDD, 0x33, 0xD7, 0x11, 0xF3, 0x63,
0x58, 0x38, 0xDD, 0x18, 0x15, 0xFB, 0x09, 0x55, 0xBE, 0x76, 0x56, 0xB9,
0x70, 0x48, 0xA5, 0x69, 0x47, 0x27, 0x7B, 0xC2, 0x24, 0x08, 0x92, 0xF1,
0x5A, 0x1F, 0x4A, 0x12, 0x29, 0x37, 0x24, 0x74, 0x51, 0x1C, 0x62, 0x68,
0xB8, 0xCD, 0x95, 0x70, 0x67, 0xE5, 0xF7, 0xA4, 0xBC, 0x4E, 0x28, 0x51,
0xCD, 0x9B, 0xE8, 0xAE, 0x87, 0x9D, 0xEA, 0xD8, 0xBA, 0x5A, 0xA1, 0x01,
0x9A, 0xDC, 0xF0, 0xDD, 0x6A, 0x1D, 0x6A, 0xD8, 0x3E, 0x57, 0x23, 0x9E,
0xA6, 0x1E, 0x04, 0x62, 0x9A, 0xFF, 0xD7, 0x05, 0xCA, 0xB7, 0x1F, 0x3F,
0xC0, 0x0A, 0x48, 0xBC, 0x94, 0xB0, 0xB6, 0x65, 0x62, 0xE0, 0xC1, 0x54,
0xE5, 0xA3, 0x2A, 0xAD, 0x20, 0xC4, 0xE9, 0xE6, 0xBB, 0xDC, 0xC8, 0xF6,
0xB5, 0xC3, 0x32, 0xA3, 0x98, 0xCC, 0x77, 0xA8, 0xE6, 0x79, 0x65, 0x07,
0x2B, 0xCB, 0x28, 0xFE, 0x3A, 0x16, 0x52, 0x81, 0xCE, 0x52, 0x0C, 0x2E,
0x5F, 0x83, 0xE8, 0xD5, 0x06, 0x33, 0xFB, 0x77, 0x6C, 0xCE, 0x40, 0xEA,
0x32, 0x9E, 0x1F, 0x92, 0x5C, 0x41, 0xC1, 0x74, 0x6C, 0x5B, 0x5D, 0x0A,
0x5F, 0x33, 0xCC, 0x4D, 0x9F, 0xAC, 0x38, 0xF0, 0x2F, 0x7B, 0x2C, 0x62,
0x9D, 0xD9, 0xA3, 0x91, 0x6F, 0x25, 0x1B, 0x2F, 0x90, 0xB1, 0x19, 0x46,
0x3D, 0xF6, 0x7E, 0x1B, 0xA6, 0x7A, 0x87, 0xB9, 0xA3, 0x7A, 0x6D, 0x18,
0xFA, 0x25, 0xA5, 0x91, 0x87, 0x15, 0xE0, 0xF2, 0x16, 0x2F, 0x58, 0xB0,
0x06, 0x2F, 0x2C, 0x68, 0x26, 0xC6, 0x4B, 0x98, 0xCD, 0xDA, 0x9F, 0x0C,
0xF9, 0x7F, 0x90, 0xED, 0x43, 0x4A, 0x12, 0x44, 0x4E, 0x6F, 0x73, 0x7A,
0x28, 0xEA, 0xA4, 0xAA, 0x6E, 0x7B, 0x4C, 0x7D, 0x87, 0xDD, 0xE0, 0xC9,
0x02, 0x44, 0xA7, 0x87, 0xAF, 0xC3, 0x34, 0x5B, 0xB4, 0x42
}; };
const br_x509_certificate PROGMEM LetsencryptRootCA3_chain[] = { static const unsigned char TA0_RSA_E[] = {
{ (unsigned char *)LetsencryptRootCA3, sizeof LetsencryptRootCA3 } 0x01, 0x00, 0x01
}; };
#define LETSENCRYPTROOTCA3LEN 1 static const br_x509_trust_anchor PROGMEM LetsEncryptX3CrossSigned_TA = {
{ (unsigned char *)TA0_DN, sizeof TA0_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N,
(unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E,
} }
}
};
#endif // USE_MQTT_TLS_CA_CERT #define TAs_NUM 1
#endif // not USE_MQTT_AWS_IOT
#ifdef USE_MQTT_AWS_IOT #ifdef USE_MQTT_AWS_IOT
/*********************************************************************************************\ /*********************************************************************************************\
@ -149,88 +97,63 @@ const br_x509_certificate PROGMEM LetsencryptRootCA3_chain[] = {
* https://letsencrypt.org/certificates/ * https://letsencrypt.org/certificates/
* Downloaded from https://www.amazontrust.com/repository/AmazonRootCA1.pem * Downloaded from https://www.amazontrust.com/repository/AmazonRootCA1.pem
* *
* to convert do: bearssl chain AmazonRootCA1.pem * to convert do: bearssl ta AmazonRootCA1.pem
* then copy and paste below, chain the generic names to the same as below * then copy and paste below, chain the generic names to the same as below
* remove static and add PROGMEM * remove static and add PROGMEM
\*********************************************************************************************/ \*********************************************************************************************/
const unsigned char PROGMEM AmazonRootCA1[] = {
0x30, 0x82, 0x03, 0x41, 0x30, 0x82, 0x02, 0x29, 0xA0, 0x03, 0x02, 0x01, const unsigned char PROGMEM TA0_DN[] = {
0x02, 0x02, 0x13, 0x06, 0x6C, 0x9F, 0xCF, 0x99, 0xBF, 0x8C, 0x0A, 0x39, 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0xE2, 0xF0, 0x78, 0x8A, 0x43, 0xE6, 0x96, 0x36, 0x5B, 0xCA, 0x30, 0x0D, 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17,
0x00, 0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F,
0x13, 0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31
0x0A, 0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30,
0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A,
0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31,
0x30, 0x1E, 0x17, 0x0D, 0x31, 0x35, 0x30, 0x35, 0x32, 0x36, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x31, 0x31,
0x37, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x39, 0x31, 0x0B,
0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x06, 0x41, 0x6D,
0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x20, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30,
0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02,
0x82, 0x01, 0x01, 0x00, 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3,
0x71, 0xAF, 0x47, 0x80, 0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76,
0xF4, 0x99, 0x68, 0xF7, 0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F,
0xAC, 0x02, 0x2D, 0x86, 0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0,
0x36, 0xBA, 0x01, 0xBE, 0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C,
0xF4, 0xEE, 0x88, 0x23, 0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8,
0x49, 0x68, 0xB0, 0xDE, 0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4,
0xFE, 0x82, 0x36, 0xA5, 0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD,
0xB4, 0x16, 0xFA, 0x74, 0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0,
0x20, 0x50, 0x06, 0x6C, 0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC,
0x47, 0x19, 0x8F, 0x50, 0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8,
0xBA, 0xD5, 0xA9, 0xF9, 0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E,
0x6F, 0x89, 0xA3, 0x51, 0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA,
0x54, 0xEB, 0xA3, 0xC3, 0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30,
0x2D, 0x7D, 0x2D, 0x74, 0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4,
0x59, 0x6E, 0xBB, 0x73, 0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43,
0xFA, 0xB7, 0x1D, 0xAA, 0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B,
0xF7, 0x71, 0x5C, 0x5E, 0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A,
0xAE, 0x50, 0x38, 0x6F, 0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E,
0x54, 0xE1, 0x77, 0xE0, 0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F,
0x40, 0x20, 0x7F, 0x20, 0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26,
0x8E, 0x04, 0xAE, 0x6C, 0x9A, 0xC8, 0xAA, 0x0D, 0x02, 0x03, 0x01, 0x00,
0x01, 0xA3, 0x42, 0x30, 0x40, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13,
0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0E,
0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02,
0x01, 0x86, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04,
0x14, 0x84, 0x18, 0xCC, 0x85, 0x34, 0xEC, 0xBC, 0x0C, 0x94, 0x94, 0x2E,
0x08, 0x59, 0x9C, 0xC7, 0xB2, 0x10, 0x4E, 0x0A, 0x08, 0x30, 0x0D, 0x06,
0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00,
0x03, 0x82, 0x01, 0x01, 0x00, 0x98, 0xF2, 0x37, 0x5A, 0x41, 0x90, 0xA1,
0x1A, 0xC5, 0x76, 0x51, 0x28, 0x20, 0x36, 0x23, 0x0E, 0xAE, 0xE6, 0x28,
0xBB, 0xAA, 0xF8, 0x94, 0xAE, 0x48, 0xA4, 0x30, 0x7F, 0x1B, 0xFC, 0x24,
0x8D, 0x4B, 0xB4, 0xC8, 0xA1, 0x97, 0xF6, 0xB6, 0xF1, 0x7A, 0x70, 0xC8,
0x53, 0x93, 0xCC, 0x08, 0x28, 0xE3, 0x98, 0x25, 0xCF, 0x23, 0xA4, 0xF9,
0xDE, 0x21, 0xD3, 0x7C, 0x85, 0x09, 0xAD, 0x4E, 0x9A, 0x75, 0x3A, 0xC2,
0x0B, 0x6A, 0x89, 0x78, 0x76, 0x44, 0x47, 0x18, 0x65, 0x6C, 0x8D, 0x41,
0x8E, 0x3B, 0x7F, 0x9A, 0xCB, 0xF4, 0xB5, 0xA7, 0x50, 0xD7, 0x05, 0x2C,
0x37, 0xE8, 0x03, 0x4B, 0xAD, 0xE9, 0x61, 0xA0, 0x02, 0x6E, 0xF5, 0xF2,
0xF0, 0xC5, 0xB2, 0xED, 0x5B, 0xB7, 0xDC, 0xFA, 0x94, 0x5C, 0x77, 0x9E,
0x13, 0xA5, 0x7F, 0x52, 0xAD, 0x95, 0xF2, 0xF8, 0x93, 0x3B, 0xDE, 0x8B,
0x5C, 0x5B, 0xCA, 0x5A, 0x52, 0x5B, 0x60, 0xAF, 0x14, 0xF7, 0x4B, 0xEF,
0xA3, 0xFB, 0x9F, 0x40, 0x95, 0x6D, 0x31, 0x54, 0xFC, 0x42, 0xD3, 0xC7,
0x46, 0x1F, 0x23, 0xAD, 0xD9, 0x0F, 0x48, 0x70, 0x9A, 0xD9, 0x75, 0x78,
0x71, 0xD1, 0x72, 0x43, 0x34, 0x75, 0x6E, 0x57, 0x59, 0xC2, 0x02, 0x5C,
0x26, 0x60, 0x29, 0xCF, 0x23, 0x19, 0x16, 0x8E, 0x88, 0x43, 0xA5, 0xD4,
0xE4, 0xCB, 0x08, 0xFB, 0x23, 0x11, 0x43, 0xE8, 0x43, 0x29, 0x72, 0x62,
0xA1, 0xA9, 0x5D, 0x5E, 0x08, 0xD4, 0x90, 0xAE, 0xB8, 0xD8, 0xCE, 0x14,
0xC2, 0xD0, 0x55, 0xF2, 0x86, 0xF6, 0xC4, 0x93, 0x43, 0x77, 0x66, 0x61,
0xC0, 0xB9, 0xE8, 0x41, 0xD7, 0x97, 0x78, 0x60, 0x03, 0x6E, 0x4A, 0x72,
0xAE, 0xA5, 0xD1, 0x7D, 0xBA, 0x10, 0x9E, 0x86, 0x6C, 0x1B, 0x8A, 0xB9,
0x59, 0x33, 0xF8, 0xEB, 0xC4, 0x90, 0xBE, 0xF1, 0xB9
}; };
const br_x509_certificate PROGMEM AmazonRootCA1_chain[] = { const unsigned char PROGMEM TA0_RSA_N[] = {
{ (unsigned char *)AmazonRootCA1, sizeof AmazonRootCA1 } 0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80,
0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7,
0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86,
0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE,
0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23,
0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE,
0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5,
0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74,
0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C,
0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50,
0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9,
0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51,
0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3,
0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74,
0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73,
0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA,
0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E,
0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F,
0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0,
0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20,
0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C,
0x9A, 0xC8, 0xAA, 0x0D
}; };
#define AMAZONROOTCA1_LEN 1 static const unsigned char PROGMEM TA0_RSA_E[] = {
0x01, 0x00, 0x01
};
#endif const br_x509_trust_anchor PROGMEM AmazonRootCA1_TA = {
{ (unsigned char *)TA0_DN, sizeof TA0_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N,
(unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E,
} }
}
};
#define TAs_NUM 1
#endif // USE_MQTT_AWS_IOT
#endif // USE_MQTT_TLS_CA_CERT

View File

@ -127,8 +127,17 @@ void MqttInit(void) {
0xFFFF /* all usages, don't care */, 0); 0xFFFF /* all usages, don't care */, 0);
#endif #endif
#ifdef USE_MQTT_TLS_CA_CERT
tlsClient->setTrustAnchor(&LetsEncryptX3CrossSigned_TA);
#ifdef USE_MQTT_AWS_IOT
tlsClient->setTrustAnchor(&AmazonRootCA1_TA);
#else
// LETSENCRYPT CA TODO
#endif // USE_MQTT_AWS_IOT
#endif // USE_MQTT_TLS_CA_CERT
MqttClient.setClient(*tlsClient); MqttClient.setClient(*tlsClient);
#endif #endif // USE_MQTT_AWS_IOT
} }
@ -480,8 +489,8 @@ void MqttReconnect(void)
MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port);
#endif #endif
#ifdef USE_MQTT_TLS
uint32_t mqtt_connect_time = millis(); uint32_t mqtt_connect_time = millis();
#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT)
bool allow_all_fingerprints = false; bool allow_all_fingerprints = false;
bool learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00); bool learn_fingerprint1 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[0], 0x00);
bool learn_fingerprint2 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0x00); bool learn_fingerprint2 = is_fingerprint_mono_value(Settings.mqtt_fingerprint[1], 0x00);
@ -499,15 +508,16 @@ void MqttReconnect(void)
if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data, MQTT_CLEAN_SESSION)) { if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data, MQTT_CLEAN_SESSION)) {
#endif #endif
#ifdef USE_MQTT_TLS #ifdef USE_MQTT_TLS
// create a printable version of the fingerprint received
char buf_fingerprint[64];
to_hex((unsigned char *)tlsClient->getRecvPubKeyFingerprint(), 20, buf_fingerprint, 64);
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms"), millis() - mqtt_connect_time); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "TLS connected in %d ms"), millis() - mqtt_connect_time);
if (!tlsClient->getMFLNStatus()) { if (!tlsClient->getMFLNStatus()) {
AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("MFLN not supported by TLS server")); AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR("MFLN not supported by TLS server"));
} }
#ifndef USE_MQTT_TLS_CA_CERT // don't bother with fingerprints if using CA validation
// create a printable version of the fingerprint received
char buf_fingerprint[64];
to_hex((unsigned char *)tlsClient->getRecvPubKeyFingerprint(), 20, buf_fingerprint, 64);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_MQTT "Server fingerprint: %s"), buf_fingerprint);
if (learn_fingerprint1 || learn_fingerprint2) { if (learn_fingerprint1 || learn_fingerprint2) {
// we potentially need to learn the fingerprint just seen // we potentially need to learn the fingerprint just seen
bool fingerprint_matched = false; bool fingerprint_matched = false;
@ -531,6 +541,7 @@ void MqttReconnect(void)
SettingsSaveAll(); // save settings SettingsSaveAll(); // save settings
} }
} }
#endif // !USE_MQTT_TLS_CA_CERT
#endif // USE_MQTT_TLS #endif // USE_MQTT_TLS
MqttConnected(); MqttConnected();
} else { } else {
@ -639,7 +650,7 @@ bool MqttCommand(void)
} }
Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1)); Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1));
} }
#ifdef USE_MQTT_TLS #if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT)
else if ((CMND_MQTTFINGERPRINT == command_code) && (index > 0) && (index <= 2)) { else if ((CMND_MQTTFINGERPRINT == command_code) && (index > 0) && (index <= 2)) {
char fingerprint[60]; char fingerprint[60];
if ((data_len > 0) && (data_len < sizeof(fingerprint))) { if ((data_len > 0) && (data_len < sizeof(fingerprint))) {
@ -934,11 +945,9 @@ bool Xdrv02(uint8_t function)
if (Settings.flag.mqtt_enabled) { if (Settings.flag.mqtt_enabled) {
switch (function) { switch (function) {
#ifdef USE_MQTT_TLS
case FUNC_PRE_INIT: case FUNC_PRE_INIT:
MqttInit(); MqttInit();
break; break;
#endif
case FUNC_EVERY_50_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556 case FUNC_EVERY_50_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556
MqttClient.loop(); MqttClient.loop();
break; break;