wolfssl-examples/tls/memory-tls.c

211 lines
5.4 KiB
C

/* memory-tls.c
*
* Copyright (C) 2006-2020 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* in memory TLS connection with I/O callbacks, no sockets
*
gcc -Wall memory-tls.c -l wolfssl -lpthread
*/
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
/* client messages to server in memory */
unsigned char to_server[1024*17];
int server_bytes;
int server_write_idx;
int server_read_idx;
pthread_mutex_t server_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t server_cond = PTHREAD_COND_INITIALIZER;
/* server messages to client in memory */
unsigned char to_client[1024*17];
int client_bytes;
int client_write_idx;
int client_read_idx;
pthread_mutex_t client_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t client_cond = PTHREAD_COND_INITIALIZER;
/* server send callback */
int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
{
pthread_mutex_lock(&client_mutex);
memcpy(&to_client[client_write_idx], buf, sz);
client_write_idx += sz;
client_bytes += sz;
pthread_cond_signal(&client_cond);
pthread_mutex_unlock(&client_mutex);
return sz;
}
/* server recv callback */
int ServerRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
{
pthread_mutex_lock(&server_mutex);
while (server_bytes - server_read_idx < sz)
pthread_cond_wait(&server_cond, &server_mutex);
memcpy(buf, &to_server[server_read_idx], sz);
server_read_idx += sz;
if (server_read_idx == server_write_idx) {
server_read_idx = server_write_idx = 0;
server_bytes = 0;
}
pthread_mutex_unlock(&server_mutex);
return sz;
}
/* client send callback */
int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx)
{
pthread_mutex_lock(&server_mutex);
memcpy(&to_server[server_write_idx], buf, sz);
server_write_idx += sz;
server_bytes += sz;
pthread_cond_signal(&server_cond);
pthread_mutex_unlock(&server_mutex);
return sz;
}
/* client recv callback */
int ClientRecv(WOLFSSL* ssl, char* buf, int sz, void* ctx)
{
pthread_mutex_lock(&client_mutex);
while (client_bytes - client_read_idx < sz)
pthread_cond_wait(&client_cond, &client_mutex);
memcpy(buf, &to_client[client_read_idx], sz);
client_read_idx += sz;
if (client_read_idx == client_write_idx) {
client_read_idx = client_write_idx = 0;
client_bytes = 0;
}
pthread_mutex_unlock(&client_mutex);
return sz;
}
static void err_sys(const char* msg)
{
printf("wolfSSL error: %s\n", msg);
exit(1);
}
#define key "../certs/server-key.pem"
#define cert "../certs/server-cert.pem"
#define cacert "../certs/ca-cert.pem"
static void* client_thread(void* args)
{
/* set up client */
WOLFSSL_CTX* cli_ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
if (cli_ctx == NULL) err_sys("bad client ctx new");
int ret = wolfSSL_CTX_load_verify_locations(cli_ctx, cacert, NULL);
if (ret != WOLFSSL_SUCCESS) err_sys("bad ca load");
wolfSSL_SetIOSend(cli_ctx, ClientSend);
wolfSSL_SetIORecv(cli_ctx, ClientRecv);
WOLFSSL* cli_ssl = wolfSSL_new(cli_ctx);
if (cli_ctx == NULL) err_sys("bad client new");
ret = wolfSSL_connect(cli_ssl);
if (ret != WOLFSSL_SUCCESS) err_sys("bad client tls connect");
printf("wolfSSL client success!\n");
ret = wolfSSL_write(cli_ssl, "hello memory wolfSSL!", 21);
/* clean up */
wolfSSL_free(cli_ssl);
wolfSSL_CTX_free(cli_ctx);
return NULL;
}
int main()
{
/* set up server */
WOLFSSL_CTX* srv_ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method());
if (srv_ctx == NULL) err_sys("bad server ctx new");
int ret = wolfSSL_CTX_use_PrivateKey_file(srv_ctx, key, WOLFSSL_FILETYPE_PEM);
if (ret != WOLFSSL_SUCCESS) err_sys("bad server key file load");
ret = wolfSSL_CTX_use_certificate_file(srv_ctx, cert, WOLFSSL_FILETYPE_PEM);
if (ret != WOLFSSL_SUCCESS) err_sys("bad server cert file load");
wolfSSL_SetIOSend(srv_ctx, ServerSend);
wolfSSL_SetIORecv(srv_ctx, ServerRecv);
WOLFSSL* srv_ssl = wolfSSL_new(srv_ctx);
if (srv_ctx == NULL) err_sys("bad server new");
/* start client thread */
pthread_t tid;
pthread_create(&tid, 0, client_thread, NULL);
/* accept tls connection without tcp sockets */
ret = wolfSSL_accept(srv_ssl);
if (ret != WOLFSSL_SUCCESS) err_sys("bad server tls accept");
printf("wolfSSL accept success!\n");
/* read msg post handshake from client */
unsigned char buf[80];
memset(buf, 0, sizeof(buf));
ret = wolfSSL_read(srv_ssl, buf, sizeof(buf)-1);
printf("client msg = %s\n", buf);
/* clean up */
wolfSSL_free(srv_ssl);
wolfSSL_CTX_free(srv_ctx);
return 0;
}