diff --git a/src/BearSSLClient.cpp b/src/BearSSLClient.cpp index 30037a1..e8e8d3c 100644 --- a/src/BearSSLClient.cpp +++ b/src/BearSSLClient.cpp @@ -44,7 +44,8 @@ BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs, _client(client), _TAs(myTAs), _numTAs(myNumTAs), - _noSNI(false) + _noSNI(false), + _ecChainLen(0) { _ecVrfy = br_ecdsa_vrfy_asn1_get_default(); _ecSign = br_ecdsa_sign_asn1_get_default(); @@ -53,16 +54,18 @@ BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs, _ecKey.x = NULL; _ecKey.xlen = 0; - _ecCert.data = NULL; - _ecCert.data_len = 0; + for (size_t i = 0; i < BEAR_SSL_CLIENT_CHAIN_SIZE; i++) { + _ecCert[i].data = NULL; + _ecCert[i].data_len = 0; + } _ecCertDynamic = false; } BearSSLClient::~BearSSLClient() { - if (_ecCertDynamic && _ecCert.data) { - free(_ecCert.data); - _ecCert.data = NULL; + if (_ecCertDynamic && _ecCert[0].data) { + free(_ecCert[0].data); + _ecCert[0].data = NULL; } } @@ -207,7 +210,19 @@ void BearSSLClient::setEccSign(br_ecdsa_sign sign) void BearSSLClient::setEccCert(br_x509_certificate cert) { - _ecCert = cert; + _ecCert[0] = cert; + _ecChainLen = 1; +} + +void BearSSLClient::setEccChain(br_x509_certificate* chain, size_t chainLen) +{ + if (chainLen > BEAR_SSL_CLIENT_CHAIN_SIZE) + return; + + for (size_t i = 0; i < chainLen; i++) { + _ecCert[i] = chain[i]; + } + _ecChainLen = chainLen; } void BearSSLClient::setEccSlot(int ecc508KeySlot, const byte cert[], int certLength) @@ -217,8 +232,9 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const byte cert[], int certLen _ecKey.x = (unsigned char*)ecc508KeySlot; _ecKey.xlen = 32; - _ecCert.data = (unsigned char*)cert; - _ecCert.data_len = certLength; + _ecCert[0].data = (unsigned char*)cert; + _ecCert[0].data_len = certLength; + _ecChainLen = 1; _ecCertDynamic = false; _ecVrfy = eccX08_vrfy_asn1; @@ -233,14 +249,15 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const char cert[]) size_t certLen = strlen(cert); // free old data - if (_ecCertDynamic && _ecCert.data) { - free(_ecCert.data); - _ecCert.data = NULL; + if (_ecCertDynamic && _ecCert[0].data) { + free(_ecCert[0].data); + _ecCert[0].data = NULL; } // assume the decoded cert is 3/4 the length of the input - _ecCert.data = (unsigned char*)malloc(((certLen * 3) + 3) / 4); - _ecCert.data_len = 0; + _ecCert[0].data = (unsigned char*)malloc(((certLen * 3) + 3) / 4); + _ecCert[0].data_len = 0; + _ecChainLen = 1; br_pem_decoder_init(&pemDecoder); @@ -256,9 +273,9 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const char cert[]) break; case BR_PEM_END_OBJ: - if (_ecCert.data_len) { + if (_ecCert[0].data_len) { // done - setEccSlot(ecc508KeySlot, _ecCert.data, _ecCert.data_len); + setEccSlot(ecc508KeySlot, _ecCert[0].data, _ecCert[0].data_len); _ecCertDynamic = true; return; } @@ -266,7 +283,7 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const char cert[]) case BR_PEM_ERROR: // failure - free(_ecCert.data); + free(_ecCert[0].data); setEccSlot(ecc508KeySlot, NULL, 0); return; } @@ -301,8 +318,8 @@ int BearSSLClient::connectSSL(const char* host) br_x509_minimal_set_ecdsa(&_xc, br_ssl_engine_get_ec(&_sc.eng), br_ssl_engine_get_ecdsa(&_sc.eng)); // enable client auth - if (_ecCert.data_len) { - br_ssl_client_set_single_ec(&_sc, &_ecCert, 1, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), _ecSign); + 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); } // set the hostname used for SNI @@ -401,6 +418,6 @@ void BearSSLClient::clientAppendCert(void *ctx, const void *data, size_t len) { BearSSLClient* c = (BearSSLClient*)ctx; - memcpy(&c->_ecCert.data[c->_ecCert.data_len], data, len); - c->_ecCert.data_len += len; + memcpy(&c->_ecCert[0].data[c->_ecCert[0].data_len], data, len); + c->_ecCert[0].data_len += len; } diff --git a/src/BearSSLClient.h b/src/BearSSLClient.h index 125f41e..b45e30a 100644 --- a/src/BearSSLClient.h +++ b/src/BearSSLClient.h @@ -33,6 +33,10 @@ #define BEAR_SSL_CLIENT_IBUF_SIZE 8192 + 85 + 325 - BEAR_SSL_CLIENT_OBUF_SIZE #endif +#ifndef BEAR_SSL_CLIENT_CHAIN_SIZE +#define BEAR_SSL_CLIENT_CHAIN_SIZE 3 +#endif + #include #include @@ -75,6 +79,7 @@ class BearSSLClient : public Client { void setEccSign(br_ecdsa_sign sign); void setEccCert(br_x509_certificate cert); + void setEccChain(br_x509_certificate* chain, size_t chainLen); void setEccSlot(int ecc508KeySlot, const byte cert[], int certLength); void setEccSlot(int ecc508KeySlot, const char cert[]); @@ -98,7 +103,8 @@ class BearSSLClient : public Client { br_ecdsa_sign _ecSign; br_ec_private_key _ecKey; - br_x509_certificate _ecCert; + br_x509_certificate _ecCert[BEAR_SSL_CLIENT_CHAIN_SIZE]; + int _ecChainLen; bool _ecCertDynamic; br_ssl_client_context _sc;