diff --git a/btle/btle-sim.c b/btle/btle-sim.c index cd72b941..c6c2040c 100644 --- a/btle/btle-sim.c +++ b/btle/btle-sim.c @@ -20,30 +20,126 @@ */ -#include +#include "btle-sim.h" + #include #include +#include +#include +#include +#include +#include #include +#include + +#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; } diff --git a/btle/btle-sim.h b/btle/btle-sim.h index 677b1f10..e591a572 100644 --- a/btle/btle-sim.h +++ b/btle/btle-sim.h @@ -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); diff --git a/btle/ecc-client.c b/btle/ecc-client.c index 8b8fd8c5..2a39f1c5 100644 --- a/btle/ecc-client.c +++ b/btle/ecc-client.c @@ -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: diff --git a/btle/ecc-server.c b/btle/ecc-server.c index e3e21a98..5d6e60ad 100644 --- a/btle/ecc-server.c +++ b/btle/ecc-server.c @@ -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: