@@ -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 )
@@ -110,6 +112,105 @@ void CAtHandler::add_cmds_wifi_SSL() {
110112 return chAT::CommandStatus::ERROR;
111113 }
112114 };
115+
116+ /* ....................................................................... */
117+ command_table[_SETECCSLOT] = [this ](auto & srv, auto & parser) {
118+ /* ....................................................................... */
119+ switch (parser.cmd_mode ) {
120+ case chAT::CommandMode::Write: {
121+ if (parser.args .size () != 3 ) {
122+ return chAT::CommandStatus::ERROR;
123+ }
124+
125+ auto &sock_num = parser.args [0 ];
126+ auto &slot_num = parser.args [1 ];
127+ auto &cert_len = parser.args [2 ];
128+ if (sock_num.empty () || slot_num.empty () || cert_len.empty ()) {
129+ return chAT::CommandStatus::ERROR;
130+ }
131+
132+ int sock = atoi (sock_num.c_str ());
133+ int size = atoi (cert_len.c_str ());
134+
135+ CClientWrapper the_client = getClient (sock);
136+ if (the_client.sslclient == nullptr ) {
137+ return chAT::CommandStatus::ERROR;
138+ }
139+
140+ std::vector<unsigned char > client_cert_der;
141+ client_cert_der = srv.inhibit_read (size);
142+ size_t offset = client_cert_der.size ();
143+
144+ if (offset < size) {
145+ client_cert_der.resize (size);
146+ do {
147+ offset += serial->read (client_cert_der.data () + offset, size - offset);
148+ } while (offset < size);
149+ }
150+ srv.continue_read ();
151+
152+ #if ECC_DEBUG_ENABLED
153+ log_v (" _SETECCSLOT: input cert" );
154+ log_buf_v ((const uint8_t *)client_cert_der.data (), size);
155+ #endif
156+
157+ /* Convert client certificate DER buffer into PEM */
158+ client_cert_pem.resize (1024 );
159+ size_t olen;
160+ mbedtls_pem_write_buffer (" -----BEGIN CERTIFICATE-----\n " ,
161+ " -----END CERTIFICATE-----\n " ,
162+ client_cert_der.data (), size,
163+ client_cert_pem.data (), 1024 ,
164+ &olen);
165+ client_cert_pem.resize (olen);
166+
167+ #if ECC_DEBUG_ENABLED
168+ log_v (" _SETECCSLOT: output cert" );
169+ log_v (" \n %s" , client_cert_pem.data ());
170+ #endif
171+
172+ /* Set client certificate */
173+ the_client.sslclient ->setCertificate ((const char *)client_cert_pem.data ());
174+
175+ /* Read private key from non volatile storage in DER format */
176+ std::vector<unsigned char > client_key_der;
177+ int len = sse.getBytesLength (slot_num.c_str ());
178+ int ret = -1 ;
179+ client_key_der.resize (len);
180+ if ((ret = sse.getBytes (slot_num.c_str (), client_key_der.data (), len)) < len) {
181+ log_e (" failed\n ! sse.getBytes returned -0x%04x" , (unsigned int ) -ret);
182+ return chAT::CommandStatus::ERROR;
183+ }
184+
185+ #if ECC_DEBUG_ENABLED
186+ log_v (" _SETECCSLOT: input key" );
187+ log_buf_v ((const uint8_t *)client_key_der.data (), ret);
188+ #endif
189+
190+ /* Convert private key in PEM format */
191+ client_key_pem.resize (1024 );
192+ mbedtls_pem_write_buffer (" -----BEGIN EC PRIVATE KEY-----\n " ,
193+ " -----END EC PRIVATE KEY-----\n " ,
194+ client_key_der.data (), len,
195+ client_key_pem.data (), 1024 ,
196+ &olen);
197+ client_key_pem.resize (olen);
198+
199+ #if ECC_DEBUG_ENABLED
200+ log_v (" _SETECCSLOT: output key" );
201+ log_v (" \n %s" , client_key_pem.data ());
202+ #endif
203+
204+ /* Set client key */
205+ the_client.sslclient ->setPrivateKey ((const char *)client_key_pem.data ());
206+
207+ return chAT::CommandStatus::OK;
208+ }
209+ default :
210+ return chAT::CommandStatus::ERROR;
211+ }
212+ };
213+
113214 /* ....................................................................... */
114215 command_table[_SSLCLIENTSTATE] = [this ](auto & srv, auto & parser) {
115216 /* ....................................................................... */
0 commit comments