@@ -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 }
0 commit comments