Added BTLE TLS v1.3 example.
parent
3b21b61df6
commit
809e5351bb
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
157
btle/btle-sim.c
157
btle/btle-sim.c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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`.
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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`.
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue