1
0
mirror of https://github.com/CPunch/Laika.git synced 2025-11-28 21:51:06 +00:00

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
This commit is contained in:
2022-02-03 16:25:49 -06:00
parent 310a751a07
commit dd173ee422
12 changed files with 162 additions and 97 deletions

View File

@@ -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);

View File

@@ -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");