Skip to content

Commit f2e43d1

Browse files
committed
Add setKey API to set PEM private key and public cert for client connection
1 parent e3feaf2 commit f2e43d1

File tree

3 files changed

+101
-1
lines changed

3 files changed

+101
-1
lines changed

keywords.txt

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ getTime KEYWORD2
1717
onGetTime KEYWORD2
1818

1919
setEccSlot KEYWORD2
20+
setKey KEYWORD2
2021
errorCode KEYWORD2
2122

2223
########################################

src/BearSSLClient.cpp

+97-1
Original file line numberDiff line numberDiff line change
@@ -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

8086
int 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+
306385
void 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+
489585
void BearSSLClient::parentAppendCert(void *ctx, const void *data, size_t len)
490586
{
491587
BearSSLClient* c = (BearSSLClient*)ctx;

src/BearSSLClient.h

+3
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class BearSSLClient : public Client {
8383

8484
void setEccSlot(int ecc508KeySlot, const byte cert[], int certLength);
8585
void setEccSlot(int ecc508KeySlot, const char cert[]);
86+
void setKey(const char key[], const char cert[]);
8687
void setEccCertParent(const char cert[]);
8788

8889
int errorCode();
@@ -92,6 +93,7 @@ class BearSSLClient : public Client {
9293
static int clientRead(void *ctx, unsigned char *buf, size_t len);
9394
static int clientWrite(void *ctx, const unsigned char *buf, size_t len);
9495
static void clientAppendCert(void *ctx, const void *data, size_t len);
96+
static void clientAppendKey(void *ctx, const void *data, size_t len);
9597
static void parentAppendCert(void *ctx, const void *data, size_t len);
9698

9799
private:
@@ -105,6 +107,7 @@ class BearSSLClient : public Client {
105107
br_ecdsa_sign _ecSign;
106108

107109
br_ec_private_key _ecKey;
110+
br_skey_decoder_context* _skeyDecoder;
108111
br_x509_certificate _ecCert[BEAR_SSL_CLIENT_CHAIN_SIZE];
109112
int _ecChainLen;
110113
bool _ecCertDynamic;

0 commit comments

Comments
 (0)