Skip to content

Commit

Permalink
SocketWrapper: implement SSLClient
Browse files Browse the repository at this point in the history
connect() temporarily accepts a third parameter with a PEM encoded certificate

Cleanest way to add it is via raw strings

const char * certificate = R"(-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----)";
  • Loading branch information
facchinm committed Dec 18, 2024
1 parent 83cc65e commit 3ef1d37
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 2 deletions.
96 changes: 94 additions & 2 deletions libraries/SocketWrapper/SocketWrapper.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
#pragma once

#include "zephyr/sys/printk.h"
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
#include <zephyr/net/tls_credentials.h>
#define CA_CERTIFICATE_TAG 1
#endif

#include <zephyr/net/socket.h>

class ZephyrSocketWrapper {
protected:
int sock_fd;
bool is_ssl = false;
int ssl_sock_temp_char = -1;

public:
ZephyrSocketWrapper() : sock_fd(-1) {}
Expand Down Expand Up @@ -33,6 +41,8 @@ class ZephyrSocketWrapper {

if (ret == 0) {
break;
} else {
k_sleep(K_MSEC(1));
}
}

Expand Down Expand Up @@ -77,11 +87,86 @@ class ZephyrSocketWrapper {
return true;
}

#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
bool connectSSL(const char* host, uint16_t port, char* ca_certificate_pem = nullptr) {

// Resolve address
struct addrinfo hints;
struct addrinfo *res;

hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

int resolve_attempts = 100;
int ret;

while (resolve_attempts--) {
ret = getaddrinfo(host, String(port).c_str(), &hints, &res);

if (ret == 0) {
break;
} else {
k_sleep(K_MSEC(1));
}
}

if (ret != 0) {
return false;
}

if (ca_certificate_pem != nullptr) {
ret = tls_credential_add(CA_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
ca_certificate_pem, strlen(ca_certificate_pem) + 1);
Serial.println(ret);
}

sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
if (sock_fd < 0) {
return false;
}

sec_tag_t sec_tag_opt[] = {
CA_CERTIFICATE_TAG,
};
setsockopt(sock_fd, SOL_TLS, TLS_SEC_TAG_LIST,
sec_tag_opt, sizeof(sec_tag_opt));

setsockopt(sock_fd, SOL_TLS, TLS_HOSTNAME, host, strlen(host));

uint32_t timeo_optval = 100;
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_optval, sizeof(timeo_optval));

if (::connect(sock_fd, res->ai_addr, res->ai_addrlen) < 0) {
::close(sock_fd);
sock_fd = -1;
return false;
}
is_ssl = true;

return true;
}
#endif

int available() {
int count = 0;
zsock_ioctl(sock_fd, ZFD_IOCTL_FIONREAD, &count);
if (count == 0) {
if (is_ssl) {
/*
TODO: HACK:
The correct colution would be to call
::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_PEEK | MSG_DONTWAIT);
but it doesn't seem to work. Instead, save a temporary variable
and use it in read()
*/
if (ssl_sock_temp_char != -1) {
return 1;
}
count = ::recv(sock_fd, &ssl_sock_temp_char, 1, MSG_DONTWAIT);
} else {
zsock_ioctl(sock_fd, ZFD_IOCTL_FIONREAD, &count);
}
if (count <= 0) {
delay(1);
count = 0;
}
return count;
}
Expand All @@ -90,6 +175,13 @@ class ZephyrSocketWrapper {
if (sock_fd == -1) {
return -1;
}
// TODO: see available()
if (ssl_sock_temp_char != -1) {
int ret = ::recv(sock_fd, &buffer[1], size - 1, flags);
buffer[0] = ssl_sock_temp_char;
ssl_sock_temp_char = -1;
return ret + 1;
}
return ::recv(sock_fd, buffer, size, flags);
}

Expand Down
12 changes: 12 additions & 0 deletions libraries/SocketWrapper/ZephyrClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ class ZephyrClient : public arduino::Client, ZephyrSocketWrapper {
}
return ret;
}
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
int connectSSL(const char* host, uint16_t port, const char* cert) {
return this->connectSSL(host, port, (char*)cert);
}
int connectSSL(const char* host, uint16_t port, char* cert) {
auto ret = ZephyrSocketWrapper::connectSSL((char*)host, port, cert);
if (ret) {
_connected = true;
}
return ret;
}
#endif
uint8_t connected() override {
return _connected;
}
Expand Down
18 changes: 18 additions & 0 deletions libraries/SocketWrapper/ZephyrSSLClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "SocketWrapper.h"
#include "api/Client.h"
#include "unistd.h"
#include "zephyr/sys/printk.h"
#include "ZephyrClient.h"

#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
class ZephyrSSLClient : public ZephyrClient {

public:
int connect(const char* host, uint16_t port, const char* cert) {
return connectSSL(host, port, (char*)cert);
}
int connect(const char* host, uint16_t port, char* cert) {
return connectSSL(host, port, cert);
}
};
#endif

0 comments on commit 3ef1d37

Please sign in to comment.