Added error response checking. Added header to indicate packet type and length. Added padding for packets. Testing almost complete.

pull/67/head
David Garske 2017-07-18 20:43:14 -07:00
parent b55905b164
commit bf4b1875ba
4 changed files with 362 additions and 55 deletions

View File

@ -20,30 +20,126 @@
*/
#include <fcntl.h>
#include "btle-sim.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/select.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define BTLE_VER 1
typedef struct {
int fd;
int role;
int fdmiso;
int fdmosi;
} BtleDev_t;
typedef struct {
unsigned char ver;
unsigned char type;
unsigned short len;
} __attribute__ ((packed)) BtleHeader_t;
static BtleDev_t gBtleDev;
static const char* myfifo = "/tmp/myfifo";
static const char* kBtleMisoFifo = "/tmp/btleMiso";
static const char* kBtleMosiFifo = "/tmp/btleMosi";
int btle_open(void** dev)
//#define BTLE_DEBUG_IO
static int btle_get_write(BtleDev_t* dev)
{
int fd;
return (dev->role == BTLE_ROLE_SERVER) ? dev->fdmosi : dev->fdmiso;
}
mkfifo(myfifo, 0666);
static int btle_get_read(BtleDev_t* dev)
{
return (dev->role == BTLE_ROLE_SERVER) ? dev->fdmiso : dev->fdmosi;
}
fd = open(myfifo, O_WRONLY);
if (fd < 0) {
unlink(myfifo);
static int btle_send_block(BtleDev_t* dev, const void* buf, int len, int fd)
{
int ret;
ret = write(fd, buf, len);
#ifdef BTLE_DEBUG_IO
printf("Write: %d\n", ret);
#endif
(void)dev;
return ret;
}
static int btle_recv_block(BtleDev_t* dev, void* buf, int len, int fd)
{
fd_set set;
int ret, pos = 0;
FD_ZERO(&set);
FD_SET(fd, &set);
while (pos < len) {
ret = select(fd+1, &set, NULL, NULL, NULL);
if (ret == 0)
continue;
if (ret < 0)
return ret;
if (FD_ISSET(fd, &set)) {
ret = read(fd, &buf[pos], len - pos);
#ifdef BTLE_DEBUG_IO
printf("Read: %d\n", ret);
#endif
if (ret > 0) {
pos += ret;
}
else {
if (errno == EWOULDBLOCK) {
continue;
}
else {
return ret;
}
}
}
}
(void)dev;
return pos;
}
int btle_open(void** dev, int role)
{
int fdmiso, fdmosi;
mkfifo(kBtleMisoFifo, 0666);
mkfifo(kBtleMosiFifo, 0666);
if (role == BTLE_ROLE_SERVER) {
fdmiso = open(kBtleMisoFifo, O_RDONLY | O_NONBLOCK);
fdmosi = open(kBtleMosiFifo, O_WRONLY);
}
else {
fdmosi = open(kBtleMosiFifo, O_RDONLY | O_NONBLOCK);
fdmiso = open(kBtleMisoFifo, O_WRONLY);
}
if (fdmiso < 0) {
printf("Open %s failed! %d\n", kBtleMisoFifo, errno);
return -1;
}
gBtleDev.fd = fd;
if (fdmosi < 0) {
printf("Open %s failed! %d\n", kBtleMosiFifo, errno);
close(fdmiso);
return -1;
}
gBtleDev.role = role;
gBtleDev.fdmiso = fdmiso;
gBtleDev.fdmosi = fdmosi;
if (dev)
*dev = &gBtleDev;
@ -51,24 +147,76 @@ int btle_open(void** dev)
return 0;
}
int btle_send(const unsigned char* buf, int len, void* context)
int btle_send(const unsigned char* buf, int len, int type, void* context)
{
BtleDev_t* dev = (BtleDev_t*)context;
write(dev->fd, buf, len);
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, &header, sizeof(header), fd);
ret = btle_send_block(dev, buf, len, fd);
return len;
}
int btle_recv(unsigned char* buf, int len, void* context)
int btle_recv(unsigned char* buf, int len, int* type, void* context)
{
BtleDev_t* dev = (BtleDev_t*)context;
return read(dev->fd, buf, len);
BtleHeader_t header;
int ret;
int fd = btle_get_read(dev);
ret = btle_recv_block(dev, &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;
}
void btle_close(void* context)
{
BtleDev_t* dev = (BtleDev_t*)context;
close(dev->fd);
unlink(myfifo);
close(dev->fdmiso);
close(dev->fdmosi);
unlink(kBtleMisoFifo);
unlink(kBtleMosiFifo);
}
int btle_msg_pad(unsigned char* buf, int* len, void* context)
{
BtleDev_t* dev = (BtleDev_t*)context;
int newLen = *len;
int odd = (newLen % BTLE_BLOCK_SIZE);
if (odd != 0) {
int addLen = (BTLE_BLOCK_SIZE - odd);
newLen += addLen;
if (newLen > BTLE_MSG_MAX_SIZE)
return -1;
memset(&buf[*len], 0, addLen);
}
*len = newLen;
(void)dev;
return 0;
}

View File

@ -20,9 +20,25 @@
*/
#define MAX_BTLE_MSG_SIZE 1024
#define BTLE_MSG_MAX_SIZE 1024
#define BTLE_BLOCK_SIZE 16
int btle_open(void** dev);
int btle_send(const unsigned char* buf, int len, void* context);
int btle_recv(unsigned char* buf, int len, void* context);
typedef enum {
BTLE_PKT_TYPE_NULL,
BTLE_PKT_TYPE_KEY,
BTLE_PKT_TYPE_SALT,
BTLE_PKT_TYPE_MSG,
BTLE_PKT_TYPE_MAX,
} BtlePacket_t;
typedef enum {
BTLE_ROLE_CLIENT,
BTLE_ROLE_SERVER,
} BtleRole_t;
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);
void btle_close(void* context);
int btle_msg_pad(unsigned char* buf, int* len, void* context);

