Added BTLE TLS v1.3 example.

pull/293/head
David Garske 2022-02-14 16:07:19 -08:00
parent 3b21b61df6
commit 809e5351bb
13 changed files with 668 additions and 112 deletions

6
.gitignore vendored
View File

@ -119,8 +119,10 @@ certgen/ed25519-key.pem
certgen/newCert.der
certgen/newCert.pem
btle/ecc-client
btle/ecc-server
btle/ecies/ecc-client
btle/ecies/ecc-server
btle/tls/server-tls13-btle
btle/tls/client-tls13-btle
signature/sigtest/wolfsigtest
signature/sigtest/opensigtest

View File

@ -4,35 +4,28 @@ BTLE / Lightweight Secure Transport Example:
Bluetooth Low Energy (BTLE) is a lightweight / low power wireless protocol. Its supported by Apple iPhone 4s and later and most Android phones. It operates in the 2.4GHz spectrum and has 3 advertising channels and 37 data channels.
This example demonstrates a lightweight method for exchanging data securely over any type of publicly visible link.
## Elliptic Curve Integrated Encryption Scheme (ECIES) Example
The first phase is key establishment, which is done through ECDH and HDKF. ECC was chosen for these examples because its lightweight and widely used. Then salt exchanged for each message to prevent reply attacks. The encryption is done with AES CBC. The data integrity is done using HMAC-SHA256.
wolfSSL ECIES support:
* SEC1: `--enable-eccencrypt=yes`
* ISO 18033: `--enable-eccencrypt=iso18033`
* wolfSSL proprietary version: `--enable-eccencrypt=old`
ECIES Features:
* Encryption: AES CBC or Counter
* Integrity: HMAC-SHA2-256
* Keys: ECDHE
* Nonce: for each message to prevent replay
* Authentication: Out of band
## ECC Encrypt/Decrypt Example
## TLS v1.3 Example
See `BTLESecureMessageExchange.pdf` for details.
### Building
The wolfSSL library must be built and installed using './configure --enable-ecc --enable-eccencrypt --enable-hkdf && make && sudo make install' or by defining `#define HAVE_ECC`, `#define HAVE_ECC_ENCRYPT` and `HAVE_HKDF`.
### Usage
Use two consoles and STDIN to exchange data between the client and server. From the client enter a message and hit enter. This will be encrypted and sent to the server. The server will decrypt, print and re-encrypt the message and send it back to the client (echo).
```
./ecc-server
./ecc-client
```
### Debugging
To enable debugging or switch to using a static version of wolfSSL edit the `Makefile` and uncomment `CFLAGS+=$(DEBUG_FLAGS)` and `STATIC_LIB+=$(LIB_PATH)/lib/libwolfssl.a`. Then comment out `LIBS+=$(DYN_LIB) -lm`.
TLS v1.3 Features:
* Encryption: AES-GCM or ChaCha20/Poly1305
* Authentication: Standard X.509 certificates against long term key (recommend ECC)
* Resumption: Session Tickets.
## BTLE Simulator
The simulator uses IPC (pipes) to communicate between threads for simulated communication between two devices.
These example use a BTLE simulator to demonstrate communications between devices. The simulator uses IPC (pipes) to communicate between threads.

View File

