Skip to content

Commit aa2f94e

Browse files
committed
migrate ascon-xof128
1 parent bcd6ad0 commit aa2f94e

8 files changed

Lines changed: 83 additions & 83 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ascon-xof128/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,18 @@ categories = ["cryptography", "no-std"]
1313
description = "Implementation of Ascon-XOF128 and Ascon-СXOF128"
1414

1515
[dependencies]
16-
digest = "0.11"
16+
digest = { version = "0.11", default-features = false }
1717
ascon = "0.5"
18+
sponge-cursor = "0.1"
1819

1920
[dev-dependencies]
20-
digest = { version = "0.11", features = ["dev"] }
21+
digest = { version = "0.11", default-features = false, features = ["dev"] }
2122
hex-literal = "1"
2223

2324
[features]
2425
default = ["alloc"]
2526
alloc = ["digest/alloc"]
26-
zeroize = ["digest/zeroize"]
27+
zeroize = ["digest/zeroize", "sponge-cursor/zeroize"]
2728

2829
[package.metadata.docs.rs]
2930
all-features = true

ascon-xof128/src/cxof.rs

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use ascon::State;
22
use digest::{
33
CollisionResistance, CustomizedInit, ExtendableOutput, HashMarker, OutputSizeUser, Update,
4-
block_api::AlgorithmName,
5-
block_buffer::EagerBuffer,
4+
common::AlgorithmName,
65
common::hazmat::{DeserializeStateError, SerializableState, SerializedState},
7-
consts::{U8, U16, U32, U48},
6+
consts::{U8, U16, U32, U41},
87
};
8+
use sponge_cursor::SpongeCursor;
99

1010
use crate::{AsconXof128Reader, consts::CXOF_INIT_STATE};
1111

@@ -20,7 +20,7 @@ use crate::{AsconXof128Reader, consts::CXOF_INIT_STATE};
2020
#[derive(Clone, Debug)]
2121
pub struct AsconCxof128 {
2222
state: State,
23-
buffer: EagerBuffer<U8>,
23+
cursor: SpongeCursor<U8>,
2424
}
2525

2626
impl CustomizedInit for AsconCxof128 {
@@ -52,8 +52,8 @@ impl CustomizedInit for AsconCxof128 {
5252

5353
ascon::permute12(&mut state);
5454

55-
let buffer = Default::default();
56-
Self { state, buffer }
55+
let cursor = Default::default();
56+
Self { state, cursor }
5757
}
5858
}
5959

