mirror of
https://github.com/rosenpass/rosenpass.git
synced 2026-02-27 22:13:12 -08:00
feat: Move lenses into library
This commit is contained in:
committed by
Karolin Varner
parent
972e82b35f
commit
d45e24e9b6
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -1115,6 +1115,7 @@ dependencies = [
|
|||||||
"rosenpass-cipher-traits",
|
"rosenpass-cipher-traits",
|
||||||
"rosenpass-ciphers",
|
"rosenpass-ciphers",
|
||||||
"rosenpass-constant-time",
|
"rosenpass-constant-time",
|
||||||
|
"rosenpass-lenses",
|
||||||
"rosenpass-secret-memory",
|
"rosenpass-secret-memory",
|
||||||
"rosenpass-sodium",
|
"rosenpass-sodium",
|
||||||
"rosenpass-to",
|
"rosenpass-to",
|
||||||
@@ -1167,6 +1168,14 @@ dependencies = [
|
|||||||
"stacker",
|
"stacker",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rosenpass-lenses"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"paste",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rosenpass-oqs"
|
name = "rosenpass-oqs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ members = [
|
|||||||
"to",
|
"to",
|
||||||
"fuzz",
|
"fuzz",
|
||||||
"secret-memory",
|
"secret-memory",
|
||||||
|
"lenses",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
@@ -32,6 +33,7 @@ rosenpass-ciphers = { path = "ciphers" }
|
|||||||
rosenpass-to = { path = "to" }
|
rosenpass-to = { path = "to" }
|
||||||
rosenpass-secret-memory = { path = "secret-memory" }
|
rosenpass-secret-memory = { path = "secret-memory" }
|
||||||
rosenpass-oqs = { path = "oqs" }
|
rosenpass-oqs = { path = "oqs" }
|
||||||
|
rosenpass-lenses = { path = "lenses" }
|
||||||
criterion = "0.4.0"
|
criterion = "0.4.0"
|
||||||
test_bin = "0.4.0"
|
test_bin = "0.4.0"
|
||||||
libfuzzer-sys = "0.4"
|
libfuzzer-sys = "0.4"
|
||||||
|
|||||||
16
lenses/Cargo.toml
Normal file
16
lenses/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "rosenpass-lenses"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Karolin Varner <karo@cupdev.net>", "wucke13 <wucke13@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
description = "Rosenpass internal library for parsing binary data securely"
|
||||||
|
homepage = "https://rosenpass.eu/"
|
||||||
|
repository = "https://github.com/rosenpass/rosenpass"
|
||||||
|
readme = "readme.md"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
paste = { workspace = true }
|
||||||
|
thiserror = { workspace = true }
|
||||||
3
lenses/readme.md
Normal file
3
lenses/readme.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Rosenpass internal binary parsing library
|
||||||
|
|
||||||
|
This is an internal library; no guarantee is made about its API at this point in time.
|
||||||
206
lenses/src/lib.rs
Normal file
206
lenses/src/lib.rs
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
use std::result::Result;
|
||||||
|
|
||||||
|
/// Common trait shared by all Lenses
|
||||||
|
pub trait LenseView {
|
||||||
|
const LEN: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error during lense creation
|
||||||
|
#[derive(thiserror::Error, Debug, Eq, PartialEq, Clone)]
|
||||||
|
pub enum LenseError {
|
||||||
|
#[error("buffer size mismatch")]
|
||||||
|
BufferSizeMismatch,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type LenseResult<T> = Result<T, LenseError>;
|
||||||
|
|
||||||
|
impl LenseError {
|
||||||
|
pub fn ensure_exact_buffer_size(len: usize, required: usize) -> LenseResult<()> {
|
||||||
|
(len == required)
|
||||||
|
.then_some(())
|
||||||
|
.ok_or(LenseError::BufferSizeMismatch)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ensure_sufficient_buffer_size(len: usize, required: usize) -> LenseResult<()> {
|
||||||
|
(len >= required)
|
||||||
|
.then_some(())
|
||||||
|
.ok_or(LenseError::BufferSizeMismatch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A macro to create data lenses.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! lense(
|
||||||
|
// prefix @ offset ; optional meta ; field name : field length, ...
|
||||||
|
(token_muncher_ref @ $offset:expr ; $( $attr:meta )* ; $field:ident : $len:expr $(, $( $tail:tt )+ )?) => {
|
||||||
|
::paste::paste!{
|
||||||
|
|
||||||
|
#[allow(rustdoc::broken_intra_doc_links)]
|
||||||
|
$( #[ $attr ] )*
|
||||||
|
///
|
||||||
|
#[doc = lense!(maybe_docstring_link $len)]
|
||||||
|
/// bytes long
|
||||||
|
pub fn $field(&self) -> &__ContainerType::Output {
|
||||||
|
&self.0[$offset .. $offset + $len]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The bytes until the
|
||||||
|
#[doc = lense!(maybe_docstring_link Self::$field)]
|
||||||
|
/// field
|
||||||
|
pub fn [< until_ $field >](&self) -> &__ContainerType::Output {
|
||||||
|
&self.0[0 .. $offset]
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the tail exits, consume it as well
|
||||||
|
$(
|
||||||
|
lense!{token_muncher_ref @ $offset + $len ; $( $tail )+ }
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// prefix @ offset ; optional meta ; field name : field length, ...
|
||||||
|
(token_muncher_mut @ $offset:expr ; $( $attr:meta )* ; $field:ident : $len:expr $(, $( $tail:tt )+ )?) => {
|
||||||
|
::paste::paste!{
|
||||||
|
|
||||||
|
#[allow(rustdoc::broken_intra_doc_links)]
|
||||||
|
$( #[ $attr ] )*
|
||||||
|
///
|
||||||
|
#[doc = lense!(maybe_docstring_link $len)]
|
||||||
|
/// bytes long
|
||||||
|
pub fn [< $field _mut >](&mut self) -> &mut __ContainerType::Output {
|
||||||
|
&mut self.0[$offset .. $offset + $len]
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the tail exits, consume it as well
|
||||||
|
$(
|
||||||
|
lense!{token_muncher_mut @ $offset + $len ; $( $tail )+ }
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// switch that yields literals unchanged, but creates docstring links to
|
||||||
|
// constants
|
||||||
|
// TODO the doc string link doesn't work if $x is taken from a generic,
|
||||||
|
(maybe_docstring_link $x:literal) => (stringify!($x));
|
||||||
|
(maybe_docstring_link $x:expr) => (stringify!([$x]));
|
||||||
|
|
||||||
|
// struct name < optional generics > := optional doc string field name : field length, ...
|
||||||
|
($type:ident $( < $( $generic:ident ),+ > )? := $( $( #[ $attr:meta ] )* $field:ident : $len:expr ),+) => (::paste::paste!{
|
||||||
|
|
||||||
|
#[allow(rustdoc::broken_intra_doc_links)]
|
||||||
|
/// A data lense to manipulate byte slices.
|
||||||
|
///
|
||||||
|
//// # Fields
|
||||||
|
///
|
||||||
|
$(
|
||||||
|
/// - `
|
||||||
|
#[doc = stringify!($field)]
|
||||||
|
/// `:
|
||||||
|
#[doc = lense!(maybe_docstring_link $len)]
|
||||||
|
/// bytes
|
||||||
|
)+
|
||||||
|
pub struct $type<__ContainerType $(, $( $generic ),+ )? > (
|
||||||
|
__ContainerType,
|
||||||
|
// The phantom data is required, since all generics declared on a
|
||||||
|
// type need to be used on the type.
|
||||||
|
// https://doc.rust-lang.org/stable/error_codes/E0392.html
|
||||||
|
$( $( ::core::marker::PhantomData<$generic> ),+ )?
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<__ContainerType $(, $( $generic: LenseView ),+ )? > $type<__ContainerType $(, $( $generic ),+ )? >{
|
||||||
|
$(
|
||||||
|
/// Size in bytes of the field `
|
||||||
|
#[doc = !($field)]
|
||||||
|
/// `
|
||||||
|
pub const fn [< $field _len >]() -> usize{
|
||||||
|
$len
|
||||||
|
}
|
||||||
|
)+
|
||||||
|
|
||||||
|
/// Verify that `len` exactly holds [Self]
|
||||||
|
pub fn check_size(len: usize) -> ::rosenpass_lenses::LenseResult<()> {
|
||||||
|
::rosenpass_lenses::LenseError::ensure_exact_buffer_size(len, $( $len + )+ 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read-only accessor functions
|
||||||
|
impl<'a, __ContainerType $(, $( $generic: LenseView ),+ )?> $type<&'a __ContainerType $(, $( $generic ),+ )?>
|
||||||
|
where
|
||||||
|
__ContainerType: std::ops::Index<std::ops::Range<usize>> + ?Sized,
|
||||||
|
{
|
||||||
|
lense!{token_muncher_ref @ 0 ; $( $( $attr )* ; $field : $len ),+ }
|
||||||
|
|
||||||
|
/// View into all bytes belonging to this Lense
|
||||||
|
pub fn all_bytes(&self) -> &__ContainerType::Output {
|
||||||
|
&self.0[0..Self::LEN]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutable accessor functions
|
||||||
|
impl<'a, __ContainerType $(, $( $generic: LenseView ),+ )?> $type<&'a mut __ContainerType $(, $( $generic ),+ )?>
|
||||||
|
where
|
||||||
|
__ContainerType: std::ops::IndexMut<std::ops::Range<usize>> + ?Sized,
|
||||||
|
{
|
||||||
|
lense!{token_muncher_ref @ 0 ; $( $( $attr )* ; $field : $len ),+ }
|
||||||
|
lense!{token_muncher_mut @ 0 ; $( $( $attr )* ; $field : $len ),+ }
|
||||||
|
|
||||||
|
/// View into all bytes belonging to this Lense
|
||||||
|
pub fn all_bytes(&self) -> &__ContainerType::Output {
|
||||||
|
&self.0[0..Self::LEN]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// View into all bytes belonging to this Lense
|
||||||
|
pub fn all_bytes_mut(&mut self) -> &mut __ContainerType::Output {
|
||||||
|
&mut self.0[0..Self::LEN]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// lense trait, allowing us to know the implementing lenses size
|
||||||
|
impl<__ContainerType $(, $( $generic: LenseView ),+ )? > LenseView for $type<__ContainerType $(, $( $generic ),+ )? >{
|
||||||
|
/// Number of bytes required to store this type in binary format
|
||||||
|
const LEN: usize = $( $len + )+ 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extension trait to allow checked creation of a lense over
|
||||||
|
/// some byte slice that contains a
|
||||||
|
#[doc = lense!(maybe_docstring_link $type)]
|
||||||
|
pub trait [< $type Ext >] {
|
||||||
|
type __ContainerType;
|
||||||
|
|
||||||
|
/// Create a lense to the byte slice
|
||||||
|
fn [< $type:snake >] $(< $($generic : LenseView),* >)? (self) -> ::rosenpass_lenses::LenseResult< $type<Self::__ContainerType, $( $($generic),+ )? >>;
|
||||||
|
|
||||||
|
/// Create a lense to the byte slice, automatically truncating oversized buffers
|
||||||
|
fn [< $type:snake _ truncating >] $(< $($generic : LenseView),* >)? (self) -> ::rosenpass_lenses::LenseResult< $type<Self::__ContainerType, $( $($generic),+ )? >>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> [< $type Ext >] for &'a [u8] {
|
||||||
|
type __ContainerType = &'a [u8];
|
||||||
|
|
||||||
|
fn [< $type:snake >] $(< $($generic : LenseView),* >)? (self) -> ::rosenpass_lenses::LenseResult< $type<Self::__ContainerType, $( $($generic),+ )? >> {
|
||||||
|
$type::<Self::__ContainerType, $( $($generic),+ )? >::check_size(self.len())?;
|
||||||
|
Ok($type ( self, $( $( ::core::marker::PhantomData::<$generic> ),+ )? ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn [< $type:snake _ truncating >] $(< $($generic : LenseView),* >)? (self) -> ::rosenpass_lenses::LenseResult< $type<Self::__ContainerType, $( $($generic),+ )? >> {
|
||||||
|
let required_size = $( $len + )+ 0;
|
||||||
|
::rosenpass_lenses::LenseError::ensure_sufficient_buffer_size(self.len(), required_size)?;
|
||||||
|
[< $type Ext >]::[< $type:snake >](&self[..required_size])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> [< $type Ext >] for &'a mut [u8] {
|
||||||
|
type __ContainerType = &'a mut [u8];
|
||||||
|
fn [< $type:snake >] $(< $($generic : LenseView),* >)? (self) -> ::rosenpass_lenses::LenseResult< $type<Self::__ContainerType, $( $($generic),+ )? >> {
|
||||||
|
$type::<Self::__ContainerType, $( $($generic),+ )? >::check_size(self.len())?;
|
||||||
|
Ok($type ( self, $( $( ::core::marker::PhantomData::<$generic> ),+ )? ))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn [< $type:snake _ truncating >] $(< $($generic : LenseView),* >)? (self) -> ::rosenpass_lenses::LenseResult< $type<Self::__ContainerType, $( $($generic),+ )? >> {
|
||||||
|
let required_size = $( $len + )+ 0;
|
||||||
|
::rosenpass_lenses::LenseError::ensure_sufficient_buffer_size(self.len(), required_size)?;
|
||||||
|
[< $type Ext >]::[< $type:snake >](&mut self[..required_size])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
);
|
||||||
@@ -21,6 +21,7 @@ rosenpass-ciphers = { workspace = true }
|
|||||||
rosenpass-cipher-traits = { workspace = true }
|
rosenpass-cipher-traits = { workspace = true }
|
||||||
rosenpass-to = { workspace = true }
|
rosenpass-to = { workspace = true }
|
||||||
rosenpass-secret-memory = { workspace = true }
|
rosenpass-secret-memory = { workspace = true }
|
||||||
|
rosenpass-lenses = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
static_assertions = { workspace = true }
|
static_assertions = { workspace = true }
|
||||||
memoffset = { workspace = true }
|
memoffset = { workspace = true }
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use rosenpass_lenses::LenseError;
|
||||||
|
|
||||||
pub mod app_server;
|
pub mod app_server;
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
@@ -7,11 +9,16 @@ pub mod protocol;
|
|||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum RosenpassError {
|
pub enum RosenpassError {
|
||||||
#[error("buffer size mismatch, required {required_size} but found {actual_size}")]
|
#[error("buffer size mismatch")]
|
||||||
BufferSizeMismatch {
|
BufferSizeMismatch,
|
||||||
required_size: usize,
|
|
||||||
actual_size: usize,
|
|
||||||
},
|
|
||||||
#[error("invalid message type")]
|
#[error("invalid message type")]
|
||||||
InvalidMessageType(u8),
|
InvalidMessageType(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<LenseError> for RosenpassError {
|
||||||
|
fn from(value: LenseError) -> Self {
|
||||||
|
match value {
|
||||||
|
LenseError::BufferSizeMismatch => RosenpassError::BufferSizeMismatch,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,14 +9,15 @@
|
|||||||
//!
|
//!
|
||||||
//! # Example
|
//! # Example
|
||||||
//!
|
//!
|
||||||
//! The following example uses the [`data_lense` macro](crate::data_lense) to create a lense that
|
//! The following example uses the [`lense` macro](rosenpass_lenses::lense) to create a lense that
|
||||||
//! might be useful when dealing with UDP headers.
|
//! might be useful when dealing with UDP headers.
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use rosenpass::{data_lense, RosenpassError, msgs::LenseView};
|
//! use rosenpass_lenses::{lense, LenseView};
|
||||||
|
//! use rosenpass::RosenpassError;
|
||||||
//! # fn main() -> Result<(), RosenpassError> {
|
//! # fn main() -> Result<(), RosenpassError> {
|
||||||
//!
|
//!
|
||||||
//! data_lense! {UdpDatagramHeader :=
|
//! lense! {UdpDatagramHeader :=
|
||||||
//! source_port: 2,
|
//! source_port: 2,
|
||||||
//! dest_port: 2,
|
//! dest_port: 2,
|
||||||
//! length: 2,
|
//! length: 2,
|
||||||
@@ -47,217 +48,11 @@ use super::RosenpassError;
|
|||||||
use rosenpass_cipher_traits::Kem;
|
use rosenpass_cipher_traits::Kem;
|
||||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
||||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
||||||
|
use rosenpass_lenses::{lense, LenseView};
|
||||||
|
|
||||||
// Macro magic ////////////////////////////////////////////////////////////////
|
// Macro magic ////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// A macro to create data lenses. Refer to the [`msgs` mod](crate::msgs) for
|
lense! { Envelope<M> :=
|
||||||
/// an example and further elaboration
|
|
||||||
// TODO implement TryFrom<[u8]> and From<[u8; Self::len()]>
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! data_lense(
|
|
||||||
// prefix @ offset ; optional meta ; field name : field length, ...
|
|
||||||
(token_muncher_ref @ $offset:expr ; $( $attr:meta )* ; $field:ident : $len:expr $(, $( $tail:tt )+ )?) => {
|
|
||||||
::paste::paste!{
|
|
||||||
|
|
||||||
#[allow(rustdoc::broken_intra_doc_links)]
|
|
||||||
$( #[ $attr ] )*
|
|
||||||
///
|
|
||||||
#[doc = data_lense!(maybe_docstring_link $len)]
|
|
||||||
/// bytes long
|
|
||||||
pub fn $field(&self) -> &__ContainerType::Output {
|
|
||||||
&self.0[$offset .. $offset + $len]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The bytes until the
|
|
||||||
#[doc = data_lense!(maybe_docstring_link Self::$field)]
|
|
||||||
/// field
|
|
||||||
pub fn [< until_ $field >](&self) -> &__ContainerType::Output {
|
|
||||||
&self.0[0 .. $offset]
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the tail exits, consume it as well
|
|
||||||
$(
|
|
||||||
data_lense!{token_muncher_ref @ $offset + $len ; $( $tail )+ }
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// prefix @ offset ; optional meta ; field name : field length, ...
|
|
||||||
(token_muncher_mut @ $offset:expr ; $( $attr:meta )* ; $field:ident : $len:expr $(, $( $tail:tt )+ )?) => {
|
|
||||||
::paste::paste!{
|
|
||||||
|
|
||||||
#[allow(rustdoc::broken_intra_doc_links)]
|
|
||||||
$( #[ $attr ] )*
|
|
||||||
///
|
|
||||||
#[doc = data_lense!(maybe_docstring_link $len)]
|
|
||||||
/// bytes long
|
|
||||||
pub fn [< $field _mut >](&mut self) -> &mut __ContainerType::Output {
|
|
||||||
&mut self.0[$offset .. $offset + $len]
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the tail exits, consume it as well
|
|
||||||
$(
|
|
||||||
data_lense!{token_muncher_mut @ $offset + $len ; $( $tail )+ }
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// switch that yields literals unchanged, but creates docstring links to
|
|
||||||
// constants
|
|
||||||
// TODO the doc string link doesn't work if $x is taken from a generic,
|
|
||||||
(maybe_docstring_link $x:literal) => (stringify!($x));
|
|
||||||
(maybe_docstring_link $x:expr) => (stringify!([$x]));
|
|
||||||
|
|
||||||
// struct name < optional generics > := optional doc string field name : field length, ...
|
|
||||||
($type:ident $( < $( $generic:ident ),+ > )? := $( $( #[ $attr:meta ] )* $field:ident : $len:expr ),+) => (::paste::paste!{
|
|
||||||
|
|
||||||
#[allow(rustdoc::broken_intra_doc_links)]
|
|
||||||
/// A data lense to manipulate byte slices.
|
|
||||||
///
|
|
||||||
//// # Fields
|
|
||||||
///
|
|
||||||
$(
|
|
||||||
/// - `
|
|
||||||
#[doc = stringify!($field)]
|
|
||||||
/// `:
|
|
||||||
#[doc = data_lense!(maybe_docstring_link $len)]
|
|
||||||
/// bytes
|
|
||||||
)+
|
|
||||||
pub struct $type<__ContainerType $(, $( $generic ),+ )? > (
|
|
||||||
__ContainerType,
|
|
||||||
// The phantom data is required, since all generics declared on a
|
|
||||||
// type need to be used on the type.
|
|
||||||
// https://doc.rust-lang.org/stable/error_codes/E0392.html
|
|
||||||
$( $( ::core::marker::PhantomData<$generic> ),+ )?
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<__ContainerType $(, $( $generic: LenseView ),+ )? > $type<__ContainerType $(, $( $generic ),+ )? >{
|
|
||||||
$(
|
|
||||||
/// Size in bytes of the field `
|
|
||||||
#[doc = !($field)]
|
|
||||||
/// `
|
|
||||||
pub const fn [< $field _len >]() -> usize{
|
|
||||||
$len
|
|
||||||
}
|
|
||||||
)+
|
|
||||||
|
|
||||||
/// Verify that `len` is sufficiently long to hold [Self]
|
|
||||||
pub fn check_size(len: usize) -> Result<(), RosenpassError>{
|
|
||||||
let required_size = $( $len + )+ 0;
|
|
||||||
let actual_size = len;
|
|
||||||
if required_size != actual_size {
|
|
||||||
Err(RosenpassError::BufferSizeMismatch {
|
|
||||||
required_size,
|
|
||||||
actual_size,
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// read-only accessor functions
|
|
||||||
impl<'a, __ContainerType $(, $( $generic: LenseView ),+ )?> $type<&'a __ContainerType $(, $( $generic ),+ )?>
|
|
||||||
where
|
|
||||||
__ContainerType: std::ops::Index<std::ops::Range<usize>> + ?Sized,
|
|
||||||
{
|
|
||||||
data_lense!{token_muncher_ref @ 0 ; $( $( $attr )* ; $field : $len ),+ }
|
|
||||||
|
|
||||||
/// View into all bytes belonging to this Lense
|
|
||||||
pub fn all_bytes(&self) -> &__ContainerType::Output {
|
|
||||||
&self.0[0..Self::LEN]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mutable accessor functions
|
|
||||||
impl<'a, __ContainerType $(, $( $generic: LenseView ),+ )?> $type<&'a mut __ContainerType $(, $( $generic ),+ )?>
|
|
||||||
where
|
|
||||||
__ContainerType: std::ops::IndexMut<std::ops::Range<usize>> + ?Sized,
|
|
||||||
{
|
|
||||||
data_lense!{token_muncher_ref @ 0 ; $( $( $attr )* ; $field : $len ),+ }
|
|
||||||
data_lense!{token_muncher_mut @ 0 ; $( $( $attr )* ; $field : $len ),+ }
|
|
||||||
|
|
||||||
/// View into all bytes belonging to this Lense
|
|
||||||
pub fn all_bytes(&self) -> &__ContainerType::Output {
|
|
||||||
&self.0[0..Self::LEN]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// View into all bytes belonging to this Lense
|
|
||||||
pub fn all_bytes_mut(&mut self) -> &mut __ContainerType::Output {
|
|
||||||
&mut self.0[0..Self::LEN]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// lense trait, allowing us to know the implementing lenses size
|
|
||||||
impl<__ContainerType $(, $( $generic: LenseView ),+ )? > LenseView for $type<__ContainerType $(, $( $generic ),+ )? >{
|
|
||||||
/// Number of bytes required to store this type in binary format
|
|
||||||
const LEN: usize = $( $len + )+ 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extension trait to allow checked creation of a lense over
|
|
||||||
/// some byte slice that contains a
|
|
||||||
#[doc = data_lense!(maybe_docstring_link $type)]
|
|
||||||
pub trait [< $type Ext >] {
|
|
||||||
type __ContainerType;
|
|
||||||
|
|
||||||
/// Create a lense to the byte slice
|
|
||||||
fn [< $type:snake >] $(< $($generic : LenseView),* >)? (self) -> Result< $type<Self::__ContainerType, $( $($generic),+ )? >, RosenpassError>;
|
|
||||||
|
|
||||||
/// Create a lense to the byte slice, automatically truncating oversized buffers
|
|
||||||
fn [< $type:snake _ truncating >] $(< $($generic : LenseView),* >)? (self) -> Result< $type<Self::__ContainerType, $( $($generic),+ )? >, RosenpassError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> [< $type Ext >] for &'a [u8] {
|
|
||||||
type __ContainerType = &'a [u8];
|
|
||||||
|
|
||||||
fn [< $type:snake >] $(< $($generic : LenseView),* >)? (self) -> Result< $type<Self::__ContainerType, $( $($generic),+ )? >, RosenpassError> {
|
|
||||||
$type::<Self::__ContainerType, $( $($generic),+ )? >::check_size(self.len())?;
|
|
||||||
Ok($type ( self, $( $( ::core::marker::PhantomData::<$generic> ),+ )? ))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn [< $type:snake _ truncating >] $(< $($generic : LenseView),* >)? (self) -> Result< $type<Self::__ContainerType, $( $($generic),+ )? >, RosenpassError> {
|
|
||||||
let required_size = $( $len + )+ 0;
|
|
||||||
let actual_size = self.len();
|
|
||||||
if actual_size < required_size {
|
|
||||||
return Err(RosenpassError::BufferSizeMismatch {
|
|
||||||
required_size,
|
|
||||||
actual_size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[< $type Ext >]::[< $type:snake >](&self[..required_size])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> [< $type Ext >] for &'a mut [u8] {
|
|
||||||
type __ContainerType = &'a mut [u8];
|
|
||||||
fn [< $type:snake >] $(< $($generic : LenseView),* >)? (self) -> Result< $type<Self::__ContainerType, $( $($generic),+ )? >, RosenpassError> {
|
|
||||||
$type::<Self::__ContainerType, $( $($generic),+ )? >::check_size(self.len())?;
|
|
||||||
Ok($type ( self, $( $( ::core::marker::PhantomData::<$generic> ),+ )? ))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn [< $type:snake _ truncating >] $(< $($generic : LenseView),* >)? (self) -> Result< $type<Self::__ContainerType, $( $($generic),+ )? >, RosenpassError> {
|
|
||||||
let required_size = $( $len + )+ 0;
|
|
||||||
let actual_size = self.len();
|
|
||||||
if actual_size < required_size {
|
|
||||||
return Err(RosenpassError::BufferSizeMismatch {
|
|
||||||
required_size,
|
|
||||||
actual_size,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[< $type Ext >]::[< $type:snake >](&mut self[..required_size])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Common trait shared by all Lenses
|
|
||||||
pub trait LenseView {
|
|
||||||
const LEN: usize;
|
|
||||||
}
|
|
||||||
|
|
||||||
data_lense! { Envelope<M> :=
|
|
||||||
/// [MsgType] of this message
|
/// [MsgType] of this message
|
||||||
msg_type: 1,
|
msg_type: 1,
|
||||||
/// Reserved for future use
|
/// Reserved for future use
|
||||||
@@ -271,7 +66,7 @@ data_lense! { Envelope<M> :=
|
|||||||
cookie: 16
|
cookie: 16
|
||||||
}
|
}
|
||||||
|
|
||||||
data_lense! { InitHello :=
|
lense! { InitHello :=
|
||||||
/// Randomly generated connection id
|
/// Randomly generated connection id
|
||||||
sidi: 4,
|
sidi: 4,
|
||||||
/// Kyber 512 Ephemeral Public Key
|
/// Kyber 512 Ephemeral Public Key
|
||||||
@@ -284,7 +79,7 @@ data_lense! { InitHello :=
|
|||||||
auth: aead::TAG_LEN
|
auth: aead::TAG_LEN
|
||||||
}
|
}
|
||||||
|
|
||||||
data_lense! { RespHello :=
|
lense! { RespHello :=
|
||||||
/// Randomly generated connection id
|
/// Randomly generated connection id
|
||||||
sidr: 4,
|
sidr: 4,
|
||||||
/// Copied from InitHello
|
/// Copied from InitHello
|
||||||
@@ -299,7 +94,7 @@ data_lense! { RespHello :=
|
|||||||
biscuit: BISCUIT_CT_LEN
|
biscuit: BISCUIT_CT_LEN
|
||||||
}
|
}
|
||||||
|
|
||||||
data_lense! { InitConf :=
|
lense! { InitConf :=
|
||||||
/// Copied from InitHello
|
/// Copied from InitHello
|
||||||
sidi: 4,
|
sidi: 4,
|
||||||
/// Copied from RespHello
|
/// Copied from RespHello
|
||||||
@@ -310,7 +105,7 @@ data_lense! { InitConf :=
|
|||||||
auth: aead::TAG_LEN
|
auth: aead::TAG_LEN
|
||||||
}
|
}
|
||||||
|
|
||||||
data_lense! { EmptyData :=
|
lense! { EmptyData :=
|
||||||
/// Copied from RespHello
|
/// Copied from RespHello
|
||||||
sid: 4,
|
sid: 4,
|
||||||
/// Nonce
|
/// Nonce
|
||||||
@@ -319,7 +114,7 @@ data_lense! { EmptyData :=
|
|||||||
auth: aead::TAG_LEN
|
auth: aead::TAG_LEN
|
||||||
}
|
}
|
||||||
|
|
||||||
data_lense! { Biscuit :=
|
lense! { Biscuit :=
|
||||||
/// H(spki) – Ident ifies the initiator
|
/// H(spki) – Ident ifies the initiator
|
||||||
pidi: KEY_LEN,
|
pidi: KEY_LEN,
|
||||||
/// The biscuit number (replay protection)
|
/// The biscuit number (replay protection)
|
||||||
@@ -328,11 +123,11 @@ data_lense! { Biscuit :=
|
|||||||
ck: KEY_LEN
|
ck: KEY_LEN
|
||||||
}
|
}
|
||||||
|
|
||||||
data_lense! { DataMsg :=
|
lense! { DataMsg :=
|
||||||
dummy: 4
|
dummy: 4
|
||||||
}
|
}
|
||||||
|
|
||||||
data_lense! { CookieReply :=
|
lense! { CookieReply :=
|
||||||
dummy: 4
|
dummy: 4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ use rosenpass_cipher_traits::Kem;
|
|||||||
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
use rosenpass_ciphers::hash_domain::{SecretHashDomain, SecretHashDomainNamespace};
|
||||||
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
use rosenpass_ciphers::kem::{EphemeralKem, StaticKem};
|
||||||
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
use rosenpass_ciphers::{aead, xaead, KEY_LEN};
|
||||||
|
use rosenpass_lenses::LenseView;
|
||||||
use rosenpass_secret_memory::{Public, Secret};
|
use rosenpass_secret_memory::{Public, Secret};
|
||||||
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
use rosenpass_util::{cat, mem::cpy_min, ord::max_usize, time::Timebase};
|
||||||
use std::collections::hash_map::{
|
use std::collections::hash_map::{
|
||||||
|
|||||||
Reference in New Issue
Block a user