Skip to content

Add WiFi command to configure ECC slot #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion UNOR4USBBridge/at_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
#include "cmds_wifi_station.h"
#include "cmds_wifi_softAP.h"
#include "cmds_wifi_netif.h"
#include "cmds_preferences.h"
#include "cmds_wifi_SSL.h"
#include "cmds_wifi_udp.h"
#include "cmds_ble_bridge.h"
#include "cmds_ota.h"
#include "cmds_preferences.h"
#include "cmds_se.h"

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

for(int i = 0; i < MAX_CLIENT_AVAILABLE; i++) {
sslclients[i] = nullptr;
clients_ca[i].clear();
clients_cert_pem[i].clear();
clients_key_pem[i].clear();
}

/* set up serial */
Expand Down
12 changes: 11 additions & 1 deletion UNOR4USBBridge/at_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class CAtHandler {
WiFiClient * clients[MAX_CLIENT_AVAILABLE];
CServerClient serverClients[MAX_CLIENT_AVAILABLE];
WiFiClientSecure * sslclients[MAX_CLIENT_AVAILABLE];
std::vector<std::uint8_t> clients_ca[MAX_CLIENT_AVAILABLE];
std::vector<std::uint8_t> clients_cert_pem[MAX_CLIENT_AVAILABLE];
std::vector<std::uint8_t> clients_key_pem[MAX_CLIENT_AVAILABLE];
int udps_num = 0;
int servers_num = 0;
int clientsToServer_num = 0;
Expand All @@ -85,8 +88,15 @@ class CAtHandler {
void add_cmds_preferences();
void add_cmds_se();
public:
std::vector<std::uint8_t> cert_buf;
/* Used by cmds_se */
std::vector<std::uint8_t> se_buf;

/* Used by cmds_ota */
std::vector<std::uint8_t> ota_cert_buf;

/* Used by cmds_preferences */
std::vector<std::uint8_t> pref_buf;

CAtHandler(HardwareSerial *s);
CAtHandler() = delete ;
static void onWiFiEvent(WiFiEvent_t event);
Expand Down
10 changes: 5 additions & 5 deletions UNOR4USBBridge/cmds_ota.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ void CAtHandler::add_cmds_ota() {
return chAT::CommandStatus::ERROR;
}

cert_buf = srv.inhibit_read(ca_root_size);
size_t offset = cert_buf.size();
ota_cert_buf = srv.inhibit_read(ca_root_size);
size_t offset = ota_cert_buf.size();
if(offset < ca_root_size) {
cert_buf.resize(ca_root_size);
ota_cert_buf.resize(ca_root_size);
do {
offset += serial->read(cert_buf.data() + offset, ca_root_size - offset);
offset += serial->read(ota_cert_buf.data() + offset, ca_root_size - offset);
} while (offset < ca_root_size);
}
OTA.setCACert((const char *)cert_buf.data());
OTA.setCACert((const char *)ota_cert_buf.data());
srv.continue_read();
return chAT::CommandStatus::OK;
}
Expand Down
10 changes: 5 additions & 5 deletions UNOR4USBBridge/cmds_preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,16 @@ void CAtHandler::add_cmds_preferences() {
break;
case PreferenceType::PT_BLOB: {
int value = atoi(parser.args[2].c_str());
cert_buf = srv.inhibit_read(value);
size_t offset = cert_buf.size();
pref_buf = srv.inhibit_read(value);
size_t offset = pref_buf.size();
if(offset < value) {
cert_buf.resize(value);
pref_buf.resize(value);
do {
offset += serial->read(cert_buf.data() + offset, value - offset);
offset += serial->read(pref_buf.data() + offset, value - offset);
} while (offset < value);
}
srv.continue_read();
error = String(pref.putBytes(key.c_str(), cert_buf.data(), value)) + "\r\n";
error = String(pref.putBytes(key.c_str(), pref_buf.data(), value)) + "\r\n";
}
break;
default:
Expand Down
196 changes: 189 additions & 7 deletions UNOR4USBBridge/cmds_wifi_SSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ INCBIN(x509_crt_bundle, PATH_CERT_BUNDLE);
#endif

#include "at_handler.h"
#include "mbedtls/pem.h"
#include "SSE.h"

#ifndef WIFI_CLIENT_DEF_CONN_TIMEOUT_MS
#define WIFI_CLIENT_DEF_CONN_TIMEOUT_MS (3000)
Expand Down Expand Up @@ -66,6 +68,11 @@ void CAtHandler::add_cmds_wifi_SSL() {
return chAT::CommandStatus::ERROR;
}

const int internal_sock = the_client.can_delete;
if (internal_sock == -1) {
return chAT::CommandStatus::ERROR;
}

bool ca_root_custom = false;
int ca_root_size = 0;
if (parser.args.size() >= 2){
Expand All @@ -78,19 +85,17 @@ void CAtHandler::add_cmds_wifi_SSL() {
}

if(ca_root_custom) {


cert_buf = srv.inhibit_read(ca_root_size);
size_t offset = cert_buf.size();
clients_ca[internal_sock] = srv.inhibit_read(ca_root_size);
size_t offset = clients_ca[internal_sock].size();

if(offset < ca_root_size) {

cert_buf.resize(ca_root_size);
clients_ca[internal_sock].resize(ca_root_size);
do {
offset += serial->read(cert_buf.data() + offset, ca_root_size - offset);
offset += serial->read(clients_ca[internal_sock].data() + offset, ca_root_size - offset);
} while (offset < ca_root_size);
}
the_client.sslclient->setCACert((const char *)cert_buf.data());
the_client.sslclient->setCACert((const char *)clients_ca[internal_sock].data());
srv.continue_read();
} else {
#ifdef BUNDLED_CA_ROOT_CRT
Expand All @@ -110,6 +115,120 @@ void CAtHandler::add_cmds_wifi_SSL() {
return chAT::CommandStatus::ERROR;
}
};

/* ....................................................................... */
command_table[_SETECCSLOT] = [this](auto & srv, auto & parser) {
/* ....................................................................... */
switch (parser.cmd_mode) {
case chAT::CommandMode::Write: {
if (parser.args.size() != 3) {
return chAT::CommandStatus::ERROR;
}

auto &sock_num = parser.args[0];
auto &slot_num = parser.args[1];
auto &cert_len = parser.args[2];
if (sock_num.empty() || slot_num.empty() || cert_len.empty()) {
return chAT::CommandStatus::ERROR;
}

int sock = atoi(sock_num.c_str());
int size = atoi(cert_len.c_str());

CClientWrapper the_client = getClient(sock);
if (the_client.sslclient == nullptr) {
return chAT::CommandStatus::ERROR;
}

const int internal_sock = the_client.can_delete;
if (internal_sock == -1) {
return chAT::CommandStatus::ERROR;
}

std::vector<unsigned char> client_cert_der;
client_cert_der = srv.inhibit_read(size);
size_t offset = client_cert_der.size();

if(offset < size) {
client_cert_der.resize(size);
do {
offset += serial->read(client_cert_der.data() + offset, size - offset);
} while (offset < size);
}
srv.continue_read();

#if ECC_DEBUG_ENABLED
log_v("_SETECCSLOT: input cert");
log_buf_v((const uint8_t *)client_cert_der.data(), size);
#endif

/* Convert client certificate DER buffer into PEM */
clients_cert_pem[internal_sock].resize(1024);
size_t olen;
int ret = -1;
if ((ret = mbedtls_pem_write_buffer("-----BEGIN CERTIFICATE-----\n",
"-----END CERTIFICATE-----\n",
client_cert_der.data(), size,
clients_cert_pem[internal_sock].data(), 1024,
&olen)) != 0)
{
log_e(" failed\n ! mbedtls_pem_write_buffer returned -0x%04x", (unsigned int) -ret);
clients_cert_pem[internal_sock].clear();
return chAT::CommandStatus::ERROR;
}
clients_cert_pem[internal_sock].resize(olen);

#if ECC_DEBUG_ENABLED
log_v("_SETECCSLOT: output cert");
log_v("\n%s", clients_cert_pem[internal_sock].data());
#endif

/* Set client certificate */
the_client.sslclient->setCertificate((const char *)clients_cert_pem[internal_sock].data());

/* Read private key from non volatile storage in DER format */
std::vector<unsigned char> client_key_der;
int len = sse.getBytesLength(slot_num.c_str());
client_key_der.resize(len);
if ((ret = sse.getBytes(slot_num.c_str(), client_key_der.data(), len)) < len) {
log_e(" failed\n ! sse.getBytes returned -0x%04x", (unsigned int) -ret);
return chAT::CommandStatus::ERROR;
}

#if ECC_DEBUG_ENABLED
log_v("_SETECCSLOT: input key");
log_buf_v((const uint8_t *)client_key_der.data(), ret);
#endif

/* Convert private key in PEM format */
clients_key_pem[internal_sock].resize(1024);
if ((ret = mbedtls_pem_write_buffer("-----BEGIN EC PRIVATE KEY-----\n",
"-----END EC PRIVATE KEY-----\n",
client_key_der.data(), len,
clients_key_pem[internal_sock].data(), 1024,
&olen)) != 0)
{
log_e(" failed\n ! mbedtls_pem_write_buffer returned -0x%04x", (unsigned int) -ret);
clients_cert_pem[internal_sock].clear();
return chAT::CommandStatus::ERROR;
}
clients_key_pem[internal_sock].resize(olen);

#if ECC_DEBUG_ENABLED
log_v("_SETECCSLOT: output key");
log_v("\n%s", clients_key_pem[internal_sock].data());
#endif

/* Set client key */
the_client.sslclient->setPrivateKey((const char *)clients_key_pem[internal_sock].data());

return chAT::CommandStatus::OK;
}
default:
return chAT::CommandStatus::ERROR;
}
};

/* ....................................................................... */
command_table[_SSLCLIENTSTATE] = [this](auto & srv, auto & parser) {
/* ....................................................................... */
Expand Down Expand Up @@ -166,6 +285,11 @@ void CAtHandler::add_cmds_wifi_SSL() {
return chAT::CommandStatus::ERROR;
}

const int internal_sock = the_client.can_delete;
if (internal_sock == -1) {
return chAT::CommandStatus::ERROR;
}

auto &host = parser.args[1];
if (host.empty()) {
return chAT::CommandStatus::ERROR;
Expand All @@ -176,6 +300,21 @@ void CAtHandler::add_cmds_wifi_SSL() {
return chAT::CommandStatus::ERROR;
}

/* Set custom root ca */
if (clients_ca[internal_sock].size()) {
the_client.sslclient->setCACert((const char *)clients_ca[internal_sock].data());
}
/* Default ca bundle is configured automatically on connect by the WiFiSSLClient */

if (clients_cert_pem[internal_sock].size()) {
/* Set client certificate */
the_client.sslclient->setCertificate((const char *)clients_cert_pem[internal_sock].data());
}
if (clients_key_pem[internal_sock].size()) {
/* Set client key */
the_client.sslclient->setPrivateKey((const char *)clients_key_pem[internal_sock].data());
}

if (!the_client.sslclient->connect(host.c_str(), atoi(port.c_str()))) {
return chAT::CommandStatus::ERROR;
}
Expand Down Expand Up @@ -210,6 +349,11 @@ void CAtHandler::add_cmds_wifi_SSL() {
return chAT::CommandStatus::ERROR;
}

const int internal_sock = the_client.can_delete;
if (internal_sock == -1) {
return chAT::CommandStatus::ERROR;
}

auto &hostip = parser.args[1];
if (hostip.empty()) {
return chAT::CommandStatus::ERROR;
Expand All @@ -225,6 +369,21 @@ void CAtHandler::add_cmds_wifi_SSL() {
return chAT::CommandStatus::ERROR;
}

/* Set custom root ca */
if (clients_ca[internal_sock].size()) {
the_client.sslclient->setCACert((const char *)clients_ca[internal_sock].data());
}
/* Default ca bundle is configured automatically on connect by the WiFiSSLClient */

if (clients_cert_pem[internal_sock].size()) {
/* Set client certificate */
the_client.sslclient->setCertificate((const char *)clients_cert_pem[internal_sock].data());
}
if (clients_key_pem[internal_sock].size()) {
/* Set client key */
the_client.sslclient->setPrivateKey((const char *)clients_key_pem[internal_sock].data());
}

if (!the_client.sslclient->connect(address, atoi(hostport.c_str()))) {
return chAT::CommandStatus::ERROR;
}
Expand Down Expand Up @@ -258,6 +417,11 @@ void CAtHandler::add_cmds_wifi_SSL() {
return chAT::CommandStatus::ERROR;
}

const int internal_sock = the_client.can_delete;
if (internal_sock == -1) {
return chAT::CommandStatus::ERROR;
}

auto &host = parser.args[1];
if (host.empty()) {
return chAT::CommandStatus::ERROR;
Expand All @@ -280,6 +444,21 @@ void CAtHandler::add_cmds_wifi_SSL() {
}
}

/* Set custom root ca */
if (clients_ca[internal_sock].size()) {
the_client.sslclient->setCACert((const char *)clients_ca[internal_sock].data());
}
/* Default ca bundle is configured automatically on connect by the WiFiSSLClient */

if (clients_cert_pem[internal_sock].size()) {
/* Set client certificate */
the_client.sslclient->setCertificate((const char *)clients_cert_pem[internal_sock].data());
}
if (clients_key_pem[internal_sock].size()) {
/* Set client key */
the_client.sslclient->setPrivateKey((const char *)clients_key_pem[internal_sock].data());
}

if (!the_client.sslclient->connect(host.c_str(), atoi(port.c_str()), timeout)) {
return chAT::CommandStatus::ERROR;
}
Expand Down Expand Up @@ -397,6 +576,9 @@ void CAtHandler::add_cmds_wifi_SSL() {
if(the_client.can_delete >= 0) {
delete sslclients[the_client.can_delete];
sslclients[the_client.can_delete] = nullptr;
clients_ca[the_client.can_delete].clear();
clients_cert_pem[the_client.can_delete].clear();
clients_key_pem[the_client.can_delete].clear();
sslclients_num--;
}
}
Expand Down
1 change: 1 addition & 0 deletions UNOR4USBBridge/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ enum file_op {
#define _CLIENTCONNECTED "+CLIENTCONNECTED"
#define _SSLBEGINCLIENT "+SSLBEGINCLIENT"
#define _SETCAROOT "+SETCAROOT"
#define _SETECCSLOT "+SETECCSLOT"
#define _SSLCLIENTSTATE "+SSLCLIENTSTATE"
#define _SSLCLIENTCONNECTNAME "+SSLCLIENTCONNECTNAME"
#define _SSLCLIENTCONNECT "+SSLCLIENTCONNECT"
Expand Down