2020-08-14 16:20:42 -04:00
|
|
|
// Copyright (c) Facebook, Inc. and its affiliates.
|
|
|
|
|
//
|
|
|
|
|
// This source code is licensed under the MIT license found in the
|
|
|
|
|
// LICENSE file in the root directory of this source tree.
|
2020-10-09 10:51:58 -07:00
|
|
|
|
2021-08-22 12:28:19 -07:00
|
|
|
use crate::errors::ProtocolError;
|
2021-08-12 06:25:07 +02:00
|
|
|
use alloc::vec::Vec;
|
2020-08-14 16:20:42 -04:00
|
|
|
|
2020-11-12 10:00:09 -08:00
|
|
|
// Corresponds to the I2OSP() function from RFC8017
|
2021-08-22 12:28:19 -07:00
|
|
|
pub(crate) fn i2osp(input: usize, length: usize) -> Result<alloc::vec::Vec<u8>, ProtocolError> {
|
2021-08-12 06:25:07 +02:00
|
|
|
let sizeof_usize = core::mem::size_of::<usize>();
|
2021-07-08 11:04:32 -07:00
|
|
|
|
|
|
|
|
// Check if input >= 256^length
|
|
|
|
|
if (sizeof_usize as u32 - input.leading_zeros() / 8) > length as u32 {
|
2021-08-22 12:28:19 -07:00
|
|
|
return Err(ProtocolError::SerializationError);
|
2021-07-08 11:04:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if length <= sizeof_usize {
|
|
|
|
|
return Ok((&input.to_be_bytes()[sizeof_usize - length..]).to_vec());
|
2020-11-12 10:00:09 -08:00
|
|
|
}
|
|
|
|
|
|
2021-08-12 06:25:07 +02:00
|
|
|
let mut output = alloc::vec![0u8; length];
|
2020-11-12 10:00:09 -08:00
|
|
|
output.splice(
|
2021-07-08 11:04:32 -07:00
|
|
|
length - sizeof_usize..length,
|
2020-11-12 10:00:09 -08:00
|
|
|
input.to_be_bytes().iter().cloned(),
|
|
|
|
|
);
|
2021-07-08 11:04:32 -07:00
|
|
|
Ok(output)
|
2020-08-14 16:20:42 -04:00
|
|
|
}
|
|
|
|
|
|
2020-11-12 10:00:09 -08:00
|
|
|
// Corresponds to the OS2IP() function from RFC8017
|
2021-08-22 12:28:19 -07:00
|
|
|
pub(crate) fn os2ip(input: &[u8]) -> Result<usize, ProtocolError> {
|
2021-08-12 06:25:07 +02:00
|
|
|
if input.len() > core::mem::size_of::<usize>() {
|
2021-08-22 12:28:19 -07:00
|
|
|
return Err(ProtocolError::SerializationError);
|
2020-08-14 16:20:42 -04:00
|
|
|
}
|
|
|
|
|
|
2021-08-12 06:25:07 +02:00
|
|
|
let mut output_array = [0u8; core::mem::size_of::<usize>()];
|
|
|
|
|
output_array[core::mem::size_of::<usize>() - input.len()..].copy_from_slice(input);
|
2020-11-12 10:00:09 -08:00
|
|
|
Ok(usize::from_be_bytes(output_array))
|
|
|
|
|
}
|
2020-11-12 09:56:06 -05:00
|
|
|
|
2020-11-12 10:00:09 -08:00
|
|
|
// Computes I2OSP(len(input), max_bytes) || input
|
2021-08-22 12:28:19 -07:00
|
|
|
pub(crate) fn serialize(input: &[u8], max_bytes: usize) -> Result<Vec<u8>, ProtocolError> {
|
2021-07-08 11:04:32 -07:00
|
|
|
Ok([&i2osp(input.len(), max_bytes)?, input].concat())
|
2020-11-12 10:00:09 -08:00
|
|
|
}
|
2020-11-12 09:56:06 -05:00
|
|
|
|
2020-11-12 10:00:09 -08:00
|
|
|
// Tokenizes an input of the format I2OSP(len(input), max_bytes) || input, outputting
|
|
|
|
|
// (input, remainder)
|
2021-08-22 12:28:19 -07:00
|
|
|
pub(crate) fn tokenize(
|
|
|
|
|
input: &[u8],
|
|
|
|
|
size_bytes: usize,
|
|
|
|
|
) -> Result<(Vec<u8>, Vec<u8>), ProtocolError> {
|
2021-08-12 06:25:07 +02:00
|
|
|
if size_bytes > core::mem::size_of::<usize>() || input.len() < size_bytes {
|
2021-08-22 12:28:19 -07:00
|
|
|
return Err(ProtocolError::SerializationError);
|
2020-11-12 09:56:06 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-12 10:00:09 -08:00
|
|
|
let size = os2ip(&input[..size_bytes])?;
|
2020-08-14 16:20:42 -04:00
|
|
|
if size_bytes + size > input.len() {
|
2021-08-22 12:28:19 -07:00
|
|
|
return Err(ProtocolError::SerializationError);
|
2020-08-14 16:20:42 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok((
|
|
|
|
|
input[size_bytes..size_bytes + size].to_vec(),
|
|
|
|
|
input[size_bytes + size..].to_vec(),
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests;
|
2021-07-08 11:04:32 -07:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod unit_tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
// Test the error condition for I2OSP
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_i2osp_err_check() {
|
|
|
|
|
assert!(i2osp(0, 1).is_ok());
|
|
|
|
|
|
|
|
|
|
assert!(i2osp(255, 1).is_ok());
|
|
|
|
|
assert!(i2osp(256, 1).is_err());
|
|
|
|
|
assert!(i2osp(257, 1).is_err());
|
|
|
|
|
|
|
|
|
|
assert!(i2osp(256 * 256 - 1, 2).is_ok());
|
|
|
|
|
assert!(i2osp(256 * 256, 2).is_err());
|
|
|
|
|
assert!(i2osp(256 * 256 + 1, 2).is_err());
|
|
|
|
|
}
|
|
|
|
|
}
|