View File

@ -34,11 +34,12 @@ int main(int argc, char** argv)
const byte* mySalt;
void* devCtx = NULL;
byte peerSalt[EXCHANGE_SALT_SZ];
byte buffer[MAX_BTLE_MSG_SIZE];
byte buffer[BTLE_MSG_MAX_SIZE];
word32 bufferSz;
byte plain[MAX_BTLE_MSG_SIZE];
byte plain[BTLE_MSG_MAX_SIZE];
word32 plainSz;
ecc_key myKey, peerKey;
int type;
wolfSSL_Init();
@ -47,13 +48,17 @@ int main(int argc, char** argv)
#endif
/* make my session key */
wc_ecc_init(&myKey);
wc_ecc_init(&peerKey);
wc_ecc_make_key(&rng, 32, &myKey);
ret = wc_ecc_init(&myKey);
ret |= wc_ecc_init(&peerKey);
if (ret != 0) {
printf("wc_ecc_init failed!\n");
goto cleanup;
}
/* open BTLE */
ret = btle_open(&devCtx);
ret = btle_open(&devCtx, BTLE_ROLE_CLIENT);
if (ret != 0) {
printf("btle_open failed %d! errno %d\n", ret, errno);
goto cleanup;
}
@ -63,6 +68,12 @@ int main(int argc, char** argv)
goto cleanup;
}
ret = wc_ecc_make_key(&rng, 32, &myKey);
if (ret != 0) {
printf("wc_ecc_make_key failed %d\n", ret);
goto cleanup;
}
cliCtx = wc_ecc_ctx_new(REQ_RESP_CLIENT, &rng);
if (cliCtx == NULL) {
printf("wc_ecc_ctx_new failed!\n");
@ -73,13 +84,33 @@ int main(int argc, char** argv)
/* send my public key */
/* export my public key */
bufferSz = sizeof(buffer);
wc_ecc_export_x963(&myKey, buffer, &bufferSz);
ret = btle_send(buffer, bufferSz, devCtx);
ret = wc_ecc_export_x963(&myKey, buffer, &bufferSz);
if (ret != 0) {
printf("wc_ecc_export_x963 failed %d\n", ret);
goto cleanup;
}
ret = btle_send(buffer, bufferSz, BTLE_PKT_TYPE_KEY, devCtx);
if (ret != bufferSz) {
printf("btle_send key failed %d!\n", ret);
goto cleanup;
}
/* Get peer key */
ret = btle_recv(buffer, sizeof(buffer), devCtx);
ret = btle_recv(buffer, sizeof(buffer), &type, devCtx);
if (ret <= 0) {
printf("btle_recv key failed %d\n", ret);
goto cleanup;
}
if (type != BTLE_PKT_TYPE_KEY) {
printf("btle_recv expected key!\n");
ret = -1; goto cleanup;
}
bufferSz = ret;
ret = wc_ecc_import_x963(buffer, bufferSz, &peerKey);
if (ret != 0) {
printf("wc_ecc_import_x963 failed %d\n", ret);
goto cleanup;
}
/* Collect Message to send and get echo */
while (1) {
@ -91,31 +122,66 @@ int main(int argc, char** argv)
}
/* Send my salt */
ret = btle_send(mySalt, EXCHANGE_SALT_SZ, devCtx);
ret = btle_send(mySalt, EXCHANGE_SALT_SZ, BTLE_PKT_TYPE_SALT, devCtx);
if (ret != EXCHANGE_SALT_SZ) {
printf("btle_send salt failed %d!\n", ret);
goto cleanup;
}
/* Get peer salt */
ret = btle_recv(peerSalt, EXCHANGE_SALT_SZ, devCtx);
wc_ecc_ctx_set_peer_salt(cliCtx, peerSalt);
ret = btle_recv(peerSalt, EXCHANGE_SALT_SZ, &type, devCtx);
if (ret <= 0) {
printf("btle_recv failed %d! errno %d\n", ret, errno);
}
if (type != BTLE_PKT_TYPE_SALT) {
printf("btle_recv expected salt!\n");
ret = -1; goto cleanup;
}
ret = wc_ecc_ctx_set_peer_salt(cliCtx, peerSalt);
if (ret != 0) {
printf("wc_ecc_ctx_set_peer_salt failed %d\n", ret);
goto cleanup;
}
/* get message to send */
bufferSz = sizeof(buffer);
fgets((char*)buffer, bufferSz, stdin);
bufferSz = strlen((char*)buffer);
plainSz = sizeof(plain);
fgets((char*)plain, plainSz, stdin);
plainSz = strlen((char*)plain);
ret = btle_msg_pad(plain, (int*)&plainSz, devCtx);
if (ret != 0) {
printf("btle_msg_pad failed %d\n", ret);
goto cleanup;
}
/* Encrypt message */
bufferSz = sizeof(buffer);
ret = wc_ecc_encrypt(&myKey, &peerKey, plain, plainSz, buffer, &bufferSz, cliCtx);
if (ret != 0) {
printf("wc_ecc_encrypt failed %d!\n", ret);
goto cleanup;
}
/* Send message */
btle_send(buffer, bufferSz, devCtx);
ret = btle_send(buffer, bufferSz, BTLE_PKT_TYPE_MSG, devCtx);
if (ret != bufferSz) {
printf("btle_send failed %d!\n", ret);
goto cleanup;
}
/* get message until null termination found */
/* Get message */
bufferSz = sizeof(bufferSz);
ret = btle_recv(buffer, bufferSz, devCtx);
ret = btle_recv(buffer, bufferSz, &type, devCtx);
if (type != BTLE_PKT_TYPE_MSG) {
ret = -1; goto cleanup;
}
/* decrypt message */
/* Decrypt message */
bufferSz = ret;
ret = wc_ecc_decrypt(&myKey, &peerKey, buffer, bufferSz, plain, &plainSz, cliCtx);
if (ret != 0) {
printf("wc_ecc_decrypt failed %d!\n", ret);
goto cleanup;
}
printf("Recv %d: %s\n", plainSz, plain);
@ -125,6 +191,10 @@ int main(int argc, char** argv)
/* reset context (reset my salt) */
ret = wc_ecc_ctx_reset(cliCtx, &rng);
if (ret != 0) {
printf("wc_ecc_ctx_reset failed %d\n", ret);
goto cleanup;
}
}
cleanup:

