Add 4 bytes of random nonce to PKI (#4493)

This commit is contained in:
Jonathan Bennett 2024-08-18 07:23:56 -05:00 committed by GitHub
parent c7c620ac69
commit 23e3e6db92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 12 deletions

View File

@ -41,7 +41,11 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_
uint8_t *bytesOut) uint8_t *bytesOut)
{ {
uint8_t *auth; uint8_t *auth;
uint32_t *extraNonce;
auth = bytesOut + numBytes; auth = bytesOut + numBytes;
extraNonce = (uint32_t *)(auth + 8);
*extraNonce = random();
LOG_INFO("Random nonce value: %d\n", *extraNonce);
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(toNode); meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(toNode);
if (node->num < 1 || node->user.public_key.size == 0) { if (node->num < 1 || node->user.public_key.size == 0) {
LOG_DEBUG("Node %d or their public_key not found\n", toNode); LOG_DEBUG("Node %d or their public_key not found\n", toNode);
@ -50,10 +54,10 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_
if (!crypto->setDHKey(toNode)) { if (!crypto->setDHKey(toNode)) {
return false; return false;
} }
initNonce(fromNode, packetNum); initNonce(fromNode, packetNum, *extraNonce);
// Calculate the shared secret with the destination node and encrypt // Calculate the shared secret with the destination node and encrypt
printBytes("Attempting encrypt using nonce: ", nonce, 16); printBytes("Attempting encrypt using nonce: ", nonce, 13);
printBytes("Attempting encrypt using shared_key: ", shared_key, 32); printBytes("Attempting encrypt using shared_key: ", shared_key, 32);
aes_ccm_ae(shared_key, 32, nonce, 8, bytes, numBytes, nullptr, 0, bytesOut, auth); aes_ccm_ae(shared_key, 32, nonce, 8, bytes, numBytes, nullptr, 0, bytesOut, auth);
return true; return true;
@ -68,7 +72,10 @@ bool CryptoEngine::encryptCurve25519(uint32_t toNode, uint32_t fromNode, uint64_
bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes, uint8_t *bytesOut) bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size_t numBytes, uint8_t *bytes, uint8_t *bytesOut)
{ {
uint8_t *auth; // set to last 8 bytes of text? uint8_t *auth; // set to last 8 bytes of text?
auth = bytes + numBytes - 8; uint32_t *extraNonce;
auth = bytes + numBytes - 12;
extraNonce = (uint32_t *)(auth + 8);
LOG_INFO("Random nonce value: %d\n", *extraNonce);
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(fromNode); meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(fromNode);
if (node == nullptr || node->num < 1 || node->user.public_key.size == 0) { if (node == nullptr || node->num < 1 || node->user.public_key.size == 0) {
@ -80,10 +87,10 @@ bool CryptoEngine::decryptCurve25519(uint32_t fromNode, uint64_t packetNum, size
if (!crypto->setDHKey(fromNode)) { if (!crypto->setDHKey(fromNode)) {
return false; return false;
} }
initNonce(fromNode, packetNum); initNonce(fromNode, packetNum, *extraNonce);
printBytes("Attempting decrypt using nonce: ", nonce, 16); printBytes("Attempting decrypt using nonce: ", nonce, 13);
printBytes("Attempting decrypt using shared_key: ", shared_key, 32); printBytes("Attempting decrypt using shared_key: ", shared_key, 32);
return aes_ccm_ad(shared_key, 32, nonce, 8, bytes, numBytes - 8, nullptr, 0, auth, bytesOut); return aes_ccm_ad(shared_key, 32, nonce, 8, bytes, numBytes - 12, nullptr, 0, auth, bytesOut);
} }
void CryptoEngine::setDHPrivateKey(uint8_t *_private_key) void CryptoEngine::setDHPrivateKey(uint8_t *_private_key)
@ -232,13 +239,15 @@ void CryptoEngine::encryptAESCtr(CryptoKey _key, uint8_t *_nonce, size_t numByte
/** /**
* Init our 128 bit nonce for a new packet * Init our 128 bit nonce for a new packet
*/ */
void CryptoEngine::initNonce(uint32_t fromNode, uint64_t packetId) void CryptoEngine::initNonce(uint32_t fromNode, uint64_t packetId, uint32_t extraNonce)
{ {
memset(nonce, 0, sizeof(nonce)); memset(nonce, 0, sizeof(nonce));
// use memcpy to avoid breaking strict-aliasing // use memcpy to avoid breaking strict-aliasing
memcpy(nonce, &packetId, sizeof(uint64_t)); memcpy(nonce, &packetId, sizeof(uint64_t));
memcpy(nonce + sizeof(uint64_t), &fromNode, sizeof(uint32_t)); memcpy(nonce + sizeof(uint64_t), &fromNode, sizeof(uint32_t));
if (extraNonce)
memcpy(nonce + sizeof(uint32_t), &extraNonce, sizeof(uint32_t));
} }
#ifndef HAS_CUSTOM_CRYPTO_ENGINE #ifndef HAS_CUSTOM_CRYPTO_ENGINE
CryptoEngine *crypto = new CryptoEngine; CryptoEngine *crypto = new CryptoEngine;

View File

@ -88,7 +88,7 @@ class CryptoEngine
* a 32 bit sending node number (stored in little endian order) * a 32 bit sending node number (stored in little endian order)
* a 32 bit block counter (starts at zero) * a 32 bit block counter (starts at zero)
*/ */
void initNonce(uint32_t fromNode, uint64_t packetId); void initNonce(uint32_t fromNode, uint64_t packetId, uint32_t extraNonce = 0);
}; };
extern CryptoEngine *crypto; extern CryptoEngine *crypto;

View File

@ -322,13 +322,13 @@ bool perhapsDecode(meshtastic_MeshPacket *p)
// Attempt PKI decryption first // Attempt PKI decryption first
if (p->channel == 0 && p->to == nodeDB->getNodeNum() && p->to > 0 && p->to != NODENUM_BROADCAST && if (p->channel == 0 && p->to == nodeDB->getNodeNum() && p->to > 0 && p->to != NODENUM_BROADCAST &&
nodeDB->getMeshNode(p->from) != nullptr && nodeDB->getMeshNode(p->from)->user.public_key.size > 0 && nodeDB->getMeshNode(p->from) != nullptr && nodeDB->getMeshNode(p->from)->user.public_key.size > 0 &&
nodeDB->getMeshNode(p->to)->user.public_key.size > 0 && rawSize > 8) { nodeDB->getMeshNode(p->to)->user.public_key.size > 0 && rawSize > 12) {
LOG_DEBUG("Attempting PKI decryption\n"); LOG_DEBUG("Attempting PKI decryption\n");
if (crypto->decryptCurve25519(p->from, p->id, rawSize, ScratchEncrypted, bytes)) { if (crypto->decryptCurve25519(p->from, p->id, rawSize, ScratchEncrypted, bytes)) {
LOG_INFO("PKI Decryption worked!\n"); LOG_INFO("PKI Decryption worked!\n");
memset(&p->decoded, 0, sizeof(p->decoded)); memset(&p->decoded, 0, sizeof(p->decoded));
rawSize -= 8; rawSize -= 12;
if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded) && if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded) &&
p->decoded.portnum != meshtastic_PortNum_UNKNOWN_APP) { p->decoded.portnum != meshtastic_PortNum_UNKNOWN_APP) {
decrypted = true; decrypted = true;
@ -470,7 +470,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
p->decoded.portnum != meshtastic_PortNum_NODEINFO_APP && p->decoded.portnum != meshtastic_PortNum_ROUTING_APP && p->decoded.portnum != meshtastic_PortNum_NODEINFO_APP && p->decoded.portnum != meshtastic_PortNum_ROUTING_APP &&
p->decoded.portnum != meshtastic_PortNum_POSITION_APP) { p->decoded.portnum != meshtastic_PortNum_POSITION_APP) {
LOG_DEBUG("Using PKI!\n"); LOG_DEBUG("Using PKI!\n");
if (numbytes + 8 > MAX_RHPACKETLEN) if (numbytes + 12 > MAX_RHPACKETLEN)
return meshtastic_Routing_Error_TOO_LARGE; return meshtastic_Routing_Error_TOO_LARGE;
if (p->pki_encrypted && !memfll(p->public_key.bytes, 0, 32) && if (p->pki_encrypted && !memfll(p->public_key.bytes, 0, 32) &&
memcmp(p->public_key.bytes, node->user.public_key.bytes, 32) != 0) { memcmp(p->public_key.bytes, node->user.public_key.bytes, 32) != 0) {
@ -479,7 +479,7 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p)
return meshtastic_Routing_Error_PKI_FAILED; return meshtastic_Routing_Error_PKI_FAILED;
} }
crypto->encryptCurve25519(p->to, getFrom(p), p->id, numbytes, bytes, ScratchEncrypted); crypto->encryptCurve25519(p->to, getFrom(p), p->id, numbytes, bytes, ScratchEncrypted);
numbytes += 8; numbytes += 12;
memcpy(p->encrypted.bytes, ScratchEncrypted, numbytes); memcpy(p->encrypted.bytes, ScratchEncrypted, numbytes);
p->channel = 0; p->channel = 0;
p->pki_encrypted = true; p->pki_encrypted = true;