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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
//! Pseudorandom number utilities for HashX's program generator
//!
//! HashX uses pseudorandom numbers to make individual decisions in the program
//! generation process. The program generator consumes u8 and u32 values that
//! use a shared u64 generator, implemented using SipHash1,3.
//!
//! We use the [`RngCore`] trait for this underlying u64 generator,
//! allowing substitute random number generators for testing or for special
//! purposes that don't require compatibility with HashX proper.
//!
//! The stateful u8 and u32 layer comes from this module's ['RngBuffer'].
//! It's important for the u8 and u32 queues to share a common generator.
//! The order of dequeueing u8 items vs u32 items intentionally modifies the
//! assignment of particular u64 [`RngCore`] values to the two queues.

use crate::siphash::{siphash13_ctr, SipState};
use arrayvec::ArrayVec;
use rand_core::RngCore;

/// Wrap a [`RngCore`] implementation for fast `u8` and `u32` output.
///
/// This maintains small queues for each data type: up to one `u32` and up to
/// 7 bytes. The queueing behavior matches convenions required by HashX:
/// The underlying `u64` values are always generated lazily, and component
/// values are extracted in big endian order.
#[derive(Debug)]
pub(crate) struct RngBuffer<'a, T: RngCore> {
    /// Inner [`RngCore`] implementation
    inner: &'a mut T,
    /// Buffer of remaining u8 values from breaking up a u64
    u8_vec: ArrayVec<u8, 7>,
    /// Up to one buffered u32 value
    u32_opt: Option<u32>,
}

impl<'a, T: RngCore> RngBuffer<'a, T> {
    /// Construct a new empty buffer around a [`RngCore`] implementation.
    ///
    /// No actual random numbers will be generated until the first call to
    /// [`Self::next_u8`] or [`Self::next_u32`].
    #[inline(always)]
    pub(crate) fn new(rng: &'a mut T) -> Self {
        Self {
            inner: rng,
            u8_vec: Default::default(),
            u32_opt: None,
        }
    }

    /// Request 32 bits from the buffered random number generator.
    ///
    /// If we have buffered data stored, returns that. If not,
    /// requests 64 bits from the [`RngCore`] and saves half for later.
    #[inline(always)]
    pub(crate) fn next_u32(&mut self) -> u32 {
        let previous = self.u32_opt;
        match previous {
            Some(value) => {
                self.u32_opt = None;
                value
            }
            None => {
                let value = self.inner.next_u64();
                self.u32_opt = Some(value as u32);
                (value >> 32) as u32
            }
        }
    }

    /// Request 8 bits from the buffered random number generator.
    ///
    /// If we have buffered data stored, returns that. If not,
    /// requests 64 bits from the [`RngCore`] and saves 7 bytes for later.
    #[inline(always)]
    pub(crate) fn next_u8(&mut self) -> u8 {
        let value = self.u8_vec.pop();
        match value {
            Some(value) => value,
            None => {
                // Little endian (reversed) order here,
                // because we dequeue items from the end of the Vec.
                let bytes = self.inner.next_u64().to_le_bytes();
                let (last, saved) = bytes.split_last().expect("u64 has nonzero length");
                self.u8_vec
                    .try_extend_from_slice(saved)
                    .expect("slice length correct");
                *last
            }
        }
    }
}

/// HashX-style random number generator built on SipHash1,3
///
/// This is an implementation of [`RngCore`] using SipHash1,3 as
/// the 64-bit PRNG layer needed by HashX's program generator.
#[derive(Debug, Clone)]
pub struct SipRand {
    /// SipHash state vector used as input to SipHash1,3 in counter mode
    key: SipState,
    /// Next unused counter value
    counter: u64,
}

impl SipRand {
    /// Build a new SipHash random number generator.
    ///
    /// The internal SipHash1,3 generator is initialized to a supplied
    /// internal state, and the counter is reset to zero.
    #[inline(always)]
    pub fn new(key: SipState) -> Self {
        Self::new_with_counter(key, 0)
    }

