nRF52: don't truncate the AES-CTR block length to uint8_t (#11261)
blockLen() rounds numBytes up to the AES block size, so 241..256 returns 256. Stored in a uint8_t that truncates to 0, giving a zero-length encBuf that Process() then writes numBytes bytes into, smashing the stack with attacker-controlled ciphertext. encrypted.size is a 256-byte protobuf field and encryptPacket admits numBytes up to MAX_BLOCKSIZE, so sizes above the 239-byte LoRa frame limit arrive via the MQTT and UDP multicast ingress paths, which pass the packet to the router without clamping. Only the hardware AES path for keys of 16 bytes or less is affected, which includes the default channel.
This commit is contained in:
co-authored by
GitHub
parent
80f972655d
commit
3e2c98420b
@@ -18,7 +18,10 @@ class NRF52CryptoEngine : public CryptoEngine
|
|||||||
} else if (_key.length > 0) {
|
} else if (_key.length > 0) {
|
||||||
nRFCrypto.begin();
|
nRFCrypto.begin();
|
||||||
nRFCrypto_AES ctx;
|
nRFCrypto_AES ctx;
|
||||||
uint8_t myLen = ctx.blockLen(numBytes);
|
// Must not be uint8_t: blockLen() rounds up to the AES block size, so numBytes in
|
||||||
|
// 241..256 yields 256, which truncates to 0 and leaves Process() writing numBytes
|
||||||
|
// attacker-controlled bytes onto a zero-length stack buffer.
|
||||||
|
size_t myLen = ctx.blockLen(numBytes);
|
||||||
char encBuf[myLen] = {0};
|
char encBuf[myLen] = {0};
|
||||||
ctx.begin();
|
ctx.begin();
|
||||||
ctx.Process((char *)bytes, numBytes, _nonce, _key.bytes, _key.length, encBuf, ctx.encryptFlag, ctx.ctrMode);
|
ctx.Process((char *)bytes, numBytes, _nonce, _key.bytes, _key.length, encBuf, ctx.encryptFlag, ctx.ctrMode);
|
||||||
|
|||||||
Reference in New Issue
Block a user