View File

@ -34,11 +34,12 @@ int main(int argc, char** argv)
const byte* mySalt;
void* devCtx = NULL;
byte peerSalt[EXCHANGE_SALT_SZ];
byte buffer[MAX_BTLE_MSG_SIZE];
byte buffer[BTLE_MSG_MAX_SIZE];
word32 bufferSz;
byte plain[MAX_BTLE_MSG_SIZE];
byte plain[BTLE_MSG_MAX_SIZE];
word32 plainSz;
ecc_key myKey, peerKey;
int type;
wolfSSL_Init();
@ -47,13 +48,17 @@ int main(int argc, char** argv)
#endif
/* make my session key */
wc_ecc_init(&myKey);
wc_ecc_init(&peerKey);
wc_ecc_make_key(&rng, 32, &myKey);
ret = wc_ecc_init(&myKey);
ret |= wc_ecc_init(&peerKey);
if (ret != 0) {
printf("wc_ecc_init failed!\n");
goto cleanup;
}
/* open BTLE */
ret = btle_open(&devCtx);
ret = btle_open(&devCtx, BTLE_ROLE_SERVER);
if (ret != 0) {
printf("btle_open failed %d! errno %d\n", ret, errno);
goto cleanup;
}
@ -63,6 +68,12 @@ int main(int argc, char** argv)
goto cleanup;
}
ret = wc_ecc_make_key(&rng, 32, &myKey);
if (ret != 0) {
printf("wc_ecc_make_key failed %d\n", ret);
goto cleanup;
}
srvCtx = wc_ecc_ctx_new(REQ_RESP_SERVER, &rng);
if (srvCtx == NULL) {
printf("wc_ecc_ctx_new failed!\n");
@ -71,15 +82,35 @@ int main(int argc, char** argv)
/* exchange public keys */
/* Get peer key */
ret = btle_recv(buffer, sizeof(buffer), devCtx);
ret = btle_recv(buffer, sizeof(buffer), &type, devCtx);
if (ret < 0) {
printf("btle_recv key failed %d! errno %d\n", ret, errno);
goto cleanup;
}
if (type != BTLE_PKT_TYPE_KEY) {
printf("btle_recv expected key!\n");
ret = -1; goto cleanup;
}
bufferSz = ret;
ret = wc_ecc_import_x963(buffer, bufferSz, &peerKey);
if (ret != 0) {
printf("wc_ecc_import_x963 failed %d!\n", ret);
goto cleanup;
}
/* send my public key */
/* export my public key */
bufferSz = sizeof(buffer);
wc_ecc_export_x963(&myKey, buffer, &bufferSz);
ret = btle_send(buffer, bufferSz, devCtx);
ret = wc_ecc_export_x963(&myKey, buffer, &bufferSz);
if (ret != 0) {
printf("wc_ecc_export_x963 failed %d\n", ret);
goto cleanup;
}
ret = btle_send(buffer, bufferSz, BTLE_PKT_TYPE_KEY, devCtx);
if (ret != bufferSz) {
printf("btle_send key failed %d!\n", ret);
goto cleanup;
}
while (1) {
mySalt = wc_ecc_ctx_get_own_salt(srvCtx);
@ -89,27 +120,65 @@ int main(int argc, char** argv)
}
/* Get peer salt */
ret = btle_recv(peerSalt, EXCHANGE_SALT_SZ, devCtx);
ret = btle_recv(peerSalt, EXCHANGE_SALT_SZ, &type, devCtx);
if (ret <= 0) {
printf("btle_recv salt failed %d! errno %d\n", ret, errno);
goto cleanup;
}
if (type != BTLE_PKT_TYPE_SALT) {
printf("btle_recv expected salt!\n");
ret = -1; goto cleanup;
}
ret = wc_ecc_ctx_set_peer_salt(srvCtx, peerSalt);
if (ret != 0) {
printf("wc_ecc_ctx_set_peer_salt failed %d\n", ret);
goto cleanup;
}
/* Send my salt */
ret = btle_send(mySalt, EXCHANGE_SALT_SZ, devCtx);
ret = btle_send(mySalt, EXCHANGE_SALT_SZ, BTLE_PKT_TYPE_SALT, devCtx);
if (ret != EXCHANGE_SALT_SZ) {
printf("btle_send salt failed %d!\n", ret);
goto cleanup;
}
/* get message until null termination found */
/* Get message */
bufferSz = sizeof(bufferSz);
ret = btle_recv(buffer, bufferSz, devCtx);
ret = btle_recv(buffer, bufferSz, &type, devCtx);
if (ret <= 0) {
printf("btle_recv msg failed %d! errno %d\n", ret, errno);
goto cleanup;
}
if (type != BTLE_PKT_TYPE_MSG) {
printf("btle_recv expected msg!\n");
ret = -1; goto cleanup;
}
/* decrypt message */
/* Decrypt message */
bufferSz = ret;
plainSz = sizeof(plain);
ret = wc_ecc_decrypt(&myKey, &peerKey, buffer, bufferSz, plain, &plainSz, srvCtx);
if (ret != 0) {
printf("wc_ecc_decrypt failed %d!\n", ret);
goto cleanup;
}
printf("Recv %d: %s\n", plainSz, plain);
/* Encrypt message */
bufferSz = sizeof(buffer);
ret = wc_ecc_encrypt(&myKey, &peerKey, plain, plainSz, buffer, &bufferSz, srvCtx);
if (ret != 0) {
printf("wc_ecc_encrypt failed %d!\n", ret);
goto cleanup;
}
/* Send message */
btle_send(buffer, bufferSz, devCtx);
ret = btle_send(buffer, bufferSz, BTLE_PKT_TYPE_MSG, devCtx);
if (ret != bufferSz) {
printf("btle_send failed %d!\n", ret);
goto cleanup;
}
/* check for exit flag */
if (strstr((char*)plain, "EXIT"))
@ -117,6 +186,10 @@ int main(int argc, char** argv)
/* reset context (reset my salt) */
ret = wc_ecc_ctx_reset(srvCtx, &rng);
if (ret != 0) {
printf("wc_ecc_ctx_reset failed %d\n", ret);
goto cleanup;
}
}
cleanup: