#include "wolfssl/ssl.h"
#include "certs.h"
#include "lwip/tcp.h"
#include "tls_client.h"
#include <stdlib.h>
static WOLFSSL_CTX *g_ctx = NULL;
#define TLS_RX_BUF_SIZE 4096
typedef enum {
TLS_STATE_IDLE = 0,
TLS_STATE_TCP_CONNECTING,
TLS_STATE_TCP_CONNECTED,
TLS_STATE_TLS_HANDSHAKE,
TLS_STATE_TLS_ESTABLISHED,
TLS_STATE_ERROR
} tls_state_t;
typedef struct {
struct tcp_pcb* pcb;
WOLFSSL* ssl;
tls_state_t state;
uint8_t rxBuf[TLS_RX_BUF_SIZE];
uint32_t rxHead;
uint32_t rxTail;
int lastErr; // debug
} tls_conn_t;
static tls_conn_t g_tls;
//
//static void* myMalloc(size_t n) { return malloc(n); }
//static void myFree(void* p) { free(p); }
//static void* myRealloc(void* p, size_t n) { return realloc(p, n); }
static uint32_t tls_rx_available(tls_conn_t* c) {
if (c->rxHead >= c->rxTail)
return c->rxHead - c->rxTail;
else
return TLS_RX_BUF_SIZE - (c->rxTail - c->rxHead);
}
static uint32_t tls_rx_space(tls_conn_t* c) {
return TLS_RX_BUF_SIZE - 1 - tls_rx_available(c);
}
static void tls_rx_push(tls_conn_t* c, const uint8_t* data, uint32_t len) {
while (len--) {
c->rxBuf[c->rxHead] = *data++;
c->rxHead = (c->rxHead + 1) % TLS_RX_BUF_SIZE;
}
}
static uint32_t tls_rx_pop(tls_conn_t* c, uint8_t* dst, uint32_t maxLen) {
uint32_t avail = tls_rx_available(c);
if (avail == 0) return 0;
if (maxLen > avail) maxLen = avail;
for (uint32_t i = 0; i < maxLen; i++) {
dst[i] = c->rxBuf[c->rxTail];
c->rxTail = (c->rxTail + 1) % TLS_RX_BUF_SIZE;
}
return maxLen;
}
static err_t tls_tcp_connected_cb(void *arg, struct tcp_pcb *tpcb, err_t err)
{
tls_conn_t* c = (tls_conn_t*)arg;
printf("connected_cb err=%d\r\n", (int)err);
if (err != ERR_OK) {
c->state = TLS_STATE_ERROR;
return err;
}
c->state = TLS_STATE_TCP_CONNECTED;
return ERR_OK;
}
static err_t tls_tcp_recv_cb(void *arg, struct tcp_pcb *tpcb,
struct pbuf *p, err_t err)
{
tls_conn_t* c = (tls_conn_t*)arg;
if (p == NULL) {
c->state = TLS_STATE_ERROR;
return ERR_OK;
}
if (tls_rx_space(c) < p->tot_len) {
printf("RX overflow -> abort TLS\n");
pbuf_free(p);
// tcp_abort(tpcb);
c->state = TLS_STATE_ERROR;
c->lastErr = ERR_MEM;
return ERR_ABRT;
}
struct pbuf* q = p;
while (q) {
tls_rx_push(c, (uint8_t*)q->payload, q->len);
q = q->next;
}
tcp_recved(tpcb, p->tot_len);
pbuf_free(p);
return ERR_OK;
}
static void tls_tcp_err_cb(void *arg, err_t err)
{
tls_conn_t* c = (tls_conn_t*)arg;
printf("tcp_err_cb err=%d\r\n", (int)err);
c->state = TLS_STATE_ERROR;
c->lastErr = err;
}
/* wird via WOLFSSL_USER_IO verwendet */
static int my_IORecv(WOLFSSL* ssl, char* buff, int sz, void* ctx)
{
tls_conn_t* c = (tls_conn_t*)ctx;
uint32_t n = tls_rx_pop(c, (uint8_t*)buff, (uint32_t)sz);
if (n == 0) {
// keine Daten gerade → nicht blocken
return WOLFSSL_CBIO_ERR_WANT_READ;
}
return (int)n;
}
static int my_IOSend(WOLFSSL* ssl, char* buff, int sz, void* ctx)
{
static int cnt = 0;
cnt++;
printf("IOSend #%d sz=%d\r\n", cnt, sz);
tls_conn_t* c = (tls_conn_t*)ctx;
if (c->pcb == NULL) return WOLFSSL_CBIO_ERR_CONN_CLOSE;
err_t err = tcp_write(c->pcb, buff, sz, TCP_WRITE_FLAG_COPY);
if (err == ERR_MEM) {
return WOLFSSL_CBIO_ERR_WANT_WRITE;
} else if (err != ERR_OK) {
return WOLFSSL_CBIO_ERR_GENERAL;
}
tcp_output(c->pcb);
return sz;
}
static void wolfssl_dump_errors(void)
{
unsigned long e;
char buf[WOLFSSL_MAX_ERROR_SZ];
while ((e = wolfSSL_ERR_get_error()) != 0) {
wolfSSL_ERR_error_string_n(e, buf, sizeof(buf));
printf("wolfSSL: %s\n", buf);
}
}
void test_rng(void) {
WC_RNG rng;
int ret = wc_InitRng(&rng);
if (ret != 0) {
char msg[WOLFSSL_MAX_ERROR_SZ];
wc_ErrorString(ret, msg);
printf("wc_InitRng failed: %d (%s)\r\n", ret, msg);
return;
}
wc_FreeRng(&rng);
printf("wc_InitRng OK\r\n");
}
void TLS_GlobalInit(void)
{
test_rng();
wolfSSL_Init();
int i = 0;
int ret;
// wolfSSL_SetAllocators(myMalloc, myFree, myRealloc);
g_ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
wolfSSL_SetIORecv(g_ctx, my_IORecv);
wolfSSL_SetIOSend(g_ctx, my_IOSend);
if (g_ctx == NULL)
{
/* fatal – keine TLS-Konfiguration */
while (1)
{
if (i == 0)
{
printf("leider falsch\n");
i += 1;
}
}
}
ret = wolfSSL_CTX_load_verify_buffer(g_ctx, ca_ed25519_der,
ca_ed25519_der_len, WOLFSSL_FILETYPE_ASN1);
// wolfSSL_CTX_set_verify(g_ctx, WOLFSSL_VERIFY_NONE, 0);
if (ret != WOLFSSL_SUCCESS) {
char errBuf[80];
/* Bei ctx-Funktionen einfach direkt den Code in einen String umwandeln: */
wolfSSL_ERR_error_string_n((unsigned long)ret, errBuf, sizeof(errBuf));
printf("load_verify_buffer failed: %d (%s)\n", ret, errBuf);
}
printf("hallihallo\n");
}
void TLS_ClientStart(const ip_addr_t* ip, u16_t port)
{
memset(&g_tls, 0, sizeof(g_tls));
g_tls.pcb = tcp_new();
if (g_tls.pcb == NULL) {
g_tls.state = TLS_STATE_ERROR;
return;
}
g_tls.state = TLS_STATE_TCP_CONNECTING;
tcp_arg(g_tls.pcb, &g_tls); // our connection struct as arg
tcp_err(g_tls.pcb, tls_tcp_err_cb);
tcp_recv(g_tls.pcb, tls_tcp_recv_cb);
err_t e = tcp_connect(g_tls.pcb, ip, port, tls_tcp_connected_cb);
printf("tcp_connect()=%d\r\n", (int)e);
if (e != ERR_OK) { g_tls.state = TLS_STATE_ERROR; g_tls.lastErr = e; }
}
void TLS_ClientProcess(void)
{
int ret;
switch (g_tls.state) {
case TLS_STATE_TCP_CONNECTED:
printf("g_ctx=%p\r\n", (void*)g_ctx);
g_tls.ssl = wolfSSL_new(g_ctx);
if (g_tls.ssl == NULL) {
g_tls.state = TLS_STATE_ERROR;
break;
}
// wolfSSL_SSLSetIORecv(g_tls.ssl, my_IORecv); //extra
// wolfSSL_SSLSetIOSend(g_tls.ssl, my_IOSend); //etxra
wolfSSL_SetIOReadCtx(g_tls.ssl, &g_tls);
wolfSSL_SetIOWriteCtx(g_tls.ssl, &g_tls);
wolfSSL_set_using_nonblock(g_tls.ssl, 1);
g_tls.state = TLS_STATE_TLS_HANDSHAKE;
break;
case TLS_STATE_TLS_HANDSHAKE:
// const char dummy[] = "X";
// ret = wolfSSL_write(g_tls.ssl, dummy, sizeof(dummy));
// int err = wolfSSL_get_error(g_tls.ssl, ret);
// printf("wolfSSL_write ret=%d err=%d\r\n", ret, err);
ret = wolfSSL_connect(g_tls.ssl);
if (ret == WOLFSSL_SUCCESS) {
printf("TLS handshake OK\r\n");
g_tls.state = TLS_STATE_TLS_ESTABLISHED;
} else
{
int err = wolfSSL_get_error(g_tls.ssl, ret);
if (err == WOLFSSL_ERROR_WANT_READ ||
err == WOLFSSL_ERROR_WANT_WRITE) {
} else {
printf("TLS handshake failed: %d\r\n", err);
g_tls.state = TLS_STATE_ERROR;
wolfssl_dump_errors(); // <-- zeigt den echten Grund
}
}
break;
case TLS_STATE_TLS_ESTABLISHED:
/* hier könntest du z.B. einmalig etwas senden: */
// const char* msg = "HELLO FROM STM32\r\n";
// wolfSSL_write(g_tls.ssl, msg, strlen(msg));
// g_tls.state = TLS_STATE_IDLE; // oder weitere Logik
break;
case TLS_STATE_ERROR:
printf("tcp_err_cb: err=%d\r\n", g_tls.lastErr);
// printf("TCP connect failed, err=%d\r\n", g_tls.lastErr);
// ggf. pcb/ssl freigeben etc.
g_tls.state = TLS_STATE_TLS_HANDSHAKE;
break;
default:
// printf("TCP connect failed, err=%d\r\n", g_tls.state);
break;
}
}