    /// Build a new [`SipRand`] with a specific initial counter value.
    #[inline(always)]
    pub fn new_with_counter(key: SipState, counter: u64) -> Self {
        Self { key, counter }
    }
}

impl RngCore for SipRand {
    /// Generate a full 64-bit random result using SipHash1,3.
    fn next_u64(&mut self) -> u64 {
        let value = siphash13_ctr(self.key, self.counter);
        self.counter += 1;
        value
    }

    /// Return a 32-bit value by discarding the upper half of a 64-bit result.
    fn next_u32(&mut self) -> u32 {
        self.next_u64() as u32
    }

    /// Fill `dest` with random data.
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        rand_core::impls::fill_bytes_via_next(self, dest);
    }

    /// Fill `dest` with random data.
    ///
    /// Always succeeds.
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::{RngBuffer, SipRand, SipState};

    #[test]
    fn rng_vectors() {
        // Check against pseudorandom number streams seen during tor unit tests

        let (key0, _key1) = SipState::pair_from_seed(b"abc");
        let mut rng_inner = SipRand::new(key0);
        let mut rng = RngBuffer::new(&mut rng_inner);

        #[derive(Debug, PartialEq)]
        enum Value {
            U32(u32),
            U8(u8),
        }

        let expected = vec![
            Value::U32(0xf695edd0),
            Value::U32(0x2205449d),
            Value::U32(0x51c1ac51),
            Value::U32(0xcd19a7d1),
            Value::U8(0xad),
            Value::U32(0x79793a52),
            Value::U32(0xd965083d),
            Value::U8(0xf4),
            Value::U32(0x915e9969),
            Value::U32(0x7563b6e2),
            Value::U32(0x4e5a9d8b),
            Value::U32(0xef2bb9ce),
            Value::U8(0xcb),
            Value::U32(0xa4beee16),
            Value::U32(0x78fa6e6f),
            Value::U8(0x30),
            Value::U32(0xc321cb9f),
            Value::U32(0xbbf29635),
            Value::U32(0x919450f4),
            Value::U32(0xf3d8f358),
            Value::U8(0x3b),
            Value::U32(0x818a72e9),
            Value::U32(0x58225fcf),
            Value::U8(0x98),
            Value::U32(0x3fcb5059),
            Value::U32(0xaf5bcb70),
            Value::U8(0x14),
            Value::U32(0xd41e0326),
            Value::U32(0xe79aebc6),
            Value::U32(0xa348672c),
            Value::U8(0xcf),
            Value::U32(0x5d51b520),
            Value::U32(0x73afc36f),
            Value::U32(0x31348711),
            Value::U32(0xca25b040),
            Value::U32(0x3700c37b),
            Value::U8(0x62),
            Value::U32(0xf0d1d6a6),
            Value::U32(0xc1edebf3),
            Value::U8(0x9d),
            Value::U32(0x9bb1f33f),
            Value::U32(0xf1309c95),
            Value::U32(0x0797718a),
            Value::U32(0xa3bbcf7e),
            Value::U8(0x80),
            Value::U8(0x28),
            Value::U8(0xe9),
            Value::U8(0x2e),
            Value::U32(0xf5506289),
            Value::U32(0x97b46d7c),
            Value::U8(0x64),
            Value::U32(0xc99fe4ad),
            Value::U32(0x6e756189),
            Value::U8(0x54),
            Value::U8(0xf7),
            Value::U8(0x0f),
            Value::U8(0x7d),
            Value::U32(0x38c983eb),
        ];

        let mut actual = Vec::new();
        for item in &expected {
            match item {
                Value::U8(_) => actual.push(Value::U8(rng.next_u8())),
                Value::U32(_) => actual.push(Value::U32(rng.next_u32())),
            }
        }

        assert_eq!(expected, actual);
    }
}