mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
fix(ecies): bound initial header body size (#12172)
This commit is contained in:
@ -650,7 +650,8 @@ impl ECIES {
|
||||
out.extend_from_slice(tag.as_slice());
|
||||
}
|
||||
|
||||
/// Extracts the header from slice and returns the body size.
|
||||
/// Reads the `RLPx` header from the slice, setting up the MAC and AES, returning the body
|
||||
/// size contained in the header.
|
||||
pub fn read_header(&mut self, data: &mut [u8]) -> Result<usize, ECIESError> {
|
||||
// If the data is not large enough to fit the header and mac bytes, return an error
|
||||
//
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
//! This contains the main codec for `RLPx` ECIES messages
|
||||
|
||||
use crate::{algorithm::ECIES, ECIESError, EgressECIESValue, IngressECIESValue};
|
||||
use crate::{algorithm::ECIES, ECIESError, ECIESErrorImpl, EgressECIESValue, IngressECIESValue};
|
||||
use alloy_primitives::{bytes::BytesMut, B512 as PeerId};
|
||||
use secp256k1::SecretKey;
|
||||
use std::{fmt::Debug, io};
|
||||
use tokio_util::codec::{Decoder, Encoder};
|
||||
use tracing::{instrument, trace};
|
||||
|
||||
/// The max size that the initial handshake packet can be. Currently 2KiB.
|
||||
const MAX_INITIAL_HANDSHAKE_SIZE: usize = 2048;
|
||||
|
||||
/// Tokio codec for ECIES
|
||||
#[derive(Debug)]
|
||||
pub struct ECIESCodec {
|
||||
@ -26,6 +29,11 @@ pub enum ECIESState {
|
||||
/// message containing the nonce and other metadata.
|
||||
Ack,
|
||||
|
||||
/// This is the same as the [`ECIESState::Header`] stage, but occurs only after the first
|
||||
/// [`ECIESState::Ack`] message. This is so that the initial handshake message can be properly
|
||||
/// validated.
|
||||
InitialHeader,
|
||||
|
||||
/// The third stage of the ECIES handshake, where header is parsed, message integrity checks
|
||||
/// performed, and message is decrypted.
|
||||
Header,
|
||||
@ -70,7 +78,7 @@ impl Decoder for ECIESCodec {
|
||||
|
||||
self.ecies.read_auth(&mut buf.split_to(total_size))?;
|
||||
|
||||
self.state = ECIESState::Header;
|
||||
self.state = ECIESState::InitialHeader;
|
||||
return Ok(Some(IngressECIESValue::AuthReceive(self.ecies.remote_id())))
|
||||
}
|
||||
ECIESState::Ack => {
|
||||
@ -89,9 +97,29 @@ impl Decoder for ECIESCodec {
|
||||
|
||||
self.ecies.read_ack(&mut buf.split_to(total_size))?;
|
||||
|
||||
self.state = ECIESState::Header;
|
||||
self.state = ECIESState::InitialHeader;
|
||||
return Ok(Some(IngressECIESValue::Ack))
|
||||
}
|
||||
ECIESState::InitialHeader => {
|
||||
if buf.len() < ECIES::header_len() {
|
||||
trace!("current len {}, need {}", buf.len(), ECIES::header_len());
|
||||
return Ok(None)
|
||||
}
|
||||
|
||||
let body_size =
|
||||
self.ecies.read_header(&mut buf.split_to(ECIES::header_len()))?;
|
||||
|
||||
if body_size > MAX_INITIAL_HANDSHAKE_SIZE {
|
||||
trace!(?body_size, max=?MAX_INITIAL_HANDSHAKE_SIZE, "Header exceeds max initial handshake size");
|
||||
return Err(ECIESErrorImpl::InitialHeaderBodyTooLarge {
|
||||
body_size,
|
||||
max_body_size: MAX_INITIAL_HANDSHAKE_SIZE,
|
||||
}
|
||||
.into())
|
||||
}
|
||||
|
||||
self.state = ECIESState::Body;
|
||||
}
|
||||
ECIESState::Header => {
|
||||
if buf.len() < ECIES::header_len() {
|
||||
trace!("current len {}, need {}", buf.len(), ECIES::header_len());
|
||||
@ -131,7 +159,7 @@ impl Encoder<EgressECIESValue> for ECIESCodec {
|
||||
Ok(())
|
||||
}
|
||||
EgressECIESValue::Ack => {
|
||||
self.state = ECIESState::Header;
|
||||
self.state = ECIESState::InitialHeader;
|
||||
self.ecies.write_ack(buf);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -62,6 +62,14 @@ pub enum ECIESErrorImpl {
|
||||
/// The encrypted data is not large enough for all fields
|
||||
#[error("encrypted data is not large enough for all fields")]
|
||||
EncryptedDataTooSmall,
|
||||
/// The initial header body is too large.
|
||||
#[error("initial header body is {body_size} but the max is {max_body_size}")]
|
||||
InitialHeaderBodyTooLarge {
|
||||
/// The body size from the header
|
||||
body_size: usize,
|
||||
/// The max body size
|
||||
max_body_size: usize,
|
||||
},
|
||||
/// Error when trying to split an array beyond its length
|
||||
#[error("requested {idx} but array len is {len}")]
|
||||
OutOfBounds {
|
||||
|
||||
Reference in New Issue
Block a user