arduino-emulator
Loading...
Searching...
No Matches
NetworkClientSecure.h
1/*
2 NetworkClientSecure.h
3 Copyright (c) 2025 Phil Schatzmann. All right reserved.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18*/
19
20#pragma once
21#if defined(USE_HTTPS)
22#include <errno.h>
23#include <wolfssl/options.h>
24#include <wolfssl/ssl.h>
25
26#include "Ethernet.h"
27#include "SocketImpl.h"
28
29namespace arduino {
30
31#define SOCKET_IMPL_SEC "SocketImplSecure"
32
33static int wolf_ssl_counter = 0;
34static WOLFSSL_CTX* wolf_ctx = nullptr;
35
41 public:
43 if (wolf_ssl_counter++ == 0 || wolf_ctx == nullptr) {
45 if ((wolf_ctx = wolfSSL_CTX_new(wolfTLS_client_method())) == NULL) {
46 Logger.error(SOCKET_IMPL_SEC, "wolfSSL_CTX_new error.");
47 }
48 }
49 if ((ssl = wolfSSL_new(wolf_ctx)) == NULL) {
50 Logger.error(SOCKET_IMPL_SEC, "wolfSSL_new error.");
51 }
52 }
53
55 if (ssl) {
56 wolfSSL_free(ssl);
57 ssl = nullptr;
58 }
59 if (--wolf_ssl_counter == 0 && wolf_ctx) {
60 wolfSSL_CTX_free(wolf_ctx);
61 wolf_ctx = nullptr;
63 }
64 }
65 // direct read
66 size_t read(uint8_t* buffer, size_t len) {
67 // size_t result = ::recv(sock, buffer, len, MSG_DONTWAIT );
68 if (ssl == nullptr) {
69 wolfSSL_set_fd(ssl, sock);
70 }
71 int result = ::wolfSSL_read(ssl, buffer, len);
72
73 if (result < 0) {
74 result = 0;
75 }
76 //
77 char lenStr[80];
78 sprintf(lenStr, "%ld -> %d", len, result);
79 Logger.debug(SOCKET_IMPL_SEC, "read->", lenStr);
80
81 return result;
82 }
83
84 int connect(const char* address, uint16_t port) override {
85 // Create socket
86 sock = ::socket(AF_INET, SOCK_STREAM, 0);
87 if (sock < 0) {
88 Logger.error(SOCKET_IMPL_SEC, "Socket creation failed");
89 return -1;
90 }
91
92 // Setup server address
93 memset(&serv_addr, 0, sizeof(serv_addr));
94 serv_addr.sin_family = AF_INET;
95 serv_addr.sin_port = htons(port);
96 if (::inet_pton(AF_INET, address, &serv_addr.sin_addr) <= 0) {
97 Logger.error(SOCKET_IMPL_SEC, "Invalid address", address);
98 ::close(sock);
99 sock = -1;
100 return -1;
101 }
102
103 // Connect to server
104 if (::connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
105 Logger.error(SOCKET_IMPL_SEC, "Connection failed");
106 ::close(sock);
107 sock = -1;
108 return -1;
109 }
110
111 // Set SSL file descriptor
112 wolfSSL_set_fd(ssl, sock);
113
114 // Set SNI (Server Name Indication) if needed
115 wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, address, strlen(address));
116
117 // Perform SSL handshake
118 int rc = wolfSSL_connect(ssl);
119 if (rc != SSL_SUCCESS) {
120 int err = wolfSSL_get_error(ssl, rc);
122 char msg[160];
123 snprintf(msg, sizeof(msg),
124 "SSL handshake failed, error code: %d reason: %s", err,
125 errStr ? errStr : "unknown");
126 Logger.error(SOCKET_IMPL_SEC, msg);
127 ::close(sock);
128 sock = -1;
129 return -1;
130 }
131
132 is_connected = true;
133 return 1;
134 }
135
136 // send the data via the socket - returns the number of characters written or
137 // -1=>Error
138 size_t write(const uint8_t* str, size_t len) {
139 Logger.debug(SOCKET_IMPL_SEC, "write");
140 if (ssl == nullptr) {
141 wolfSSL_set_fd(ssl, sock);
142 }
143 // return ::send(sock , str , len , 0 );
144 return ::wolfSSL_write(ssl, str, len);
145 }
146
147 void setCACert(const char* cert) override {
148 if (wolf_ctx == nullptr) return;
149 // Load CA certificate from a PEM string
150 int ret =
151 wolfSSL_CTX_load_verify_buffer(wolf_ctx, (const unsigned char*)cert,
153 if (ret != SSL_SUCCESS) {
154 Logger.error(SOCKET_IMPL_SEC, "Failed to load CA certificate");
155 }
156 }
157
158 void setInsecure() {
159 is_insecure = true;
160 if (wolf_ctx == nullptr) return;
161 // Disable certificate verification on context
162 wolfSSL_CTX_set_verify(wolf_ctx, SSL_VERIFY_NONE, nullptr);
163 // Also disable on SSL object if already created
164 if (ssl) wolfSSL_set_verify(ssl, SSL_VERIFY_NONE, nullptr);
165 }
166
167 protected:
168 WOLFSSL* ssl = nullptr;
169 bool is_insecure = false;
170};
171
176 public:
177 NetworkClientSecure(int bufferSize = 256, long timeout = 2000)
178 : EthernetClient(std::make_shared<SocketImplSecure>(), bufferSize, timeout) {}
179 void setCACert(const char* cert) override { p_sock->setCACert(cert); }
180 void setInsecure() override { p_sock->setInsecure(); }
181};
182
183} // namespace arduino
184
185#endif
Definition DMAPool.h:103
Definition Ethernet.h:128
NetworkClientSecure based on wolf ssl.
Definition NetworkClientSecure.h:175
Definition SocketImpl.h:26
SSL Socket using wolf ssl. For error codes see https://wolfssl.jp/docs-3/wolfssl-manual/appendix-c.
Definition NetworkClientSecure.h:40
We provide the WiFi class to simulate the Arduino WIFI. In in Linux we can expect that networking is ...
Definition CanMsg.cpp:31