This commit is contained in:
Adam Ierymenko 2022-09-13 10:48:36 -04:00
parent 4763404d98
commit 07fc8b2d2b
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
87 changed files with 8325 additions and 6871 deletions

View file

@ -44,25 +44,55 @@ fn bind_udp_socket(_device_name: &str, address: &InetAddress) -> Result<FastUDPR
let mut setsockopt_results: c_int = 0;
fl = 1;
setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_REUSEPORT.as_(), (&mut fl as *mut c_int).cast(), fl_size);
setsockopt_results |= libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_REUSEPORT.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
);
fl = 0;
setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_LINGER.as_(), (&mut fl as *mut c_int).cast(), fl_size);
setsockopt_results |= libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_LINGER.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
);
//fl = 1;
//setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET, libc::SO_REUSEADDR, (&mut fl as *mut c_int).cast(), fl_size);
fl = 1;
setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_BROADCAST.as_(), (&mut fl as *mut c_int).cast(), fl_size);
setsockopt_results |= libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_BROADCAST.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
);
if af == libc::AF_INET6 {
fl = 1;
setsockopt_results |= libc::setsockopt(s, libc::IPPROTO_IPV6.as_(), libc::IPV6_V6ONLY.as_(), (&mut fl as *mut c_int).cast(), fl_size);
setsockopt_results |= libc::setsockopt(
s,
libc::IPPROTO_IPV6.as_(),
libc::IPV6_V6ONLY.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
);
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
{
fl = 1;
setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_NOSIGPIPE.as_(), (&mut fl as *mut c_int).cast(), fl_size)
setsockopt_results |= libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_NOSIGPIPE.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
)
}
#[cfg(target_os = "linux")]
@ -70,7 +100,13 @@ fn bind_udp_socket(_device_name: &str, address: &InetAddress) -> Result<FastUDPR
if !_device_name.is_empty() {
let _ = std::ffi::CString::new(_device_name).map(|dn| {
let dnb = dn.as_bytes_with_nul();
let _ = libc::setsockopt(s.as_(), libc::SOL_SOCKET.as_(), libc::SO_BINDTODEVICE.as_(), dnb.as_ptr().cast(), (dnb.len() - 1).as_());
let _ = libc::setsockopt(
s.as_(),
libc::SOL_SOCKET.as_(),
libc::SO_BINDTODEVICE.as_(),
dnb.as_ptr().cast(),
(dnb.len() - 1).as_(),
);
});
}
}
@ -84,30 +120,62 @@ fn bind_udp_socket(_device_name: &str, address: &InetAddress) -> Result<FastUDPR
#[cfg(not(target_os = "linux"))]
{
fl = 0;
libc::setsockopt(s, libc::IPPROTO_IP.as_(), libc::IP_DF.as_(), (&mut fl as *mut c_int).cast(), fl_size);
libc::setsockopt(
s,
libc::IPPROTO_IP.as_(),
libc::IP_DF.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
);
}
#[cfg(target_os = "linux")]
{
fl = libc::IP_PMTUDISC_DONT as c_int;
libc::setsockopt(s, libc::IPPROTO_IP.as_(), libc::IP_MTU_DISCOVER.as_(), (&mut fl as *mut c_int).cast(), fl_size);
libc::setsockopt(
s,
libc::IPPROTO_IP.as_(),
libc::IP_MTU_DISCOVER.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
);
}
}
if af == libc::AF_INET6 {
fl = 0;
libc::setsockopt(s, libc::IPPROTO_IPV6.as_(), libc::IPV6_DONTFRAG.as_(), (&mut fl as *mut c_int).cast(), fl_size);
libc::setsockopt(
s,
libc::IPPROTO_IPV6.as_(),
libc::IPV6_DONTFRAG.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
);
}
fl = 1048576;
while fl >= 131072 {
if libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_RCVBUF.as_(), (&mut fl as *mut c_int).cast(), fl_size) == 0 {
if libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_RCVBUF.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
) == 0
{
break;
}
fl -= 65536;
}
fl = 1048576;
while fl >= 131072 {
if libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_SNDBUF.as_(), (&mut fl as *mut c_int).cast(), fl_size) == 0 {
if libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_SNDBUF.as_(),
(&mut fl as *mut c_int).cast(),
fl_size,
) == 0
{
break;
}
fl -= 65536;
@ -172,10 +240,22 @@ pub(crate) fn fast_udp_socket_sendto(socket: &FastUDPRawOsSocket, to_address: &I
let _ = libc::sendmsg(socket.get().as_(), transmute(&mhdr as *const libc::msghdr), 0);
} else {
let mut ttl = packet_ttl as c_int;
libc::setsockopt(socket.get().as_(), libc::IPPROTO_IP.as_(), libc::IP_TTL.as_(), (&mut ttl as *mut c_int).cast(), std::mem::size_of::<c_int>().as_());
libc::setsockopt(
socket.get().as_(),
libc::IPPROTO_IP.as_(),
libc::IP_TTL.as_(),
(&mut ttl as *mut c_int).cast(),
std::mem::size_of::<c_int>().as_(),
);
let _ = libc::sendmsg(socket.get().as_(), transmute(&mhdr as *const libc::msghdr), 0);
ttl = 255;
libc::setsockopt(socket.get().as_(), libc::IPPROTO_IP.as_(), libc::IP_TTL.as_(), (&mut ttl as *mut c_int).cast(), std::mem::size_of::<c_int>().as_());
libc::setsockopt(
socket.get().as_(),
libc::IPPROTO_IP.as_(),
libc::IP_TTL.as_(),
(&mut ttl as *mut c_int).cast(),
std::mem::size_of::<c_int>().as_(),
);
}
}
}
@ -185,7 +265,14 @@ pub(crate) fn fast_udp_socket_sendto(socket: &FastUDPRawOsSocket, to_address: &I
fn fast_udp_socket_recvfrom(socket: &FastUDPRawOsSocket, buf: &mut PacketBuffer, from_address: &mut InetAddress) -> isize {
unsafe {
let mut addrlen = std::mem::size_of::<InetAddress>() as libc::socklen_t;
let s = libc::recvfrom(socket.get().as_(), buf.as_mut_ptr().cast(), buf.capacity().as_(), 0, (from_address as *mut InetAddress).cast(), &mut addrlen) as isize;
let s = libc::recvfrom(
socket.get().as_(),
buf.as_mut_ptr().cast(),
buf.capacity().as_(),
0,
(from_address as *mut InetAddress).cast(),
&mut addrlen,
) as isize;
if s > 0 {
buf.set_size_unchecked(s as usize);
}
@ -194,7 +281,12 @@ fn fast_udp_socket_recvfrom(socket: &FastUDPRawOsSocket, buf: &mut PacketBuffer,
}
impl FastUDPSocket {
pub fn new<F: Fn(&FastUDPRawOsSocket, &InetAddress, PacketBuffer) + Send + Sync + Clone + 'static>(device_name: &str, address: &InetAddress, packet_buffer_pool: &Arc<PacketBufferPool>, handler: F) -> Result<Self, String> {
pub fn new<F: Fn(&FastUDPRawOsSocket, &InetAddress, PacketBuffer) + Send + Sync + Clone + 'static>(
device_name: &str,
address: &InetAddress,
packet_buffer_pool: &Arc<PacketBufferPool>,
handler: F,
) -> Result<Self, String> {
let thread_count = num_cpus::get_physical().clamp(1, FAST_UDP_SOCKET_MAX_THREADS);
let mut s = Self {
@ -273,7 +365,14 @@ impl Drop for FastUDPSocket {
self.thread_run.store(false, Ordering::Relaxed);
for s in self.sockets.iter() {
unsafe {
libc::sendto(s.get().as_(), tmp.as_ptr().cast(), 0, 0, (&self.bind_address as *const InetAddress).cast(), std::mem::size_of::<InetAddress>() as libc::socklen_t);
libc::sendto(
s.get().as_(),
tmp.as_ptr().cast(),
0,
0,
(&self.bind_address as *const InetAddress).cast(),
std::mem::size_of::<InetAddress>() as libc::socklen_t,
);
}
}
for s in self.sockets.iter() {
@ -309,9 +408,14 @@ mod tests {
let ba0 = ba0.unwrap();
let cnt0 = Arc::new(AtomicU32::new(0));
let cnt0c = cnt0.clone();
let s0 = FastUDPSocket::new("", &ba0, &pool, move |sock: &FastUDPRawOsSocket, _: &InetAddress, data: PacketBuffer| {
let s0 = FastUDPSocket::new(
"",
&ba0,
&pool,
move |sock: &FastUDPRawOsSocket, _: &InetAddress, data: PacketBuffer| {
cnt0c.fetch_add(1, Ordering::Relaxed);
});
},
);
assert!(s0.is_ok());
let s0 = s0.unwrap();
@ -320,9 +424,14 @@ mod tests {
let ba1 = ba1.unwrap();
let cnt1 = Arc::new(AtomicU32::new(0));
let cnt1c = cnt1.clone();
let s1 = FastUDPSocket::new("", &ba1, &pool, move |sock: &FastUDPRawOsSocket, _: &InetAddress, data: PacketBuffer| {
let s1 = FastUDPSocket::new(
"",
&ba1,
&pool,
move |sock: &FastUDPRawOsSocket, _: &InetAddress, data: PacketBuffer| {
cnt1c.fetch_add(1, Ordering::Relaxed);
});
},
);
assert!(s1.is_ok());
let s1 = s1.unwrap();

View file

@ -55,7 +55,11 @@ impl<const BUCKETS: usize, const ITEM_BYTES: usize, const HASHES: usize> Clone f
// of implementing clone() may not since check_hash[] is u32.
unsafe {
let mut tmp: Self = std::mem::MaybeUninit::uninit().assume_init();
std::ptr::copy_nonoverlapping((self as *const Self).cast::<u8>(), (&mut tmp as *mut Self).cast::<u8>(), Self::SIZE_BYTES);
std::ptr::copy_nonoverlapping(
(self as *const Self).cast::<u8>(),
(&mut tmp as *mut Self).cast::<u8>(),
Self::SIZE_BYTES,
);
tmp
}
}
@ -159,7 +163,10 @@ impl<const BUCKETS: usize, const ITEM_BYTES: usize, const HASHES: usize> IBLT<BU
/// Subtract another IBLT from this one to get a set difference.
pub fn subtract(&mut self, other: &Self) {
self.check_hash.iter_mut().zip(other.check_hash.iter()).for_each(|(a, b)| *a ^= *b);
self.count.iter_mut().zip(other.count.iter()).for_each(|(a, b)| *a = a.wrapping_sub(*b));
self.count
.iter_mut()
.zip(other.count.iter())
.for_each(|(a, b)| *a = a.wrapping_sub(*b));
self.key.iter_mut().zip(other.key.iter()).for_each(|(a, b)| xor_with(a, b));
}
@ -310,7 +317,14 @@ mod tests {
assert!(d);
});
println!("inserted: {}\tlisted: {}\tcapacity: {}\tscore: {:.4}\tfill: {:.4}", count, list_count, CAPACITY, (list_count as f64) / (count as f64), (count as f64) / (CAPACITY as f64));
println!(
"inserted: {}\tlisted: {}\tcapacity: {}\tscore: {:.4}\tfill: {:.4}",
count,
list_count,
CAPACITY,
(list_count as f64) / (count as f64),
(count as f64) / (CAPACITY as f64)
);
count += 32;
}
}
@ -358,7 +372,17 @@ mod tests {
cnt += 1;
});
println!("total: {} missing: {:5} recovered: {:5} size: {:5} score: {:.4} bytes/item: {:.2} extract(fill): {:.4} 100%: {}", REMOTE_SIZE, missing.len(), cnt, bytes, (cnt as f64) / (missing.len() as f64), (bytes as f64) / (cnt as f64), (cnt as f64) / (CAPACITY as f64), all_success);
println!(
"total: {} missing: {:5} recovered: {:5} size: {:5} score: {:.4} bytes/item: {:.2} extract(fill): {:.4} 100%: {}",
REMOTE_SIZE,
missing.len(),
cnt,
bytes,
(cnt as f64) / (missing.len() as f64),
(bytes as f64) / (cnt as f64),
(cnt as f64) / (CAPACITY as f64),
all_success
);
missing_count += STEP;
}

View file

@ -84,10 +84,22 @@ pub trait DataStore: Sync + Send {
/// Iterate through keys in a range.
///
/// Keys MUST be output in ascending binary sort order.
async fn keys<F: Send + FnMut(&[u8]) -> bool>(&self, subset: Option<&[u8]>, range_start: &[u8; KEY_SIZE], range_end: &[u8; KEY_SIZE], f: F);
async fn keys<F: Send + FnMut(&[u8]) -> bool>(
&self,
subset: Option<&[u8]>,
range_start: &[u8; KEY_SIZE],
range_end: &[u8; KEY_SIZE],
f: F,
);
/// Iterate through values in a range.
///
/// Entries MUST be output in ascending binary sort order.
async fn values<F: Send + FnMut(&[u8], &[u8]) -> bool>(&self, subset: Option<&[u8]>, range_start: &[u8; KEY_SIZE], range_end: &[u8; KEY_SIZE], f: F);
async fn values<F: Send + FnMut(&[u8], &[u8]) -> bool>(
&self,
subset: Option<&[u8]>,
range_start: &[u8; KEY_SIZE],
range_end: &[u8; KEY_SIZE],
f: F,
);
}

View file

@ -140,8 +140,15 @@ impl DataStore for TestNodeHost {
}
fn main() {
tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(async {
println!("Running syncwhole local self-test network with {} nodes starting at 127.0.0.1:{}", TEST_NODE_COUNT, TEST_PORT_RANGE_START);
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(async {
println!(
"Running syncwhole local self-test network with {} nodes starting at 127.0.0.1:{}",
TEST_NODE_COUNT, TEST_PORT_RANGE_START
);
println!();
println!("Starting nodes on 127.0.0.1...");
@ -158,7 +165,11 @@ fn main() {
th.config.name = port.to_string();
let nh = Arc::new(th);
//println!("Starting node on 127.0.0.1:{}...", port, nh.db.lock().unwrap().len());
nodes.push(Node::new(nh.clone(), nh.clone(), SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, port))).await.unwrap());
nodes.push(
Node::new(nh.clone(), nh.clone(), SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, port)))
.await
.unwrap(),
);
}
print!("Waiting for all connections to be established...");

View file

@ -75,7 +75,11 @@ pub struct Node<D: DataStore + 'static, H: Host + 'static> {
impl<D: DataStore + 'static, H: Host + 'static> Node<D, H> {
pub async fn new(db: Arc<D>, host: Arc<H>, bind_address: SocketAddr) -> std::io::Result<Self> {
let listener = if bind_address.is_ipv4() { TcpSocket::new_v4() } else { TcpSocket::new_v6() }?;
let listener = if bind_address.is_ipv4() {
TcpSocket::new_v4()
} else {
TcpSocket::new_v6()
}?;
configure_tcp_socket(&listener)?;
listener.bind(bind_address.clone())?;
let listener = listener.listen(1024)?;
@ -119,7 +123,12 @@ impl<D: DataStore + 'static, H: Host + 'static> Node<D, H> {
/// to the endpoint. An error is returned if the connection fails.
pub async fn connect(&self, address: &SocketAddr) -> std::io::Result<bool> {
if self.internal.connecting_to.lock().await.insert(address.clone()) {
self.internal.connect(address, Instant::now().add(Duration::from_millis(self.internal.host.node_config().connection_timeout))).await
self.internal
.connect(
address,
Instant::now().add(Duration::from_millis(self.internal.host.node_config().connection_timeout)),
)
.await
} else {
Ok(false)
}
@ -161,7 +170,12 @@ fn configure_tcp_socket(socket: &TcpSocket) -> std::io::Result<()> {
}
fn decode_msgpack<'a, T: Deserialize<'a>>(b: &'a [u8]) -> std::io::Result<T> {
rmp_serde::from_slice(b).map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, format!("invalid msgpack object: {}", e.to_string())))
rmp_serde::from_slice(b).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("invalid msgpack object: {}", e.to_string()),
)
})
}
pub struct NodeInternal<D: DataStore + 'static, H: Host + 'static> {
@ -228,7 +242,10 @@ impl<D: DataStore + 'static, H: Host + 'static> NodeInternal<D, H> {
let e = j.unwrap().await;
if e.is_ok() {
let e = e.unwrap();
host.on_connection_closed(&*cc.info.lock().unwrap(), e.map_or_else(|e| e.to_string(), |_| "unknown error".to_string()));
host.on_connection_closed(
&*cc.info.lock().unwrap(),
e.map_or_else(|e| e.to_string(), |_| "unknown error".to_string()),
);
} else {
host.on_connection_closed(&*cc.info.lock().unwrap(), "remote host closed connection".to_string());
}
@ -299,7 +316,10 @@ impl<D: DataStore + 'static, H: Host + 'static> NodeInternal<D, H> {
background_tasks.spawn(async move {
// If the connection dies this will either fail or time out in 1s. Usually these execute instantly due to
// write buffering but a short timeout prevents them from building up too much.
let _ = tokio::time::timeout(announce_timeout, c2.send_msg(MessageType::HaveRecords, have_records.as_slice(), now));
let _ = tokio::time::timeout(
announce_timeout,
c2.send_msg(MessageType::HaveRecords, have_records.as_slice(), now),
);
});
have_records = Vec::with_capacity(have_records_est_size);
}
@ -332,7 +352,11 @@ impl<D: DataStore + 'static, H: Host + 'static> NodeInternal<D, H> {
/// either succeeds or fails.
async fn connect(self: &Arc<Self>, address: &SocketAddr, deadline: Instant) -> std::io::Result<bool> {
let f = async {
let stream = if address.is_ipv4() { TcpSocket::new_v4() } else { TcpSocket::new_v6() }?;
let stream = if address.is_ipv4() {
TcpSocket::new_v4()
} else {
TcpSocket::new_v6()
}?;
configure_tcp_socket(&stream)?;
stream.bind(self.bind_address.clone())?;
@ -389,7 +413,12 @@ impl<D: DataStore + 'static, H: Host + 'static> NodeInternal<D, H> {
ok
}
async fn connection_io_task_main(self: Arc<Self>, connection: &Arc<Connection>, remote_address: SocketAddr, mut reader: OwnedReadHalf) -> std::io::Result<()> {
async fn connection_io_task_main(
self: Arc<Self>,
connection: &Arc<Connection>,
remote_address: SocketAddr,
mut reader: OwnedReadHalf,
) -> std::io::Result<()> {
const BUF_CHUNK_SIZE: usize = 4096;
const READ_BUF_INITIAL_SIZE: usize = 65536; // should be a multiple of BUF_CHUNK_SIZE
@ -479,20 +508,29 @@ impl<D: DataStore + 'static, H: Host + 'static> NodeInternal<D, H> {
info.name = msg.node_name.to_string();
info.contact = msg.node_contact.to_string();
let _ = msg.explicit_ipv4.map(|pv4| {
info.explicit_addresses.push(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(pv4.ip), pv4.port)));
info.explicit_addresses
.push(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(pv4.ip), pv4.port)));
});
let _ = msg.explicit_ipv6.map(|pv6| {
info.explicit_addresses.push(SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(pv6.ip), pv6.port, 0, 0)));
info.explicit_addresses
.push(SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(pv6.ip), pv6.port, 0, 0)));
});
let info = info.clone();
let auth_challenge_response = self.host.authenticate(&info, msg.auth_challenge);
if auth_challenge_response.is_none() {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "authenticate() returned None, connection dropped"));
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"authenticate() returned None, connection dropped",
));
}
let auth_challenge_response = auth_challenge_response.unwrap();
(H::hmac_sha512(&self.anti_loopback_secret, msg.anti_loopback_challenge), H::hmac_sha512(&H::sha512(&[self.host.node_config().domain.as_bytes()]), msg.domain_challenge), auth_challenge_response)
(
H::hmac_sha512(&self.anti_loopback_secret, msg.anti_loopback_challenge),
H::hmac_sha512(&H::sha512(&[self.host.node_config().domain.as_bytes()]), msg.domain_challenge),
auth_challenge_response,
)
};
connection
@ -517,14 +555,27 @@ impl<D: DataStore + 'static, H: Host + 'static> NodeInternal<D, H> {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "duplicate init response"));
}
if msg.anti_loopback_response.eq(&H::hmac_sha512(&self.anti_loopback_secret, &anti_loopback_challenge_sent)) {
if msg
.anti_loopback_response
.eq(&H::hmac_sha512(&self.anti_loopback_secret, &anti_loopback_challenge_sent))
{
return Err(std::io::Error::new(std::io::ErrorKind::Other, "rejected connection to self"));
}
if !msg.domain_response.eq(&H::hmac_sha512(&H::sha512(&[self.host.node_config().domain.as_bytes()]), &domain_challenge_sent)) {
if !msg.domain_response.eq(&H::hmac_sha512(
&H::sha512(&[self.host.node_config().domain.as_bytes()]),
&domain_challenge_sent,
)) {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "domain mismatch"));
}
if !self.host.authenticate(&info, &auth_challenge_sent).map_or(false, |cr| msg.auth_response.eq(&cr)) {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "challenge/response authentication failed"));
if !self
.host
.authenticate(&info, &auth_challenge_sent)
.map_or(false, |cr| msg.auth_response.eq(&cr))
{
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"challenge/response authentication failed",
));
}
initialized = true;
@ -537,7 +588,10 @@ impl<D: DataStore + 'static, H: Host + 'static> NodeInternal<D, H> {
// Handle messages other than INIT and INIT_RESPONSE after checking 'initialized' flag.
_ => {
if !initialized {
return Err(std::io::Error::new(std::io::ErrorKind::Other, "init exchange must be completed before other messages are sent"));
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
"init exchange must be completed before other messages are sent",
));
}
match message_type {
@ -556,7 +610,10 @@ impl<D: DataStore + 'static, H: Host + 'static> NodeInternal<D, H> {
}
}
StoreResult::Rejected => {
return Err(std::io::Error::new(std::io::ErrorKind::Other, format!("record rejected by data store: {}", to_hex_string(&key))));
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("record rejected by data store: {}", to_hex_string(&key)),
));
}
_ => {}
}
@ -615,7 +672,14 @@ impl Connection {
let mut header: [u8; 16] = unsafe { MaybeUninit::uninit().assume_init() };
header[0] = message_type as u8;
let header_size = 1 + varint::encode(&mut header[1..], data.len() as u64);
if self.writer.lock().await.write_vectored(&[IoSlice::new(&header[0..header_size]), IoSlice::new(data)]).await? == (data.len() + header_size) {
if self
.writer
.lock()
.await
.write_vectored(&[IoSlice::new(&header[0..header_size]), IoSlice::new(data)])
.await?
== (data.len() + header_size)
{
self.last_send_time.store(now, Ordering::Relaxed);
Ok(())
} else {
@ -628,7 +692,10 @@ impl Connection {
if rmp_serde::encode::write_named(write_buf, obj).is_ok() {
self.send_msg(message_type, write_buf.as_slice(), now).await
} else {
Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "serialize failure (internal error)"))
Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"serialize failure (internal error)",
))
}
}
}

View file

@ -16,12 +16,17 @@ use tokio::task::JoinHandle;
/// Get the real time clock in milliseconds since Unix epoch.
pub fn ms_since_epoch() -> i64 {
std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis() as i64
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis() as i64
}
/// Encode a byte slice to a hexadecimal string.
pub fn to_hex_string(b: &[u8]) -> String {
const HEX_CHARS: [u8; 16] = [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f'];
const HEX_CHARS: [u8; 16] = [
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f',
];
let mut s = String::new();
s.reserve(b.len() * 2);
for c in b {

View file

@ -19,7 +19,9 @@ pub fn criterion_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("cryptography");
group.measurement_time(Duration::new(10, 0));
group.bench_function("ecdhp384", |b| b.iter(|| p384_a.agree(p384_b.public_key()).expect("ecdhp384 failed")));
group.bench_function("ecdhp384", |b| {
b.iter(|| p384_a.agree(p384_b.public_key()).expect("ecdhp384 failed"))
});
group.bench_function("ecdhx25519", |b| b.iter(|| x25519_a.agree(&x25519_b_pub)));
group.bench_function("kyber_encapsulate", |b| {
b.iter(|| pqc_kyber::encapsulate(&kyber_a.public, &mut random::SecureRandom::default()).expect("kyber encapsulate failed"))

View file

@ -36,7 +36,14 @@ mod fruit_flavored {
options: i32,
cryyptor_ref: *mut *mut c_void,
) -> i32;
fn CCCryptorUpdate(cryptor_ref: *mut c_void, data_in: *const c_void, data_in_len: usize, data_out: *mut c_void, data_out_len: usize, data_out_written: *mut usize) -> i32;
fn CCCryptorUpdate(
cryptor_ref: *mut c_void,
data_in: *const c_void,
data_in_len: usize,
data_out: *mut c_void,
data_out_len: usize,
data_out_written: *mut usize,
) -> i32;
//fn CCCryptorReset(cryptor_ref: *mut c_void, iv: *const c_void) -> i32;
fn CCCryptorRelease(cryptor_ref: *mut c_void) -> i32;
fn CCCryptorGCMSetIV(cryptor_ref: *mut c_void, iv: *const c_void, iv_len: usize) -> i32;
@ -110,7 +117,14 @@ mod fruit_flavored {
assert_eq!(ciphertext.len(), 16);
unsafe {
let mut data_out_written = 0;
CCCryptorUpdate(self.0, plaintext.as_ptr().cast(), 16, ciphertext.as_mut_ptr().cast(), 16, &mut data_out_written);
CCCryptorUpdate(
self.0,
plaintext.as_ptr().cast(),
16,
ciphertext.as_mut_ptr().cast(),
16,
&mut data_out_written,
);
}
}
@ -119,7 +133,14 @@ mod fruit_flavored {
assert_eq!(data.len(), 16);
unsafe {
let mut data_out_written = 0;
CCCryptorUpdate(self.0, data.as_ptr().cast(), 16, data.as_mut_ptr().cast(), 16, &mut data_out_written);
CCCryptorUpdate(
self.0,
data.as_ptr().cast(),
16,
data.as_mut_ptr().cast(),
16,
&mut data_out_written,
);
}
}
@ -129,7 +150,14 @@ mod fruit_flavored {
assert_eq!(ciphertext.len(), 16);
unsafe {
let mut data_out_written = 0;
CCCryptorUpdate(self.1, ciphertext.as_ptr().cast(), 16, plaintext.as_mut_ptr().cast(), 16, &mut data_out_written);
CCCryptorUpdate(
self.1,
ciphertext.as_ptr().cast(),
16,
plaintext.as_mut_ptr().cast(),
16,
&mut data_out_written,
);
}
}
@ -138,7 +166,14 @@ mod fruit_flavored {
assert_eq!(data.len(), 16);
unsafe {
let mut data_out_written = 0;
CCCryptorUpdate(self.1, data.as_ptr().cast(), 16, data.as_mut_ptr().cast(), 16, &mut data_out_written);
CCCryptorUpdate(
self.1,
data.as_ptr().cast(),
16,
data.as_mut_ptr().cast(),
16,
&mut data_out_written,
);
}
}
}
@ -215,9 +250,15 @@ mod fruit_flavored {
unsafe {
assert_eq!(input.len(), output.len());
if self.1 {
assert_eq!(CCCryptorGCMEncrypt(self.0, input.as_ptr().cast(), input.len(), output.as_mut_ptr().cast()), 0);
assert_eq!(
CCCryptorGCMEncrypt(self.0, input.as_ptr().cast(), input.len(), output.as_mut_ptr().cast()),
0
);
} else {
assert_eq!(CCCryptorGCMDecrypt(self.0, input.as_ptr().cast(), input.len(), output.as_mut_ptr().cast()), 0);
assert_eq!(
CCCryptorGCMDecrypt(self.0, input.as_ptr().cast(), input.len(), output.as_mut_ptr().cast()),
0
);
}
}
}
@ -226,9 +267,15 @@ mod fruit_flavored {
pub fn crypt_in_place(&mut self, data: &mut [u8]) {
unsafe {
if self.1 {
assert_eq!(CCCryptorGCMEncrypt(self.0, data.as_ptr().cast(), data.len(), data.as_mut_ptr().cast()), 0);
assert_eq!(
CCCryptorGCMEncrypt(self.0, data.as_ptr().cast(), data.len(), data.as_mut_ptr().cast()),
0
);
} else {
assert_eq!(CCCryptorGCMDecrypt(self.0, data.as_ptr().cast(), data.len(), data.as_mut_ptr().cast()), 0);
assert_eq!(
CCCryptorGCMDecrypt(self.0, data.as_ptr().cast(), data.len(), data.as_mut_ptr().cast()),
0
);
}
}
}
@ -392,7 +439,12 @@ mod openssl_aes {
/// Encrypt or decrypt in place (same operation with CTR mode)
#[inline(always)]
pub fn crypt_in_place(&mut self, data: &mut [u8]) {
assert!(self.2.as_mut().unwrap().update(unsafe { &*std::slice::from_raw_parts(data.as_ptr(), data.len()) }, data).is_ok());
assert!(self
.2
.as_mut()
.unwrap()
.update(unsafe { &*std::slice::from_raw_parts(data.as_ptr(), data.len()) }, data)
.is_ok());
}
#[inline(always)]

View file

@ -35,7 +35,14 @@ extern "C" {
options: i32,
cryyptor_ref: *mut *mut c_void,
) -> i32;
fn CCCryptorUpdate(cryptor_ref: *mut c_void, data_in: *const c_void, data_in_len: usize, data_out: *mut c_void, data_out_len: usize, data_out_written: *mut usize) -> i32;
fn CCCryptorUpdate(
cryptor_ref: *mut c_void,
data_in: *const c_void,
data_in_len: usize,
data_out: *mut c_void,
data_out_len: usize,
data_out_written: *mut usize,
) -> i32;
fn CCCryptorReset(cryptor_ref: *mut c_void, iv: *const c_void) -> i32;
fn CCCryptorRelease(cryptor_ref: *mut c_void) -> i32;
fn CCCryptorGCMSetIV(cryptor_ref: *mut c_void, iv: *const c_void, iv_len: usize) -> i32;
@ -65,7 +72,20 @@ impl AesCtr {
}
unsafe {
let mut ptr: *mut c_void = null_mut();
let result = CCCryptorCreateWithMode(kCCEncrypt, kCCModeCTR, kCCAlgorithmAES, 0, crate::ZEROES.as_ptr().cast(), k.as_ptr().cast(), k.len(), null(), 0, 0, 0, &mut ptr);
let result = CCCryptorCreateWithMode(
kCCEncrypt,
kCCModeCTR,
kCCAlgorithmAES,
0,
crate::ZEROES.as_ptr().cast(),
k.as_ptr().cast(),
k.len(),
null(),
0,
0,
0,
&mut ptr,
);
if result != 0 {
panic!("CCCryptorCreateWithMode for CTR mode returned {}", result);
}
@ -99,7 +119,14 @@ impl AesCtr {
unsafe {
assert!(output.len() >= input.len());
let mut data_out_written: usize = 0;
CCCryptorUpdate(self.0, input.as_ptr().cast(), input.len(), output.as_mut_ptr().cast(), output.len(), &mut data_out_written);
CCCryptorUpdate(
self.0,
input.as_ptr().cast(),
input.len(),
output.as_mut_ptr().cast(),
output.len(),
&mut data_out_written,
);
}
}
@ -108,7 +135,14 @@ impl AesCtr {
pub fn crypt_in_place(&mut self, data: &mut [u8]) {
unsafe {
let mut data_out_written: usize = 0;
CCCryptorUpdate(self.0, data.as_ptr().cast(), data.len(), data.as_mut_ptr().cast(), data.len(), &mut data_out_written);
CCCryptorUpdate(
self.0,
data.as_ptr().cast(),
data.len(),
data.as_mut_ptr().cast(),
data.len(),
&mut data_out_written,
);
}
}
}
@ -164,8 +198,20 @@ impl AesGmacSiv {
gmac: null_mut(),
};
unsafe {
let result =
CCCryptorCreateWithMode(kCCEncrypt, kCCModeCTR, kCCAlgorithmAES, 0, crate::ZEROES.as_ptr().cast(), k1.as_ptr().cast(), k1.len(), null(), 0, 0, 0, &mut c.ctr);
let result = CCCryptorCreateWithMode(
kCCEncrypt,
kCCModeCTR,
kCCAlgorithmAES,
0,
crate::ZEROES.as_ptr().cast(),
k1.as_ptr().cast(),
k1.len(),
null(),
0,
0,
0,
&mut c.ctr,
);
if result != 0 {
panic!("CCCryptorCreateWithMode for CTR mode returned {}", result);
}
@ -203,8 +249,20 @@ impl AesGmacSiv {
if result != 0 {
panic!("CCCryptorCreateWithMode for ECB decrypt mode returned {}", result);
}
let result =
CCCryptorCreateWithMode(kCCEncrypt, kCCModeGCM, kCCAlgorithmAES, 0, crate::ZEROES.as_ptr().cast(), k0.as_ptr().cast(), k0.len(), null(), 0, 0, 0, &mut c.gmac);
let result = CCCryptorCreateWithMode(
kCCEncrypt,
kCCModeGCM,
kCCAlgorithmAES,
0,
crate::ZEROES.as_ptr().cast(),
k0.as_ptr().cast(),
k0.len(),
null(),
0,
0,
0,
&mut c.gmac,
);
if result != 0 {
panic!("CCCryptorCreateWithMode for GCM (GMAC) mode returned {}", result);
}
@ -262,7 +320,14 @@ impl AesGmacSiv {
let tmp = self.tmp.as_mut_ptr().cast::<u64>();
*self.tag.as_mut_ptr().cast::<u64>().offset(1) = *tmp ^ *tmp.offset(1);
let mut data_out_written: usize = 0;
CCCryptorUpdate(self.ecb_enc, self.tag.as_ptr().cast(), 16, self.tag.as_mut_ptr().cast(), 16, &mut data_out_written);
CCCryptorUpdate(
self.ecb_enc,
self.tag.as_ptr().cast(),
16,
self.tag.as_mut_ptr().cast(),
16,
&mut data_out_written,
);
}
self.tmp.copy_from_slice(&self.tag);
self.tmp[12] &= 0x7f;
@ -280,7 +345,14 @@ impl AesGmacSiv {
unsafe {
assert!(ciphertext.len() >= plaintext.len());
let mut data_out_written: usize = 0;
CCCryptorUpdate(self.ctr, plaintext.as_ptr().cast(), plaintext.len(), ciphertext.as_mut_ptr().cast(), ciphertext.len(), &mut data_out_written);
CCCryptorUpdate(
self.ctr,
plaintext.as_ptr().cast(),
plaintext.len(),
ciphertext.as_mut_ptr().cast(),
ciphertext.len(),
&mut data_out_written,
);
}
}
@ -316,7 +388,14 @@ impl AesGmacSiv {
panic!("CCCryptorReset for CTR mode failed (old MacOS bug)");
}
let mut data_out_written = 0;
CCCryptorUpdate(self.ecb_dec, self.tag.as_ptr().cast(), 16, self.tag.as_mut_ptr().cast(), 16, &mut data_out_written);
CCCryptorUpdate(
self.ecb_dec,
self.tag.as_ptr().cast(),
16,
self.tag.as_mut_ptr().cast(),
16,
&mut data_out_written,
);
let tmp = self.tmp.as_mut_ptr().cast::<u64>();
*tmp = *self.tag.as_mut_ptr().cast::<u64>();
*tmp.add(1) = 0;
@ -345,7 +424,14 @@ impl AesGmacSiv {
pub fn decrypt(&mut self, ciphertext: &[u8], plaintext: &mut [u8]) {
unsafe {
let mut data_out_written = 0;
CCCryptorUpdate(self.ctr, ciphertext.as_ptr().cast(), ciphertext.len(), plaintext.as_mut_ptr().cast(), plaintext.len(), &mut data_out_written);
CCCryptorUpdate(
self.ctr,
ciphertext.as_ptr().cast(),
ciphertext.len(),
plaintext.as_mut_ptr().cast(),
plaintext.len(),
&mut data_out_written,
);
CCCryptorGCMAddAAD(self.gmac, plaintext.as_ptr().cast(), plaintext.len());
}
}

View file

@ -56,7 +56,9 @@ impl AesCtr {
/// If it's already been used, this also resets the cipher. There is no separate reset.
#[inline(always)]
pub fn init(&mut self, iv: &[u8]) {
let _ = self.1.replace(Crypter::new(aes_ctr_by_key_size(self.0.len()), Mode::Encrypt, self.0.as_slice(), Some(iv)).unwrap());
let _ = self
.1
.replace(Crypter::new(aes_ctr_by_key_size(self.0.len()), Mode::Encrypt, self.0.as_slice(), Some(iv)).unwrap());
}
/// Encrypt or decrypt (same operation with CTR mode)
@ -68,7 +70,11 @@ impl AesCtr {
/// Encrypt or decrypt in place (same operation with CTR mode)
#[inline(always)]
pub fn crypt_in_place(&mut self, data: &mut [u8]) {
let _ = self.1.as_mut().unwrap().update(unsafe { &*std::slice::from_raw_parts(data.as_ptr(), data.len()) }, data);
let _ = self
.1
.as_mut()
.unwrap()
.update(unsafe { &*std::slice::from_raw_parts(data.as_ptr(), data.len()) }, data);
}
}
@ -116,7 +122,15 @@ impl AesGmacSiv {
pub fn encrypt_init(&mut self, iv: &[u8]) {
self.tag[0..8].copy_from_slice(iv);
self.tag[8..12].fill(0);
let _ = self.gmac.replace(Crypter::new(aes_gcm_by_key_size(self.k0.len()), Mode::Encrypt, self.k0.as_slice(), Some(&self.tag[0..12])).unwrap());
let _ = self.gmac.replace(
Crypter::new(
aes_gcm_by_key_size(self.k0.len()),
Mode::Encrypt,
self.k0.as_slice(),
Some(&self.tag[0..12]),
)
.unwrap(),
);
}
/// Set additional authenticated data (data to be authenticated but not encrypted).
@ -164,7 +178,15 @@ impl AesGmacSiv {
self.tmp.copy_from_slice(&tag_tmp[0..16]);
self.tmp[12] &= 0x7f;
let _ = self.ctr.replace(Crypter::new(aes_ctr_by_key_size(self.k1.len()), Mode::Encrypt, self.k1.as_slice(), Some(&self.tmp)).unwrap());
let _ = self.ctr.replace(
Crypter::new(
aes_ctr_by_key_size(self.k1.len()),
Mode::Encrypt,
self.k1.as_slice(),
Some(&self.tmp),
)
.unwrap(),
);
}
/// Feed plaintext for second pass and write ciphertext to supplied buffer.
@ -178,7 +200,10 @@ impl AesGmacSiv {
/// This may be called more than once.
#[inline(always)]
pub fn encrypt_second_pass_in_place(&mut self, plaintext_to_ciphertext: &mut [u8]) {
let _ = self.ctr.as_mut().unwrap().update(unsafe { std::slice::from_raw_parts(plaintext_to_ciphertext.as_ptr(), plaintext_to_ciphertext.len()) }, plaintext_to_ciphertext);
let _ = self.ctr.as_mut().unwrap().update(
unsafe { std::slice::from_raw_parts(plaintext_to_ciphertext.as_ptr(), plaintext_to_ciphertext.len()) },
plaintext_to_ciphertext,
);
}
/// Finish second pass and return a reference to the tag for this message.
@ -194,7 +219,15 @@ impl AesGmacSiv {
pub fn decrypt_init(&mut self, tag: &[u8]) {
self.tmp.copy_from_slice(tag);
self.tmp[12] &= 0x7f;
let _ = self.ctr.replace(Crypter::new(aes_ctr_by_key_size(self.k1.len()), Mode::Decrypt, self.k1.as_slice(), Some(&self.tmp)).unwrap());
let _ = self.ctr.replace(
Crypter::new(
aes_ctr_by_key_size(self.k1.len()),
Mode::Decrypt,
self.k1.as_slice(),
Some(&self.tmp),
)
.unwrap(),
);
let mut tag_tmp = [0_u8; 32];
let mut ecb = Crypter::new(aes_ecb_by_key_size(self.k1.len()), Mode::Decrypt, self.k1.as_slice(), None).unwrap();
@ -204,7 +237,15 @@ impl AesGmacSiv {
}
self.tag.copy_from_slice(&tag_tmp[0..16]);
tag_tmp[8..12].fill(0);
let _ = self.gmac.replace(Crypter::new(aes_gcm_by_key_size(self.k0.len()), Mode::Encrypt, self.k0.as_slice(), Some(&tag_tmp[0..12])).unwrap());
let _ = self.gmac.replace(
Crypter::new(
aes_gcm_by_key_size(self.k0.len()),
Mode::Encrypt,
self.k0.as_slice(),
Some(&tag_tmp[0..12]),
)
.unwrap(),
);
}
/// Set additional authenticated data to be checked.
@ -225,7 +266,10 @@ impl AesGmacSiv {
/// This may be called more than once.
#[inline(always)]
pub fn decrypt_in_place(&mut self, ciphertext_to_plaintext: &mut [u8]) {
self.decrypt(unsafe { std::slice::from_raw_parts(ciphertext_to_plaintext.as_ptr(), ciphertext_to_plaintext.len()) }, ciphertext_to_plaintext);
self.decrypt(
unsafe { std::slice::from_raw_parts(ciphertext_to_plaintext.as_ptr(), ciphertext_to_plaintext.len()) },
ciphertext_to_plaintext,
);
}
/// Finish decryption and return true if authentication appears valid.

View file

@ -20,98 +20,441 @@ mod tests {
use sha2::Digest;
use std::time::SystemTime;
const TV0_KEYS: [&'static [u8]; 2] = ["00000000000000000000000000000000".as_bytes(), "11111111111111111111111111111111".as_bytes()];
const TV0_KEYS: [&'static [u8]; 2] = [
"00000000000000000000000000000000".as_bytes(),
"11111111111111111111111111111111".as_bytes(),
];
/// Test vectors consist of a series of input sizes, a SHA384 hash of a resulting ciphertext, and an expected tag.
/// Input is a standard byte array consisting of bytes 0, 1, 2, 3, ..., 255 and then cycling back to 0 over and over
/// and is provided both as ciphertext and associated data (AAD).
#[allow(unused)]
const TEST_VECTORS: [(usize, &'static str, &'static str); 85] = [
(0, "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", "43847e644239134deccf5538162c861e"),
(777, "aabf892f18a620b9c3bae91bb03a74c84193e4a7b64916c6bc88b885b9ebed4134495e5f22f12e3046fbb3f26fa111a7", "b8c318b5dcc1d672114a6f7be54ef289"),
(1554, "648f551df29217f0e634b72ba6973c0eb95c7d4be8b135e550d8bcdf65b75980881bc0e03cf22589e04bedc7da1804cd", "535b8ddd51ec82a1e850906fe321b21a"),
(2331, "bfbfdffea40062e23bbdf0835e1d38d1623bebca7407908bbc6d5b3f2bfd062a2d237f091affda7348094fafda0bd1a7", "4f521876fbb2c563051196b33c20c822"),
(3108, "cc6035cab70f3a3298a5c4956ff07f179acf3771bb915c590a8a19fe5133d6d8a81c118148394dfb364af5c2fbdaadeb", "d3adfa578c8bcd738c55ffc527358cef"),
(3885, "15ec2760a21c25f9870a84ee757f3da2c261a950c2f692d75ff9e99b2d50c826c21e27e49c4cd3450fedc7e60371589f", "a4c22d6c3d773634c2dc057e1f7c6738"),
(4662, "c2afad6f034704300c34f143dcdcb86c9b954cec1ebf22e7071f288c58a2ae430d3e3748d214d1021472793d3f337dc6", "c0601cb6cd4883102f70570c2cdc0ab6"),
(5439, "8fee067f5a7a475a630f9db8b2eb80c1edc40eb4246a0f1c078e535df7d06451c6a9bde1a23ba70285690dd7100a8626", "7352239f2302b08844309d28b13fa867"),
(6216, "60095b4172438aee61e65f5379f4ef276c3632d4ac74eea7723a2201823432614aba7b4670d9bf7a5b9126ca38f3b88a", "c0f0b0aa651965f8514b473c5406285e"),
(6993, "10e754dd08b4d2a6c109fb01fce2b57d54743947e14a7e67d7efd0608baf91f7fc42a53328fe8c18d234abad8ebcdff0", "58444988a62a99060728a7637c8499eb"),
(7770, "1abc4a5dcd2696336bd0e8af20fe7fc261aa424b52cfb5ad80ee7c7c793ac44f11db3506cdbbbaed0f80000925d08d52", "e8065c563bc6018cdcbf9aaafef767e6"),
(8547, "26aaf74ae8bfc6aaf45ceee0476ea0a484304f5c36050d3e2265cb194a2f7c308213314232270608b6d3f1c11b834e33", "ec50e4b3f6e4b3de24b3476623d08157"),
(9324, "863206305d466aa9c0d0ec674572069f61fe5009767f99ec8832912725c28c49d6a106ad3f55372c922e4e169fc382ce", "0cfac64f49e0f128d0a18d293878f222"),
(10101, "bd0c0950b947a6c34f1fa6e877433b42c039a8ea7b37634c40fb47efae4958ba74ef0991cfedf3c82a0b87ef59635071", "e0220a02b74259eeebbebede847d50f9"),
(10878, "d7b9901af1dacf6a8c369b993ba1c607f9b7f073d02311c72d8449d3494d477ffc8344a1d8b488020ccfc7c80fbd27e1", "ebe3933146734a6ade2b434f2bcd78ae"),
(11655, "0ba265e3ef0bebf01a4f3490da462c7730aad6aa6c70bb9ce64a36d26d24fe213660e60e4d3301329170471f11ff8ca2", "ec3dd4bf4cb7d527a86dd559c773a87b"),
(12432, "c3b6755a1be922ec71c1e187ead36c4e6fc307c72969c64ca1e9b7339d61e1a93a74a315fd73bed8fa5797b78b19dbe5", "5b58dcf392749bcef91056ba9475d0ef"),
(13209, "2fb1a67151183daa2f0d7f0064534497357f173161349dd008499a8c1a123cc942662ecc426e2ad7743fe0ab9f5d7be1", "c011260d328d310e2ab606aa1ef8afd4"),
(13986, "6afae2a07ce9bfe30fbbfb7dcf32d755bcf357334dc5c309e58cab38ebe559f25b313a0b3ca32ff1dc41f7b99718f653", "011bf43cfbbb7ae5986f8e0fc87771a9"),
(14763, "cc6215c115eb6411f4712c2289f5bf0ccb5151635f9f9ceac7c1b62d8d2f4d26498079d0289f83aeb26e97b5b924ffc4", "a015034a8d5bc83cc76c6983a5ba19ab"),
(15540, "3cebce794e947341c4ceec444ca43c6ac57c6f58de462bfec7566cbd59a1b6f2eae774120e29521e76120a604d1a12d9", "d373cd2bd9000655141ac632880eca40"),
(16317, "899147b98d78bb5d137dc7c4f03be7eca82bcca19cc3a701261332923707aed2e6719d35d2f2bf067cd1d193a53529cf", "ed223b64529299c787f49d631ce181c1"),
(17094, "aecd1830958b994b2c331b90e7d8ff79f27c83a71f5797a65ade3a30b4fa5928e79140bcd03f375591d53df96fea1a4d", "948a7c253d54bb6b65d78530c0eb7aab"),
(17871, "e677ffd4ecaba5899659fefe5fe8e643004392be3be6dc5a801409870ac1e3398f47cc1d83f7a4c41925b6337e01f7fd", "156a600c336f3ac034ca90034aa22635"),
(18648, "4ee50f4a98d0bbd160add6acf76765ccdac0c1cd0bb2adbbcb22dd012a1121620b739a120df7dc4091e684ddf28eb726", "75873467b416a7b025f9f1b015bf653a"),
(19425, "aa025f32c0575af7209828fc7fc4591b41fa7cfb485e26c5401e63ca1fa05776f8b8af1769a15e81f2c663bca9b02ab3", "5679efa7a4404e1e5c9b372782a41bf2"),
(20202, "6e77ab62d2affeb27f4ef326191b3df3863c338a629f64a785505f4a5968ff59bc011c7a27951cb00e2e7d9b9bd32fec", "36a9c4515d34f9bb962d8876ab3b5c86"),
(20979, "1625b4f0e65fc66f11ba3ee6b3e20c732535654c447df6b517ced113107a1057a64477faa2af4a5ede4034bf3cff98ea", "9058044e0f71c28d4f8d3281a3aec024"),
(21756, "94efe6aa55bd77bfa58c185dec313a41003f9bef02568e72c337be4de1b46c6e5bb9a9329b4f108686489b8bc9d5f4f0", "8d6d2c90590268a26f5e7d76351f48c1"),
(22533, "7327a05fdb0ac92433dfc2c85c5e96e6ddcbdb01e079f8dafbee79c14cb4d5fd46047acd6bb0e09a98f6dd03dced2a0a", "4e0f0a394f85bca35c68ef667aa9c244"),
(23310, "93da9e356efbc8b5ae366256f4c6fc11c11fc347aaa879d591b7c1262d90adf98925f571914696054f1d09c74783561e", "8c83c157be439280afc790ee3fd667eb"),
(24087, "99b91be5ffca51b1cbc7410798b1540b5b1a3356f801ed4dc54812919c08ca5a9adc218bc51e594d97b46445a1515506", "9436ff05729a77f673e815e464aeaa75"),
(24864, "074253ad5d5a5d2b072e7aeaffa04a06119ec812a88ca43481fe5e2dce02cf6736952095cd342ec70b833c12fc1777f4", "69d8951b96866a08efbb65f2bc31cfbc"),
(25641, "c0a301f90597c05cf19e60c35378676764086b7156e455f4800347f8a6e733d644e4cc709fb9d95a9211f3e1e10c762a", "3561c9802143c306ecc5e07e3b976d9e"),
(26418, "3c839e59d945b841acb604e1b9ae3df36a291444ce0bcae336ee875beaf208bf10af7342b375429ecb92ec54d11a5907", "3032ffdb8daee11b2e739132c6175615"),
(27195, "3dc59b16603950dfc26a90bf036712eb088412e8de4d1b27c3fa6be6502ac12d89d194764fb53c3dc7d90fa696ba5a16", "49436717edff7cd67c9a1be16d524f07"),
(27972, "4fbc0d40ff13376b8ed5382890cdea337b4a0c9c31b477c4008d2ef8299bd5ab771ba70b1b4b743f8f7caa1f0164d1a1", "64a9856a3bb81dc81ff1bc1025192dc9"),
(28749, "6ab191aa6327f229cc94e8c7b1b7ee30bc723e6aeaf3050eb7d14cb491c3513254e9b19894c2b4f071d298401fd31945", "101f2ffea60f246a3b57c4a530d67cf1"),
(29526, "d06dece58e6c7345986aae4b7f15b3317653f5387d6262f389b5cbbe804568124a876eabb89204e96b3c0f7b552df3c4", "5c0e873adba65a9f4cb24cce4f194b18"),
(30303, "7a33c1268eafdc1f89ad460fa4ded8d3df9a3cabe4339706877878c64a2c8080cf3fa5ea7f2f24744e3341476b1eb5a5", "b7dc708fc46ce5cde24a31ad549fec83"),
(31080, "37bf1f9fca6d705b989b2d63259ca924dc860fc6027e07d9aad79b94841227739774f5d324590df45d8f41249ef742ea", "8ead50308c281e699b79b69dad7ecb91"),
(31857, "91b120c73be86f9d53326fa707cfa1411e5ac76ab998a2d7ebd73a75e3b1a04c9f0855d102184b8a3fd5d99818b0b134", "6056d09595bd16bfa317c6f87ce64bb7"),
(32634, "42cc255c06184ead57b27efd0cefb0f2c788c8962a6fd15db3f25533a7f49700bca85af916f9e985f1941a6e66943b38", "3b15e332d2f53bb97e1a9d03e6113b97"),
(33411, "737f8bb8f3fd03a9d13e50abba3a42f4491c36eda3eb215085abda733227ec490cb863ffbd68f915c8fb2926a899fbc3", "b2c647d25c46aab4d4a5ede4a3b4576d"),
(34188, "e9caa36505e19628175d1ce8b933267380099753a41e503fa2f894cea17b7692f0b27079ed33cdd1293db9a35722d561", "a2882adfd00f22823250215b12b3a1fd"),
(34965, "81ddc348ebbdfb963daa5d0c1b51bbb73cacd883d4fc4316db6bd3388779beff7be0655bbac73951f89dc53832199c11", "f33106eb8104f3780350c6d4f82333ad"),
(35742, "308ce31daf40dab707e2cb4c4a5307bc403e24c971ae1e30e998449f804a167fe5f2cf617d585851b6fe9f2b4209f09c", "44070ac90cbf350ab92289cc063e978c"),
(36519, "71f51b4bddbe8a52f18be75f9bdb3fca0773901b794de845450fb308c34775ede1a6da9a82b61e9682a29a3ef71274e2", "0e387704298c444bf3afba0edc0c1c1c"),
(37296, "478ac94eee8c5f96210003fcb478392b91f2ef6fc3a729774e5fe82a2d8d0abc54ae1d25b3eaefb061e2bd43b70ca4ea", "fb65ebeda52cd5848d303c0677cecb7f"),
(38073, "bc3a9390618da7d644be932627353e2c92024df939d2d8497fba61fae3dd822cdd3e130c1707f4a9d5d4a0cbb4b3e0b3", "d790d529a837ec79f7cc3f66ed9a399f"),
(38850, "ef0e63a53a10e56477c47e13320b8a7d330aee3a4363c850edc56c0707a2686478e5a5193f54ceb33467ab7e8a22aa21", "6f2c18742f106f16fc290767342fb62b"),
(39627, "c16f63533c099d872d9a01c326db7756e7eb488c756b9a6ebf575993d8ea2eb45c572b2e162f061e145710e0e21e8e18", "a57afde7938b223ae5e109a03db4ee4c"),
(40404, "ade484ae8c13465a73589ef14789bb6891c933453e198df84edd34b4ac5c83aa90f2cf61fa072fa4d8f5b5c4cd68fa9e", "a01d13009db86ac442f7afd39d83309f"),
(41181, "6c5c7eed0e043a0bd60bcac9b5b546e150028d70c1efefc9ff69037ef4dc1a36878b171b9f2a639df822d11054a0e405", "6321c8622ca5866c875d340206d06a28"),
(41958, "dd311c54222fb0d92858719cf5b1c51bb5e3ca2539ffd68f1dd6c7e38969495be935804855ccdcc4b4cf221fcdbda886", "cf401eb819b5dc5cd8c909aae9b3b34b"),
(42735, "31cda9d663199b32eff042dd16c0b909ba999641e77ba751c91752bfc4d595e17ec6467119e74a600b72da72ba287d0a", "12fd6298ab5d744eb6ade3106565afad"),
(43512, "11b014057d51a8384d549d5d083c4406b575df6a9295853dd8f2f84f078cc241bb90495a119126b10b9510efcb68c0d3", "a48a49eea5dc90359ef21f32132f8604"),
(44289, "b44f5dbeecd76ee7efe3fb4dfe10ba8135d7a5e4d104149f4a91c5c6ee9446d9be19fb4c9ba668b074466d3892e22228", "07e1cbb7a19174d9b1e4d5a2c741cc14"),
(45066, "d87bbba3a3c739cab622386c89aeb685a70009fab1a606bd34622adfa3a75a05b58d56ee6b9874d414db38a6a32927b3", "a27cd252712cd2a1a2d95dea39f888d4"),
(45843, "abb90e60ea13c6cb3b401b8e271637416b87fbede165dde7be1d34abe4427dae4b39b499352cacac909bc43fb94028c8", "df3ae762b9257936feda435a61a9c3a1"),
(46620, "56d1132ee6e0f85543950d2d9667244b66b0ce6414eacd1859b128ed0b9026b31a25bfdcce3d1a0ce7c39d99f609c89c", "cfe7c3c3f1cb615e2d210cc8136443e6"),
(47397, "ecb023ec4c23cf95d1848a38b359f1f590f172dee9d8fb1be6bc9c4fb2ce96f612d60d7b111de539ab8313a87b821176", "501d24752bf55cb12239863981898a07"),
(48174, "34236ab60f05bb510aa0880fec358fb2002903efa14c912cab8a399e09418f97223ca2f7b8d6798c11d39e79032eaaa8", "4ecaba4eae886aa429927188abab9623"),
(48951, "55e8b40fad90a3d8c85a0f4d5bcf5975b8a6e2fb78377109f5b607a5e367187fbbc9a1e978aab3228fbf43ad23d0ad13", "84c43bc30eb4a67230b6c634fe3c7782"),
(49728, "14b1f896d0d01ecff4e456c3c392b1ca2bad9f1ef07713f84cdd89e663aa27ca77d80213ed57a89431eb992b11d98749", "7f58c2f9a249f70fe1c6f9b4f65e5a1d"),
(50505, "1335b1fb56196e0b371fa53ab7445845fdefcea3eb2833478deb3526e2ec888945e95ee8239b52caae5b9920ba4f43bb", "5fd729126b236ce3e0686fc706dce20f"),
(51282, "0d1983a6cab870c5e78f89a11dd30e7d2c71a3882f8bba3e71dc1b96a2d9fc6cc6d91d683b74456b886de34df792cfda", "7731ae6e6c54dfde12f6116357e812ea"),
(52059, "9d619fb4aa8441baaefed7b778693c291f2c1441b206ec135930fac3529d26587ac36f4472949e0b198b51c0c5a9d0f8", "39db2c996aea28996e03d576c118630f"),
(52836, "31dca4fa285878ba3efc3b66a248a078b69a11c3c73f81077377c4ffcb7002627aad5faa955e3141c1d8508aad68c8f6", "32ac1e5a09e7e629ff95f30aa9b69c00"),
(53613, "931a9969cf2bb02302c32b1eecd4933805e2da403d85aaf98c82c68129fb95f089eb85c65a6fcbc7d81bedb39de0cabb", "1a6f54b87c12868da530eac94d99eb31"),
(54390, "2f0742565801a37810ecb3f50a6f782e73a369a790d1a6a85135e7ffa12fc063db8909ab9eca7cf7308832887a6149d1", "1b18ed6a8f901b7947626216839f0643"),
(55167, "901defbd308b54deef89acd0d94e4387b370f9d2e6f870d72da2e447ed3ebe69c5f9f144488bd6207a732102160bff47", "1e0e6a05fcc0794121f617e28cfac1a0"),
(55944, "df984a5f7475250155dc4733a746e98446dc93a56a3f3bff691ddfef7deefb32b1da1b0e7e15cce443831ebfb3e30ada", "876121af882d0ebeae38f111f3d4b6e8"),
(56721, "acb693ed837b33561408cb1eed636e0082ac404f3fd72d277fa146ae5cd81a1fde3645f4cdc7babd8ba044b78075cb67", "5b90ed6c7943fc6da623c536e2ff1352"),
(57498, "dffb54bf5938e812076cfbf15cd524d72a189566c7980363a49dd89fb49e230d9742ef0b0e1ac543dca14366d735d152", "22aee072457306e32747fbbbc3ae127c"),
(58275, "92dbc245a980fc78974f7a27e62c22b12a00be9d3ef8d3718ff85f6d5fbcbf1d9d1e0f0a3daeb8c2628d090550a0ff6b", "5fa348117faba4ac8c9d9317ff44cd2d"),
(59052, "57721475cb719691850696d9a8ad4c28ca8ef9a7d45874ca21df4df250cb87ea60c464f4e3252e2d6161ed36c4b56d75", "24d92ae7cac56d9c0276b06f7428d5df"),
(59829, "d0936026440b5276747cb9fb7dc96de5d4e7846c233ca5f6f9354b2b39f760333483cbe99ffa905facb347242f58a7ef", "05c57068e183f9d835e7f461202f923c"),
(60606, "7b3bb3527b73a8692f076f6a503b2e09b427119543c7812db73c7c7fb2d43af9ecbd2a8a1452ac8ada96ad0bad7bb185", "f958635a193fec0bfb958e97961381df"),
(61383, "ff0d00255a36747eced86acfccd0cf9ef09faa9f44c8cf382efec462e7ead66e562a971060c3f32798ba142d9e1640a2", "838159b222e56aadde8229ed56a14095"),
(62160, "15806e088ed1428cd73ede3fecf5b60e2a616f1925004dadd2cab8e847059f795659659e82a4554f270baf88bf60af63", "fed2aa0c9c0a73d499cc970aef21c52f"),
(62937, "cfad71b23b6da51256bd1ddbd1ac77977fe10b2ad0a830a23a794cef914bf71a9519d78a5f83fc411e8d8db996a45d4e", "e1ea412fd3e1bd91c24b6b6445e8ff43"),
(63714, "7d03a3698a79b1af1663e3e485c2efdc306ecd87b2644f2e01d83a35999d6cdf12241b6114d60d107c10c0d0c9cc0d23", "e6a3c3f3fd2d9cfcdc06cca2f59e9a83"),
(64491, "e12b168cce0e82ed1db88df549f39b3ff40b5884a09fceae69c4c3db13c1c37ea79531c47b2700d1c27774a1ab7e8b35", "4cbb14d789f5cd8eca49ce9e1d442ea1"),
(65268, "056c9d1172cfa76ce7f19c605e5969c284b82dca155dc9c1ed58062ab4d5a7704e27fe69f3aa745b73f45f1cd0ee57df", "8195187f092d52c2a8695b680568b934"),
(
0,
"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b",
"43847e644239134deccf5538162c861e",
),
(
777,
"aabf892f18a620b9c3bae91bb03a74c84193e4a7b64916c6bc88b885b9ebed4134495e5f22f12e3046fbb3f26fa111a7",
"b8c318b5dcc1d672114a6f7be54ef289",
),
(
1554,
"648f551df29217f0e634b72ba6973c0eb95c7d4be8b135e550d8bcdf65b75980881bc0e03cf22589e04bedc7da1804cd",
"535b8ddd51ec82a1e850906fe321b21a",
),
(
2331,
"bfbfdffea40062e23bbdf0835e1d38d1623bebca7407908bbc6d5b3f2bfd062a2d237f091affda7348094fafda0bd1a7",
"4f521876fbb2c563051196b33c20c822",
),
(
3108,
"cc6035cab70f3a3298a5c4956ff07f179acf3771bb915c590a8a19fe5133d6d8a81c118148394dfb364af5c2fbdaadeb",
"d3adfa578c8bcd738c55ffc527358cef",
),
(
3885,
"15ec2760a21c25f9870a84ee757f3da2c261a950c2f692d75ff9e99b2d50c826c21e27e49c4cd3450fedc7e60371589f",
"a4c22d6c3d773634c2dc057e1f7c6738",
),
(
4662,
"c2afad6f034704300c34f143dcdcb86c9b954cec1ebf22e7071f288c58a2ae430d3e3748d214d1021472793d3f337dc6",
"c0601cb6cd4883102f70570c2cdc0ab6",
),
(
5439,
"8fee067f5a7a475a630f9db8b2eb80c1edc40eb4246a0f1c078e535df7d06451c6a9bde1a23ba70285690dd7100a8626",
"7352239f2302b08844309d28b13fa867",
),
(
6216,
"60095b4172438aee61e65f5379f4ef276c3632d4ac74eea7723a2201823432614aba7b4670d9bf7a5b9126ca38f3b88a",
"c0f0b0aa651965f8514b473c5406285e",
),
(
6993,
"10e754dd08b4d2a6c109fb01fce2b57d54743947e14a7e67d7efd0608baf91f7fc42a53328fe8c18d234abad8ebcdff0",
"58444988a62a99060728a7637c8499eb",
),
(
7770,
"1abc4a5dcd2696336bd0e8af20fe7fc261aa424b52cfb5ad80ee7c7c793ac44f11db3506cdbbbaed0f80000925d08d52",
"e8065c563bc6018cdcbf9aaafef767e6",
),
(
8547,
"26aaf74ae8bfc6aaf45ceee0476ea0a484304f5c36050d3e2265cb194a2f7c308213314232270608b6d3f1c11b834e33",
"ec50e4b3f6e4b3de24b3476623d08157",
),
(
9324,
"863206305d466aa9c0d0ec674572069f61fe5009767f99ec8832912725c28c49d6a106ad3f55372c922e4e169fc382ce",
"0cfac64f49e0f128d0a18d293878f222",
),
(
10101,
"bd0c0950b947a6c34f1fa6e877433b42c039a8ea7b37634c40fb47efae4958ba74ef0991cfedf3c82a0b87ef59635071",
"e0220a02b74259eeebbebede847d50f9",
),
(
10878,
"d7b9901af1dacf6a8c369b993ba1c607f9b7f073d02311c72d8449d3494d477ffc8344a1d8b488020ccfc7c80fbd27e1",
"ebe3933146734a6ade2b434f2bcd78ae",
),
(
11655,
"0ba265e3ef0bebf01a4f3490da462c7730aad6aa6c70bb9ce64a36d26d24fe213660e60e4d3301329170471f11ff8ca2",
"ec3dd4bf4cb7d527a86dd559c773a87b",
),
(
12432,
"c3b6755a1be922ec71c1e187ead36c4e6fc307c72969c64ca1e9b7339d61e1a93a74a315fd73bed8fa5797b78b19dbe5",
"5b58dcf392749bcef91056ba9475d0ef",
),
(
13209,
"2fb1a67151183daa2f0d7f0064534497357f173161349dd008499a8c1a123cc942662ecc426e2ad7743fe0ab9f5d7be1",
"c011260d328d310e2ab606aa1ef8afd4",
),
(
13986,
"6afae2a07ce9bfe30fbbfb7dcf32d755bcf357334dc5c309e58cab38ebe559f25b313a0b3ca32ff1dc41f7b99718f653",
"011bf43cfbbb7ae5986f8e0fc87771a9",
),
(
14763,
"cc6215c115eb6411f4712c2289f5bf0ccb5151635f9f9ceac7c1b62d8d2f4d26498079d0289f83aeb26e97b5b924ffc4",
"a015034a8d5bc83cc76c6983a5ba19ab",
),
(
15540,
"3cebce794e947341c4ceec444ca43c6ac57c6f58de462bfec7566cbd59a1b6f2eae774120e29521e76120a604d1a12d9",
"d373cd2bd9000655141ac632880eca40",
),
(
16317,
"899147b98d78bb5d137dc7c4f03be7eca82bcca19cc3a701261332923707aed2e6719d35d2f2bf067cd1d193a53529cf",
"ed223b64529299c787f49d631ce181c1",
),
(
17094,
"aecd1830958b994b2c331b90e7d8ff79f27c83a71f5797a65ade3a30b4fa5928e79140bcd03f375591d53df96fea1a4d",
"948a7c253d54bb6b65d78530c0eb7aab",
),
(
17871,
"e677ffd4ecaba5899659fefe5fe8e643004392be3be6dc5a801409870ac1e3398f47cc1d83f7a4c41925b6337e01f7fd",
"156a600c336f3ac034ca90034aa22635",
),
(
18648,
"4ee50f4a98d0bbd160add6acf76765ccdac0c1cd0bb2adbbcb22dd012a1121620b739a120df7dc4091e684ddf28eb726",
"75873467b416a7b025f9f1b015bf653a",
),
(
19425,
"aa025f32c0575af7209828fc7fc4591b41fa7cfb485e26c5401e63ca1fa05776f8b8af1769a15e81f2c663bca9b02ab3",
"5679efa7a4404e1e5c9b372782a41bf2",
),
(
20202,
"6e77ab62d2affeb27f4ef326191b3df3863c338a629f64a785505f4a5968ff59bc011c7a27951cb00e2e7d9b9bd32fec",
"36a9c4515d34f9bb962d8876ab3b5c86",
),
(
20979,
"1625b4f0e65fc66f11ba3ee6b3e20c732535654c447df6b517ced113107a1057a64477faa2af4a5ede4034bf3cff98ea",
"9058044e0f71c28d4f8d3281a3aec024",
),
(
21756,
"94efe6aa55bd77bfa58c185dec313a41003f9bef02568e72c337be4de1b46c6e5bb9a9329b4f108686489b8bc9d5f4f0",
"8d6d2c90590268a26f5e7d76351f48c1",
),
(
22533,
"7327a05fdb0ac92433dfc2c85c5e96e6ddcbdb01e079f8dafbee79c14cb4d5fd46047acd6bb0e09a98f6dd03dced2a0a",
"4e0f0a394f85bca35c68ef667aa9c244",
),
(
23310,
"93da9e356efbc8b5ae366256f4c6fc11c11fc347aaa879d591b7c1262d90adf98925f571914696054f1d09c74783561e",
"8c83c157be439280afc790ee3fd667eb",
),
(
24087,
"99b91be5ffca51b1cbc7410798b1540b5b1a3356f801ed4dc54812919c08ca5a9adc218bc51e594d97b46445a1515506",
"9436ff05729a77f673e815e464aeaa75",
),
(
24864,
"074253ad5d5a5d2b072e7aeaffa04a06119ec812a88ca43481fe5e2dce02cf6736952095cd342ec70b833c12fc1777f4",
"69d8951b96866a08efbb65f2bc31cfbc",
),
(
25641,
"c0a301f90597c05cf19e60c35378676764086b7156e455f4800347f8a6e733d644e4cc709fb9d95a9211f3e1e10c762a",
"3561c9802143c306ecc5e07e3b976d9e",
),
(
26418,
"3c839e59d945b841acb604e1b9ae3df36a291444ce0bcae336ee875beaf208bf10af7342b375429ecb92ec54d11a5907",
"3032ffdb8daee11b2e739132c6175615",
),
(
27195,
"3dc59b16603950dfc26a90bf036712eb088412e8de4d1b27c3fa6be6502ac12d89d194764fb53c3dc7d90fa696ba5a16",
"49436717edff7cd67c9a1be16d524f07",
),
(
27972,
"4fbc0d40ff13376b8ed5382890cdea337b4a0c9c31b477c4008d2ef8299bd5ab771ba70b1b4b743f8f7caa1f0164d1a1",
"64a9856a3bb81dc81ff1bc1025192dc9",
),
(
28749,
"6ab191aa6327f229cc94e8c7b1b7ee30bc723e6aeaf3050eb7d14cb491c3513254e9b19894c2b4f071d298401fd31945",
"101f2ffea60f246a3b57c4a530d67cf1",
),
(
29526,
"d06dece58e6c7345986aae4b7f15b3317653f5387d6262f389b5cbbe804568124a876eabb89204e96b3c0f7b552df3c4",
"5c0e873adba65a9f4cb24cce4f194b18",
),
(
30303,
"7a33c1268eafdc1f89ad460fa4ded8d3df9a3cabe4339706877878c64a2c8080cf3fa5ea7f2f24744e3341476b1eb5a5",
"b7dc708fc46ce5cde24a31ad549fec83",
),
(
31080,
"37bf1f9fca6d705b989b2d63259ca924dc860fc6027e07d9aad79b94841227739774f5d324590df45d8f41249ef742ea",
"8ead50308c281e699b79b69dad7ecb91",
),
(
31857,
"91b120c73be86f9d53326fa707cfa1411e5ac76ab998a2d7ebd73a75e3b1a04c9f0855d102184b8a3fd5d99818b0b134",
"6056d09595bd16bfa317c6f87ce64bb7",
),
(
32634,
"42cc255c06184ead57b27efd0cefb0f2c788c8962a6fd15db3f25533a7f49700bca85af916f9e985f1941a6e66943b38",
"3b15e332d2f53bb97e1a9d03e6113b97",
),
(
33411,
"737f8bb8f3fd03a9d13e50abba3a42f4491c36eda3eb215085abda733227ec490cb863ffbd68f915c8fb2926a899fbc3",
"b2c647d25c46aab4d4a5ede4a3b4576d",
),
(
34188,
"e9caa36505e19628175d1ce8b933267380099753a41e503fa2f894cea17b7692f0b27079ed33cdd1293db9a35722d561",
"a2882adfd00f22823250215b12b3a1fd",
),
(
34965,
"81ddc348ebbdfb963daa5d0c1b51bbb73cacd883d4fc4316db6bd3388779beff7be0655bbac73951f89dc53832199c11",
"f33106eb8104f3780350c6d4f82333ad",
),
(
35742,
"308ce31daf40dab707e2cb4c4a5307bc403e24c971ae1e30e998449f804a167fe5f2cf617d585851b6fe9f2b4209f09c",
"44070ac90cbf350ab92289cc063e978c",
),
(
36519,
"71f51b4bddbe8a52f18be75f9bdb3fca0773901b794de845450fb308c34775ede1a6da9a82b61e9682a29a3ef71274e2",
"0e387704298c444bf3afba0edc0c1c1c",
),
(
37296,
"478ac94eee8c5f96210003fcb478392b91f2ef6fc3a729774e5fe82a2d8d0abc54ae1d25b3eaefb061e2bd43b70ca4ea",
"fb65ebeda52cd5848d303c0677cecb7f",
),
(
38073,
"bc3a9390618da7d644be932627353e2c92024df939d2d8497fba61fae3dd822cdd3e130c1707f4a9d5d4a0cbb4b3e0b3",
"d790d529a837ec79f7cc3f66ed9a399f",
),
(
38850,
"ef0e63a53a10e56477c47e13320b8a7d330aee3a4363c850edc56c0707a2686478e5a5193f54ceb33467ab7e8a22aa21",
"6f2c18742f106f16fc290767342fb62b",
),
(
39627,
"c16f63533c099d872d9a01c326db7756e7eb488c756b9a6ebf575993d8ea2eb45c572b2e162f061e145710e0e21e8e18",
"a57afde7938b223ae5e109a03db4ee4c",
),
(
40404,
"ade484ae8c13465a73589ef14789bb6891c933453e198df84edd34b4ac5c83aa90f2cf61fa072fa4d8f5b5c4cd68fa9e",
"a01d13009db86ac442f7afd39d83309f",
),
(
41181,
"6c5c7eed0e043a0bd60bcac9b5b546e150028d70c1efefc9ff69037ef4dc1a36878b171b9f2a639df822d11054a0e405",
"6321c8622ca5866c875d340206d06a28",
),
(
41958,
"dd311c54222fb0d92858719cf5b1c51bb5e3ca2539ffd68f1dd6c7e38969495be935804855ccdcc4b4cf221fcdbda886",
"cf401eb819b5dc5cd8c909aae9b3b34b",
),
(
42735,
"31cda9d663199b32eff042dd16c0b909ba999641e77ba751c91752bfc4d595e17ec6467119e74a600b72da72ba287d0a",
"12fd6298ab5d744eb6ade3106565afad",
),
(
43512,
"11b014057d51a8384d549d5d083c4406b575df6a9295853dd8f2f84f078cc241bb90495a119126b10b9510efcb68c0d3",
"a48a49eea5dc90359ef21f32132f8604",
),
(
44289,
"b44f5dbeecd76ee7efe3fb4dfe10ba8135d7a5e4d104149f4a91c5c6ee9446d9be19fb4c9ba668b074466d3892e22228",
"07e1cbb7a19174d9b1e4d5a2c741cc14",
),
(
45066,
"d87bbba3a3c739cab622386c89aeb685a70009fab1a606bd34622adfa3a75a05b58d56ee6b9874d414db38a6a32927b3",
"a27cd252712cd2a1a2d95dea39f888d4",
),
(
45843,
"abb90e60ea13c6cb3b401b8e271637416b87fbede165dde7be1d34abe4427dae4b39b499352cacac909bc43fb94028c8",
"df3ae762b9257936feda435a61a9c3a1",
),
(
46620,
"56d1132ee6e0f85543950d2d9667244b66b0ce6414eacd1859b128ed0b9026b31a25bfdcce3d1a0ce7c39d99f609c89c",
"cfe7c3c3f1cb615e2d210cc8136443e6",
),
(
47397,
"ecb023ec4c23cf95d1848a38b359f1f590f172dee9d8fb1be6bc9c4fb2ce96f612d60d7b111de539ab8313a87b821176",
"501d24752bf55cb12239863981898a07",
),
(
48174,
"34236ab60f05bb510aa0880fec358fb2002903efa14c912cab8a399e09418f97223ca2f7b8d6798c11d39e79032eaaa8",
"4ecaba4eae886aa429927188abab9623",
),
(
48951,
"55e8b40fad90a3d8c85a0f4d5bcf5975b8a6e2fb78377109f5b607a5e367187fbbc9a1e978aab3228fbf43ad23d0ad13",
"84c43bc30eb4a67230b6c634fe3c7782",
),
(
49728,
"14b1f896d0d01ecff4e456c3c392b1ca2bad9f1ef07713f84cdd89e663aa27ca77d80213ed57a89431eb992b11d98749",
"7f58c2f9a249f70fe1c6f9b4f65e5a1d",
),
(
50505,
"1335b1fb56196e0b371fa53ab7445845fdefcea3eb2833478deb3526e2ec888945e95ee8239b52caae5b9920ba4f43bb",
"5fd729126b236ce3e0686fc706dce20f",
),
(
51282,
"0d1983a6cab870c5e78f89a11dd30e7d2c71a3882f8bba3e71dc1b96a2d9fc6cc6d91d683b74456b886de34df792cfda",
"7731ae6e6c54dfde12f6116357e812ea",
),
(
52059,
"9d619fb4aa8441baaefed7b778693c291f2c1441b206ec135930fac3529d26587ac36f4472949e0b198b51c0c5a9d0f8",
"39db2c996aea28996e03d576c118630f",
),
(
52836,
"31dca4fa285878ba3efc3b66a248a078b69a11c3c73f81077377c4ffcb7002627aad5faa955e3141c1d8508aad68c8f6",
"32ac1e5a09e7e629ff95f30aa9b69c00",
),
(
53613,
"931a9969cf2bb02302c32b1eecd4933805e2da403d85aaf98c82c68129fb95f089eb85c65a6fcbc7d81bedb39de0cabb",
"1a6f54b87c12868da530eac94d99eb31",
),
(
54390,
"2f0742565801a37810ecb3f50a6f782e73a369a790d1a6a85135e7ffa12fc063db8909ab9eca7cf7308832887a6149d1",
"1b18ed6a8f901b7947626216839f0643",
),
(
55167,
"901defbd308b54deef89acd0d94e4387b370f9d2e6f870d72da2e447ed3ebe69c5f9f144488bd6207a732102160bff47",
"1e0e6a05fcc0794121f617e28cfac1a0",
),
(
55944,
"df984a5f7475250155dc4733a746e98446dc93a56a3f3bff691ddfef7deefb32b1da1b0e7e15cce443831ebfb3e30ada",
"876121af882d0ebeae38f111f3d4b6e8",
),
(
56721,
"acb693ed837b33561408cb1eed636e0082ac404f3fd72d277fa146ae5cd81a1fde3645f4cdc7babd8ba044b78075cb67",
"5b90ed6c7943fc6da623c536e2ff1352",
),
(
57498,
"dffb54bf5938e812076cfbf15cd524d72a189566c7980363a49dd89fb49e230d9742ef0b0e1ac543dca14366d735d152",
"22aee072457306e32747fbbbc3ae127c",
),
(
58275,
"92dbc245a980fc78974f7a27e62c22b12a00be9d3ef8d3718ff85f6d5fbcbf1d9d1e0f0a3daeb8c2628d090550a0ff6b",
"5fa348117faba4ac8c9d9317ff44cd2d",
),
(
59052,
"57721475cb719691850696d9a8ad4c28ca8ef9a7d45874ca21df4df250cb87ea60c464f4e3252e2d6161ed36c4b56d75",
"24d92ae7cac56d9c0276b06f7428d5df",
),
(
59829,
"d0936026440b5276747cb9fb7dc96de5d4e7846c233ca5f6f9354b2b39f760333483cbe99ffa905facb347242f58a7ef",
"05c57068e183f9d835e7f461202f923c",
),
(
60606,
"7b3bb3527b73a8692f076f6a503b2e09b427119543c7812db73c7c7fb2d43af9ecbd2a8a1452ac8ada96ad0bad7bb185",
"f958635a193fec0bfb958e97961381df",
),
(
61383,
"ff0d00255a36747eced86acfccd0cf9ef09faa9f44c8cf382efec462e7ead66e562a971060c3f32798ba142d9e1640a2",
"838159b222e56aadde8229ed56a14095",
),
(
62160,
"15806e088ed1428cd73ede3fecf5b60e2a616f1925004dadd2cab8e847059f795659659e82a4554f270baf88bf60af63",
"fed2aa0c9c0a73d499cc970aef21c52f",
),
(
62937,
"cfad71b23b6da51256bd1ddbd1ac77977fe10b2ad0a830a23a794cef914bf71a9519d78a5f83fc411e8d8db996a45d4e",
"e1ea412fd3e1bd91c24b6b6445e8ff43",
),
(
63714,
"7d03a3698a79b1af1663e3e485c2efdc306ecd87b2644f2e01d83a35999d6cdf12241b6114d60d107c10c0d0c9cc0d23",
"e6a3c3f3fd2d9cfcdc06cca2f59e9a83",
),
(
64491,
"e12b168cce0e82ed1db88df549f39b3ff40b5884a09fceae69c4c3db13c1c37ea79531c47b2700d1c27774a1ab7e8b35",
"4cbb14d789f5cd8eca49ce9e1d442ea1",
),
(
65268,
"056c9d1172cfa76ce7f19c605e5969c284b82dca155dc9c1ed58062ab4d5a7704e27fe69f3aa745b73f45f1cd0ee57df",
"8195187f092d52c2a8695b680568b934",
),
];
fn to_hex(b: &[u8]) -> String {
@ -156,8 +499,12 @@ mod tests {
/// Test repeated encrypt/decrypt and run a benchmark. Run with --nocapture to see it.
#[test]
fn encrypt_decrypt() {
let aes_key_0: [u8; 32] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32];
let aes_key_1: [u8; 32] = [2, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32];
let aes_key_0: [u8; 32] = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
];
let aes_key_1: [u8; 32] = [
2, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
];
let iv: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let mut buf = [0_u8; 12345];
@ -205,7 +552,10 @@ mod tests {
let _ = c.encrypt_second_pass_finish();
}
let duration = SystemTime::now().duration_since(start).unwrap();
println!("AES-GMAC-SIV (legacy) encrypt benchmark: {} MiB/sec", (((benchmark_iterations * buf.len()) as f64) / 1048576.0) / duration.as_secs_f64());
println!(
"AES-GMAC-SIV (legacy) encrypt benchmark: {} MiB/sec",
(((benchmark_iterations * buf.len()) as f64) / 1048576.0) / duration.as_secs_f64()
);
let start = SystemTime::now();
for _ in 0..benchmark_iterations {
c.reset();
@ -214,6 +564,9 @@ mod tests {
c.decrypt_finish();
}
let duration = SystemTime::now().duration_since(start).unwrap();
println!("AES-GMAC-SIV (legacy) decrypt benchmark: {} MiB/sec", (((benchmark_iterations * buf.len()) as f64) / 1048576.0) / duration.as_secs_f64());
println!(
"AES-GMAC-SIV (legacy) decrypt benchmark: {} MiB/sec",
(((benchmark_iterations * buf.len()) as f64) / 1048576.0) / duration.as_secs_f64()
);
}
}

View file

@ -1,6 +1,14 @@
// (c) 2020-2022 ZeroTier, Inc. -- currently propritery pending actual release and licensing. See LICENSE.md.
#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)]
#![allow(
dead_code,
mutable_transmutes,
non_camel_case_types,
non_snake_case,
non_upper_case_globals,
unused_assignments,
unused_mut
)]
pub const P384_PUBLIC_KEY_SIZE: usize = 49;
pub const P384_SECRET_KEY_SIZE: usize = 48;
@ -116,7 +124,8 @@ mod builtin {
/* Returns nonzero if bit p_bit of p_vli is set. */
unsafe fn vli_testBit(mut p_vli: *mut uint64_t, mut p_bit: uint) -> uint64_t {
return *p_vli.offset(p_bit.wrapping_div(64 as libc::c_int as libc::c_uint) as isize) & (1 as libc::c_int as uint64_t) << p_bit.wrapping_rem(64 as libc::c_int as libc::c_uint);
return *p_vli.offset(p_bit.wrapping_div(64 as libc::c_int as libc::c_uint) as isize)
& (1 as libc::c_int as uint64_t) << p_bit.wrapping_rem(64 as libc::c_int as libc::c_uint);
}
/* Counts the number of 64-bit "digits" in p_vli. */
@ -215,7 +224,9 @@ mod builtin {
let mut i: uint = 0;
i = 0 as libc::c_int as uint;
while i < (48 as libc::c_int / 8 as libc::c_int) as libc::c_uint {
let mut l_sum: uint64_t = (*p_left.offset(i as isize)).wrapping_add(*p_right.offset(i as isize)).wrapping_add(l_carry);
let mut l_sum: uint64_t = (*p_left.offset(i as isize))
.wrapping_add(*p_right.offset(i as isize))
.wrapping_add(l_carry);
if l_sum != *p_left.offset(i as isize) {
l_carry = (l_sum < *p_left.offset(i as isize)) as libc::c_int as uint64_t
}
@ -231,7 +242,9 @@ mod builtin {
let mut i: uint = 0;
i = 0 as libc::c_int as uint;
while i < (48 as libc::c_int / 8 as libc::c_int) as libc::c_uint {
let mut l_diff: uint64_t = (*p_left.offset(i as isize)).wrapping_sub(*p_right.offset(i as isize)).wrapping_sub(l_borrow);
let mut l_diff: uint64_t = (*p_left.offset(i as isize))
.wrapping_sub(*p_right.offset(i as isize))
.wrapping_sub(l_borrow);
if l_diff != *p_left.offset(i as isize) {
l_borrow = (l_diff > *p_left.offset(i as isize)) as libc::c_int as uint64_t
}
@ -253,11 +266,13 @@ mod builtin {
let mut l_min: uint = if k < (48 as libc::c_int / 8 as libc::c_int) as libc::c_uint {
0 as libc::c_int as libc::c_uint
} else {
k.wrapping_add(1 as libc::c_int as libc::c_uint).wrapping_sub((48 as libc::c_int / 8 as libc::c_int) as libc::c_uint)
k.wrapping_add(1 as libc::c_int as libc::c_uint)
.wrapping_sub((48 as libc::c_int / 8 as libc::c_int) as libc::c_uint)
};
i = l_min;
while i <= k && i < (48 as libc::c_int / 8 as libc::c_int) as libc::c_uint {
let mut l_product: uint128_t = (*p_left.offset(i as isize) as uint128_t).wrapping_mul(*p_right.offset(k.wrapping_sub(i) as isize) as u128);
let mut l_product: uint128_t =
(*p_left.offset(i as isize) as uint128_t).wrapping_mul(*p_right.offset(k.wrapping_sub(i) as isize) as u128);
r01 = (r01 as u128).wrapping_add(l_product) as uint128_t as uint128_t;
r2 = (r2 as libc::c_ulong).wrapping_add((r01 < l_product) as libc::c_int as libc::c_ulong) as uint64_t as uint64_t;
i = i.wrapping_add(1)
@ -281,11 +296,13 @@ mod builtin {
let mut l_min: uint = if k < (48 as libc::c_int / 8 as libc::c_int) as libc::c_uint {
0 as libc::c_int as libc::c_uint
} else {
k.wrapping_add(1 as libc::c_int as libc::c_uint).wrapping_sub((48 as libc::c_int / 8 as libc::c_int) as libc::c_uint)
k.wrapping_add(1 as libc::c_int as libc::c_uint)
.wrapping_sub((48 as libc::c_int / 8 as libc::c_int) as libc::c_uint)
};
i = l_min;
while i <= k && i <= k.wrapping_sub(i) {
let mut l_product: uint128_t = (*p_left.offset(i as isize) as uint128_t).wrapping_mul(*p_left.offset(k.wrapping_sub(i) as isize) as u128);
let mut l_product: uint128_t =
(*p_left.offset(i as isize) as uint128_t).wrapping_mul(*p_left.offset(k.wrapping_sub(i) as isize) as u128);
if i < k.wrapping_sub(i) {
r2 = (r2 as u128).wrapping_add(l_product >> 127 as libc::c_int) as uint64_t as uint64_t;
l_product = (l_product as u128).wrapping_mul(2 as libc::c_int as u128) as uint128_t as uint128_t
@ -333,9 +350,16 @@ mod builtin {
/* Multiply by (2^128 + 2^96 - 2^32 + 1). */
vli_set(p_result, p_right); /* 1 */
l_carry = vli_lshift(l_tmp.as_mut_ptr(), p_right, 32 as libc::c_int as uint); /* 2^96 + 1 */
*p_result.offset((1 as libc::c_int + 48 as libc::c_int / 8 as libc::c_int) as isize) =
l_carry.wrapping_add(vli_add(p_result.offset(1 as libc::c_int as isize), p_result.offset(1 as libc::c_int as isize), l_tmp.as_mut_ptr())); /* 2^128 + 2^96 + 1 */
*p_result.offset((2 as libc::c_int + 48 as libc::c_int / 8 as libc::c_int) as isize) = vli_add(p_result.offset(2 as libc::c_int as isize), p_result.offset(2 as libc::c_int as isize), p_right); /* 2^128 + 2^96 - 2^32 + 1 */
*p_result.offset((1 as libc::c_int + 48 as libc::c_int / 8 as libc::c_int) as isize) = l_carry.wrapping_add(vli_add(
p_result.offset(1 as libc::c_int as isize),
p_result.offset(1 as libc::c_int as isize),
l_tmp.as_mut_ptr(),
)); /* 2^128 + 2^96 + 1 */
*p_result.offset((2 as libc::c_int + 48 as libc::c_int / 8 as libc::c_int) as isize) = vli_add(
p_result.offset(2 as libc::c_int as isize),
p_result.offset(2 as libc::c_int as isize),
p_right,
); /* 2^128 + 2^96 - 2^32 + 1 */
l_carry = (l_carry as libc::c_ulong).wrapping_add(vli_sub(p_result, p_result, l_tmp.as_mut_ptr())) as uint64_t as uint64_t;
l_diff = (*p_result.offset((48 as libc::c_int / 8 as libc::c_int) as isize)).wrapping_sub(l_carry);
if l_diff > *p_result.offset((48 as libc::c_int / 8 as libc::c_int) as isize) {
@ -365,12 +389,17 @@ mod builtin {
let mut i: uint = 0; /* p = c0 */
vli_clear(l_tmp.as_mut_ptr());
vli_clear(l_tmp.as_mut_ptr().offset((48 as libc::c_int / 8 as libc::c_int) as isize));
omega_mult(l_tmp.as_mut_ptr(), p_product.offset((48 as libc::c_int / 8 as libc::c_int) as isize));
omega_mult(
l_tmp.as_mut_ptr(),
p_product.offset((48 as libc::c_int / 8 as libc::c_int) as isize),
);
vli_clear(p_product.offset((48 as libc::c_int / 8 as libc::c_int) as isize));
/* (c1, c0) = c0 + w * c1 */
i = 0 as libc::c_int as uint;
while i < (48 as libc::c_int / 8 as libc::c_int + 3 as libc::c_int) as libc::c_uint {
let mut l_sum: uint64_t = (*p_product.offset(i as isize)).wrapping_add(l_tmp[i as usize]).wrapping_add(l_carry);
let mut l_sum: uint64_t = (*p_product.offset(i as isize))
.wrapping_add(l_tmp[i as usize])
.wrapping_add(l_carry);
if l_sum != *p_product.offset(i as isize) {
l_carry = (l_sum < *p_product.offset(i as isize)) as libc::c_int as uint64_t
}
@ -432,7 +461,8 @@ mod builtin {
vli_rshift1(u.as_mut_ptr());
if l_carry != 0 {
u[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] =
(u[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] as libc::c_ulonglong | 0x8000000000000000 as libc::c_ulonglong) as uint64_t
(u[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] as libc::c_ulonglong
| 0x8000000000000000 as libc::c_ulonglong) as uint64_t
}
} else if b[0 as libc::c_int as usize] & 1 as libc::c_int as libc::c_ulong == 0 {
vli_rshift1(b.as_mut_ptr());
@ -442,7 +472,8 @@ mod builtin {
vli_rshift1(v.as_mut_ptr());
if l_carry != 0 {
v[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] =
(v[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] as libc::c_ulonglong | 0x8000000000000000 as libc::c_ulonglong) as uint64_t
(v[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] as libc::c_ulonglong
| 0x8000000000000000 as libc::c_ulonglong) as uint64_t
}
} else if l_cmpResult > 0 as libc::c_int {
vli_sub(a.as_mut_ptr(), a.as_mut_ptr(), b.as_mut_ptr());
@ -457,7 +488,8 @@ mod builtin {
vli_rshift1(u.as_mut_ptr());
if l_carry != 0 {
u[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] =
(u[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] as libc::c_ulonglong | 0x8000000000000000 as libc::c_ulonglong) as uint64_t
(u[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] as libc::c_ulonglong
| 0x8000000000000000 as libc::c_ulonglong) as uint64_t
}
} else {
vli_sub(b.as_mut_ptr(), b.as_mut_ptr(), a.as_mut_ptr());
@ -472,7 +504,8 @@ mod builtin {
vli_rshift1(v.as_mut_ptr());
if l_carry != 0 {
v[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] =
(v[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] as libc::c_ulonglong | 0x8000000000000000 as libc::c_ulonglong) as uint64_t
(v[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] as libc::c_ulonglong
| 0x8000000000000000 as libc::c_ulonglong) as uint64_t
}
}
}
@ -538,7 +571,13 @@ mod builtin {
}
/* P = (x1, y1) => 2P, (x2, y2) => P' */
unsafe fn XYcZ_initial_double(mut X1: *mut uint64_t, mut Y1: *mut uint64_t, mut X2: *mut uint64_t, mut Y2: *mut uint64_t, mut p_initialZ: *mut uint64_t) {
unsafe fn XYcZ_initial_double(
mut X1: *mut uint64_t,
mut Y1: *mut uint64_t,
mut X2: *mut uint64_t,
mut Y2: *mut uint64_t,
mut p_initialZ: *mut uint64_t,
) {
let mut z: [uint64_t; 6] = std::mem::MaybeUninit::uninit().assume_init();
vli_set(X2, X1);
vli_set(Y2, Y1);
@ -606,7 +645,12 @@ mod builtin {
vli_set(X1, t7.as_mut_ptr());
}
unsafe fn EccPoint_mult(mut p_result: *mut EccPoint, mut p_point: *mut EccPoint, mut p_scalar: *mut uint64_t, mut p_initialZ: *mut uint64_t) {
unsafe fn EccPoint_mult(
mut p_result: *mut EccPoint,
mut p_point: *mut EccPoint,
mut p_scalar: *mut uint64_t,
mut p_initialZ: *mut uint64_t,
) {
/* R0 and R1 */
let mut Rx: [[uint64_t; 6]; 2] = std::mem::MaybeUninit::uninit().assume_init();
let mut Ry: [[uint64_t; 6]; 2] = std::mem::MaybeUninit::uninit().assume_init();
@ -665,7 +709,11 @@ mod builtin {
Rx[(1 as libc::c_int - nb) as usize].as_mut_ptr(),
Ry[(1 as libc::c_int - nb) as usize].as_mut_ptr(),
);
apply_z(Rx[0 as libc::c_int as usize].as_mut_ptr(), Ry[0 as libc::c_int as usize].as_mut_ptr(), z.as_mut_ptr());
apply_z(
Rx[0 as libc::c_int as usize].as_mut_ptr(),
Ry[0 as libc::c_int as usize].as_mut_ptr(),
z.as_mut_ptr(),
);
vli_set((*p_result).x.as_mut_ptr(), Rx[0 as libc::c_int as usize].as_mut_ptr());
vli_set((*p_result).y.as_mut_ptr(), Ry[0 as libc::c_int as usize].as_mut_ptr());
}
@ -674,8 +722,11 @@ mod builtin {
let mut i: libc::c_uint = 0;
i = 0 as libc::c_int as libc::c_uint;
while i < (48 as libc::c_int / 8 as libc::c_int) as libc::c_uint {
let mut p_digit: *const uint8_t =
p_bytes.offset((8 as libc::c_int as libc::c_uint).wrapping_mul(((48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as libc::c_uint).wrapping_sub(i)) as isize);
let mut p_digit: *const uint8_t = p_bytes.offset(
(8 as libc::c_int as libc::c_uint)
.wrapping_mul(((48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as libc::c_uint).wrapping_sub(i))
as isize,
);
*p_native.offset(i as isize) = (*p_digit.offset(0 as libc::c_int as isize) as uint64_t) << 56 as libc::c_int
| (*p_digit.offset(1 as libc::c_int as isize) as uint64_t) << 48 as libc::c_int
| (*p_digit.offset(2 as libc::c_int as isize) as uint64_t) << 40 as libc::c_int
@ -692,8 +743,11 @@ mod builtin {
let mut i: libc::c_uint = 0;
i = 0 as libc::c_int as libc::c_uint;
while i < (48 as libc::c_int / 8 as libc::c_int) as libc::c_uint {
let mut p_digit: *mut uint8_t =
p_bytes.offset((8 as libc::c_int as libc::c_uint).wrapping_mul(((48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as libc::c_uint).wrapping_sub(i)) as isize);
let mut p_digit: *mut uint8_t = p_bytes.offset(
(8 as libc::c_int as libc::c_uint)
.wrapping_mul(((48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as libc::c_uint).wrapping_sub(i))
as isize,
);
*p_digit.offset(0 as libc::c_int as isize) = (*p_native.offset(i as isize) >> 56 as libc::c_int) as uint8_t;
*p_digit.offset(1 as libc::c_int as isize) = (*p_native.offset(i as isize) >> 48 as libc::c_int) as uint8_t;
*p_digit.offset(2 as libc::c_int as isize) = (*p_native.offset(i as isize) >> 40 as libc::c_int) as uint8_t;
@ -730,11 +784,23 @@ mod builtin {
let mut _3: [uint64_t; 6] = [3 as libc::c_int as uint64_t, 0, 0, 0, 0, 0];
ecc_bytes2native((*p_point).x.as_mut_ptr(), p_compressed.offset(1 as libc::c_int as isize));
vli_modSquare_fast((*p_point).y.as_mut_ptr(), (*p_point).x.as_mut_ptr());
vli_modSub((*p_point).y.as_mut_ptr(), (*p_point).y.as_mut_ptr(), _3.as_mut_ptr(), curve_p.as_mut_ptr());
vli_modSub(
(*p_point).y.as_mut_ptr(),
(*p_point).y.as_mut_ptr(),
_3.as_mut_ptr(),
curve_p.as_mut_ptr(),
);
vli_modMult_fast((*p_point).y.as_mut_ptr(), (*p_point).y.as_mut_ptr(), (*p_point).x.as_mut_ptr());
vli_modAdd((*p_point).y.as_mut_ptr(), (*p_point).y.as_mut_ptr(), curve_b.as_mut_ptr(), curve_p.as_mut_ptr());
vli_modAdd(
(*p_point).y.as_mut_ptr(),
(*p_point).y.as_mut_ptr(),
curve_b.as_mut_ptr(),
curve_p.as_mut_ptr(),
);
mod_sqrt((*p_point).y.as_mut_ptr());
if (*p_point).y[0 as libc::c_int as usize] & 0x1 as libc::c_int as libc::c_ulong != (*p_compressed.offset(0 as libc::c_int as isize) as libc::c_int & 0x1 as libc::c_int) as libc::c_ulong {
if (*p_point).y[0 as libc::c_int as usize] & 0x1 as libc::c_int as libc::c_ulong
!= (*p_compressed.offset(0 as libc::c_int as isize) as libc::c_int & 0x1 as libc::c_int) as libc::c_ulong
{
vli_sub((*p_point).y.as_mut_ptr(), curve_p.as_mut_ptr(), (*p_point).y.as_mut_ptr());
};
}
@ -763,11 +829,20 @@ mod builtin {
}
}
ecc_native2bytes(p_privateKey, l_private.as_mut_ptr() as *const uint64_t);
ecc_native2bytes(p_publicKey.offset(1 as libc::c_int as isize), l_public.x.as_mut_ptr() as *const uint64_t);
*p_publicKey.offset(0 as libc::c_int as isize) = (2 as libc::c_int as libc::c_ulong).wrapping_add(l_public.y[0 as libc::c_int as usize] & 0x1 as libc::c_int as libc::c_ulong) as uint8_t;
ecc_native2bytes(
p_publicKey.offset(1 as libc::c_int as isize),
l_public.x.as_mut_ptr() as *const uint64_t,
);
*p_publicKey.offset(0 as libc::c_int as isize) = (2 as libc::c_int as libc::c_ulong)
.wrapping_add(l_public.y[0 as libc::c_int as usize] & 0x1 as libc::c_int as libc::c_ulong)
as uint8_t;
return 1 as libc::c_int;
}
pub unsafe fn ecdh_shared_secret(mut p_publicKey: *const uint8_t, mut p_privateKey: *const uint8_t, mut p_secret: *mut uint8_t) -> libc::c_int {
pub unsafe fn ecdh_shared_secret(
mut p_publicKey: *const uint8_t,
mut p_privateKey: *const uint8_t,
mut p_secret: *mut uint8_t,
) -> libc::c_int {
let mut l_public: EccPoint = std::mem::MaybeUninit::uninit().assume_init();
let mut l_private: [uint64_t; 6] = std::mem::MaybeUninit::uninit().assume_init();
let mut l_random: [uint64_t; 6] = std::mem::MaybeUninit::uninit().assume_init();
@ -794,7 +869,9 @@ mod builtin {
vli_mult(l_product.as_mut_ptr(), p_left, p_right);
l_productBits = vli_numBits(l_product.as_mut_ptr().offset((48 as libc::c_int / 8 as libc::c_int) as isize));
if l_productBits != 0 {
l_productBits = (l_productBits as libc::c_uint).wrapping_add((48 as libc::c_int / 8 as libc::c_int * 64 as libc::c_int) as libc::c_uint) as uint as uint
l_productBits = (l_productBits as libc::c_uint)
.wrapping_add((48 as libc::c_int / 8 as libc::c_int * 64 as libc::c_int) as libc::c_uint)
as uint as uint
} else {
l_productBits = vli_numBits(l_product.as_mut_ptr())
}
@ -807,8 +884,12 @@ mod builtin {
power of two possible while still resulting in a number less than p_left. */
vli_clear(l_modMultiple.as_mut_ptr());
vli_clear(l_modMultiple.as_mut_ptr().offset((48 as libc::c_int / 8 as libc::c_int) as isize));
l_digitShift = l_productBits.wrapping_sub(l_modBits).wrapping_div(64 as libc::c_int as libc::c_uint);
l_bitShift = l_productBits.wrapping_sub(l_modBits).wrapping_rem(64 as libc::c_int as libc::c_uint);
l_digitShift = l_productBits
.wrapping_sub(l_modBits)
.wrapping_div(64 as libc::c_int as libc::c_uint);
l_bitShift = l_productBits
.wrapping_sub(l_modBits)
.wrapping_rem(64 as libc::c_int as libc::c_uint);
if l_bitShift != 0 {
l_modMultiple[l_digitShift.wrapping_add((48 as libc::c_int / 8 as libc::c_int) as libc::c_uint) as usize] =
vli_lshift(l_modMultiple.as_mut_ptr().offset(l_digitShift as isize), p_mod, l_bitShift)
@ -818,12 +899,16 @@ mod builtin {
/* Subtract all multiples of p_mod to get the remainder. */
vli_clear(p_result); /* Use p_result as a temp var to store 1 (for subtraction) */
*p_result.offset(0 as libc::c_int as isize) = 1 as libc::c_int as uint64_t;
while l_productBits > (48 as libc::c_int / 8 as libc::c_int * 64 as libc::c_int) as libc::c_uint || vli_cmp(l_modMultiple.as_mut_ptr(), p_mod) >= 0 as libc::c_int {
while l_productBits > (48 as libc::c_int / 8 as libc::c_int * 64 as libc::c_int) as libc::c_uint
|| vli_cmp(l_modMultiple.as_mut_ptr(), p_mod) >= 0 as libc::c_int
{
let mut l_cmp: libc::c_int = vli_cmp(
l_modMultiple.as_mut_ptr().offset((48 as libc::c_int / 8 as libc::c_int) as isize),
l_product.as_mut_ptr().offset((48 as libc::c_int / 8 as libc::c_int) as isize),
);
if l_cmp < 0 as libc::c_int || l_cmp == 0 as libc::c_int && vli_cmp(l_modMultiple.as_mut_ptr(), l_product.as_mut_ptr()) <= 0 as libc::c_int {
if l_cmp < 0 as libc::c_int
|| l_cmp == 0 as libc::c_int && vli_cmp(l_modMultiple.as_mut_ptr(), l_product.as_mut_ptr()) <= 0 as libc::c_int
{
if vli_sub(l_product.as_mut_ptr(), l_product.as_mut_ptr(), l_modMultiple.as_mut_ptr()) != 0 {
/* borrow */
vli_sub(
@ -838,7 +923,8 @@ mod builtin {
l_modMultiple.as_mut_ptr().offset((48 as libc::c_int / 8 as libc::c_int) as isize),
);
}
let mut l_carry: uint64_t = (l_modMultiple[(48 as libc::c_int / 8 as libc::c_int) as usize] & 0x1 as libc::c_int as libc::c_ulong) << 63 as libc::c_int;
let mut l_carry: uint64_t =
(l_modMultiple[(48 as libc::c_int / 8 as libc::c_int) as usize] & 0x1 as libc::c_int as libc::c_ulong) << 63 as libc::c_int;
vli_rshift1(l_modMultiple.as_mut_ptr().offset((48 as libc::c_int / 8 as libc::c_int) as isize));
vli_rshift1(l_modMultiple.as_mut_ptr());
l_modMultiple[(48 as libc::c_int / 8 as libc::c_int - 1 as libc::c_int) as usize] |= l_carry;
@ -890,7 +976,11 @@ mod builtin {
ecc_native2bytes(p_signature.offset(48 as libc::c_int as isize), l_s.as_mut_ptr() as *const uint64_t);
return 1 as libc::c_int;
}
pub unsafe fn ecdsa_verify(mut p_publicKey: *const uint8_t, mut p_hash: *const uint8_t, mut p_signature: *const uint8_t) -> libc::c_int {
pub unsafe fn ecdsa_verify(
mut p_publicKey: *const uint8_t,
mut p_hash: *const uint8_t,
mut p_signature: *const uint8_t,
) -> libc::c_int {
let mut u1: [uint64_t; 6] = std::mem::MaybeUninit::uninit().assume_init();
let mut u2: [uint64_t; 6] = std::mem::MaybeUninit::uninit().assume_init();
let mut z: [uint64_t; 6] = std::mem::MaybeUninit::uninit().assume_init();
@ -910,7 +1000,9 @@ mod builtin {
/* r, s must not be 0. */
return 0 as libc::c_int;
}
if vli_cmp(curve_n.as_mut_ptr(), l_r.as_mut_ptr()) != 1 as libc::c_int || vli_cmp(curve_n.as_mut_ptr(), l_s.as_mut_ptr()) != 1 as libc::c_int {
if vli_cmp(curve_n.as_mut_ptr(), l_r.as_mut_ptr()) != 1 as libc::c_int
|| vli_cmp(curve_n.as_mut_ptr(), l_s.as_mut_ptr()) != 1 as libc::c_int
{
/* r, s must be < n. */
return 0 as libc::c_int;
}
@ -931,9 +1023,10 @@ mod builtin {
/* Use Shamir's trick to calculate u1*G + u2*Q */
let mut l_points: [*mut EccPoint; 4] = [0 as *mut EccPoint, &mut curve_G, &mut l_public, &mut l_sum]; /* Z = x2 - x1 */
let mut l_numBits: uint = umax(vli_numBits(u1.as_mut_ptr()), vli_numBits(u2.as_mut_ptr())); /* Z = 1/Z */
let mut l_point: *mut EccPoint = l_points[((vli_testBit(u1.as_mut_ptr(), l_numBits.wrapping_sub(1 as libc::c_int as libc::c_uint)) != 0) as libc::c_int
| ((vli_testBit(u2.as_mut_ptr(), l_numBits.wrapping_sub(1 as libc::c_int as libc::c_uint)) != 0) as libc::c_int) << 1 as libc::c_int)
as usize];
let mut l_point: *mut EccPoint = l_points[((vli_testBit(u1.as_mut_ptr(), l_numBits.wrapping_sub(1 as libc::c_int as libc::c_uint))
!= 0) as libc::c_int
| ((vli_testBit(u2.as_mut_ptr(), l_numBits.wrapping_sub(1 as libc::c_int as libc::c_uint)) != 0) as libc::c_int)
<< 1 as libc::c_int) as usize];
vli_set(rx.as_mut_ptr(), (*l_point).x.as_mut_ptr());
vli_set(ry.as_mut_ptr(), (*l_point).y.as_mut_ptr());
vli_clear(z.as_mut_ptr());
@ -942,7 +1035,8 @@ mod builtin {
i = l_numBits.wrapping_sub(2 as libc::c_int as libc::c_uint) as libc::c_int;
while i >= 0 as libc::c_int {
EccPoint_double_jacobian(rx.as_mut_ptr(), ry.as_mut_ptr(), z.as_mut_ptr());
let mut l_index: libc::c_int = (vli_testBit(u1.as_mut_ptr(), i as uint) != 0) as libc::c_int | ((vli_testBit(u2.as_mut_ptr(), i as uint) != 0) as libc::c_int) << 1 as libc::c_int;
let mut l_index: libc::c_int = (vli_testBit(u1.as_mut_ptr(), i as uint) != 0) as libc::c_int
| ((vli_testBit(u2.as_mut_ptr(), i as uint) != 0) as libc::c_int) << 1 as libc::c_int;
let mut l_point_0: *mut EccPoint = l_points[l_index as usize];
if !l_point_0.is_null() {
vli_set(tx.as_mut_ptr(), (*l_point_0).x.as_mut_ptr());
@ -1002,7 +1096,10 @@ mod builtin {
pub fn from_bytes(public_bytes: &[u8], secret_bytes: &[u8]) -> Option<P384KeyPair> {
if public_bytes.len() == 49 && secret_bytes.len() == 48 {
Some(Self(P384PublicKey(public_bytes.try_into().unwrap()), Secret(secret_bytes.try_into().unwrap())))
Some(Self(
P384PublicKey(public_bytes.try_into().unwrap()),
Secret(secret_bytes.try_into().unwrap()),
))
} else {
None
}
@ -1080,7 +1177,9 @@ mod openssl_based {
impl P384PublicKey {
fn new_from_point(key: &EcPointRef) -> Self {
let mut bnc = BigNumContext::new().unwrap();
let kb = key.to_bytes(GROUP_P384.as_ref(), PointConversionForm::COMPRESSED, &mut bnc).unwrap();
let kb = key
.to_bytes(GROUP_P384.as_ref(), PointConversionForm::COMPRESSED, &mut bnc)
.unwrap();
let mut bytes = [0_u8; 49];
bytes[(49 - kb.len())..].copy_from_slice(kb.as_slice());
Self {
@ -1219,7 +1318,14 @@ mod openssl_based {
pub fn agree(&self, other_public: &P384PublicKey) -> Option<Secret<P384_ECDH_SHARED_SECRET_SIZE>> {
unsafe {
let mut s: Secret<P384_ECDH_SHARED_SECRET_SIZE> = Secret::default();
if ECDH_compute_key(s.0.as_mut_ptr().cast(), 48, other_public.key.public_key().as_ptr().cast(), self.pair.as_ptr().cast(), null()) == 48 {
if ECDH_compute_key(
s.0.as_mut_ptr().cast(),
48,
other_public.key.public_key().as_ptr().cast(),
self.pair.as_ptr().cast(),
null(),
) == 48
{
Some(s)
} else {
None

View file

@ -10,7 +10,10 @@ pub const POLY1305_MAC_SIZE: usize = 16;
#[inline(always)]
pub fn compute(one_time_key: &[u8], message: &[u8]) -> [u8; POLY1305_MAC_SIZE] {
poly1305::Poly1305::new(poly1305::Key::from_slice(one_time_key)).compute_unpadded(message).into_bytes().into()
poly1305::Poly1305::new(poly1305::Key::from_slice(one_time_key))
.compute_unpadded(message)
.into_bytes()
.into()
}
#[cfg(test)]
@ -18,18 +21,25 @@ mod tests {
use crate::poly1305::*;
const TV0_INPUT: [u8; 32] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
const TV0_KEY: [u8; 32] = [
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x66, 0x6f,
0x72, 0x20, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35,
];
const TV0_TAG: [u8; 16] = [
0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07,
];
const TV0_TAG: [u8; 16] = [0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07];
const TV1_INPUT: [u8; 12] = [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21];
const TV1_KEY: [u8; 32] = [
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35,
0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x33, 0x32, 0x2d, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x66, 0x6f,
0x72, 0x20, 0x50, 0x6f, 0x6c, 0x79, 0x31, 0x33, 0x30, 0x35,
];
const TV1_TAG: [u8; 16] = [
0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0,
];
const TV1_TAG: [u8; 16] = [0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0];
#[test]
fn poly1305() {

View file

@ -3,7 +3,12 @@
use std::convert::TryInto;
use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
const CONSTANTS: [u32; 4] = [u32::from_le_bytes(*b"expa"), u32::from_le_bytes(*b"nd 3"), u32::from_le_bytes(*b"2-by"), u32::from_le_bytes(*b"te k")];
const CONSTANTS: [u32; 4] = [
u32::from_le_bytes(*b"expa"),
u32::from_le_bytes(*b"nd 3"),
u32::from_le_bytes(*b"2-by"),
u32::from_le_bytes(*b"te k"),
];
/// Salsa stream cipher implementation supporting 8, 12, or 20 rounds.
///
@ -65,8 +70,24 @@ impl<const ROUNDS: usize> Salsa<ROUNDS> {
);
while !plaintext.is_empty() {
let (mut x0, mut x1, mut x2, mut x3, mut x4, mut x5, mut x6, mut x7, mut x8, mut x9, mut x10, mut x11, mut x12, mut x13, mut x14, mut x15) =
(j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15);
let (
mut x0,
mut x1,
mut x2,
mut x3,
mut x4,
mut x5,
mut x6,
mut x7,
mut x8,
mut x9,
mut x10,
mut x11,
mut x12,
mut x13,
mut x14,
mut x15,
) = (j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15);
for _ in 0..(ROUNDS / 2) {
x4 ^= x0.wrapping_add(x12).rotate_left(7);
@ -206,7 +227,12 @@ impl<const ROUNDS: usize> Salsa<ROUNDS> {
#[inline(always)]
pub fn crypt_in_place(&mut self, data: &mut [u8]) {
unsafe { self.crypt(&*slice_from_raw_parts(data.as_ptr(), data.len()), &mut *slice_from_raw_parts_mut(data.as_mut_ptr(), data.len())) }
unsafe {
self.crypt(
&*slice_from_raw_parts(data.as_ptr(), data.len()),
&mut *slice_from_raw_parts_mut(data.as_mut_ptr(), data.len()),
)
}
}
}
@ -215,12 +241,14 @@ mod tests {
use crate::salsa::*;
const SALSA_20_TV0_KEY: [u8; 32] = [
0x0f, 0x62, 0xb5, 0x08, 0x5b, 0xae, 0x01, 0x54, 0xa7, 0xfa, 0x4d, 0xa0, 0xf3, 0x46, 0x99, 0xec, 0x3f, 0x92, 0xe5, 0x38, 0x8b, 0xde, 0x31, 0x84, 0xd7, 0x2a, 0x7d, 0xd0, 0x23, 0x76, 0xc9, 0x1c,
0x0f, 0x62, 0xb5, 0x08, 0x5b, 0xae, 0x01, 0x54, 0xa7, 0xfa, 0x4d, 0xa0, 0xf3, 0x46, 0x99, 0xec, 0x3f, 0x92, 0xe5, 0x38, 0x8b, 0xde,
0x31, 0x84, 0xd7, 0x2a, 0x7d, 0xd0, 0x23, 0x76, 0xc9, 0x1c,
];
const SALSA_20_TV0_IV: [u8; 8] = [0x28, 0x8f, 0xf6, 0x5d, 0xc4, 0x2b, 0x92, 0xf9];
const SALSA_20_TV0_KS: [u8; 64] = [
0x5e, 0x5e, 0x71, 0xf9, 0x01, 0x99, 0x34, 0x03, 0x04, 0xab, 0xb2, 0x2a, 0x37, 0xb6, 0x62, 0x5b, 0xf8, 0x83, 0xfb, 0x89, 0xce, 0x3b, 0x21, 0xf5, 0x4a, 0x10, 0xb8, 0x10, 0x66, 0xef, 0x87, 0xda,
0x30, 0xb7, 0x76, 0x99, 0xaa, 0x73, 0x79, 0xda, 0x59, 0x5c, 0x77, 0xdd, 0x59, 0x54, 0x2d, 0xa2, 0x08, 0xe5, 0x95, 0x4f, 0x89, 0xe4, 0x0e, 0xb7, 0xaa, 0x80, 0xa8, 0x4a, 0x61, 0x76, 0x66, 0x3f,
0x5e, 0x5e, 0x71, 0xf9, 0x01, 0x99, 0x34, 0x03, 0x04, 0xab, 0xb2, 0x2a, 0x37, 0xb6, 0x62, 0x5b, 0xf8, 0x83, 0xfb, 0x89, 0xce, 0x3b,
0x21, 0xf5, 0x4a, 0x10, 0xb8, 0x10, 0x66, 0xef, 0x87, 0xda, 0x30, 0xb7, 0x76, 0x99, 0xaa, 0x73, 0x79, 0xda, 0x59, 0x5c, 0x77, 0xdd,
0x59, 0x54, 0x2d, 0xa2, 0x08, 0xe5, 0x95, 0x4f, 0x89, 0xe4, 0x0e, 0xb7, 0xaa, 0x80, 0xa8, 0x4a, 0x61, 0x76, 0x66, 0x3f,
];
#[test]

View file

@ -84,7 +84,11 @@ impl X25519KeyPair {
impl Clone for X25519KeyPair {
fn clone(&self) -> Self {
Self(x25519_dalek::StaticSecret::from(self.0.to_bytes()), self.1.clone(), x25519_dalek::PublicKey::from(self.1 .0.clone()))
Self(
x25519_dalek::StaticSecret::from(self.0.to_bytes()),
self.1.clone(),
x25519_dalek::PublicKey::from(self.1 .0.clone()),
)
}
}

View file

@ -117,8 +117,9 @@ const KBKDF_KEY_USAGE_LABEL_RATCHETING: u8 = b'R';
const INITIAL_KEY: [u8; 64] = [
// macOS command line to generate:
// echo -n 'ZSSP_Noise_IKpsk2_NISTP384_?KYBER1024_AESGCM_SHA512' | shasum -a 512 | cut -d ' ' -f 1 | xxd -r -p | xxd -i
0x35, 0x6a, 0x75, 0xc0, 0xbf, 0xbe, 0xc3, 0x59, 0x70, 0x94, 0x50, 0x69, 0x4c, 0xa2, 0x08, 0x40, 0xc7, 0xdf, 0x67, 0xa8, 0x68, 0x52, 0x6e, 0xd5, 0xdd, 0x77, 0xec, 0x59, 0x6f, 0x8e, 0xa1, 0x99,
0xb4, 0x32, 0x85, 0xaf, 0x7f, 0x0d, 0xa9, 0x6c, 0x01, 0xfb, 0x72, 0x46, 0xc0, 0x09, 0x58, 0xb8, 0xe0, 0xa8, 0xcf, 0xb1, 0x58, 0x04, 0x6e, 0x32, 0xba, 0xa8, 0xb8, 0xf9, 0x0a, 0xa4, 0xbf, 0x36,
0x35, 0x6a, 0x75, 0xc0, 0xbf, 0xbe, 0xc3, 0x59, 0x70, 0x94, 0x50, 0x69, 0x4c, 0xa2, 0x08, 0x40, 0xc7, 0xdf, 0x67, 0xa8, 0x68, 0x52,
0x6e, 0xd5, 0xdd, 0x77, 0xec, 0x59, 0x6f, 0x8e, 0xa1, 0x99, 0xb4, 0x32, 0x85, 0xaf, 0x7f, 0x0d, 0xa9, 0x6c, 0x01, 0xfb, 0x72, 0x46,
0xc0, 0x09, 0x58, 0xb8, 0xe0, 0xa8, 0xcf, 0xb1, 0x58, 0x04, 0x6e, 0x32, 0xba, 0xa8, 0xb8, 0xf9, 0x0a, 0xa4, 0xbf, 0x36,
];
pub enum Error {
@ -232,7 +233,8 @@ impl SessionId {
pub fn new_from_reader<R: Read>(r: &mut R) -> std::io::Result<Option<SessionId>> {
let mut tmp = [0_u8; 8];
r.read_exact(&mut tmp[..SESSION_ID_SIZE]).map(|_| NonZeroU64::new(u64::from_le_bytes(tmp)).map(|i| Self(i)))
r.read_exact(&mut tmp[..SESSION_ID_SIZE])
.map(|_| NonZeroU64::new(u64::from_le_bytes(tmp)).map(|i| Self(i)))
}
}
@ -278,7 +280,12 @@ pub trait Host: Sized {
/// On success a tuple of local session ID, static secret, and associated object is returned. The
/// static secret is whatever results from agreement between the local and remote static public
/// keys.
fn accept_new_session(&self, receive_context: &ReceiveContext<Self>, remote_static_public: &[u8], remote_metadata: &[u8]) -> Option<(SessionId, Secret<64>, Self::AssociatedObject)>;
fn accept_new_session(
&self,
receive_context: &ReceiveContext<Self>,
remote_static_public: &[u8],
remote_metadata: &[u8],
) -> Option<(SessionId, Secret<64>, Self::AssociatedObject)>;
}
/// ZSSP bi-directional packet transport channel.
@ -338,7 +345,8 @@ impl<H: Host> Session<H> {
let send_counter = Counter::new();
let header_check_cipher = Aes::new(kbkdf512(ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>());
let remote_s_public_hash = SHA384::hash(remote_s_public);
let outgoing_init_header_check_cipher = Aes::new(kbkdf512(&remote_s_public_hash, KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>());
let outgoing_init_header_check_cipher =
Aes::new(kbkdf512(&remote_s_public_hash, KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>());
if let Ok(offer) = create_initial_offer(
&mut send,
send_counter.next(),
@ -381,7 +389,12 @@ impl<H: Host> Session<H> {
///
/// * `mtu_buffer` - A writable work buffer whose size must be equal to the wire MTU
/// * `data` - Data to send
pub fn send<SendFunction: FnMut(&mut [u8])>(&self, mut send: SendFunction, mtu_buffer: &mut [u8], mut data: &[u8]) -> Result<(), Error> {
pub fn send<SendFunction: FnMut(&mut [u8])>(
&self,
mut send: SendFunction,
mtu_buffer: &mut [u8],
mut data: &[u8],
) -> Result<(), Error> {
debug_assert!(mtu_buffer.len() >= MIN_MTU);
let state = self.state.read();
if let Some(remote_session_id) = state.remote_session_id {
@ -389,7 +402,14 @@ impl<H: Host> Session<H> {
let mut packet_len = data.len() + HEADER_SIZE + AES_GCM_TAG_SIZE;
let counter = self.send_counter.next();
create_packet_header(mtu_buffer, packet_len, mtu_buffer.len(), PACKET_TYPE_DATA, remote_session_id.into(), counter)?;
create_packet_header(
mtu_buffer,
packet_len,
mtu_buffer.len(),
PACKET_TYPE_DATA,
remote_session_id.into(),
counter,
)?;
let mut c = key.get_send_cipher(counter)?;
c.init(memory::as_byte_array::<Pseudoheader, 12>(&Pseudoheader::make(
@ -461,13 +481,24 @@ impl<H: Host> Session<H> {
/// * `mtu` - Physical MTU for sent packets
/// * `current_time` - Current monotonic time in milliseconds
/// * `force_rekey` - Re-key the session now regardless of key aging (still subject to rate limiting)
pub fn service<SendFunction: FnMut(&mut [u8])>(&self, host: &H, mut send: SendFunction, offer_metadata: &[u8], mtu: usize, current_time: i64, force_rekey: bool) {
pub fn service<SendFunction: FnMut(&mut [u8])>(
&self,
host: &H,
mut send: SendFunction,
offer_metadata: &[u8],
mtu: usize,
current_time: i64,
force_rekey: bool,
) {
let state = self.state.upgradable_read();
if (force_rekey
|| state.keys[state.key_ptr]
.as_ref()
.map_or(true, |key| key.lifetime.should_rekey(self.send_counter.current(), current_time)))
&& state.offer.as_ref().map_or(true, |o| (current_time - o.creation_time) > OFFER_RATE_LIMIT_MS)
&& state
.offer
.as_ref()
.map_or(true, |o| (current_time - o.creation_time) > OFFER_RATE_LIMIT_MS)
{
if let Some(remote_s_public_p384) = P384PublicKey::from_bytes(&self.remote_s_public_p384) {
let mut tmp_header_check_cipher = None;
@ -485,7 +516,9 @@ impl<H: Host> Session<H> {
if state.remote_session_id.is_some() {
&self.header_check_cipher
} else {
let _ = tmp_header_check_cipher.insert(Aes::new(kbkdf512(&self.remote_s_public_hash, KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>()));
let _ = tmp_header_check_cipher.insert(Aes::new(
kbkdf512(&self.remote_s_public_hash, KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>(),
));
tmp_header_check_cipher.as_ref().unwrap()
},
mtu,
@ -502,7 +535,9 @@ impl<H: Host> ReceiveContext<H> {
pub fn new(host: &H) -> Self {
Self {
initial_offer_defrag: Mutex::new(RingBufferMap::new(random::xorshift64_random() as u32)),
incoming_init_header_check_cipher: Aes::new(kbkdf512(host.get_local_s_public_hash(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>()),
incoming_init_header_check_cipher: Aes::new(
kbkdf512(host.get_local_s_public_hash(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>(),
),
}
}
@ -529,7 +564,9 @@ impl<H: Host> ReceiveContext<H> {
if let Some(local_session_id) = SessionId::new_from_u64(memory::u64_from_le_bytes(incoming_packet) & SessionId::MAX_BIT_MASK) {
if let Some(session) = host.session_lookup(local_session_id) {
if let Some((packet_type, fragment_count, fragment_no, counter)) = dearmor_header(incoming_packet, &session.header_check_cipher) {
if let Some((packet_type, fragment_count, fragment_no, counter)) =
dearmor_header(incoming_packet, &session.header_check_cipher)
{
let pseudoheader = Pseudoheader::make(u64::from(local_session_id), packet_type, counter);
if fragment_count > 1 {
if fragment_count <= (MAX_FRAGMENTS as u8) && fragment_no < fragment_count {
@ -576,7 +613,9 @@ impl<H: Host> ReceiveContext<H> {
}
} else {
unlikely_branch();
if let Some((packet_type, fragment_count, fragment_no, counter)) = dearmor_header(incoming_packet, &self.incoming_init_header_check_cipher) {
if let Some((packet_type, fragment_count, fragment_no, counter)) =
dearmor_header(incoming_packet, &self.incoming_init_header_check_cipher)
{
let pseudoheader = Pseudoheader::make(0, packet_type, counter);
if fragment_count > 1 {
let mut defrag = self.initial_offer_defrag.lock();
@ -670,13 +709,20 @@ impl<H: Host> ReceiveContext<H> {
key.return_receive_cipher(c);
return Err(Error::DataBufferTooSmall);
}
c.crypt(&tail[HEADER_SIZE..(tail.len() - AES_GCM_TAG_SIZE)], &mut data_buf[current_frag_data_start..data_len]);
c.crypt(
&tail[HEADER_SIZE..(tail.len() - AES_GCM_TAG_SIZE)],
&mut data_buf[current_frag_data_start..data_len],
);
let ok = c.finish_decrypt(&tail[(tail.len() - AES_GCM_TAG_SIZE)..]);
key.return_receive_cipher(c);
if ok {
// Select this key as the new default if it's newer than the current key.
if p > 0 && state.keys[state.key_ptr].as_ref().map_or(true, |old| old.establish_counter < key.establish_counter) {
if p > 0
&& state.keys[state.key_ptr]
.as_ref()
.map_or(true, |old| old.establish_counter < key.establish_counter)
{
drop(state);
let mut state = session.state.write();
state.key_ptr = key_ptr;
@ -741,7 +787,13 @@ impl<H: Host> ReceiveContext<H> {
let hmac1_end = incoming_packet_len - HMAC_SIZE;
// Check that the sender knows this host's identity before doing anything else.
if !hmac_sha384_2(host.get_local_s_public_hash(), pseudoheader, &incoming_packet[HEADER_SIZE..hmac1_end]).eq(&incoming_packet[hmac1_end..]) {
if !hmac_sha384_2(
host.get_local_s_public_hash(),
pseudoheader,
&incoming_packet[HEADER_SIZE..hmac1_end],
)
.eq(&incoming_packet[hmac1_end..])
{
return Err(Error::FailedAuthentication);
}
@ -755,7 +807,8 @@ impl<H: Host> ReceiveContext<H> {
}
// Key agreement: alice (remote) ephemeral NIST P-384 <> local static NIST P-384
let (alice_e0_public, e0s) = P384PublicKey::from_bytes(&incoming_packet[(HEADER_SIZE + 1)..(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)])
let (alice_e0_public, e0s) =
P384PublicKey::from_bytes(&incoming_packet[(HEADER_SIZE + 1)..(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)])
.and_then(|pk| host.get_local_s_keypair_p384().agree(&pk).map(move |s| (pk, s)))
.ok_or(Error::FailedAuthentication)?;
@ -763,7 +816,10 @@ impl<H: Host> ReceiveContext<H> {
let mut key = Secret(hmac_sha512(&hmac_sha512(&INITIAL_KEY, alice_e0_public.as_bytes()), e0s.as_bytes()));
// Decrypt the encrypted part of the packet payload and authenticate the above key exchange via AES-GCM auth.
let mut c = AesGcm::new(kbkdf512(key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_ALICE_TO_BOB).first_n::<32>(), false);
let mut c = AesGcm::new(
kbkdf512(key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_ALICE_TO_BOB).first_n::<32>(),
false,
);
c.init(pseudoheader);
c.crypt_in_place(&mut incoming_packet[(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)..payload_end]);
if !c.finish_decrypt(&incoming_packet[payload_end..aes_gcm_tag_end]) {
@ -812,7 +868,10 @@ impl<H: Host> ReceiveContext<H> {
let alice_s_public_p384 = H::extract_p384_static(alice_s_public).ok_or(Error::InvalidPacket)?;
// Key agreement: both sides' static P-384 keys.
let ss = host.get_local_s_keypair_p384().agree(&alice_s_public_p384).ok_or(Error::FailedAuthentication)?;
let ss = host
.get_local_s_keypair_p384()
.agree(&alice_s_public_p384)
.ok_or(Error::FailedAuthentication)?;
// Mix result of 'ss' agreement into master key.
key = Secret(hmac_sha512(key.as_bytes(), ss.as_bytes()));
@ -843,7 +902,9 @@ impl<H: Host> ReceiveContext<H> {
let new_session = if session.is_some() {
None
} else {
if let Some((new_session_id, psk, associated_object)) = host.accept_new_session(self, alice_s_public, alice_metadata) {
if let Some((new_session_id, psk, associated_object)) =
host.accept_new_session(self, alice_s_public, alice_metadata)
{
let header_check_cipher = Aes::new(kbkdf512(ss.as_bytes(), KBKDF_KEY_USAGE_LABEL_HEADER_CHECK).first_n::<16>());
Some(Session::<H> {
id: new_session_id,
@ -877,7 +938,10 @@ impl<H: Host> ReceiveContext<H> {
// fixed size so this shouldn't matter cryptographically.
key = Secret(hmac_sha512(
session.psk.as_bytes(),
&hmac_sha512(&hmac_sha512(&hmac_sha512(key.as_bytes(), bob_e0_keypair.public_key_bytes()), e0e0.as_bytes()), se0.as_bytes()),
&hmac_sha512(
&hmac_sha512(&hmac_sha512(key.as_bytes(), bob_e0_keypair.public_key_bytes()), e0e0.as_bytes()),
se0.as_bytes(),
),
));
// At this point we've completed Noise_IK key derivation with NIST P-384 ECDH, but now for hybrid and ratcheting...
@ -922,12 +986,23 @@ impl<H: Host> ReceiveContext<H> {
REPLY_BUF_LEN - rp.len()
};
create_packet_header(&mut reply_buf, reply_len, mtu, PACKET_TYPE_KEY_COUNTER_OFFER, alice_session_id.into(), reply_counter)?;
let reply_pseudoheader = Pseudoheader::make(alice_session_id.into(), PACKET_TYPE_KEY_COUNTER_OFFER, reply_counter.to_u32());
create_packet_header(
&mut reply_buf,
reply_len,
mtu,
PACKET_TYPE_KEY_COUNTER_OFFER,
alice_session_id.into(),
reply_counter,
)?;
let reply_pseudoheader =
Pseudoheader::make(alice_session_id.into(), PACKET_TYPE_KEY_COUNTER_OFFER, reply_counter.to_u32());
// Encrypt reply packet using final Noise_IK key BEFORE mixing hybrid or ratcheting, since the other side
// must decrypt before doing these things.
let mut c = AesGcm::new(kbkdf512(key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE).first_n::<32>(), true);
let mut c = AesGcm::new(
kbkdf512(key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE).first_n::<32>(),
true,
);
c.init(memory::as_byte_array::<Pseudoheader, 12>(&reply_pseudoheader));
c.crypt_in_place(&mut reply_buf[(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)..reply_len]);
let c = c.finish_encrypt();
@ -985,17 +1060,27 @@ impl<H: Host> ReceiveContext<H> {
if let Some(session) = session {
let state = session.state.upgradable_read();
if let Some(offer) = state.offer.as_ref() {
let (bob_e0_public, e0e0) = P384PublicKey::from_bytes(&incoming_packet[(HEADER_SIZE + 1)..(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)])
let (bob_e0_public, e0e0) =
P384PublicKey::from_bytes(&incoming_packet[(HEADER_SIZE + 1)..(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)])
.and_then(|pk| offer.alice_e0_keypair.agree(&pk).map(move |s| (pk, s)))
.ok_or(Error::FailedAuthentication)?;
let se0 = host.get_local_s_keypair_p384().agree(&bob_e0_public).ok_or(Error::FailedAuthentication)?;
let se0 = host
.get_local_s_keypair_p384()
.agree(&bob_e0_public)
.ok_or(Error::FailedAuthentication)?;
let mut key = Secret(hmac_sha512(
session.psk.as_bytes(),
&hmac_sha512(&hmac_sha512(&hmac_sha512(offer.key.as_bytes(), bob_e0_public.as_bytes()), e0e0.as_bytes()), se0.as_bytes()),
&hmac_sha512(
&hmac_sha512(&hmac_sha512(offer.key.as_bytes(), bob_e0_public.as_bytes()), e0e0.as_bytes()),
se0.as_bytes(),
),
));
let mut c = AesGcm::new(kbkdf512(key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE).first_n::<32>(), false);
let mut c = AesGcm::new(
kbkdf512(key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_BOB_TO_ALICE).first_n::<32>(),
false,
);
c.init(pseudoheader);
c.crypt_in_place(&mut incoming_packet[(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)..payload_end]);
if !c.finish_decrypt(&incoming_packet[payload_end..aes_gcm_tag_end]) {
@ -1046,10 +1131,21 @@ impl<H: Host> ReceiveContext<H> {
let key = SessionKey::new(key, Role::Alice, current_time, counter, ratchet_count + 1, e1e1.is_some());
let mut reply_buf = [0_u8; HEADER_SIZE + AES_GCM_TAG_SIZE];
create_packet_header(&mut reply_buf, HEADER_SIZE + AES_GCM_TAG_SIZE, mtu, PACKET_TYPE_NOP, bob_session_id.into(), counter)?;
create_packet_header(
&mut reply_buf,
HEADER_SIZE + AES_GCM_TAG_SIZE,
mtu,
PACKET_TYPE_NOP,
bob_session_id.into(),
counter,
)?;
let mut c = key.get_send_cipher(counter)?;
c.init(memory::as_byte_array::<Pseudoheader, 12>(&Pseudoheader::make(bob_session_id.into(), PACKET_TYPE_NOP, counter.to_u32())));
c.init(memory::as_byte_array::<Pseudoheader, 12>(&Pseudoheader::make(
bob_session_id.into(),
PACKET_TYPE_NOP,
counter.to_u32(),
)));
reply_buf[HEADER_SIZE..].copy_from_slice(&c.finish_encrypt());
key.return_send_cipher(c);
@ -1204,10 +1300,16 @@ fn create_initial_offer<SendFunction: FnMut(&mut [u8])>(
create_packet_header(&mut packet_buf, packet_len, mtu, PACKET_TYPE_KEY_OFFER, bob_session_id, counter)?;
let pseudoheader = Pseudoheader::make(bob_session_id, PACKET_TYPE_KEY_OFFER, counter.to_u32());
let key = Secret(hmac_sha512(&hmac_sha512(&INITIAL_KEY, alice_e0_keypair.public_key_bytes()), e0s.unwrap().as_bytes()));
let key = Secret(hmac_sha512(
&hmac_sha512(&INITIAL_KEY, alice_e0_keypair.public_key_bytes()),
e0s.unwrap().as_bytes(),
));
let gcm_tag = {
let mut c = AesGcm::new(kbkdf512(key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_ALICE_TO_BOB).first_n::<32>(), true);
let mut c = AesGcm::new(
kbkdf512(key.as_bytes(), KBKDF_KEY_USAGE_LABEL_AES_GCM_ALICE_TO_BOB).first_n::<32>(),
true,
);
c.init(memory::as_byte_array::<Pseudoheader, 12>(&pseudoheader));
c.crypt_in_place(&mut packet_buf[(HEADER_SIZE + 1 + P384_PUBLIC_KEY_SIZE)..packet_len]);
c.finish_encrypt()
@ -1225,7 +1327,11 @@ fn create_initial_offer<SendFunction: FnMut(&mut [u8])>(
packet_buf[packet_len..(packet_len + HMAC_SIZE)].copy_from_slice(&hmac);
packet_len += HMAC_SIZE;
let hmac = hmac_sha384_2(bob_s_public_hash, memory::as_byte_array::<Pseudoheader, 12>(&pseudoheader), &packet_buf[HEADER_SIZE..packet_len]);
let hmac = hmac_sha384_2(
bob_s_public_hash,
memory::as_byte_array::<Pseudoheader, 12>(&pseudoheader),
&packet_buf[HEADER_SIZE..packet_len],
);
packet_buf[packet_len..(packet_len + HMAC_SIZE)].copy_from_slice(&hmac);
packet_len += HMAC_SIZE;
@ -1243,7 +1349,14 @@ fn create_initial_offer<SendFunction: FnMut(&mut [u8])>(
}
#[inline(always)]
fn create_packet_header(header: &mut [u8], packet_len: usize, mtu: usize, packet_type: u8, recipient_session_id: u64, counter: CounterValue) -> Result<(), Error> {
fn create_packet_header(
header: &mut [u8],
packet_len: usize,
mtu: usize,
packet_type: u8,
recipient_session_id: u64,
counter: CounterValue,
) -> Result<(), Error> {
let fragment_count = ((packet_len as f32) / (mtu - HEADER_SIZE) as f32).ceil() as usize;
debug_assert!(header.len() >= HEADER_SIZE);
@ -1255,7 +1368,9 @@ fn create_packet_header(header: &mut [u8], packet_len: usize, mtu: usize, packet
debug_assert!(recipient_session_id <= 0xffffffffffff); // session ID is 48 bits
if fragment_count <= MAX_FRAGMENTS {
header[0..8].copy_from_slice(&(recipient_session_id | (packet_type as u64).wrapping_shl(48) | ((fragment_count - 1) as u64).wrapping_shl(52)).to_le_bytes());
header[0..8].copy_from_slice(
&(recipient_session_id | (packet_type as u64).wrapping_shl(48) | ((fragment_count - 1) as u64).wrapping_shl(52)).to_le_bytes(),
);
header[8..12].copy_from_slice(&counter.to_u32().to_le_bytes());
header[12..16].fill(0);
Ok(())
@ -1265,7 +1380,12 @@ fn create_packet_header(header: &mut [u8], packet_len: usize, mtu: usize, packet
}
}
fn send_with_fragmentation<SendFunction: FnMut(&mut [u8])>(send: &mut SendFunction, packet: &mut [u8], mtu: usize, header_check_cipher: &Aes) {
fn send_with_fragmentation<SendFunction: FnMut(&mut [u8])>(
send: &mut SendFunction,
packet: &mut [u8],
mtu: usize,
header_check_cipher: &Aes,
) {
let packet_len = packet.len();
let mut fragment_start = 0;
let mut fragment_end = packet_len.min(mtu);
@ -1294,7 +1414,10 @@ fn armor_header(packet: &mut [u8], header_check_cipher: &Aes) {
debug_assert!(packet.len() >= MIN_PACKET_SIZE);
let mut header_pad = 0u128.to_ne_bytes();
header_check_cipher.encrypt_block(&packet[16..32], &mut header_pad);
packet[SESSION_ID_SIZE..HEADER_SIZE].iter_mut().zip(header_pad.iter()).for_each(|(x, y)| *x ^= *y);
packet[SESSION_ID_SIZE..HEADER_SIZE]
.iter_mut()
.zip(header_pad.iter())
.for_each(|(x, y)| *x ^= *y);
}
/// Dearmor the armored part of the header and return it if the 32-bit MAC matches.
@ -1326,7 +1449,10 @@ fn dearmor_header(packet: &[u8], header_check_cipher: &Aes) -> Option<(u8, u8, u
}
/// Parse KEY_OFFER and KEY_COUNTER_OFFER starting after the unencrypted public key part.
fn parse_key_offer_after_header(incoming_packet: &[u8], packet_type: u8) -> Result<([u8; 16], SessionId, &[u8], &[u8], &[u8], Option<[u8; 16]>), Error> {
fn parse_key_offer_after_header(
incoming_packet: &[u8],
packet_type: u8,
) -> Result<([u8; 16], SessionId, &[u8], &[u8], &[u8], Option<[u8; 16]>), Error> {
let mut p = &incoming_packet[..];
let mut offer_id = [0_u8; 16];
p.read_exact(&mut offer_id)?;
@ -1381,7 +1507,14 @@ fn parse_key_offer_after_header(incoming_packet: &[u8], packet_type: u8) -> Resu
} else {
None
};
Ok((offer_id, alice_session_id, alice_s_public, alice_metadata, alice_e1_public, alice_ratchet_key_fingerprint))
Ok((
offer_id,
alice_session_id,
alice_s_public,
alice_metadata,
alice_e1_public,
alice_ratchet_key_fingerprint,
))
}
enum Role {
@ -1399,9 +1532,13 @@ struct KeyLifetime {
impl KeyLifetime {
fn new(current_counter: CounterValue, current_time: i64) -> Self {
Self {
rekey_at_or_after_counter: current_counter.0 + REKEY_AFTER_USES + (random::next_u32_secure() % REKEY_AFTER_USES_MAX_JITTER) as u64,
rekey_at_or_after_counter: current_counter.0
+ REKEY_AFTER_USES
+ (random::next_u32_secure() % REKEY_AFTER_USES_MAX_JITTER) as u64,
hard_expire_at_counter: current_counter.0 + EXPIRE_AFTER_USES,
rekey_at_or_after_timestamp: current_time + REKEY_AFTER_TIME_MS + (random::next_u32_secure() % REKEY_AFTER_TIME_MS_MAX_JITTER) as i64,
rekey_at_or_after_timestamp: current_time
+ REKEY_AFTER_TIME_MS
+ (random::next_u32_secure() % REKEY_AFTER_TIME_MS_MAX_JITTER) as i64,
}
}
@ -1458,7 +1595,11 @@ impl SessionKey {
#[inline(always)]
fn get_send_cipher(&self, counter: CounterValue) -> Result<Box<AesGcm>, Error> {
if !self.lifetime.expired(counter) {
Ok(self.send_cipher_pool.lock().pop().unwrap_or_else(|| Box::new(AesGcm::new(self.send_key.as_bytes(), true))))
Ok(self
.send_cipher_pool
.lock()
.pop()
.unwrap_or_else(|| Box::new(AesGcm::new(self.send_key.as_bytes(), true))))
} else {
Err(Error::MaxKeyLifetimeExceeded)
}
@ -1471,7 +1612,10 @@ impl SessionKey {
#[inline(always)]
fn get_receive_cipher(&self) -> Box<AesGcm> {
self.receive_cipher_pool.lock().pop().unwrap_or_else(|| Box::new(AesGcm::new(self.receive_key.as_bytes(), false)))
self.receive_cipher_pool
.lock()
.pop()
.unwrap_or_else(|| Box::new(AesGcm::new(self.receive_key.as_bytes(), false)))
}
#[inline(always)]
@ -1574,7 +1718,12 @@ mod tests {
})
}
fn accept_new_session(&self, _: &ReceiveContext<Self>, _: &[u8], _: &[u8]) -> Option<(SessionId, Secret<64>, Self::AssociatedObject)> {
fn accept_new_session(
&self,
_: &ReceiveContext<Self>,
_: &[u8],
_: &[u8],
) -> Option<(SessionId, Secret<64>, Self::AssociatedObject)> {
loop {
let mut new_id = self.session_id_counter.lock();
*new_id += 1;
@ -1646,7 +1795,13 @@ mod tests {
assert!(!data.iter().any(|x| *x != 0x12));
}
ReceiveResult::OkNewSession(new_session) => {
println!("zssp: {} => {} ({}): OkNewSession ({})", host.other_name, host.this_name, qi_len, u64::from(new_session.id));
println!(
"zssp: {} => {} ({}): OkNewSession ({})",
host.other_name,
host.this_name,
qi_len,
u64::from(new_session.id)
);
let mut hs = host.session.lock();
assert!(hs.is_none());
let _ = hs.insert(Arc::new(new_session));
@ -1656,7 +1811,13 @@ mod tests {
}
}
} else {
println!("zssp: {} => {} ({}): error: {}", host.other_name, host.this_name, qi_len, r.err().unwrap().to_string());
println!(
"zssp: {} => {} ({}): error: {}",
host.other_name,
host.this_name,
qi_len,
r.err().unwrap().to_string()
);
panic!();
}
} else {
@ -1683,7 +1844,11 @@ mod tests {
}
for _ in 0..4 {
assert!(session
.send(send_to_other, &mut mtu_buffer, &data_buf[..((random::xorshift64_random() as usize) % data_buf.len())])
.send(
send_to_other,
&mut mtu_buffer,
&data_buf[..((random::xorshift64_random() as usize) % data_buf.len())]
)
.is_ok());
}
if (test_loop % 8) == 0 && test_loop >= 8 && host.this_name.eq("alice") {

View file

@ -54,8 +54,17 @@ impl<I: Interface> NetworkHypervisor<I> {
/// Process a physical packet received over a network interface.
#[inline(always)]
pub async fn handle_incoming_physical_packet(&self, ii: &I, source_endpoint: &Endpoint, source_local_socket: &I::LocalSocket, source_local_interface: &I::LocalInterface, data: PooledPacketBuffer) {
self.vl1.handle_incoming_physical_packet(ii, &self.vl2, source_endpoint, source_local_socket, source_local_interface, data).await
pub async fn handle_incoming_physical_packet(
&self,
ii: &I,
source_endpoint: &Endpoint,
source_local_socket: &I::LocalSocket,
source_local_interface: &I::LocalInterface,
data: PooledPacketBuffer,
) {
self.vl1
.handle_incoming_physical_packet(ii, &self.vl2, source_endpoint, source_local_socket, source_local_interface, data)
.await
}
/// Add or update a root set.

View file

@ -2,5 +2,16 @@
// from zeronsd
pub fn randstring(len: u8) -> String {
(0..len).map(|_| (rand::random::<u8>() % 26) + 'a' as u8).map(|c| if rand::random::<bool>() { (c as char).to_ascii_uppercase() } else { c as char }).map(|c| c.to_string()).collect::<Vec<String>>().join("")
(0..len)
.map(|_| (rand::random::<u8>() % 26) + 'a' as u8)
.map(|c| {
if rand::random::<bool>() {
(c as char).to_ascii_uppercase()
} else {
c as char
}
})
.map(|c| c.to_string())
.collect::<Vec<String>>()
.join("")
}

View file

@ -78,7 +78,10 @@ impl Marshalable for Address {
#[inline(always)]
fn unmarshal<const BL: usize>(buf: &Buffer<BL>, cursor: &mut usize) -> std::io::Result<Self> {
Self::from_bytes_fixed(buf.read_bytes_fixed(cursor)?).map_or_else(|| Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "cannot be zero")), |a| Ok(a))
Self::from_bytes_fixed(buf.read_bytes_fixed(cursor)?).map_or_else(
|| Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "cannot be zero")),
|a| Ok(a),
)
}
}
@ -275,8 +278,14 @@ mod tests {
let addr = safe_address();
for _ in 0..1000 {
assert_eq!(serde_json::from_str::<super::Address>(&serde_json::to_string(&addr).unwrap()).unwrap(), addr);
assert_eq!(serde_cbor::from_slice::<super::Address>(&serde_cbor::to_vec(&addr).unwrap()).unwrap(), addr);
assert_eq!(
serde_json::from_str::<super::Address>(&serde_json::to_string(&addr).unwrap()).unwrap(),
addr
);
assert_eq!(
serde_cbor::from_slice::<super::Address>(&serde_cbor::to_vec(&addr).unwrap()).unwrap(),
addr
);
}
}
}

View file

@ -81,7 +81,9 @@ impl Dictionary {
}
pub fn get_str(&self, k: &str) -> Option<&str> {
self.0.get(k).map_or(None, |v| std::str::from_utf8(v.as_slice()).map_or(None, |s| Some(s)))
self.0
.get(k)
.map_or(None, |v| std::str::from_utf8(v.as_slice()).map_or(None, |s| Some(s)))
}
pub fn get_bytes(&self, k: &str) -> Option<&[u8]> {
@ -89,15 +91,19 @@ impl Dictionary {
}
pub fn get_u64(&self, k: &str) -> Option<u64> {
self.get_str(k).map_or(None, |s| u64::from_str_radix(s, 16).map_or(None, |i| Some(i)))
self.get_str(k)
.map_or(None, |s| u64::from_str_radix(s, 16).map_or(None, |i| Some(i)))
}
pub fn get_i64(&self, k: &str) -> Option<i64> {
self.get_str(k).map_or(None, |s| i64::from_str_radix(s, 16).map_or(None, |i| Some(i)))
self.get_str(k)
.map_or(None, |s| i64::from_str_radix(s, 16).map_or(None, |i| Some(i)))
}
pub fn get_bool(&self, k: &str) -> Option<bool> {
self.0.get(k).map_or(None, |v| v.first().map_or(Some(false), |c| Some(BOOL_TRUTH.contains(*c as char))))
self.0
.get(k)
.map_or(None, |v| v.first().map_or(Some(false), |c| Some(BOOL_TRUTH.contains(*c as char))))
}
pub fn set_str(&mut self, k: &str, v: &str) {
@ -238,7 +244,13 @@ mod tests {
match selection {
0 => d.set_str(&key, &randstring(10)),
1 => d.set_u64(&key, rand::random()),
2 => d.set_bytes(&key, (0..((rand::random::<usize>() % 10) + 1)).into_iter().map(|_| rand::random()).collect::<Vec<u8>>()),
2 => d.set_bytes(
&key,
(0..((rand::random::<usize>() % 10) + 1))
.into_iter()
.map(|_| rand::random())
.collect::<Vec<u8>>(),
),
3 => d.set_bool(&key, rand::random::<bool>()),
_ => unreachable!(),
}

View file

@ -190,19 +190,31 @@ impl Marshalable for Endpoint {
if type_byte < 16 {
if type_byte == 4 {
let b: &[u8; 6] = buf.read_bytes_fixed(cursor)?;
Ok(Endpoint::IpUdp(InetAddress::from_ip_port(&b[0..4], u16::from_be_bytes(b[4..6].try_into().unwrap()))))
Ok(Endpoint::IpUdp(InetAddress::from_ip_port(
&b[0..4],
u16::from_be_bytes(b[4..6].try_into().unwrap()),
)))
} else if type_byte == 6 {
let b: &[u8; 18] = buf.read_bytes_fixed(cursor)?;
Ok(Endpoint::IpUdp(InetAddress::from_ip_port(&b[0..16], u16::from_be_bytes(b[16..18].try_into().unwrap()))))
Ok(Endpoint::IpUdp(InetAddress::from_ip_port(
&b[0..16],
u16::from_be_bytes(b[16..18].try_into().unwrap()),
)))
} else {
Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "unrecognized endpoint type in stream"))
Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"unrecognized endpoint type in stream",
))
}
} else {
match type_byte - 16 {
TYPE_NIL => Ok(Endpoint::Nil),
TYPE_ZEROTIER => {
let zt = Address::unmarshal(buf, cursor)?;
Ok(Endpoint::ZeroTier(zt, buf.read_bytes_fixed::<IDENTITY_FINGERPRINT_SIZE>(cursor)?.clone()))
Ok(Endpoint::ZeroTier(
zt,
buf.read_bytes_fixed::<IDENTITY_FINGERPRINT_SIZE>(cursor)?.clone(),
))
}
TYPE_ETHERNET => Ok(Endpoint::Ethernet(MAC::unmarshal(buf, cursor)?)),
TYPE_WIFIDIRECT => Ok(Endpoint::WifiDirect(MAC::unmarshal(buf, cursor)?)),
@ -210,13 +222,20 @@ impl Marshalable for Endpoint {
TYPE_ICMP => Ok(Endpoint::Icmp(InetAddress::unmarshal(buf, cursor)?)),
TYPE_IPUDP => Ok(Endpoint::IpUdp(InetAddress::unmarshal(buf, cursor)?)),
TYPE_IPTCP => Ok(Endpoint::IpTcp(InetAddress::unmarshal(buf, cursor)?)),
TYPE_HTTP => Ok(Endpoint::Http(String::from_utf8_lossy(buf.read_bytes(buf.read_varint(cursor)? as usize, cursor)?).to_string())),
TYPE_WEBRTC => Ok(Endpoint::WebRTC(buf.read_bytes(buf.read_varint(cursor)? as usize, cursor)?.to_vec())),
TYPE_HTTP => Ok(Endpoint::Http(
String::from_utf8_lossy(buf.read_bytes(buf.read_varint(cursor)? as usize, cursor)?).to_string(),
)),
TYPE_WEBRTC => Ok(Endpoint::WebRTC(
buf.read_bytes(buf.read_varint(cursor)? as usize, cursor)?.to_vec(),
)),
TYPE_ZEROTIER_ENCAP => {
let zt = Address::unmarshal(buf, cursor)?;
Ok(Endpoint::ZeroTierEncap(zt, buf.read_bytes_fixed(cursor)?.clone()))
}
_ => Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "unrecognized endpoint type in stream")),
_ => Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"unrecognized endpoint type in stream",
)),
}
}
}
@ -342,7 +361,10 @@ impl FromStr for Endpoint {
if endpoint_type == "zt" {
return Ok(Endpoint::ZeroTier(Address::from_str(address)?, hash.as_slice().try_into().unwrap()));
} else {
return Ok(Endpoint::ZeroTierEncap(Address::from_str(address)?, hash.as_slice().try_into().unwrap()));
return Ok(Endpoint::ZeroTierEncap(
Address::from_str(address)?,
hash.as_slice().try_into().unwrap(),
));
}
}
}
@ -538,7 +560,11 @@ mod tests {
for _ in 0..1000 {
let mac = crate::vl1::MAC::from_u64(rand::random()).unwrap();
for e in [Endpoint::Ethernet(mac.clone()), Endpoint::WifiDirect(mac.clone()), Endpoint::Bluetooth(mac.clone())] {
for e in [
Endpoint::Ethernet(mac.clone()),
Endpoint::WifiDirect(mac.clone()),
Endpoint::Bluetooth(mac.clone()),
] {
let mut buf = Buffer::<7>::new();
let res = e.marshal(&mut buf);
@ -563,7 +589,11 @@ mod tests {
let inet = crate::vl1::InetAddress::from_ip_port(&v, 1234);
for e in [Endpoint::Icmp(inet.clone()), Endpoint::IpTcp(inet.clone()), Endpoint::IpUdp(inet.clone())] {
for e in [
Endpoint::Icmp(inet.clone()),
Endpoint::IpTcp(inet.clone()),
Endpoint::IpUdp(inet.clone()),
] {
let mut buf = Buffer::<20>::new();
let res = e.marshal(&mut buf);

View file

@ -75,7 +75,12 @@ fn concat_arrays_2<const A: usize, const B: usize, const S: usize>(a: &[u8; A],
}
#[inline(always)]
fn concat_arrays_4<const A: usize, const B: usize, const C: usize, const D: usize, const S: usize>(a: &[u8; A], b: &[u8; B], c: &[u8; C], d: &[u8; D]) -> [u8; S] {
fn concat_arrays_4<const A: usize, const B: usize, const C: usize, const D: usize, const S: usize>(
a: &[u8; A],
b: &[u8; B],
c: &[u8; C],
d: &[u8; D],
) -> [u8; S] {
assert_eq!(A + B + C + D, S);
let mut tmp = [0_u8; S];
tmp[..A].copy_from_slice(a);
@ -137,10 +142,19 @@ impl Identity {
pub const BYTE_LENGTH_X25519_SECRET: usize = Self::BYTE_LENGTH_X25519_PUBLIC + C25519_SECRET_KEY_SIZE + ED25519_SECRET_KEY_SIZE;
/// Length of a new dual-key public identity in byte array form.
pub const BYTE_LENGTH_X25519P384_PUBLIC: usize = Self::BYTE_LENGTH_X25519_PUBLIC + 1 + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE;
pub const BYTE_LENGTH_X25519P384_PUBLIC: usize = Self::BYTE_LENGTH_X25519_PUBLIC
+ 1
+ P384_PUBLIC_KEY_SIZE
+ P384_PUBLIC_KEY_SIZE
+ P384_ECDSA_SIGNATURE_SIZE
+ ED25519_SIGNATURE_SIZE;
/// Length of a new dual-key secret identity in byte array form.
pub const BYTE_LENGTH_X25519P384_SECRET: usize = Self::BYTE_LENGTH_X25519P384_PUBLIC + C25519_SECRET_KEY_SIZE + ED25519_SECRET_KEY_SIZE + P384_SECRET_KEY_SIZE + P384_SECRET_KEY_SIZE;
pub const BYTE_LENGTH_X25519P384_SECRET: usize = Self::BYTE_LENGTH_X25519P384_PUBLIC
+ C25519_SECRET_KEY_SIZE
+ ED25519_SECRET_KEY_SIZE
+ P384_SECRET_KEY_SIZE
+ P384_SECRET_KEY_SIZE;
const ALGORITHM_X25519: u8 = 0x01;
const ALGORITHM_EC_NIST_P384: u8 = 0x02;
@ -203,14 +217,23 @@ impl Identity {
/// It would be possible to change this in the future, with care.
pub fn upgrade(&mut self) -> Result<bool, InvalidParameterError> {
if self.secret.is_none() {
return Err(InvalidParameterError("an identity can only be upgraded if it includes its private key"));
return Err(InvalidParameterError(
"an identity can only be upgraded if it includes its private key",
));
}
if self.p384.is_none() {
let p384_ecdh = P384KeyPair::generate();
let p384_ecdsa = P384KeyPair::generate();
let mut self_sign_buf: Vec<u8> =
Vec::with_capacity(ADDRESS_SIZE + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + 4);
let mut self_sign_buf: Vec<u8> = Vec::with_capacity(
ADDRESS_SIZE
+ C25519_PUBLIC_KEY_SIZE
+ ED25519_PUBLIC_KEY_SIZE
+ P384_PUBLIC_KEY_SIZE
+ P384_PUBLIC_KEY_SIZE
+ P384_ECDSA_SIGNATURE_SIZE
+ 4,
);
let _ = self_sign_buf.write_all(&self.address.to_bytes());
let _ = self_sign_buf.write_all(&self.x25519);
let _ = self_sign_buf.write_all(&self.ed25519);
@ -233,7 +256,12 @@ impl Identity {
ecdsa_self_signature,
ed25519_self_signature,
});
let _ = self.secret.as_mut().unwrap().p384.insert(IdentityP384Secret { ecdh: p384_ecdh, ecdsa: p384_ecdsa });
let _ = self
.secret
.as_mut()
.unwrap()
.p384
.insert(IdentityP384Secret { ecdh: p384_ecdh, ecdsa: p384_ecdsa });
self.fingerprint = SHA384::hash(self.to_public_bytes().as_bytes());
@ -259,7 +287,9 @@ impl Identity {
/// This is somewhat time consuming due to the memory-intensive work algorithm.
pub fn validate_identity(&self) -> bool {
if let Some(p384) = self.p384.as_ref() {
let mut self_sign_buf: Vec<u8> = Vec::with_capacity(ADDRESS_SIZE + 4 + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE);
let mut self_sign_buf: Vec<u8> = Vec::with_capacity(
ADDRESS_SIZE + 4 + C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE,
);
let _ = self_sign_buf.write_all(&self.address.to_bytes());
let _ = self_sign_buf.write_all(&self.x25519);
let _ = self_sign_buf.write_all(&self.ed25519);
@ -469,7 +499,11 @@ impl Identity {
}
IdentityBytes::X25519Secret(b) => {
let b: &packed::V0S = bytes_as_flat_object(b);
if b.key_type == 0 && b.secret_length == (C25519_SECRET_KEY_SIZE + ED25519_SECRET_KEY_SIZE) as u8 && b.reserved == 0x03 && u16::from_be_bytes(b.ext_len) == 0 {
if b.key_type == 0
&& b.secret_length == (C25519_SECRET_KEY_SIZE + ED25519_SECRET_KEY_SIZE) as u8
&& b.reserved == 0x03
&& u16::from_be_bytes(b.ext_len) == 0
{
Some(Self {
address: Address::from_bytes_fixed(&b.address)?,
x25519: b.x25519,
@ -570,7 +604,12 @@ impl Identity {
};
IdentityBytes::try_from(&buf[..obj_len]).map_or_else(
|_| Err(std::io::Error::new(std::io::ErrorKind::Other, "invalid identity")),
|b| Identity::from_bytes(&b).map_or_else(|| Err(std::io::Error::new(std::io::ErrorKind::Other, "invalid identity")), |id| Ok(id)),
|b| {
Identity::from_bytes(&b).map_or_else(
|| Err(std::io::Error::new(std::io::ErrorKind::Other, "invalid identity")),
|id| Ok(id),
)
},
)
}
@ -594,14 +633,21 @@ impl Identity {
}
s.push_str(":2:"); // 2 == IDENTITY_ALGORITHM_EC_NIST_P384
let p384_joined: [u8; P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE] =
concat_arrays_4(p384.ecdh.as_bytes(), p384.ecdsa.as_bytes(), &p384.ecdsa_self_signature, &p384.ed25519_self_signature);
concat_arrays_4(
p384.ecdh.as_bytes(),
p384.ecdsa.as_bytes(),
&p384.ecdsa_self_signature,
&p384.ed25519_self_signature,
);
s.push_str(base64::encode_config(p384_joined, base64::URL_SAFE_NO_PAD).as_str());
if self.secret.is_some() && include_private {
let secret = self.secret.as_ref().unwrap();
if secret.p384.is_some() {
let p384_secret = secret.p384.as_ref().unwrap();
let p384_secret_joined: [u8; P384_SECRET_KEY_SIZE + P384_SECRET_KEY_SIZE] =
concat_arrays_2(p384_secret.ecdh.secret_key_bytes().as_bytes(), p384_secret.ecdsa.secret_key_bytes().as_bytes());
let p384_secret_joined: [u8; P384_SECRET_KEY_SIZE + P384_SECRET_KEY_SIZE] = concat_arrays_2(
p384_secret.ecdh.secret_key_bytes().as_bytes(),
p384_secret.ecdsa.secret_key_bytes().as_bytes(),
);
s.push(':');
s.push_str(base64::encode_config(p384_secret_joined, base64::URL_SAFE_NO_PAD).as_str());
}
@ -680,7 +726,9 @@ impl FromStr for Identity {
if keys[0].len() != C25519_PUBLIC_KEY_SIZE + ED25519_PUBLIC_KEY_SIZE {
return Err(InvalidFormatError);
}
if !keys[2].is_empty() && keys[2].len() != P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE {
if !keys[2].is_empty()
&& keys[2].len() != P384_PUBLIC_KEY_SIZE + P384_PUBLIC_KEY_SIZE + P384_ECDSA_SIGNATURE_SIZE + ED25519_SIGNATURE_SIZE
{
return Err(InvalidFormatError);
}
if !keys[3].is_empty() && keys[3].len() != P384_SECRET_KEY_SIZE + P384_SECRET_KEY_SIZE {
@ -710,10 +758,13 @@ impl FromStr for Identity {
Some(IdentityP384Public {
ecdh: ecdh.unwrap(),
ecdsa: ecdsa.unwrap(),
ecdsa_self_signature: keys[2].as_slice()[(P384_PUBLIC_KEY_SIZE * 2)..((P384_PUBLIC_KEY_SIZE * 2) + P384_ECDSA_SIGNATURE_SIZE)]
ecdsa_self_signature: keys[2].as_slice()
[(P384_PUBLIC_KEY_SIZE * 2)..((P384_PUBLIC_KEY_SIZE * 2) + P384_ECDSA_SIGNATURE_SIZE)]
.try_into()
.unwrap(),
ed25519_self_signature: keys[2].as_slice()[((P384_PUBLIC_KEY_SIZE * 2) + P384_ECDSA_SIGNATURE_SIZE)..]
.try_into()
.unwrap(),
ed25519_self_signature: keys[2].as_slice()[((P384_PUBLIC_KEY_SIZE * 2) + P384_ECDSA_SIGNATURE_SIZE)..].try_into().unwrap(),
})
},
secret: if keys[1].is_empty() {
@ -742,14 +793,20 @@ impl FromStr for Identity {
} else {
Some(IdentityP384Secret {
ecdh: {
let tmp = P384KeyPair::from_bytes(&keys[2].as_slice()[..P384_PUBLIC_KEY_SIZE], &keys[3].as_slice()[..P384_SECRET_KEY_SIZE]);
let tmp = P384KeyPair::from_bytes(
&keys[2].as_slice()[..P384_PUBLIC_KEY_SIZE],
&keys[3].as_slice()[..P384_SECRET_KEY_SIZE],
);
if tmp.is_none() {
return Err(InvalidFormatError);
}
tmp.unwrap()
},
ecdsa: {
let tmp = P384KeyPair::from_bytes(&keys[2].as_slice()[P384_PUBLIC_KEY_SIZE..(P384_PUBLIC_KEY_SIZE * 2)], &keys[3].as_slice()[P384_SECRET_KEY_SIZE..]);
let tmp = P384KeyPair::from_bytes(
&keys[2].as_slice()[P384_PUBLIC_KEY_SIZE..(P384_PUBLIC_KEY_SIZE * 2)],
&keys[3].as_slice()[P384_SECRET_KEY_SIZE..],
);
if tmp.is_none() {
return Err(InvalidFormatError);
}
@ -781,7 +838,9 @@ impl Eq for Identity {}
impl Ord for Identity {
#[inline(always)]
fn cmp(&self, other: &Self) -> Ordering {
self.address.cmp(&other.address).then_with(|| self.fingerprint.cmp(&other.fingerprint))
self.address
.cmp(&other.address)
.then_with(|| self.fingerprint.cmp(&other.fingerprint))
}
}
@ -973,7 +1032,8 @@ mod tests {
#[test]
fn v0_identity() {
let self_agree_expected = hex::from_string("de904fc90ff3a2b96b739b926e623113f5334c80841b654509b77916c4c4a6eb0ca69ec6ed01a7f04aee17c546b30ba4");
let self_agree_expected =
hex::from_string("de904fc90ff3a2b96b739b926e623113f5334c80841b654509b77916c4c4a6eb0ca69ec6ed01a7f04aee17c546b30ba4");
// Test self-agree with a known good x25519-only (v0) identity.
let id = Identity::from_str(
@ -1020,7 +1080,11 @@ mod tests {
let gen_unmarshaled = Identity::from_bytes(&bytes).unwrap();
assert!(gen_unmarshaled.secret.is_some());
if !gen_unmarshaled.eq(&gen) {
println!("{} != {}", hex::to_string(&gen_unmarshaled.fingerprint), hex::to_string(&gen.fingerprint));
println!(
"{} != {}",
hex::to_string(&gen_unmarshaled.fingerprint),
hex::to_string(&gen.fingerprint)
);
}
assert!(Identity::from_str(string.as_str()).unwrap().secret.is_some());

View file

@ -82,8 +82,10 @@ impl ToSocketAddrs for InetAddress {
#[inline(always)]
fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
self.try_into()
.map_or_else(|_| Err(std::io::Error::new(std::io::ErrorKind::Other, "not an IP address")), |sa| Ok(std::iter::once(sa)))
self.try_into().map_or_else(
|_| Err(std::io::Error::new(std::io::ErrorKind::Other, "not an IP address")),
|sa| Ok(std::iter::once(sa)),
)
}
}
@ -199,7 +201,10 @@ impl TryInto<SocketAddrV4> for &InetAddress {
fn try_into(self) -> Result<SocketAddrV4, Self::Error> {
unsafe {
match self.sa.sa_family {
AF_INET => Ok(SocketAddrV4::new(Ipv4Addr::from(self.sin.sin_addr.s_addr.to_ne_bytes()), u16::from_be(self.sin.sin_port as u16))),
AF_INET => Ok(SocketAddrV4::new(
Ipv4Addr::from(self.sin.sin_addr.s_addr.to_ne_bytes()),
u16::from_be(self.sin.sin_port as u16),
)),
_ => Err(crate::error::InvalidParameterError("not an IPv4 address")),
}
}
@ -222,7 +227,12 @@ impl TryInto<SocketAddrV6> for &InetAddress {
fn try_into(self) -> Result<SocketAddrV6, Self::Error> {
unsafe {
match self.sa.sa_family {
AF_INET6 => Ok(SocketAddrV6::new(Ipv6Addr::from(self.sin6.sin6_addr.s6_addr), u16::from_be(self.sin6.sin6_port as u16), 0, 0)),
AF_INET6 => Ok(SocketAddrV6::new(
Ipv6Addr::from(self.sin6.sin6_addr.s6_addr),
u16::from_be(self.sin6.sin6_port as u16),
0,
0,
)),
_ => Err(crate::error::InvalidParameterError("not an IPv6 address")),
}
}
@ -597,7 +607,9 @@ impl InetAddress {
AF_INET => {
if cidr_bits <= 32 {
let discard_bits = 32 - cidr_bits;
if u32::from_be(self.sin.sin_addr.s_addr as u32).wrapping_shr(discard_bits) == u32::from_be(cidr.sin.sin_addr.s_addr as u32).wrapping_shr(discard_bits) {
if u32::from_be(self.sin.sin_addr.s_addr as u32).wrapping_shr(discard_bits)
== u32::from_be(cidr.sin.sin_addr.s_addr as u32).wrapping_shr(discard_bits)
{
return true;
}
}
@ -784,7 +796,11 @@ impl Marshalable for InetAddress {
AF_INET6 => {
let b = buf.append_bytes_fixed_get_mut::<19>()?;
b[0] = 6;
copy_nonoverlapping((&(self.sin6.sin6_addr) as *const in6_addr).cast::<u8>(), b.as_mut_ptr().offset(1), 16);
copy_nonoverlapping(
(&(self.sin6.sin6_addr) as *const in6_addr).cast::<u8>(),
b.as_mut_ptr().offset(1),
16,
);
b[17] = *(&self.sin6.sin6_port as *const u16).cast::<u8>();
b[18] = *(&self.sin6.sin6_port as *const u16).cast::<u8>().offset(1);
Ok(())
@ -801,7 +817,10 @@ impl Marshalable for InetAddress {
Ok(InetAddress::from_ip_port(&b[0..4], u16::from_be_bytes(b[4..6].try_into().unwrap())))
} else if t == 6 {
let b: &[u8; 18] = buf.read_bytes_fixed(cursor)?;
Ok(InetAddress::from_ip_port(&b[0..16], u16::from_be_bytes(b[16..18].try_into().unwrap())))
Ok(InetAddress::from_ip_port(
&b[0..16],
u16::from_be_bytes(b[16..18].try_into().unwrap()),
))
} else {
Ok(InetAddress::new())
}
@ -880,7 +899,8 @@ impl PartialEq for InetAddress {
AF_INET => self.sin.sin_port == other.sin.sin_port && self.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr,
AF_INET6 => {
if self.sin6.sin6_port == other.sin6.sin6_port {
(*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>()).eq(&*(&(other.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>())
(*(&(self.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>())
.eq(&*(&(other.sin6.sin6_addr) as *const in6_addr).cast::<[u8; 16]>())
} else {
false
}
@ -912,7 +932,8 @@ impl Ord for InetAddress {
match self.sa.sa_family as AddressFamilyType {
0 => Ordering::Equal,
AF_INET => {
let ip_ordering = u32::from_be(self.sin.sin_addr.s_addr as u32).cmp(&u32::from_be(other.sin.sin_addr.s_addr as u32));
let ip_ordering =
u32::from_be(self.sin.sin_addr.s_addr as u32).cmp(&u32::from_be(other.sin.sin_addr.s_addr as u32));
if ip_ordering == Ordering::Equal {
u16::from_be(self.sin.sin_port as u16).cmp(&u16::from_be(other.sin.sin_port as u16))
} else {
@ -931,7 +952,8 @@ impl Ord for InetAddress {
}
_ => {
// This shouldn't be possible, but handle it for correctness.
(*slice_from_raw_parts((self as *const Self).cast::<u8>(), size_of::<Self>())).cmp(&*slice_from_raw_parts((other as *const Self).cast::<u8>(), size_of::<Self>()))
(*slice_from_raw_parts((self as *const Self).cast::<u8>(), size_of::<Self>()))
.cmp(&*slice_from_raw_parts((other as *const Self).cast::<u8>(), size_of::<Self>()))
}
}
} else {

View file

@ -33,7 +33,15 @@ impl MAC {
#[inline(always)]
pub fn from_bytes(b: &[u8]) -> Option<MAC> {
if b.len() >= 6 {
NonZeroU64::new((b[0] as u64) << 40 | (b[1] as u64) << 32 | (b[2] as u64) << 24 | (b[3] as u64) << 16 as u64 | (b[4] as u64) << 8 | b[5] as u64).map(|i| MAC(i))
NonZeroU64::new(
(b[0] as u64) << 40
| (b[1] as u64) << 32
| (b[2] as u64) << 24
| (b[3] as u64) << 16 as u64
| (b[4] as u64) << 8
| b[5] as u64,
)
.map(|i| MAC(i))
} else {
None
}
@ -41,13 +49,23 @@ impl MAC {
#[inline(always)]
pub fn from_bytes_fixed(b: &[u8; 6]) -> Option<MAC> {
NonZeroU64::new((b[0] as u64) << 40 | (b[1] as u64) << 32 | (b[2] as u64) << 24 | (b[3] as u64) << 16 as u64 | (b[4] as u64) << 8 | b[5] as u64).map(|i| MAC(i))
NonZeroU64::new(
(b[0] as u64) << 40 | (b[1] as u64) << 32 | (b[2] as u64) << 24 | (b[3] as u64) << 16 as u64 | (b[4] as u64) << 8 | b[5] as u64,
)
.map(|i| MAC(i))
}
#[inline(always)]
pub fn to_bytes(&self) -> [u8; 6] {
let i = self.0.get();
[(i >> 40) as u8, (i >> 32) as u8, (i >> 24) as u8, (i >> 16) as u8, (i >> 8) as u8, i as u8]
[
(i >> 40) as u8,
(i >> 32) as u8,
(i >> 24) as u8,
(i >> 16) as u8,
(i >> 8) as u8,
i as u8,
]
}
}
@ -75,14 +93,20 @@ impl Marshalable for MAC {
#[inline(always)]
fn unmarshal<const BL: usize>(buf: &Buffer<BL>, cursor: &mut usize) -> std::io::Result<Self> {
Self::from_bytes_fixed(buf.read_bytes_fixed(cursor)?).map_or_else(|| Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "cannot be zero")), |a| Ok(a))
Self::from_bytes_fixed(buf.read_bytes_fixed(cursor)?).map_or_else(
|| Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "cannot be zero")),
|a| Ok(a),
)
}
}
impl ToString for MAC {
fn to_string(&self) -> String {
let b: [u8; 6] = self.to_bytes();
format!("{:0>2x}:{:0>2x}:{:0>2x}:{:0>2x}:{:0>2x}:{:0>2x}", b[0], b[1], b[2], b[3], b[4], b[5])
format!(
"{:0>2x}:{:0>2x}:{:0>2x}:{:0>2x}:{:0>2x}:{:0>2x}",
b[0], b[1], b[2], b[3], b[4], b[5]
)
}
}

View file

@ -70,10 +70,23 @@ pub trait SystemInterface: Sync + Send + 'static {
/// For endpoint types that support a packet TTL, the implementation may set the TTL
/// if the 'ttl' parameter is not zero. If the parameter is zero or TTL setting is not
/// supported, the default TTL should be used.
async fn wire_send(&self, endpoint: &Endpoint, local_socket: Option<&Self::LocalSocket>, local_interface: Option<&Self::LocalInterface>, data: &[&[u8]], packet_ttl: u8) -> bool;
async fn wire_send(
&self,
endpoint: &Endpoint,
local_socket: Option<&Self::LocalSocket>,
local_interface: Option<&Self::LocalInterface>,
data: &[&[u8]],
packet_ttl: u8,
) -> bool;
/// Called to check and see if a physical address should be used for ZeroTier traffic to a node.
async fn check_path(&self, id: &Identity, endpoint: &Endpoint, local_socket: Option<&Self::LocalSocket>, local_interface: Option<&Self::LocalInterface>) -> bool;
async fn check_path(
&self,
id: &Identity,
endpoint: &Endpoint,
local_socket: Option<&Self::LocalSocket>,
local_interface: Option<&Self::LocalInterface>,
) -> bool;
/// Called to look up any statically defined or memorized paths to known nodes.
async fn get_path_hints(&self, id: &Identity) -> Option<Vec<(Endpoint, Option<Self::LocalSocket>, Option<Self::LocalInterface>)>>;
@ -96,7 +109,8 @@ pub trait InnerProtocolInterface: Sync + Send + 'static {
/// Handle a packet, returning true if it was handled by the next layer.
///
/// Do not attempt to handle OK or ERROR. Instead implement handle_ok() and handle_error().
async fn handle_packet<SI: SystemInterface>(&self, source: &Peer<SI>, source_path: &Path<SI>, verb: u8, payload: &PacketBuffer) -> bool;
async fn handle_packet<SI: SystemInterface>(&self, source: &Peer<SI>, source_path: &Path<SI>, verb: u8, payload: &PacketBuffer)
-> bool;
/// Handle errors, returning true if the error was recognized.
async fn handle_error<SI: SystemInterface>(
@ -111,7 +125,15 @@ pub trait InnerProtocolInterface: Sync + Send + 'static {
) -> bool;
/// Handle an OK, returing true if the OK was recognized.
async fn handle_ok<SI: SystemInterface>(&self, source: &Peer<SI>, source_path: &Path<SI>, in_re_verb: u8, in_re_message_id: u64, payload: &PacketBuffer, cursor: &mut usize) -> bool;
async fn handle_ok<SI: SystemInterface>(
&self,
source: &Peer<SI>,
source_path: &Path<SI>,
in_re_verb: u8,
in_re_message_id: u64,
payload: &PacketBuffer,
cursor: &mut usize,
) -> bool;
/// Check if this peer should communicate with another at all.
fn should_communicate_with(&self, id: &Identity) -> bool;
@ -298,7 +320,12 @@ impl<SI: SystemInterface> Node<SI> {
let mut best_root = self.best_root.write();
if let Some(best_root) = best_root.as_mut() {
if !Arc::ptr_eq(best_root, best) {
debug_event!(si, "[vl1] new best root: {} (replaced {})", best.identity.address.to_string(), best_root.identity.address.to_string());
debug_event!(
si,
"[vl1] new best root: {} (replaced {})",
best.identity.address.to_string(),
best_root.identity.address.to_string()
);
*best_root = best.clone();
}
} else {
@ -409,8 +436,14 @@ impl<SI: SystemInterface> Node<SI> {
for m in rs.members.iter() {
if m.identity.eq(&self.identity) {
let _ = my_root_sets.get_or_insert_with(|| Vec::new()).write_all(rs.to_bytes().as_slice());
} else if self.peers.read().get(&m.identity.address).map_or(false, |p| !p.identity.eq(&m.identity))
|| address_collision_check.insert(m.identity.address, &m.identity).map_or(false, |old_id| !old_id.eq(&m.identity))
} else if self
.peers
.read()
.get(&m.identity.address)
.map_or(false, |p| !p.identity.eq(&m.identity))
|| address_collision_check
.insert(m.identity.address, &m.identity)
.map_or(false, |old_id| !old_id.eq(&m.identity))
{
address_collisions.push(m.identity.address);
}
@ -420,7 +453,8 @@ impl<SI: SystemInterface> Node<SI> {
for (_, rs) in roots.sets.iter() {
for m in rs.members.iter() {
if m.endpoints.is_some() && !address_collisions.contains(&m.identity.address) && !m.identity.eq(&self.identity) {
if m.endpoints.is_some() && !address_collisions.contains(&m.identity.address) && !m.identity.eq(&self.identity)
{
debug_event!(
si,
"[vl1] examining root {} with {} endpoints",
@ -493,7 +527,12 @@ impl<SI: SystemInterface> Node<SI> {
};
for (root, endpoints) in roots.iter() {
for ep in endpoints.iter() {
debug_event!(si, "sending HELLO to root {} (root interval: {})", root.identity.address.to_string(), ROOT_HELLO_INTERVAL);
debug_event!(
si,
"sending HELLO to root {} (root interval: {})",
root.identity.address.to_string(),
ROOT_HELLO_INTERVAL
);
root.send_hello(si, self, Some(ep)).await;
}
}
@ -538,7 +577,8 @@ impl<SI: SystemInterface> Node<SI> {
let ka = [tt as u8]; // send different bytes every time for keepalive in case some things filter zero packets
let ka2 = [&ka[..1]];
for ka in need_keepalive.iter() {
si.wire_send(&ka.endpoint, Some(&ka.local_socket), Some(&ka.local_interface), &ka2, 0).await;
si.wire_send(&ka.endpoint, Some(&ka.local_socket), Some(&ka.local_interface), &ka2, 0)
.await;
}
}
@ -563,7 +603,8 @@ impl<SI: SystemInterface> Node<SI> {
si,
"[vl1] {} -> #{} {}->{} length {} (on socket {}@{})",
source_endpoint.to_string(),
data.bytes_fixed_at::<8>(0).map_or("????????????????".into(), |pid| hex::to_string(pid)),
data.bytes_fixed_at::<8>(0)
.map_or("????????????????".into(), |pid| hex::to_string(pid)),
data.bytes_fixed_at::<5>(13).map_or("??????????".into(), |src| hex::to_string(src)),
data.bytes_fixed_at::<5>(8).map_or("??????????".into(), |dest| hex::to_string(dest)),
data.len(),
@ -589,7 +630,13 @@ impl<SI: SystemInterface> Node<SI> {
fragment_header.total_fragments()
);
if let Some(assembled_packet) = path.receive_fragment(fragment_header.packet_id(), fragment_header.fragment_no(), fragment_header.total_fragments(), data, time_ticks) {
if let Some(assembled_packet) = path.receive_fragment(
fragment_header.packet_id(),
fragment_header.fragment_no(),
fragment_header.total_fragments(),
data,
time_ticks,
) {
if let Some(frag0) = assembled_packet.frags[0].as_ref() {
#[cfg(debug_assertions)]
debug_event!(si, "[vl1] #{:0>16x} packet fully assembled!", fragment_header_id);
@ -597,7 +644,16 @@ impl<SI: SystemInterface> Node<SI> {
if let Ok(packet_header) = frag0.struct_at::<v1::PacketHeader>(0) {
if let Some(source) = Address::from_bytes(&packet_header.src) {
if let Some(peer) = self.peer(source) {
peer.receive(self, si, ph, time_ticks, &path, packet_header, frag0, &assembled_packet.frags[1..(assembled_packet.have as usize)])
peer.receive(
self,
si,
ph,
time_ticks,
&path,
packet_header,
frag0,
&assembled_packet.frags[1..(assembled_packet.have as usize)],
)
.await;
} else {
self.whois.query(self, si, source, Some(QueuedPacket::Fragmented(assembled_packet)));
@ -613,7 +669,8 @@ impl<SI: SystemInterface> Node<SI> {
if let Some(source) = Address::from_bytes(&packet_header.src) {
if let Some(peer) = self.peer(source) {
peer.receive(self, si, ph, time_ticks, &path, packet_header, data.as_ref(), &[]).await;
peer.receive(self, si, ph, time_ticks, &path, packet_header, data.as_ref(), &[])
.await;
} else {
self.whois.query(self, si, source, Some(QueuedPacket::Unfragmented(data)));
}
@ -628,7 +685,12 @@ impl<SI: SystemInterface> Node<SI> {
#[cfg(debug_assertions)]
{
debug_packet_id = u64::from_be_bytes(fragment_header.id);
debug_event!(si, "[vl1] #{:0>16x} forwarding packet fragment to {}", debug_packet_id, dest.to_string());
debug_event!(
si,
"[vl1] #{:0>16x} forwarding packet fragment to {}",
debug_packet_id,
dest.to_string()
);
}
if fragment_header.increment_hops() > v1::FORWARD_MAX_HOPS {
#[cfg(debug_assertions)]
@ -644,7 +706,11 @@ impl<SI: SystemInterface> Node<SI> {
}
if packet_header.increment_hops() > v1::FORWARD_MAX_HOPS {
#[cfg(debug_assertions)]
debug_event!(si, "[vl1] #{:0>16x} discarded: max hops exceeded!", u64::from_be_bytes(packet_header.id));
debug_event!(
si,
"[vl1] #{:0>16x} discarded: max hops exceeded!",
u64::from_be_bytes(packet_header.id)
);
return;
}
} else {
@ -714,7 +780,13 @@ impl<SI: SystemInterface> Node<SI> {
self.roots.read().my_root_sets.is_some()
}
pub(crate) fn canonical_path(&self, ep: &Endpoint, local_socket: &SI::LocalSocket, local_interface: &SI::LocalInterface, time_ticks: i64) -> Arc<Path<SI>> {
pub(crate) fn canonical_path(
&self,
ep: &Endpoint,
local_socket: &SI::LocalSocket,
local_interface: &SI::LocalInterface,
time_ticks: i64,
) -> Arc<Path<SI>> {
if let Some(path) = self.paths.read().get(&PathKey::Ref(ep, local_socket)) {
return path.clone();
}

View file

@ -50,7 +50,14 @@ impl<SI: SystemInterface> Path<SI> {
/// Receive a fragment and return a FragmentedPacket if the entire packet was assembled.
/// This returns None if more fragments are needed to assemble the packet.
pub(crate) fn receive_fragment(&self, packet_id: PacketId, fragment_no: u8, fragment_expecting_count: u8, packet: PooledPacketBuffer, time_ticks: i64) -> Option<FragmentedPacket> {
pub(crate) fn receive_fragment(
&self,
packet_id: PacketId,
fragment_no: u8,
fragment_expecting_count: u8,
packet: PooledPacketBuffer,
time_ticks: i64,
) -> Option<FragmentedPacket> {
let mut fp = self.fragmented_packets.lock();
// Discard some old waiting packets if the total incoming fragments for a path exceeds a
@ -90,7 +97,9 @@ impl<SI: SystemInterface> Path<SI> {
}
pub(crate) fn service(&self, time_ticks: i64) -> PathServiceResult {
self.fragmented_packets.lock().retain(|_, frag| (time_ticks - frag.ts_ticks) < v1::FRAGMENT_EXPIRATION);
self.fragmented_packets
.lock()
.retain(|_, frag| (time_ticks - frag.ts_ticks) < v1::FRAGMENT_EXPIRATION);
if (time_ticks - self.last_receive_time_ticks.load(Ordering::Relaxed)) < PATH_EXPIRATION_TIME {
if (time_ticks - self.last_send_time_ticks.load(Ordering::Relaxed)) >= PATH_KEEPALIVE_INTERVAL {
self.last_send_time_ticks.store(time_ticks, Ordering::Relaxed);

View file

@ -210,7 +210,12 @@ impl<SI: SystemInterface> Peer<SI> {
pub fn version(&self) -> Option<[u16; 4]> {
let rv = self.remote_node_info.read().remote_version;
if rv != 0 {
Some([rv.wrapping_shr(48) as u16, rv.wrapping_shr(32) as u16, rv.wrapping_shr(16) as u16, rv as u16])
Some([
rv.wrapping_shr(48) as u16,
rv.wrapping_shr(32) as u16,
rv.wrapping_shr(16) as u16,
rv as u16,
])
} else {
None
}
@ -299,7 +304,12 @@ impl<SI: SystemInterface> Peer<SI> {
}
// Learn new path if it's not a duplicate or should not replace an existing path.
debug_event!(si, "[vl1] {} learned new path: {}", self.identity.address.to_string(), new_path.endpoint.to_string());
debug_event!(
si,
"[vl1] {} learned new path: {}",
self.identity.address.to_string(),
new_path.endpoint.to_string()
);
paths.push(PeerPath::<SI> {
path: Arc::downgrade(new_path),
last_receive_time_ticks: time_ticks,
@ -314,7 +324,10 @@ impl<SI: SystemInterface> Peer<SI> {
paths.retain(|p| ((time_ticks - p.last_receive_time_ticks) < PEER_EXPIRATION_TIME) && (p.path.strong_count() > 0));
prioritize_paths(&mut paths);
}
self.remote_node_info.write().reported_local_endpoints.retain(|_, ts| (time_ticks - *ts) < PEER_EXPIRATION_TIME);
self.remote_node_info
.write()
.reported_local_endpoints
.retain(|_, ts| (time_ticks - *ts) < PEER_EXPIRATION_TIME);
(time_ticks - self.last_receive_time_ticks.load(Ordering::Relaxed).max(self.create_time_ticks)) < PEER_EXPIRATION_TIME
}
@ -334,13 +347,17 @@ impl<SI: SystemInterface> Peer<SI> {
let packet_size = packet.len();
if packet_size > max_fragment_size {
let bytes = packet.as_bytes();
if !si.wire_send(endpoint, local_socket, local_interface, &[&bytes[0..UDP_DEFAULT_MTU]], 0).await {
if !si
.wire_send(endpoint, local_socket, local_interface, &[&bytes[0..UDP_DEFAULT_MTU]], 0)
.await
{
return false;
}
let mut pos = UDP_DEFAULT_MTU;
let overrun_size = (packet_size - UDP_DEFAULT_MTU) as u32;
let fragment_count = (overrun_size / (UDP_DEFAULT_MTU - v1::FRAGMENT_HEADER_SIZE) as u32) + (((overrun_size % (UDP_DEFAULT_MTU - v1::FRAGMENT_HEADER_SIZE) as u32) != 0) as u32);
let fragment_count = (overrun_size / (UDP_DEFAULT_MTU - v1::FRAGMENT_HEADER_SIZE) as u32)
+ (((overrun_size % (UDP_DEFAULT_MTU - v1::FRAGMENT_HEADER_SIZE) as u32) != 0) as u32);
debug_assert!(fragment_count <= v1::FRAGMENT_COUNT_MAX as u32);
let mut header = v1::FragmentHeader {
@ -355,7 +372,16 @@ impl<SI: SystemInterface> Peer<SI> {
loop {
header.total_and_fragment_no += 1;
let next_pos = pos + chunk_size;
if !si.wire_send(endpoint, local_socket, local_interface, &[header.as_bytes(), &bytes[pos..next_pos]], 0).await {
if !si
.wire_send(
endpoint,
local_socket,
local_interface,
&[header.as_bytes(), &bytes[pos..next_pos]],
0,
)
.await
{
return false;
}
pos = next_pos;
@ -376,7 +402,14 @@ impl<SI: SystemInterface> Peer<SI> {
/// via a root or some other route.
///
/// It encrypts and sets the MAC and cipher fields and packet ID and other things.
pub(crate) async fn send(&self, si: &SI, path: Option<&Arc<Path<SI>>>, node: &Node<SI>, time_ticks: i64, packet: &mut PacketBuffer) -> bool {
pub(crate) async fn send(
&self,
si: &SI,
path: Option<&Arc<Path<SI>>>,
node: &Node<SI>,
time_ticks: i64,
packet: &mut PacketBuffer,
) -> bool {
let mut _path_arc = None;
let path = if let Some(path) = path {
path
@ -402,7 +435,11 @@ impl<SI: SystemInterface> Peer<SI> {
let mut aes_gmac_siv = self.identity_symmetric_key.aes_gmac_siv.get();
aes_gmac_siv.encrypt_init(&self.next_message_id().to_ne_bytes());
aes_gmac_siv.encrypt_set_aad(&v1::get_packet_aad_bytes(self.identity.address, node.identity.address, flags_cipher_hops));
aes_gmac_siv.encrypt_set_aad(&v1::get_packet_aad_bytes(
self.identity.address,
node.identity.address,
flags_cipher_hops,
));
if let Ok(payload) = packet.as_bytes_starting_at_mut(v1::HEADER_SIZE) {
aes_gmac_siv.encrypt_first_pass(payload);
aes_gmac_siv.encrypt_first_pass_finish();
@ -419,7 +456,14 @@ impl<SI: SystemInterface> Peer<SI> {
}
if self
.internal_send(si, &path.endpoint, Some(&path.local_socket), Some(&path.local_interface), max_fragment_size, packet)
.internal_send(
si,
&path.endpoint,
Some(&path.local_socket),
Some(&path.local_interface),
max_fragment_size,
packet,
)
.await
{
self.last_send_time_ticks.store(time_ticks, Ordering::Relaxed);
@ -438,7 +482,16 @@ impl<SI: SystemInterface> Peer<SI> {
/// Intermediates don't need to adjust fragmentation.
pub(crate) async fn forward(&self, si: &SI, time_ticks: i64, packet: &PacketBuffer) -> bool {
if let Some(path) = self.direct_path() {
if si.wire_send(&path.endpoint, Some(&path.local_socket), Some(&path.local_interface), &[packet.as_bytes()], 0).await {
if si
.wire_send(
&path.endpoint,
Some(&path.local_socket),
Some(&path.local_interface),
&[packet.as_bytes()],
0,
)
.await
{
self.last_forward_time_ticks.store(time_ticks, Ordering::Relaxed);
return true;
}
@ -479,7 +532,8 @@ impl<SI: SystemInterface> Peer<SI> {
let message_id = self.next_message_id();
{
let f: &mut (v1::PacketHeader, v1::message_component_structs::HelloFixedHeaderFields) = packet.append_struct_get_mut().unwrap();
let f: &mut (v1::PacketHeader, v1::message_component_structs::HelloFixedHeaderFields) =
packet.append_struct_get_mut().unwrap();
f.0.id = message_id.to_ne_bytes();
f.0.dest = self.identity.address.to_bytes();
f.0.src = node.identity.address.to_bytes();
@ -495,17 +549,37 @@ impl<SI: SystemInterface> Peer<SI> {
debug_assert_eq!(packet.len(), 41);
assert!(packet.append_bytes((&node.identity.to_public_bytes()).into()).is_ok());
let (_, poly1305_key) = salsa_poly_create(&self.identity_symmetric_key, packet.struct_at::<v1::PacketHeader>(0).unwrap(), packet.len());
let (_, poly1305_key) = salsa_poly_create(
&self.identity_symmetric_key,
packet.struct_at::<v1::PacketHeader>(0).unwrap(),
packet.len(),
);
let mac = poly1305::compute(&poly1305_key, packet.as_bytes_starting_at(v1::HEADER_SIZE).unwrap());
packet.as_mut()[v1::MAC_FIELD_INDEX..v1::MAC_FIELD_INDEX + 8].copy_from_slice(&mac[0..8]);
self.last_send_time_ticks.store(time_ticks, Ordering::Relaxed);
debug_event!(si, "HELLO -> {} @ {} ({} bytes)", self.identity.address.to_string(), destination.to_string(), packet.len());
debug_event!(
si,
"HELLO -> {} @ {} ({} bytes)",
self.identity.address.to_string(),
destination.to_string(),
packet.len()
);
}
if let Some(p) = path.as_ref() {
if self.internal_send(si, destination, Some(&p.local_socket), Some(&p.local_interface), max_fragment_size, &packet).await {
if self
.internal_send(
si,
destination,
Some(&p.local_socket),
Some(&p.local_interface),
max_fragment_size,
&packet,
)
.await
{
p.log_send_anything(time_ticks);
true
} else {
@ -536,7 +610,13 @@ impl<SI: SystemInterface> Peer<SI> {
if let Ok(packet_frag0_payload_bytes) = frag0.as_bytes_starting_at(v1::VERB_INDEX) {
let mut payload = PacketBuffer::new();
let message_id = if let Some(message_id2) = try_aead_decrypt(&self.identity_symmetric_key, packet_frag0_payload_bytes, packet_header, fragments, &mut payload) {
let message_id = if let Some(message_id2) = try_aead_decrypt(
&self.identity_symmetric_key,
packet_frag0_payload_bytes,
packet_header,
fragments,
&mut payload,
) {
// Decryption successful with static secret.
message_id2
} else {
@ -582,13 +662,25 @@ impl<SI: SystemInterface> Peer<SI> {
if match verb {
verbs::VL1_NOP => true,
verbs::VL1_HELLO => self.handle_incoming_hello(si, ph, node, time_ticks, message_id, source_path, packet_header.hops(), &payload).await,
verbs::VL1_HELLO => {
self.handle_incoming_hello(si, ph, node, time_ticks, message_id, source_path, packet_header.hops(), &payload)
.await
}
verbs::VL1_ERROR => self.handle_incoming_error(si, ph, node, time_ticks, source_path, &payload).await,
verbs::VL1_OK => self.handle_incoming_ok(si, ph, node, time_ticks, source_path, packet_header.hops(), path_is_known, &payload).await,
verbs::VL1_OK => {
self.handle_incoming_ok(si, ph, node, time_ticks, source_path, packet_header.hops(), path_is_known, &payload)
.await
}
verbs::VL1_WHOIS => self.handle_incoming_whois(si, ph, node, time_ticks, message_id, &payload).await,
verbs::VL1_RENDEZVOUS => self.handle_incoming_rendezvous(si, node, time_ticks, message_id, source_path, &payload).await,
verbs::VL1_RENDEZVOUS => {
self.handle_incoming_rendezvous(si, node, time_ticks, message_id, source_path, &payload)
.await
}
verbs::VL1_ECHO => self.handle_incoming_echo(si, ph, node, time_ticks, message_id, &payload).await,
verbs::VL1_PUSH_DIRECT_PATHS => self.handle_incoming_push_direct_paths(si, node, time_ticks, source_path, &payload).await,
verbs::VL1_PUSH_DIRECT_PATHS => {
self.handle_incoming_push_direct_paths(si, node, time_ticks, source_path, &payload)
.await
}
verbs::VL1_USER_MESSAGE => self.handle_incoming_user_message(si, node, time_ticks, source_path, &payload).await,
_ => ph.handle_packet(self, &source_path, verb, &payload).await,
} {
@ -614,7 +706,11 @@ impl<SI: SystemInterface> Peer<SI> {
payload: &PacketBuffer,
) -> bool {
if !(ph.should_communicate_with(&self.identity) || node.this_node_is_root() || node.is_peer_root(self)) {
debug_event!(si, "[vl1] dropping HELLO from {} due to lack of trust relationship", self.identity.address.to_string());
debug_event!(
si,
"[vl1] dropping HELLO from {} due to lack of trust relationship",
self.identity.address.to_string()
);
return true; // packet wasn't invalid, just ignored
}
@ -633,7 +729,10 @@ impl<SI: SystemInterface> Peer<SI> {
let mut packet = PacketBuffer::new();
packet.set_size(v1::HEADER_SIZE);
{
let f: &mut (v1::message_component_structs::OkHeader, v1::message_component_structs::OkHelloFixedHeaderFields) = packet.append_struct_get_mut().unwrap();
let f: &mut (
v1::message_component_structs::OkHeader,
v1::message_component_structs::OkHelloFixedHeaderFields,
) = packet.append_struct_get_mut().unwrap();
f.0.verb = verbs::VL1_OK;
f.0.in_re_verb = verbs::VL1_HELLO;
f.0.in_re_message_id = message_id.to_ne_bytes();
@ -651,7 +750,15 @@ impl<SI: SystemInterface> Peer<SI> {
return false;
}
async fn handle_incoming_error<PH: InnerProtocolInterface>(&self, _si: &SI, ph: &PH, _node: &Node<SI>, _time_ticks: i64, source_path: &Arc<Path<SI>>, payload: &PacketBuffer) -> bool {
async fn handle_incoming_error<PH: InnerProtocolInterface>(
&self,
_si: &SI,
ph: &PH,
_node: &Node<SI>,
_time_ticks: i64,
source_path: &Arc<Path<SI>>,
payload: &PacketBuffer,
) -> bool {
let mut cursor = 0;
if let Ok(error_header) = payload.read_struct::<v1::message_component_structs::ErrorHeader>(&mut cursor) {
let in_re_message_id: MessageId = u64::from_ne_bytes(error_header.in_re_message_id);
@ -659,7 +766,15 @@ impl<SI: SystemInterface> Peer<SI> {
match error_header.in_re_verb {
_ => {
return ph
.handle_error(self, &source_path, error_header.in_re_verb, in_re_message_id, error_header.error_code, payload, &mut cursor)
.handle_error(
self,
&source_path,
error_header.in_re_verb,
in_re_message_id,
error_header.error_code,
payload,
&mut cursor,
)
.await;
}
}
@ -685,12 +800,20 @@ impl<SI: SystemInterface> Peer<SI> {
if self.message_id_counter.load(Ordering::Relaxed).wrapping_sub(in_re_message_id) <= PACKET_RESPONSE_COUNTER_DELTA_MAX {
match ok_header.in_re_verb {
verbs::VL1_HELLO => {
if let Ok(ok_hello_fixed_header_fields) = payload.read_struct::<v1::message_component_structs::OkHelloFixedHeaderFields>(&mut cursor) {
if let Ok(ok_hello_fixed_header_fields) =
payload.read_struct::<v1::message_component_structs::OkHelloFixedHeaderFields>(&mut cursor)
{
if hops == 0 {
if let Ok(reported_endpoint) = Endpoint::unmarshal(&payload, &mut cursor) {
#[cfg(debug_assertions)]
let reported_endpoint2 = reported_endpoint.clone();
if self.remote_node_info.write().reported_local_endpoints.insert(reported_endpoint, time_ticks).is_none() {
if self
.remote_node_info
.write()
.reported_local_endpoints
.insert(reported_endpoint, time_ticks)
.is_none()
{
#[cfg(debug_assertions)]
debug_event!(
si,
@ -725,7 +848,9 @@ impl<SI: SystemInterface> Peer<SI> {
}
_ => {
return ph.handle_ok(self, &source_path, ok_header.in_re_verb, in_re_message_id, payload, &mut cursor).await;
return ph
.handle_ok(self, &source_path, ok_header.in_re_verb, in_re_message_id, payload, &mut cursor)
.await;
}
}
}
@ -733,7 +858,15 @@ impl<SI: SystemInterface> Peer<SI> {
return false;
}
async fn handle_incoming_whois<PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node<SI>, time_ticks: i64, message_id: MessageId, payload: &PacketBuffer) -> bool {
async fn handle_incoming_whois<PH: InnerProtocolInterface>(
&self,
si: &SI,
ph: &PH,
node: &Node<SI>,
time_ticks: i64,
message_id: MessageId,
payload: &PacketBuffer,
) -> bool {
if node.this_node_is_root() || ph.should_communicate_with(&self.identity) {
let mut packet = PacketBuffer::new();
packet.set_size(v1::HEADER_SIZE);
@ -763,12 +896,28 @@ impl<SI: SystemInterface> Peer<SI> {
}
#[allow(unused)]
async fn handle_incoming_rendezvous(&self, si: &SI, node: &Node<SI>, time_ticks: i64, message_id: MessageId, source_path: &Arc<Path<SI>>, payload: &PacketBuffer) -> bool {
async fn handle_incoming_rendezvous(
&self,
si: &SI,
node: &Node<SI>,
time_ticks: i64,
message_id: MessageId,
source_path: &Arc<Path<SI>>,
payload: &PacketBuffer,
) -> bool {
if node.is_peer_root(self) {}
return true;
}
async fn handle_incoming_echo<PH: InnerProtocolInterface>(&self, si: &SI, ph: &PH, node: &Node<SI>, time_ticks: i64, message_id: MessageId, payload: &PacketBuffer) -> bool {
async fn handle_incoming_echo<PH: InnerProtocolInterface>(
&self,
si: &SI,
ph: &PH,
node: &Node<SI>,
time_ticks: i64,
message_id: MessageId,
payload: &PacketBuffer,
) -> bool {
if ph.should_communicate_with(&self.identity) || node.is_peer_root(self) {
let mut packet = PacketBuffer::new();
packet.set_size(v1::HEADER_SIZE);
@ -784,18 +933,36 @@ impl<SI: SystemInterface> Peer<SI> {
false
}
} else {
debug_event!(si, "[vl1] dropping ECHO from {} due to lack of trust relationship", self.identity.address.to_string());
debug_event!(
si,
"[vl1] dropping ECHO from {} due to lack of trust relationship",
self.identity.address.to_string()
);
true // packet wasn't invalid, just ignored
}
}
#[allow(unused)]
async fn handle_incoming_push_direct_paths(&self, si: &SI, node: &Node<SI>, time_ticks: i64, source_path: &Arc<Path<SI>>, payload: &PacketBuffer) -> bool {
async fn handle_incoming_push_direct_paths(
&self,
si: &SI,
node: &Node<SI>,
time_ticks: i64,
source_path: &Arc<Path<SI>>,
payload: &PacketBuffer,
) -> bool {
false
}
#[allow(unused)]
async fn handle_incoming_user_message(&self, si: &SI, node: &Node<SI>, time_ticks: i64, source_path: &Arc<Path<SI>>, payload: &PacketBuffer) -> bool {
async fn handle_incoming_user_message(
&self,
si: &SI,
node: &Node<SI>,
time_ticks: i64,
source_path: &Arc<Path<SI>>,
payload: &PacketBuffer,
) -> bool {
false
}
}

View file

@ -90,7 +90,11 @@ impl RootSet {
/// Get the ZeroTier default root set, which contains roots run by ZeroTier Inc.
pub fn zerotier_default() -> Self {
let mut cursor = 0;
let rs = Self::unmarshal(&Buffer::from(include_bytes!("../../default-rootset/root.zerotier.com.bin")), &mut cursor).unwrap();
let rs = Self::unmarshal(
&Buffer::from(include_bytes!("../../default-rootset/root.zerotier.com.bin")),
&mut cursor,
)
.unwrap();
assert!(rs.verify());
rs
}
@ -156,7 +160,13 @@ impl RootSet {
}
/// Add a member to this definition, replacing any current entry with this address.
pub fn add<'a, I: Iterator<Item = &'a Endpoint>>(&mut self, member_identity: &Identity, endpoints: Option<I>, priority: u8, protocol_version: u8) {
pub fn add<'a, I: Iterator<Item = &'a Endpoint>>(
&mut self,
member_identity: &Identity,
endpoints: Option<I>,
priority: u8,
protocol_version: u8,
) {
self.members.retain(|m| m.identity.address != member_identity.address);
let _ = self.members.push(Root {
identity: member_identity.clone_without_secret(),
@ -263,11 +273,15 @@ impl Marshalable for RootSet {
}
let name_len = buf.read_varint(cursor)?;
rc.name = String::from_utf8(buf.read_bytes(name_len as usize, cursor)?.to_vec()).map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid UTF8"))?;
rc.name = String::from_utf8(buf.read_bytes(name_len as usize, cursor)?.to_vec())
.map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid UTF8"))?;
let url_len = buf.read_varint(cursor)?;
if url_len > 0 {
rc.url = Some(String::from_utf8(buf.read_bytes(url_len as usize, cursor)?.to_vec()).map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid UTF8"))?);
rc.url = Some(
String::from_utf8(buf.read_bytes(url_len as usize, cursor)?.to_vec())
.map_err(|_| std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid UTF8"))?,
);
}
rc.revision = buf.read_varint(cursor)?;

View file

@ -67,7 +67,10 @@ impl Marshalable for NetworkId {
#[inline(always)]
fn unmarshal<const BL: usize>(buf: &Buffer<BL>, cursor: &mut usize) -> std::io::Result<Self> {
Self::from_u64(buf.read_u64(cursor)?).map_or_else(|| Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "cannot be zero")), |a| Ok(a))
Self::from_u64(buf.read_u64(cursor)?).map_or_else(
|| Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "cannot be zero")),
|a| Ok(a),
)
}
}

View file

@ -18,12 +18,29 @@ impl InnerProtocolInterface for Switch {
}
#[allow(unused)]
async fn handle_error<SI: SystemInterface>(&self, peer: &Peer<SI>, source_path: &Path<SI>, in_re_verb: u8, in_re_message_id: u64, error_code: u8, payload: &PacketBuffer, cursor: &mut usize) -> bool {
async fn handle_error<SI: SystemInterface>(
&self,
peer: &Peer<SI>,
source_path: &Path<SI>,
in_re_verb: u8,
in_re_message_id: u64,
error_code: u8,
payload: &PacketBuffer,
cursor: &mut usize,
) -> bool {
false
}
#[allow(unused)]
async fn handle_ok<SI: SystemInterface>(&self, peer: &Peer<SI>, source_path: &Path<SI>, in_re_verb: u8, in_re_message_id: u64, payload: &PacketBuffer, cursor: &mut usize) -> bool {
async fn handle_ok<SI: SystemInterface>(
&self,
peer: &Peer<SI>,
source_path: &Path<SI>,
in_re_verb: u8,
in_re_message_id: u64,
payload: &PacketBuffer,
cursor: &mut usize,
) -> bool {
false
}

View file

@ -1,8 +1,8 @@
#unstable_features = true
max_width = 200
max_width = 140
#use_small_heuristics = "Max"
edition = "2021"
empty_item_single_line = true
#empty_item_single_line = true
newline_style = "Unix"
struct_lit_width = 60
tab_spaces = 4

View file

@ -32,7 +32,10 @@ impl DataDir {
if !base_path.is_dir() {
let _ = std::fs::create_dir_all(&base_path);
if !base_path.is_dir() {
return Err(std::io::Error::new(std::io::ErrorKind::NotFound, "base path not found and cannot be created"));
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
"base path not found and cannot be created",
));
}
}
@ -57,7 +60,9 @@ impl DataDir {
/// Load identity.secret from data directory.
pub async fn load_identity(&self) -> std::io::Result<Identity> {
let id_data = Identity::from_str(String::from_utf8_lossy(read_limit(self.base_path.join(IDENTITY_SECRET_FILENAME), 4096).await?.as_slice()).as_ref());
let id_data = Identity::from_str(
String::from_utf8_lossy(read_limit(self.base_path.join(IDENTITY_SECRET_FILENAME), 4096).await?.as_slice()).as_ref(),
);
if id_data.is_err() {
return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, id_data.err().unwrap()));
}

View file

@ -27,9 +27,17 @@ pub fn for_each_address<F: FnMut(&InetAddress, &LocalInterface)>(mut f: F) {
let sa_family = (*(*i).ifa_addr).sa_family as u8;
if sa_family == libc::AF_INET as u8 {
copy_nonoverlapping((*i).ifa_addr.cast::<u8>(), (&mut a as *mut InetAddress).cast::<u8>(), size_of::<libc::sockaddr_in>());
copy_nonoverlapping(
(*i).ifa_addr.cast::<u8>(),
(&mut a as *mut InetAddress).cast::<u8>(),
size_of::<libc::sockaddr_in>(),
);
} else if sa_family == libc::AF_INET6 as u8 {
copy_nonoverlapping((*i).ifa_addr.cast::<u8>(), (&mut a as *mut InetAddress).cast::<u8>(), size_of::<libc::sockaddr_in6>());
copy_nonoverlapping(
(*i).ifa_addr.cast::<u8>(),
(&mut a as *mut InetAddress).cast::<u8>(),
size_of::<libc::sockaddr_in6>(),
);
} else {
i = (*i).ifa_next;
continue;
@ -87,7 +95,9 @@ mod tests {
#[test]
fn test_getifaddrs() {
println!("starting getifaddrs...");
crate::getifaddrs::for_each_address(|a: &InetAddress, interface: &LocalInterface| println!(" {} {}", interface.to_string(), a.to_string()));
crate::getifaddrs::for_each_address(|a: &InetAddress, interface: &LocalInterface| {
println!(" {} {}", interface.to_string(), a.to_string())
});
println!("done.")
}
}

View file

@ -56,7 +56,11 @@ mod freebsd_like {
let device_name_bytes = device_name.as_bytes();
assert!(device_name_bytes.len() <= 15);
ifr6.ifr_name[..device_name_bytes.len()].copy_from_slice(device_name_bytes);
std::ptr::copy_nonoverlapping((address as *const InetAddress).cast(), &mut ifr6.ifr_ifru.ifru_addr, size_of::<libc::sockaddr_in6>());
std::ptr::copy_nonoverlapping(
(address as *const InetAddress).cast(),
&mut ifr6.ifr_ifru.ifru_addr,
size_of::<libc::sockaddr_in6>(),
);
if libc::ioctl((*info_socket).as_(), SIOCGIFAFLAG_IN6, &mut ifr6 as *mut in6_ifreq) != -1 {
if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TEMPORARY) != 0 {
return true;

View file

@ -9,12 +9,17 @@ use zerotier_network_hypervisor::vl2::NetworkId;
/// A list of unassigned or obsolete ports under 1024 that could possibly be squatted.
pub const UNASSIGNED_PRIVILEGED_PORTS: [u16; 299] = [
4, 6, 8, 10, 12, 14, 15, 16, 26, 28, 30, 32, 34, 36, 40, 60, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 285, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 323, 324, 325, 326, 327, 328,
329, 330, 331, 332, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 703, 708, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 732, 733, 734, 735, 736, 737, 738, 739, 740, 743, 745, 746, 755, 756, 766, 768, 778, 779,
781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 802, 803, 804, 805, 806, 807, 808, 809, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 834, 835, 836, 837, 838, 839,
840, 841, 842, 843, 844, 845, 846, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 889, 890, 891, 892, 893, 894, 895, 896, 897,
898, 899, 904, 905, 906, 907, 908, 909, 910, 911, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953,
954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1023,
4, 6, 8, 10, 12, 14, 15, 16, 26, 28, 30, 32, 34, 36, 40, 60, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 285, 288, 289, 290,
291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 703, 708, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727,
728, 732, 733, 734, 735, 736, 737, 738, 739, 740, 743, 745, 746, 755, 756, 766, 768, 778, 779, 781, 782, 783, 784, 785, 786, 787, 788,
789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 802, 803, 804, 805, 806, 807, 808, 809, 811, 812, 813, 814, 815, 816, 817, 818,
819, 820, 821, 822, 823, 824, 825, 826, 827, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 849, 850, 851, 852, 853,
854, 855, 856, 857, 858, 859, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883,
884, 885, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 904, 905, 906, 907, 908, 909, 910, 911, 914, 915, 916, 917, 918, 919,
920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946,
947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973,
974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1023,
];
/// Default primary ZeroTier port.

View file

@ -99,17 +99,36 @@ fn main() {
.subcommand(Command::new("secondaryport").arg(Arg::new("port#").index(1).validator(utils::is_valid_port)))
.subcommand(
Command::new("blacklist")
.subcommand(Command::new("cidr").arg(Arg::new("ip_bits").index(1)).arg(Arg::new("boolean").index(2).validator(utils::is_valid_bool)))
.subcommand(Command::new("if").arg(Arg::new("prefix").index(1)).arg(Arg::new("boolean").index(2).validator(utils::is_valid_bool))),
.subcommand(
Command::new("cidr")
.arg(Arg::new("ip_bits").index(1))
.arg(Arg::new("boolean").index(2).validator(utils::is_valid_bool)),
)
.subcommand(
Command::new("if")
.arg(Arg::new("prefix").index(1))
.arg(Arg::new("boolean").index(2).validator(utils::is_valid_bool)),
),
)
.subcommand(Command::new("portmap").arg(Arg::new("boolean").index(1).validator(utils::is_valid_bool))),
)
.subcommand(Command::new("peer").subcommand(Command::new("show").arg(Arg::new("address").index(1).required(true))).subcommand(Command::new("list")).subcommand(Command::new("listroots")).subcommand(Command::new("try")))
.subcommand(
Command::new("peer")
.subcommand(Command::new("show").arg(Arg::new("address").index(1).required(true)))
.subcommand(Command::new("list"))
.subcommand(Command::new("listroots"))
.subcommand(Command::new("try")),
)
.subcommand(
Command::new("network")
.subcommand(Command::new("show").arg(Arg::new("nwid").index(1).required(true)))
.subcommand(Command::new("list"))
.subcommand(Command::new("set").arg(Arg::new("nwid").index(1).required(true)).arg(Arg::new("setting").index(2).required(false)).arg(Arg::new("value").index(3).required(false))),
.subcommand(
Command::new("set")
.arg(Arg::new("nwid").index(1).required(true))
.arg(Arg::new("setting").index(2).required(false))
.arg(Arg::new("value").index(3).required(false)),
),
)
.subcommand(Command::new("join").arg(Arg::new("nwid").index(1).required(true)))
.subcommand(Command::new("leave").arg(Arg::new("nwid").index(1).required(true)))
@ -120,15 +139,28 @@ fn main() {
.subcommand(Command::new("getpublic").arg(Arg::new("identity").index(1).required(true)))
.subcommand(Command::new("fingerprint").arg(Arg::new("identity").index(1).required(true)))
.subcommand(Command::new("validate").arg(Arg::new("identity").index(1).required(true)))
.subcommand(Command::new("sign").arg(Arg::new("identity").index(1).required(true)).arg(Arg::new("path").index(2).required(true)))
.subcommand(Command::new("verify").arg(Arg::new("identity").index(1).required(true)).arg(Arg::new("path").index(2).required(true)).arg(Arg::new("signature").index(3).required(true))),
.subcommand(
Command::new("sign")
.arg(Arg::new("identity").index(1).required(true))
.arg(Arg::new("path").index(2).required(true)),
)
.subcommand(
Command::new("verify")
.arg(Arg::new("identity").index(1).required(true))
.arg(Arg::new("path").index(2).required(true))
.arg(Arg::new("signature").index(3).required(true)),
),
)
.subcommand(
Command::new("rootset")
.subcommand(Command::new("add").arg(Arg::new("path").index(1).required(true)))
.subcommand(Command::new("remove").arg(Arg::new("name").index(1).required(true)))
.subcommand(Command::new("list"))
.subcommand(Command::new("sign").arg(Arg::new("path").index(1).required(true)).arg(Arg::new("secret").index(2).required(true)))
.subcommand(
Command::new("sign")
.arg(Arg::new("path").index(1).required(true))
.arg(Arg::new("secret").index(2).required(true)),
)
.subcommand(Command::new("verify").arg(Arg::new("path").index(1).required(true)))
.subcommand(Command::new("marshal").arg(Arg::new("path").index(1).required(true)))
.subcommand(Command::new("restoredefault")),
@ -163,7 +195,10 @@ fn main() {
if suggested.is_empty() {
eprintln!("Unrecognized option '{}'. Use 'help' for help.", invalid);
} else {
eprintln!("Unrecognized option '{}', did you mean {}? Use 'help' for help.", invalid, suggested);
eprintln!(
"Unrecognized option '{}', did you mean {}? Use 'help' for help.",
invalid, suggested
);
}
}
std::process::exit(exitcode::ERR_USAGE);
@ -173,10 +208,18 @@ fn main() {
let flags = Flags {
json_output: global_args.is_present("json"),
base_path: global_args.value_of("path").map_or_else(platform_default_home_path, |p| p.to_string()),
base_path: global_args
.value_of("path")
.map_or_else(platform_default_home_path, |p| p.to_string()),
auth_token_path_override: global_args.value_of("token_path").map(|p| p.to_string()),
auth_token_override: global_args.value_of("token").map(|t| t.to_string()),
};
std::process::exit(tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap().block_on(async_main(flags, global_args)));
std::process::exit(
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
.block_on(async_main(flags, global_args)),
);
}

View file

@ -63,7 +63,11 @@ impl Service {
///
/// This launches a number of background tasks in the async runtime that will run as long as this object exists.
/// When this is dropped these tasks are killed.
pub async fn new<P: AsRef<Path>>(rt: tokio::runtime::Handle, base_path: P, auto_upgrade_identity: bool) -> Result<Self, Box<dyn Error>> {
pub async fn new<P: AsRef<Path>>(
rt: tokio::runtime::Handle,
base_path: P,
auto_upgrade_identity: bool,
) -> Result<Self, Box<dyn Error>> {
let mut si = ServiceImpl {
rt,
data: DataDir::open(base_path).await.map_err(|e| Box::new(e))?,
@ -126,7 +130,13 @@ impl ServiceImpl {
let mut buf = core.get_packet_buffer();
if let Ok((bytes, source)) = socket.recv_from(unsafe { buf.entire_buffer_mut() }).await {
unsafe { buf.set_size_unchecked(bytes) };
core.handle_incoming_physical_packet(&self2, &Endpoint::IpUdp(InetAddress::from(source)), &local_socket, &interface, buf)
core.handle_incoming_physical_packet(
&self2,
&Endpoint::IpUdp(InetAddress::from(source)),
&local_socket,
&interface,
buf,
)
.await;
} else {
break;
@ -144,7 +154,11 @@ impl ServiceImpl {
let config = self.data.config().await;
if let Some(errors) = self
.update_udp_bindings_for_port(config.settings.primary_port, &config.settings.interface_prefix_blacklist, &config.settings.cidr_blacklist)
.update_udp_bindings_for_port(
config.settings.primary_port,
&config.settings.interface_prefix_blacklist,
&config.settings.cidr_blacklist,
)
.await
{
for e in errors.iter() {
@ -193,7 +207,14 @@ impl SystemInterface for ServiceImpl {
assert!(self.data.save_identity(id).await.is_ok())
}
async fn wire_send(&self, endpoint: &Endpoint, local_socket: Option<&Self::LocalSocket>, local_interface: Option<&Self::LocalInterface>, data: &[&[u8]], packet_ttl: u8) -> bool {
async fn wire_send(
&self,
endpoint: &Endpoint,
local_socket: Option<&Self::LocalSocket>,
local_interface: Option<&Self::LocalInterface>,
data: &[&[u8]],
packet_ttl: u8,
) -> bool {
match endpoint {
Endpoint::IpUdp(address) => {
// This is the fast path -- the socket is known to the core so just send it.
@ -251,7 +272,13 @@ impl SystemInterface for ServiceImpl {
return false;
}
async fn check_path(&self, _id: &Identity, endpoint: &Endpoint, _local_socket: Option<&Self::LocalSocket>, _local_interface: Option<&Self::LocalInterface>) -> bool {
async fn check_path(
&self,
_id: &Identity,
endpoint: &Endpoint,
_local_socket: Option<&Self::LocalSocket>,
_local_interface: Option<&Self::LocalInterface>,
) -> bool {
let config = self.data.config().await;
if let Some(pps) = config.physical.get(endpoint) {
!pps.blacklist

View file

@ -52,7 +52,15 @@ impl BoundUdpSocket {
#[inline(always)]
fn set_ttl(&self, packet_ttl: u8) {
let ttl = packet_ttl as libc::c_int;
unsafe { libc::setsockopt(self.fd.as_(), libc::IPPROTO_IP.as_(), libc::IP_TOS.as_(), (&ttl as *const libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_()) };
unsafe {
libc::setsockopt(
self.fd.as_(),
libc::IPPROTO_IP.as_(),
libc::IP_TOS.as_(),
(&ttl as *const libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
)
};
}
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
@ -65,7 +73,14 @@ impl BoundUdpSocket {
unsafe {
if b.len() == 1 {
let bb = *b.get_unchecked(0);
ok = libc::sendto(self.fd.as_(), bb.as_ptr().cast(), bb.len().as_(), 0, (dest as *const InetAddress).cast(), size_of::<InetAddress>().as_()) > 0;
ok = libc::sendto(
self.fd.as_(),
bb.as_ptr().cast(),
bb.len().as_(),
0,
(dest as *const InetAddress).cast(),
size_of::<InetAddress>().as_(),
) > 0;
} else {
let mut iov: [libc::iovec; 16] = MaybeUninit::uninit().assume_init();
assert!(b.len() <= iov.len());
@ -143,10 +158,17 @@ impl BoundUdpPort {
/// The caller can check the 'sockets' member variable after calling to determine which if any bindings were
/// successful. Any errors that occurred are returned as tuples of (interface, address, error). The second vector
/// returned contains newly bound sockets.
pub fn update_bindings(&mut self, interface_prefix_blacklist: &Vec<String>, cidr_blacklist: &Vec<InetAddress>) -> (Vec<(LocalInterface, InetAddress, std::io::Error)>, Vec<Arc<BoundUdpSocket>>) {
pub fn update_bindings(
&mut self,
interface_prefix_blacklist: &Vec<String>,
cidr_blacklist: &Vec<InetAddress>,
) -> (Vec<(LocalInterface, InetAddress, std::io::Error)>, Vec<Arc<BoundUdpSocket>>) {
let mut existing_bindings: HashMap<LocalInterface, HashMap<InetAddress, Arc<BoundUdpSocket>>> = HashMap::with_capacity(4);
for s in self.sockets.drain(..) {
existing_bindings.entry(s.interface).or_insert_with(|| HashMap::with_capacity(4)).insert(s.address.clone(), s);
existing_bindings
.entry(s.interface)
.or_insert_with(|| HashMap::with_capacity(4))
.insert(s.address.clone(), s);
}
let mut errors = Vec::new();
@ -156,7 +178,10 @@ impl BoundUdpPort {
let mut addr_with_port = address.clone();
addr_with_port.set_port(self.port);
if address.is_ip()
&& matches!(address.scope(), IpScope::Global | IpScope::PseudoPrivate | IpScope::Private | IpScope::Shared)
&& matches!(
address.scope(),
IpScope::Global | IpScope::PseudoPrivate | IpScope::Private | IpScope::Shared
)
&& !interface_prefix_blacklist.iter().any(|pfx| interface_str.starts_with(pfx.as_str()))
&& !cidr_blacklist.iter().any(|r| address.is_within(r))
&& !ipv6::is_ipv6_temporary(interface_str.as_str(), address)
@ -187,7 +212,11 @@ impl BoundUdpPort {
errors.push((interface.clone(), addr_with_port, s.err().unwrap()));
}
} else {
errors.push((interface.clone(), addr_with_port, std::io::Error::new(std::io::ErrorKind::Other, s.err().unwrap())));
errors.push((
interface.clone(),
addr_with_port,
std::io::Error::new(std::io::ErrorKind::Other, s.err().unwrap()),
));
}
}
}
@ -220,15 +249,33 @@ unsafe fn bind_udp_to_device(device_name: &str, address: &InetAddress) -> Result
let mut fl: libc::c_int;
fl = 1;
setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_REUSEPORT.as_(), (&mut fl as *mut libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_());
setsockopt_results |= libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_REUSEPORT.as_(),
(&mut fl as *mut libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
);
debug_assert!(setsockopt_results == 0);
fl = 1;
setsockopt_results |= libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_BROADCAST.as_(), (&mut fl as *mut libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_());
setsockopt_results |= libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_BROADCAST.as_(),
(&mut fl as *mut libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
);
debug_assert!(setsockopt_results == 0);
if af == AF_INET6 {
fl = 1;
setsockopt_results |= libc::setsockopt(s, libc::IPPROTO_IPV6.as_(), libc::IPV6_V6ONLY.as_(), (&mut fl as *mut libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_());
setsockopt_results |= libc::setsockopt(
s,
libc::IPPROTO_IPV6.as_(),
libc::IPV6_V6ONLY.as_(),
(&mut fl as *mut libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
);
debug_assert!(setsockopt_results == 0);
}
@ -237,7 +284,13 @@ unsafe fn bind_udp_to_device(device_name: &str, address: &InetAddress) -> Result
if !device_name.is_empty() {
let _ = std::ffi::CString::new(device_name).map(|dn| {
let dnb = dn.as_bytes_with_nul();
let _ = libc::setsockopt(s.as_(), libc::SOL_SOCKET.as_(), libc::SO_BINDTODEVICE.as_(), dnb.as_ptr().cast(), (dnb.len() - 1).as_());
let _ = libc::setsockopt(
s.as_(),
libc::SOL_SOCKET.as_(),
libc::SO_BINDTODEVICE.as_(),
dnb.as_ptr().cast(),
(dnb.len() - 1).as_(),
);
});
}
}
@ -251,30 +304,62 @@ unsafe fn bind_udp_to_device(device_name: &str, address: &InetAddress) -> Result
#[cfg(not(target_os = "linux"))]
{
fl = 0;
libc::setsockopt(s, libc::IPPROTO_IP.as_(), libc::IP_DONTFRAG.as_(), (&mut fl as *mut libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_());
libc::setsockopt(
s,
libc::IPPROTO_IP.as_(),
libc::IP_DONTFRAG.as_(),
(&mut fl as *mut libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
);
}
#[cfg(target_os = "linux")]
{
fl = libc::IP_PMTUDISC_DONT as libc::c_int;
libc::setsockopt(s, libc::IPPROTO_IP.as_(), libc::IP_MTU_DISCOVER.as_(), (&mut fl as *mut libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_());
libc::setsockopt(
s,
libc::IPPROTO_IP.as_(),
libc::IP_MTU_DISCOVER.as_(),
(&mut fl as *mut libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
);
}
}
if af == AF_INET6 {
fl = 0;
libc::setsockopt(s, libc::IPPROTO_IPV6.as_(), libc::IPV6_DONTFRAG.as_(), (&mut fl as *mut libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_());
libc::setsockopt(
s,
libc::IPPROTO_IPV6.as_(),
libc::IPV6_DONTFRAG.as_(),
(&mut fl as *mut libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
);
}
fl = 1048576;
while fl >= 65536 {
if libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_RCVBUF.as_(), (&mut fl as *mut libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_()) == 0 {
if libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_RCVBUF.as_(),
(&mut fl as *mut libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
) == 0
{
break;
}
fl -= 65536;
}
fl = 1048576;
while fl >= 65536 {
if libc::setsockopt(s, libc::SOL_SOCKET.as_(), libc::SO_SNDBUF.as_(), (&mut fl as *mut libc::c_int).cast(), std::mem::size_of::<libc::c_int>().as_()) == 0 {
if libc::setsockopt(
s,
libc::SOL_SOCKET.as_(),
libc::SO_SNDBUF.as_(),
(&mut fl as *mut libc::c_int).cast(),
std::mem::size_of::<libc::c_int>().as_(),
) == 0
{
break;
}
fl -= 65536;

View file

@ -99,7 +99,11 @@ pub fn json_patch(target: &mut serde_json::value::Value, source: &serde_json::va
///
/// If there are no changes, None is returned. The depth limit is passed through to json_patch and
/// should be set to a sanity check value to prevent overflows.
pub fn json_patch_object<O: Serialize + DeserializeOwned + Eq>(obj: O, patch: &str, depth_limit: usize) -> Result<Option<O>, serde_json::Error> {
pub fn json_patch_object<O: Serialize + DeserializeOwned + Eq>(
obj: O,
patch: &str,
depth_limit: usize,
) -> Result<Option<O>, serde_json::Error> {
serde_json::from_str::<serde_json::value::Value>(patch).map_or_else(
|e| Err(e),
|patch| {
@ -156,7 +160,14 @@ pub async fn read_limit<P: AsRef<Path>>(path: P, limit: usize) -> std::io::Resul
pub fn fs_restrict_permissions<P: AsRef<Path>>(path: P) -> bool {
unsafe {
let c_path = std::ffi::CString::new(path.as_ref().to_str().unwrap()).unwrap();
libc::chmod(c_path.as_ptr(), if path.as_ref().is_dir() { 0o700 } else { 0o600 }) == 0
libc::chmod(
c_path.as_ptr(),
if path.as_ref().is_dir() {
0o700
} else {
0o600
},
) == 0
}
}
@ -177,7 +188,10 @@ pub async fn parse_cli_identity(input: &str, validate: bool) -> Result<Identity,
let input_p = Path::new(input);
if input_p.is_file() {
read_limit(input_p, 16384).await.map_or_else(|e| Err(e.to_string()), |v| String::from_utf8(v).map_or_else(|e| Err(e.to_string()), |s| parse_func(s.as_str())))
read_limit(input_p, 16384).await.map_or_else(
|e| Err(e.to_string()),
|v| String::from_utf8(v).map_or_else(|e| Err(e.to_string()), |s| parse_func(s.as_str())),
)
} else {
parse_func(input)
}

View file

@ -9,7 +9,15 @@ use num_traits::AsPrimitive;
#[allow(unused_imports)]
use zerotier_network_hypervisor::vl1::MAC;
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly", target_os = "freebsd", target_os = "darwin"))]
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "darwin"
))]
#[allow(non_camel_case_types)]
#[repr(C)]
struct ifmaddrs {
@ -19,13 +27,29 @@ struct ifmaddrs {
ifma_lladdr: *mut libc::sockaddr,
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly", target_os = "freebsd", target_os = "darwin"))]
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "darwin"
))]
extern "C" {
fn getifmaddrs(ifmap: *mut *mut ifmaddrs) -> c_int;
fn freeifmaddrs(ifmp: *mut ifmaddrs);
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd", target_os = "openbsd", target_os = "dragonfly", target_os = "freebsd", target_os = "darwin"))]
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "darwin"
))]
pub fn get_l2_multicast_subscriptions(dev: &str) -> HashSet<MAC> {
let mut groups: HashSet<MAC> = HashSet::new();
let dev = dev.as_bytes();
@ -37,9 +61,19 @@ pub fn get_l2_multicast_subscriptions(dev: &str) -> HashSet<MAC> {
if !(*i).ifma_name.is_null() && !(*i).ifma_addr.is_null() && (*(*i).ifma_addr).sa_family as i32 == libc::AF_LINK as i32 {
let in_: &libc::sockaddr_dl = &*((*i).ifma_name.cast());
let la: &libc::sockaddr_dl = &*((*i).ifma_addr.cast());
if la.sdl_alen == 6 && in_.sdl_nlen <= dev.len().as_() && libc::memcmp(dev.as_ptr().cast(), in_.sdl_data.as_ptr().cast(), in_.sdl_nlen.as_()) == 0 {
if la.sdl_alen == 6
&& in_.sdl_nlen <= dev.len().as_()
&& libc::memcmp(dev.as_ptr().cast(), in_.sdl_data.as_ptr().cast(), in_.sdl_nlen.as_()) == 0
{
let mi = la.sdl_nlen as usize;
MAC::from_u64((la.sdl_data[mi] as u64) << 40 | (la.sdl_data[mi + 1] as u64) << 32 | (la.sdl_data[mi + 2] as u64) << 24 | (la.sdl_data[mi + 3] as u64) << 16 | (la.sdl_data[mi + 4] as u64) << 8 | la.sdl_data[mi + 5] as u64)
MAC::from_u64(
(la.sdl_data[mi] as u64) << 40
| (la.sdl_data[mi + 1] as u64) << 32
| (la.sdl_data[mi + 2] as u64) << 24
| (la.sdl_data[mi + 3] as u64) << 16
| (la.sdl_data[mi + 4] as u64) << 8
| la.sdl_data[mi + 5] as u64,
)
.map(|mac| groups.insert(mac));
}
}

View file

@ -225,7 +225,15 @@ fn device_ipv6_set_params(device: &String, perform_nud: bool, accept_ra: bool) -
}
let mut nd: in6_ndireq = zeroed();
copy_nonoverlapping(dev.as_ptr(), nd.ifname.as_mut_ptr().cast::<u8>(), if dev.len() > (nd.ifname.len() - 1) { nd.ifname.len() - 1 } else { dev.len() });
copy_nonoverlapping(
dev.as_ptr(),
nd.ifname.as_mut_ptr().cast::<u8>(),
if dev.len() > (nd.ifname.len() - 1) {
nd.ifname.len() - 1
} else {
dev.len()
},
);
if libc::ioctl(s, 76 /* SIOCGIFINFO_IN6 */, (&mut nd as *mut in6_ndireq).cast::<c_void>()) == 0 {
let oldflags = nd.ndi.flags;
if perform_nud {
@ -243,7 +251,15 @@ fn device_ipv6_set_params(device: &String, perform_nud: bool, accept_ra: bool) -
}
let mut ifr: in6_ifreq = zeroed();
copy_nonoverlapping(dev.as_ptr(), ifr.ifr_name.as_mut_ptr().cast::<u8>(), if dev.len() > (ifr.ifr_name.len() - 1) { ifr.ifr_name.len() - 1 } else { dev.len() });
copy_nonoverlapping(
dev.as_ptr(),
ifr.ifr_name.as_mut_ptr().cast::<u8>(),
if dev.len() > (ifr.ifr_name.len() - 1) {
ifr.ifr_name.len() - 1
} else {
dev.len()
},
);
if libc::ioctl(
s,
if accept_ra {
@ -323,7 +339,13 @@ impl MacFethTap {
/// given will not remain valid after it returns. Also note that F will be called
/// from another thread that is spawned here, so all its bound references must
/// be "Send" and "Sync" e.g. Arc<>.
pub fn new<F: Fn(&[u8]) + Send + Sync + 'static>(nwid: u64, mac: &MAC, mtu: i32, metric: i32, eth_frame_func: F) -> Result<MacFethTap, String> {
pub fn new<F: Fn(&[u8]) + Send + Sync + 'static>(
nwid: u64,
mac: &MAC,
mtu: i32,
metric: i32,
eth_frame_func: F,
) -> Result<MacFethTap, String> {
// This tracks BPF devices we are using so we don't try to reopen them, and also
// doubles as a global lock to ensure that only one feth tap is created at once per
// ZeroTier process per system.
@ -369,12 +391,20 @@ impl MacFethTap {
// Create pair of feth interfaces and create MacFethDevice struct.
let cmd = Command::new(IFCONFIG).arg(&device_name).arg("create").spawn();
if cmd.is_err() {
return Err(format!("unable to create device '{}': {}", device_name.as_str(), cmd.err().unwrap().to_string()));
return Err(format!(
"unable to create device '{}': {}",
device_name.as_str(),
cmd.err().unwrap().to_string()
));
}
let _ = cmd.unwrap().wait();
let cmd = Command::new(IFCONFIG).arg(&peer_device_name).arg("create").spawn();
if cmd.is_err() {
return Err(format!("unable to create device '{}': {}", peer_device_name.as_str(), cmd.err().unwrap().to_string()));
return Err(format!(
"unable to create device '{}': {}",
peer_device_name.as_str(),
cmd.err().unwrap().to_string()
));
}
let _ = cmd.unwrap().wait();
let device = MacFethDevice { name: device_name, peer_name: peer_device_name };
@ -382,28 +412,60 @@ impl MacFethTap {
// Set link-layer (MAC) address of primary interface.
let cmd = Command::new(IFCONFIG).arg(&device.name).arg("lladdr").arg(mac.to_string()).spawn();
if cmd.is_err() {
return Err(format!("unable to configure device '{}': {}", &device.name, cmd.err().unwrap().to_string()));
return Err(format!(
"unable to configure device '{}': {}",
&device.name,
cmd.err().unwrap().to_string()
));
}
let _ = cmd.unwrap().wait();
// Bind peer interfaces together.
let cmd = Command::new(IFCONFIG).arg(&device.peer_name).arg("peer").arg(device.name.as_str()).spawn();
let cmd = Command::new(IFCONFIG)
.arg(&device.peer_name)
.arg("peer")
.arg(device.name.as_str())
.spawn();
if cmd.is_err() {
return Err(format!("unable to configure device '{}': {}", &device.peer_name, cmd.err().unwrap().to_string()));
return Err(format!(
"unable to configure device '{}': {}",
&device.peer_name,
cmd.err().unwrap().to_string()
));
}
let _ = cmd.unwrap().wait();
// Set MTU of secondary peer interface, bring up.
let cmd = Command::new(IFCONFIG).arg(&device.peer_name).arg("mtu").arg(mtu.to_string()).arg("up").spawn();
let cmd = Command::new(IFCONFIG)
.arg(&device.peer_name)
.arg("mtu")
.arg(mtu.to_string())
.arg("up")
.spawn();
if cmd.is_err() {
return Err(format!("unable to configure device '{}': {}", &device.peer_name, cmd.err().unwrap().to_string()));
return Err(format!(
"unable to configure device '{}': {}",
&device.peer_name,
cmd.err().unwrap().to_string()
));
}
let _ = cmd.unwrap().wait();
// Set MTU and metric of primary interface, bring up.
let cmd = Command::new(IFCONFIG).arg(&device.name).arg("mtu").arg(mtu.to_string()).arg("metric").arg(metric.to_string()).arg("up").spawn();
let cmd = Command::new(IFCONFIG)
.arg(&device.name)
.arg("mtu")
.arg(mtu.to_string())
.arg("metric")
.arg(metric.to_string())
.arg("up")
.spawn();
if cmd.is_err() {
return Err(format!("unable to configure device '{}': {}", &device.name.as_str(), cmd.err().unwrap().to_string()));
return Err(format!(
"unable to configure device '{}': {}",
&device.name.as_str(),
cmd.err().unwrap().to_string()
));
}
let _ = cmd.unwrap().wait();
@ -449,7 +511,11 @@ impl MacFethTap {
// Set immediate mode for "live" capture.
fl = 1;
if unsafe {
libc::ioctl(bpf_fd as c_int, 112 /* BIOCIMMEDIATE */, (&mut fl as *mut c_int).cast::<c_void>())
libc::ioctl(
bpf_fd as c_int,
112, /* BIOCIMMEDIATE */
(&mut fl as *mut c_int).cast::<c_void>(),
)
} != 0
{
unsafe {
@ -461,7 +527,11 @@ impl MacFethTap {
// Do not send us back packets we inject or send.
fl = 0;
if unsafe {
libc::ioctl(bpf_fd as c_int, 119 /* BIOCSSEESENT */, (&mut fl as *mut c_int).cast::<c_void>())
libc::ioctl(
bpf_fd as c_int,
119, /* BIOCSSEESENT */
(&mut fl as *mut c_int).cast::<c_void>(),
)
} != 0
{
unsafe {
@ -474,10 +544,22 @@ impl MacFethTap {
let mut bpf_ifr: ifreq = unsafe { std::mem::zeroed() };
let peer_dev_name_bytes = device.peer_name.as_bytes();
unsafe {
copy_nonoverlapping(peer_dev_name_bytes.as_ptr(), bpf_ifr.ifr_name.as_mut_ptr().cast::<u8>(), if peer_dev_name_bytes.len() > (bpf_ifr.ifr_name.len() - 1) { bpf_ifr.ifr_name.len() - 1 } else { peer_dev_name_bytes.len() });
copy_nonoverlapping(
peer_dev_name_bytes.as_ptr(),
bpf_ifr.ifr_name.as_mut_ptr().cast::<u8>(),
if peer_dev_name_bytes.len() > (bpf_ifr.ifr_name.len() - 1) {
bpf_ifr.ifr_name.len() - 1
} else {
peer_dev_name_bytes.len()
},
);
}
if unsafe {
libc::ioctl(bpf_fd as c_int, 108 /* BIOCSETIF */, (&mut bpf_ifr as *mut ifreq).cast::<c_void>())
libc::ioctl(
bpf_fd as c_int,
108, /* BIOCSETIF */
(&mut bpf_ifr as *mut ifreq).cast::<c_void>(),
)
} != 0
{
unsafe {
@ -489,7 +571,11 @@ impl MacFethTap {
// Include Ethernet header in BPF captures.
fl = 1;
if unsafe {
libc::ioctl(bpf_fd as c_int, 117 /* BIOCSHDRCMPLT */, (&mut fl as *mut c_int).cast::<c_void>())
libc::ioctl(
bpf_fd as c_int,
117, /* BIOCSHDRCMPLT */
(&mut fl as *mut c_int).cast::<c_void>(),
)
} != 0
{
unsafe {
@ -501,7 +587,11 @@ impl MacFethTap {
// Set promiscuous mode so bridging can work.
fl = 1;
if unsafe {
libc::ioctl(bpf_fd as c_int, 105 /* BIOCPROMISC */, (&mut fl as *mut c_int).cast::<c_void>())
libc::ioctl(
bpf_fd as c_int,
105, /* BIOCPROMISC */
(&mut fl as *mut c_int).cast::<c_void>(),
)
} != 0
{
unsafe {
@ -558,9 +648,24 @@ impl MacFethTap {
ndrv_sa.snd_len = std::mem::size_of::<sockaddr_ndrv>() as c_uchar;
ndrv_sa.snd_family = 27 /* AF_NDRV */;
unsafe {
copy_nonoverlapping(peer_dev_name_bytes.as_ptr(), ndrv_sa.snd_name.as_mut_ptr().cast::<u8>(), if peer_dev_name_bytes.len() > (bpf_ifr.ifr_name.len() - 1) { bpf_ifr.ifr_name.len() - 1 } else { peer_dev_name_bytes.len() });
copy_nonoverlapping(
peer_dev_name_bytes.as_ptr(),
ndrv_sa.snd_name.as_mut_ptr().cast::<u8>(),
if peer_dev_name_bytes.len() > (bpf_ifr.ifr_name.len() - 1) {
bpf_ifr.ifr_name.len() - 1
} else {
peer_dev_name_bytes.len()
},
);
}
if unsafe { libc::bind(ndrv_fd, (&ndrv_sa as *const sockaddr_ndrv).cast(), std::mem::size_of::<sockaddr_ndrv>() as libc::socklen_t) } != 0 {
if unsafe {
libc::bind(
ndrv_fd,
(&ndrv_sa as *const sockaddr_ndrv).cast(),
std::mem::size_of::<sockaddr_ndrv>() as libc::socklen_t,
)
} != 0
{
unsafe {
libc::close(bpf_fd);
}
@ -569,7 +674,14 @@ impl MacFethTap {
}
return Err(String::from("unable to bind AF_NDRV socket"));
}
if unsafe { libc::connect(ndrv_fd, (&ndrv_sa as *const sockaddr_ndrv).cast(), std::mem::size_of::<sockaddr_ndrv>() as libc::socklen_t) } != 0 {
if unsafe {
libc::connect(
ndrv_fd,
(&ndrv_sa as *const sockaddr_ndrv).cast(),
std::mem::size_of::<sockaddr_ndrv>() as libc::socklen_t,
)
} != 0
{
unsafe {
libc::close(bpf_fd);
}
@ -605,7 +717,16 @@ impl MacFethTap {
impl VNIC for MacFethTap {
fn add_ip(&self, ip: &InetAddress) -> bool {
if !self.have_ip(ip) {
let cmd = Command::new(IFCONFIG).arg(&self.device.name).arg(if ip.is_v6() { "inet6" } else { "inet" }).arg(ip.to_string()).arg("alias").spawn();
let cmd = Command::new(IFCONFIG)
.arg(&self.device.name)
.arg(if ip.is_v6() {
"inet6"
} else {
"inet"
})
.arg(ip.to_string())
.arg("alias")
.spawn();
if cmd.is_ok() {
let _ = cmd.unwrap().wait();
}
@ -616,7 +737,16 @@ impl VNIC for MacFethTap {
fn remove_ip(&self, ip: &InetAddress) -> bool {
if self.have_ip(ip) {
let cmd = Command::new(IFCONFIG).arg(&self.device.name).arg(if ip.is_v6() { "inet6" } else { "inet" }).arg(ip.to_string()).arg("-alias").spawn();
let cmd = Command::new(IFCONFIG)
.arg(&self.device.name)
.arg(if ip.is_v6() {
"inet6"
} else {
"inet"
})
.arg(ip.to_string())
.arg("-alias")
.spawn();
if cmd.is_ok() {
let _ = cmd.unwrap().wait();
}
@ -644,18 +774,42 @@ impl VNIC for MacFethTap {
fn get_multicast_groups(&self) -> HashSet<MulticastGroup> {
let mut all_groups: HashSet<MulticastGroup> = HashSet::new();
crate::vnic::common::get_l2_multicast_subscriptions(self.device.name.as_str()).into_iter().for_each(|mac| {
crate::vnic::common::get_l2_multicast_subscriptions(self.device.name.as_str())
.into_iter()
.for_each(|mac| {
all_groups.insert(MulticastGroup::from(&mac));
});
all_groups
}
#[inline(always)]
fn put(&self, source_mac: &zerotier_network_hypervisor::vl1::MAC, dest_mac: &zerotier_network_hypervisor::vl1::MAC, ethertype: u16, _vlan_id: u16, data: *const u8, len: usize) -> bool {
fn put(
&self,
source_mac: &zerotier_network_hypervisor::vl1::MAC,
dest_mac: &zerotier_network_hypervisor::vl1::MAC,
ethertype: u16,
_vlan_id: u16,
data: *const u8,
len: usize,
) -> bool {
let dm = dest_mac.0;
let sm = source_mac.0;
let mut hdr: [u8; 14] =
[(dm >> 40) as u8, (dm >> 32) as u8, (dm >> 24) as u8, (dm >> 16) as u8, (dm >> 8) as u8, dm as u8, (sm >> 40) as u8, (sm >> 32) as u8, (sm >> 24) as u8, (sm >> 16) as u8, (sm >> 8) as u8, sm as u8, (ethertype >> 8) as u8, ethertype as u8];
let mut hdr: [u8; 14] = [
(dm >> 40) as u8,
(dm >> 32) as u8,
(dm >> 24) as u8,
(dm >> 16) as u8,
(dm >> 8) as u8,
dm as u8,
(sm >> 40) as u8,
(sm >> 32) as u8,
(sm >> 24) as u8,
(sm >> 16) as u8,
(sm >> 8) as u8,
sm as u8,
(ethertype >> 8) as u8,
ethertype as u8,
];
unsafe {
let iov: [libc::iovec; 2] = [
libc::iovec { iov_base: hdr.as_mut_ptr().cast(), iov_len: 14 },

View file

@ -10,56 +10,44 @@ const CT_HEX: &str = "EADD5ADA14DA57F0AEF3505F1CAA6485D4238D999A3EF4B0A59A1CDBE0
// Benchmarking key generation
fn keypair_bench(c: &mut Criterion) {
let mut rng = rand::thread_rng();
c.bench_function(
"Keypair Generation",
|b| b.iter(
|| {
c.bench_function("Keypair Generation", |b| {
b.iter(|| {
let _keys = keypair(&mut rng);
}
)
);
})
});
}
// Encapsulating a single public key
fn encap_bench(c: &mut Criterion) {
let pk = crate::decode_hex(PK_HEX);
let mut rng = rand::thread_rng();
c.bench_function(
"Encapsulate",
|b| b.iter(
|| {
c.bench_function("Encapsulate", |b| {
b.iter(|| {
let _enc = encapsulate(&pk, &mut rng);
}
)
);
})
});
}
// Decapsulating a single correct ciphertext
fn decap_bench(c: &mut Criterion) {
let sk = decode_hex(SK_HEX);
let ct = decode_hex(CT_HEX);
c.bench_function(
"Decapsulate",
|b| b.iter(
|| {
c.bench_function("Decapsulate", |b| {
b.iter(|| {
let _dec = decapsulate(&ct, &sk);
}
)
);
})
});
}
// Decapsulating a single incorrect ciphertext
fn decap_fail_bench(c: &mut Criterion) {
let sk = decode_hex(BAD_SK);
let ct = decode_hex(CT_HEX);
c.bench_function(
"Decapsulate Failure",
|b| b.iter(
|| {
c.bench_function("Decapsulate Failure", |b| {
b.iter(|| {
let _dec = decapsulate(&ct, &sk);
}
)
);
})
});
}
criterion_group!(benches, keypair_bench, encap_bench, decap_bench, decap_fail_bench);

View file

@ -13,9 +13,7 @@ fn main() -> Result<(), KyberError> {
// Bob receives the request and authenticates Alice, sends
// encapsulated shared secret back
let server_send = bob.server_receive(
client_send, &alice_keys.public, &bob_keys.secret, &mut rng
)?;
let server_send = bob.server_receive(client_send, &alice_keys.public, &bob_keys.secret, &mut rng)?;
// Alice autheticates and decapsulates
alice.client_confirm(server_send, &alice_keys.secret)?;

View file

@ -13,9 +13,7 @@ fn main() -> Result<(), KyberError> {
// Bob receives the request and authenticates Alice, sends
// encapsulated shared secret back
let server_send = bob.server_receive(
client_send, &bob_keys.secret, &mut rng
)?;
let server_send = bob.server_receive(client_send, &bob_keys.secret, &mut rng)?;
// Alice autheticates and decapsulates
alice.client_confirm(server_send)?;

View file

@ -7,11 +7,13 @@ fn main() -> Result<(), KyberError> {
const SKBYTES: usize = KYBER_SECRETKEYBYTES;
loop {
fuzz!(|data: &[u8]| {
if data.len() != CTBYTES + SKBYTES {return};
if data.len() != CTBYTES + SKBYTES {
return;
};
match crypto_kem_dec(&mut ss, &data[..CTBYTES], &data[CTBYTES..SKBYTES]) {
Ok(_) => (),
Err(_) => ()
Err(_) => (),
}
});
};
}
}

View file

@ -1,6 +1,6 @@
use honggfuzz::fuzz;
use pqc_kyber::*;
use rand_xoshiro::rand_core::{SeedableRng, RngCore};
use rand_xoshiro::rand_core::{RngCore, SeedableRng};
use rand_xoshiro::Xoshiro256Plus;
fn main() -> Result<(), KyberError> {
@ -12,8 +12,10 @@ fn main() -> Result<(), KyberError> {
loop {
rng.fill_bytes(&mut s1);
fuzz!(|data: &[u8]| {
if data.len() != KYBER_PUBLICKEYBYTES {return};
if data.len() != KYBER_PUBLICKEYBYTES {
return;
};
crypto_kem_enc(&mut ct, &mut ss, data, &mut _rng, Some(&s1));
});
};
}
}

View file

@ -1,6 +1,6 @@
use honggfuzz::fuzz;
use pqc_kyber::*;
use rand_xoshiro::rand_core::{SeedableRng, RngCore};
use rand_xoshiro::rand_core::{RngCore, SeedableRng};
use rand_xoshiro::Xoshiro256Plus;
fn main() -> Result<(), KyberError> {
@ -16,5 +16,5 @@ fn main() -> Result<(), KyberError> {
fuzz!(|data: ()| {
crypto_kem_keypair(&mut public, &mut secret, &mut _rng, Some((&s1, &s2)));
});
};
}
}

View file

@ -1,9 +1,9 @@
use crate::{
params::*,
error::KyberError,
RngCore, CryptoRng,
kem::*,
kex::{PublicKey, SecretKey, Encapsulated, Decapsulated}
kex::{Decapsulated, Encapsulated, PublicKey, SecretKey},
params::*,
CryptoRng, RngCore,
};
/// Keypair generation with a provided RNG.
@ -17,7 +17,8 @@ use crate::{
/// # Ok(())}
/// ```
pub fn keypair<R>(rng: &mut R) -> Keypair
where R: RngCore + CryptoRng
where
R: RngCore + CryptoRng,
{
let mut public = [0u8; KYBER_PUBLICKEYBYTES];
let mut secret = [0u8; KYBER_SECRETKEYBYTES];
@ -38,10 +39,11 @@ pub fn keypair<R>(rng: &mut R) -> Keypair
/// # Ok(())}
/// ```
pub fn encapsulate<R>(pk: &[u8], rng: &mut R) -> Encapsulated
where R: CryptoRng + RngCore
where
R: CryptoRng + RngCore,
{
if pk.len() != KYBER_PUBLICKEYBYTES {
return Err(KyberError::InvalidInput)
return Err(KyberError::InvalidInput);
}
let mut ct = [0u8; KYBER_CIPHERTEXTBYTES];
let mut ss = [0u8; KYBER_SSBYTES];
@ -63,15 +65,14 @@ pub fn encapsulate<R>(pk: &[u8], rng: &mut R) -> Encapsulated
/// assert_eq!(ss1, ss2);
/// # Ok(())}
/// ```
pub fn decapsulate(ct: &[u8], sk: &[u8]) -> Decapsulated
{
pub fn decapsulate(ct: &[u8], sk: &[u8]) -> Decapsulated {
if ct.len() != KYBER_CIPHERTEXTBYTES || sk.len() != KYBER_SECRETKEYBYTES {
return Err(KyberError::InvalidInput)
return Err(KyberError::InvalidInput);
}
let mut ss = [0u8; KYBER_SSBYTES];
match crypto_kem_dec(&mut ss, ct, sk) {
Ok(_) => Ok(ss),
Err(e) => Err(e)
Err(e) => Err(e),
}
}
@ -81,7 +82,7 @@ pub fn decapsulate(ct: &[u8], sk: &[u8]) -> Decapsulated
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Keypair {
pub public: PublicKey,
pub secret: SecretKey
pub secret: SecretKey,
}
impl Keypair {

View file

@ -10,22 +10,16 @@ use core::arch::x86_64::*;
#[repr(C)]
pub(crate) struct Aes256CtrCtx {
pub rkeys: [__m128i; 16],
pub n: __m128i
pub n: __m128i,
}
impl Aes256CtrCtx {
pub fn new() -> Self {
unsafe {
Self {
rkeys: [_mm_setzero_si128(); 16],
n: _mm_setzero_si128()
}
}
unsafe { Self { rkeys: [_mm_setzero_si128(); 16], n: _mm_setzero_si128() } }
}
}
unsafe fn aesni_encrypt4(out: &mut[u8], n :&mut __m128i, rkeys: &[__m128i; 16])
{
unsafe fn aesni_encrypt4(out: &mut [u8], n: &mut __m128i, rkeys: &[__m128i; 16]) {
let idx: __m128i = _mm_set_epi8(8, 9, 10, 11, 12, 13, 14, 15, 7, 6, 5, 4, 3, 2, 1, 0);
// Load current counter value
@ -69,18 +63,15 @@ unsafe fn aesni_encrypt4(out: &mut[u8], n :&mut __m128i, rkeys: &[__m128i; 16])
}
// Casting aliases
unsafe fn cast_128i(x: __m128) -> __m128i
{
unsafe fn cast_128i(x: __m128) -> __m128i {
_mm_castps_si128(x)
}
unsafe fn cast_128(x: __m128i) -> __m128
{
unsafe fn cast_128(x: __m128i) -> __m128 {
_mm_castsi128_ps(x)
}
pub(crate) fn aes256ctr_init(state: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12])
{
pub(crate) fn aes256ctr_init(state: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12]) {
unsafe {
let mut idx = 0;
let key0 = _mm_loadu_si128(key.as_ptr() as *const __m128i);
@ -142,36 +133,38 @@ pub(crate) fn aes256ctr_init(state: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 1
}
}
pub(crate) fn aes256ctr_squeezeblocks(out: &mut[u8], nblocks: usize, state: &mut Aes256CtrCtx)
{
pub(crate) fn aes256ctr_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut Aes256CtrCtx) {
let mut idx = 0;
for _ in 0..nblocks {
unsafe { aesni_encrypt4(&mut out[idx..], &mut state.n, &state.rkeys); }
unsafe {
aesni_encrypt4(&mut out[idx..], &mut state.n, &state.rkeys);
}
idx += 64
}
}
#[cfg(feature = "90s")]
pub(crate) fn aes256ctr_prf(out: &mut[u8], mut outlen: usize, seed: &[u8], nonce: u8)
{
pub(crate) fn aes256ctr_prf(out: &mut [u8], mut outlen: usize, seed: &[u8], nonce: u8) {
let mut buf = [0u8; 64];
let mut idx = 0;
let mut pad_nonce = [0u8; 12];
let mut state = unsafe{
Aes256CtrCtx{rkeys: [ _mm_setzero_si128(); 16], n: _mm_setzero_si128()}
};
let mut state = unsafe { Aes256CtrCtx { rkeys: [_mm_setzero_si128(); 16], n: _mm_setzero_si128() } };
pad_nonce[0] = nonce;
aes256ctr_init(&mut state, seed, pad_nonce);
while outlen >= 64 {
unsafe { aesni_encrypt4(&mut out[idx..], &mut state.n, &state.rkeys); }
unsafe {
aesni_encrypt4(&mut out[idx..], &mut state.n, &state.rkeys);
}
outlen -= 64;
idx += 64;
}
if outlen != 0 {
unsafe { aesni_encrypt4(&mut buf, &mut state.n, &state.rkeys); }
unsafe {
aesni_encrypt4(&mut buf, &mut state.n, &state.rkeys);
}
out[idx..][..outlen].copy_from_slice(&buf[..outlen]);
}
}

View file

@ -1,11 +1,11 @@
#![allow(dead_code)]
use core::arch::x86_64::*;
use crate::avx2::rejsample::REJ_UNIFORM_AVX_NBLOCKS;
use crate::fips202::{SHAKE128_RATE, SHAKE256_RATE};
use crate::params::*;
use crate::poly::NOISE_NBLOCKS;
use crate::fips202::{SHAKE128_RATE, SHAKE256_RATE};
use crate::symmetric::*;
use crate::avx2::rejsample::REJ_UNIFORM_AVX_NBLOCKS;
use core::arch::x86_64::*;
// Buffer unions
// #[derive(Copy, Clone)]
@ -27,7 +27,7 @@ use crate::avx2::rejsample::REJ_UNIFORM_AVX_NBLOCKS;
#[repr(C, align(32))]
pub union GenMatrixBuf {
pub coeffs: [u8; REJ_UNIFORM_AVX_NBLOCKS * SHAKE128_RATE],
pub vec: [__m256i; (REJ_UNIFORM_AVX_NBLOCKS*SHAKE128_RATE+31)/32]
pub vec: [__m256i; (REJ_UNIFORM_AVX_NBLOCKS * SHAKE128_RATE + 31) / 32],
}
impl GenMatrixBuf {
@ -39,25 +39,23 @@ impl GenMatrixBuf {
#[cfg(feature = "90s")]
#[repr(C)]
pub union GenMatrixBuf90s {
pub coeffs:
[u8; REJ_UNIFORM_AVX_NBLOCKS*XOF_BLOCKBYTES],
pub vec:
[__m256i; (REJ_UNIFORM_AVX_NBLOCKS*XOF_BLOCKBYTES+31)/32]
pub coeffs: [u8; REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES],
pub vec: [__m256i; (REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES + 31) / 32],
}
#[cfg(feature = "90s")]
impl GenMatrixBuf90s {
pub fn new() -> Self {
Self {
coeffs: [0u8; REJ_UNIFORM_AVX_NBLOCKS*XOF_BLOCKBYTES]
}
Self { coeffs: [0u8; REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES] }
}
#[cfg(debug_assertions)]
pub fn checksum(&self) -> i16 {
let mut out = 0;
for i in 0..REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES {
unsafe { out ^= self.coeffs[i] as i16; }
unsafe {
out ^= self.coeffs[i] as i16;
}
}
out
}
@ -65,20 +63,14 @@ impl GenMatrixBuf90s {
#[repr(C)]
pub union IndcpaBuf {
pub coeffs: [u8;
(KYBER_ETA1*KYBER_N/4)
/XOF_BLOCKBYTES*XOF_BLOCKBYTES+32],
pub vec: [__m256i;
((KYBER_ETA1*KYBER_N/4)
/XOF_BLOCKBYTES*XOF_BLOCKBYTES+32+31)/32]
pub coeffs: [u8; (KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES * XOF_BLOCKBYTES + 32],
pub vec: [__m256i; ((KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES * XOF_BLOCKBYTES + 32 + 31) / 32],
}
impl IndcpaBuf {
pub fn new() -> Self {
Self {
coeffs: [0u8;
(KYBER_ETA1*KYBER_N/4)
/XOF_BLOCKBYTES*XOF_BLOCKBYTES+32]
coeffs: [0u8; (KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES * XOF_BLOCKBYTES + 32],
}
}
}
@ -86,7 +78,7 @@ impl IndcpaBuf {
#[repr(C, align(8))]
pub union Eta2Buf {
pub coeffs: [u8; KYBER_ETA2 * KYBER_N / 4],
pub vec: [__m256i; (KYBER_ETA2*KYBER_N/4+31)/32]
pub vec: [__m256i; (KYBER_ETA2 * KYBER_N / 4 + 31) / 32],
}
impl Eta2Buf {
@ -99,7 +91,7 @@ impl Eta2Buf {
#[repr(C, align(8))]
pub union Eta4xBuf {
pub coeffs: [u8; NOISE_NBLOCKS * SHAKE256_RATE],
pub vec: [__m256i; (NOISE_NBLOCKS*SHAKE256_RATE+31)/32]
pub vec: [__m256i; (NOISE_NBLOCKS * SHAKE256_RATE + 31) / 32],
}
impl Eta4xBuf {
@ -107,4 +99,3 @@ impl Eta4xBuf {
Self { coeffs: [0u8; NOISE_NBLOCKS * SHAKE256_RATE] }
}
}

View file

@ -1,11 +1,10 @@
#![allow(non_snake_case, dead_code)]
use core::arch::x86_64::*;
use crate::params::KYBER_N;
use crate::poly::*;
use crate::align::Eta4xBuf;
#[cfg(feature = "90s")]
use crate::align::IndcpaBuf;
use crate::params::KYBER_N;
use crate::poly::*;
use core::arch::x86_64::*;
fn cbd2(r: &mut Poly, buf: &[__m256i]) {
unsafe {
@ -59,8 +58,7 @@ fn cbd3(r: &mut Poly, buf: &[u8]) {
let mask70: __m256i = _mm256_set1_epi32(7 << 16);
let mask: __m256i = _mm256_set1_epi16(3);
let shufbidx: __m256i = _mm256_set_epi8(
-1,15,14,13,-1,12,11,10,-1, 9, 8, 7,-1, 6, 5, 4,
-1,11,10, 9,-1, 8, 7, 6,-1, 5, 4, 3,-1, 2, 1, 0
-1, 15, 14, 13, -1, 12, 11, 10, -1, 9, 8, 7, -1, 6, 5, 4, -1, 11, 10, 9, -1, 8, 7, 6, -1, 5, 4, 3, -1, 2, 1, 0,
);
for i in 0..(KYBER_N / 32) {
@ -104,33 +102,27 @@ fn cbd3(r: &mut Poly, buf: &[u8]) {
}
}
pub fn poly_cbd_eta1(r: &mut Poly, buf: &Eta4xBuf)
{
pub fn poly_cbd_eta1(r: &mut Poly, buf: &Eta4xBuf) {
unsafe {
if cfg!(feature = "kyber512") {
cbd3(r, &buf.coeffs)
}
else {
} else {
cbd2(r, &buf.vec)
}
}
}
#[cfg(feature = "90s")]
pub fn poly_cbd_eta1_90s(r: &mut Poly, buf: &IndcpaBuf)
{
pub fn poly_cbd_eta1_90s(r: &mut Poly, buf: &IndcpaBuf) {
unsafe {
if cfg!(feature = "kyber512") {
cbd3(r, &buf.coeffs)
}
else {
} else {
cbd2(r, &buf.vec)
}
}
}
pub fn poly_cbd_eta2(r: &mut Poly, buf: &[__m256i])
{
pub fn poly_cbd_eta2(r: &mut Poly, buf: &[__m256i]) {
cbd2(r, &buf)
}

View file

@ -1,5 +1,5 @@
use core::arch::x86_64::*;
use crate::params::KYBER_Q;
use core::arch::x86_64::*;
pub(crate) const Q: i16 = KYBER_Q as i16;
// pub(crate) const MONT: i16 = -1044; // 2^16 mod q
@ -28,89 +28,42 @@ pub(crate) const _16XSHIFT: usize = 624;
#[repr(C, align(32))]
pub union Qdata {
pub coeffs: [i16; 640],
pub vec: [__m256i; 40]
pub vec: [__m256i; 40],
}
pub const QDATA: Qdata = Qdata { coeffs:
[ Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q,
QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV,
QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV,
V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V,
FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO,
FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO,
FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI,
FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI,
MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO,
MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO,
MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO,
MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO,
MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI,
MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI,
MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI,
MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI,
MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK,
MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK,
3854, 3340, 2826, 2312, 1798, 1284, 770, 256,
3854, 3340, 2826, 2312, 1798, 1284, 770, 256,
7, 0, 6, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
31498, 31498, 31498, 31498, -758, -758, -758, -758,
5237, 5237, 5237, 5237, 1397, 1397, 1397, 1397,
14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745,
14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745,
-359, -359, -359, -359, -359, -359, -359, -359,
-359, -359, -359, -359, -359, -359, -359, -359,
13525, 13525, 13525, 13525, 13525, 13525, 13525, 13525,
-12402, -12402, -12402, -12402, -12402, -12402, -12402, -12402,
1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493,
1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422,
-20907, -20907, -20907, -20907, 27758, 27758, 27758, 27758,
-3799, -3799, -3799, -3799, -15690, -15690, -15690, -15690,
-171, -171, -171, -171, 622, 622, 622, 622,
1577, 1577, 1577, 1577, 182, 182, 182, 182,
-5827, -5827, 17363, 17363, -26360, -26360, -29057, -29057,
5571, 5571, -1102, -1102, 21438, 21438, -26242, -26242,
573, 573, -1325, -1325, 264, 264, 383, 383,
-829, -829, 1458, 1458, -1602, -1602, -130, -130,
-5689, -6516, 1496, 30967, -23565, 20179, 20710, 25080,
-12796, 26616, 16064, -12442, 9134, -650, -25986, 27837,
1223, 652, -552, 1015, -1293, 1491, -282, -1544,
516, -8, -320, -666, -1618, -1162, 126, 1469,
-335, -11477, -32227, 20494, -27738, 945, -14883, 6182,
32010, 10631, 29175, -28762, -18486, 17560, -14430, -5276,
-1103, 555, -1251, 1550, 422, 177, -291, 1574,
-246, 1159, -777, -602, -1590, -872, 418, -156,
11182, 13387, -14233, -21655, 13131, -4587, 23092, 5493,
-32502, 30317, -18741, 12639, 20100, 18525, 19529, -12619,
430, 843, 871, 105, 587, -235, -460, 1653,
778, -147, 1483, 1119, 644, 349, 329, -75,
787, 787, 787, 787, 787, 787, 787, 787,
787, 787, 787, 787, 787, 787, 787, 787,
-1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517,
-1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517,
28191, 28191, 28191, 28191, 28191, 28191, 28191, 28191,
-16694, -16694, -16694, -16694, -16694, -16694, -16694, -16694,
287, 287, 287, 287, 287, 287, 287, 287,
202, 202, 202, 202, 202, 202, 202, 202,
10690, 10690, 10690, 10690, 1358, 1358, 1358, 1358,
-11202, -11202, -11202, -11202, 31164, 31164, 31164, 31164,
962, 962, 962, 962, -1202, -1202, -1202, -1202,
-1474, -1474, -1474, -1474, 1468, 1468, 1468, 1468,
-28073, -28073, 24313, 24313, -10532, -10532, 8800, 8800,
18426, 18426, 8859, 8859, 26675, 26675, -16163, -16163,
-681, -681, 1017, 1017, 732, 732, 608, 608,
-1542, -1542, 411, 411, -205, -205, -1571, -1571,
19883, -28250, -15887, -8898, -28309, 9075, -30199, 18249,
13426, 14017, -29156, -12757, 16832, 4311, -24155, -17915,
-853, -90, -271, 830, 107, -1421, -247, -951,
-398, 961, -1508, -725, 448, -1065, 677, -1275,
-31183, 25435, -7382, 24391, -20927, 10946, 24214, 16989,
10335, -7934, -22502, 10906, 31636, 28644, 23998, -17422,
817, 603, 1322, -1465, -1215, 1218, -874, -1187,
-1185, -1278, -1510, -870, -108, 996, 958, 1522,
20297, 2146, 15355, -32384, -6280, -14903, -11044, 14469,
-21498, -20198, 23210, -17442, -23860, -20257, 7756, 23132,
1097, 610, -1285, 384, -136, -1335, 220, -1659,
-1530, 794, -854, 478, -308, 991, -1460, 1628,
SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT,
SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT ]
pub const QDATA: Qdata = Qdata {
coeffs: [
Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV,
QINV, QINV, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, V, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO,
FLO, FLO, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO,
MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQHI,
MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI,
MONTSQHI, MONTSQHI, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, 3854, 3340,
2826, 2312, 1798, 1284, 770, 256, 3854, 3340, 2826, 2312, 1798, 1284, 770, 256, 7, 0, 6, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0,
31498, 31498, 31498, 31498, -758, -758, -758, -758, 5237, 5237, 5237, 5237, 1397, 1397, 1397, 1397, 14745, 14745, 14745, 14745,
14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, -359, -359, -359, -359, -359, -359, -359, -359,
-359, -359, -359, -359, -359, -359, -359, -359, 13525, 13525, 13525, 13525, 13525, 13525, 13525, 13525, -12402, -12402, -12402,
-12402, -12402, -12402, -12402, -12402, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1422, 1422, 1422, 1422, 1422, 1422, 1422,
1422, -20907, -20907, -20907, -20907, 27758, 27758, 27758, 27758, -3799, -3799, -3799, -3799, -15690, -15690, -15690, -15690, -171,
-171, -171, -171, 622, 622, 622, 622, 1577, 1577, 1577, 1577, 182, 182, 182, 182, -5827, -5827, 17363, 17363, -26360, -26360,
-29057, -29057, 5571, 5571, -1102, -1102, 21438, 21438, -26242, -26242, 573, 573, -1325, -1325, 264, 264, 383, 383, -829, -829,
1458, 1458, -1602, -1602, -130, -130, -5689, -6516, 1496, 30967, -23565, 20179, 20710, 25080, -12796, 26616, 16064, -12442, 9134,
-650, -25986, 27837, 1223, 652, -552, 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666, -1618, -1162, 126, 1469, -335, -11477,
-32227, 20494, -27738, 945, -14883, 6182, 32010, 10631, 29175, -28762, -18486, 17560, -14430, -5276, -1103, 555, -1251, 1550, 422,
177, -291, 1574, -246, 1159, -777, -602, -1590, -872, 418, -156, 11182, 13387, -14233, -21655, 13131, -4587, 23092, 5493, -32502,
30317, -18741, 12639, 20100, 18525, 19529, -12619, 430, 843, 871, 105, 587, -235, -460, 1653, 778, -147, 1483, 1119, 644, 349, 329,
-75, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, 787, -1517, -1517, -1517, -1517, -1517, -1517,
-1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, 28191, 28191, 28191, 28191, 28191, 28191, 28191, 28191,
-16694, -16694, -16694, -16694, -16694, -16694, -16694, -16694, 287, 287, 287, 287, 287, 287, 287, 287, 202, 202, 202, 202, 202,
202, 202, 202, 10690, 10690, 10690, 10690, 1358, 1358, 1358, 1358, -11202, -11202, -11202, -11202, 31164, 31164, 31164, 31164, 962,
962, 962, 962, -1202, -1202, -1202, -1202, -1474, -1474, -1474, -1474, 1468, 1468, 1468, 1468, -28073, -28073, 24313, 24313,
-10532, -10532, 8800, 8800, 18426, 18426, 8859, 8859, 26675, 26675, -16163, -16163, -681, -681, 1017, 1017, 732, 732, 608, 608,
-1542, -1542, 411, 411, -205, -205, -1571, -1571, 19883, -28250, -15887, -8898, -28309, 9075, -30199, 18249, 13426, 14017, -29156,
-12757, 16832, 4311, -24155, -17915, -853, -90, -271, 830, 107, -1421, -247, -951, -398, 961, -1508, -725, 448, -1065, 677, -1275,
-31183, 25435, -7382, 24391, -20927, 10946, 24214, 16989, 10335, -7934, -22502, 10906, 31636, 28644, 23998, -17422, 817, 603, 1322,
-1465, -1215, 1218, -874, -1187, -1185, -1278, -1510, -870, -108, 996, 958, 1522, 20297, 2146, 15355, -32384, -6280, -14903,
-11044, 14469, -21498, -20198, 23210, -17442, -23860, -20257, 7756, 23132, 1097, 610, -1285, 384, -136, -1335, 220, -1659, -1530,
794, -854, 478, -308, 991, -1460, 1628, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT,
SHIFT, SHIFT, SHIFT,
],
};

View file

@ -7,8 +7,7 @@ const SHA3_256_RATE: usize = 136;
const SHA3_512_RATE: usize = 72;
const NROUNDS: usize = 24;
fn rol(a: u64, offset: u64) -> u64
{
fn rol(a: u64, offset: u64) -> u64 {
(a << offset) ^ (a >> (64 - offset))
}
@ -19,8 +18,7 @@ fn rol(a: u64, offset: u64) -> u64
// Arguments: - const [u8] x: input byte array
//
// Returns the loaded 64-bit unsigned integer
pub fn load64(x: &[u8]) -> u64
{
pub fn load64(x: &[u8]) -> u64 {
let mut r = 0u64;
for i in 0..8 {
r |= (x[i] as u64) << (8 * i);
@ -34,8 +32,7 @@ pub fn load64(x: &[u8]) -> u64
//
// Arguments: - [u8] x: the output byte array
// - u64 u: input 64-bit unsigned integer
pub fn store64(x: &mut[u8], mut u: u64)
{
pub fn store64(x: &mut [u8], mut u: u64) {
for i in x.iter_mut().take(8) {
*i = u as u8;
u >>= 8;
@ -67,7 +64,7 @@ const KECCAKF_ROUNDCONSTANTS: [u64; NROUNDS] = [
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008
0x8000000080008008,
];
// Name: KeccakF1600_StatePermute
@ -75,8 +72,7 @@ const KECCAKF_ROUNDCONSTANTS: [u64; NROUNDS] = [
// Description: The Keccak F1600 Permutation
//
// Arguments: - u64 * state: in/output Keccak state
pub(crate) fn keccakf1600_statepermute(state: &mut[u64])
{
pub(crate) fn keccakf1600_statepermute(state: &mut [u64]) {
//copyFromState(A, state)
let mut aba = state[0];
let mut abe = state[1];
@ -333,14 +329,7 @@ pub(crate) fn keccakf1600_statepermute(state: &mut[u64])
// - usize r: rate in bytes (e.g., 168 for SHAKE128)
// - const [u8] input: pointer to input to be absorbed into s
// - u64 inlen: length of input in bytes
pub(crate) fn keccak_absorb(
s: &mut[u64],
mut pos: usize,
r: usize,
input: &[u8],
mut inlen: usize
) -> usize
{
pub(crate) fn keccak_absorb(s: &mut [u64], mut pos: usize, r: usize, input: &[u8], mut inlen: usize) -> usize {
let mut idx = 0usize;
while pos + inlen >= r {
for i in pos..r {
@ -368,8 +357,7 @@ pub(crate) fn keccak_absorb(
// - u64 nblocks: number of blocks to be squeezed (written to h)
// - u64 *s: in/output Keccak state
// - usize r: rate in bytes (e.g., 168 for SHAKE128)
pub(crate) fn keccak_squeezeblocks(h: &mut[u8], mut nblocks: usize, s: &mut [u64], r: usize)
{
pub(crate) fn keccak_squeezeblocks(h: &mut [u8], mut nblocks: usize, s: &mut [u64], r: usize) {
let mut idx = 0usize;
while nblocks > 0 {
keccakf1600_statepermute(s);
@ -389,8 +377,7 @@ pub(crate) fn keccak_squeezeblocks(h: &mut[u8], mut nblocks: usize, s: &mut [u64
// Arguments: - u64 *s: (uninitialized) output Keccak state
// - const [u8] input: input to be absorbed into s
// - u64 inputByteLen: length of input in bytes
pub(crate) fn shake128_absorb(state: &mut KeccakState, input: &[u8], inlen: usize)
{
pub(crate) fn shake128_absorb(state: &mut KeccakState, input: &[u8], inlen: usize) {
let pos = state.pos;
state.pos = keccak_absorb(&mut state.s, pos, SHAKE128_RATE, input, inlen);
}
@ -405,8 +392,7 @@ pub(crate) fn shake128_absorb(state: &mut KeccakState, input: &[u8], inlen: usiz
// Arguments: - [u8] out: pointer to output blocks
// - u64 nblocks: number of blocks to be squeezed (written to output)
// - KeccakState state: pointer to input/output Keccak state
pub(crate) fn shake128_squeezeblocks(out: &mut[u8], nblocks: usize, state: &mut KeccakState)
{
pub(crate) fn shake128_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) {
keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE128_RATE);
}
@ -418,8 +404,7 @@ pub(crate) fn shake128_squeezeblocks(out: &mut[u8], nblocks: usize, state: &mut
// - usize outlen: requested output length in bytes
// - [u8] input: input
// - usize inlen: length of input in bytes
pub(crate) fn shake256(out: &mut[u8], mut outlen: usize, input: &[u8], inlen: usize)
{
pub(crate) fn shake256(out: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) {
let mut state = KeccakState::new();
let mut idx = 0;
shake256_absorb_once(&mut state, input, inlen);
@ -437,8 +422,7 @@ pub(crate) fn shake256(out: &mut[u8], mut outlen: usize, input: &[u8], inlen: us
// Arguments: - [u8] h: output (32 bytes)
// - const [u8] input: input
// - usize inlen: length of input in bytes
pub(crate) fn sha3_256(h: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn sha3_256(h: &mut [u8], input: &[u8], inlen: usize) {
let mut s = [0u64; 25];
keccak_absorb_once(&mut s, SHA3_256_RATE, input, inlen, 0x06);
keccakf1600_statepermute(&mut s);
@ -454,8 +438,7 @@ pub(crate) fn sha3_256(h: &mut[u8], input: &[u8], inlen: usize)
// Arguments: - [u8] h: output (64 bytes)
// - const [u8] input: input
// - usize inlen: length of input in bytes
pub(crate) fn sha3_512(h: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn sha3_512(h: &mut [u8], input: &[u8], inlen: usize) {
let mut s = [0u64; 25];
keccak_absorb_once(&mut s, SHA3_512_RATE, input, inlen, 0x06);
keccakf1600_statepermute(&mut s);
@ -464,8 +447,6 @@ pub(crate) fn sha3_512(h: &mut[u8], input: &[u8], inlen: usize)
}
}
// Name: keccak_finalize
//
// Description: Finalize absorb step.
@ -474,8 +455,7 @@ pub(crate) fn sha3_512(h: &mut[u8], input: &[u8], inlen: usize)
// - usize pos: position in current block to be absorbed
// - usize r: rate in bytes (e.g., 168 for SHAKE128)
// - u8 p: domain separation byte
fn keccak_finalize(s: &mut[u64], pos: usize, r: usize, p: u8)
{
fn keccak_finalize(s: &mut [u64], pos: usize, r: usize, p: u8) {
s[pos / 8] ^= (p as u64) << 8 * (pos % 8);
s[r / 8 - 1] ^= 1u64 << 63;
}
@ -490,14 +470,7 @@ fn keccak_finalize(s: &mut[u64], pos: usize, r: usize, p: u8)
// - const [u8] input: input to be absorbed into s
// - u64 mlen: length of input in bytes
// - [u8] p: domain-separation byte for different Keccak-derived functions
pub(crate) fn keccak_absorb_once(
s: &mut[u64],
r: usize,
input: &[u8],
mut inlen:
usize,
p: u8)
{
pub(crate) fn keccak_absorb_once(s: &mut [u64], r: usize, input: &[u8], mut inlen: usize, p: u8) {
// Zero State
for i in s.iter_mut() {
*i = 0;
@ -532,14 +505,7 @@ pub(crate) fn keccak_absorb_once(
// usize pos: number of bytes in current block already squeezed
// - usize r: rate in bytes (e.g., 168 for SHAKE128)
// Returns new position pos in current block
pub(crate) fn keccak_squeeze(
out: &mut[u8],
mut outlen: usize,
s: &mut [u64],
mut pos: usize,
r: usize
) -> usize
{
pub(crate) fn keccak_squeeze(out: &mut [u8], mut outlen: usize, s: &mut [u64], mut pos: usize, r: usize) -> usize {
let mut idx = 0;
while outlen > 0 {
if pos == r {
@ -563,19 +529,16 @@ pub(crate) fn keccak_squeeze(
// Description: Initializes Keccak state for use as SHAKE128 XOF
//
// Arguments: - keccak_state state: (uninitialized) Keccak state
fn shake128_init(state: &mut KeccakState)
{
fn shake128_init(state: &mut KeccakState) {
state.reset()
}
// Name: shake128_finalize
//
// Description: Finalize absorb step of the SHAKE128 XOF.
//
// Arguments: - keccak_state state: pointer to Keccak state
fn shake128_finalize(state: &mut KeccakState)
{
fn shake128_finalize(state: &mut KeccakState) {
keccak_finalize(&mut state.s, state.pos, SHAKE128_RATE, 0x1F);
state.pos = SHAKE128_RATE;
}
@ -588,8 +551,7 @@ fn shake128_finalize(state: &mut KeccakState)
// Arguments: - [u8] out: pointer to output blocks
// - usize outlen : number of bytes to be squeezed (written to output)
// - keccak_state s: pointer to input/output Keccak state
fn shake128_squeeze(out: &mut[u8], outlen: usize, state: &mut KeccakState)
{
fn shake128_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) {
state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE128_RATE);
}
@ -600,8 +562,7 @@ fn shake128_squeeze(out: &mut[u8], outlen: usize, state: &mut KeccakState)
// Arguments: - keccak_state state: pointer to (uninitialized) output Keccak state
// - const [u8] in: input to be absorbed into s
// - usize inlen: length of input in bytes
pub(crate) fn shake128_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize)
{
pub(crate) fn shake128_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) {
keccak_absorb_once(&mut state.s, SHAKE128_RATE, input, inlen, 0x1F);
state.pos = SHAKE128_RATE;
}
@ -610,35 +571,29 @@ fn shake256_init(state: &mut KeccakState) {
state.reset();
}
fn shake256_absorb(state: &mut KeccakState, input: &[u8], inlen: usize)
{
fn shake256_absorb(state: &mut KeccakState, input: &[u8], inlen: usize) {
state.pos = keccak_absorb(&mut state.s, state.pos, SHAKE256_RATE, input, inlen);
}
fn shake256_finalize(state: &mut KeccakState)
{
fn shake256_finalize(state: &mut KeccakState) {
keccak_finalize(&mut state.s, state.pos, SHAKE256_RATE, 0x1F);
state.pos = SHAKE256_RATE;
}
fn shake256_squeeze(out: &mut[u8], outlen: usize, state: &mut KeccakState)
{
fn shake256_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) {
state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE256_RATE);
}
pub(crate) fn shake256_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize)
{
pub(crate) fn shake256_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) {
keccak_absorb_once(&mut state.s, SHAKE256_RATE, input, inlen, 0x1F);
state.pos = SHAKE256_RATE;
}
fn shake256_squeezeblocks(out: &mut[u8], nblocks: usize, state: &mut KeccakState)
{
fn shake256_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) {
keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE256_RATE);
}
fn shake128(out: &mut[u8], mut outlen: usize, input: &[u8], inlen: usize)
{
fn shake128(out: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) {
let mut state = KeccakState::new();
let mut idx = 0;
shake128_absorb_once(&mut state, input, inlen);
@ -648,4 +603,3 @@ fn shake128(out: &mut[u8], mut outlen: usize, input: &[u8], inlen: usize)
idx += nblocks * SHAKE128_RATE;
shake128_squeeze(&mut out[idx..], outlen, &mut state);
}

View file

@ -1,13 +1,13 @@
#![allow(dead_code)]
use core::arch::x86_64::*;
use crate::align::{Eta4xBuf, GenMatrixBuf};
use crate::fips202::*;
use crate::keccak4x::f1600_x4;
use crate::align::{GenMatrixBuf, Eta4xBuf};
use core::arch::x86_64::*;
#[repr(C)]
pub struct Keccakx4State {
s: [__m256i; 25]
s: [__m256i; 25],
}
impl Keccakx4State {
@ -24,20 +24,14 @@ pub unsafe fn keccakx4_absorb_once(
in2: &[u8],
in3: &[u8],
mut inlen: usize,
p: u8
)
{
p: u8,
) {
let mut pos = 0i64;
let mut t;
for i in 0..25 {
s[i] = _mm256_setzero_si256();
}
let mut idx = _mm256_set_epi64x(
in3.as_ptr() as i64,
in2.as_ptr() as i64,
in1.as_ptr() as i64,
in0.as_ptr() as i64,
);
let mut idx = _mm256_set_epi64x(in3.as_ptr() as i64, in2.as_ptr() as i64, in1.as_ptr() as i64, in0.as_ptr() as i64);
while inlen >= r {
for i in 0..(r / 8) {
t = _mm256_i64gather_epi64(pos as *const i64, idx, 1);
@ -68,13 +62,7 @@ pub unsafe fn keccakx4_absorb_once(
s[r / 8 - 1] = _mm256_xor_si256(s[r / 8 - 1], t);
}
pub unsafe fn keccakx4_squeezeblocks128(
out: &mut [GenMatrixBuf; 4],
mut nblocks: usize,
r: usize,
s: &mut [__m256i; 25]
)
{
pub unsafe fn keccakx4_squeezeblocks128(out: &mut [GenMatrixBuf; 4], mut nblocks: usize, r: usize, s: &mut [__m256i; 25]) {
let mut t;
let mut idx = 0usize;
while nblocks > 0 {
@ -97,13 +85,7 @@ pub unsafe fn keccakx4_squeezeblocks128(
}
}
pub unsafe fn keccakx4_squeezeblocks256(
out: &mut [Eta4xBuf; 4],
mut nblocks: usize,
r: usize,
s: &mut [__m256i; 25]
)
{
pub unsafe fn keccakx4_squeezeblocks256(out: &mut [Eta4xBuf; 4], mut nblocks: usize, r: usize, s: &mut [__m256i; 25]) {
let mut t;
let mut idx = 0usize;
while nblocks > 0 {
@ -156,66 +138,20 @@ pub unsafe fn keccakx4_squeezeblocks256(
// }
// }
pub unsafe fn shake128x4_absorb_once(
state: &mut Keccakx4State,
in0: &[u8],
in1: &[u8],
in2: &[u8],
in3: &[u8],
inlen: usize,
)
{
keccakx4_absorb_once(
&mut state.s,
SHAKE128_RATE,
in0, in1, in2, in3, inlen,
0x1F
)
pub unsafe fn shake128x4_absorb_once(state: &mut Keccakx4State, in0: &[u8], in1: &[u8], in2: &[u8], in3: &[u8], inlen: usize) {
keccakx4_absorb_once(&mut state.s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F)
}
pub unsafe fn shake128x4_squeezeblocks(
out: &mut[GenMatrixBuf; 4],
nblocks: usize,
state: &mut Keccakx4State
)
{
keccakx4_squeezeblocks128(
out,
nblocks,
SHAKE128_RATE,
&mut state.s
);
pub unsafe fn shake128x4_squeezeblocks(out: &mut [GenMatrixBuf; 4], nblocks: usize, state: &mut Keccakx4State) {
keccakx4_squeezeblocks128(out, nblocks, SHAKE128_RATE, &mut state.s);
}
pub unsafe fn shake256x4_absorb_once(
state: &mut Keccakx4State,
in0: &[u8],
in1: &[u8],
in2: &[u8],
in3: &[u8],
inlen: usize,
)
{
keccakx4_absorb_once(
&mut state.s,
SHAKE256_RATE,
in0, in1, in2, in3, inlen,
0x1F
)
pub unsafe fn shake256x4_absorb_once(state: &mut Keccakx4State, in0: &[u8], in1: &[u8], in2: &[u8], in3: &[u8], inlen: usize) {
keccakx4_absorb_once(&mut state.s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F)
}
pub unsafe fn shake256x4_squeezeblocks(
out: &mut[Eta4xBuf; 4],
nblocks: usize,
state: &mut Keccakx4State
)
{
keccakx4_squeezeblocks256(
out,
nblocks,
SHAKE256_RATE,
&mut state.s
);
pub unsafe fn shake256x4_squeezeblocks(out: &mut [Eta4xBuf; 4], nblocks: usize, state: &mut Keccakx4State) {
keccakx4_squeezeblocks256(out, nblocks, SHAKE256_RATE, &mut state.s);
}
// pub unsafe fn shake128x4(

View file

@ -1,20 +1,11 @@
use core::arch::x86_64::*;
#[cfg(not(feature = "90s"))]
use crate::{fips202::*, fips202x4::*};
#[cfg(feature = "90s")]
use crate::{aes256ctr::*, cbd::*};
#[cfg(not(feature = "KATs"))]
use crate::rng::randombytes;
use crate::{
align::*,
CryptoRng,
params::*,
poly::*,
polyvec::*,
rejsample::*,
RngCore,
symmetric::*,
};
#[cfg(feature = "90s")]
use crate::{aes256ctr::*, cbd::*};
use crate::{align::*, params::*, poly::*, polyvec::*, rejsample::*, symmetric::*, CryptoRng, RngCore};
#[cfg(not(feature = "90s"))]
use crate::{fips202::*, fips202x4::*};
use core::arch::x86_64::*;
// Name: pack_pk
//
@ -25,11 +16,9 @@ use crate::{
// Arguments: [u8] r: the output serialized public key
// const poly *pk: the input public-key polynomial
// const [u8] seed: the input public seed
fn pack_pk(r: &mut[u8], pk: &Polyvec, seed: &[u8])
{
fn pack_pk(r: &mut [u8], pk: &Polyvec, seed: &[u8]) {
polyvec_tobytes(r, pk);
r[KYBER_POLYVECBYTES..][..KYBER_SYMBYTES]
.copy_from_slice(&seed[..KYBER_SYMBYTES]);
r[KYBER_POLYVECBYTES..][..KYBER_SYMBYTES].copy_from_slice(&seed[..KYBER_SYMBYTES]);
}
// Name: unpack_pk
@ -40,11 +29,11 @@ fn pack_pk(r: &mut[u8], pk: &Polyvec, seed: &[u8])
// Arguments: - Polyvec pk: output public-key vector of polynomials
// - [u8] seed: output seed to generate matrix A
// - const [u8] packedpk: input serialized public key
fn unpack_pk(pk: &mut Polyvec, seed: &mut[u8], packedpk: &[u8])
{
unsafe {polyvec_frombytes(pk, packedpk);}
seed[..KYBER_SYMBYTES]
.copy_from_slice(&packedpk[KYBER_POLYVECBYTES..][..KYBER_SYMBYTES]);
fn unpack_pk(pk: &mut Polyvec, seed: &mut [u8], packedpk: &[u8]) {
unsafe {
polyvec_frombytes(pk, packedpk);
}
seed[..KYBER_SYMBYTES].copy_from_slice(&packedpk[KYBER_POLYVECBYTES..][..KYBER_SYMBYTES]);
}
// Name: pack_sk
@ -53,8 +42,7 @@ fn unpack_pk(pk: &mut Polyvec, seed: &mut[u8], packedpk: &[u8])
//
// Arguments: - [u8] r: output serialized secret key
// - const Polyvec sk: input vector of polynomials (secret key)
fn pack_sk(r: &mut[u8], sk: &Polyvec)
{
fn pack_sk(r: &mut [u8], sk: &Polyvec) {
polyvec_tobytes(r, sk);
}
@ -65,9 +53,10 @@ fn pack_sk(r: &mut[u8], sk: &Polyvec)
//
// Arguments: - Polyvec sk: output vector of polynomials (secret key)
// - const [u8] packedsk: input serialized secret key
fn unpack_sk(sk: &mut Polyvec, packedsk: &[u8])
{
unsafe {polyvec_frombytes(sk, packedsk);}
fn unpack_sk(sk: &mut Polyvec, packedsk: &[u8]) {
unsafe {
polyvec_frombytes(sk, packedsk);
}
}
// Name: pack_ciphertext
@ -79,8 +68,7 @@ fn unpack_sk(sk: &mut Polyvec, packedsk: &[u8])
// Arguments: [u8] r: the output serialized ciphertext
// const poly *pk: the input vector of polynomials b
// const [u8] seed: the input polynomial v
fn pack_ciphertext(r: &mut[u8], b: &Polyvec, v: Poly)
{
fn pack_ciphertext(r: &mut [u8], b: &Polyvec, v: Poly) {
unsafe {
polyvec_compress(r, b);
poly_compress(&mut r[KYBER_POLYVECCOMPRESSEDBYTES..], v);
@ -95,8 +83,7 @@ fn pack_ciphertext(r: &mut[u8], b: &Polyvec, v: Poly)
// Arguments: - Polyvec b: output vector of polynomials b
// - Poly *v: output polynomial v
// - const [u8] c: input serialized ciphertext
fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8])
{
fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8]) {
unsafe {
polyvec_decompress(b, c);
poly_decompress(v, &c[KYBER_POLYVECCOMPRESSEDBYTES..]);
@ -114,8 +101,7 @@ fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8])
// - usize buflen: length of input buffer in bytes
//
// Returns number of sampled 16-bit integers (at most len)
fn rej_uniform(r: &mut[i16], len: usize, buf: &[u8], buflen: usize) -> usize
{
fn rej_uniform(r: &mut [i16], len: usize, buf: &[u8], buflen: usize) -> usize {
let (mut ctr, mut pos) = (0usize, 0usize);
let (mut val0, mut val1);
@ -136,19 +122,20 @@ fn rej_uniform(r: &mut[i16], len: usize, buf: &[u8], buflen: usize) -> usize
ctr
}
pub fn gen_a(a: &mut[Polyvec], b: &[u8])
{
unsafe { gen_matrix(a, b, false); }
pub fn gen_a(a: &mut [Polyvec], b: &[u8]) {
unsafe {
gen_matrix(a, b, false);
}
}
pub fn gen_at(a: &mut[Polyvec], b: &[u8])
{
unsafe { gen_matrix(a, b, true); }
pub fn gen_at(a: &mut [Polyvec], b: &[u8]) {
unsafe {
gen_matrix(a, b, true);
}
}
#[cfg(feature = "90s")]
unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
{
unsafe fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) {
let (mut ctr, mut off, mut buflen);
let mut nonce: u64;
let mut state = Aes256CtrCtx::new();
@ -180,8 +167,7 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
}
#[cfg(all(feature = "kyber512", not(feature = "90s")))]
unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
{
unsafe fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) {
let mut state = Keccakx4State::new();
let mut buf = [GenMatrixBuf::new(); 4];
@ -200,8 +186,7 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
buf[2].coeffs[33] = 0;
buf[3].coeffs[32] = 1;
buf[3].coeffs[33] = 1;
}
else {
} else {
buf[0].coeffs[32] = 0;
buf[0].coeffs[33] = 0;
buf[1].coeffs[32] = 1;
@ -212,9 +197,7 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
buf[3].coeffs[33] = 1;
}
shake128x4_absorb_once(
&mut state, &buf[0].coeffs, &buf[1].coeffs, &buf[2].coeffs, &buf[3].coeffs, 34
);
shake128x4_absorb_once(&mut state, &buf[0].coeffs, &buf[1].coeffs, &buf[2].coeffs, &buf[3].coeffs, 34);
shake128x4_squeezeblocks(&mut buf, REJ_UNIFORM_AVX_NBLOCKS, &mut state);
let mut ctr0 = rej_uniform_avx(&mut a[0].vec[0].coeffs, &buf[0].coeffs);
@ -225,18 +208,10 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
while ctr0 < KYBER_N || ctr1 < KYBER_N || ctr2 < KYBER_N || ctr3 < KYBER_N {
shake128x4_squeezeblocks(&mut buf, 1, &mut state);
ctr0 += rej_uniform(
&mut a[0].vec[0].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE
);
ctr1 += rej_uniform(
&mut a[0].vec[1].coeffs[ctr1..], KYBER_N - ctr1, &buf[1].coeffs, SHAKE128_RATE
);
ctr2 += rej_uniform(
&mut a[1].vec[0].coeffs[ctr2..], KYBER_N - ctr2, &buf[2].coeffs, SHAKE128_RATE
);
ctr3 += rej_uniform(
&mut a[1].vec[1].coeffs[ctr3..], KYBER_N - ctr3, &buf[3].coeffs, SHAKE128_RATE
);
ctr0 += rej_uniform(&mut a[0].vec[0].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE);
ctr1 += rej_uniform(&mut a[0].vec[1].coeffs[ctr1..], KYBER_N - ctr1, &buf[1].coeffs, SHAKE128_RATE);
ctr2 += rej_uniform(&mut a[1].vec[0].coeffs[ctr2..], KYBER_N - ctr2, &buf[2].coeffs, SHAKE128_RATE);
ctr3 += rej_uniform(&mut a[1].vec[1].coeffs[ctr3..], KYBER_N - ctr3, &buf[3].coeffs, SHAKE128_RATE);
}
poly_nttunpack(&mut a[0].vec[0]);
@ -246,8 +221,7 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
}
#[cfg(all(not(feature = "kyber512"), not(feature = "kyber1024"), not(feature = "90s")))]
unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
{
unsafe fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) {
let mut state = Keccakx4State::new();
let mut state1x = KeccakState::new();
let mut buf = [GenMatrixBuf::new(); 4];
@ -267,8 +241,7 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
buf[2].coeffs[33] = 2;
buf[3].coeffs[32] = 1;
buf[3].coeffs[33] = 0;
}
else {
} else {
buf[0].coeffs[32] = 0;
buf[0].coeffs[33] = 0;
buf[1].coeffs[32] = 1;
@ -279,16 +252,8 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
buf[3].coeffs[33] = 1;
}
shake128x4_absorb_once(
&mut state,
&buf[0].coeffs, &buf[1].coeffs,
&buf[2].coeffs, &buf[3].coeffs,
34
);
shake128x4_squeezeblocks(
&mut buf,
REJ_UNIFORM_AVX_NBLOCKS, &mut state
);
shake128x4_absorb_once(&mut state, &buf[0].coeffs, &buf[1].coeffs, &buf[2].coeffs, &buf[3].coeffs, 34);
shake128x4_squeezeblocks(&mut buf, REJ_UNIFORM_AVX_NBLOCKS, &mut state);
let mut ctr0 = rej_uniform_avx(&mut a[0].vec[0].coeffs, &buf[0].coeffs);
let mut ctr1 = rej_uniform_avx(&mut a[0].vec[1].coeffs, &buf[1].coeffs);
@ -298,18 +263,10 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
while ctr0 < KYBER_N || ctr1 < KYBER_N || ctr2 < KYBER_N || ctr3 < KYBER_N {
shake128x4_squeezeblocks(&mut buf, 1, &mut state);
ctr0 += rej_uniform(
&mut a[0].vec[0].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE
);
ctr1 += rej_uniform(
&mut a[0].vec[1].coeffs[ctr1..], KYBER_N - ctr1, &buf[1].coeffs, SHAKE128_RATE
);
ctr2 += rej_uniform(
&mut a[0].vec[2].coeffs[ctr2..], KYBER_N - ctr2, &buf[2].coeffs, SHAKE128_RATE
);
ctr3 += rej_uniform(
&mut a[1].vec[0].coeffs[ctr3..], KYBER_N - ctr3, &buf[3].coeffs, SHAKE128_RATE
);
ctr0 += rej_uniform(&mut a[0].vec[0].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE);
ctr1 += rej_uniform(&mut a[0].vec[1].coeffs[ctr1..], KYBER_N - ctr1, &buf[1].coeffs, SHAKE128_RATE);
ctr2 += rej_uniform(&mut a[0].vec[2].coeffs[ctr2..], KYBER_N - ctr2, &buf[2].coeffs, SHAKE128_RATE);
ctr3 += rej_uniform(&mut a[1].vec[0].coeffs[ctr3..], KYBER_N - ctr3, &buf[3].coeffs, SHAKE128_RATE);
}
poly_nttunpack(&mut a[0].vec[0]);
@ -332,8 +289,7 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
buf[2].coeffs[33] = 0;
buf[3].coeffs[32] = 2;
buf[3].coeffs[33] = 1;
}
else {
} else {
buf[0].coeffs[32] = 1;
buf[0].coeffs[33] = 1;
buf[1].coeffs[32] = 2;
@ -344,12 +300,7 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
buf[3].coeffs[33] = 2;
}
shake128x4_absorb_once(
&mut state,
&buf[0].coeffs, &buf[1].coeffs,
&buf[2].coeffs, &buf[3].coeffs,
34
);
shake128x4_absorb_once(&mut state, &buf[0].coeffs, &buf[1].coeffs, &buf[2].coeffs, &buf[3].coeffs, 34);
shake128x4_squeezeblocks(&mut buf, REJ_UNIFORM_AVX_NBLOCKS, &mut state);
ctr0 = rej_uniform_avx(&mut a[1].vec[1].coeffs, &buf[0].coeffs);
@ -360,18 +311,10 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
while ctr0 < KYBER_N || ctr1 < KYBER_N || ctr2 < KYBER_N || ctr3 < KYBER_N {
shake128x4_squeezeblocks(&mut buf, 1, &mut state);
ctr0 += rej_uniform(
&mut a[1].vec[1].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE
);
ctr1 += rej_uniform(
&mut a[1].vec[2].coeffs[ctr1..], KYBER_N - ctr1, &buf[1].coeffs, SHAKE128_RATE
);
ctr2 += rej_uniform(
&mut a[2].vec[0].coeffs[ctr2..], KYBER_N - ctr2, &buf[2].coeffs, SHAKE128_RATE
);
ctr3 += rej_uniform(
&mut a[2].vec[1].coeffs[ctr3..], KYBER_N - ctr3, &buf[3].coeffs, SHAKE128_RATE
);
ctr0 += rej_uniform(&mut a[1].vec[1].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE);
ctr1 += rej_uniform(&mut a[1].vec[2].coeffs[ctr1..], KYBER_N - ctr1, &buf[1].coeffs, SHAKE128_RATE);
ctr2 += rej_uniform(&mut a[2].vec[0].coeffs[ctr2..], KYBER_N - ctr2, &buf[2].coeffs, SHAKE128_RATE);
ctr3 += rej_uniform(&mut a[2].vec[1].coeffs[ctr3..], KYBER_N - ctr3, &buf[3].coeffs, SHAKE128_RATE);
}
poly_nttunpack(&mut a[1].vec[1]);
@ -388,17 +331,14 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
ctr0 = rej_uniform_avx(&mut a[2].vec[2].coeffs, &buf[0].coeffs);
while ctr0 < KYBER_N {
shake128_squeezeblocks(&mut buf[0].coeffs, 1, &mut state1x);
ctr0 += rej_uniform(
&mut a[2].vec[2].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE
);
ctr0 += rej_uniform(&mut a[2].vec[2].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE);
}
poly_nttunpack(&mut a[2].vec[2]);
}
#[cfg(all(feature = "kyber1024", not(feature = "90s")))]
unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
{
unsafe fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) {
let mut f;
let mut state = Keccakx4State::new();
let mut buf = [GenMatrixBuf::new(); 4];
@ -422,10 +362,7 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
}
}
shake128x4_absorb_once(
&mut state,
&buf[0].coeffs, &buf[1].coeffs, &buf[2].coeffs, &buf[3].coeffs, 34
);
shake128x4_absorb_once(&mut state, &buf[0].coeffs, &buf[1].coeffs, &buf[2].coeffs, &buf[3].coeffs, 34);
shake128x4_squeezeblocks(&mut buf, REJ_UNIFORM_AVX_NBLOCKS, &mut state);
let mut ctr0 = rej_uniform_avx(&mut a[i].vec[0].coeffs, &buf[0].coeffs);
@ -436,18 +373,10 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
while ctr0 < KYBER_N || ctr1 < KYBER_N || ctr2 < KYBER_N || ctr3 < KYBER_N {
shake128x4_squeezeblocks(&mut buf, 1, &mut state);
ctr0 += rej_uniform(
&mut a[i].vec[0].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE
);
ctr1 += rej_uniform(
&mut a[i].vec[1].coeffs[ctr1..], KYBER_N - ctr1, &buf[1].coeffs, SHAKE128_RATE
);
ctr2 += rej_uniform(
&mut a[i].vec[2].coeffs[ctr2..], KYBER_N - ctr2, &buf[2].coeffs, SHAKE128_RATE
);
ctr3 += rej_uniform(
&mut a[i].vec[3].coeffs[ctr3..], KYBER_N - ctr3, &buf[3].coeffs, SHAKE128_RATE
);
ctr0 += rej_uniform(&mut a[i].vec[0].coeffs[ctr0..], KYBER_N - ctr0, &buf[0].coeffs, SHAKE128_RATE);
ctr1 += rej_uniform(&mut a[i].vec[1].coeffs[ctr1..], KYBER_N - ctr1, &buf[1].coeffs, SHAKE128_RATE);
ctr2 += rej_uniform(&mut a[i].vec[2].coeffs[ctr2..], KYBER_N - ctr2, &buf[2].coeffs, SHAKE128_RATE);
ctr3 += rej_uniform(&mut a[i].vec[3].coeffs[ctr3..], KYBER_N - ctr3, &buf[3].coeffs, SHAKE128_RATE);
}
poly_nttunpack(&mut a[i].vec[0]);
@ -457,15 +386,10 @@ unsafe fn gen_matrix(a: &mut[Polyvec], seed: &[u8], transposed: bool)
}
}
pub fn indcpa_keypair<R>(
pk: &mut[u8],
sk: &mut[u8],
_seed: Option<(&[u8], &[u8])>,
_rng: &mut R
)
where R: CryptoRng + RngCore
pub fn indcpa_keypair<R>(pk: &mut [u8], sk: &mut [u8], _seed: Option<(&[u8], &[u8])>, _rng: &mut R)
where
R: CryptoRng + RngCore,
{
let mut a = [Polyvec::new(); KYBER_K];
let (mut e, mut pkpv, mut skpv) = (Polyvec::new(), Polyvec::new(), Polyvec::new());
let mut buf = [0u8; 2 * KYBER_SYMBYTES];
@ -477,7 +401,6 @@ pub fn indcpa_keypair<R>(
#[cfg(feature = "KATs")]
randbuf[..KYBER_SYMBYTES].copy_from_slice(&_seed.expect("KAT seed").0);
hash_g(&mut buf, &randbuf, KYBER_SYMBYTES);
let (publicseed, noiseseed) = buf.split_at(KYBER_SYMBYTES);
@ -512,9 +435,7 @@ pub fn indcpa_keypair<R>(
{
let (skpv0, skpv1) = skpv.vec.split_at_mut(1);
let (e0, e1) = e.vec.split_at_mut(1);
poly_getnoise_eta1_4x(
&mut skpv0[0], &mut skpv1[0], &mut e0[0], &mut e1[0], noiseseed, 0, 1, 2, 3
);
poly_getnoise_eta1_4x(&mut skpv0[0], &mut skpv1[0], &mut e0[0], &mut e1[0], noiseseed, 0, 1, 2, 3);
}
#[cfg(all(feature = "kyber1024", not(feature = "90s")))]
@ -522,29 +443,21 @@ pub fn indcpa_keypair<R>(
let (skpv0, skpv1) = skpv.vec.split_at_mut(1);
let (skpv1, skpv2) = skpv1.split_at_mut(1);
let (skpv2, skpv3) = skpv2.split_at_mut(1);
poly_getnoise_eta1_4x(
&mut skpv0[0], &mut skpv1[0], &mut skpv2[0], &mut skpv3[0], noiseseed, 0, 1, 2, 3
);
poly_getnoise_eta1_4x(&mut skpv0[0], &mut skpv1[0], &mut skpv2[0], &mut skpv3[0], noiseseed, 0, 1, 2, 3);
let (e0, e1) = e.vec.split_at_mut(1);
let (e1, e2) = e1.split_at_mut(1);
let (e2, e3) = e2.split_at_mut(1);
poly_getnoise_eta1_4x(
&mut e0[0], &mut e1[0], &mut e2[0], &mut e3[0], noiseseed, 4, 5, 6, 7
);
poly_getnoise_eta1_4x(&mut e0[0], &mut e1[0], &mut e2[0], &mut e3[0], noiseseed, 4, 5, 6, 7);
}
#[cfg(not(any(feature = "kyber1024", feature = "kyber512", feature = "90s")))] // kyber764
{
let (skpv0, skpv1) = skpv.vec.split_at_mut(1);
let (skpv1, skpv2) = skpv1.split_at_mut(1);
poly_getnoise_eta1_4x(
&mut skpv0[0], &mut skpv1[0], &mut skpv2[0], &mut e.vec[0], noiseseed, 0, 1, 2, 3
);
poly_getnoise_eta1_4x(&mut skpv0[0], &mut skpv1[0], &mut skpv2[0], &mut e.vec[0], noiseseed, 0, 1, 2, 3);
let (e1, e2) = e.vec.split_at_mut(2);
let (pkpv0, pkpv1) = pkpv.vec.split_at_mut(1);
poly_getnoise_eta1_4x(
&mut e1[1], &mut e2[0], &mut pkpv0[0], &mut pkpv1[0], noiseseed, 4, 5, 6, 7
);
poly_getnoise_eta1_4x(&mut e1[1], &mut e2[0], &mut pkpv0[0], &mut pkpv1[0], noiseseed, 4, 5, 6, 7);
}
polyvec_ntt(&mut skpv);
@ -563,8 +476,7 @@ pub fn indcpa_keypair<R>(
pack_pk(pk, &pkpv, publicseed);
}
pub fn indcpa_enc(c: &mut[u8], m: &[u8], pk: &[u8], coins: &[u8])
{
pub fn indcpa_enc(c: &mut [u8], m: &[u8], pk: &[u8], coins: &[u8]) {
unsafe {
let mut at = [Polyvec::new(); KYBER_K];
let (mut sp, mut pkpv, mut ep, mut b) = (Polyvec::new(), Polyvec::new(), Polyvec::new(), Polyvec::new());
@ -605,9 +517,7 @@ pub fn indcpa_enc(c: &mut[u8], m: &[u8], pk: &[u8], coins: &[u8])
{
let (sp0, sp1) = sp.vec.split_at_mut(1);
let (ep0, ep1) = ep.vec.split_at_mut(1);
poly_getnoise_eta1122_4x(
&mut sp0[0], &mut sp1[0], &mut ep0[0], &mut ep1[0], coins, 0, 1, 2, 3
);
poly_getnoise_eta1122_4x(&mut sp0[0], &mut sp1[0], &mut ep0[0], &mut ep1[0], coins, 0, 1, 2, 3);
poly_getnoise_eta2(&mut epp, coins, 4);
}
@ -615,13 +525,9 @@ pub fn indcpa_enc(c: &mut[u8], m: &[u8], pk: &[u8], coins: &[u8])
{
let (sp0, sp1) = sp.vec.split_at_mut(1);
let (sp1, sp2) = sp1.split_at_mut(1);
poly_getnoise_eta1_4x(
&mut sp0[0], &mut sp1[0], &mut sp2[0], &mut ep.vec[0], coins, 0, 1, 2 ,3
);
poly_getnoise_eta1_4x(&mut sp0[0], &mut sp1[0], &mut sp2[0], &mut ep.vec[0], coins, 0, 1, 2, 3);
let (ep1, ep2) = ep.vec.split_at_mut(2);
poly_getnoise_eta1_4x(
&mut ep1[1], &mut ep2[0], &mut epp, &mut b.vec[0], coins, 4, 5, 6, 7
);
poly_getnoise_eta1_4x(&mut ep1[1], &mut ep2[0], &mut epp, &mut b.vec[0], coins, 4, 5, 6, 7);
}
#[cfg(all(feature = "kyber1024", not(feature = "90s")))]
@ -629,15 +535,11 @@ pub fn indcpa_enc(c: &mut[u8], m: &[u8], pk: &[u8], coins: &[u8])
let (sp0, sp1) = sp.vec.split_at_mut(1);
let (sp1, sp2) = sp1.split_at_mut(1);
let (sp2, sp3) = sp2.split_at_mut(1);
poly_getnoise_eta1_4x(
&mut sp0[0], &mut sp1[0], &mut sp2[0],&mut sp3[0], coins, 0, 1, 2, 3
);
poly_getnoise_eta1_4x(&mut sp0[0], &mut sp1[0], &mut sp2[0], &mut sp3[0], coins, 0, 1, 2, 3);
let (ep0, ep1) = ep.vec.split_at_mut(1);
let (ep1, ep2) = ep1.split_at_mut(1);
let (ep2, ep3) = ep2.split_at_mut(1);
poly_getnoise_eta1_4x(
&mut ep0[0], &mut ep1[0], &mut ep2[0],&mut ep3[0], coins, 4, 5, 6, 7
);
poly_getnoise_eta1_4x(&mut ep0[0], &mut ep1[0], &mut ep2[0], &mut ep3[0], coins, 4, 5, 6, 7);
poly_getnoise_eta2(&mut epp, coins, 8);
}
@ -662,8 +564,7 @@ pub fn indcpa_enc(c: &mut[u8], m: &[u8], pk: &[u8], coins: &[u8])
}
}
pub fn indcpa_dec(m: &mut[u8], c: &[u8], sk: &[u8])
{
pub fn indcpa_dec(m: &mut [u8], c: &[u8], sk: &[u8]) {
let (mut b, mut skpv) = (Polyvec::new(), Polyvec::new());
let (mut v, mut mp) = (Poly::new(), Poly::new());

View file

@ -17,98 +17,250 @@ use core::arch::x86_64::*;
#[repr(C, align(32))]
union RC_Data {
vecs: [__m256i; 24],
u: [u64; 96]
u: [u64; 96],
}
#[repr(C, align(32))]
union Temp {
pub vec: __m256i,
pub u: [u64; 4]
pub u: [u64; 4],
}
const RHO: [u32; 24] = [
1, 3, 6, 10, 15, 21, 28, 36,
45, 55, 2, 14, 27, 41, 56, 8,
25, 43, 62, 18, 39, 61, 20, 44,
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44,
];
const PI: [usize; 24] = [
10, 7, 11, 17, 18, 3, 5, 16,
8, 21, 24, 4, 15, 23, 19, 13,
12, 2, 20, 14, 22, 9, 6, 1,
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
];
// Set __mm256i constants with a union
const RC_X4: RC_Data = RC_Data { u: [
0x0000000000000001, 0x0000000000000001, 0x0000000000000001, 0x0000000000000001,
0x0000000000008082, 0x0000000000008082, 0x0000000000008082, 0x0000000000008082,
0x800000000000808a, 0x800000000000808a, 0x800000000000808a, 0x800000000000808a,
0x8000000080008000, 0x8000000080008000, 0x8000000080008000, 0x8000000080008000,
0x000000000000808b, 0x000000000000808b, 0x000000000000808b, 0x000000000000808b,
0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001,
0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081,
0x8000000000008009, 0x8000000000008009, 0x8000000000008009, 0x8000000000008009,
0x000000000000008a, 0x000000000000008a, 0x000000000000008a, 0x000000000000008a,
0x0000000000000088, 0x0000000000000088, 0x0000000000000088, 0x0000000000000088,
0x0000000080008009, 0x0000000080008009, 0x0000000080008009, 0x0000000080008009,
0x000000008000000a, 0x000000008000000a, 0x000000008000000a, 0x000000008000000a,
0x000000008000808b, 0x000000008000808b, 0x000000008000808b, 0x000000008000808b,
0x800000000000008b, 0x800000000000008b, 0x800000000000008b, 0x800000000000008b,
0x8000000000008089, 0x8000000000008089, 0x8000000000008089, 0x8000000000008089,
0x8000000000008003, 0x8000000000008003, 0x8000000000008003, 0x8000000000008003,
0x8000000000008002, 0x8000000000008002, 0x8000000000008002, 0x8000000000008002,
0x8000000000000080, 0x8000000000000080, 0x8000000000000080, 0x8000000000000080,
0x000000000000800a, 0x000000000000800a, 0x000000000000800a, 0x000000000000800a,
0x800000008000000a, 0x800000008000000a, 0x800000008000000a, 0x800000008000000a,
0x8000000080008081, 0x8000000080008081, 0x8000000080008081, 0x8000000080008081,
0x8000000000008080, 0x8000000000008080, 0x8000000000008080, 0x8000000000008080,
0x0000000080000001, 0x0000000080000001, 0x0000000080000001, 0x0000000080000001,
0x8000000080008008, 0x8000000080008008, 0x8000000080008008, 0x8000000080008008
]};
const RC_X4: RC_Data = RC_Data {
u: [
0x0000000000000001,
0x0000000000000001,
0x0000000000000001,
0x0000000000000001,
0x0000000000008082,
0x0000000000008082,
0x0000000000008082,
0x0000000000008082,
0x800000000000808a,
0x800000000000808a,
0x800000000000808a,
0x800000000000808a,
0x8000000080008000,
0x8000000080008000,
0x8000000080008000,
0x8000000080008000,
0x000000000000808b,
0x000000000000808b,
0x000000000000808b,
0x000000000000808b,
0x0000000080000001,
0x0000000080000001,
0x0000000080000001,
0x0000000080000001,
0x8000000080008081,
0x8000000080008081,
0x8000000080008081,
0x8000000080008081,
0x8000000000008009,
0x8000000000008009,
0x8000000000008009,
0x8000000000008009,
0x000000000000008a,
0x000000000000008a,
0x000000000000008a,
0x000000000000008a,
0x0000000000000088,
0x0000000000000088,
0x0000000000000088,
0x0000000000000088,
0x0000000080008009,
0x0000000080008009,
0x0000000080008009,
0x0000000080008009,
0x000000008000000a,
0x000000008000000a,
0x000000008000000a,
0x000000008000000a,
0x000000008000808b,
0x000000008000808b,
0x000000008000808b,
0x000000008000808b,
0x800000000000008b,
0x800000000000008b,
0x800000000000008b,
0x800000000000008b,
0x8000000000008089,
0x8000000000008089,
0x8000000000008089,
0x8000000000008089,
0x8000000000008003,
0x8000000000008003,
0x8000000000008003,
0x8000000000008003,
0x8000000000008002,
0x8000000000008002,
0x8000000000008002,
0x8000000000008002,
0x8000000000000080,
0x8000000000000080,
0x8000000000000080,
0x8000000000000080,
0x000000000000800a,
0x000000000000800a,
0x000000000000800a,
0x000000000000800a,
0x800000008000000a,
0x800000008000000a,
0x800000008000000a,
0x800000008000000a,
0x8000000080008081,
0x8000000080008081,
0x8000000080008081,
0x8000000080008081,
0x8000000000008080,
0x8000000000008080,
0x8000000000008080,
0x8000000000008080,
0x0000000080000001,
0x0000000080000001,
0x0000000080000001,
0x0000000080000001,
0x8000000080008008,
0x8000000080008008,
0x8000000080008008,
0x8000000080008008,
],
};
macro_rules! unroll5 {
($var:ident, $body:block) => {
{ const $var: usize = 0; $body; }
{ const $var: usize = 1; $body; }
{ const $var: usize = 2; $body; }
{ const $var: usize = 3; $body; }
{ const $var: usize = 4; $body; }
};
($var:ident, $body:block) => {{
const $var: usize = 0;
$body;
}
{
const $var: usize = 1;
$body;
}
{
const $var: usize = 2;
$body;
}
{
const $var: usize = 3;
$body;
}
{
const $var: usize = 4;
$body;
}};
}
macro_rules! unroll24 {
($var: ident, $body: block) => {
{ const $var: usize = 0; $body; }
{ const $var: usize = 1; $body; }
{ const $var: usize = 2; $body; }
{ const $var: usize = 3; $body; }
{ const $var: usize = 4; $body; }
{ const $var: usize = 5; $body; }
{ const $var: usize = 6; $body; }
{ const $var: usize = 7; $body; }
{ const $var: usize = 8; $body; }
{ const $var: usize = 9; $body; }
{ const $var: usize = 10; $body; }
{ const $var: usize = 11; $body; }
{ const $var: usize = 12; $body; }
{ const $var: usize = 13; $body; }
{ const $var: usize = 14; $body; }
{ const $var: usize = 15; $body; }
{ const $var: usize = 16; $body; }
{ const $var: usize = 17; $body; }
{ const $var: usize = 18; $body; }
{ const $var: usize = 19; $body; }
{ const $var: usize = 20; $body; }
{ const $var: usize = 21; $body; }
{ const $var: usize = 22; $body; }
{ const $var: usize = 23; $body; }
};
($var: ident, $body: block) => {{
const $var: usize = 0;
$body;
}
{
const $var: usize = 1;
$body;
}
{
const $var: usize = 2;
$body;
}
{
const $var: usize = 3;
$body;
}
{
const $var: usize = 4;
$body;
}
{
const $var: usize = 5;
$body;
}
{
const $var: usize = 6;
$body;
}
{
const $var: usize = 7;
$body;
}
{
const $var: usize = 8;
$body;
}
{
const $var: usize = 9;
$body;
}
{
const $var: usize = 10;
$body;
}
{
const $var: usize = 11;
$body;
}
{
const $var: usize = 12;
$body;
}
{
const $var: usize = 13;
$body;
}
{
const $var: usize = 14;
$body;
}
{
const $var: usize = 15;
$body;
}
{
const $var: usize = 16;
$body;
}
{
const $var: usize = 17;
$body;
}
{
const $var: usize = 18;
$body;
}
{
const $var: usize = 19;
$body;
}
{
const $var: usize = 20;
$body;
}
{
const $var: usize = 21;
$body;
}
{
const $var: usize = 22;
$body;
}
{
const $var: usize = 23;
$body;
}};
}
#[allow(unused_assignments, non_upper_case_globals)]
pub fn f1600_x4(a: &mut [__m256i]) {
unsafe {
for i in 0..24 {
let mut array = [_mm256_setzero_si256(); 5];
@ -171,23 +323,59 @@ mod tests {
#[test]
fn known_vectors() {
let vec1: [u64; 25] = [
0xF1258F7940E1DDE7, 0x84D5CCF933C0478A, 0xD598261EA65AA9EE, 0xBD1547306F80494D,
0x8B284E056253D057, 0xFF97A42D7F8E6FD4, 0x90FEE5A0A44647C4, 0x8C5BDA0CD6192E76,
0xAD30A6F71B19059C, 0x30935AB7D08FFC64, 0xEB5AA93F2317D635, 0xA9A6E6260D712103,
0x81A57C16DBCF555F, 0x43B831CD0347C826, 0x01F22F1A11A5569F, 0x05E5635A21D9AE61,
0x64BEFEF28CC970F2, 0x613670957BC46611, 0xB87C5A554FD00ECB, 0x8C3EE88A1CCF32C8,
0x940C7922AE3A2614, 0x1841F924A2C509E4, 0x16F53526E70465C2, 0x75F644E97F30A13B,
0xEAF1FF7B5CECA249
0xF1258F7940E1DDE7,
0x84D5CCF933C0478A,
0xD598261EA65AA9EE,
0xBD1547306F80494D,
0x8B284E056253D057,
0xFF97A42D7F8E6FD4,
0x90FEE5A0A44647C4,
0x8C5BDA0CD6192E76,
0xAD30A6F71B19059C,
0x30935AB7D08FFC64,
0xEB5AA93F2317D635,
0xA9A6E6260D712103,
0x81A57C16DBCF555F,
0x43B831CD0347C826,
0x01F22F1A11A5569F,
0x05E5635A21D9AE61,
0x64BEFEF28CC970F2,
0x613670957BC46611,
0xB87C5A554FD00ECB,
0x8C3EE88A1CCF32C8,
0x940C7922AE3A2614,
0x1841F924A2C509E4,
0x16F53526E70465C2,
0x75F644E97F30A13B,
0xEAF1FF7B5CECA249,
];
let vec2: [u64; 25] = [
0x2D5C954DF96ECB3C, 0x6A332CD07057B56D, 0x093D8D1270D76B6C, 0x8A20D9B25569D094,
0x4F9C4F99E5E7F156, 0xF957B9A2DA65FB38, 0x85773DAE1275AF0D, 0xFAF4F247C3D810F7,
0x1F1B9EE6F79A8759, 0xE4FECC0FEE98B425, 0x68CE61B6B9CE68A1, 0xDEEA66C4BA8F974F,
0x33C43D836EAFB1F5, 0xE00654042719DBD9, 0x7CF8A9F009831265, 0xFD5449A6BF174743,
0x97DDAD33D8994B40, 0x48EAD5FC5D0BE774, 0xE3B8C8EE55B7B03C, 0x91A0226E649E42E9,
0x900E3129E7BADD7B, 0x202A9EC5FAA3CCE8, 0x5B3402464E1C3DB6, 0x609F4E62A44C1059,
0x20D06CD26A8FBF5C
0x2D5C954DF96ECB3C,
0x6A332CD07057B56D,
0x093D8D1270D76B6C,
0x8A20D9B25569D094,
0x4F9C4F99E5E7F156,
0xF957B9A2DA65FB38,
0x85773DAE1275AF0D,
0xFAF4F247C3D810F7,
0x1F1B9EE6F79A8759,
0xE4FECC0FEE98B425,
0x68CE61B6B9CE68A1,
0xDEEA66C4BA8F974F,
0x33C43D836EAFB1F5,
0xE00654042719DBD9,
0x7CF8A9F009831265,
0xFD5449A6BF174743,
0x97DDAD33D8994B40,
0x48EAD5FC5D0BE774,
0xE3B8C8EE55B7B03C,
0x91A0226E649E42E9,
0x900E3129E7BADD7B,
0x202A9EC5FAA3CCE8,
0x5B3402464E1C3DB6,
0x609F4E62A44C1059,
0x20D06CD26A8FBF5C,
];
// repeat values to check all lanes
@ -201,12 +389,11 @@ mod tests {
f1600_x4(&mut data.lanes);
assert_eq!(data.u, tvec2);
}
}
#[repr(C)]
pub union Data {
pub lanes: [__m256i; PLEN],
pub u: [u64; PLEN * 4]
pub u: [u64; PLEN * 4],
}
// [0,1...] expands to [0,0,0,0,1,1,1,1...]

View file

@ -1,4 +1,3 @@
pub mod aes256ctr;
pub mod align;
pub mod cbd;

View file

@ -1,32 +1,21 @@
#![allow(unused_imports)]
use crate::{align::*, cbd::*, consts::*, fips202::*, fips202x4::*, params::*, symmetric::*};
use core::arch::x86_64::*;
use crate::{
align::*,
cbd::*,
consts::*,
fips202::*,
fips202x4::*,
params::*,
symmetric::*,
};
pub(crate) const NOISE_NBLOCKS: usize =
(KYBER_ETA1*KYBER_N/4+SHAKE256_RATE-1)/SHAKE256_RATE;
pub(crate) const NOISE_NBLOCKS: usize = (KYBER_ETA1 * KYBER_N / 4 + SHAKE256_RATE - 1) / SHAKE256_RATE;
#[derive(Clone)]
#[repr(C)]
pub union Poly {
pub coeffs: [i16; KYBER_N],
pub vec: [__m256i; (KYBER_N+15)/16]
pub vec: [__m256i; (KYBER_N + 15) / 16],
}
impl Copy for Poly {}
impl Poly {
pub fn new() -> Self {
Poly {
coeffs: [0i16; KYBER_N]
}
Poly { coeffs: [0i16; KYBER_N] }
}
// Basic polynomial value checking for development
// #[cfg(debug_assertions)]
@ -41,16 +30,11 @@ impl Poly {
// }
}
extern {
extern "C" {
fn ntt_avx(r: &mut [i16; KYBER_N], q_data: &[i16; 640]);
fn invntt_avx(r: &mut [i16; KYBER_N], q_data: &[i16; 640]);
fn nttunpack_avx(r: &mut [i16; KYBER_N], q_data: &[i16; 640]);
fn basemul_avx(
r: &mut[i16; KYBER_N],
a: &[i16; KYBER_N],
b: &[i16; KYBER_N],
q_data: &[i16; 640]
);
fn basemul_avx(r: &mut [i16; KYBER_N], a: &[i16; KYBER_N], b: &[i16; KYBER_N], q_data: &[i16; 640]);
fn tomont_avx(r: &mut [i16; KYBER_N], q_data: &[i16; 640]);
fn reduce_avx(r: &mut [i16; KYBER_N], q_data: &[i16; 640]);
fn ntttobytes_avx(r: *mut u8, a: &[i16; KYBER_N], q_data: &[i16; 640]);
@ -59,8 +43,7 @@ extern {
// #[target_feature(enable = "avx2")]
#[cfg(any(feature = "kyber512", not(feature = "kyber1024")))]
pub unsafe fn poly_compress(r: &mut[u8], a: Poly)
{
pub unsafe fn poly_compress(r: &mut [u8], a: Poly) {
let (mut f0, mut f1, mut f2, mut f3);
let v: __m256i = _mm256_load_si256(QDATA.vec[_16XV / 16..].as_ptr());
let shift1: __m256i = _mm256_set1_epi16(1 << 9);
@ -96,13 +79,11 @@ pub unsafe fn poly_compress(r: &mut[u8], a: Poly)
}
// #[target_feature(enable = "avx2")]
#[cfg(any(feature = "kyber512", not(feature = "kyber1024")))]
pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8])
{
pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8]) {
let (mut t, mut f);
let q: __m256i = _mm256_load_si256(QDATA.vec[_16XQ / 16..].as_ptr());
let shufbidx: __m256i = _mm256_set_epi8(
7,7,7,7,6,6,6,6,5,5,5,5,4,4,4,4,
3,3,3,3,2,2,2,2,1,1,1,1,0,0,0,0
7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0,
);
let mask: __m256i = _mm256_set1_epi32(0x00F0000F);
let shift: __m256i = _mm256_set1_epi32((128 << 16) + 2048);
@ -120,8 +101,7 @@ pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8])
// #[target_feature(enable = "avx2")]
#[cfg(feature = "kyber1024")]
pub unsafe fn poly_compress(r: &mut[u8], a: Poly)
{
pub unsafe fn poly_compress(r: &mut [u8], a: Poly) {
let (mut f0, mut f1);
let (mut t0, mut t1);
let mut tmp;
@ -132,8 +112,7 @@ pub unsafe fn poly_compress(r: &mut[u8], a: Poly)
let shift3: __m256i = _mm256_set1_epi32((1024 << 16) + 1);
let sllvdidx: __m256i = _mm256_set1_epi64x(12);
let shufbidx: __m256i = _mm256_set_epi8(
8,-1,-1,-1,-1,-1, 4, 3, 2, 1, 0,-1,12,11,10, 9,
-1,12,11,10, 9, 8,-1,-1,-1,-1,-1 ,4, 3, 2, 1, 0
8, -1, -1, -1, -1, -1, 4, 3, 2, 1, 0, -1, 12, 11, 10, 9, -1, 12, 11, 10, 9, 8, -1, -1, -1, -1, -1, 4, 3, 2, 1, 0,
);
for i in 0..(KYBER_N / 32) {
@ -162,23 +141,15 @@ pub unsafe fn poly_compress(r: &mut[u8], a: Poly)
// #[target_feature(enable = "avx2")]
#[cfg(feature = "kyber1024")]
pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8])
{
pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8]) {
let (mut t, mut f, mut ti);
let q = _mm256_load_si256(&QDATA.vec[_16XQ / 16]);
let shufbidx = _mm256_set_epi8(
9,9,9,8,8,8,8,7,7,6,6,6,6,5,5,5,
4,4,4,3,3,3,3,2,2,1,1,1,1,0,0,0
);
let mask = _mm256_set_epi16(
248,1984,62,496,3968,124,992,31,
248,1984,62,496,3968,124,992,31
);
let shift = _mm256_set_epi16(
128,16,512,64,8,256,32,1024,
128,16,512,64,8,256,32,1024
9, 9, 9, 8, 8, 8, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0,
);
let mask = _mm256_set_epi16(248, 1984, 62, 496, 3968, 124, 992, 31, 248, 1984, 62, 496, 3968, 124, 992, 31);
let shift = _mm256_set_epi16(128, 16, 512, 64, 8, 256, 32, 1024, 128, 16, 512, 64, 8, 256, 32, 1024);
for i in 0..KYBER_N / 16 {
t = _mm_loadl_epi64(a[10 * i + 0..].as_ptr() as *const __m128i);
@ -193,27 +164,24 @@ pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8])
}
}
pub fn poly_frombytes(r: &mut Poly, a: &[u8])
{
pub fn poly_frombytes(r: &mut Poly, a: &[u8]) {
unsafe {
nttfrombytes_avx(r.coeffs.as_mut_ptr(), a.as_ptr(), &QDATA.coeffs);
}
}
pub fn poly_tobytes(r: &mut[u8], a: Poly)
{
pub fn poly_tobytes(r: &mut [u8], a: Poly) {
let mut buf = [0u8; KYBER_POLYBYTES];
unsafe { ntttobytes_avx(buf.as_mut_ptr(), &a.coeffs, &QDATA.coeffs); }
unsafe {
ntttobytes_avx(buf.as_mut_ptr(), &a.coeffs, &QDATA.coeffs);
}
r[..KYBER_POLYBYTES].copy_from_slice(&buf[..]);
}
// #[target_feature(enable = "avx2")]
pub unsafe fn poly_frommsg(r: &mut Poly, msg: &[u8])
{
pub unsafe fn poly_frommsg(r: &mut Poly, msg: &[u8]) {
let shift = _mm256_broadcastsi128_si256(_mm_set_epi32(0, 1, 2, 3));
let idx = _mm256_broadcastsi128_si256(
_mm_set_epi8(15,14,11,10,7,6,3,2,13,12,9,8,5,4,1,0)
);
let idx = _mm256_broadcastsi128_si256(_mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 13, 12, 9, 8, 5, 4, 1, 0));
let hqs: __m256i = _mm256_set1_epi16((KYBER_Q + 1) as i16 / 2);
let f = _mm256_loadu_si256(msg.as_ptr() as *const __m256i);
@ -253,8 +221,7 @@ pub unsafe fn poly_frommsg(r: &mut Poly, msg: &[u8])
}
// #[target_feature(enable = "avx2")]
pub fn poly_tomsg(msg: &mut[u8], a: Poly)
{
pub fn poly_tomsg(msg: &mut [u8], a: Poly) {
unsafe {
let (mut f0, mut f1, mut g0, mut g1);
let hq: __m256i = _mm256_set1_epi16((KYBER_Q - 1) as i16 / 2);
@ -280,8 +247,7 @@ pub fn poly_tomsg(msg: &mut[u8], a: Poly)
}
#[cfg(all(any(feature = "kyber1024", feature = "kyber512"), not(feature = "90s")))]
pub fn poly_getnoise_eta2(r: &mut Poly, seed: &[u8], nonce: u8)
{
pub fn poly_getnoise_eta2(r: &mut Poly, seed: &[u8], nonce: u8) {
let mut buf = Eta2Buf::new();
unsafe {
prf(&mut buf.coeffs, KYBER_ETA2 * KYBER_N / 4, seed, nonce);
@ -291,10 +257,16 @@ pub fn poly_getnoise_eta2(r: &mut Poly, seed: &[u8], nonce: u8)
#[cfg(not(feature = "90s"))]
pub fn poly_getnoise_eta1_4x(
r0: &mut Poly, r1: &mut Poly, r2: &mut Poly, r3: &mut Poly, seed: &[u8],
nonce0: u8, nonce1: u8, nonce2: u8, nonce3: u8
)
{
r0: &mut Poly,
r1: &mut Poly,
r2: &mut Poly,
r3: &mut Poly,
seed: &[u8],
nonce0: u8,
nonce1: u8,
nonce2: u8,
nonce3: u8,
) {
unsafe {
let mut buf = [Eta4xBuf::new(); 4];
let mut state = Keccakx4State::new();
@ -309,12 +281,7 @@ pub fn poly_getnoise_eta1_4x(
buf[2].coeffs[32] = nonce2;
buf[3].coeffs[32] = nonce3;
shake256x4_absorb_once(
&mut state,
&buf[0].coeffs, &buf[1].coeffs,
&buf[2].coeffs, &buf[3].coeffs,
33
);
shake256x4_absorb_once(&mut state, &buf[0].coeffs, &buf[1].coeffs, &buf[2].coeffs, &buf[3].coeffs, 33);
shake256x4_squeezeblocks(&mut buf, NOISE_NBLOCKS, &mut state);
poly_cbd_eta1(r0, &buf[0]);
@ -326,10 +293,16 @@ pub fn poly_getnoise_eta1_4x(
#[cfg(all(feature = "kyber512", not(feature = "90s")))]
pub fn poly_getnoise_eta1122_4x(
r0: &mut Poly, r1: &mut Poly, r2: &mut Poly, r3: &mut Poly, seed: &[u8],
nonce0: u8, nonce1: u8, nonce2: u8, nonce3: u8,
)
{
r0: &mut Poly,
r1: &mut Poly,
r2: &mut Poly,
r3: &mut Poly,
seed: &[u8],
nonce0: u8,
nonce1: u8,
nonce2: u8,
nonce3: u8,
) {
let mut buf = [Eta4xBuf::new(); 4];
let mut state = Keccakx4State::new();
unsafe {
@ -344,12 +317,7 @@ pub fn poly_getnoise_eta1122_4x(
buf[2].coeffs[32] = nonce2;
buf[3].coeffs[32] = nonce3;
shake256x4_absorb_once(
&mut state,
&buf[0].coeffs, &buf[1].coeffs,
&buf[2].coeffs, &buf[3].coeffs,
33
);
shake256x4_absorb_once(&mut state, &buf[0].coeffs, &buf[1].coeffs, &buf[2].coeffs, &buf[3].coeffs, 33);
shake256x4_squeezeblocks(&mut buf, NOISE_NBLOCKS, &mut state);
poly_cbd_eta1(r0, &buf[0]);
@ -359,38 +327,43 @@ pub fn poly_getnoise_eta1122_4x(
}
}
pub fn poly_ntt(r: &mut Poly)
{
unsafe { ntt_avx(&mut r.coeffs, &QDATA.coeffs); }
pub fn poly_ntt(r: &mut Poly) {
unsafe {
ntt_avx(&mut r.coeffs, &QDATA.coeffs);
}
}
pub fn poly_invntt_tomont(r: &mut Poly)
{
unsafe { invntt_avx(&mut r.coeffs, &QDATA.coeffs); }
pub fn poly_invntt_tomont(r: &mut Poly) {
unsafe {
invntt_avx(&mut r.coeffs, &QDATA.coeffs);
}
}
pub fn poly_nttunpack(r: &mut Poly)
{
unsafe { nttunpack_avx(&mut r.coeffs, &QDATA.coeffs); }
pub fn poly_nttunpack(r: &mut Poly) {
unsafe {
nttunpack_avx(&mut r.coeffs, &QDATA.coeffs);
}
}
pub fn poly_basemul(r: &mut Poly, a: &Poly, b: &Poly)
{
unsafe { basemul_avx(&mut r.coeffs, &a.coeffs, &b.coeffs, &QDATA.coeffs); }
pub fn poly_basemul(r: &mut Poly, a: &Poly, b: &Poly) {
unsafe {
basemul_avx(&mut r.coeffs, &a.coeffs, &b.coeffs, &QDATA.coeffs);
}
}
pub fn poly_tomont(r: &mut Poly)
{
unsafe { tomont_avx(&mut r.coeffs, &QDATA.coeffs); }
pub fn poly_tomont(r: &mut Poly) {
unsafe {
tomont_avx(&mut r.coeffs, &QDATA.coeffs);
}
}
pub fn poly_reduce(r: &mut Poly)
{
unsafe { reduce_avx(&mut r.coeffs, &QDATA.coeffs); }
pub fn poly_reduce(r: &mut Poly) {
unsafe {
reduce_avx(&mut r.coeffs, &QDATA.coeffs);
}
}
pub fn poly_add(r: &mut Poly, b: &Poly)
{
pub fn poly_add(r: &mut Poly, b: &Poly) {
let (mut f0, mut f1);
for i in 0..(KYBER_N / 16) {
unsafe {
@ -402,8 +375,7 @@ pub fn poly_add(r: &mut Poly, b: &Poly)
}
}
pub fn poly_sub(r: &mut Poly, a: &Poly)
{
pub fn poly_sub(r: &mut Poly, a: &Poly) {
let (mut f0, mut f1);
for i in 0..(KYBER_N / 16) {
unsafe {
@ -414,4 +386,3 @@ pub fn poly_sub(r: &mut Poly, a: &Poly)
}
}
}

View file

@ -1,22 +1,16 @@
use crate::{consts::*, params::*, poly::*};
use core::arch::x86_64::*;
use crate::{
poly::*,
params::*,
consts::*
};
#[derive(Clone)]
pub struct Polyvec {
pub vec: [Poly; KYBER_K]
pub vec: [Poly; KYBER_K],
}
impl Copy for Polyvec {}
impl Polyvec {
pub fn new() -> Self {
Polyvec {
vec: [Poly::new(); KYBER_K]
}
Polyvec { vec: [Poly::new(); KYBER_K] }
}
// Basic polynomial value check for development
// #[cfg(debug_assertions)]
@ -34,8 +28,7 @@ impl Polyvec {
}
// #[target_feature(enable = "avx")]
pub unsafe fn poly_compress10(r: &mut[u8], a: &Poly)
{
pub unsafe fn poly_compress10(r: &mut [u8], a: &Poly) {
let (mut f0, mut f1, mut f2);
let (mut t0, mut t1);
@ -44,13 +37,10 @@ pub unsafe fn poly_compress10(r: &mut[u8], a: &Poly)
let off = _mm256_set1_epi16(15);
let shift1 = _mm256_set1_epi16(1 << 12);
let mask = _mm256_set1_epi16(1023);
let shift2 = _mm256_set1_epi64x(
((1024u64 << 48) + (1u64 << 32) + (1024 << 16) + 1) as i64
);
let shift2 = _mm256_set1_epi64x(((1024u64 << 48) + (1u64 << 32) + (1024 << 16) + 1) as i64);
let sllvdidx = _mm256_set1_epi64x(12);
let shufbidx = _mm256_set_epi8(
8, 4, 3, 2, 1, 0,-1,-1,-1,-1,-1,-1,12,11,10, 9,
-1,-1,-1,-1,-1,-1,12,11,10, 9, 8, 4, 3, 2, 1, 0
8, 4, 3, 2, 1, 0, -1, -1, -1, -1, -1, -1, 12, 11, 10, 9, -1, -1, -1, -1, -1, -1, 12, 11, 10, 9, 8, 4, 3, 2, 1, 0,
);
for i in 0..(KYBER_N / 16) {
@ -78,14 +68,12 @@ pub unsafe fn poly_compress10(r: &mut[u8], a: &Poly)
}
// #[target_feature(enable = "avx")]
pub unsafe fn poly_decompress10(r: &mut Poly, a: &[u8])
{
pub unsafe fn poly_decompress10(r: &mut Poly, a: &[u8]) {
let mut f;
let q = _mm256_set1_epi32(((KYBER_Q as i32) << 16) + 4 * KYBER_Q as i32);
let shufbidx = _mm256_set_epi8(11,10,10, 9, 9, 8, 8, 7,
6, 5, 5, 4, 4, 3, 3, 2,
9, 8, 8, 7, 7, 6, 6, 5,
4, 3, 3, 2, 2, 1, 1, 0);
let shufbidx = _mm256_set_epi8(
11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 5, 4, 4, 3, 3, 2, 9, 8, 8, 7, 7, 6, 6, 5, 4, 3, 3, 2, 2, 1, 1, 0,
);
let sllvdidx = _mm256_set1_epi64x(4);
let mask = _mm256_set1_epi32((32736 << 16) + 8184);
for i in 0..KYBER_N / 16 {
@ -101,8 +89,7 @@ pub unsafe fn poly_decompress10(r: &mut Poly, a: &[u8])
}
// #[target_feature(enable = "avx")]
pub unsafe fn poly_compress11(r: &mut[u8], a: &Poly)
{
pub unsafe fn poly_compress11(r: &mut [u8], a: &Poly) {
let (mut f0, mut f1, mut f2);
let (mut t0, mut t1);
let v = _mm256_load_si256(QDATA.vec[_16XV / 16..].as_ptr());
@ -110,14 +97,11 @@ pub unsafe fn poly_compress11(r: &mut[u8], a: &Poly)
let off = _mm256_set1_epi16(36);
let shift1 = _mm256_set1_epi16(1 << 13);
let mask = _mm256_set1_epi16(2047);
let shift2 = _mm256_set1_epi64x(
((2048u64 << 48) + (1u64 << 32) + (2048 << 16) + 1) as i64
);
let shift2 = _mm256_set1_epi64x(((2048u64 << 48) + (1u64 << 32) + (2048 << 16) + 1) as i64);
let sllvdidx = _mm256_set1_epi64x(10);
let srlvqidx = _mm256_set_epi64x(30, 10, 30, 10);
let shufbidx = _mm256_set_epi8(
4, 3, 2, 1, 0, 0,-1,-1,-1,-1,10, 9, 8, 7, 6, 5,
-1,-1,-1,-1,-1,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
4, 3, 2, 1, 0, 0, -1, -1, -1, -1, 10, 9, 8, 7, 6, 5, -1, -1, -1, -1, -1, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0,
);
for i in 0..KYBER_N / 16 {
@ -148,16 +132,12 @@ pub unsafe fn poly_compress11(r: &mut[u8], a: &Poly)
}
// #[target_feature(enable = "avx")]
pub unsafe fn poly_decompress11(r: &mut Poly, a: &[u8])
{
pub unsafe fn poly_decompress11(r: &mut Poly, a: &[u8]) {
let mut f;
let q = _mm256_load_si256(QDATA.vec[_16XQ / 16..].as_ptr());
let shufbidx = _mm256_set_epi8(
13,12,12,11,10, 9, 9, 8,
8, 7, 6, 5, 5, 4, 4, 3,
10, 9, 9, 8, 7, 6, 6, 5,
5, 4, 3, 2, 2, 1, 1, 0
13, 12, 12, 11, 10, 9, 9, 8, 8, 7, 6, 5, 5, 4, 4, 3, 10, 9, 9, 8, 7, 6, 6, 5, 5, 4, 3, 2, 2, 1, 1, 0,
);
let srlvdidx = _mm256_set_epi32(0, 0, 1, 0, 0, 0, 1, 0);
let srlvqidx = _mm256_set_epi64x(2, 0, 2, 0);
@ -178,9 +158,7 @@ pub unsafe fn poly_decompress11(r: &mut Poly, a: &[u8])
}
}
pub unsafe fn polyvec_compress(r: &mut[u8], a: &Polyvec)
{
pub unsafe fn polyvec_compress(r: &mut [u8], a: &Polyvec) {
if cfg!(feature = "kyber1024") {
for i in 0..KYBER_K {
poly_compress11(&mut r[352 * i..], &a.vec[i]);
@ -192,8 +170,7 @@ pub unsafe fn polyvec_compress(r: &mut[u8], a: &Polyvec)
}
}
pub unsafe fn polyvec_decompress(r: &mut Polyvec, a: &[u8])
{
pub unsafe fn polyvec_decompress(r: &mut Polyvec, a: &[u8]) {
if cfg!(feature = "kyber1024") {
for i in 0..KYBER_K {
poly_decompress11(&mut r.vec[i], &a[352 * i..]);
@ -205,15 +182,13 @@ pub unsafe fn polyvec_decompress(r: &mut Polyvec, a: &[u8])
}
}
pub fn polyvec_tobytes(r: &mut[u8], a: &Polyvec)
{
pub fn polyvec_tobytes(r: &mut [u8], a: &Polyvec) {
for i in 0..KYBER_K {
poly_tobytes(&mut r[i * KYBER_POLYBYTES..], a.vec[i]);
}
}
pub unsafe fn polyvec_frombytes(r: &mut Polyvec, a: &[u8])
{
pub unsafe fn polyvec_frombytes(r: &mut Polyvec, a: &[u8]) {
for i in 0..KYBER_K {
poly_frombytes(&mut r.vec[i], &a[i * KYBER_POLYBYTES..]);
}
@ -224,8 +199,7 @@ pub unsafe fn polyvec_frombytes(r: &mut Polyvec, a: &[u8])
// Description: Apply forward NTT to all elements of a vector of polynomials
//
// Arguments: - Polyvec r: in/output vector of polynomials
pub fn polyvec_ntt(r: &mut Polyvec)
{
pub fn polyvec_ntt(r: &mut Polyvec) {
for i in 0..KYBER_K {
poly_ntt(&mut r.vec[i]);
}
@ -236,8 +210,7 @@ pub fn polyvec_ntt(r: &mut Polyvec)
// Description: Apply inverse NTT to all elements of a vector of polynomials
//
// Arguments: - Polyvec r: in/output vector of polynomials
pub fn polyvec_invntt_tomont(r: &mut Polyvec)
{
pub fn polyvec_invntt_tomont(r: &mut Polyvec) {
for i in 0..KYBER_K {
poly_invntt_tomont(&mut r.vec[i]);
}
@ -250,8 +223,7 @@ pub fn polyvec_invntt_tomont(r: &mut Polyvec)
// Arguments: - poly *r: output polynomial
// - const Polyvec a: first input vector of polynomials
// - const Polyvec b: second input vector of polynomials
pub fn polyvec_basemul_acc_montgomery(r: &mut Poly, a: &Polyvec, b: &Polyvec)
{
pub fn polyvec_basemul_acc_montgomery(r: &mut Poly, a: &Polyvec, b: &Polyvec) {
let mut t = Poly::new();
poly_basemul(r, &a.vec[0], &b.vec[0]);
for i in 1..KYBER_K {
@ -267,14 +239,12 @@ pub fn polyvec_basemul_acc_montgomery(r: &mut Poly, a: &Polyvec, b: &Polyvec)
// for details of the Barrett reduction see comments in reduce.c
//
// Arguments: - poly *r: input/output polynomial
pub fn polyvec_reduce(r: &mut Polyvec)
{
pub fn polyvec_reduce(r: &mut Polyvec) {
for i in 0..KYBER_K {
poly_reduce(&mut r.vec[i]);
}
}
// Name: polyvec_add
//
// Description: Add vectors of polynomials
@ -282,8 +252,7 @@ pub fn polyvec_reduce(r: &mut Polyvec)
// Arguments: - Polyvec r: output vector of polynomials
// - const Polyvec a: first input vector of polynomials
// - const Polyvec b: second input vector of polynomials
pub fn polyvec_add(r: &mut Polyvec, b: &Polyvec)
{
pub fn polyvec_add(r: &mut Polyvec, b: &Polyvec) {
for i in 0..KYBER_K {
poly_add(&mut r.vec[i], &b.vec[i]);
}

View file

@ -1,12 +1,7 @@
use crate::{consts::*, params::*, symmetric::*};
use core::arch::x86_64::*;
use crate::{
params::*,
consts::*,
symmetric::*
};
pub(crate) const REJ_UNIFORM_AVX_NBLOCKS: usize =
(12*KYBER_N/8*(1 << 12)/KYBER_Q + XOF_BLOCKBYTES)/XOF_BLOCKBYTES;
pub(crate) const REJ_UNIFORM_AVX_NBLOCKS: usize = (12 * KYBER_N / 8 * (1 << 12) / KYBER_Q + XOF_BLOCKBYTES) / XOF_BLOCKBYTES;
const REJ_UNIFORM_AVX_BUFLEN: usize = REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES;
pub unsafe fn _mm256_cmpge_epu16(a: __m256i, b: __m256i) -> __m256i {
@ -29,10 +24,7 @@ pub unsafe fn rej_uniform_avx(r: &mut[i16], buf: &[u8]) -> usize {
let ones = _mm256_set1_epi8(1);
let mask = _mm256_set1_epi16(0xFFF);
let idx8 = _mm256_set_epi8(
15,14,14,13,12,11,11,10,
9, 8, 8, 7, 6, 5, 5, 4,
11,10,10, 9, 8, 7, 7, 6,
5, 4, 4, 3, 2, 1, 1, 0
15, 14, 14, 13, 12, 11, 11, 10, 9, 8, 8, 7, 6, 5, 5, 4, 11, 10, 10, 9, 8, 7, 7, 6, 5, 4, 4, 3, 2, 1, 1, 0,
);
while ctr <= KYBER_N - 32 && pos <= REJ_UNIFORM_AVX_BUFLEN - 48 {
f0 = _mm256_loadu_si256(buf[pos..].as_ptr() as *const __m256i);
@ -376,5 +368,5 @@ const IDX: [[i8; 8]; 256] = [
[4, 6, 8, 10, 12, 14, -1, -1],
[0, 4, 6, 8, 10, 12, 14, -1],
[2, 4, 6, 8, 10, 12, 14, -1],
[ 0, 2, 4, 6, 8, 10, 12, 14]
[0, 2, 4, 6, 8, 10, 12, 14],
];

View file

@ -1,7 +1,6 @@
use core::arch::x86_64::*;
pub fn verify(a: &[u8], b: &[u8], mut len: usize) -> u8
{
pub fn verify(a: &[u8], b: &[u8], mut len: usize) -> u8 {
let (mut f, mut g);
let mut r: u64;
unsafe {
@ -22,8 +21,7 @@ pub fn verify(a: &[u8], b: &[u8], mut len: usize) -> u8
(r.wrapping_neg() >> 63) as u8
}
pub fn cmov(r: &mut[u8], x: &[u8], mut len: usize, mut b: u8)
{
pub fn cmov(r: &mut [u8], x: &[u8], mut len: usize, mut b: u8) {
let (mut xvec, mut rvec);
unsafe {
let bvec = _mm256_set1_epi64x(b as i64);

View file

@ -1,13 +1,7 @@
#[cfg(not(feature = "KATs"))]
use crate::rng::randombytes;
use rand_core::{RngCore, CryptoRng};
use crate::{
params::*,
indcpa::*,
symmetric::*,
error::KyberError,
verify::*
};
use crate::{error::KyberError, indcpa::*, params::*, symmetric::*, verify::*};
use rand_core::{CryptoRng, RngCore};
// Name: crypto_kem_keypair
//
@ -16,10 +10,9 @@ use crate::{
//
// Arguments: - [u8] pk: output public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
// - [u8] sk: output private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes)
pub fn crypto_kem_keypair<R>(
pk: &mut[u8], sk: &mut[u8], _rng: &mut R, _seed: Option<(&[u8], &[u8])>
)
where R: RngCore + CryptoRng
pub fn crypto_kem_keypair<R>(pk: &mut [u8], sk: &mut [u8], _rng: &mut R, _seed: Option<(&[u8], &[u8])>)
where
R: RngCore + CryptoRng,
{
const PK_START: usize = KYBER_SECRETKEYBYTES - (2 * KYBER_SYMBYTES);
const SK_START: usize = KYBER_SECRETKEYBYTES - KYBER_SYMBYTES;
@ -27,8 +20,7 @@ pub fn crypto_kem_keypair<R>(
indcpa_keypair(pk, sk, _seed, _rng);
sk[KYBER_INDCPA_SECRETKEYBYTES..END]
.copy_from_slice(&pk[..KYBER_INDCPA_PUBLICKEYBYTES]);
sk[KYBER_INDCPA_SECRETKEYBYTES..END].copy_from_slice(&pk[..KYBER_INDCPA_PUBLICKEYBYTES]);
hash_h(&mut sk[PK_START..], pk, KYBER_PUBLICKEYBYTES);
#[cfg(feature = "KATs")]
@ -36,7 +28,6 @@ pub fn crypto_kem_keypair<R>(
#[cfg(not(feature = "KATs"))]
randombytes(&mut sk[SK_START..], KYBER_SYMBYTES, _rng);
}
// Name: crypto_kem_enc
@ -47,10 +38,9 @@ pub fn crypto_kem_keypair<R>(
// Arguments: - [u8] ct: output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
// - [u8] ss: output shared secret (an already allocated array of CRYPTO_BYTES bytes)
// - const [u8] pk: input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
pub fn crypto_kem_enc<R>(
ct: &mut[u8], ss: &mut[u8], pk: &[u8], _rng: &mut R,_seed: Option<&[u8]>
)
where R: RngCore + CryptoRng
pub fn crypto_kem_enc<R>(ct: &mut [u8], ss: &mut [u8], pk: &[u8], _rng: &mut R, _seed: Option<&[u8]>)
where
R: RngCore + CryptoRng,
{
let mut kr = [0u8; 2 * KYBER_SYMBYTES];
let mut buf = [0u8; 2 * KYBER_SYMBYTES];
@ -61,8 +51,7 @@ pub fn crypto_kem_enc<R>(
// Deterministic randbuf for KAT's
#[cfg(feature = "KATs")]
randbuf[..KYBER_SYMBYTES]
.copy_from_slice(&_seed.expect("KATs feature only works with `cargo test`"));
randbuf[..KYBER_SYMBYTES].copy_from_slice(&_seed.expect("KATs feature only works with `cargo test`"));
// Don't release system RNG output
hash_h(&mut buf, &randbuf, KYBER_SYMBYTES);
@ -91,11 +80,7 @@ pub fn crypto_kem_enc<R>(
// - const [u8] sk: input private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes)
//
// On failure, ss will contain a pseudo-random value.
pub fn crypto_kem_dec(
ss: &mut[u8], ct: &[u8], sk: &[u8]
)
-> Result<(), KyberError>
{
pub fn crypto_kem_dec(ss: &mut [u8], ct: &[u8], sk: &[u8]) -> Result<(), KyberError> {
let mut buf = [0u8; 2 * KYBER_SYMBYTES];
let mut kr = [0u8; 2 * KYBER_SYMBYTES];
let mut cmp = [0u8; KYBER_CIPHERTEXTBYTES];
@ -123,6 +108,6 @@ pub fn crypto_kem_dec(
match fail {
0 => Ok(()),
_ => Err(KyberError::Decapsulation)
_ => Err(KyberError::Decapsulation),
}
}

View file

@ -1,10 +1,5 @@
use rand_core::{RngCore, CryptoRng};
use crate::{
kem::*,
symmetric::kdf,
params::*,
KyberError
};
use crate::{kem::*, params::*, symmetric::kdf, KyberError};
use rand_core::{CryptoRng, RngCore};
/// Unilateral Key Exchange Initiation Byte Length
pub const UAKE_INIT_BYTES: usize = KYBER_PUBLICKEYBYTES + KYBER_CIPHERTEXTBYTES;
@ -66,7 +61,7 @@ pub struct Uake {
send_b: UakeSendResponse,
// Epheremal keys
temp_key: TempKey,
eska: Eska
eska: Eska,
}
impl Default for Uake {
@ -101,14 +96,11 @@ impl Uake {
/// let client_init = alice.client_init(&bob_keys.public, &mut rng);
/// # Ok(()) }
/// ```
pub fn client_init<R>(&mut self, pubkey: &PublicKey, rng: &mut R)
-> UakeSendInit
where R: CryptoRng + RngCore
pub fn client_init<R>(&mut self, pubkey: &PublicKey, rng: &mut R) -> UakeSendInit
where
R: CryptoRng + RngCore,
{
uake_init_a(
&mut self.send_a, &mut self.temp_key,
&mut self.eska, pubkey, rng
);
uake_init_a(&mut self.send_a, &mut self.temp_key, &mut self.eska, pubkey, rng);
self.send_a
}
@ -123,16 +115,11 @@ impl Uake {
/// let client_init = alice.client_init(&bob_keys.public, &mut rng);
/// let server_send = bob.server_receive(client_init, &bob_keys.secret, &mut rng)?;
/// # Ok(()) }
pub fn server_receive<R>(
&mut self, send_a: UakeSendInit, secretkey: &SecretKey, rng: &mut R
)
-> Result<UakeSendResponse, KyberError>
where R: CryptoRng + RngCore
pub fn server_receive<R>(&mut self, send_a: UakeSendInit, secretkey: &SecretKey, rng: &mut R) -> Result<UakeSendResponse, KyberError>
where
R: CryptoRng + RngCore,
{
uake_shared_b(
&mut self.send_b, &mut self.shared_secret,
&send_a, secretkey, rng
)?;
uake_shared_b(&mut self.send_b, &mut self.shared_secret, &send_a, secretkey, rng)?;
Ok(self.send_b)
}
@ -150,13 +137,8 @@ impl Uake {
/// let client_confirm = alice.client_confirm(server_send);
/// assert_eq!(alice.shared_secret, bob.shared_secret);
/// # Ok(()) }
pub fn client_confirm(&mut self, send_b: UakeSendResponse)
-> Result<(), KyberError>
{
uake_shared_a(
&mut self.shared_secret, &send_b,
&self.temp_key, &self.eska
)?;
pub fn client_confirm(&mut self, send_b: UakeSendResponse) -> Result<(), KyberError> {
uake_shared_a(&mut self.shared_secret, &send_b, &self.temp_key, &self.eska)?;
Ok(())
}
}
@ -192,7 +174,7 @@ pub struct Ake {
send_b: AkeSendResponse,
// Epheremal keys
temp_key: TempKey,
eska: Eska
eska: Eska,
}
impl Default for Ake {
@ -227,14 +209,11 @@ impl Ake {
/// let client_init = alice.client_init(&bob_keys.public, &mut rng);
/// # Ok(()) }
/// ```
pub fn client_init<R>(&mut self, pubkey: &PublicKey, rng: &mut R)
-> AkeSendInit
where R: CryptoRng + RngCore
pub fn client_init<R>(&mut self, pubkey: &PublicKey, rng: &mut R) -> AkeSendInit
where
R: CryptoRng + RngCore,
{
ake_init_a(
&mut self.send_a, &mut self.temp_key,
&mut self.eska, pubkey, rng
);
ake_init_a(&mut self.send_a, &mut self.temp_key, &mut self.eska, pubkey, rng);
self.send_a
}
@ -251,16 +230,16 @@ impl Ake {
/// let server_send = bob.server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng)?;
/// # Ok(()) }
pub fn server_receive<R>(
&mut self, ake_send_a: AkeSendInit, pubkey: &PublicKey,
secretkey: &SecretKey, rng: &mut R
)
-> Result<AkeSendResponse, KyberError>
where R: CryptoRng + RngCore
&mut self,
ake_send_a: AkeSendInit,
pubkey: &PublicKey,
secretkey: &SecretKey,
rng: &mut R,
) -> Result<AkeSendResponse, KyberError>
where
R: CryptoRng + RngCore,
{
ake_shared_b(
&mut self.send_b, &mut self.shared_secret,
&ake_send_a, secretkey, pubkey, rng
)?;
ake_shared_b(&mut self.send_b, &mut self.shared_secret, &ake_send_a, secretkey, pubkey, rng)?;
Ok(self.send_b)
}
@ -279,41 +258,25 @@ impl Ake {
/// let client_confirm = alice.client_confirm(server_send, &alice_keys.secret);
/// assert_eq!(alice.shared_secret, bob.shared_secret);
/// # Ok(()) }
pub fn client_confirm(&mut self, send_b: AkeSendResponse, secretkey: &SecretKey)
-> Result<(), KyberError>
{
ake_shared_a(
&mut self.shared_secret, &send_b,
&self.temp_key, &self.eska, secretkey
)?;
pub fn client_confirm(&mut self, send_b: AkeSendResponse, secretkey: &SecretKey) -> Result<(), KyberError> {
ake_shared_a(&mut self.shared_secret, &send_b, &self.temp_key, &self.eska, secretkey)?;
Ok(())
}
}
// Unilaterally Authenticated Key Exchange initiation
fn uake_init_a<R>(
send: &mut[u8],
tk: &mut[u8],
sk: &mut[u8],
pkb: &[u8],
rng: &mut R
)
where R: CryptoRng + RngCore
fn uake_init_a<R>(send: &mut [u8], tk: &mut [u8], sk: &mut [u8], pkb: &[u8], rng: &mut R)
where
R: CryptoRng + RngCore,
{
crypto_kem_keypair(send, sk, rng, None);
crypto_kem_enc(&mut send[KYBER_PUBLICKEYBYTES..], tk, pkb, rng, None);
}
// Unilaterally authenticated key exchange computation by Bob
fn uake_shared_b<R>(
send: &mut[u8],
k: &mut[u8],
recv: &[u8],
skb: &[u8],
rng: &mut R
) -> Result<(), KyberError>
where R: CryptoRng + RngCore
fn uake_shared_b<R>(send: &mut [u8], k: &mut [u8], recv: &[u8], skb: &[u8], rng: &mut R) -> Result<(), KyberError>
where
R: CryptoRng + RngCore,
{
let mut buf = [0u8; 2 * KYBER_SYMBYTES];
crypto_kem_enc(send, &mut buf, recv, rng, None);
@ -323,13 +286,7 @@ fn uake_shared_b<R>(
}
// Unilaterally authenticated key exchange computation by Alice
fn uake_shared_a(
k: &mut[u8],
recv: &[u8],
tk: &[u8],
sk: &[u8]
) -> Result<(), KyberError>
{
fn uake_shared_a(k: &mut [u8], recv: &[u8], tk: &[u8], sk: &[u8]) -> Result<(), KyberError> {
let mut buf = [0u8; 2 * KYBER_SYMBYTES];
crypto_kem_dec(&mut buf, recv, sk)?;
buf[KYBER_SYMBYTES..].copy_from_slice(&tk[..]);
@ -338,29 +295,18 @@ fn uake_shared_a(
}
// Authenticated key exchange initiation by Alice
fn ake_init_a<R>(
send: &mut[u8],
tk: &mut[u8],
sk: &mut[u8],
pkb: &[u8],
rng: &mut R
)
where R: CryptoRng + RngCore
fn ake_init_a<R>(send: &mut [u8], tk: &mut [u8], sk: &mut [u8], pkb: &[u8], rng: &mut R)
where
R: CryptoRng + RngCore,
{
crypto_kem_keypair(send, sk, rng, None);
crypto_kem_enc(&mut send[KYBER_PUBLICKEYBYTES..], tk, pkb, rng, None);
}
// Mutually authenticated key exchange computation by Bob
fn ake_shared_b<R>(
send: &mut[u8],
k: &mut[u8],
recv: &[u8],
skb: &[u8],
pka: &[u8],
rng: &mut R
) -> Result<(), KyberError>
where R: CryptoRng + RngCore
fn ake_shared_b<R>(send: &mut [u8], k: &mut [u8], recv: &[u8], skb: &[u8], pka: &[u8], rng: &mut R) -> Result<(), KyberError>
where
R: CryptoRng + RngCore,
{
let mut buf = [0u8; 3 * KYBER_SYMBYTES];
crypto_kem_enc(send, &mut buf, recv, rng, None);
@ -371,14 +317,7 @@ fn ake_shared_b<R>(
}
// Mutually authenticated key exchange computation by Alice
fn ake_shared_a(
k: &mut[u8],
recv: &[u8],
tk: &[u8],
sk: &[u8],
ska: &[u8]
) -> Result<(), KyberError>
{
fn ake_shared_a(k: &mut [u8], recv: &[u8], tk: &[u8], sk: &[u8], ska: &[u8]) -> Result<(), KyberError> {
let mut buf = [0u8; 3 * KYBER_SYMBYTES];
crypto_kem_dec(&mut buf, recv, sk)?;
crypto_kem_dec(&mut buf[KYBER_SYMBYTES..], &recv[KYBER_CIPHERTEXTBYTES..], ska)?;

View file

@ -30,28 +30,20 @@
pub struct Aes256CtrCtx {
pub sk_exp: [u64; 120],
pub ivw: [u32; 16]
pub ivw: [u32; 16],
}
impl Aes256CtrCtx {
pub fn new() -> Self {
Self {
sk_exp: [0u64; 120],
ivw: [0u32; 16]
}
Self { sk_exp: [0u64; 120], ivw: [0u32; 16] }
}
}
fn br_dec32le(src: &[u8]) -> u32
{
src[0] as u32
| (src[1] as u32) << 8
| (src[2] as u32) << 16
| (src[3] as u32) << 24
fn br_dec32le(src: &[u8]) -> u32 {
src[0] as u32 | (src[1] as u32) << 8 | (src[2] as u32) << 16 | (src[3] as u32) << 24
}
fn br_range_dec32le(v: &mut [u32], mut num: usize, src: &[u8])
{
fn br_range_dec32le(v: &mut [u32], mut num: usize, src: &[u8]) {
let mut v_idx: usize = 0;
let mut src_idx: usize = 0;
while num > 0 {
@ -62,22 +54,19 @@ fn br_range_dec32le(v: &mut [u32], mut num: usize, src: &[u8])
}
}
fn br_swap32(mut x: u32) -> u32
{
fn br_swap32(mut x: u32) -> u32 {
x = ((x & 0x00FF00FFu32) << 8) | ((x >> 8) & 0x00FF00FFu32);
(x << 16) | (x >> 16)
}
fn br_enc32le(dst: &mut [u8], x: u32)
{
fn br_enc32le(dst: &mut [u8], x: u32) {
dst[0] = x as u8;
dst[1] = (x >> 8) as u8;
dst[2] = (x >> 16) as u8;
dst[3] = (x >> 24) as u8;
}
fn br_range_enc32le(dst: &mut [u8], v: &[u32], mut num: usize)
{
fn br_range_enc32le(dst: &mut [u8], v: &[u32], mut num: usize) {
let mut v_idx = 0;
let mut dst_idx = 0;
while num > 0 {
@ -88,8 +77,7 @@ fn br_range_enc32le(dst: &mut [u8], v: &[u32], mut num: usize)
}
}
fn br_aes_ct64_bitslice_sbox(q: &mut [u64])
{
fn br_aes_ct64_bitslice_sbox(q: &mut [u64]) {
// This S-box implementation is a straightforward translation of
// the circuit described by Boyar and Peralta in "A new
// combinational logic minimization technique with applications
@ -253,31 +241,26 @@ fn br_aes_ct64_bitslice_sbox(q: &mut [u64])
q[0] = s7;
}
fn swapn(cl: u64, ch: u64, s: usize, x: u64, y: &mut u64) -> u64
{
fn swapn(cl: u64, ch: u64, s: usize, x: u64, y: &mut u64) -> u64 {
let a = x;
let b = *y;
*y = ((a & ch) >> (s)) | (b & ch); // update y
(a & cl) | ((b & cl) << s) // return x
}
fn swap2(x: u64, y: &mut u64) -> u64
{
fn swap2(x: u64, y: &mut u64) -> u64 {
swapn(0x5555555555555555u64, 0xAAAAAAAAAAAAAAAAu64, 1, x, y)
}
fn swap4(x: u64, y: &mut u64) -> u64
{
fn swap4(x: u64, y: &mut u64) -> u64 {
swapn(0x3333333333333333u64, 0xCCCCCCCCCCCCCCCCu64, 2, x, y)
}
fn swap8(x: u64, y: &mut u64) -> u64
{
fn swap8(x: u64, y: &mut u64) -> u64 {
swapn(0x0F0F0F0F0F0F0F0Fu64, 0xF0F0F0F0F0F0F0F0u64, 4, x, y)
}
fn br_aes_ct64_ortho(q: &mut [u64])
{
fn br_aes_ct64_ortho(q: &mut [u64]) {
q[0] = swap2(q[0], &mut q[1]);
q[2] = swap2(q[2], &mut q[3]);
q[4] = swap2(q[4], &mut q[5]);
@ -294,8 +277,7 @@ fn br_aes_ct64_ortho(q: &mut [u64])
q[3] = swap8(q[3], &mut q[7]);
}
fn br_aes_ct64_interleave_in(q0: &mut u64, q1: &mut u64, w: &[u32])
{
fn br_aes_ct64_interleave_in(q0: &mut u64, q1: &mut u64, w: &[u32]) {
let (mut x0, mut x1, mut x2, mut x3): (u64, u64, u64, u64);
x0 = w[0].into();
@ -322,8 +304,7 @@ fn br_aes_ct64_interleave_in(q0: &mut u64, q1: &mut u64, w: &[u32])
*q1 = x1 | (x3 << 8);
}
fn br_aes_ct64_interleave_out(w: &mut[u32], q0: u64, q1: u64)
{
fn br_aes_ct64_interleave_out(w: &mut [u32], q0: u64, q1: u64) {
let (mut x0, mut x1, mut x2, mut x3): (u64, u64, u64, u64);
x0 = q0 & 0x00FF00FF00FF00FFu64;
@ -355,8 +336,7 @@ fn sub_word(x: u32) -> u32 {
const RCON: [u32; 10] = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36];
fn br_aes_ct64_keysched(comp_skey: &mut[u64], key: &[u8])
{
fn br_aes_ct64_keysched(comp_skey: &mut [u64], key: &[u8]) {
let (mut j, mut k) = (0usize, 0usize);
let mut skey = [0u32; 60];
@ -386,7 +366,6 @@ fn br_aes_ct64_keysched(comp_skey: &mut[u64], key: &[u8])
for idx in (0..nkf).step_by(4) {
let mut q = [0u64; 8];
let (q0, q1) = q.split_at_mut(4);
br_aes_ct64_interleave_in(&mut q0[0], &mut q1[0], &skey[idx..]);
q[1] = q[0];
@ -397,21 +376,14 @@ fn br_aes_ct64_keysched(comp_skey: &mut[u64], key: &[u8])
q[7] = q[4];
br_aes_ct64_ortho(&mut q);
comp_skey[j] =
(q[0] & 0x1111111111111111)
| (q[1] & 0x2222222222222222)
| (q[2] & 0x4444444444444444)
| (q[3] & 0x8888888888888888);
(q[0] & 0x1111111111111111) | (q[1] & 0x2222222222222222) | (q[2] & 0x4444444444444444) | (q[3] & 0x8888888888888888);
comp_skey[j + 1] =
(q[4] & 0x1111111111111111)
| (q[5] & 0x2222222222222222)
| (q[6] & 0x4444444444444444)
| (q[7] & 0x8888888888888888);
(q[4] & 0x1111111111111111) | (q[5] & 0x2222222222222222) | (q[6] & 0x4444444444444444) | (q[7] & 0x8888888888888888);
j += 2;
}
}
fn br_aes_ct64_skey_expand(skey: &mut[u64], comp_skey: &[u64])
{
fn br_aes_ct64_skey_expand(skey: &mut [u64], comp_skey: &[u64]) {
const N: usize = 15 << 1;
let mut u = 0;
let mut v = 0;
@ -440,8 +412,7 @@ fn br_aes_ct64_skey_expand(skey: &mut[u64], comp_skey: &[u64])
}
}
fn add_round_key(q: &mut[u64], sk: &[u64])
{
fn add_round_key(q: &mut [u64], sk: &[u64]) {
q[0] ^= sk[0];
q[1] ^= sk[1];
q[2] ^= sk[2];
@ -452,8 +423,7 @@ fn add_round_key(q: &mut[u64], sk: &[u64])
q[7] ^= sk[7];
}
fn shift_rows(q: &mut [u64])
{
fn shift_rows(q: &mut [u64]) {
for x in q.iter_mut() {
*x = (*x & 0x000000000000FFFF)
| ((*x & 0x00000000FFF00000) >> 4)
@ -462,16 +432,14 @@ fn shift_rows(q: &mut [u64])
| ((*x & 0x000000FF00000000) << 8)
| ((*x & 0xF000000000000000) >> 12)
| ((*x & 0x0FFF000000000000) << 4)
};
}
}
fn rotr32(x: u64) -> u64
{
fn rotr32(x: u64) -> u64 {
(x << 32) | (x >> 32)
}
fn mix_columns(q: &mut [u64])
{
fn mix_columns(q: &mut [u64]) {
let q0 = q[0];
let q1 = q[1];
let q2 = q[2];
@ -499,14 +467,12 @@ fn mix_columns(q: &mut [u64])
q[7] = q6 ^ r6 ^ r7 ^ rotr32(q7 ^ r7);
}
fn inc4_be(x: u32) -> u32
{
fn inc4_be(x: u32) -> u32 {
let t = br_swap32(x) + 4;
br_swap32(t)
}
fn aes_ctr4x(out: &mut [u8], ivw: &mut [u32], sk_exp: &[u64])
{
fn aes_ctr4x(out: &mut [u8], ivw: &mut [u32], sk_exp: &[u64]) {
let mut w = [0u32; 16];
w.copy_from_slice(&ivw);
let mut q = [0u64; 8];
@ -540,15 +506,13 @@ fn aes_ctr4x(out: &mut [u8], ivw: &mut [u32], sk_exp: &[u64])
ivw[15] = inc4_be(ivw[15]);
}
fn br_aes_ct64_ctr_init(sk_exp: &mut [u64], key: &[u8])
{
fn br_aes_ct64_ctr_init(sk_exp: &mut [u64], key: &[u8]) {
let mut skey = [0u64; 30];
br_aes_ct64_keysched(&mut skey, key);
br_aes_ct64_skey_expand(sk_exp, &skey);
}
fn br_aes_ct64_ctr_run(sk_exp: &mut[u64], iv: &[u8], cc: u32, data: &mut[u8], mut len: usize)
{
fn br_aes_ct64_ctr_run(sk_exp: &mut [u64], iv: &[u8], cc: u32, data: &mut [u8], mut len: usize) {
let mut ivw = [0u32; 16];
br_range_dec32le(&mut ivw, 3, iv);
let mut slice = [0u32; 3];
@ -583,8 +547,7 @@ fn br_aes_ct64_ctr_run(sk_exp: &mut[u64], iv: &[u8], cc: u32, data: &mut[u8], mu
// - usize outlen: length of requested output in bytes
// - const [u8] key: 32-byte key
// - const u8 nonce: 1-byte nonce (will be zero-padded to 12 bytes)
pub fn aes256ctr_prf(output: &mut[u8], outlen: usize, key: &[u8], nonce: u8)
{
pub fn aes256ctr_prf(output: &mut [u8], outlen: usize, key: &[u8], nonce: u8) {
let mut sk_exp = [0u64; 120];
let mut pad_nonce = [0u8; 12];
pad_nonce[0] = nonce;
@ -601,12 +564,7 @@ pub fn aes256ctr_prf(output: &mut[u8], outlen: usize, key: &[u8], nonce: u8)
// Arguments: - aes256xof_ctx *s: state to "absorb" key and IV into
// - const [u8] key: 32-byte key
// - [u8] nonce: additional bytes to "absorb"
pub fn aes256ctr_init(
s: &mut Aes256CtrCtx,
key: &[u8],
nonce: [u8; 12]
)
{
pub fn aes256ctr_init(s: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12]) {
br_aes_ct64_ctr_init(&mut s.sk_exp, key);
br_range_dec32le(&mut s.ivw, 3, &nonce);
@ -621,12 +579,7 @@ pub fn aes256ctr_init(
s.ivw[15] = br_swap32(3);
}
pub fn aes256ctr_squeezeblocks(
out: &mut[u8],
mut nblocks: usize,
s: &mut Aes256CtrCtx
)
{
pub fn aes256ctr_squeezeblocks(out: &mut [u8], mut nblocks: usize, s: &mut Aes256CtrCtx) {
let mut idx = 0;
while nblocks > 0 {
aes_ctr4x(&mut out[idx..], &mut s.ivw, &s.sk_exp);

View file

@ -1,5 +1,5 @@
use crate::poly::Poly;
use crate::params::KYBER_N;
use crate::poly::Poly;
// Name: load32_littleendian
//
@ -9,8 +9,7 @@ use crate::params::KYBER_N;
// Arguments: - const [u8] x: input byte array
//
// Returns 32-bit unsigned integer loaded from x
fn load32_littleendian(x: &[u8]) -> u32
{
fn load32_littleendian(x: &[u8]) -> u32 {
let mut r = x[0] as u32;
r |= (x[1] as u32) << 8;
r |= (x[2] as u32) << 16;
@ -27,8 +26,7 @@ fn load32_littleendian(x: &[u8]) -> u32
// Arguments: - const [u8] x: input byte array
//
// Returns 32-bit unsigned integer loaded from x
fn load24_littleendian(x: &[u8]) -> u32
{
fn load24_littleendian(x: &[u8]) -> u32 {
let mut r = x[0] as u32;
r |= (x[1] as u32) << 8;
r |= (x[2] as u32) << 16;
@ -43,8 +41,7 @@ fn load24_littleendian(x: &[u8]) -> u32
//
// Arguments: - poly *r: output polynomial
// - const [u8] buf: input byte array
pub fn cbd2(r: &mut Poly, buf: &[u8])
{
pub fn cbd2(r: &mut Poly, buf: &[u8]) {
let (mut d, mut t, mut a, mut b);
for i in 0..(KYBER_N / 8) {
t = load32_littleendian(&buf[4 * i..]);
@ -66,8 +63,7 @@ pub fn cbd2(r: &mut Poly, buf: &[u8])
// This function is only needed for Kyber-512
// Arguments: - poly *r: output polynomial
// - const [u8] buf: input byte array
pub fn cbd3(r: &mut Poly, buf: &[u8])
{
pub fn cbd3(r: &mut Poly, buf: &[u8]) {
let (mut d, mut t, mut a, mut b);
for i in 0..(KYBER_N / 4) {
t = load24_littleendian(&buf[3 * i..]);
@ -82,17 +78,14 @@ pub fn cbd3(r: &mut Poly, buf: &[u8])
}
}
pub fn poly_cbd_eta1(r: &mut Poly, buf: &[u8])
{
pub fn poly_cbd_eta1(r: &mut Poly, buf: &[u8]) {
if cfg!(feature = "kyber512") {
cbd3(r, buf)
}
else {
} else {
cbd2(r, buf)
}
}
pub fn poly_cbd_eta2(r: &mut Poly, buf: &[u8])
{
pub fn poly_cbd_eta2(r: &mut Poly, buf: &[u8]) {
cbd2(r, buf)
}

View file

@ -8,8 +8,7 @@ const SHA3_256_RATE: usize = 136;
const SHA3_512_RATE: usize = 72;
const NROUNDS: usize = 24;
fn rol(a: u64, offset: u64) -> u64
{
fn rol(a: u64, offset: u64) -> u64 {
(a << offset) ^ (a >> (64 - offset))
}
@ -20,8 +19,7 @@ fn rol(a: u64, offset: u64) -> u64
// Arguments: - const [u8] x: input byte array
//
// Returns the loaded 64-bit unsigned integer
pub fn load64(x: &[u8]) -> u64
{
pub fn load64(x: &[u8]) -> u64 {
let mut r = 0u64;
for i in 0..8 {
r |= (x[i] as u64) << (8 * i);
@ -35,8 +33,7 @@ pub fn load64(x: &[u8]) -> u64
//
// Arguments: - [u8] x: the output byte array
// - u64 u: input 64-bit unsigned integer
pub fn store64(x: &mut[u8], mut u: u64)
{
pub fn store64(x: &mut [u8], mut u: u64) {
for i in x.iter_mut().take(8) {
*i = u as u8;
u >>= 8;
@ -68,7 +65,7 @@ const KECCAKF_ROUNDCONSTANTS: [u64; NROUNDS] = [
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008
0x8000000080008008,
];
// Name: KeccakF1600_StatePermute
@ -76,8 +73,7 @@ const KECCAKF_ROUNDCONSTANTS: [u64; NROUNDS] = [
// Description: The Keccak F1600 Permutation
//
// Arguments: - u64 * state: in/output Keccak state
pub fn keccakf1600_statepermute(state: &mut[u64])
{
pub fn keccakf1600_statepermute(state: &mut [u64]) {
//copyFromState(A, state)
let mut aba = state[0];
let mut abe = state[1];
@ -334,14 +330,7 @@ pub fn keccakf1600_statepermute(state: &mut[u64])
// - usize r: rate in bytes (e.g., 168 for SHAKE128)
// - const [u8] input: pointer to input to be absorbed into s
// - u64 inlen: length of input in bytes
pub(crate) fn keccak_absorb(
s: &mut[u64],
mut pos: usize,
r: usize,
input: &[u8],
mut inlen: usize
) -> usize
{
pub(crate) fn keccak_absorb(s: &mut [u64], mut pos: usize, r: usize, input: &[u8], mut inlen: usize) -> usize {
let mut idx = 0usize;
while pos + inlen >= r {
for i in pos..r {
@ -369,8 +358,7 @@ pub(crate) fn keccak_absorb(
// - u64 nblocks: number of blocks to be squeezed (written to h)
// - u64 *s: in/output Keccak state
// - usize r: rate in bytes (e.g., 168 for SHAKE128)
pub(crate) fn keccak_squeezeblocks(h: &mut[u8], mut nblocks: usize, s: &mut [u64], r: usize)
{
pub(crate) fn keccak_squeezeblocks(h: &mut [u8], mut nblocks: usize, s: &mut [u64], r: usize) {
let mut idx = 0usize;
while nblocks > 0 {
keccakf1600_statepermute(s);
@ -390,8 +378,7 @@ pub(crate) fn keccak_squeezeblocks(h: &mut[u8], mut nblocks: usize, s: &mut [u64
// Arguments: - u64 *s: (uninitialized) output Keccak state
// - const [u8] input: input to be absorbed into s
// - u64 inputByteLen: length of input in bytes
pub(crate) fn shake128_absorb(state: &mut KeccakState, input: &[u8], inlen: usize)
{
pub(crate) fn shake128_absorb(state: &mut KeccakState, input: &[u8], inlen: usize) {
let pos = state.pos;
state.pos = keccak_absorb(&mut state.s, pos, SHAKE128_RATE, input, inlen);
}
@ -406,8 +393,7 @@ pub(crate) fn shake128_absorb(state: &mut KeccakState, input: &[u8], inlen: usiz
// Arguments: - [u8] out: pointer to output blocks
// - u64 nblocks: number of blocks to be squeezed (written to output)
// - KeccakState state: pointer to input/output Keccak state
pub(crate) fn shake128_squeezeblocks(out: &mut[u8], nblocks: usize, state: &mut KeccakState)
{
pub(crate) fn shake128_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) {
keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE128_RATE);
}
@ -419,8 +405,7 @@ pub(crate) fn shake128_squeezeblocks(out: &mut[u8], nblocks: usize, state: &mut
// - usize outlen: requested output length in bytes
// - [u8] input: input
// - usize inlen: length of input in bytes
pub(crate) fn shake256(out: &mut[u8], mut outlen: usize, input: &[u8], inlen: usize)
{
pub(crate) fn shake256(out: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) {
let mut state = KeccakState::new();
let mut idx = 0;
shake256_absorb_once(&mut state, input, inlen);
@ -438,8 +423,7 @@ pub(crate) fn shake256(out: &mut[u8], mut outlen: usize, input: &[u8], inlen: us
// Arguments: - [u8] h: output (32 bytes)
// - const [u8] input: input
// - usize inlen: length of input in bytes
pub(crate) fn sha3_256(h: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn sha3_256(h: &mut [u8], input: &[u8], inlen: usize) {
let mut s = [0u64; 25];
keccak_absorb_once(&mut s, SHA3_256_RATE, input, inlen, 0x06);
keccakf1600_statepermute(&mut s);
@ -455,8 +439,7 @@ pub(crate) fn sha3_256(h: &mut[u8], input: &[u8], inlen: usize)
// Arguments: - [u8] h: output (64 bytes)
// - const [u8] input: input
// - usize inlen: length of input in bytes
pub(crate) fn sha3_512(h: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn sha3_512(h: &mut [u8], input: &[u8], inlen: usize) {
let mut s = [0u64; 25];
keccak_absorb_once(&mut s, SHA3_512_RATE, input, inlen, 0x06);
keccakf1600_statepermute(&mut s);
@ -465,8 +448,6 @@ pub(crate) fn sha3_512(h: &mut[u8], input: &[u8], inlen: usize)
}
}
// Name: keccak_finalize
//
// Description: Finalize absorb step.
@ -475,8 +456,7 @@ pub(crate) fn sha3_512(h: &mut[u8], input: &[u8], inlen: usize)
// - usize pos: position in current block to be absorbed
// - usize r: rate in bytes (e.g., 168 for SHAKE128)
// - u8 p: domain separation byte
fn keccak_finalize(s: &mut[u64], pos: usize, r: usize, p: u8)
{
fn keccak_finalize(s: &mut [u64], pos: usize, r: usize, p: u8) {
s[pos / 8] ^= (p as u64) << 8 * (pos % 8);
s[r / 8 - 1] ^= 1u64 << 63;
}
@ -491,14 +471,7 @@ fn keccak_finalize(s: &mut[u64], pos: usize, r: usize, p: u8)
// - const [u8] input: input to be absorbed into s
// - u64 mlen: length of input in bytes
// - [u8] p: domain-separation byte for different Keccak-derived functions
pub(crate) fn keccak_absorb_once(
s: &mut[u64],
r: usize,
input: &[u8],
mut inlen:
usize,
p: u8)
{
pub(crate) fn keccak_absorb_once(s: &mut [u64], r: usize, input: &[u8], mut inlen: usize, p: u8) {
// Zero State
for i in s.iter_mut() {
*i = 0;
@ -533,14 +506,7 @@ pub(crate) fn keccak_absorb_once(
// usize pos: number of bytes in current block already squeezed
// - usize r: rate in bytes (e.g., 168 for SHAKE128)
// Returns new position pos in current block
pub(crate) fn keccak_squeeze(
out: &mut[u8],
mut outlen: usize,
s: &mut [u64],
mut pos: usize,
r: usize
) -> usize
{
pub(crate) fn keccak_squeeze(out: &mut [u8], mut outlen: usize, s: &mut [u64], mut pos: usize, r: usize) -> usize {
let mut idx = 0;
while outlen > 0 {
if pos == r {
@ -564,19 +530,16 @@ pub(crate) fn keccak_squeeze(
// Description: Initilizes Keccak state for use as SHAKE128 XOF
//
// Arguments: - keccak_state state: (uninitialized) Keccak state
fn shake128_init(state: &mut KeccakState)
{
fn shake128_init(state: &mut KeccakState) {
state.reset()
}
// Name: shake128_finalize
//
// Description: Finalize absorb step of the SHAKE128 XOF.
//
// Arguments: - keccak_state state: pointer to Keccak state
fn shake128_finalize(state: &mut KeccakState)
{
fn shake128_finalize(state: &mut KeccakState) {
keccak_finalize(&mut state.s, state.pos, SHAKE128_RATE, 0x1F);
state.pos = SHAKE128_RATE;
}
@ -589,8 +552,7 @@ fn shake128_finalize(state: &mut KeccakState)
// Arguments: - [u8] out: pointer to output blocks
// - usize outlen : number of bytes to be squeezed (written to output)
// - keccak_state s: pointer to input/output Keccak state
fn shake128_squeeze(out: &mut[u8], outlen: usize, state: &mut KeccakState)
{
fn shake128_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) {
state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE128_RATE);
}
@ -601,8 +563,7 @@ fn shake128_squeeze(out: &mut[u8], outlen: usize, state: &mut KeccakState)
// Arguments: - keccak_state state: pointer to (uninitialized) output Keccak state
// - const [u8] in: input to be absorbed into s
// - usize inlen: length of input in bytes
pub(crate) fn shake128_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize)
{
pub(crate) fn shake128_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) {
keccak_absorb_once(&mut state.s, SHAKE128_RATE, input, inlen, 0x1F);
state.pos = SHAKE128_RATE;
}
@ -611,35 +572,29 @@ fn shake256_init(state: &mut KeccakState) {
state.reset();
}
fn shake256_absorb(state: &mut KeccakState, input: &[u8], inlen: usize)
{
fn shake256_absorb(state: &mut KeccakState, input: &[u8], inlen: usize) {
state.pos = keccak_absorb(&mut state.s, state.pos, SHAKE256_RATE, input, inlen);
}
fn shake256_finalize(state: &mut KeccakState)
{
fn shake256_finalize(state: &mut KeccakState) {
keccak_finalize(&mut state.s, state.pos, SHAKE256_RATE, 0x1F);
state.pos = SHAKE256_RATE;
}
fn shake256_squeeze(out: &mut[u8], outlen: usize, state: &mut KeccakState)
{
fn shake256_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) {
state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE256_RATE);
}
fn shake256_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize)
{
fn shake256_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) {
keccak_absorb_once(&mut state.s, SHAKE256_RATE, input, inlen, 0x1F);
state.pos = SHAKE256_RATE;
}
fn shake256_squeezeblocks(out: &mut[u8], nblocks: usize, state: &mut KeccakState)
{
fn shake256_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) {
keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE256_RATE);
}
fn shake128(out: &mut[u8], mut outlen: usize, input: &[u8], inlen: usize)
{
fn shake128(out: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) {
let mut state = KeccakState::new();
let mut idx = 0;
shake128_absorb_once(&mut state, input, inlen);
@ -649,4 +604,3 @@ fn shake128(out: &mut[u8], mut outlen: usize, input: &[u8], inlen: usize)
idx += nblocks * SHAKE128_RATE;
shake128_squeeze(&mut out[idx..], outlen, &mut state);
}

View file

@ -1,13 +1,6 @@
#[cfg(not(feature = "KATs"))]
use crate::rng::randombytes;
use crate::{
poly::*,
polyvec::*,
symmetric::*,
params::*,
RngCore,
CryptoRng,
};
use crate::{params::*, poly::*, polyvec::*, symmetric::*, CryptoRng, RngCore};
// Name: pack_pk
//
@ -18,8 +11,7 @@ use crate::{
// Arguments: [u8] r: the output serialized public key
// const poly *pk: the input public-key polynomial
// const [u8] seed: the input public seed
fn pack_pk(r: &mut[u8], pk: &mut Polyvec, seed: &[u8])
{
fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) {
const END: usize = KYBER_SYMBYTES + KYBER_POLYVECBYTES;
polyvec_tobytes(r, pk);
r[KYBER_POLYVECBYTES..END].copy_from_slice(&seed[..KYBER_SYMBYTES]);
@ -33,8 +25,7 @@ fn pack_pk(r: &mut[u8], pk: &mut Polyvec, seed: &[u8])
// Arguments: - Polyvec pk: output public-key vector of polynomials
// - [u8] seed: output seed to generate matrix A
// - const [u8] packedpk: input serialized public key
fn unpack_pk(pk: &mut Polyvec, seed: &mut[u8], packedpk: &[u8])
{
fn unpack_pk(pk: &mut Polyvec, seed: &mut [u8], packedpk: &[u8]) {
const END: usize = KYBER_SYMBYTES + KYBER_POLYVECBYTES;
polyvec_frombytes(pk, packedpk);
seed[..KYBER_SYMBYTES].copy_from_slice(&packedpk[KYBER_POLYVECBYTES..END]);
@ -46,8 +37,7 @@ fn unpack_pk(pk: &mut Polyvec, seed: &mut[u8], packedpk: &[u8])
//
// Arguments: - [u8] r: output serialized secret key
// - const Polyvec sk: input vector of polynomials (secret key)
fn pack_sk(r: &mut[u8], sk: &mut Polyvec)
{
fn pack_sk(r: &mut [u8], sk: &mut Polyvec) {
polyvec_tobytes(r, sk);
}
@ -57,8 +47,7 @@ fn pack_sk(r: &mut[u8], sk: &mut Polyvec)
//
// Arguments: - Polyvec sk: output vector of polynomials (secret key)
// - const [u8] packedsk: input serialized secret key
fn unpack_sk(sk: &mut Polyvec, packedsk: &[u8])
{
fn unpack_sk(sk: &mut Polyvec, packedsk: &[u8]) {
polyvec_frombytes(sk, packedsk);
}
@ -71,8 +60,7 @@ fn unpack_sk(sk: &mut Polyvec, packedsk: &[u8])
// Arguments: [u8] r: the output serialized ciphertext
// const poly *pk: the input vector of polynomials b
// const [u8] seed: the input polynomial v
fn pack_ciphertext(r: &mut[u8], b: &mut Polyvec, v: Poly)
{
fn pack_ciphertext(r: &mut [u8], b: &mut Polyvec, v: Poly) {
polyvec_compress(r, *b);
poly_compress(&mut r[KYBER_POLYVECCOMPRESSEDBYTES..], v);
}
@ -85,8 +73,7 @@ fn pack_ciphertext(r: &mut[u8], b: &mut Polyvec, v: Poly)
// Arguments: - Polyvec b: output vector of polynomials b
// - poly *v: output polynomial v
// - const [u8] c: input serialized ciphertext
fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8])
{
fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8]) {
polyvec_decompress(b, c);
poly_decompress(v, &c[KYBER_POLYVECCOMPRESSEDBYTES..]);
}
@ -102,8 +89,7 @@ fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8])
// - usize buflen: length of input buffer in bytes
//
// Returns number of sampled 16-bit integers (at most len)
fn rej_uniform(r: &mut[i16], len: usize, buf: &[u8], buflen: usize) -> usize
{
fn rej_uniform(r: &mut [i16], len: usize, buf: &[u8], buflen: usize) -> usize {
let (mut ctr, mut pos) = (0usize, 0usize);
let (mut val0, mut val1);
@ -124,13 +110,11 @@ fn rej_uniform(r: &mut[i16], len: usize, buf: &[u8], buflen: usize) -> usize
ctr
}
fn gen_a(a: &mut [Polyvec], b: &[u8])
{
fn gen_a(a: &mut [Polyvec], b: &[u8]) {
gen_matrix(a, b, false);
}
fn gen_at(a: &mut [Polyvec], b: &[u8])
{
fn gen_at(a: &mut [Polyvec], b: &[u8]) {
gen_matrix(a, b, true);
}
@ -144,12 +128,10 @@ fn gen_at(a: &mut [Polyvec], b: &[u8])
// Arguments: - Polyvec a: ouptput matrix A
// - const [u8] seed: input seed
// - bool transposed: boolean deciding whether A or A^T is generated
fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool)
{
fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) {
let mut ctr;
// 530 is expected number of required bytes
const GEN_MATRIX_NBLOCKS: usize =
(12*KYBER_N/8*(1 << 12)/KYBER_Q + XOF_BLOCKBYTES)/XOF_BLOCKBYTES;
const GEN_MATRIX_NBLOCKS: usize = (12 * KYBER_N / 8 * (1 << 12) / KYBER_Q + XOF_BLOCKBYTES) / XOF_BLOCKBYTES;
const BUFLEN: usize = GEN_MATRIX_NBLOCKS * XOF_BLOCKBYTES;
let mut buf = [0u8; BUFLEN + 2];
let mut off: usize;
@ -159,15 +141,13 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool)
for j in 0..KYBER_K {
if transposed {
xof_absorb(&mut state, seed, i as u8, j as u8);
}
else {
} else {
xof_absorb(&mut state, seed, j as u8, i as u8);
}
xof_squeezeblocks(&mut buf, GEN_MATRIX_NBLOCKS, &mut state);
ctr = rej_uniform(&mut a[i].vec[j].coeffs, KYBER_N, &buf, BUFLEN);
while ctr < KYBER_N
{
while ctr < KYBER_N {
off = BUFLEN % 3;
for k in 0..off {
buf[k] = buf[BUFLEN - off + k];
@ -186,13 +166,9 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool)
//
// Arguments: - [u8] pk: output public key (length KYBER_INDCPA_PUBLICKEYBYTES)
// - [u8] sk: output private key (length KYBER_INDCPA_SECRETKEYBYTES)
pub fn indcpa_keypair<R>(
pk : &mut[u8],
sk: &mut[u8],
_seed: Option<(&[u8], &[u8])>,
_rng: &mut R
)
where R: CryptoRng + RngCore
pub fn indcpa_keypair<R>(pk: &mut [u8], sk: &mut [u8], _seed: Option<(&[u8], &[u8])>, _rng: &mut R)
where
R: CryptoRng + RngCore,
{
let mut a = [Polyvec::new(); KYBER_K];
let (mut e, mut pkpv, mut skpv) = (Polyvec::new(), Polyvec::new(), Polyvec::new());
@ -246,11 +222,9 @@ pub fn indcpa_keypair<R>(
// - const [u8] pk: input public key (length KYBER_INDCPA_PUBLICKEYBYTES)
// - const [u8] coin: input random coins used as seed (length KYBER_SYMBYTES)
// to deterministically generate all randomness
pub fn indcpa_enc(c: &mut[u8], m: &[u8], pk: &[u8], coins: &[u8])
{
pub fn indcpa_enc(c: &mut [u8], m: &[u8], pk: &[u8], coins: &[u8]) {
let mut at = [Polyvec::new(); KYBER_K];
let (mut sp, mut pkpv, mut ep, mut b) =
(Polyvec::new(),Polyvec::new(), Polyvec::new(), Polyvec::new());
let (mut sp, mut pkpv, mut ep, mut b) = (Polyvec::new(), Polyvec::new(), Polyvec::new(), Polyvec::new());
let (mut v, mut k, mut epp) = (Poly::new(), Poly::new(), Poly::new());
let mut seed = [0u8; KYBER_SYMBYTES];
let mut nonce = 0u8;
@ -297,8 +271,7 @@ pub fn indcpa_enc(c: &mut[u8], m: &[u8], pk: &[u8], coins: &[u8])
// Arguments: - [u8] m: output decrypted message (of length KYBER_INDCPA_MSGBYTES)
// - const [u8] c: input ciphertext (of length KYBER_INDCPA_BYTES)
// - const [u8] sk: input secret key (of length KYBER_INDCPA_SECRETKEYBYTES)
pub fn indcpa_dec(m: &mut[u8], c: &[u8], sk: &[u8])
{
pub fn indcpa_dec(m: &mut [u8], c: &[u8], sk: &[u8]) {
let (mut b, mut skpv) = (Polyvec::new(), Polyvec::new());
let (mut v, mut mp) = (Poly::new(), Poly::new());

View file

@ -37,22 +37,12 @@ use crate::reduce::*;
//}
pub const ZETAS: [i16; 128] = [
-1044, -758, -359, -1517, 1493, 1422, 287, 202,
-171, 622, 1577, 182, 962, -1202, -1474, 1468,
573, -1325, 264, 383, -829, 1458, -1602, -130,
-681, 1017, 732, 608, -1542, 411, -205, -1571,
1223, 652, -552, 1015, -1293, 1491, -282, -1544,
516, -8, -320, -666, -1618, -1162, 126, 1469,
-853, -90, -271, 830, 107, -1421, -247, -951,
-398, 961, -1508, -725, 448, -1065, 677, -1275,
-1103, 430, 555, 843, -1251, 871, 1550, 105,
422, 587, 177, -235, -291, -460, 1574, 1653,
-246, 778, 1159, -147, -777, 1483, -602, 1119,
-1590, 644, -872, 349, 418, 329, -156, -75,
817, 1097, 603, 610, 1322, -1285, -1465, 384,
-1215, -136, 1218, -1335, -874, 220, -1187, -1659,
-1185, -1530, -1278, 794, -1510, -854, -870, 478,
-108, -308, 996, 991, 958, -1460, 1522, 1628
-1044, -758, -359, -1517, 1493, 1422, 287, 202, -171, 622, 1577, 182, 962, -1202, -1474, 1468, 573, -1325, 264, 383, -829, 1458, -1602,
-130, -681, 1017, 732, 608, -1542, 411, -205, -1571, 1223, 652, -552, 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666, -1618,
-1162, 126, 1469, -853, -90, -271, 830, 107, -1421, -247, -951, -398, 961, -1508, -725, 448, -1065, 677, -1275, -1103, 430, 555, 843,
-1251, 871, 1550, 105, 422, 587, 177, -235, -291, -460, 1574, 1653, -246, 778, 1159, -147, -777, 1483, -602, 1119, -1590, 644, -872,
349, 418, 329, -156, -75, 817, 1097, 603, 610, 1322, -1285, -1465, 384, -1215, -136, 1218, -1335, -874, 220, -1187, -1659, -1185,
-1530, -1278, 794, -1510, -854, -870, 478, -108, -308, 996, 991, 958, -1460, 1522, 1628,
];
// Name: fqmul
@ -63,8 +53,7 @@ pub const ZETAS: [i16; 128] = [
// - i16 b: second factor
//
// Returns 16-bit integer congruent to a*b*R^{-1} mod q
pub fn fqmul(a: i16, b: i16) -> i16
{
pub fn fqmul(a: i16, b: i16) -> i16 {
montgomery_reduce(a as i32 * b as i32)
}
@ -74,8 +63,7 @@ pub fn fqmul(a: i16, b: i16) -> i16
// input is in standard order, output is in bitreversed order
//
// Arguments: - i16 r[256]: input/output vector of elements of Zq
pub fn ntt(r: &mut[i16])
{
pub fn ntt(r: &mut [i16]) {
let mut j;
let mut k = 1usize;
let mut len = 128;
@ -105,8 +93,7 @@ pub fn ntt(r: &mut[i16])
// input is in bitreversed order, output is in standard order
//
// Arguments: - i16 r[256]: input/output vector of elements of Zq
pub fn invntt(r: &mut[i16])
{
pub fn invntt(r: &mut [i16]) {
let mut j;
let mut k = 127usize;
let mut len = 2;
@ -143,8 +130,7 @@ pub fn invntt(r: &mut[i16])
// - const i16 a[2]: the first factor
// - const i16 b[2]: the second factor
// - i16 zeta: integer defining the reduction polynomial
pub fn basemul(r: &mut[i16], a: &[i16], b: &[i16], zeta: i16)
{
pub fn basemul(r: &mut [i16], a: &[i16], b: &[i16], zeta: i16) {
r[0] = fqmul(a[1], b[1]);
r[0] = fqmul(r[0], zeta);
r[0] += fqmul(a[0], b[0]);

View file

@ -1,23 +1,15 @@
use crate::{
params::*,
ntt::*,
reduce::*,
cbd::*,
symmetric::*
};
use crate::{cbd::*, ntt::*, params::*, reduce::*, symmetric::*};
#[derive(Clone)]
pub struct Poly {
pub coeffs: [i16; KYBER_N]
pub coeffs: [i16; KYBER_N],
}
impl Copy for Poly {}
impl Default for Poly {
fn default() -> Self {
Poly {
coeffs: [0i16; KYBER_N]
}
Poly { coeffs: [0i16; KYBER_N] }
}
}
@ -34,8 +26,7 @@ impl Poly {
//
// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYCOMPRESSEDBYTES bytes)
// - const poly *a: input polynomial
pub fn poly_compress(r: &mut[u8], a: Poly)
{
pub fn poly_compress(r: &mut [u8], a: Poly) {
let mut t = [0u8; 8];
let mut k = 0usize;
let mut u: i16;
@ -55,7 +46,7 @@ pub fn poly_compress(r: &mut[u8], a: Poly)
r[k + 3] = t[6] | (t[7] << 4);
k += 4;
}
},
}
160 => {
for i in 0..(KYBER_N / 8) {
for j in 0..8 {
@ -71,12 +62,11 @@ pub fn poly_compress(r: &mut[u8], a: Poly)
r[k + 4] = (t[6] >> 2) | (t[7] << 3);
k += 5;
}
},
_ => panic!("KYBER_POLYCOMPRESSEDBYTES needs to be one of (128, 160)")
}
_ => panic!("KYBER_POLYCOMPRESSEDBYTES needs to be one of (128, 160)"),
}
}
// Name: poly_decompress
//
// Description: De-serialization and subsequent decompression of a polynomial;
@ -84,8 +74,7 @@ pub fn poly_compress(r: &mut[u8], a: Poly)
//
// Arguments: - poly *r: output polynomial
// - const [u8] a: input byte array (of length KYBER_POLYCOMPRESSEDBYTES bytes)
pub fn poly_decompress(r: &mut Poly, a: &[u8])
{
pub fn poly_decompress(r: &mut Poly, a: &[u8]) {
match KYBER_POLYCOMPRESSEDBYTES {
128 => {
let mut idx = 0usize;
@ -94,7 +83,7 @@ pub fn poly_decompress(r: &mut Poly, a: &[u8])
r.coeffs[2 * i + 1] = ((((a[idx] >> 4) as usize * KYBER_Q) + 8) >> 4) as i16;
idx += 1;
}
},
}
160 => {
let mut idx = 0usize;
let mut t = [0u8; 8];
@ -112,8 +101,8 @@ pub fn poly_decompress(r: &mut Poly, a: &[u8])
r.coeffs[8 * i + j] = ((((t[j] as u32) & 31) * KYBER_Q as u32 + 16) >> 5) as i16;
}
}
},
_ => panic!("KYBER_POLYCOMPRESSEDBYTES needs to be either (128, 160)")
}
_ => panic!("KYBER_POLYCOMPRESSEDBYTES needs to be either (128, 160)"),
}
}
@ -123,8 +112,7 @@ pub fn poly_decompress(r: &mut Poly, a: &[u8])
//
// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYBYTES bytes)
// - const poly *a: input polynomial
pub fn poly_tobytes(r: &mut[u8], a: Poly)
{
pub fn poly_tobytes(r: &mut [u8], a: Poly) {
let (mut t0, mut t1);
for i in 0..(KYBER_N / 2) {
@ -146,8 +134,7 @@ pub fn poly_tobytes(r: &mut[u8], a: Poly)
//
// Arguments: - poly *r: output polynomial
// - const [u8] a: input byte array (of KYBER_POLYBYTES bytes)
pub fn poly_frombytes(r: &mut Poly, a: &[u8])
{
pub fn poly_frombytes(r: &mut Poly, a: &[u8]) {
for i in 0..(KYBER_N / 2) {
r.coeffs[2 * i + 0] = ((a[3 * i + 0] >> 0) as u16 | ((a[3 * i + 1] as u16) << 8) & 0xFFF) as i16;
r.coeffs[2 * i + 1] = ((a[3 * i + 1] >> 4) as u16 | ((a[3 * i + 2] as u16) << 4) & 0xFFF) as i16;
@ -163,8 +150,7 @@ pub fn poly_frombytes(r: &mut Poly, a: &[u8])
// Arguments: - poly *r: output polynomial
// - const [u8] seed: input seed (pointing to array of length KYBER_SYMBYTES bytes)
// - [u8] nonce: one-byte input nonce
pub fn poly_getnoise_eta1(r: &mut Poly, seed: &[u8], nonce: u8)
{
pub fn poly_getnoise_eta1(r: &mut Poly, seed: &[u8], nonce: u8) {
const LENGTH: usize = KYBER_ETA1 * KYBER_N / 4;
let mut buf = [0u8; LENGTH];
prf(&mut buf, LENGTH, seed, nonce);
@ -180,16 +166,13 @@ pub fn poly_getnoise_eta1(r: &mut Poly, seed: &[u8], nonce: u8)
// Arguments: - poly *r: output polynomial
// - const [u8] seed: input seed (pointing to array of length KYBER_SYMBYTES bytes)
// - [u8] nonce: one-byte input nonce
pub fn poly_getnoise_eta2(r: &mut Poly, seed: &[u8], nonce: u8)
{
pub fn poly_getnoise_eta2(r: &mut Poly, seed: &[u8], nonce: u8) {
const LENGTH: usize = KYBER_ETA2 * KYBER_N / 4;
let mut buf = [0u8; LENGTH];
prf(&mut buf, LENGTH, seed, nonce);
poly_cbd_eta2(r, &buf);
}
// Name: poly_ntt
//
// Description: Computes negacyclic number-theoretic transform (NTT) of
@ -197,8 +180,7 @@ pub fn poly_getnoise_eta2(r: &mut Poly, seed: &[u8], nonce: u8)
// inputs assumed to be in normal order, output in bitreversed order
//
// Arguments: - Poly r: in/output polynomial
pub fn poly_ntt(r: &mut Poly)
{
pub fn poly_ntt(r: &mut Poly) {
ntt(&mut r.coeffs);
poly_reduce(r);
}
@ -210,8 +192,7 @@ pub fn poly_ntt(r: &mut Poly)
// inputs assumed to be in bitreversed order, output in normal order
//
// Arguments: - Poly a: in/output polynomial
pub fn poly_invntt_tomont(r: &mut Poly)
{
pub fn poly_invntt_tomont(r: &mut Poly) {
invntt(&mut r.coeffs);
}
@ -222,21 +203,15 @@ pub fn poly_invntt_tomont(r: &mut Poly)
// Arguments: - poly *r: output polynomial
// - const poly *a: first input polynomial
// - const poly *b: second input polynomial
pub fn poly_basemul(r: &mut Poly, a: &Poly, b: &Poly)
{
pub fn poly_basemul(r: &mut Poly, a: &Poly, b: &Poly) {
for i in 0..(KYBER_N / 4) {
basemul(
&mut r.coeffs[4*i..],
&a.coeffs[4*i..],
&b.coeffs[4*i..],
ZETAS[64 + i]
);
basemul(&mut r.coeffs[4 * i..], &a.coeffs[4 * i..], &b.coeffs[4 * i..], ZETAS[64 + i]);
basemul(
&mut r.coeffs[4 * i + 2..],
&a.coeffs[4 * i + 2..],
&b.coeffs[4 * i + 2..],
-(ZETAS[64 + i]));
-(ZETAS[64 + i]),
);
}
}
@ -246,8 +221,7 @@ pub fn poly_basemul(r: &mut Poly, a: &Poly, b: &Poly)
// from Montgomery domain to normal domain
//
// Arguments: - poly *r: input/output polynomial
pub fn poly_frommont(r: &mut Poly)
{
pub fn poly_frommont(r: &mut Poly) {
let f = ((1u64 << 32) % KYBER_Q as u64) as i16;
for i in 0..KYBER_N {
let a = r.coeffs[i] as i32 * f as i32;
@ -261,8 +235,7 @@ pub fn poly_frommont(r: &mut Poly)
// for details of the Barrett reduction see comments in reduce.c
//
// Arguments: - poly *r: input/output polynomial
pub fn poly_reduce(r: &mut Poly)
{
pub fn poly_reduce(r: &mut Poly) {
for i in 0..KYBER_N {
r.coeffs[i] = barrett_reduce(r.coeffs[i]);
}
@ -275,8 +248,7 @@ pub fn poly_reduce(r: &mut Poly)
// Arguments: - poly *r: output polynomial
// - const poly *a: first input polynomial
// - const poly *b: second input polynomial
pub fn poly_add(r: &mut Poly, b: &Poly)
{
pub fn poly_add(r: &mut Poly, b: &Poly) {
for i in 0..KYBER_N {
r.coeffs[i] += b.coeffs[i];
}
@ -289,8 +261,7 @@ pub fn poly_add(r: &mut Poly, b: &Poly)
// Arguments: - poly *r: output polynomial
// - const poly *a: first input polynomial
// - const poly *b: second input polynomial
pub fn poly_sub(r: &mut Poly, a: &Poly)
{
pub fn poly_sub(r: &mut Poly, a: &Poly) {
for i in 0..KYBER_N {
r.coeffs[i] = a.coeffs[i] - r.coeffs[i];
}
@ -302,8 +273,7 @@ pub fn poly_sub(r: &mut Poly, a: &Poly)
//
// Arguments: - poly *r: output polynomial
// - const [u8] msg: input message
pub fn poly_frommsg(r: &mut Poly, msg: &[u8])
{
pub fn poly_frommsg(r: &mut Poly, msg: &[u8]) {
let mut mask;
for i in 0..KYBER_SYMBYTES {
for j in 0..8 {
@ -319,8 +289,7 @@ pub fn poly_frommsg(r: &mut Poly, msg: &[u8])
//
// Arguments: - [u8] msg: output message
// - const poly *a: input polynomial
pub fn poly_tomsg(msg: &mut[u8], a: Poly)
{
pub fn poly_tomsg(msg: &mut [u8], a: Poly) {
let mut t;
for i in 0..KYBER_SYMBYTES {

View file

@ -1,21 +1,16 @@
#![allow(clippy::precedence)]
use crate::{
poly::*,
params::*
};
use crate::{params::*, poly::*};
#[derive(Clone)]
pub struct Polyvec {
pub vec: [Poly; KYBER_K]
pub vec: [Poly; KYBER_K],
}
impl Copy for Polyvec {}
impl Polyvec {
pub fn new() -> Self {
Polyvec {
vec: [Poly::new(); KYBER_K]
}
Polyvec { vec: [Poly::new(); KYBER_K] }
}
// #[cfg(debug_assertions)]
@ -36,8 +31,7 @@ impl Polyvec {
//
// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYVECCOMPRESSEDBYTES)
// - const Polyvec a: input vector of polynomials
pub fn polyvec_compress(r: &mut[u8], a: Polyvec)
{
pub fn polyvec_compress(r: &mut [u8], a: Polyvec) {
#[cfg(feature = "kyber1024")]
{
let mut t = [0u16; 8];
@ -74,8 +68,7 @@ pub fn polyvec_compress(r: &mut[u8], a: Polyvec)
for k in 0..4 {
t[k] = a.vec[i].coeffs[4 * j + k] as u16;
t[k] = t[k].wrapping_add((((t[k] as i16) >> 15) & KYBER_Q as i16) as u16);
t[k] =
(((((t[k] as u32) << 10) + KYBER_Q as u32/2)/ KYBER_Q as u32) & 0x3ff) as u16;
t[k] = (((((t[k] as u32) << 10) + KYBER_Q as u32 / 2) / KYBER_Q as u32) & 0x3ff) as u16;
}
r[idx + 0] = (t[0] >> 0) as u8;
r[idx + 1] = ((t[0] >> 8) | (t[1] << 2)) as u8;
@ -95,9 +88,7 @@ pub fn polyvec_compress(r: &mut[u8], a: Polyvec)
//
// Arguments: - Polyvec r: output vector of polynomials
// - [u8] a: input byte array (of length KYBER_POLYVECCOMPRESSEDBYTES)
pub fn polyvec_decompress(r: &mut Polyvec, a: &[u8])
{
pub fn polyvec_decompress(r: &mut Polyvec, a: &[u8]) {
#[cfg(feature = "kyber1024")]
{
let mut t = [0u16; 8];
@ -115,8 +106,7 @@ pub fn polyvec_decompress(r: &mut Polyvec, a: &[u8])
idx += 11;
for k in 0..8 {
r.vec[i].coeffs[8*j+k] =
(((t[k] & 0x7FF)as u32 * KYBER_Q as u32 + 1024) >> 11) as i16;
r.vec[i].coeffs[8 * j + k] = (((t[k] & 0x7FF) as u32 * KYBER_Q as u32 + 1024) >> 11) as i16;
}
}
}
@ -135,8 +125,7 @@ pub fn polyvec_decompress(r: &mut Polyvec, a: &[u8])
idx += 5;
for k in 0..4 {
r.vec[i].coeffs[4*j+k] =
((((t[k] as u32) & 0x3FF) * KYBER_Q as u32 + 512) >> 10) as i16;
r.vec[i].coeffs[4 * j + k] = ((((t[k] as u32) & 0x3FF) * KYBER_Q as u32 + 512) >> 10) as i16;
}
}
}
@ -149,8 +138,7 @@ pub fn polyvec_decompress(r: &mut Polyvec, a: &[u8])
//
// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYVECBYTES)
// - const Polyvec a: input vector of polynomials
pub fn polyvec_tobytes(r: &mut[u8], a: &Polyvec)
{
pub fn polyvec_tobytes(r: &mut [u8], a: &Polyvec) {
for i in 0..KYBER_K {
poly_tobytes(&mut r[i * KYBER_POLYBYTES..], a.vec[i]);
}
@ -163,8 +151,7 @@ pub fn polyvec_tobytes(r: &mut[u8], a: &Polyvec)
//
// Arguments: - [u8] r: output byte array
// - const Polyvec a: input vector of polynomials (of length KYBER_POLYVECBYTES)
pub fn polyvec_frombytes(r: &mut Polyvec, a: &[u8])
{
pub fn polyvec_frombytes(r: &mut Polyvec, a: &[u8]) {
for i in 0..KYBER_K {
poly_frombytes(&mut r.vec[i], &a[i * KYBER_POLYBYTES..]);
}
@ -175,8 +162,7 @@ pub fn polyvec_frombytes(r: &mut Polyvec, a: &[u8])
// Description: Apply forward NTT to all elements of a vector of polynomials
//
// Arguments: - Polyvec r: in/output vector of polynomials
pub fn polyvec_ntt(r: &mut Polyvec)
{
pub fn polyvec_ntt(r: &mut Polyvec) {
for i in 0..KYBER_K {
poly_ntt(&mut r.vec[i]);
}
@ -187,8 +173,7 @@ pub fn polyvec_ntt(r: &mut Polyvec)
// Description: Apply inverse NTT to all elements of a vector of polynomials
//
// Arguments: - Polyvec r: in/output vector of polynomials
pub fn polyvec_invntt_tomont(r: &mut Polyvec)
{
pub fn polyvec_invntt_tomont(r: &mut Polyvec) {
for i in 0..KYBER_K {
poly_invntt_tomont(&mut r.vec[i]);
}
@ -201,8 +186,7 @@ pub fn polyvec_invntt_tomont(r: &mut Polyvec)
// Arguments: - poly *r: output polynomial
// - const Polyvec a: first input vector of polynomials
// - const Polyvec b: second input vector of polynomials
pub fn polyvec_basemul_acc_montgomery(r: &mut Poly, a: &Polyvec, b: &Polyvec)
{
pub fn polyvec_basemul_acc_montgomery(r: &mut Poly, a: &Polyvec, b: &Polyvec) {
let mut t = Poly::new();
poly_basemul(r, &a.vec[0], &b.vec[0]);
for i in 1..KYBER_K {
@ -219,22 +203,19 @@ pub fn polyvec_basemul_acc_montgomery(r: &mut Poly, a: &Polyvec, b: &Polyvec)
// for details of the Barrett reduction see comments in reduce.c
//
// Arguments: - poly *r: input/output polynomial
pub fn polyvec_reduce(r: &mut Polyvec)
{
pub fn polyvec_reduce(r: &mut Polyvec) {
for i in 0..KYBER_K {
poly_reduce(&mut r.vec[i]);
}
}
// Name: polyvec_add
//
// Description: Add vectors of polynomials
//
// Arguments: - Polyvec r: output vector of polynomials
// - const Polyvec b: second input vector of polynomials
pub fn polyvec_add(r: &mut Polyvec, b: &Polyvec)
{
pub fn polyvec_add(r: &mut Polyvec, b: &Polyvec) {
for i in 0..KYBER_K {
poly_add(&mut r.vec[i], &b.vec[i]);
}

View file

@ -11,8 +11,7 @@ const QINV: i32 = 62209; // q^(-1) mod 2^16
// Arguments: - i32 a: input integer to be reduced; has to be in {-q2^15,...,q2^15-1}
//
// Returns: integer in {-q+1,...,q-1} congruent to a * R^-1 modulo q.
pub fn montgomery_reduce(a: i32) -> i16
{
pub fn montgomery_reduce(a: i32) -> i16 {
let ua = a.wrapping_mul(QINV) as i16;
let u = ua as i32;
let mut t = u * KYBER_Q as i32;
@ -29,13 +28,10 @@ pub fn montgomery_reduce(a: i32) -> i16
// Arguments: - i16 a: input integer to be reduced
//
// Returns: i16 in {-(q-1)/2,...,(q-1)/2} congruent to a modulo q.
pub fn barrett_reduce(a: i16) -> i16
{
pub fn barrett_reduce(a: i16) -> i16 {
let v = ((1u32 << 26) / KYBER_Q as u32 + 1) as i32;
let mut t = v * a as i32 + (1 << 25);
t >>= 26;
t *= KYBER_Q as i32;
a - t as i16
}

View file

@ -7,8 +7,7 @@
// size_t len: length of the byte arrays
//
// Returns 0 if the byte arrays are equal, 1 otherwise
pub fn verify(a: &[u8], b: &[u8], len: usize) -> u8
{
pub fn verify(a: &[u8], b: &[u8], len: usize) -> u8 {
let mut r = 0u64;
for i in 0..len {
r |= (a[i] ^ b[i]) as u64;
@ -28,8 +27,7 @@ pub fn verify(a: &[u8], b: &[u8], len: usize) -> u8
// const [u8] x: input byte array
// size_t len: Amount of bytes to be copied
// [u8] b: Condition bit; has to be in {0,1}
pub fn cmov(r: &mut[u8], x: &[u8], len: usize, mut b: u8)
{
pub fn cmov(r: &mut [u8], x: &[u8], len: usize, mut b: u8) {
b = b.wrapping_neg();
for i in 0..len {
r[i] ^= b & (x[i] ^ r[i]);

View file

@ -4,7 +4,8 @@ use rand_core::*;
// Fills buffer x with len bytes, RNG must satisfy the
// RngCore trait and CryptoRng marker trait requirements
pub fn randombytes<R>(x: &mut [u8], len: usize, rng: &mut R)
where R: RngCore + CryptoRng,
where
R: RngCore + CryptoRng,
{
rng.fill_bytes(&mut x[..len]);
}

View file

@ -1,8 +1,11 @@
#![allow(dead_code)]
#[cfg(not(feature = "90s"))] use crate::{fips202::*, params::*};
#[cfg(feature = "90s")] use crate::aes256ctr::*;
#[cfg(feature = "90s")] use sha2::{Sha256, Sha512, Digest};
#[cfg(feature = "90s")]
use crate::aes256ctr::*;
#[cfg(not(feature = "90s"))]
use crate::{fips202::*, params::*};
#[cfg(feature = "90s")]
use sha2::{Digest, Sha256, Sha512};
// TODO: Rustrypto AES-CTR feature
// #[cfg(feature = "90s")] use aes_ctr::Aes256Ctr;
// #[cfg(feature = "90s")] use aes_ctr::cipher::{
@ -27,15 +30,12 @@ pub(crate) type XofState = Aes256CtrCtx;
#[derive(Copy, Clone)]
pub(crate) struct KeccakState {
pub s: [u64; 25],
pub pos: usize
pub pos: usize,
}
impl KeccakState {
pub fn new() -> Self {
KeccakState {
s: [0u64; 25],
pos: 0usize
}
KeccakState { s: [0u64; 25], pos: 0usize }
}
pub fn reset(&mut self) {
@ -46,15 +46,13 @@ impl KeccakState {
// SHA3-256
#[cfg(not(feature = "90s"))]
pub(crate) fn hash_h(out: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn hash_h(out: &mut [u8], input: &[u8], inlen: usize) {
sha3_256(out, input, inlen);
}
// 90s mode SHA2-256
#[cfg(feature = "90s")]
pub(crate) fn hash_h(out: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn hash_h(out: &mut [u8], input: &[u8], inlen: usize) {
let mut hasher = Sha256::new();
hasher.update(&input[..inlen]);
let digest = hasher.finalize();
@ -62,14 +60,12 @@ pub(crate) fn hash_h(out: &mut[u8], input: &[u8], inlen: usize)
}
#[cfg(not(feature = "90s"))]
pub(crate) fn hash_g(out: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn hash_g(out: &mut [u8], input: &[u8], inlen: usize) {
sha3_512(out, input, inlen);
}
#[cfg(feature = "90s")]
pub(crate) fn hash_g(out: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn hash_g(out: &mut [u8], input: &[u8], inlen: usize) {
let mut hasher = Sha512::new();
hasher.update(&input[..inlen]);
let digest = hasher.finalize();
@ -77,14 +73,12 @@ pub(crate) fn hash_g(out: &mut[u8], input: &[u8], inlen: usize)
}
#[cfg(not(feature = "90s"))]
pub(crate) fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8)
{
pub(crate) fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8) {
kyber_shake128_absorb(state, &input, x, y);
}
#[cfg(feature = "90s")]
pub(crate) fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8)
{
pub(crate) fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8) {
let mut nonce = [0u8; 12];
nonce[0] = x;
nonce[1] = y;
@ -92,26 +86,22 @@ pub(crate) fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8)
}
#[cfg(not(feature = "90s"))]
pub(crate) fn xof_squeezeblocks(out: &mut[u8], outblocks: usize, state: &mut XofState)
{
pub(crate) fn xof_squeezeblocks(out: &mut [u8], outblocks: usize, state: &mut XofState) {
kyber_shake128_squeezeblocks(out, outblocks, state);
}
#[cfg(feature = "90s")]
pub(crate) fn xof_squeezeblocks(out: &mut[u8], outblocks: usize, state: &mut XofState)
{
pub(crate) fn xof_squeezeblocks(out: &mut [u8], outblocks: usize, state: &mut XofState) {
aes256ctr_squeezeblocks(out, outblocks, state);
}
#[cfg(not(feature = "90s"))]
pub(crate) fn prf(out: &mut[u8], outbytes: usize, key: &[u8], nonce: u8)
{
pub(crate) fn prf(out: &mut [u8], outbytes: usize, key: &[u8], nonce: u8) {
shake256_prf(out, outbytes, &key, nonce);
}
#[cfg(feature = "90s")]
pub(crate) fn prf(out: &mut[u8], outbytes: usize, key: &[u8], nonce: u8)
{
pub(crate) fn prf(out: &mut [u8], outbytes: usize, key: &[u8], nonce: u8) {
aes256ctr_prf(out, outbytes, &key, nonce);
// TODO: Add feature to use RustCrypto AES_CTR
@ -130,14 +120,12 @@ pub(crate) fn prf(out: &mut[u8], outbytes: usize, key: &[u8], nonce: u8)
}
#[cfg(not(feature = "90s"))]
pub(crate) fn kdf(out: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn kdf(out: &mut [u8], input: &[u8], inlen: usize) {
shake256(out, KYBER_SSBYTES, input, inlen);
}
#[cfg(feature = "90s")]
pub(crate) fn kdf(out: &mut[u8], input: &[u8], inlen: usize)
{
pub(crate) fn kdf(out: &mut [u8], input: &[u8], inlen: usize) {
let mut hasher = Sha256::new();
hasher.update(&input[..inlen]);
let digest = hasher.finalize();
@ -153,13 +141,7 @@ pub(crate) fn kdf(out: &mut[u8], input: &[u8], inlen: usize)
// - u8 x additional byte of input
// - u8 y additional byte of input
#[cfg(not(feature = "90s"))]
fn kyber_shake128_absorb(
s: &mut KeccakState,
input: &[u8],
x: u8,
y: u8
)
{
fn kyber_shake128_absorb(s: &mut KeccakState, input: &[u8], x: u8, y: u8) {
let mut extseed = [0u8; KYBER_SYMBYTES + 2];
extseed[..KYBER_SYMBYTES].copy_from_slice(input);
extseed[KYBER_SYMBYTES] = x;
@ -177,12 +159,7 @@ fn kyber_shake128_absorb(
// - u64 nblocks: number of blocks to be squeezed (written to output)
// - keccak_state *s: in/output Keccak state
#[cfg(not(feature = "90s"))]
fn kyber_shake128_squeezeblocks(
output: &mut[u8],
nblocks: usize,
s: &mut KeccakState
)
{
fn kyber_shake128_squeezeblocks(output: &mut [u8], nblocks: usize, s: &mut KeccakState) {
shake128_squeezeblocks(output, nblocks, s);
}
@ -196,8 +173,7 @@ fn kyber_shake128_squeezeblocks(
// - const [u8] key: the key (of length KYBER_SYMBYTES)
// - const [u8] nonce: single-byte nonce (public PRF input)
#[cfg(not(feature = "90s"))]
fn shake256_prf(output: &mut[u8], outlen: usize, key: &[u8], nonce: u8)
{
fn shake256_prf(output: &mut [u8], outlen: usize, key: &[u8], nonce: u8) {
let mut extkey = [0u8; KYBER_SYMBYTES + 1];
extkey[..KYBER_SYMBYTES].copy_from_slice(key);
extkey[KYBER_SYMBYTES] = nonce;

View file

@ -16,7 +16,7 @@ pub fn keypair() -> Keys {
#[wasm_bindgen]
pub fn encapsulate(pk: Box<[u8]>) -> Result<Keys, JsValue> {
if pk.len() != KYBER_PUBLICKEYBYTES {
return Err(JsValue::null())
return Err(JsValue::null());
}
let mut ct = [0u8; KYBER_CIPHERTEXTBYTES];
let mut ss = [0u8; KYBER_SSBYTES];
@ -33,7 +33,7 @@ pub fn decapsulate(ct: Box<[u8]>, sk: Box<[u8]>) -> Result<Keys, JsValue> {
let mut ss = [0u8; KYBER_SSBYTES];
match kem::crypto_kem_dec(&mut ss, &ct, &sk) {
Ok(_) => Ok(Keys { shared_secret: Box::new(ss), ..Default::default() }),
Err(_) => Err(JsValue::null())
Err(_) => Err(JsValue::null()),
}
}

View file

@ -2,8 +2,8 @@
mod load;
use pqc_kyber::*;
use load::*;
use pqc_kyber::*;
// Generate KAT keypairs from seeds.
#[test]
@ -24,7 +24,6 @@ fn keypairs() {
}
}
// Encapsulating KAT's using deterministic rand buffers
#[test]
fn encaps() {

View file

@ -9,4 +9,3 @@ fn keypair_encap_decap_kem() {
let ss2 = decapsulate(&ct, &keys.secret).unwrap();
assert_eq!(ss1, ss2);
}

View file

@ -22,7 +22,9 @@ fn kyber_ake() {
let alice_keys = keypair(&mut rng);
let bob_keys = keypair(&mut rng);
let client_init = alice.client_init(&bob_keys.public, &mut rng);
let server_send = bob.server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng).unwrap();
let server_send = bob
.server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng)
.unwrap();
let _client_confirm = alice.client_confirm(server_send, &alice_keys.secret).unwrap();
assert_eq!(alice.shared_secret, bob.shared_secret);
}

View file

@ -1,7 +1,7 @@
use pqc_kyber::{KYBER_90S, KYBER_K};
use std::fs::File;
use std::path::PathBuf;
use std::io::{prelude::*, BufReader};
use pqc_kyber::{KYBER_K, KYBER_90S};
use std::path::PathBuf;
// Known Answer Tests
#[derive(Debug)]
@ -14,24 +14,23 @@ pub struct Kat {
pub pk: String,
pub sk: String,
pub ct: String,
pub ss: String
pub ss: String,
}
// Converts string octuples from tvec files into Kat structs
impl From<&[String]> for Kat {
fn from(kat: &[String]) -> Self {
// Extract values from key:value lines
let values: Vec<String> = kat.iter()
.map(
|katline| {
let values: Vec<String> = kat
.iter()
.map(|katline| {
let val: Vec<&str> = katline.split(": ").collect();
if val.len() > 1 {
val[1].into()
} else {
val[0].into()
}
}
)
})
.collect();
// Build KAT from values
Kat {
@ -52,7 +51,7 @@ fn get_filename() -> String {
2 => "tvecs512".to_string(),
3 => "tvecs768".to_string(),
4 => "tvecs1024".to_string(),
_ => panic!("No security level set")
_ => panic!("No security level set"),
};
if KYBER_90S {
filename.push_str("-90s");
@ -83,9 +82,7 @@ fn load_file(filepath: PathBuf) -> File {
fn parse_kats() -> Vec<String> {
let file = load_file(get_kat_filepath());
let buf = BufReader::new(file);
buf.lines()
.map(|l| l.expect("Unable to parse line"))
.collect()
buf.lines().map(|l| l.expect("Unable to parse line")).collect()
}
// Packs chunks of lines into Kat structs
@ -93,8 +90,5 @@ pub fn build_kats() -> Vec<Kat> {
let lines = parse_kats();
let kats = lines.chunks_exact(8);
// Map String slices into Vec<KAT>
kats.map(
|c| {c.into()}
)
.collect::<Vec<Kat>>()
kats.map(|c| c.into()).collect::<Vec<Kat>>()
}

View file

@ -47,7 +47,11 @@ impl<T, const C: usize> GatherArray<T, C> {
if (self.have_count as usize) == goal {
debug_assert_eq!(0xffffffffffffffffu64.wrapping_shr(64 - goal as u32), have);
let mut tmp = ArrayVec::new();
copy_nonoverlapping(self.a.as_ptr().cast::<u8>(), tmp.a.as_mut_ptr().cast::<u8>(), size_of::<MaybeUninit<T>>() * goal);
copy_nonoverlapping(
self.a.as_ptr().cast::<u8>(),
tmp.a.as_mut_ptr().cast::<u8>(),
size_of::<MaybeUninit<T>>() * goal,
);
tmp.s = goal;
self.goal = 0;
return Some(tmp);

View file

@ -1,6 +1,8 @@
// (c) 2020-2022 ZeroTier, Inc. -- currently propritery pending actual release and licensing. See LICENSE.md.
pub const HEX_CHARS: [u8; 16] = [b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f'];
pub const HEX_CHARS: [u8; 16] = [
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f',
];
/// Encode a byte slice to a hexadecimal string.
pub fn to_string(b: &[u8]) -> String {

View file

@ -43,7 +43,10 @@ impl<O: Send, F: PoolFactory<O>> Pooled<O, F> {
#[inline(always)]
pub unsafe fn into_raw(self) -> *mut O {
// Verify that the structure is not padded before 'obj'.
assert_eq!((&self.0.as_ref().obj as *const O).cast::<u8>(), (self.0.as_ref() as *const PoolEntry<O, F>).cast::<u8>());
assert_eq!(
(&self.0.as_ref().obj as *const O).cast::<u8>(),
(self.0.as_ref() as *const PoolEntry<O, F>).cast::<u8>()
);
let ptr = self.0.as_ptr().cast::<O>();
std::mem::forget(self);