@ -19,13 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/logging.h>
#include "btle-sim.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/select.h>
@ -36,14 +29,10 @@
#include <unistd.h>
#include <string.h>
//#define BTLE_DEBUG_IO
#define BTLE_VER 1
#include "btle-sim.h"
typedef struct {
int role;
int fdmiso;
int fdmosi;
} BtleDev_t;
//#define DEBUG_BTLE_IO
#define BTLE_VER 1
typedef struct {
unsigned char ver;
@ -51,6 +40,20 @@ typedef struct {
unsigned short len;
} __attribute__ ((packed)) BtleHeader_t;
typedef struct {
int pos;
int total;
BtleHeader_t header;
} BtlePkt_t;
typedef struct {
int role;
int fdmiso;
int fdmosi;
BtlePkt_t recv;
BtlePkt_t send;
} BtleDev_t;
static BtleDev_t gBtleDev;
static const char* kBtleMisoFifo = "/tmp/btleMiso";
static const char* kBtleMosiFifo = "/tmp/btleMosi";
@ -66,44 +69,50 @@ static int btle_get_read(BtleDev_t* dev)
return (dev->role == BTLE_ROLE_SERVER) ? dev->fdmiso : dev->fdmosi;
}
static int btle_send_block(BtleDev_t* dev, const unsigned char* buf, int len, int fd)
static int btle_send_block(BtleDev_t* dev, const unsigned char* buf,int len)
{
int ret;
int fd = btle_get_write(dev);
ret = write(fd, buf, len);
#ifdef BTLE_DEBUG_IO
#ifdef DEBUG_BTLE_IO
printf("Write: %d\n", ret);
WOLFSSL_BUFFER(buf, len);
#endif
(void)dev;
return ret;
}
static int btle_recv_block(BtleDev_t* dev, unsigned char* buf, int len, int fd)
static int btle_recv_block(BtleDev_t* dev, unsigned char* buf, int len,
int non_block)
{
fd_set set;
int ret, pos = 0;
int fd = btle_get_read(dev);
FD_ZERO(&set);
FD_SET(fd, &set);
while (pos < len) {
ret = select(fd+1, &set, NULL, NULL, NULL);
if (ret == 0)
if (ret == 0) {
if (non_block)
return 0;
continue;
}
if (ret < 0)
return ret;
if (FD_ISSET(fd, &set)) {
ret = read(fd, &buf[pos], len - pos);
#ifdef BTLE_DEBUG_IO
#ifdef DEBUG_BTLE_IO
printf("Read: %d\n", ret);
WOLFSSL_BUFFER(&buf[pos], len-pos);
#endif
if (ret > 0) {
pos += ret;
}
else {
if (errno == EWOULDBLOCK) {
if (non_block)
return 0;
continue;
}
else {
@ -143,68 +152,92 @@ int btle_open(void** dev, int role)
return -1;
}
memset(&gBtleDev, 0, sizeof(gBtleDev));
gBtleDev.role = role;
gBtleDev.fdmiso = fdmiso;
gBtleDev.fdmosi = fdmosi;
if (dev)
if (dev) {
*dev = &gBtleDev;
}
return 0;
}
int btle_send(const unsigned char* buf, int len, int type, void* context)
{
BtleDev_t* dev = (BtleDev_t*)context;
BtleHeader_t header;
int fd = btle_get_write(dev);
int ret;
header.ver = BTLE_VER;
header.type = type;
header.len = len;
ret = btle_send_block(dev, (unsigned char*)&header, sizeof(header), fd);
if (ret < 0)
return ret;
ret = btle_send_block(dev, buf, len, fd);
if (ret < 0)
return ret;
return len;
BtleDev_t* dev = (BtleDev_t*)context;
if (dev == NULL)
return -1;
memset(&dev->send.header, 0, sizeof(dev->send.header));
dev->send.header.ver = BTLE_VER;
dev->send.header.type = type;
dev->send.header.len = len;
ret = btle_send_block(dev, (unsigned char*)&dev->send.header,
sizeof(dev->send.header));
if (ret > 0) {
ret = btle_send_block(dev, buf, len);
}
return ret;
}
int btle_recv_ex(unsigned char* buf, int len, int* type, void* context,
int non_block)
{
int ret;
BtleDev_t* dev = (BtleDev_t*)context;
if (dev == NULL)
return -1;
if (dev->recv.total == 0) {
/* read header */
memset(&dev->recv.header, 0, sizeof(dev->recv.header));
ret = btle_recv_block(dev, (unsigned char*)&dev->recv.header,
sizeof(dev->recv.header), non_block);
if (ret <= 0)
return ret;
if (dev->recv.header.ver != BTLE_VER)
return -1;
dev->recv.total = dev->recv.header.len;
dev->recv.pos = 0;
}
/* read data */
if (len > dev->recv.total - dev->recv.pos) {
len = dev->recv.total - dev->recv.pos;
}
ret = btle_recv_block(dev, buf, len, non_block);
if (ret > 0) {
dev->recv.pos += ret;
}
if (type) {
*type = dev->recv.header.type;
}
if (ret < 0 || dev->recv.pos >= dev->recv.total) {
/* reset recv state */
memset(&dev->recv.header, 0, sizeof(dev->recv.header));
dev->recv.total = 0;
dev->recv.pos = 0;
}
return ret;
}
int btle_recv(unsigned char* buf, int len, int* type, void* context)
{
BtleDev_t* dev = (BtleDev_t*)context;
BtleHeader_t header;
int ret;
int fd = btle_get_read(dev);
ret = btle_recv_block(dev, (unsigned char*)&header, sizeof(header), fd);
if (ret < 0)
return ret;
if (header.ver != BTLE_VER)
return -1;
if (type)
*type = header.type;
if (len > 0) {
ret = header.len;
if (ret > len)
ret = len;
ret = btle_recv_block(dev, buf, ret, fd);
if (ret < 0)
return ret;
}
return header.len;
return btle_recv_ex(buf, len, type, context, 0);
}
void btle_close(void* context)
{
BtleDev_t* dev = (BtleDev_t*)context;
if (dev == NULL)
return;
close(dev->fdmiso);
close(dev->fdmosi);

View File

@ -28,6 +28,7 @@ typedef enum {
BTLE_PKT_TYPE_KEY,
BTLE_PKT_TYPE_SALT,
BTLE_PKT_TYPE_MSG,
BTLE_PKT_TYPE_TLS,
BTLE_PKT_TYPE_MAX,
} BtlePacket_t;
@ -40,5 +41,6 @@ typedef enum {
int btle_open(void** dev, int role);
int btle_send(const unsigned char* buf, int len, int type, void* context);
int btle_recv(unsigned char* buf, int len, int* type, void* context);
int btle_recv_ex(unsigned char* buf, int len, int* type, void* context, int non_block);
void btle_close(void* context);
int btle_msg_pad(unsigned char* buf, int* len, void* context);

View File

@ -7,7 +7,7 @@ LIBS = -L$(LIB_PATH)/lib
# option variables
DYN_LIB = -lwolfssl
STATIC_LIB =
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_WOLFSSL
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_WOLFSSL -DDEBUG_BTLE_IO
OPTIMIZE = -Os
# Options
@ -31,13 +31,13 @@ debug: all
%.o: %.c
gcc -c $< -o $@ $(CFLAGS)
ecc-server: ecc-server.o btle-sim.o $(STATIC_LIB)
ecc-server: ecc-server.o ../btle-sim.o $(STATIC_LIB)
$(CC) $^ -o $@ $(LIBS)
ecc-client: ecc-client.o btle-sim.o $(STATIC_LIB)
ecc-client: ecc-client.o ../btle-sim.o $(STATIC_LIB)
$(CC) $^ -o $@ $(LIBS)
clean:
rm *.o
rm ecc-server
rm ecc-client
rm -f *.o ../*.o
rm -f ecc-server
rm -f ecc-client

View File

@ -0,0 +1,44 @@
# BTLE ECIES Example
This example demonstrates a lightweight method for exchanging data securely over any type of publicly visible link.
The first phase is key establishment, which is done through ECDH and HDKF. ECC was chosen for these examples because its lightweight and widely used.
Then salt exchanged for each message to prevent reply attacks. The encryption is done with AES CBC. The data integrity is done using HMAC-SHA256.
## ECC Encrypt/Decrypt Example
See `BTLESecureMessageExchange.pdf` for details.
### Building
The wolfSSL library must be built and installed using:
```
./configure --enable-ecc --enable-eccencrypt --enable-hkdf
make
sudo make install
```
OR by defining:
```
#define HAVE_ECC
#define HAVE_ECC_ENCRYP
#define HAVE_HKDF
```
### Usage
Use two consoles and STDIN to exchange data between the client and server.
From the client enter a message and hit enter. This will be encrypted and sent to the server. The server will decrypt, print and re-encrypt the message and send it back to the client (echo).
```
./ecc-server
./ecc-client
```
### Debugging
To enable debugging or switch to using a static version of wolfSSL edit the `Makefile` and uncomment `CFLAGS+=$(DEBUG_FLAGS)` and `STATIC_LIB+=$(LIB_PATH)/lib/libwolfssl.a`. Then comment out `LIBS+=$(DYN_LIB) -lm`.

View File

@ -19,12 +19,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wolfssl/options.h>
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include "btle-sim.h"
#include "../btle-sim.h"
int main(int argc, char** argv)
{
@ -41,7 +42,7 @@ int main(int argc, char** argv)
ecc_key myKey, peerKey;
int type;
wolfSSL_Init();
wolfCrypt_Init();
#ifdef DEBUG_WOLFSSL
wolfSSL_Debugging_ON();
@ -58,7 +59,7 @@ int main(int argc, char** argv)
/* open BTLE */
ret = btle_open(&devCtx, BTLE_ROLE_CLIENT);
if (ret != 0) {
printf("btle_open failed %d! errno %d\n", ret, errno);
printf("btle_open failed %d!\n", ret);
goto cleanup;
}
@ -136,7 +137,7 @@ int main(int argc, char** argv)
/* Get peer salt */
ret = btle_recv(peerSalt, EXCHANGE_SALT_SZ, &type, devCtx);
if (ret <= 0) {
printf("btle_recv failed %d! errno %d\n", ret, errno);
printf("btle_recv failed %d!\n", ret);
}
if (type != BTLE_PKT_TYPE_SALT) {
printf("btle_recv expected salt!\n");
@ -209,7 +210,7 @@ cleanup:
if (devCtx != NULL)
btle_close(devCtx);
wolfSSL_Cleanup();
wolfCrypt_Cleanup();
return ret;
}

View File

@ -19,12 +19,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wolfssl/options.h>
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include "btle-sim.h"
#include "../btle-sim.h"
int main(int argc, char** argv)
{
@ -41,7 +42,7 @@ int main(int argc, char** argv)
ecc_key myKey, peerKey;
int type;
wolfSSL_Init();
wolfCrypt_Init();
#ifdef DEBUG_WOLFSSL
wolfSSL_Debugging_ON();
@ -58,7 +59,7 @@ int main(int argc, char** argv)
/* open BTLE */
ret = btle_open(&devCtx, BTLE_ROLE_SERVER);
if (ret != 0) {
printf("btle_open failed %d! errno %d\n", ret, errno);
printf("btle_open failed %d!\n", ret);
goto cleanup;
}
@ -84,7 +85,7 @@ int main(int argc, char** argv)
/* Get peer key */
ret = btle_recv(buffer, sizeof(buffer), &type, devCtx);
if (ret < 0) {
printf("btle_recv key failed %d! errno %d\n", ret, errno);
printf("btle_recv key failed %d!\n", ret);
goto cleanup;
}
if (type != BTLE_PKT_TYPE_KEY) {
@ -126,7 +127,7 @@ int main(int argc, char** argv)
/* Get peer salt */
ret = btle_recv(peerSalt, EXCHANGE_SALT_SZ, &type, devCtx);
if (ret <= 0) {
printf("btle_recv salt failed %d! errno %d\n", ret, errno);
printf("btle_recv salt failed %d!\n", ret);
goto cleanup;
}
if (type != BTLE_PKT_TYPE_SALT) {
@ -152,7 +153,7 @@ int main(int argc, char** argv)
bufferSz = sizeof(buffer);
ret = btle_recv(buffer, bufferSz, &type, devCtx);
if (ret <= 0) {
printf("btle_recv msg failed %d! errno %d\n", ret, errno);
printf("btle_recv msg failed %d!\n", ret);
goto cleanup;
}
if (type != BTLE_PKT_TYPE_MSG) {
@ -203,7 +204,7 @@ cleanup:
if (devCtx != NULL)
btle_close(devCtx);
wolfSSL_Cleanup();
wolfCrypt_Cleanup();
return ret;
}

43
btle/tls/Makefile 100644
View File

@ -0,0 +1,43 @@
# BTLE Examples Makefile
CC = gcc
LIB_PATH = /usr/local
CFLAGS = -Wall -I$(LIB_PATH)/include
LIBS = -L$(LIB_PATH)/lib
# option variables
DYN_LIB = -lwolfssl
STATIC_LIB =
DEBUG_FLAGS = -g -DDEBUG -DDEBUG_WOLFSSL -DDEBUG_BTLE_IO
OPTIMIZE = -Os
# Options
#CFLAGS+=$(DEBUG_FLAGS)
CFLAGS+=$(OPTIMIZE)
# Static or Dynamic Library
#STATIC_LIB+=$(LIB_PATH)/lib/libwolfssl.a
LIBS+=$(DYN_LIB) -lm
.PHONY: clean all
all: server-tls13-btle client-tls13-btle
debug: CFLAGS+=$(DEBUG_FLAGS)
debug: all
# build template
%.o: %.c
gcc -c $< -o $@ $(CFLAGS)
server-tls13-btle: server-tls13-btle.o ../btle-sim.o $(STATIC_LIB)
$(CC) $^ -o $@ $(LIBS)
client-tls13-btle: client-tls13-btle.o ../btle-sim.o $(STATIC_LIB)
$(CC) $^ -o $@ $(LIBS)
clean:
rm -f *.o ../*.o
rm -f server-tls13-btle
rm -f client-tls13-btle

39
btle/tls/README.md 100644
View File

@ -0,0 +1,39 @@
# BTLE TLS v1.3 Example
This example demonstrates using TLS v1.3 to exchange data securely over a BTLE type transport link.
### Building
The wolfSSL library must be built and installed using:
```
./configure --enable-tls13
make
sudo make install
```
### Usage
Use two consoles run the examples to send a test message securely. The server will present an ECC server certificate and the client will validate it.
```
% ./server-tls13-btle
Waiting for client
TLS accepting
TLS Accept handshake done
Read (0): Testing 1, 2 and 3
Sent (0): Testing 1, 2 and 3
```
```
% ./client-tls13-btle
TLS connecting
TLS Connect handshake done
Sending test string
Sent (0): Testing 1, 2 and 3
Read (0): Testing 1, 2 and 3
```
### Debugging
To enable debugging or switch to using a static version of wolfSSL edit the `Makefile` and uncomment `CFLAGS+=$(DEBUG_FLAGS)` and `STATIC_LIB+=$(LIB_PATH)/lib/libwolfssl.a`. Then comment out `LIBS+=$(DYN_LIB) -lm`.

View File

@ -0,0 +1,201 @@
/* client-tls13-btle.c
*
* Copyright (C) 2006-2022 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
*
*=============================================================================
*
* Example TLSv1.3 client over BTLE
*/
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include "../btle-sim.h"
#define CERT_FILE "../../certs/client-cert.pem"
#define KEY_FILE "../../certs/client-key.pem"
#define CA_FILE "../../certs/ca-cert.pem"
typedef struct CbCtx {
void* devCtx;
} CbCtx_t;
static int btleIORx(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
int recvd;
CbCtx_t* cbCtx = (CbCtx_t*)ctx;
#ifdef DEBUG_BTLE_IO
printf("BTLE Read: In %d\n", sz);
#endif
recvd = btle_recv((unsigned char*)buf, sz, NULL, cbCtx->devCtx);
if (recvd == 0) {
return WOLFSSL_CBIO_ERR_WANT_READ;
}
#ifdef DEBUG_BTLE_IO
printf("BTLE Read: Out %d\n", recvd);
#endif
return recvd;
}
static int btleIOTx(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
int sent;
CbCtx_t* cbCtx = (CbCtx_t*)ctx;
#ifdef DEBUG_BTLE_IO
printf("BTLE Write: In %d\n", sz);
#endif
sent = btle_send((unsigned char*)buf, sz, BTLE_PKT_TYPE_TLS, cbCtx->devCtx);
if (sent == 0) {
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
#ifdef DEBUG_BTLE_IO
printf("BTLE Write: Out %d\n", sent);
#endif
return sent;
}
int main(int argc, char** argv)
{
int ret = -1, err;
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
CbCtx_t cBctx;
const char testStr[] = "Testing 1, 2 and 3";
byte readBuf[100];
memset(&cBctx, 0, sizeof(cBctx));
#if 0
wolfSSL_Debugging_ON();
#endif
wolfSSL_Init();
/* open BTLE */
ret = btle_open(&cBctx.devCtx, BTLE_ROLE_CLIENT);
if (ret != 0) {
printf("btle_open failed %d! errno %d\n", ret, errno);
goto done;
}
ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
if (ctx == NULL) {
printf("Error creating WOLFSSL_CTX\n");
goto done;
}
/* Register wolfSSL send/recv callbacks */
wolfSSL_CTX_SetIOSend(ctx, btleIOTx);
wolfSSL_CTX_SetIORecv(ctx, btleIORx);
/* Mutual Authentication */
#if 0
/* Load client certificate into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, WOLFSSL_FILETYPE_PEM))
!= WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
CERT_FILE);
goto done;
}
/* Load client key into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, WOLFSSL_FILETYPE_PEM))
!= WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
KEY_FILE);
goto done;
}
#endif
/* Load CA certificate into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CA_FILE, NULL))
!= WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
CA_FILE);
goto done;
}
/* Enable peer certificate verification */
wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
printf("Error creating WOLFSSL\n");
goto done;
}
/* Register wolfSSL read/write callback contexts */
wolfSSL_SetIOReadCtx(ssl, &cBctx);
wolfSSL_SetIOWriteCtx(ssl, &cBctx);
printf("TLS connecting\n");
do {
ret = wolfSSL_connect(ssl);
err = wolfSSL_get_error(ssl, ret);
} while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
if (ret != WOLFSSL_SUCCESS) {
printf("TLS connect error %d\n", err);
goto done;
}
printf("TLS Connect handshake done\n");
printf("Sending test string\n");
do {
ret = wolfSSL_write(ssl, testStr, XSTRLEN(testStr));
err = wolfSSL_get_error(ssl, ret);
} while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
printf("Sent (%d): %s\n", err, testStr);
XMEMSET(readBuf, 0, sizeof(readBuf));
do {
ret = wolfSSL_read(ssl, readBuf, sizeof(readBuf)-1);
err = wolfSSL_get_error(ssl, ret);
} while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
printf("Read (%d): %s\n", err, readBuf);
ret = 0; /* Success */
done:
if (ssl) {
wolfSSL_shutdown(ssl);
wolfSSL_free(ssl);
}
if (ctx) {
wolfSSL_CTX_free(ctx);
}
if (cBctx.devCtx != NULL) {
btle_close(cBctx.devCtx);
}
wolfSSL_Cleanup();
return ret;
}

View File

@ -0,0 +1,197 @@
/* server-tls13-btle.c
*
* Copyright (C) 2006-2022 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
*
*=============================================================================
*
* Example TLS v1.3 server over BTLE
*/
#ifndef WOLFSSL_USER_SETTINGS
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include "../btle-sim.h"
#define CERT_FILE "../../certs/server-cert.pem"
#define KEY_FILE "../../certs/server-key.pem"
#define CA_FILE "../../certs/client-cert.pem"
typedef struct CbCtx {
void* devCtx;
} CbCtx_t;
static int btleIORx(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
int recvd;
CbCtx_t* cbCtx = (CbCtx_t*)ctx;
#ifdef DEBUG_BTLE_IO
printf("BTLE Read: In %d\n", sz);
#endif
recvd = btle_recv((unsigned char*)buf, sz, NULL, cbCtx->devCtx);
if (recvd == 0) {
return WOLFSSL_CBIO_ERR_WANT_READ;
}
#ifdef DEBUG_BTLE_IO
printf("BTLE Read: Out %d\n", recvd);
#endif
return recvd;
}
static int btleIOTx(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
int sent;
CbCtx_t* cbCtx = (CbCtx_t*)ctx;
#ifdef DEBUG_BTLE_IO
printf("BTLE Write: In %d\n", sz);
#endif
sent = btle_send((unsigned char*)buf, sz, BTLE_PKT_TYPE_TLS, cbCtx->devCtx);
if (sent == 0) {
return WOLFSSL_CBIO_ERR_WANT_WRITE;
}
#ifdef DEBUG_BTLE_IO
printf("BTLE Write: Out %d\n", sent);
#endif
return sent;
}
int main(int argc, char** argv)
{
int ret = -1, err;
WOLFSSL_CTX* ctx = NULL;
WOLFSSL* ssl = NULL;
CbCtx_t cBctx;
byte echoBuffer[100];
memset(&cBctx, 0, sizeof(cBctx));
#if 0
wolfSSL_Debugging_ON();
#endif
wolfSSL_Init();
/* open BTLE */
printf("Waiting for client\n");
ret = btle_open(&cBctx.devCtx, BTLE_ROLE_SERVER);
if (ret != 0) {
printf("btle_open failed %d! errno %d\n", ret, errno);
goto done;
}
ctx = wolfSSL_CTX_new(wolfTLSv1_3_server_method());
if (ctx == NULL) {
printf("Error creating WOLFSSL_CTX\n");
goto done;
}
/* Register wolfSSL send/recv callbacks */
wolfSSL_CTX_SetIOSend(ctx, btleIOTx);
wolfSSL_CTX_SetIORecv(ctx, btleIORx);
/* For testing disable peer cert verification */
wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
/* Set server key and certificate (required) */
if ((ret = wolfSSL_CTX_use_certificate_file(ctx, CERT_FILE, WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", CERT_FILE);
goto done;
}
/* Load server key into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, WOLFSSL_FILETYPE_PEM)) != WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n", KEY_FILE);
goto done;
}
/* Mutual Authentication */
#if 0
/* Load client certificate as "trusted" into WOLFSSL_CTX */
if ((ret = wolfSSL_CTX_load_verify_locations(ctx, CA_FILE, NULL))
!= WOLFSSL_SUCCESS) {
fprintf(stderr, "ERROR: failed to load %s, please check the file.\n",
CA_FILE);
goto done;
}
#endif
ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
printf("Error creating WOLFSSL\n");
goto done;
}
/* Register wolfSSL read/write callback contexts */
wolfSSL_SetIOReadCtx(ssl, &cBctx);
wolfSSL_SetIOWriteCtx(ssl, &cBctx);
printf("TLS accepting\n");
do {
ret = wolfSSL_accept(ssl);
err = wolfSSL_get_error(ssl, ret);
} while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
if (ret != WOLFSSL_SUCCESS) {
printf("TLS accept error %d\n", err);
goto done;
}
printf("TLS Accept handshake done\n");
/* Waiting for data to echo */
XMEMSET(echoBuffer, 0, sizeof(echoBuffer));
do {
ret = wolfSSL_read(ssl, echoBuffer, sizeof(echoBuffer)-1);
err = wolfSSL_get_error(ssl, ret);
} while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
printf("Read (%d): %s\n", err, echoBuffer);
do {
ret = wolfSSL_write(ssl, echoBuffer, XSTRLEN((char*)echoBuffer));
err = wolfSSL_get_error(ssl, ret);
} while (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE);
printf("Sent (%d): %s\n", err, echoBuffer);
ret = 0; /* Success */
done:
if (ssl) {
wolfSSL_shutdown(ssl);
wolfSSL_free(ssl);
}
if (ctx) {
wolfSSL_CTX_free(ctx);
}
if (cBctx.devCtx != NULL) {
btle_close(cBctx.devCtx);
}
wolfSSL_Cleanup();
return ret;
}