From f2e43d11f1cf14bad159e25a760223b77e5331d8 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 13 Jul 2021 17:55:16 -0400 Subject: [PATCH 1/2] Add setKey API to set PEM private key and public cert for client connection --- keywords.txt | 1 + src/BearSSLClient.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++- src/BearSSLClient.h | 3 ++ 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/keywords.txt b/keywords.txt index 934dc5c..ebeb751 100644 --- a/keywords.txt +++ b/keywords.txt @@ -17,6 +17,7 @@ getTime KEYWORD2 onGetTime KEYWORD2 setEccSlot KEYWORD2 +setKey KEYWORD2 errorCode KEYWORD2 ######################################## diff --git a/src/BearSSLClient.cpp b/src/BearSSLClient.cpp index 5a2795d..c4fab48 100644 --- a/src/BearSSLClient.cpp +++ b/src/BearSSLClient.cpp @@ -48,6 +48,7 @@ BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs, _TAs(myTAs), _numTAs(myNumTAs), _noSNI(false), + _skeyDecoder(NULL), _ecChainLen(0) { #ifndef ARDUINO_DISABLE_ECCX08 @@ -75,6 +76,11 @@ BearSSLClient::~BearSSLClient() free(_ecCert[0].data); _ecCert[0].data = NULL; } + + if (_skeyDecoder) { + free(_skeyDecoder); + _skeyDecoder = NULL; + } } int BearSSLClient::connect(IPAddress ip, uint16_t port) @@ -303,6 +309,79 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const char cert[]) } } +void BearSSLClient::setKey(const char key[], const char cert[]) +{ + // try to decode the key and cert + br_pem_decoder_context pemDecoder; + + size_t keyLen = strlen(key); + size_t certLen = strlen(cert); + + br_pem_decoder_init(&pemDecoder); + + if (_skeyDecoder == NULL) { + _skeyDecoder = (br_skey_decoder_context*)malloc(sizeof(br_skey_decoder_context)); + } + + br_skey_decoder_init(_skeyDecoder); + + while (keyLen) { + size_t len = br_pem_decoder_push(&pemDecoder, key, keyLen); + + key += len; + keyLen -= len; + + switch (br_pem_decoder_event(&pemDecoder)) { + case BR_PEM_BEGIN_OBJ: + br_pem_decoder_setdest(&pemDecoder, BearSSLClient::clientAppendKey, this); + break; + + case BR_PEM_END_OBJ: + if (br_skey_decoder_last_error(_skeyDecoder) != 0) { + return; + } + break; + + case BR_PEM_ERROR: + return; + } + } + + // assume the decoded cert is 3/4 the length of the input + _ecCert[0].data = (unsigned char*)malloc(((certLen * 3) + 3) / 4); + _ecCert[0].data_len = 0; + _ecChainLen = 1; + + br_pem_decoder_init(&pemDecoder); + + while (certLen) { + size_t len = br_pem_decoder_push(&pemDecoder, cert, certLen); + + cert += len; + certLen -= len; + + switch (br_pem_decoder_event(&pemDecoder)) { + case BR_PEM_BEGIN_OBJ: + br_pem_decoder_setdest(&pemDecoder, BearSSLClient::clientAppendCert, this); + break; + + case BR_PEM_END_OBJ: + if (_ecCert[0].data_len) { + // done + _ecCertDynamic = true; + return; + } + break; + + case BR_PEM_ERROR: + // failure + free(_ecCert[0].data); + _ecCert[0].data = NULL; + return; + } + } +} + void BearSSLClient::setEccCertParent(const char cert[]) { // try to decode the cert @@ -383,7 +462,17 @@ int BearSSLClient::connectSSL(const char* host) // enable client auth if (_ecCert[0].data_len) { - br_ssl_client_set_single_ec(&_sc, _ecCert, _ecChainLen, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), _ecSign); + if (_skeyDecoder) { + int skeyType = br_skey_decoder_key_type(_skeyDecoder); + + if (skeyType == BR_KEYTYPE_EC) { + br_ssl_client_set_single_ec(&_sc, _ecCert, _ecChainLen, br_skey_decoder_get_ec(_skeyDecoder), BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), br_ecdsa_sign_asn1_get_default()); + } else if (skeyType == BR_KEYTYPE_RSA) { + br_ssl_client_set_single_rsa(&_sc, _ecCert, _ecChainLen, br_skey_decoder_get_rsa(_skeyDecoder), br_rsa_pkcs1_sign_get_default()); + } + } else { + br_ssl_client_set_single_ec(&_sc, _ecCert, _ecChainLen, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), _ecSign); + } } // set the hostname used for SNI @@ -486,6 +575,13 @@ void BearSSLClient::clientAppendCert(void *ctx, const void *data, size_t len) c->_ecCert[0].data_len += len; } +void BearSSLClient::clientAppendKey(void *ctx, const void *data, size_t len) +{ + BearSSLClient* c = (BearSSLClient*)ctx; + + br_skey_decoder_push(c->_skeyDecoder, data, len); +} + void BearSSLClient::parentAppendCert(void *ctx, const void *data, size_t len) { BearSSLClient* c = (BearSSLClient*)ctx; diff --git a/src/BearSSLClient.h b/src/BearSSLClient.h index 93b1779..700bb9a 100644 --- a/src/BearSSLClient.h +++ b/src/BearSSLClient.h @@ -83,6 +83,7 @@ class BearSSLClient : public Client { void setEccSlot(int ecc508KeySlot, const byte cert[], int certLength); void setEccSlot(int ecc508KeySlot, const char cert[]); + void setKey(const char key[], const char cert[]); void setEccCertParent(const char cert[]); int errorCode(); @@ -92,6 +93,7 @@ class BearSSLClient : public Client { static int clientRead(void *ctx, unsigned char *buf, size_t len); static int clientWrite(void *ctx, const unsigned char *buf, size_t len); static void clientAppendCert(void *ctx, const void *data, size_t len); + static void clientAppendKey(void *ctx, const void *data, size_t len); static void parentAppendCert(void *ctx, const void *data, size_t len); private: @@ -105,6 +107,7 @@ class BearSSLClient : public Client { br_ecdsa_sign _ecSign; br_ec_private_key _ecKey; + br_skey_decoder_context* _skeyDecoder; br_x509_certificate _ecCert[BEAR_SSL_CLIENT_CHAIN_SIZE]; int _ecChainLen; bool _ecCertDynamic; From 026f17465048cddb2530d54028474dae40146cee Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Wed, 14 Jul 2021 15:08:08 -0400 Subject: [PATCH 2/2] Add DigitCertGlobalRootCA as trust anchor --- extras/TrustAnchors/DigiCertGlobalRootCA.cer | Bin 0 -> 947 bytes src/BearSSLTrustAnchors.h | 114 ++++++++++++++----- 2 files changed, 83 insertions(+), 31 deletions(-) create mode 100644 extras/TrustAnchors/DigiCertGlobalRootCA.cer diff --git a/extras/TrustAnchors/DigiCertGlobalRootCA.cer b/extras/TrustAnchors/DigiCertGlobalRootCA.cer new file mode 100644 index 0000000000000000000000000000000000000000..2f1e5523af47d44e35ea27be89e25a663ea7f99f GIT binary patch literal 947 zcmXqLVqS01#58>YGZP~dlK_YHgRlusZW|YtW}S?jc-+f?myJ`a&7D}zCz zA-4f18*?ZNn=n&ou%W1dFo?q?%;S=op6Q%gRHERSmux6$APy4d78WQkFV{-}N+koO z^pf*)4HXRJKvK-Y;&2`AIr&M6ISN7f`6UX@js|k#yar~5hK2?Z5GBrQ4CKMN^l(BG zqY|>m8Ce;an;7{S44N3Zn3@dd`IJs!)JE3#aq8T|A z&M;11?q{$)_`CCwOos5ek9w8vwzD}fG;*FhC*8dN{#olnw@25~jV;t*_#-WJ|60ik06Z{$usNcN*7A>Z>YdMz&_;#V8wj@Ao_KA}aTB!TxfA z{eKw0wccFeA`oG;vQ*;g#YOwvAE{@3nPvRLlOv(~O8ge9mi-G?dHK}Zo%fH=DT`a+ zZ9Z|{9i?Zv=R~CXvQGayyICYf{CKqHJfr=e-u=4F?Q~`Jc1NRIJXhZTXuP_+H^P3a z^b1doMFqDES?+${B=*UN%a47$hjQ?3! zfC;G0fFHyc2Ju-9n1PgmEJ%QlMT|v+`Cfo&*hQb+X&)9pl9oO^eUt6QPy>08v@(l? zfmj1}1*qu{7!8aJr{|cj@(>o{`gPZ3j(^aGFZb86e66hHSga!P$6LGQfbPz#$Nzmf zC?9cpNA8@elIJrtR|{@^T(Dr_S)Y!XlY1r>JX*~!vv2as|H)UMuqRwzynk*q=f|sk zkAuJTCI7NtetS#W{iL*O7xNr@Kk06LRqi!^Zp0()$O8__Z*?`AT67HFks3>ujWo?Cxj#WeU z^4IG{MPAb-4oIsket75QefOHJTU0n$4c_SP<=*eQKVav| c&#z}N3avfSacqW3d@q;Hv6ok;PR+ds0Q5R