Skip to content

Commit 20db745

Browse files
authoredFeb 4, 2021
Add setEccChain function (#39)
This will allow the user to specify a client certificate chain instead of a single client certificate. This is useful for example for AWS just-in-time registration or Just-in-time provisioning (JITP): https://aws.amazon.com/blogs/iot/just-in-time-registration-of-device-certificates-on-aws-iot https://docs.aws.amazon.com/iot/latest/developerguide/jit-provisioning.html Signed-off-by: Fabrice Fontaine <fabrice.fontaine@orange.com>
1 parent 2691d3d commit 20db745

File tree

2 files changed

+45
-22
lines changed

2 files changed

+45
-22
lines changed
 

‎src/BearSSLClient.cpp

+38-21
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs,
4444
_client(client),
4545
_TAs(myTAs),
4646
_numTAs(myNumTAs),
47-
_noSNI(false)
47+
_noSNI(false),
48+
_ecChainLen(0)
4849
{
4950
_ecVrfy = br_ecdsa_vrfy_asn1_get_default();
5051
_ecSign = br_ecdsa_sign_asn1_get_default();
@@ -53,16 +54,18 @@ BearSSLClient::BearSSLClient(Client* client, const br_x509_trust_anchor* myTAs,
5354
_ecKey.x = NULL;
5455
_ecKey.xlen = 0;
5556

56-
_ecCert.data = NULL;
57-
_ecCert.data_len = 0;
57+
for (size_t i = 0; i < BEAR_SSL_CLIENT_CHAIN_SIZE; i++) {
58+
_ecCert[i].data = NULL;
59+
_ecCert[i].data_len = 0;
60+
}
5861
_ecCertDynamic = false;
5962
}
6063

6164
BearSSLClient::~BearSSLClient()
6265
{
63-
if (_ecCertDynamic && _ecCert.data) {
64-
free(_ecCert.data);
65-
_ecCert.data = NULL;
66+
if (_ecCertDynamic && _ecCert[0].data) {
67+
free(_ecCert[0].data);
68+
_ecCert[0].data = NULL;
6669
}
6770
}
6871

@@ -207,7 +210,19 @@ void BearSSLClient::setEccSign(br_ecdsa_sign sign)
207210

208211
void BearSSLClient::setEccCert(br_x509_certificate cert)
209212
{
210-
_ecCert = cert;
213+
_ecCert[0] = cert;
214+
_ecChainLen = 1;
215+
}
216+
217+
void BearSSLClient::setEccChain(br_x509_certificate* chain, size_t chainLen)
218+
{
219+
if (chainLen > BEAR_SSL_CLIENT_CHAIN_SIZE)
220+
return;
221+
222+
for (size_t i = 0; i < chainLen; i++) {
223+
_ecCert[i] = chain[i];
224+
}
225+
_ecChainLen = chainLen;
211226
}
212227

213228
void BearSSLClient::setEccSlot(int ecc508KeySlot, const byte cert[], int certLength)
@@ -217,8 +232,9 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const byte cert[], int certLen
217232
_ecKey.x = (unsigned char*)ecc508KeySlot;
218233
_ecKey.xlen = 32;
219234

220-
_ecCert.data = (unsigned char*)cert;
221-
_ecCert.data_len = certLength;
235+
_ecCert[0].data = (unsigned char*)cert;
236+
_ecCert[0].data_len = certLength;
237+
_ecChainLen = 1;
222238
_ecCertDynamic = false;
223239

224240
_ecVrfy = eccX08_vrfy_asn1;
@@ -233,14 +249,15 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const char cert[])
233249
size_t certLen = strlen(cert);
234250

235251
// free old data
236-
if (_ecCertDynamic && _ecCert.data) {
237-
free(_ecCert.data);
238-
_ecCert.data = NULL;
252+
if (_ecCertDynamic && _ecCert[0].data) {
253+
free(_ecCert[0].data);
254+
_ecCert[0].data = NULL;
239255
}
240256

241257
// assume the decoded cert is 3/4 the length of the input
242-
_ecCert.data = (unsigned char*)malloc(((certLen * 3) + 3) / 4);
243-
_ecCert.data_len = 0;
258+
_ecCert[0].data = (unsigned char*)malloc(((certLen * 3) + 3) / 4);
259+
_ecCert[0].data_len = 0;
260+
_ecChainLen = 1;
244261

245262
br_pem_decoder_init(&pemDecoder);
246263

@@ -256,17 +273,17 @@ void BearSSLClient::setEccSlot(int ecc508KeySlot, const char cert[])
256273
break;
257274

258275
case BR_PEM_END_OBJ:
259-
if (_ecCert.data_len) {
276+
if (_ecCert[0].data_len) {
260277
// done
261-
setEccSlot(ecc508KeySlot, _ecCert.data, _ecCert.data_len);
278+
setEccSlot(ecc508KeySlot, _ecCert[0].data, _ecCert[0].data_len);
262279
_ecCertDynamic = true;
263280
return;
264281
}
265282
break;
266283

267284
case BR_PEM_ERROR:
268285
// failure
269-
free(_ecCert.data);
286+
free(_ecCert[0].data);
270287
setEccSlot(ecc508KeySlot, NULL, 0);
271288
return;
272289
}
@@ -301,8 +318,8 @@ int BearSSLClient::connectSSL(const char* host)
301318
br_x509_minimal_set_ecdsa(&_xc, br_ssl_engine_get_ec(&_sc.eng), br_ssl_engine_get_ecdsa(&_sc.eng));
302319

303320
// enable client auth
304-
if (_ecCert.data_len) {
305-
br_ssl_client_set_single_ec(&_sc, &_ecCert, 1, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), _ecSign);
321+
if (_ecCert[0].data_len) {
322+
br_ssl_client_set_single_ec(&_sc, _ecCert, _ecChainLen, &_ecKey, BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN, BR_KEYTYPE_EC, br_ec_get_default(), _ecSign);
306323
}
307324

308325
// set the hostname used for SNI
@@ -401,6 +418,6 @@ void BearSSLClient::clientAppendCert(void *ctx, const void *data, size_t len)
401418
{
402419
BearSSLClient* c = (BearSSLClient*)ctx;
403420

404-
memcpy(&c->_ecCert.data[c->_ecCert.data_len], data, len);
405-
c->_ecCert.data_len += len;
421+
memcpy(&c->_ecCert[0].data[c->_ecCert[0].data_len], data, len);
422+
c->_ecCert[0].data_len += len;
406423
}

‎src/BearSSLClient.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
#define BEAR_SSL_CLIENT_IBUF_SIZE 8192 + 85 + 325 - BEAR_SSL_CLIENT_OBUF_SIZE
3434
#endif
3535

36+
#ifndef BEAR_SSL_CLIENT_CHAIN_SIZE
37+
#define BEAR_SSL_CLIENT_CHAIN_SIZE 3
38+
#endif
39+
3640
#include <Arduino.h>
3741
#include <Client.h>
3842

@@ -75,6 +79,7 @@ class BearSSLClient : public Client {
7579
void setEccSign(br_ecdsa_sign sign);
7680

7781
void setEccCert(br_x509_certificate cert);
82+
void setEccChain(br_x509_certificate* chain, size_t chainLen);
7883

7984
void setEccSlot(int ecc508KeySlot, const byte cert[], int certLength);
8085
void setEccSlot(int ecc508KeySlot, const char cert[]);
@@ -98,7 +103,8 @@ class BearSSLClient : public Client {
98103
br_ecdsa_sign _ecSign;
99104

100105
br_ec_private_key _ecKey;
101-
br_x509_certificate _ecCert;
106+
br_x509_certificate _ecCert[BEAR_SSL_CLIENT_CHAIN_SIZE];
107+
int _ecChainLen;
102108
bool _ecCertDynamic;
103109

104110
br_ssl_client_context _sc;

0 commit comments

Comments
 (0)
Please sign in to comment.