Skip to content

Commit b74a220

Browse files
authored
Remove ChaChaXCore types (#512)
We don't need these types. The only known use is `rand::rngs::ThreadRng`, yet there's no reason that can't use `ChaChaCore` (already a public item).
1 parent 44a9c58 commit b74a220

File tree

2 files changed

+57
-94
lines changed

2 files changed

+57
-94
lines changed

chacha20/src/lib.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ pub use chacha::{ChaCha8, ChaCha12, ChaCha20, Key, KeyIvInit};
136136
#[cfg(feature = "rng")]
137137
pub use rand_core;
138138
#[cfg(feature = "rng")]
139-
pub use rng::{ChaCha8Core, ChaCha8Rng, ChaCha12Core, ChaCha12Rng, ChaCha20Core, ChaCha20Rng};
139+
pub use rng::{ChaCha8Rng, ChaCha12Rng, ChaCha20Rng};
140140

141141
#[cfg(feature = "legacy")]
142142
pub use legacy::{ChaCha20Legacy, LegacyNonce};
@@ -265,6 +265,18 @@ impl<R: Rounds, V: Variant> ChaChaCore<R, V> {
265265
_pd: PhantomData,
266266
}
267267
}
268+
269+
#[cfg(any(feature = "cipher", feature = "rng"))]
270+
#[inline(always)]
271+
fn get_block_pos(&self) -> V::Counter {
272+
V::get_block_pos(&self.state[12..])
273+
}
274+
275+
#[cfg(any(feature = "cipher", feature = "rng"))]
276+
#[inline(always)]
277+
fn set_block_pos(&mut self, pos: V::Counter) {
278+
V::set_block_pos(&mut self.state[12..], pos);
279+
}
268280
}
269281

270282
#[cfg(feature = "cipher")]
@@ -273,12 +285,12 @@ impl<R: Rounds, V: Variant> StreamCipherSeekCore for ChaChaCore<R, V> {
273285

274286
#[inline(always)]
275287
fn get_block_pos(&self) -> Self::Counter {
276-
V::get_block_pos(&self.state[12..])
288+
self.get_block_pos()
277289
}
278290

279291
#[inline(always)]
280292
fn set_block_pos(&mut self, pos: Self::Counter) {
281-
V::set_block_pos(&mut self.state[12..], pos);
293+
self.set_block_pos(pos)
282294
}
283295
}
284296

chacha20/src/rng.rs

Lines changed: 42 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use core::{convert::Infallible, fmt::Debug};
1010

1111
use rand_core::{
1212
SeedableRng, TryCryptoRng, TryRng,
13-
block::{BlockRng, CryptoGenerator, Generator},
13+
block::{BlockRng, Generator},
1414
};
1515

1616
#[cfg(feature = "zeroize")]
@@ -77,33 +77,32 @@ impl Debug for Seed {
7777
}
7878
}
7979

80-
/// A wrapper around 64 bits of data that can be constructed from any of the
81-
/// following:
80+
/// A wrapper for `stream_id` (64-bits).
81+
///
82+
/// Can be constructed from any of the following:
8283
/// * `u64`
8384
/// * `[u32; 2]`
8485
/// * `[u8; 8]`
8586
///
86-
/// The arrays should be in little endian order. You should not need to use
87-
/// this directly, as the methods in this crate that use this type call
88-
/// `.into()` for you, so you only need to supply any of the above types.
89-
pub struct U32x2([u32; Self::LEN]);
87+
/// The arrays should be in little endian order.
88+
pub struct StreamId([u32; Self::LEN]);
9089

