mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-08 22:22:05 +00:00
Add shared secret cache
This commit is contained in:
parent
f1b892ce56
commit
c211384f12
@ -253,6 +253,65 @@ void CryptoEngine::initNonce(uint32_t fromNode, uint64_t packetId, uint32_t extr
|
|||||||
if (extraNonce)
|
if (extraNonce)
|
||||||
memcpy(nonce + sizeof(uint32_t), &extraNonce, sizeof(uint32_t));
|
memcpy(nonce + sizeof(uint32_t), &extraNonce, sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CryptoEngine::setCryptoSharedSecret(meshtastic_UserLite_public_key_t pubkey)
|
||||||
|
{
|
||||||
|
// The last used timestamp is in units of ~1.165 hours, which gives us
|
||||||
|
// ~12.3 days before the timestamps roll over. This is ok since a periodic
|
||||||
|
// misfire on evicting the oldest secret has very little impact.
|
||||||
|
const uint8_t now = (millis() >> 22) & 0xff;
|
||||||
|
|
||||||
|
// Get a short lookup key from the pubkey
|
||||||
|
uint32_t lookupKey;
|
||||||
|
memcpy(&lookupKey, pubkey.bytes, sizeof(lookupKey));
|
||||||
|
|
||||||
|
// See if we cached the secret already
|
||||||
|
auto iter = sharedSecretCache.find(lookupKey);
|
||||||
|
if (iter != sharedSecretCache.end()) {
|
||||||
|
// Cache hit! Copy it into shared_key.
|
||||||
|
CachedSharedSecret &entry = iter->second;
|
||||||
|
memcpy(shared_key, entry.shared_secret, 32);
|
||||||
|
// Update the last used timestamp
|
||||||
|
entry.last_used = now;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache miss. Generate the shared secret.
|
||||||
|
if (!setDHPublicKey(pubkey.bytes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
hash(shared_key, 32);
|
||||||
|
|
||||||
|
// If the cache will grow too large, remove the oldest entry first
|
||||||
|
if (sharedSecretCache.size() >= MAX_CACHED_SHARED_SECRETS) {
|
||||||
|
uint16_t oldestDelta = 0;
|
||||||
|
uint32_t oldestKey = sharedSecretCache.begin()->first;
|
||||||
|
for (const auto &p : sharedSecretCache) {
|
||||||
|
const uint32_t key = p.first;
|
||||||
|
const CachedSharedSecret &entry = p.second;
|
||||||
|
|
||||||
|
uint16_t delta = 0;
|
||||||
|
if (now >= entry.last_used) {
|
||||||
|
delta = now - entry.last_used;
|
||||||
|
} else {
|
||||||
|
// Assume a larger last used timestamp is further in the past
|
||||||
|
delta = uint16_t(0x100) + now - entry.last_used;
|
||||||
|
}
|
||||||
|
if (delta > oldestDelta) {
|
||||||
|
oldestKey = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sharedSecretCache.erase(oldestKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now insert the calculated shared secret
|
||||||
|
CachedSharedSecret entry;
|
||||||
|
entry.last_used = now;
|
||||||
|
memcpy(entry.shared_secret, shared_key, 32);
|
||||||
|
sharedSecretCache.insert({lookupKey, entry});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef HAS_CUSTOM_CRYPTO_ENGINE
|
#ifndef HAS_CUSTOM_CRYPTO_ENGINE
|
||||||
CryptoEngine *crypto = new CryptoEngine;
|
CryptoEngine *crypto = new CryptoEngine;
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "mesh-pb-constants.h"
|
#include "mesh-pb-constants.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
extern concurrency::Lock *cryptLock;
|
extern concurrency::Lock *cryptLock;
|
||||||
|
|
||||||
@ -15,6 +16,11 @@ struct CryptoKey {
|
|||||||
int8_t length;
|
int8_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CachedSharedSecret {
|
||||||
|
uint8_t shared_secret[32];
|
||||||
|
uint8_t last_used;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* see docs/software/crypto.md for details.
|
* see docs/software/crypto.md for details.
|
||||||
*
|
*
|
||||||
@ -22,6 +28,7 @@ struct CryptoKey {
|
|||||||
|
|
||||||
#define MAX_BLOCKSIZE 256
|
#define MAX_BLOCKSIZE 256
|
||||||
#define TEST_CURVE25519_FIELD_OPS // Exposes Curve25519::isWeakPoint() for testing keys
|
#define TEST_CURVE25519_FIELD_OPS // Exposes Curve25519::isWeakPoint() for testing keys
|
||||||
|
#define MAX_CACHED_SHARED_SECRETS 64
|
||||||
|
|
||||||
class CryptoEngine
|
class CryptoEngine
|
||||||
{
|
{
|
||||||
@ -92,6 +99,16 @@ class CryptoEngine
|
|||||||
* a 32 bit block counter (starts at zero)
|
* a 32 bit block counter (starts at zero)
|
||||||
*/
|
*/
|
||||||
void initNonce(uint32_t fromNode, uint64_t packetId, uint32_t extraNonce = 0);
|
void initNonce(uint32_t fromNode, uint64_t packetId, uint32_t extraNonce = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache mapping peers' public keys -> {shared_secret, last_used}
|
||||||
|
*/
|
||||||
|
std::unordered_map<uint32_t, CachedSharedSecret> sharedSecretCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set cryptographic (hashed) shared_key calculated from the given pubkey
|
||||||
|
*/
|
||||||
|
bool setCryptoSharedSecret(meshtastic_UserLite_public_key_t pubkey);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CryptoEngine *crypto;
|
extern CryptoEngine *crypto;
|
Loading…
Reference in New Issue
Block a user