Skip to content

Commit 30e7695

Browse files
authored
Merge pull request #31 from pennam/ecc_slot
Add WiFi command to configure ECC slot
2 parents ed3d7b5 + 7495f3f commit 30e7695

File tree

6 files changed

+215
-19
lines changed

6 files changed

+215
-19
lines changed

UNOR4USBBridge/at_handler.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
#include "cmds_wifi_station.h"
99
#include "cmds_wifi_softAP.h"
1010
#include "cmds_wifi_netif.h"
11+
#include "cmds_preferences.h"
1112
#include "cmds_wifi_SSL.h"
1213
#include "cmds_wifi_udp.h"
1314
#include "cmds_ble_bridge.h"
1415
#include "cmds_ota.h"
15-
#include "cmds_preferences.h"
1616
#include "cmds_se.h"
1717

1818
using namespace SudoMaker;
@@ -92,6 +92,9 @@ CAtHandler::CAtHandler(HardwareSerial *s) : last_server_client_sock(0) {
9292

9393
for(int i = 0; i < MAX_CLIENT_AVAILABLE; i++) {
9494
sslclients[i] = nullptr;
95+
clients_ca[i].clear();
96+
clients_cert_pem[i].clear();
97+
clients_key_pem[i].clear();
9598
}
9699

97100
/* set up serial */

UNOR4USBBridge/at_handler.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class CAtHandler {
6363
WiFiClient * clients[MAX_CLIENT_AVAILABLE];
6464
CServerClient serverClients[MAX_CLIENT_AVAILABLE];
6565
WiFiClientSecure * sslclients[MAX_CLIENT_AVAILABLE];
66+
std::vector<std::uint8_t> clients_ca[MAX_CLIENT_AVAILABLE];
67+
std::vector<std::uint8_t> clients_cert_pem[MAX_CLIENT_AVAILABLE];
68+
std::vector<std::uint8_t> clients_key_pem[MAX_CLIENT_AVAILABLE];
6669
int udps_num = 0;
6770
int servers_num = 0;
6871
int clientsToServer_num = 0;
@@ -85,8 +88,15 @@ class CAtHandler {
8588
void add_cmds_preferences();
8689
void add_cmds_se();
8790
public:
88-
std::vector<std::uint8_t> cert_buf;
91+
/* Used by cmds_se */
8992
std::vector<std::uint8_t> se_buf;
93+
94+
/* Used by cmds_ota */
95+
std::vector<std::uint8_t> ota_cert_buf;
96+
97+
/* Used by cmds_preferences */
98+
std::vector<std::uint8_t> pref_buf;
99+
90100
CAtHandler(HardwareSerial *s);
91101
CAtHandler() = delete ;
92102
static void onWiFiEvent(WiFiEvent_t event);

UNOR4USBBridge/cmds_ota.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ void CAtHandler::add_cmds_ota() {
2727
return chAT::CommandStatus::ERROR;
2828
}
2929

30-
cert_buf = srv.inhibit_read(ca_root_size);
31-
size_t offset = cert_buf.size();
30+
ota_cert_buf = srv.inhibit_read(ca_root_size);
31+
size_t offset = ota_cert_buf.size();
3232
if(offset < ca_root_size) {
33-
cert_buf.resize(ca_root_size);
33+
ota_cert_buf.resize(ca_root_size);
3434
do {
35-
offset += serial->read(cert_buf.data() + offset, ca_root_size - offset);
35+
offset += serial->read(ota_cert_buf.data() + offset, ca_root_size - offset);
3636
} while (offset < ca_root_size);
3737
}
38-
OTA.setCACert((const char *)cert_buf.data());
38+
OTA.setCACert((const char *)ota_cert_buf.data());
3939
srv.continue_read();
4040
return chAT::CommandStatus::OK;
4141
}

UNOR4USBBridge/cmds_preferences.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,16 @@ void CAtHandler::add_cmds_preferences() {
171171
break;
172172
case PreferenceType::PT_BLOB: {
173173
int value = atoi(parser.args[2].c_str());
174-
cert_buf = srv.inhibit_read(value);
175-
size_t offset = cert_buf.size();
174+
pref_buf = srv.inhibit_read(value);
175+
size_t offset = pref_buf.size();
176176
if(offset < value) {
177-
cert_buf.resize(value);
177+
pref_buf.resize(value);
178178
do {
179-
offset += serial->read(cert_buf.data() + offset, value - offset);
179+
offset += serial->read(pref_buf.data() + offset, value - offset);
180180
} while (offset < value);
181181
}
182182
srv.continue_read();
183-
error = String(pref.putBytes(key.c_str(), cert_buf.data(), value)) + "\r\n";
183+
error = String(pref.putBytes(key.c_str(), pref_buf.data(), value)) + "\r\n";
184184
}
185185
break;
186186
default:

UNOR4USBBridge/cmds_wifi_SSL.h

Lines changed: 189 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ INCBIN(x509_crt_bundle, PATH_CERT_BUNDLE);
1111
#endif
1212

1313
#include "at_handler.h"
14+
#include "mbedtls/pem.h"
15+
#include "SSE.h"
1416

1517
#ifndef WIFI_CLIENT_DEF_CONN_TIMEOUT_MS
1618
#define WIFI_CLIENT_DEF_CONN_TIMEOUT_MS (3000)
@@ -66,6 +68,11 @@ void CAtHandler::add_cmds_wifi_SSL() {
6668
return chAT::CommandStatus::ERROR;
6769
}
6870

71+
const int internal_sock = the_client.can_delete;
72+
if (internal_sock == -1) {
73+
return chAT::CommandStatus::ERROR;
74+
}
75+
6976
bool ca_root_custom = false;
7077
int ca_root_size = 0;
7178
if (parser.args.size() >= 2){
@@ -78,19 +85,17 @@ void CAtHandler::add_cmds_wifi_SSL() {
7885
}
7986

8087
if(ca_root_custom) {
81-
82-
83-
cert_buf = srv.inhibit_read(ca_root_size);
84-
size_t offset = cert_buf.size();
88+
clients_ca[internal_sock] = srv.inhibit_read(ca_root_size);
89+
size_t offset = clients_ca[internal_sock].size();
8590

8691
if(offset < ca_root_size) {
8792

88-
cert_buf.resize(ca_root_size);
93+
clients_ca[internal_sock].resize(ca_root_size);
8994
do {
90-
offset += serial->read(cert_buf.data() + offset, ca_root_size - offset);
95+
offset += serial->read(clients_ca[internal_sock].data() + offset, ca_root_size - offset);
9196
} while (offset < ca_root_size);
9297
}
93-
the_client.sslclient->setCACert((const char *)cert_buf.data());
98+
the_client.sslclient->setCACert((const char *)clients_ca[internal_sock].data());
9499
srv.continue_read();
95100
} else {
96101
#ifdef BUNDLED_CA_ROOT_CRT
@@ -110,6 +115,120 @@ void CAtHandler::add_cmds_wifi_SSL() {
110115
return chAT::CommandStatus::ERROR;
111116
}
112117
};
118+
119+
/* ....................................................................... */
120+
command_table[_SETECCSLOT] = [this](auto & srv, auto & parser) {
121+
/* ....................................................................... */
122+
switch (parser.cmd_mode) {
123+
case chAT::CommandMode::Write: {
124+
if (parser.args.size() != 3) {
125+
return chAT::CommandStatus::ERROR;
126+
}
127+
128+
auto &sock_num = parser.args[0];
129+
auto &slot_num = parser.args[1];
130+
auto &cert_len = parser.args[2];
131+
if (sock_num.empty() || slot_num.empty() || cert_len.empty()) {
132+
return chAT::CommandStatus::ERROR;
133+
}
134+
135+
int sock = atoi(sock_num.c_str());
136+
int size = atoi(cert_len.c_str());
137+
138+
CClientWrapper the_client = getClient(sock);
139+
if (the_client.sslclient == nullptr) {
140+
return chAT::CommandStatus::ERROR;
141+
}
142+
143+
const int internal_sock = the_client.can_delete;
144+
if (internal_sock == -1) {
145+
return chAT::CommandStatus::ERROR;
146+
}
147+
148+
std::vector<unsigned char> client_cert_der;
149+
client_cert_der = srv.inhibit_read(size);
150+
size_t offset = client_cert_der.size();
151+
152+
if(offset < size) {
153+
client_cert_der.resize(size);
154+
do {
155+
offset += serial->read(client_cert_der.data() + offset, size - offset);
156+
} while (offset < size);
157+
}
158+
srv.continue_read();
159+
160+
#if ECC_DEBUG_ENABLED
161+
log_v("_SETECCSLOT: input cert");
162+
log_buf_v((const uint8_t *)client_cert_der.data(), size);
163+
#endif
164+
165+
/* Convert client certificate DER buffer into PEM */
166+
clients_cert_pem[internal_sock].resize(1024);
167+
size_t olen;
168+
int ret = -1;
169+
if ((ret = mbedtls_pem_write_buffer("-----BEGIN CERTIFICATE-----\n",
170+
"-----END CERTIFICATE-----\n",
171+
client_cert_der.data(), size,
172+
clients_cert_pem[internal_sock].data(), 1024,
173+
&olen)) != 0)
174+
{
175+
log_e(" failed\n ! mbedtls_pem_write_buffer returned -0x%04x", (unsigned int) -ret);
176+
clients_cert_pem[internal_sock].clear();
177+
return chAT::CommandStatus::ERROR;
178+
}
179+
clients_cert_pem[internal_sock].resize(olen);
180+
181+
#if ECC_DEBUG_ENABLED
182+
log_v("_SETECCSLOT: output cert");
183+
log_v("\n%s", clients_cert_pem[internal_sock].data());
184+
#endif
185+
186+
/* Set client certificate */
187+
the_client.sslclient->setCertificate((const char *)clients_cert_pem[internal_sock].data());
188+
189+
/* Read private key from non volatile storage in DER format */
190+
std::vector<unsigned char> client_key_der;
191+
int len = sse.getBytesLength(slot_num.c_str());
192+
client_key_der.resize(len);
193+
if ((ret = sse.getBytes(slot_num.c_str(), client_key_der.data(), len)) < len) {
194+
log_e(" failed\n ! sse.getBytes returned -0x%04x", (unsigned int) -ret);
195+
return chAT::CommandStatus::ERROR;
196+
}
197+
198+
#if ECC_DEBUG_ENABLED
199+
log_v("_SETECCSLOT: input key");
200+
log_buf_v((const uint8_t *)client_key_der.data(), ret);
201+
#endif
202+
203+
/* Convert private key in PEM format */
204+
clients_key_pem[internal_sock].resize(1024);
205+
if ((ret = mbedtls_pem_write_buffer("-----BEGIN EC PRIVATE KEY-----\n",
206+
"-----END EC PRIVATE KEY-----\n",
207+
client_key_der.data(), len,
208+
clients_key_pem[internal_sock].data(), 1024,
209+
&olen)) != 0)
210+
{
211+
log_e(" failed\n ! mbedtls_pem_write_buffer returned -0x%04x", (unsigned int) -ret);
212+
clients_cert_pem[internal_sock].clear();
213+
return chAT::CommandStatus::ERROR;
214+
}
215+
clients_key_pem[internal_sock].resize(olen);
216+
217+
#if ECC_DEBUG_ENABLED
218+
log_v("_SETECCSLOT: output key");
219+
log_v("\n%s", clients_key_pem[internal_sock].data());
220+
#endif
221+
222+
/* Set client key */
223+
the_client.sslclient->setPrivateKey((const char *)clients_key_pem[internal_sock].data());
224+
225+
return chAT::CommandStatus::OK;
226+
}
227+
default:
228+
return chAT::CommandStatus::ERROR;
229+
}
230+
};
231+
113232
/* ....................................................................... */
114233
command_table[_SSLCLIENTSTATE] = [this](auto & srv, auto & parser) {
115234
/* ....................................................................... */
@@ -166,6 +285,11 @@ void CAtHandler::add_cmds_wifi_SSL() {
166285
return chAT::CommandStatus::ERROR;
167286
}
168287

288+
const int internal_sock = the_client.can_delete;
289+
if (internal_sock == -1) {
290+
return chAT::CommandStatus::ERROR;
291+
}
292+
169293
auto &host = parser.args[1];
170294
if (host.empty()) {
171295
return chAT::CommandStatus::ERROR;
@@ -176,6 +300,21 @@ void CAtHandler::add_cmds_wifi_SSL() {
176300
return chAT::CommandStatus::ERROR;
177301
}
178302

303+
/* Set custom root ca */
304+
if (clients_ca[internal_sock].size()) {
305+
the_client.sslclient->setCACert((const char *)clients_ca[internal_sock].data());
306+
}
307+
/* Default ca bundle is configured automatically on connect by the WiFiSSLClient */
308+
309+
if (clients_cert_pem[internal_sock].size()) {
310+
/* Set client certificate */
311+
the_client.sslclient->setCertificate((const char *)clients_cert_pem[internal_sock].data());
312+
}
313+
if (clients_key_pem[internal_sock].size()) {
314+
/* Set client key */
315+
the_client.sslclient->setPrivateKey((const char *)clients_key_pem[internal_sock].data());
316+
}
317+
179318
if (!the_client.sslclient->connect(host.c_str(), atoi(port.c_str()))) {
180319
return chAT::CommandStatus::ERROR;
181320
}
@@ -210,6 +349,11 @@ void CAtHandler::add_cmds_wifi_SSL() {
210349
return chAT::CommandStatus::ERROR;
211350
}
212351

352+
const int internal_sock = the_client.can_delete;
353+
if (internal_sock == -1) {
354+
return chAT::CommandStatus::ERROR;
355+
}
356+
213357
auto &hostip = parser.args[1];
214358
if (hostip.empty()) {
215359
return chAT::CommandStatus::ERROR;
@@ -225,6 +369,21 @@ void CAtHandler::add_cmds_wifi_SSL() {
225369
return chAT::CommandStatus::ERROR;
226370
}
227371

372+
/* Set custom root ca */
373+
if (clients_ca[internal_sock].size()) {
374+
the_client.sslclient->setCACert((const char *)clients_ca[internal_sock].data());
375+
}
376+
/* Default ca bundle is configured automatically on connect by the WiFiSSLClient */
377+
378+
if (clients_cert_pem[internal_sock].size()) {
379+
/* Set client certificate */
380+
the_client.sslclient->setCertificate((const char *)clients_cert_pem[internal_sock].data());
381+
}
382+
if (clients_key_pem[internal_sock].size()) {
383+
/* Set client key */
384+
the_client.sslclient->setPrivateKey((const char *)clients_key_pem[internal_sock].data());
385+
}
386+
228387
if (!the_client.sslclient->connect(address, atoi(hostport.c_str()))) {
229388
return chAT::CommandStatus::ERROR;
230389
}
@@ -258,6 +417,11 @@ void CAtHandler::add_cmds_wifi_SSL() {
258417
return chAT::CommandStatus::ERROR;
259418
}
260419

420+
const int internal_sock = the_client.can_delete;
421+
if (internal_sock == -1) {
422+
return chAT::CommandStatus::ERROR;
423+
}
424+
261425
auto &host = parser.args[1];
262426
if (host.empty()) {
263427
return chAT::CommandStatus::ERROR;
@@ -280,6 +444,21 @@ void CAtHandler::add_cmds_wifi_SSL() {
280444
}
281445
}
282446

447+
/* Set custom root ca */
448+
if (clients_ca[internal_sock].size()) {
449+
the_client.sslclient->setCACert((const char *)clients_ca[internal_sock].data());
450+
}
451+
/* Default ca bundle is configured automatically on connect by the WiFiSSLClient */
452+
453+
if (clients_cert_pem[internal_sock].size()) {
454+
/* Set client certificate */
455+
the_client.sslclient->setCertificate((const char *)clients_cert_pem[internal_sock].data());
456+
}
457+
if (clients_key_pem[internal_sock].size()) {
458+
/* Set client key */
459+
the_client.sslclient->setPrivateKey((const char *)clients_key_pem[internal_sock].data());
460+
}
461+
283462
if (!the_client.sslclient->connect(host.c_str(), atoi(port.c_str()), timeout)) {
284463
return chAT::CommandStatus::ERROR;
285464
}
@@ -397,6 +576,9 @@ void CAtHandler::add_cmds_wifi_SSL() {
397576
if(the_client.can_delete >= 0) {
398577
delete sslclients[the_client.can_delete];
399578
sslclients[the_client.can_delete] = nullptr;
579+
clients_ca[the_client.can_delete].clear();
580+
clients_cert_pem[the_client.can_delete].clear();
581+
clients_key_pem[the_client.can_delete].clear();
400582
sslclients_num--;
401583
}
402584
}

UNOR4USBBridge/commands.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ enum file_op {
5858
#define _CLIENTCONNECTED "+CLIENTCONNECTED"
5959
#define _SSLBEGINCLIENT "+SSLBEGINCLIENT"
6060
#define _SETCAROOT "+SETCAROOT"
61+
#define _SETECCSLOT "+SETECCSLOT"
6162
#define _SSLCLIENTSTATE "+SSLCLIENTSTATE"
6263
#define _SSLCLIENTCONNECTNAME "+SSLCLIENTCONNECTNAME"
6364
#define _SSLCLIENTCONNECT "+SSLCLIENTCONNECT"

0 commit comments

Comments
 (0)