91-
impl U32x2 {
92-
/// Amount of raw bytes backing a `U32x2` instance.
90+
impl StreamId {
91+
/// Amount of raw bytes backing a `StreamId` instance.
9392
const BYTES: usize = size_of::<Self>();
9493

95-
/// The length of the array contained within `U32x2`.
94+
/// The length of the array contained within `StreamId`.
9695
const LEN: usize = 2;
9796
}
9897

99-
impl From<[u32; Self::LEN]> for U32x2 {
98+
impl From<[u32; Self::LEN]> for StreamId {
10099
#[inline]
101100
fn from(value: [u32; Self::LEN]) -> Self {
102101
Self(value)
103102
}
104103
}
105104

106-
impl From<[u8; Self::BYTES]> for U32x2 {
105+
impl From<[u8; Self::BYTES]> for StreamId {
107106
#[inline]
108107
fn from(value: [u8; Self::BYTES]) -> Self {
109108
let mut result = Self(Default::default());
@@ -118,34 +117,14 @@ impl From<[u8; Self::BYTES]> for U32x2 {
118117
}
119118
}
120119

121-
impl From<u64> for U32x2 {
120+
impl From<u64> for StreamId {
122121
#[inline]
123122
fn from(value: u64) -> Self {
124123
let result: [u8; Self::BYTES] = value.to_le_bytes()[..Self::BYTES].try_into().unwrap();
125124
result.into()
126125
}
127126
}
128127

129-
/// A wrapper for `stream_id`.
130-
///
131-
/// Can be constructed from any of the following:
132-
/// * `u64`
133-
/// * `[u32; 2]`
134-
/// * `[u8; 8]`
135-
///
136-
/// The arrays should be in little endian order.
137-
pub type StreamId = U32x2;
138-
139-
/// A wrapper for `block_pos`.
140-
///
141-
/// Can be constructed from any of the following:
142-
/// * `u64`
143-
/// * `[u32; 2]`
144-
/// * `[u8; 8]`
145-
///
146-
/// The arrays should be in little endian order.
147-
pub type BlockPos = U32x2;
148-
149128
const BUFFER_SIZE: usize = 64;
150129

151130
// NB. this must remain consistent with some currently hard-coded numbers in this module
@@ -195,7 +174,7 @@ impl<R: Rounds, V: Variant> ChaChaCore<R, V> {
195174
}
196175

197176
macro_rules! impl_chacha_rng {
198-
($ChaChaXRng:ident, $ChaChaXCore:ident, $rounds:ident, $abst:ident) => {
177+
($ChaChaXRng:ident, $rounds:ident, $abst:ident) => {
199178
/// A cryptographically secure random number generator that uses the ChaCha algorithm.
200179
///
201180
/// ChaCha is a stream cipher designed by Daniel J. Bernstein[^1], that we use as an RNG. It is
@@ -225,8 +204,9 @@ macro_rules! impl_chacha_rng {
225204
/// seed seed seed seed
226205
/// counter counter stream_id stream_id
227206
/// ```
228-
/// This implementation uses an output buffer of sixteen `u32` words, and uses
229-
/// [`BlockRng`] to implement the [`Rng`] methods.
207+
/// This implementation uses an output buffer of sixteen `u32` words, using
208+
/// [`rand_core::block::BlockRng`] over [`ChaChaCore`] to implement
209+
/// [`rand_core::Rng`].
230210
///
231211
/// # Example for `ChaCha20Rng`
232212
///
@@ -266,19 +246,15 @@ macro_rules! impl_chacha_rng {
266246
///
267247
/// [^2]: [eSTREAM: the ECRYPT Stream Cipher Project](http://www.ecrypt.eu.org/stream/)
268248
pub struct $ChaChaXRng {
269-
/// The ChaChaCore struct
270-
pub core: BlockRng<$ChaChaXCore>,
249+
core: BlockRng<ChaChaCore<$rounds, Legacy>>,
271250
}
272251

273-
/// The ChaCha core random number generator
274-
pub struct $ChaChaXCore(ChaChaCore<$rounds, Legacy>);
275-
276-
impl SeedableRng for $ChaChaXCore {
252+
impl SeedableRng for ChaChaCore<$rounds, Legacy> {
277253
type Seed = Seed;
278254

279255
#[inline]
280256
fn from_seed(seed: Self::Seed) -> Self {
281-
Self(ChaChaCore::<$rounds, Legacy>::new(seed.as_ref(), &[0u8; 8]))
257+
ChaChaCore::<$rounds, Legacy>::new(seed.as_ref(), &[0u8; 8])
282258
}
283259
}
284260
impl SeedableRng for $ChaChaXRng {
@@ -287,7 +263,7 @@ macro_rules! impl_chacha_rng {
287263
#[inline]
288264
fn from_seed(seed: Self::Seed) -> Self {
289265
Self {
290-
core: BlockRng::new($ChaChaXCore::from_seed(seed.into())),
266+
core: BlockRng::new(ChaChaCore::<$rounds, Legacy>::from_seed(seed.into())),
291267
}
292268
}
293269
}
@@ -308,11 +284,8 @@ macro_rules! impl_chacha_rng {
308284
Ok(())
309285
}
310286
}
311-
impl CryptoGenerator for $ChaChaXCore {}
312-
impl TryCryptoRng for $ChaChaXRng {}
313287

314-
#[cfg(feature = "zeroize")]
315-
impl ZeroizeOnDrop for $ChaChaXCore {}
288+
impl TryCryptoRng for $ChaChaXRng {}
316289

317290
#[cfg(feature = "zeroize")]
318291
impl ZeroizeOnDrop for $ChaChaXRng {}
@@ -336,8 +309,8 @@ macro_rules! impl_chacha_rng {
336309
/// byte-offset.
337310
#[inline]
338311
pub fn get_word_pos(&self) -> u128 {
339-
let mut block_counter = (u64::from(self.core.core.0.state[13]) << 32)
340-
| u64::from(self.core.core.0.state[12]);
312+
let mut block_counter = (u64::from(self.core.core.state[13]) << 32)
313+
| u64::from(self.core.core.state[12]);
341314
if self.core.word_offset() != 0 {
342315
block_counter = block_counter.wrapping_sub(BUF_BLOCKS as u64);
343316
}
@@ -360,8 +333,8 @@ macro_rules! impl_chacha_rng {
360333
let index = (word_offset % BLOCK_WORDS as u128) as usize;
361334
let counter = word_offset / BLOCK_WORDS as u128;
362335
//self.set_block_pos(counter as u64);
363-
self.core.core.0.state[12] = counter as u32;
364-
self.core.core.0.state[13] = (counter >> 32) as u32;
336+
self.core.core.state[12] = counter as u32;
337+
self.core.core.state[13] = (counter >> 32) as u32;
365338
self.core.reset_and_skip(index);
366339
}
367340

@@ -371,28 +344,18 @@ macro_rules! impl_chacha_rng {
371344
/// together.
372345
///
373346
/// The word pos will be equal to `block_pos * 16 words per block`.
374-
///
375-
/// This method takes any of the following:
376-
/// * `u64`
377-
/// * `[u32; 2]`
378-
/// * `[u8; 8]`
379-
///
380-
/// Note: the arrays should be in little endian order.
381347
#[inline]
382348
#[allow(unused)]
383-
pub fn set_block_pos<B: Into<BlockPos>>(&mut self, block_pos: B) {
349+
pub fn set_block_pos(&mut self, block_pos: u64) {
384350
self.core.reset_and_skip(0);
385-
let block_pos = block_pos.into().0;
386-
self.core.core.0.state[12] = block_pos[0];
387-
self.core.core.0.state[13] = block_pos[1]
351+
self.core.core.set_block_pos(block_pos);
388352
}
389353

390354
/// Get the block pos.
391355
#[inline]
392356
#[allow(unused)]
393357
pub fn get_block_pos(&self) -> u64 {
394-
let counter =
395-
self.core.core.0.state[12] as u64 | ((self.core.core.0.state[13] as u64) << 32);
358+
let counter = self.core.core.get_block_pos();
396359
if self.core.word_offset() != 0 {
397360
counter - BUF_BLOCKS as u64 + self.core.word_offset() as u64 / 16
398361
} else {
@@ -426,7 +389,7 @@ macro_rules! impl_chacha_rng {
426389
///
427390
/// // set state[12] to 0, state[13] to 1, state[14] to 2, state[15] to 3
428391
/// rng.set_stream([2u32, 3u32]);
429-
/// rng.set_block_pos([0u32, 1u32]);
392+
/// rng.set_block_pos(0x1_0000_0000_u64);
430393
///
431394
/// // confirm that state is set correctly
432395
/// assert_eq!(rng.get_block_pos(), 1 << 32);
@@ -440,15 +403,15 @@ macro_rules! impl_chacha_rng {
440403
#[inline]
441404
pub fn set_stream<S: Into<StreamId>>(&mut self, stream: S) {
442405
let stream: StreamId = stream.into();
443-
self.core.core.0.state[14..].copy_from_slice(&stream.0);
406+
self.core.core.state[14..].copy_from_slice(&stream.0);
444407
self.set_block_pos(0);
445408
}
446409

447410
/// Get the stream number.
448411
#[inline]
449412
pub fn get_stream(&self) -> u64 {
450413
let mut result = [0u8; 8];
451-
for (i, &big) in self.core.core.0.state[14..BLOCK_WORDS as usize]
414+
for (i, &big) in self.core.core.state[14..BLOCK_WORDS as usize]
452415
.iter()
453416
.enumerate()
454417
{
@@ -465,7 +428,7 @@ macro_rules! impl_chacha_rng {
465428
#[inline]
466429
pub fn get_seed(&self) -> [u8; 32] {
467430
let mut result = [0u8; 32];
468-
for (i, &big) in self.core.core.0.state[4..12].iter().enumerate() {
431+
for (i, &big) in self.core.core.state[4..12].iter().enumerate() {
469432
let index = i * 4;
470433
result[index + 0] = big as u8;
471434
result[index + 1] = (big >> 8) as u8;
@@ -486,14 +449,6 @@ macro_rules! impl_chacha_rng {
486449

487450
impl Eq for $ChaChaXRng {}
488451

489-
impl From<$ChaChaXCore> for $ChaChaXRng {
490-
fn from(core: $ChaChaXCore) -> Self {
491-
$ChaChaXRng {
492-
core: BlockRng::new(core),
493-
}
494-
}
495-
}
496-
497452
mod $abst {
498453
// The abstract state of a ChaCha stream, independent of implementation choices. The
499454
// comparison and serialization of this object is considered a semver-covered part of
@@ -529,12 +484,12 @@ macro_rules! impl_chacha_rng {
529484
}
530485
}
531486

532-
impl Generator for $ChaChaXCore {
487+
impl Generator for ChaChaCore<$rounds, Legacy> {
533488
type Output = [u32; BUFFER_SIZE];
534489

535490
#[inline]
536491
fn generate(&mut self, r: &mut Self::Output) {
537-
self.0.generate(r);
492+
self.generate(r);
538493
}
539494

540495
#[cfg(feature = "zeroize")]
@@ -545,11 +500,11 @@ macro_rules! impl_chacha_rng {
545500
};
546501
}
547502

548-
impl_chacha_rng!(ChaCha8Rng, ChaCha8Core, R8, abst8);
503+
impl_chacha_rng!(ChaCha8Rng, R8, abst8);
549504

550-
impl_chacha_rng!(ChaCha12Rng, ChaCha12Core, R12, abst12);
505+
impl_chacha_rng!(ChaCha12Rng, R12, abst12);
551506

552-
impl_chacha_rng!(ChaCha20Rng, ChaCha20Core, R20, abst20);
507+
impl_chacha_rng!(ChaCha20Rng, R20, abst20);
553508

554509
#[cfg(test)]
555510
pub(crate) mod tests {
@@ -614,16 +569,12 @@ pub(crate) mod tests {
614569
rng.set_stream(11111111);
615570
assert_eq!(rng.get_stream(), 11111111);
616571

617-
// test set_block_pos with u32
572+
// test set_block_pos with u64
618573
rng.set_block_pos(58392);
619574
assert_eq!(rng.get_block_pos(), 58392);
620575
// test word_pos = 16 * block_pos
621576
assert_eq!(rng.get_word_pos(), 58392 * 16);
622577

623-
// test set_block_pos with [u8; 8]
624-
rng.set_block_pos([77, 0, 0, 0, 0, 0, 0, 0]);
625-
assert_eq!(rng.get_block_pos(), 77);
626-
627578
// test set_word_pos with u64
628579
rng.set_word_pos(8888);
629580
assert_eq!(rng.get_word_pos(), 8888);
@@ -750,7 +701,7 @@ pub(crate) mod tests {
750701

751702
// Test block 2 by using `set_block_pos` and [u8; 8]
752703
let mut rng4 = ChaChaRng::from_seed(seed);
753-
rng4.set_block_pos([2, 0, 0, 0, 0, 0, 0, 0]);
704+
rng4.set_block_pos(2);
754705
results = [0u32; 16];
755706
for i in results.iter_mut() {
756707
*i = rng4.next_u32();
@@ -821,7 +772,7 @@ pub(crate) mod tests {
821772

822773
let stream_id = hex!("0000004a00000000");
823774
rng.set_stream(stream_id);
824-
rng.set_block_pos(hex!("0000000000000009"));
775+
rng.set_block_pos(u64::from_le_bytes(hex!("0000000000000009")));
825776

826777
// The test vectors omit the first 64-bytes of the keystream
827778
let mut discard_first_64 = [0u8; 64];
@@ -920,7 +871,7 @@ pub(crate) mod tests {
920871
#[test]
921872
fn test_chacha_word_pos_zero() {
922873
let mut rng = ChaChaRng::from_seed(Default::default());
923-
assert_eq!(rng.core.core.0.state[12], 0);
874+
assert_eq!(rng.core.core.state[12], 0);
924875
assert_eq!(rng.core.word_offset(), 0);
925876
assert_eq!(rng.get_word_pos(), 0);
926877
rng.set_word_pos(0);
@@ -1111,7 +1062,7 @@ pub(crate) mod tests {
11111062
let first_blocks_end_block_counter = rng.get_block_pos();
11121063

11131064
// get first four blocks after wrapping
1114-
rng.set_block_pos([u32::MAX, u32::MAX]);
1065+
rng.set_block_pos(u64::MAX);
11151066
let mut result = [0u8; 64 * 5];
11161067
rng.fill_bytes(&mut result);
11171068
assert_eq!(first_blocks_end_word_pos, rng.get_word_pos());

0 commit comments

Comments
 (0)