@@ -71,26 +71,18 @@ impl CollisionResistance for AsconCxof128 {
7171
impl Update for AsconCxof128 {
7272
#[inline]
7373
fn update(&mut self, data: &[u8]) {
74-
self.buffer.digest_blocks(data, |blocks| {
75-
for block in blocks {
76-
self.state[0] ^= u64::from_le_bytes(block.0);
77-
ascon::permute12(&mut self.state);
78-
}
79-
});
74+
self.cursor
75+
.absorb_u64_le(&mut self.state, ascon::permute12, data);
8076
}
8177
}
8278

8379
impl ExtendableOutput for AsconCxof128 {
8480
type Reader = AsconXof128Reader;
8581

8682
fn finalize_xof(mut self) -> Self::Reader {
87-
let Self { state, buffer } = &mut self;
88-
let len = buffer.get_pos();
89-
let last_block = buffer.pad_with_zeros();
90-
let pad = 1u64 << (8 * len);
91-
state[0] ^= u64::from_le_bytes(last_block.0) ^ pad;
92-
93-
AsconXof128Reader::new(state)
83+
let pos = self.cursor.pos();
84+
self.state[0] ^= 1u64 << (8 * pos);
85+
AsconXof128Reader::new(&self.state)
9486
}
9587
}
9688

@@ -102,37 +94,36 @@ impl AlgorithmName for AsconCxof128 {
10294
}
10395

10496
impl SerializableState for AsconCxof128 {
105-
type SerializedStateSize = U48;
97+
type SerializedStateSize = U41;
10698

10799
#[inline]
108100
fn serialize(&self) -> SerializedState<Self> {
109101
let mut res = SerializedState::<Self>::default();
110-
let (state_dst, buffer_dst) = res.split_at_mut(size_of::<State>());
102+
let (state_dst, cursor_dst) = res.split_at_mut(size_of::<State>());
111103
let mut chunks = state_dst.chunks_exact_mut(size_of::<u64>());
112104
for (src, dst) in self.state.iter().zip(&mut chunks) {
113105
dst.copy_from_slice(&src.to_le_bytes());
114106
}
115107
assert!(chunks.into_remainder().is_empty());
116-
buffer_dst.copy_from_slice(&self.buffer.serialize());
108+
assert_eq!(cursor_dst.len(), 1);
109+
cursor_dst[0] = self.cursor.raw_pos();
117110
res
118111
}
119112

120113
#[inline]
121114
fn deserialize(
122115
serialized_state: &SerializedState<Self>,
123116
) -> Result<Self, DeserializeStateError> {
124-
let (state_src, buffer_src) = serialized_state.split_at(size_of::<State>());
117+
let (state_src, cursor_src) = serialized_state.split_at(size_of::<State>());
125118
let state = core::array::from_fn(|i| {
126119
let n = size_of::<u64>();
127120
let chunk = &state_src[n * i..][..n];
128121
u64::from_le_bytes(chunk.try_into().expect("chunk has correct length"))
129122
});
130-
let buffer_src = buffer_src
131-
.try_into()
132-
.expect("buffer_src has correct length");
133-
EagerBuffer::deserialize(buffer_src)
134-
.map_err(|_| DeserializeStateError)
135-
.map(|buffer| Self { state, buffer })
123+
assert_eq!(cursor_src.len(), 1);
124+
SpongeCursor::new(cursor_src[0])
125+
.ok_or(DeserializeStateError)
126+
.map(|cursor| Self { state, cursor })
136127
}
137128
}
138129

@@ -141,10 +132,9 @@ impl Drop for AsconCxof128 {
141132
fn drop(&mut self) {
142133
#[cfg(feature = "zeroize")]
143134
{
144-
use digest::zeroize::{Zeroize, ZeroizeOnDrop};
145-
fn assert_zeroize_on_drop<T: ZeroizeOnDrop>(_: &mut T) {}
135+
use digest::zeroize::Zeroize;
146136
self.state.zeroize();
147-
assert_zeroize_on_drop(&mut self.buffer);
137+
self.cursor.zeroize();
148138
}
149139
}
150140
}

ascon-xof128/src/reader.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,42 @@
11
use ascon::State;
2-
use digest::{XofReader, block_buffer::ReadBuffer, consts::U8};
2+
use digest::{XofReader, consts::U8};
3+
use sponge_cursor::SpongeCursor;
34

45
/// XOF reader used by Ascon-XOF128 and Ascon-CXOF128
56
#[derive(Clone, Debug)]
67
pub struct AsconXof128Reader {
78
state: State,
8-
buffer: ReadBuffer<U8>,
9+
cursor: SpongeCursor<U8>,
910
}
1011

1112
impl AsconXof128Reader {
1213
pub(super) fn new(state: &State) -> Self {
1314
Self {
1415
state: *state,
15-
buffer: Default::default(),
16+
cursor: Default::default(),
1617
}
1718
}
1819
}
1920

2021
impl XofReader for AsconXof128Reader {
22+
#[inline]
2123
fn read(&mut self, buf: &mut [u8]) {
22-
self.buffer.read(buf, |dst| {
23-
ascon::permute12(&mut self.state);
24-
*dst = self.state[0].to_le_bytes().into();
25-
});
24+
self.cursor
25+
.squeeze_u64_le(&mut self.state, ascon::permute12, buf);
2626
}
2727
}
28+
29+
impl Drop for AsconXof128Reader {
30+
#[inline]
31+
fn drop(&mut self) {
32+
#[cfg(feature = "zeroize")]
33+
{
34+
use digest::zeroize::Zeroize;
35+
self.state.zeroize();
36+
self.cursor.zeroize();
37+
}
38+
}
39+
}
40+
41+
#[cfg(feature = "zeroize")]
42+
impl digest::zeroize::ZeroizeOnDrop for AsconXof128Reader {}

ascon-xof128/src/xof.rs

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@ use core::fmt;
33
use digest::{
44
CollisionResistance, ExtendableOutput, ExtendableOutputReset, HashMarker, OutputSizeUser,
55
Reset, Update,
6-
block_api::AlgorithmName,
7-
block_buffer::EagerBuffer,
6+
common::AlgorithmName,
87
common::hazmat::{DeserializeStateError, SerializableState, SerializedState},
9-
consts::{U8, U16, U32, U48},
8+
consts::{U8, U16, U32, U41},
109
};
10+
use sponge_cursor::SpongeCursor;
1111

1212
use crate::{AsconXof128Reader, consts::XOF_INIT_STATE};
1313

1414
/// Ascon-XOF128 hasher.
1515
#[derive(Clone)]
1616
pub struct AsconXof128 {
1717
state: State,
18-
buffer: EagerBuffer<U8>,
18+
cursor: SpongeCursor<U8>,
1919
}
2020

2121
impl Default for AsconXof128 {
2222
#[inline]
2323
fn default() -> Self {
2424
Self {
2525
state: XOF_INIT_STATE,
26-
buffer: Default::default(),
26+
cursor: Default::default(),
2727
}
2828
}
2929
}
@@ -42,38 +42,31 @@ impl CollisionResistance for AsconXof128 {
4242
impl Update for AsconXof128 {
4343
#[inline]
4444
fn update(&mut self, data: &[u8]) {
45-
self.buffer.digest_blocks(data, |blocks| {
46-
for block in blocks {
47-
self.state[0] ^= u64::from_le_bytes(block.0);
48-
ascon::permute12(&mut self.state);
49-
}
50-
});
45+
self.cursor
46+
.absorb_u64_le(&mut self.state, ascon::permute12, data);
5147
}
5248
}
5349

5450
impl AsconXof128 {
55-
fn finalize_xof_dirty(&mut self) -> AsconXof128Reader {
56-
let Self { state, buffer } = self;
57-
let len = buffer.get_pos();
58-
let last_block = buffer.pad_with_zeros();
59-
let pad = 1u64 << (8 * len);
60-
state[0] ^= u64::from_le_bytes(last_block.0) ^ pad;
61-
62-
AsconXof128Reader::new(state)
51+
fn pad(&mut self) {
52+
let pos = self.cursor.pos();
53+
self.state[0] ^= 1u64 << (8 * pos);
6354
}
6455
}
6556

6657
impl ExtendableOutput for AsconXof128 {
6758
type Reader = AsconXof128Reader;
6859

6960
fn finalize_xof(mut self) -> Self::Reader {
70-
self.finalize_xof_dirty()
61+
self.pad();
62+
AsconXof128Reader::new(&self.state)
7163
}
7264
}
7365

7466
impl ExtendableOutputReset for AsconXof128 {
7567
fn finalize_xof_reset(&mut self) -> Self::Reader {
76-
let res = self.finalize_xof_dirty();
68+
self.pad();
69+
let res = AsconXof128Reader::new(&self.state);
7770
self.reset();
7871
res
7972
}
@@ -83,7 +76,7 @@ impl Reset for AsconXof128 {
8376
#[inline]
8477
fn reset(&mut self) {
8578
self.state = XOF_INIT_STATE;
86-
self.buffer.reset();
79+
self.cursor = Default::default();
8780
}
8881
}
8982

@@ -102,37 +95,36 @@ impl fmt::Debug for AsconXof128 {
10295
}
10396

10497
impl SerializableState for AsconXof128 {
105-
type SerializedStateSize = U48;
98+
type SerializedStateSize = U41;
10699

107100
#[inline]
108101
fn serialize(&self) -> SerializedState<Self> {
109102
let mut res = SerializedState::<Self>::default();
110-
let (state_dst, buffer_dst) = res.split_at_mut(size_of::<State>());
103+
let (state_dst, cursor_dst) = res.split_at_mut(size_of::<State>());
111104
let mut chunks = state_dst.chunks_exact_mut(size_of::<u64>());
112105
for (src, dst) in self.state.iter().zip(&mut chunks) {
113106
dst.copy_from_slice(&src.to_le_bytes());
114107
}
115108
assert!(chunks.into_remainder().is_empty());
116-
buffer_dst.copy_from_slice(&self.buffer.serialize());
109+
assert_eq!(cursor_dst.len(), 1);
110+
cursor_dst[0] = self.cursor.raw_pos();
117111
res
118112
}
119113

120114
#[inline]
121115
fn deserialize(
122116
serialized_state: &SerializedState<Self>,
123117
) -> Result<Self, DeserializeStateError> {
124-
let (state_src, buffer_src) = serialized_state.split_at(size_of::<State>());
118+
let (state_src, cursor_src) = serialized_state.split_at(size_of::<State>());
125119
let state = core::array::from_fn(|i| {
126120
let n = size_of::<u64>();
127121
let chunk = &state_src[n * i..][..n];
128122
u64::from_le_bytes(chunk.try_into().expect("chunk has correct length"))
129123
});
130-
let buffer_src = buffer_src
131-
.try_into()
132-
.expect("buffer_src has correct length");
133-
EagerBuffer::deserialize(buffer_src)
134-
.map_err(|_| DeserializeStateError)
135-
.map(|buffer| Self { state, buffer })
124+
assert_eq!(cursor_src.len(), 1);
125+
SpongeCursor::new(cursor_src[0])
126+
.ok_or(DeserializeStateError)
127+
.map(|cursor| Self { state, cursor })
136128
}
137129
}
138130

@@ -141,10 +133,9 @@ impl Drop for AsconXof128 {
141133
fn drop(&mut self) {
142134
#[cfg(feature = "zeroize")]
143135
{
144-
use digest::zeroize::{Zeroize, ZeroizeOnDrop};
145-
fn assert_zeroize_on_drop<T: ZeroizeOnDrop>(_: &mut T) {}
136+
use digest::zeroize::Zeroize;
146137
self.state.zeroize();
147-
assert_zeroize_on_drop(&mut self.buffer);
138+
self.cursor.zeroize();
148139
}
149140
}
150141
}
-7 Bytes
Binary file not shown.
-7 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)