mirror of
https://gitlab.redox-os.org/CoffeeCode/redox-ssh.git
synced 2025-12-28 17:02:19 +01:00
Implement hmac-sha2-256
This commit is contained in:
parent
64e44de13a
commit
fe447bf443
11 changed files with 253 additions and 83 deletions
12
README.md
12
README.md
|
|
@ -6,17 +6,19 @@ A ssh client and server written entirely on rust, primarily targeted at [Redox O
|
|||
|
||||
Currently implemented features, ordered by priority:
|
||||
|
||||
- [ ] SSH Server
|
||||
- [x] SSH Server
|
||||
- [ ] SSH Client
|
||||
- [ ] Key Exchange algorithms
|
||||
- Key Exchange algorithms
|
||||
- [ ] `diffie-hellman-group-exchange-sha1`
|
||||
- [x] `curve25519-sha256`
|
||||
- [ ] Public Key algorithms
|
||||
- Public Key algorithms
|
||||
- [ ] `ssh-rsa`
|
||||
- [x] `ssh-ed25519`
|
||||
- [ ] Encryption algorithms
|
||||
- [ ] `aes256-ctr`
|
||||
- Encryption algorithms
|
||||
- [x] `aes256-ctr`
|
||||
- [ ] `aes256-gcm`
|
||||
- MAC algorithms
|
||||
- [x] `hmac-sha2-256`
|
||||
- [ ] Port forwarding
|
||||
- [ ] SCP File Transfers
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ pub static ENCRYPTION: &[EncryptionAlgorithm] =
|
|||
&[EncryptionAlgorithm::AES256_CTR];
|
||||
|
||||
/// Slice of implemented MAC algorithms, ordered by preference
|
||||
pub static MAC: &[MacAlgorithm] = &[MacAlgorithm::HMAC_SHA2_512];
|
||||
pub static MAC: &[MacAlgorithm] = &[MacAlgorithm::HMAC_SHA2_256];
|
||||
|
||||
/// Slice of implemented compression algorithms, ordered by preference
|
||||
pub static COMPRESSION: &[CompressionAlgorithm] =
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use std::sync::Arc;
|
|||
use encryption::{AesCtr, Decryptor, Encryption};
|
||||
use error::{ConnectionError, ConnectionResult};
|
||||
use key_exchange::{self, KexResult, KeyExchange};
|
||||
use mac::{Hmac, MacAlgorithm};
|
||||
use message::MessageType;
|
||||
use packet::{Packet, ReadPacketExt, WritePacketExt};
|
||||
use server::ServerConfig;
|
||||
|
|
@ -38,6 +39,8 @@ pub struct Connection {
|
|||
stream: Box<Write>,
|
||||
session_id: Option<Vec<u8>>,
|
||||
encryption: Option<(Box<Encryption>, Box<Encryption>)>,
|
||||
mac: Option<(Box<MacAlgorithm>, Box<MacAlgorithm>)>,
|
||||
seq: (u32, u32),
|
||||
}
|
||||
|
||||
impl<'a> Connection {
|
||||
|
|
@ -50,6 +53,8 @@ impl<'a> Connection {
|
|||
stream: Box::new(stream),
|
||||
session_id: None,
|
||||
encryption: None,
|
||||
mac: None,
|
||||
seq: (0, 0),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,20 +66,58 @@ impl<'a> Connection {
|
|||
|
||||
loop {
|
||||
let packet = if let Some((ref mut c2s, _)) = self.encryption {
|
||||
println!("decrypting!!!");
|
||||
let mut decryptor = Decryptor::new(&mut **c2s, &mut reader);
|
||||
Packet::read_from(&mut decryptor)?
|
||||
}
|
||||
else {
|
||||
Packet::read_from(&mut reader)?
|
||||
};
|
||||
trace!("Packet received: {:?}", packet);
|
||||
|
||||
if let Some((ref mut mac, _)) = self.mac {
|
||||
let mut sig = vec![0; mac.size()];
|
||||
reader.read_exact(&mut sig)?;
|
||||
|
||||
let mut sig_cmp = vec![0; mac.size()];
|
||||
mac.sign(packet.data(), self.seq.0, sig_cmp.as_mut_slice());
|
||||
|
||||
if sig != sig_cmp {
|
||||
return Err(ConnectionError::IntegrityError);
|
||||
}
|
||||
}
|
||||
|
||||
trace!("Packet {} received: {:?}", self.seq.0, packet);
|
||||
self.process(packet)?;
|
||||
|
||||
self.seq.0 += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send(&mut self, packet: &Packet) -> io::Result<()> {
|
||||
packet.write_to(&mut self.stream)
|
||||
pub fn send(&mut self, packet: Packet) -> io::Result<()> {
|
||||
trace!("Sending packet {}: {:?}", self.seq.1, packet);
|
||||
|
||||
let packet = packet.to_raw()?;
|
||||
|
||||
if let Some((_, ref mut s2c)) = self.encryption {
|
||||
|
||||
let mut encrypted = vec![0; packet.data().len()];
|
||||
s2c.encrypt(packet.data(), encrypted.as_mut_slice());
|
||||
|
||||
// Sending encrypted packet
|
||||
self.stream.write_all(encrypted.as_slice())?;
|
||||
}
|
||||
else {
|
||||
packet.write_to(&mut self.stream)?;
|
||||
}
|
||||
|
||||
self.seq.1 += 1;
|
||||
|
||||
if let Some((_, ref mut mac)) = self.mac {
|
||||
let mut sig = vec![0; mac.size()];
|
||||
mac.sign(packet.data(), self.seq.1, sig.as_mut_slice());
|
||||
self.stream.write_all(sig.as_slice())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn send_id(&mut self) -> io::Result<()> {
|
||||
|
|
@ -134,18 +177,18 @@ impl<'a> Connection {
|
|||
match packet.msg_type()
|
||||
{
|
||||
MessageType::KexInit => {
|
||||
println!("Starting Key Exchange!");
|
||||
debug!("Starting key exchange");
|
||||
self.kex_init(packet)
|
||||
}
|
||||
MessageType::NewKeys => {
|
||||
println!("Switching to new Keys");
|
||||
debug!("Switching to new keys");
|
||||
|
||||
let iv_c2s = self.generate_key(b"A", 256)?;
|
||||
let iv_s2c = self.generate_key(b"B", 256)?;
|
||||
let enc_c2s = self.generate_key(b"C", 256)?;
|
||||
let enc_s2c = self.generate_key(b"D", 256)?;
|
||||
let int_c2s = self.generate_key(b"E", 256)?;
|
||||
let int_s2c = self.generate_key(b"F", 256)?;
|
||||
let mac_c2s = self.generate_key(b"E", 256)?;
|
||||
let mac_s2c = self.generate_key(b"F", 256)?;
|
||||
|
||||
self.encryption =
|
||||
Some((
|
||||
|
|
@ -157,6 +200,29 @@ impl<'a> Connection {
|
|||
),
|
||||
));
|
||||
|
||||
self.mac = Some((
|
||||
Box::new(Hmac::new(mac_c2s.as_slice())),
|
||||
Box::new(Hmac::new(mac_s2c.as_slice())),
|
||||
));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
MessageType::ServiceRequest => {
|
||||
let mut reader = packet.reader();
|
||||
let name = reader.read_string()?;
|
||||
|
||||
trace!(
|
||||
"{:?}",
|
||||
::std::str::from_utf8(&name.as_slice()).unwrap()
|
||||
);
|
||||
|
||||
let mut res = Packet::new(MessageType::ServiceAccept);
|
||||
res.with_writer(&|w| {
|
||||
w.write_bytes(name.as_slice())?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
self.send(res)?;
|
||||
Ok(())
|
||||
}
|
||||
MessageType::KeyExchange(_) => {
|
||||
|
|
@ -168,7 +234,7 @@ impl<'a> Connection {
|
|||
{
|
||||
KexResult::Done(packet) => {
|
||||
self.state = ConnectionState::Established;
|
||||
self.send(&packet)?;
|
||||
self.send(packet)?;
|
||||
|
||||
if self.session_id.is_none() {
|
||||
self.session_id =
|
||||
|
|
@ -176,11 +242,11 @@ impl<'a> Connection {
|
|||
}
|
||||
|
||||
let packet = Packet::new(MessageType::NewKeys);
|
||||
self.send(&packet)?;
|
||||
self.send(packet)?;
|
||||
Ok(())
|
||||
}
|
||||
KexResult::Ok(packet) => {
|
||||
self.send(&packet)?;
|
||||
self.send(packet)?;
|
||||
Ok(())
|
||||
}
|
||||
KexResult::Error => Err(ConnectionError::KeyExchangeError),
|
||||
|
|
@ -190,8 +256,8 @@ impl<'a> Connection {
|
|||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
println!("Unhandled packet: {:?}", packet);
|
||||
Err(ConnectionError::KeyExchangeError)
|
||||
error!("Unhandled packet: {:?}", packet);
|
||||
Err(ConnectionError::ProtocolError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -220,11 +286,11 @@ impl<'a> Connection {
|
|||
let mac_algo = negotiate(MAC, mac_algos_s2c.as_slice())?;
|
||||
let comp_algo = negotiate(COMPRESSION, comp_algos_s2c.as_slice())?;
|
||||
|
||||
println!("Negotiated Kex Algorithm: {:?}", kex_algo);
|
||||
println!("Negotiated Host Key Algorithm: {:?}", srv_host_key_algo);
|
||||
println!("Negotiated Encryption Algorithm: {:?}", enc_algo);
|
||||
println!("Negotiated Mac Algorithm: {:?}", mac_algo);
|
||||
println!("Negotiated Comp Algorithm: {:?}", comp_algo);
|
||||
debug!("Negotiated Kex Algorithm: {:?}", kex_algo);
|
||||
debug!("Negotiated Host Key Algorithm: {:?}", srv_host_key_algo);
|
||||
debug!("Negotiated Encryption Algorithm: {:?}", enc_algo);
|
||||
debug!("Negotiated Mac Algorithm: {:?}", mac_algo);
|
||||
debug!("Negotiated Comp Algorithm: {:?}", comp_algo);
|
||||
}
|
||||
|
||||
// Save payload for hash generation
|
||||
|
|
|
|||
|
|
@ -9,16 +9,18 @@ pub struct AesCtr {
|
|||
|
||||
impl AesCtr {
|
||||
pub fn new(key: &[u8], iv: &[u8]) -> AesCtr {
|
||||
AesCtr { cipher: ctr(KeySize::KeySize256, key, iv) }
|
||||
AesCtr { cipher: ctr(KeySize::KeySize256, key, &iv[0..16]) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Encryption for AesCtr {
|
||||
fn encrypt(&mut self, data: &[u8], buf: &mut [u8]) {
|
||||
trace!("Encrypting {} -> {}", data.len(), buf.len());
|
||||
self.cipher.process(data, buf);
|
||||
}
|
||||
|
||||
fn decrypt(&mut self, data: &[u8], buf: &mut [u8]) {
|
||||
self.encrypt(data, buf);
|
||||
trace!("Decrypting {} -> {}", data.len(), buf.len());
|
||||
self.cipher.process(data, buf);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,11 @@ impl<'a> Decryptor<'a> {
|
|||
impl<'a> Read for Decryptor<'a> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let mut tmp = vec![0; buf.len()];
|
||||
self.stream.read(tmp.as_mut_slice())?;
|
||||
self.encryption.decrypt(tmp.as_slice(), buf);
|
||||
Ok(buf.len())
|
||||
let count = self.stream.read(tmp.as_mut_slice())?;
|
||||
self.encryption.decrypt(
|
||||
&tmp.as_slice()[0..count],
|
||||
&mut buf[0..count],
|
||||
);
|
||||
Ok(count)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ pub enum ConnectionError {
|
|||
NegotiationError,
|
||||
KeyExchangeError,
|
||||
KeyGenerationError,
|
||||
IntegrityError,
|
||||
}
|
||||
|
||||
impl fmt::Display for ConnectionError {
|
||||
|
|
@ -30,6 +31,7 @@ impl Error for ConnectionError {
|
|||
&NegotiationError => "negotiation error",
|
||||
&KeyExchangeError => "key exchange error",
|
||||
&KeyGenerationError => "key generation error",
|
||||
&IntegrityError => "integrity error",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ const ECDH_KEX_INIT: u8 = 30;
|
|||
const ECDH_KEX_REPLY: u8 = 31;
|
||||
|
||||
pub struct Curve25519 {
|
||||
shared_secret: Option<[u8; 32]>,
|
||||
shared_secret: Option<Vec<u8>>,
|
||||
exchange_hash: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
|
|
@ -65,7 +65,6 @@ impl KeyExchange for Curve25519 {
|
|||
key
|
||||
};
|
||||
|
||||
println!("Received qc: {:?}", client_public);
|
||||
let mut packet =
|
||||
Packet::new(MessageType::KeyExchange(ECDH_KEX_REPLY));
|
||||
|
||||
|
|
@ -82,8 +81,14 @@ impl KeyExchange for Curve25519 {
|
|||
};
|
||||
|
||||
let server_public = curve25519::curve25519_base(&server_secret);
|
||||
let shared_secret =
|
||||
curve25519::curve25519(&server_secret, &client_public);
|
||||
let shared_secret = {
|
||||
let mut buf = Vec::new();
|
||||
buf.write_mpint(BigInt::from_bytes_be(
|
||||
Sign::Plus,
|
||||
&curve25519::curve25519(&server_secret, &client_public),
|
||||
));
|
||||
buf
|
||||
};
|
||||
|
||||
let hash_data = {
|
||||
let mut buf = Vec::new();
|
||||
|
|
@ -104,9 +109,7 @@ impl KeyExchange for Curve25519 {
|
|||
buf.write_bytes(item);
|
||||
}
|
||||
|
||||
buf.write_mpint(
|
||||
BigInt::from_bytes_be(Sign::Plus, &shared_secret),
|
||||
);
|
||||
buf.write_raw_bytes(&shared_secret);
|
||||
|
||||
buf
|
||||
};
|
||||
|
|
@ -115,10 +118,6 @@ impl KeyExchange for Curve25519 {
|
|||
let hash = self.hash(&[hash_data.as_slice()]);
|
||||
let signature = config.as_ref().key.sign(&hash).unwrap();
|
||||
|
||||
println!("Hash: {:?}", hash);
|
||||
println!("Public Key: {:?}", public_key);
|
||||
println!("Signature: {:?}", signature);
|
||||
|
||||
packet
|
||||
.with_writer(&|w| {
|
||||
w.write_bytes(public_key.as_slice())?;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ mod message;
|
|||
mod connection;
|
||||
mod key_exchange;
|
||||
mod encryption;
|
||||
mod mac;
|
||||
|
||||
pub mod public_key;
|
||||
pub mod server;
|
||||
|
|
|
|||
35
src/mac/hmac.rs
Normal file
35
src/mac/hmac.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use crypto::hmac::Hmac as rcHmac;
|
||||
use crypto::mac::Mac;
|
||||
use crypto::sha2::Sha256;
|
||||
use mac::MacAlgorithm;
|
||||
|
||||
pub struct Hmac {
|
||||
hmac: Box<rcHmac<Sha256>>,
|
||||
}
|
||||
|
||||
impl Hmac {
|
||||
pub fn new(key: &[u8]) -> Hmac {
|
||||
let digest = Sha256::new();
|
||||
Hmac { hmac: Box::new(rcHmac::new(digest, key)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl MacAlgorithm for Hmac {
|
||||
fn size(&self) -> usize {
|
||||
32
|
||||
}
|
||||
|
||||
fn sign(&mut self, data: &[u8], seq: u32, buf: &mut [u8]) {
|
||||
let sequence = &[
|
||||
((seq & 0xff000000) >> 24) as u8,
|
||||
((seq & 0x00ff0000) >> 16) as u8,
|
||||
((seq & 0x0000ff00) >> 8) as u8,
|
||||
((seq & 0x000000ff)) as u8,
|
||||
];
|
||||
|
||||
self.hmac.input(sequence);
|
||||
self.hmac.input(data);
|
||||
self.hmac.raw_result(buf);
|
||||
self.hmac.reset();
|
||||
}
|
||||
}
|
||||
8
src/mac/mod.rs
Normal file
8
src/mac/mod.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
mod hmac;
|
||||
|
||||
pub use self::hmac::Hmac;
|
||||
|
||||
pub trait MacAlgorithm {
|
||||
fn size(&self) -> usize;
|
||||
fn sign(&mut self, data: &[u8], seq: u32, buf: &mut [u8]);
|
||||
}
|
||||
138
src/packet.rs
138
src/packet.rs
|
|
@ -8,85 +8,137 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
|||
use message::MessageType;
|
||||
use num_bigint::BigInt;
|
||||
|
||||
pub struct Packet {
|
||||
payload: Vec<u8>,
|
||||
pub enum Packet {
|
||||
Raw(Vec<u8>, usize),
|
||||
Payload(Vec<u8>),
|
||||
}
|
||||
|
||||
impl Packet {
|
||||
pub fn new(msg_type: MessageType) -> Packet {
|
||||
Packet { payload: (&[msg_type.into()]).to_vec() }
|
||||
Packet::Payload([msg_type.into()].to_vec())
|
||||
}
|
||||
|
||||
pub fn msg_type(&self) -> MessageType {
|
||||
self.payload[0].into()
|
||||
}
|
||||
|
||||
pub fn payload(self) -> Vec<u8> {
|
||||
self.payload
|
||||
match self
|
||||
{
|
||||
&Packet::Raw(ref data, _) => data[5],
|
||||
&Packet::Payload(ref data) => data[0],
|
||||
}.into()
|
||||
}
|
||||
|
||||
pub fn read_from<R: io::Read>(stream: &mut R) -> Result<Packet> {
|
||||
let mac_len = 0;
|
||||
|
||||
trace!("Waiting for incoming packet...");
|
||||
let packet_len = stream.read_u32::<BigEndian>()? as usize;
|
||||
trace!("Read incoming packet ({} bytes)", packet_len);
|
||||
|
||||
let padding_len = stream.read_u8()? as usize;
|
||||
let payload_len = packet_len - padding_len - 1;
|
||||
trace!("Padding: {} bytes", padding_len);
|
||||
let packet_len = stream.read_uint32()? as usize;
|
||||
trace!("Reading incoming packet ({} bytes)", packet_len);
|
||||
|
||||
// TODO: Prevent packets that are too large
|
||||
|
||||
let mut payload = Vec::with_capacity(payload_len);
|
||||
let mut padding = Vec::with_capacity(padding_len);
|
||||
// let mut mac = Vec::with_capacity(mac_len);
|
||||
let mut raw = Vec::with_capacity(packet_len + 4);
|
||||
raw.write_uint32(packet_len as u32)?;
|
||||
|
||||
trace!("Reading packet...");
|
||||
stream.take(payload_len as u64).read_to_end(&mut payload)?;
|
||||
trace!("Reading payload...");
|
||||
stream.take(padding_len as u64).read_to_end(&mut padding)?;
|
||||
let count = stream.take(packet_len as u64).read_to_end(&mut raw)?;
|
||||
|
||||
// if mac_len > 0 {
|
||||
// stream.take(mac_len as u64).read_to_end(&mut mac);
|
||||
// }
|
||||
|
||||
Ok(Packet { payload: payload })
|
||||
if count == packet_len {
|
||||
let padding_len = raw[4] as usize;
|
||||
let payload_len = packet_len - padding_len - 1;
|
||||
// TODO: Verify packet size (mod 8)
|
||||
Ok(Packet::Raw(raw, payload_len))
|
||||
}
|
||||
else {
|
||||
Err(io::Error::new(io::ErrorKind::BrokenPipe, "broken stream"))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_to<W: io::Write>(&self, stream: &mut W) -> Result<()> {
|
||||
let padding_len = self.padding_len();
|
||||
let packet_len = self.payload.len() + padding_len + 1;
|
||||
match self
|
||||
{
|
||||
&Packet::Raw(ref data, _) => {
|
||||
stream.write_all(data)?;
|
||||
stream.flush()
|
||||
}
|
||||
&Packet::Payload(ref payload) => {
|
||||
let padding_len = self.padding_len();
|
||||
let packet_len = payload.len() + padding_len + 1;
|
||||
|
||||
stream.write_u32::<BigEndian>(packet_len as u32)?;
|
||||
stream.write_u8(padding_len as u8)?;
|
||||
stream.write(&self.payload)?;
|
||||
stream.write(&[0u8; 255][..padding_len])?;
|
||||
stream.flush()?;
|
||||
stream.write_u32::<BigEndian>(packet_len as u32)?;
|
||||
stream.write_u8(padding_len as u8)?;
|
||||
stream.write_all(&payload)?;
|
||||
stream.write_all(&[0u8; 255][..padding_len])?;
|
||||
|
||||
Ok(())
|
||||
stream.flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn payload(self) -> Vec<u8> {
|
||||
match self
|
||||
{
|
||||
Packet::Raw(data, payload_len) => data[5..payload_len + 5].to_vec(),
|
||||
Packet::Payload(payload) => payload,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data<'a>(&'a self) -> &'a [u8] {
|
||||
match self
|
||||
{
|
||||
&Packet::Raw(ref data, _) => &data,
|
||||
&Packet::Payload(ref payload) => &payload,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_raw(self) -> Result<Packet> {
|
||||
match self
|
||||
{
|
||||
Packet::Raw(_, _) => Ok(self),
|
||||
Packet::Payload(ref payload) => {
|
||||
let mut buf = Vec::with_capacity(payload.len());
|
||||
self.write_to(&mut buf)?;
|
||||
Ok(Packet::Raw(buf, payload.len()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writer<'a>(&'a mut self) -> &'a mut Write {
|
||||
&mut self.payload
|
||||
match self
|
||||
{
|
||||
&mut Packet::Raw(ref mut data, _) => data,
|
||||
&mut Packet::Payload(ref mut payload) => payload,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_writer(&mut self, f: &Fn(&mut Write) -> Result<()>)
|
||||
-> Result<()> {
|
||||
f(&mut self.payload)
|
||||
f(self.writer())
|
||||
}
|
||||
|
||||
pub fn reader<'a>(&'a self) -> BufReader<&'a [u8]> {
|
||||
BufReader::new(&self.payload.as_slice()[1..])
|
||||
match self
|
||||
{
|
||||
&Packet::Raw(ref data, payload_len) => {
|
||||
BufReader::new(&data.as_slice()[6..payload_len + 5])
|
||||
}
|
||||
&Packet::Payload(ref payload) => {
|
||||
BufReader::new(&payload.as_slice()[1..])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn payload_len(&self) -> usize {
|
||||
match self
|
||||
{
|
||||
&Packet::Raw(_, payload_len) => payload_len,
|
||||
&Packet::Payload(ref payload) => payload.len(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn padding_len(&self) -> usize {
|
||||
let align = 32;
|
||||
|
||||
// Calculate the padding to reach a multiple of 8 bytes
|
||||
let padding_len = 8 - ((self.payload.len() + 5) % 8);
|
||||
let padding_len = align - ((self.payload_len() + 5) % align);
|
||||
|
||||
// The padding has to be at least 4 bytes long
|
||||
if padding_len < 4 {
|
||||
padding_len + 8
|
||||
padding_len + align
|
||||
}
|
||||
else {
|
||||
padding_len
|
||||
|
|
@ -200,7 +252,7 @@ impl fmt::Debug for Packet {
|
|||
f,
|
||||
"Packet({:?}, {} bytes)",
|
||||
self.msg_type(),
|
||||
self.payload.len()
|
||||
self.payload_len()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue