chore: Move xor_into, copying and base64 utils into own crates

This commit is contained in:
Karolin Varner
2023-11-16 18:39:19 +01:00
committed by Karolin Varner
parent c9cef05b29
commit a220c11e67
16 changed files with 141 additions and 85 deletions

14
Cargo.lock generated
View File

@@ -1014,7 +1014,6 @@ name = "rosenpass"
version = "0.2.1"
dependencies = [
"anyhow",
"base64",
"clap 4.4.8",
"criterion",
"env_logger",
@@ -1025,6 +1024,8 @@ dependencies = [
"mio",
"oqs-sys",
"paste",
"rosenpass-constant-time",
"rosenpass-util",
"serde",
"stacker",
"static_assertions",
@@ -1033,6 +1034,17 @@ dependencies = [
"toml",
]
[[package]]
name = "rosenpass-constant-time"
version = "0.1.0"
[[package]]
name = "rosenpass-util"
version = "0.1.0"
dependencies = [
"base64",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"

View File

@@ -3,6 +3,8 @@ resolver = "2"
members = [
"rosenpass",
"rosenpass-util",
"rosenpass-constant-time",
]
[workspace.metadata.release]

View File

@@ -0,0 +1,14 @@
[package]
name = "rosenpass-constant-time"
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 utilities for constant time crypto implementations"
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]

View File

@@ -0,0 +1,5 @@
# Rosenpass constant time library
Rosenpass internal library providing basic constant-time operations.
This is an internal library; not guarantee is made about its API at this point in time.

View File

@@ -0,0 +1,18 @@
/// Xors a and b element-wise and writes the result into a.
///
/// # Examples
///
/// ```
/// use rosenpass_constant_time::xor_into;
/// let mut a = String::from("hello").into_bytes();
/// let b = b"world";
/// xor_into(&mut a, b);
/// assert_eq!(&a, b"\x1f\n\x1e\x00\x0b");
/// ```
#[inline]
pub fn xor_into(a: &mut [u8], b: &[u8]) {
assert!(a.len() == b.len());
for (av, bv) in a.iter_mut().zip(b.iter()) {
*av ^= *bv;
}
}

15
rosenpass-util/Cargo.toml Normal file
View File

@@ -0,0 +1,15 @@
[package]
name = "rosenpass-util"
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 utilities"
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]
base64 = "0.21.1"

20
rosenpass-util/src/b64.rs Normal file
View File

@@ -0,0 +1,20 @@
use base64::{
display::Base64Display as B64Display, read::DecoderReader as B64Reader,
write::EncoderWriter as B64Writer,
};
use std::io::{Read, Write};
use base64::engine::general_purpose::GeneralPurpose as Base64Engine;
const B64ENGINE: Base64Engine = base64::engine::general_purpose::STANDARD;
pub fn fmt_b64<'a>(payload: &'a [u8]) -> B64Display<'a, 'static, Base64Engine> {
B64Display::<'a, 'static>::new(payload, &B64ENGINE)
}
pub fn b64_writer<W: Write>(w: W) -> B64Writer<'static, Base64Engine, W> {
B64Writer::new(w, &B64ENGINE)
}
pub fn b64_reader<R: Read>(r: R) -> B64Reader<'static, Base64Engine, R> {
B64Reader::new(r, &B64ENGINE)
}

View File

@@ -0,0 +1,3 @@
pub mod b64;
pub mod mem;
pub mod result;

33
rosenpass-util/src/mem.rs Normal file
View File

@@ -0,0 +1,33 @@
use std::borrow::{Borrow, BorrowMut};
use std::cmp::min;
/// Concatenate two byte arrays
// TODO: Zeroize result?
#[macro_export]
macro_rules! cat {
($len:expr; $($toks:expr),+) => {{
let mut buf = [0u8; $len];
let mut off = 0;
$({
let tok = $toks;
let tr = ::std::borrow::Borrow::<[u8]>::borrow(tok);
(&mut buf[off..(off + tr.len())]).copy_from_slice(tr);
off += tr.len();
})+
assert!(off == buf.len(), "Size mismatch in cat!()");
buf
}}
}
// TODO: consistent inout ordering
pub fn cpy<T: BorrowMut<[u8]> + ?Sized, F: Borrow<[u8]> + ?Sized>(src: &F, dst: &mut T) {
dst.borrow_mut().copy_from_slice(src.borrow());
}
/// Copy from `src` to `dst`. If `src` and `dst` are not of equal length, copy as many bytes as possible.
pub fn cpy_min<T: BorrowMut<[u8]> + ?Sized, F: Borrow<[u8]> + ?Sized>(src: &F, dst: &mut T) {
let src = src.borrow();
let dst = dst.borrow_mut();
let len = min(src.len(), dst.len());
dst[..len].copy_from_slice(&src[..len]);
}

View File

@@ -0,0 +1,7 @@
/// Try block basically…returns a result and allows the use of the question mark operator inside
#[macro_export]
macro_rules! attempt {
($block:expr) => {
(|| -> ::anyhow::Result<_> { $block })()
};
}

View File

@@ -14,8 +14,9 @@ name = "handshake"
harness = false
[dependencies]
rosenpass-util = { path = "../rosenpass-util" }
rosenpass-constant-time = { path = "../rosenpass-constant-time" }
anyhow = { version = "1.0.71", features = ["backtrace"] }
base64 = "0.21.1"
static_assertions = "1.1.0"
memoffset = "0.9.0"
libsodium-sys-stable = { version = "1.19.28", features = ["use-pkg-config"] }

View File

@@ -26,8 +26,9 @@ use crate::util::fopen_w;
use crate::{
config::Verbosity,
protocol::{CryptoServer, MsgBuf, PeerPtr, SPk, SSk, SymKey, Timing},
util::{b64_writer, fmt_b64},
};
use rosenpass_util::attempt;
use rosenpass_util::b64::{b64_writer, fmt_b64};
const IPV4_ANY_ADDR: Ipv4Addr = Ipv4Addr::new(0, 0, 0, 0);
const IPV6_ANY_ADDR: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);

View File

@@ -8,10 +8,11 @@
use crate::{
sodium::{rng, zeroize},
util::{cpy, mutating},
util::mutating,
};
use lazy_static::lazy_static;
use libsodium_sys as libsodium;
use rosenpass_util::mem::cpy;
use std::{
collections::HashMap,
convert::TryInto,

View File

@@ -77,6 +77,7 @@ use crate::{
util::*,
};
use anyhow::{bail, ensure, Context, Result};
use rosenpass_util::{cat, mem::cpy_min};
use std::collections::hash_map::{
Entry::{Occupied, Vacant},
HashMap,

View File

@@ -1,9 +1,10 @@
//! Bindings and helpers for accessing libsodium functions
use crate::util::*;
use anyhow::{ensure, Result};
use libsodium_sys as libsodium;
use log::trace;
use rosenpass_constant_time::xor_into;
use rosenpass_util::attempt;
use static_assertions::const_assert_eq;
use std::os::raw::{c_ulonglong, c_void};
use std::ptr::{null as nullptr, null_mut as nullptr_mut};

View File

@@ -1,92 +1,14 @@
//! Helper functions and macros
use anyhow::{ensure, Context, Result};
use base64::{
display::Base64Display as B64Display, read::DecoderReader as B64Reader,
write::EncoderWriter as B64Writer,
};
use std::{
borrow::{Borrow, BorrowMut},
cmp::min,
fs::{File, OpenOptions},
io::{Read, Write},
io::Read,
path::Path,
time::{Duration, Instant},
};
use crate::coloring::{Public, Secret};
/// Xors a and b element-wise and writes the result into a.
///
/// # Examples
///
/// ```
/// use rosenpass::util::xor_into;
/// let mut a = String::from("hello").into_bytes();
/// let b = b"world";
/// xor_into(&mut a, b);
/// assert_eq!(&a, b"\x1f\n\x1e\x00\x0b");
/// ```
#[inline]
pub fn xor_into(a: &mut [u8], b: &[u8]) {
assert!(a.len() == b.len());
for (av, bv) in a.iter_mut().zip(b.iter()) {
*av ^= *bv;
}
}
/// Concatenate two byte arrays
// TODO: Zeroize result?
#[macro_export]
macro_rules! cat {
($len:expr; $($toks:expr),+) => {{
let mut buf = [0u8; $len];
let mut off = 0;
$({
let tok = $toks;
let tr = ::std::borrow::Borrow::<[u8]>::borrow(tok);
(&mut buf[off..(off + tr.len())]).copy_from_slice(tr);
off += tr.len();
})+
assert!(off == buf.len(), "Size mismatch in cat!()");
buf
}}
}
// TODO: consistent inout ordering
pub fn cpy<T: BorrowMut<[u8]> + ?Sized, F: Borrow<[u8]> + ?Sized>(src: &F, dst: &mut T) {
dst.borrow_mut().copy_from_slice(src.borrow());
}
/// Copy from `src` to `dst`. If `src` and `dst` are not of equal length, copy as many bytes as possible.
pub fn cpy_min<T: BorrowMut<[u8]> + ?Sized, F: Borrow<[u8]> + ?Sized>(src: &F, dst: &mut T) {
let src = src.borrow();
let dst = dst.borrow_mut();
let len = min(src.len(), dst.len());
dst[..len].copy_from_slice(&src[..len]);
}
/// Try block basically…returns a result and allows the use of the question mark operator inside
#[macro_export]
macro_rules! attempt {
($block:expr) => {
(|| -> ::anyhow::Result<_> { $block })()
};
}
use base64::engine::general_purpose::GeneralPurpose as Base64Engine;
const B64ENGINE: Base64Engine = base64::engine::general_purpose::STANDARD;
pub fn fmt_b64<'a>(payload: &'a [u8]) -> B64Display<'a, 'static, Base64Engine> {
B64Display::<'a, 'static>::new(payload, &B64ENGINE)
}
pub fn b64_writer<W: Write>(w: W) -> B64Writer<'static, Base64Engine, W> {
B64Writer::new(w, &B64ENGINE)
}
pub fn b64_reader<R: Read>(r: R) -> B64Reader<'static, Base64Engine, R> {
B64Reader::new(r, &B64ENGINE)
}
use rosenpass_util::b64::b64_reader;
// TODO remove this once std::cmp::max becomes const
pub const fn max_usize(a: usize, b: usize) -> usize {