@@ -48,6 +48,7 @@ BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs,
4848 _TAs(myTAs),
4949 _numTAs(myNumTAs),
5050 _noSNI(false ),
51+ _skeyDecoder(NULL ),
5152 _ecChainLen(0 )
5253{
5354#ifndef ARDUINO_DISABLE_ECCX08
@@ -75,6 +76,11 @@ BearSSLClient::~BearSSLClient()
7576 free (_ecCert[0 ].data );
7677 _ecCert[0 ].data = NULL ;
7778 }
79+
80+ if (_skeyDecoder) {
81+ free (_skeyDecoder);
82+ _skeyDecoder = NULL ;
83+ }
7884}
7985
8086int BearSSLClient::connect (IPAddress ip, uint16_t port)
@@ -303,6 +309,79 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const char cert[])
303309 }
304310}
305311
312+ void BearSSLClient::setKey (const char key[], const char cert[])
313+ {
314+ // try to decode the key and cert
315+ br_pem_decoder_context pemDecoder;
316+
317+ size_t keyLen = strlen (key);
318+ size_t certLen = strlen (cert);
319+
320+ br_pem_decoder_init (&pemDecoder);
321+
322+ if (_skeyDecoder == NULL ) {
323+ _skeyDecoder = (br_skey_decoder_context*)malloc (sizeof (br_skey_decoder_context));
324+ }
325+
326+ br_skey_decoder_init (_skeyDecoder);
327+
328+ while (keyLen) {
329+ size_t len = br_pem_decoder_push (&pemDecoder, key, keyLen);
330+
331+ key += len;
332+ keyLen -= len;
333+
334+ switch (br_pem_decoder_event (&pemDecoder)) {
335+ case BR_PEM_BEGIN_OBJ:
336+ br_pem_decoder_setdest (&pemDecoder, BearSSLClient::clientAppendKey, this );
337+ break ;
338+
339+ case BR_PEM_END_OBJ:
340+ if (br_skey_decoder_last_error (_skeyDecoder) != 0 ) {
341+ return ;
342+ }
343+ break ;
344+
345+ case BR_PEM_ERROR:
346+ return ;
347+ }
348+ }
349+
350+ // assume the decoded cert is 3/4 the length of the input
351+ _ecCert[0 ].data = (unsigned char *)malloc (((certLen * 3 ) + 3 ) / 4 );
352+ _ecCert[0 ].data_len = 0 ;
353+ _ecChainLen = 1 ;
354+
355+ br_pem_decoder_init (&pemDecoder);
356+
357+ while (certLen) {
358+ size_t len = br_pem_decoder_push (&pemDecoder, cert, certLen);
359+
360+ cert += len;
361+ certLen -= len;
362+
363+ switch (br_pem_decoder_event (&pemDecoder)) {
364+ case BR_PEM_BEGIN_OBJ:
365+ br_pem_decoder_setdest (&pemDecoder, BearSSLClient::clientAppendCert, this );
366+ break ;
367+
368+ case BR_PEM_END_OBJ:
369+ if (_ecCert[0 ].data_len ) {
370+ // done
371+ _ecCertDynamic = true ;
372+ return ;
373+ }
374+ break ;
375+
376+ case BR_PEM_ERROR:
377+ // failure
378+ free (_ecCert[0 ].data );
379+ _ecCert[0 ].data = NULL ;
380+ return ;
381+ }
382+ }
383+ }
384+
306385void BearSSLClient::setEccCertParent (const char cert[])
307386{
308387 // try to decode the cert
@@ -383,7 +462,17 @@ int BearSSLClient::connectSSL(const char* host)
383462
384463 // enable client auth
385464 if (_ecCert[0 ].data_len ) {
386- br_ssl_client_set_single_ec (&_sc, _ecCert, _ecChainLen, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default (), _ecSign);
465+ if (_skeyDecoder) {
466+ int skeyType = br_skey_decoder_key_type (_skeyDecoder);
467+
468+ if (skeyType == BR_KEYTYPE_EC) {
469+ 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 ());
470+ } else if (skeyType == BR_KEYTYPE_RSA) {
471+ br_ssl_client_set_single_rsa (&_sc, _ecCert, _ecChainLen, br_skey_decoder_get_rsa (_skeyDecoder), br_rsa_pkcs1_sign_get_default ());
472+ }
473+ } else {
474+ br_ssl_client_set_single_ec (&_sc, _ecCert, _ecChainLen, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default (), _ecSign);
475+ }
387476 }
388477
389478 // set the hostname used for SNI
@@ -486,6 +575,13 @@ void BearSSLClient::clientAppendCert(void *ctx, const void *data, size_t len)
486575 c->_ecCert [0 ].data_len += len;
487576}
488577
578+ void BearSSLClient::clientAppendKey (void *ctx, const void *data, size_t len)
579+ {
580+ BearSSLClient* c = (BearSSLClient*)ctx;
581+
582+ br_skey_decoder_push (c->_skeyDecoder , data, len);
583+ }
584+
489585void BearSSLClient::parentAppendCert (void *ctx, const void *data, size_t len)
490586{
491587 BearSSLClient* c = (BearSSLClient*)ctx;
0 commit comments