@@ -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