Skip to content

Commit 0ab7b70

Browse files
Add get_single_block to chacha20 module
In the next commit, we'll want to get a single block from a chacha stream that takes a 16-byte nonce.
1 parent 10ceda5 commit 0ab7b70

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

lightning/src/util/chacha20.rs

+59
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,17 @@ mod real_chacha {
151151
ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
152152
}
153153

154+
/// Get one block from a ChaCha stream. Panics if `key`'s len is not 32 bytes or `nonce`'s len
155+
/// is not 16 bytes.
156+
pub fn get_single_block(key: &[u8], nonce: &[u8]) -> [u8; 32] {
157+
assert!(key.len() == 32);
158+
assert!(nonce.len() == 16);
159+
let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
160+
let mut chacha_bytes = [0; 32];
161+
chacha.process_in_place(&mut chacha_bytes);
162+
chacha_bytes
163+
}
164+
154165
fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
155166
let constant = match key.len() {
156167
16 => b"expand 16-byte k",
@@ -256,6 +267,16 @@ mod real_chacha {
256267
self.offset += count;
257268
}
258269
}
270+
271+
#[cfg(test)]
272+
pub fn seek(&mut self, block_offset: u32, offset_in_block: usize) -> Result<(), ()> {
273+
let u32x4(_, d2, d3, d4) = self.state.d;
274+
self.state.d = u32x4(block_offset, d2, d3, d4);
275+
self.update();
276+
self.offset = offset_in_block;
277+
278+
Ok(())
279+
}
259280
}
260281
}
261282
#[cfg(not(feature = "fuzztarget"))]
@@ -272,6 +293,12 @@ mod fuzzy_chacha {
272293
Self {}
273294
}
274295

296+
pub fn get_single_block(key: &[u8], nonce: &[u8]) -> [u8; 32] {
297+
assert!(key.len() == 32);
298+
assert!(nonce.len() == 16);
299+
[0; 32]
300+
}
301+
275302
pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
276303
output.copy_from_slice(input);
277304
}
@@ -302,6 +329,7 @@ mod test {
302329
use core::iter::repeat;
303330

304331
use super::ChaCha20;
332+
use std::convert::TryInto;
305333

306334
#[test]
307335
fn test_chacha20_256_tls_vectors() {
@@ -572,4 +600,35 @@ mod test {
572600
assert_eq!(output, tv.keystream);
573601
}
574602
}
603+
604+
#[test]
605+
fn get_single_block() {
606+
// Test that `get_single_block` is equivalent to getting a block from a 12-byte nonce from the
607+
// counter offset given by the remaining 4 bytes.
608+
let key = [
609+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
610+
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
611+
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
612+
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
613+
];
614+
let nonce_12bytes = [
615+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
616+
0x08, 0x09, 0x0a, 0x0b
617+
];
618+
let counter_pos = [0x00, 0x01, 0x02, 0x03];
619+
let nonce_16bytes = [ // nonce_12bytes prefixed by counter_pos
620+
0x00, 0x01, 0x02, 0x03,
621+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
622+
0x08, 0x09, 0x0a, 0x0b
623+
];
624+
625+
// Initialize a ChaCha20 instance with its counter starting at 0.
626+
let mut chacha20 = ChaCha20::new(&key, &nonce_12bytes);
627+
// Seek its counter to counter_pos.
628+
chacha20.seek(u32::from_le_bytes(counter_pos).try_into().unwrap(), 0).unwrap();
629+
let mut block_bytes = [0; 32];
630+
chacha20.process_in_place(&mut block_bytes);
631+
632+
assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
633+
}
575634
}

0 commit comments

Comments
 (0)