.tangled/workflows/miri.yml
.tangled/workflows/miri.yml
This file has not been changed.
src/handshake.rs
src/handshake.rs
This file has not been changed.
src/lib.rs
src/lib.rs
This file has not been changed.
wharrgarbl-neko/SPEC.md
wharrgarbl-neko/SPEC.md
This file has not been changed.
+55
wharrgarbl-neko/src/kats.rs
+55
wharrgarbl-neko/src/kats.rs
···
267
267
assert_eq!(&neko.state, &ratched_expected_state);
268
268
// The rest of the non-zeroed state should not match the previous state
269
269
assert_ne!(&expected_state[2..], &ratched_expected_state[2..]);
270
+
271
+
let large_message = r#"Lorem ipsum dolor sit amet, consectetur adipiscing elit.
272
+
Ut augue lectus, rhoncus a pulvinar ut, lacinia non est.
273
+
Pellentesque imperdiet ornare blandit. Mauris dictum mollis blandit.
274
+
Ut a arcu tincidunt, ultricies arcu sed, auctor erat.
275
+
Nunc dignissim hendrerit porttitor. Nunc fermentum mi sed viverra euismod.
276
+
Cras vel diam tortor. Morbi scelerisque augue eget elit ultrices suscipit.
277
+
Nunc varius arcu sit amet neque faucibus, id iaculis ex porta.
278
+
Nullam non neque nec neque faucibus sollicitudin.
279
+
Phasellus eget ultrices purus. Aenean tincidunt nisl mi, vel tincidunt ante pretium eu.
280
+
In scelerisque, ex et porta varius, orci risus malesuada nibh, convallis euismod nibh ipsum non turpis."#;
281
+
282
+
let mut large_encrypted_message = large_message.as_bytes().to_vec();
283
+
284
+
neko.encrypt(&mut large_encrypted_message);
285
+
286
+
let expected_state = [
287
+
0x13412b65f7e20af3,
288
+
0x6d3424b086abd336,
289
+
0xcb9fc2f09e70d9a0,
290
+
0x88c998c81951d0c2,
291
+
0x059e869c2f7a61ce,
292
+
0xc3659823ee130ee2,
293
+
0xaa59c8ff1d95842f,
294
+
0x940740fc352b4fae,
295
+
0xdbd1854b5f012452,
296
+
0xe14d604523a7c4b1,
297
+
0x4a1a2305128b2afa,
298
+
0xec94592e37b13bd9,
299
+
0x2acce9aec73ec364,
300
+
0x73324f4034356ff2,
301
+
0x563ae980c6a2e903,
302
+
0xdf6491d84e9a29dc,
303
+
0xd86c5e19f7f243ca,
304
+
0x18e7a1523d271264,
305
+
0x41f808f2bb8d7c2c,
306
+
0xfeea3498ca40ba48,
307
+
0xb304f29eb1df2f33,
308
+
0xce55d8a83bba04a4,
309
+
0x452613733fbc50df,
310
+
0xe137b9f22560f2d0,
311
+
0xb12bb41da4aa156e,
312
+
];
313
+
314
+
assert_eq!(&neko.state, &expected_state);
315
+
assert_ne!(large_message.as_bytes(), &large_encrypted_message);
316
+
317
+
let tag = neko.create_mac();
318
+
319
+
let expected_tag: [u8; 16] = [
320
+
0x9b, 0x89, 0x06, 0xea, 0x70, 0xec, 0x90, 0xc1, 0x9e, 0x47, 0x62, 0xd7, 0x52, 0xcb, 0x0d,
321
+
0xaa,
322
+
];
323
+
324
+
assert_eq!(&tag, &expected_tag);
270
325
}
271
326
272
327
#[test]
+17
-10
wharrgarbl-neko/src/lib.rs
+17
-10
wharrgarbl-neko/src/lib.rs
···
80
80
/// ```
81
81
pub fn new(protocol: &[u8]) -> Self {
82
82
const {
83
-
assert!(Sec::RATE < keccak::PLEN);
84
-
assert!(Sec::RATE < u8::MAX as usize);
83
+
assert!(Sec::BLOCK_RATE < keccak::PLEN);
84
+
assert!(Sec::BLOCK_RATE < u8::MAX as usize);
85
85
};
86
86
87
87
// OPS stack MUST be initialised with the INIT flag as the first op.
···
100
100
101
101
// Preamble is defined with 0x01 as the first byte, the RATE as the second byte
102
102
// and then 0x07 & 0x60 as the third & fourth byte.
103
-
let preamble: Array<u8, U4> = Array::from([0x01, Sec::RATE as u8, 0x07, 0x60]);
103
+
let preamble: Array<u8, U4> = Array::from([0x01, Sec::BLOCK_RATE as u8, 0x07, 0x60]);
104
104
105
105
// This is safe because the specification version string is always 10 bytes long.
106
106
let version: Array<u8, U10> = Array::try_from(NEKO_VERSION.as_bytes()).unwrap();
···
123
123
#[must_use]
124
124
pub(crate) fn block(&self) -> usize {
125
125
let block = usize::from(self.raw_position()).div_ceil(U64_CHUNK);
126
-
debug_assert!(block <= Sec::RATE);
127
-
if block <= Sec::RATE {
126
+
debug_assert!(block <= Sec::BLOCK_RATE);
127
+
if block <= Sec::BLOCK_RATE {
128
128
block
129
129
} else {
130
130
// SAFETY: the type enforces that `block` is always smaller than `RATE`
···
135
135
#[inline(always)]
136
136
#[must_use]
137
137
fn raw_position(&self) -> u8 {
138
-
debug_assert!(self.position < u8::MAX as usize && self.position <= Sec::RATE * U64_CHUNK);
139
-
if self.position < u8::MAX as usize && self.position <= Sec::RATE * U64_CHUNK {
138
+
debug_assert!(self.position < u8::MAX as usize && self.position <= Sec::POS_RATE);
139
+
if self.position < u8::MAX as usize && self.position <= Sec::POS_RATE {
140
140
self.position as u8
141
141
} else {
142
142
// SAFETY: the type enforces that `position` is always smaller than
···
145
145
}
146
146
}
147
147
148
+
#[inline(always)]
149
+
pub(crate) fn advance_position(&mut self, advance: usize) {
150
+
let updated = self.position + advance;
151
+
assert!(updated <= Sec::POS_RATE);
152
+
self.position = updated;
153
+
}
154
+
148
155
#[inline]
149
156
#[track_caller]
150
157
fn begin_op(&mut self, red_flags: OpFlags) {
···
165
172
166
173
fn permutation_p12(&mut self, continuation: OpFlags) {
167
174
const {
168
-
assert!(Sec::RATE < keccak::PLEN);
169
-
assert!(Sec::RATE < u8::MAX as usize);
175
+
assert!(Sec::BLOCK_RATE < keccak::PLEN);
176
+
assert!(Sec::BLOCK_RATE < u8::MAX as usize);
170
177
};
171
178
172
179
// Last byte is zeroed in case the terminator overlaps
···
180
187
self.state[self.position.div_ceil(U64_CHUNK) + 1] ^= permuter_block;
181
188
// Flip a bit in the last byte of the first entropy block with a 1 to act as the padding terminator.
182
189
// The bit is selected via rotating right the value 0x80 (0b1000_0000) by the position counter.
183
-
self.state[Sec::RATE].as_mut_bytes()[7] ^=
190
+
self.state[Sec::BLOCK_RATE].as_mut_bytes()[7] ^=
184
191
0x80u8.to_le().rotate_right(self.position as u32);
185
192
186
193
// The state has been fully prepared, and now can be permuted by the p1600(12) function.
+9
-9
wharrgarbl-neko/src/operators.rs
+9
-9
wharrgarbl-neko/src/operators.rs
···
16
16
#[inline(always)]
17
17
fn operate_mut(&'s mut self, operation: fn((&mut u8, &mut u8))) {
18
18
const {
19
-
assert!(S::RATE < keccak::PLEN);
20
-
assert!(S::RATE < u8::MAX as usize);
19
+
assert!(S::BLOCK_RATE < keccak::PLEN);
20
+
assert!(S::BLOCK_RATE < u8::MAX as usize);
21
21
};
22
22
23
23
while !self.data.is_empty() {
24
24
let mut block = self.neko.block();
25
25
26
-
if block == S::RATE {
26
+
if block == S::BLOCK_RATE {
27
27
self.neko.permutation_p12(ops::CONT);
28
28
block = 0;
29
29
}
30
30
31
31
// Trans the neko
32
-
let transed_bytes = self.neko.state[block..S::RATE].as_mut_bytes();
32
+
let transed_bytes = self.neko.state[block..S::BLOCK_RATE].as_mut_bytes();
33
33
34
34
let advanced = transed_bytes
35
35
.iter_mut()
···
39
39
40
40
self.data = &mut self.data[advanced..];
41
41
42
-
self.neko.position += advanced;
42
+
self.neko.advance_position(advanced);
43
43
}
44
44
}
45
45
···
87
87
#[inline(always)]
88
88
fn operate(&'s mut self, operation: fn((&mut u8, &u8))) {
89
89
const {
90
-
assert!(S::RATE < keccak::PLEN);
91
-
assert!(S::RATE < u8::MAX as usize);
90
+
assert!(S::BLOCK_RATE < keccak::PLEN);
91
+
assert!(S::BLOCK_RATE < u8::MAX as usize);
92
92
};
93
93
94
94
while !self.data.is_empty() {
95
95
let mut block = self.neko.block();
96
96
97
-
if block == S::RATE {
97
+
if block == S::BLOCK_RATE {
98
98
self.neko.permutation_p12(ops::CONT);
99
99
block = 0;
100
100
}
101
101
102
102
// Trans the neko
103
-
let transed_bytes = self.neko.state[block..S::RATE].as_mut_bytes();
103
+
let transed_bytes = self.neko.state[block..S::BLOCK_RATE].as_mut_bytes();
104
104
105
105
let advanced = transed_bytes
106
106
.iter_mut()
+17
-15
wharrgarbl-neko/src/traits.rs
+17
-15
wharrgarbl-neko/src/traits.rs
···
1
1
use aead::consts::{U128, U192, U200, U256};
2
2
use hybrid_array::typenum::Unsigned;
3
3
4
+
use crate::U64_CHUNK;
5
+
4
6
pub trait NekoSec: Unsigned {
5
-
const RATE: usize;
7
+
const BLOCK_RATE: usize;
8
+
const POS_RATE: usize;
6
9
const RATCHET: usize;
7
10
const BYTES: [u8; 2];
8
11
}
9
12
10
-
impl NekoSec for U128 {
11
-
const RATE: usize = calc_rate(Self::USIZE);
12
-
const BYTES: [u8; 2] = Self::U16.to_le_bytes();
13
-
const RATCHET: usize = Self::USIZE.wrapping_shr(6);
14
-
}
15
-
impl NekoSec for U192 {
16
-
const RATE: usize = calc_rate(Self::USIZE);
17
-
const BYTES: [u8; 2] = Self::U16.to_le_bytes();
18
-
const RATCHET: usize = Self::USIZE.wrapping_shr(6);
19
-
}
20
-
impl NekoSec for U256 {
21
-
const RATE: usize = calc_rate(Self::USIZE);
22
-
const BYTES: [u8; 2] = Self::U16.to_le_bytes();
23
-
const RATCHET: usize = Self::USIZE.wrapping_shr(6);
13
+
macro_rules! impl_nekosec_for {
14
+
($($type:ident)+) => {
15
+
$(
16
+
impl NekoSec for $type {
17
+
const BLOCK_RATE: usize = calc_rate(Self::USIZE);
18
+
const POS_RATE: usize = Self::BLOCK_RATE * U64_CHUNK;
19
+
const BYTES: [u8; 2] = Self::U16.to_le_bytes();
20
+
const RATCHET: usize = Self::USIZE.wrapping_shr(6);
21
+
}
22
+
)*
23
+
};
24
24
}
25
25
26
+
impl_nekosec_for!(U128 U192 U256);
27
+
26
28
const fn calc_rate(sec: usize) -> usize {
27
29
let rate = (U200::USIZE - sec / 4) / 8 - 1;
28
30
assert!(rate < keccak::PLEN && rate < u8::MAX as usize);
History
7 rounds
0 comments
1 commit
expand
collapse
NEKO v0.2.1 spec, 192 bit mode, const type asserts
merge conflicts detected
expand
collapse
expand
collapse
- src/handshake.rs:36
- src/lib.rs:2
- wharrgarbl-neko/SPEC.md:1
- wharrgarbl-neko/src/kats.rs:1
- wharrgarbl-neko/src/lib.rs:1
- wharrgarbl-neko/src/operators.rs:1
- wharrgarbl-neko/src/traits.rs:1