extern crate rand;
use std::mem;
use std::ops::BitXorAssign;
use std::arch::x86_64::{__m128i, _mm_aesenc_si128};
use rand::{Rand, Rng, SeedableRng};
const STATE_LEN: usize = 16;
const CAPACITY: usize = 1;
const SEED_LEN: usize = STATE_LEN - CAPACITY;
const STATE_BYTES: usize = STATE_LEN * 16;
const CAPACITY_BYTES: usize = CAPACITY * 16;
const FEISTEL_ROUNDS: usize = 17;
const FEISTEL_FUNCTIONS: usize = 8;
const ROUND_KEYS_LEN: usize = FEISTEL_ROUNDS * FEISTEL_FUNCTIONS;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(align(16))]
pub struct U128A(u128);
impl U128A {
#[inline(always)]
fn from(m128i: __m128i) -> U128A {
unsafe { mem::transmute(m128i) }
}
#[inline(always)]
fn m128i(self) -> __m128i {
unsafe { mem::transmute(self) }
}
}
impl BitXorAssign for U128A {
fn bitxor_assign(&mut self, rhs: U128A) {
self.0 ^= rhs.0;
}
}
const ROUND_KEYS: [U128A; ROUND_KEYS_LEN] = [
U128A(0x13198A2E03707344243F6A8885A308D3),
U128A(0x082EFA98EC4E6C89A4093822299F31D0),
U128A(0xBE5466CF34E90C6C452821E638D01377),
U128A(0x3F84D5B5B5470917C0AC29B7C97C50DD),
U128A(0xD1310BA698DFB5AC9216D5D98979FB1B),
U128A(0xB8E1AFED6A267E962FFD72DBD01ADFB7),
U128A(0x24A19947B3916CF7BA7C9045F12C7F99),
U128A(0x636920D871574E690801F2E2858EFC16),
U128A(0x0D95748F728EB658A458FEA3F4933D7E),
U128A(0x7B54A41DC25A59B5718BCD5882154AEE),
U128A(0xC5D1B023286085F09C30D5392AF26013),
U128A(0x8E79DCB0603A180ECA417918B8DB38EF),
U128A(0xD71577C1BD314B276C9E0E8BB01E8A3E),
U128A(0xE65525F3AA55AB9478AF2FDA55605C60),
U128A(0x55CA396A2AAB10B65748986263E81440),
U128A(0xA15486AF7C72E993B4CC5C341141E8CE),
U128A(0x2BA9C55D741831F6B3EE1411636FBC2A),
U128A(0xAFD6BA336C24CF5CCE5C3E169B87931E),
U128A(0x3B8F48986B4BB9AF7A32538128958677),
U128A(0x61D809CCFB21A991C4BFE81B66282193),
U128A(0xEF845D5DE98575B1487CAC605DEC8032),
U128A(0x23893E81D396ACC5DC262302EB651B88),
U128A(0x2E0B4482A48420040F6D6FF383F44239),
U128A(0x21C66842F6E96C9A69C8F04A9E1F9B5E),
U128A(0x6A51A0D2D8542F68670C9C61ABD388F0),
U128A(0x6EEF0B6C137A3BE4960FA728AB5133A3),
U128A(0xA1F1651D39AF0176BA3BF0507EFB2A98),
U128A(0x8CEE8619456F9FB466CA593E82430E88),
U128A(0xE06F75D885C120737D84A5C33B8B5EBE),
U128A(0x4ED3AA62363F7706401A449F56C16AA6),
U128A(0x37D0D724D00A12481BFEDF72429B023D),
U128A(0x075372C980991B7BDB0FEAD349F1C09B),
U128A(0xE3FE501AB6794C3B25D479D8F6E8DEF7),
U128A(0xC1A94FB6409F60C4976CE0BD04C006BA),
U128A(0x68FB6FAF3E6C53B55E5C9EC2196A2463),
U128A(0x6DFC511F9B30952C1339B2EB3B52EC6F),
U128A(0xBEE3D004DE334AFDCC814544AF5EBD09),
U128A(0xC0CBA85745C8740F660F2807192E4BB3),
U128A(0x5579C0BD1A60320AD20B5F39B9D3FBDB),
U128A(0x679F25FEFB1FA3CCD6A100C6402C7279),
U128A(0x3C7516DFFD616B158EA5E9F8DB3222F8),
U128A(0x323DB5FAFD2387602F501EC8AD0552AB),
U128A(0x9E5C57BBCA6F8CA053317B483E00DF82),
U128A(0xD542A8F6287EFFC31A87562EDF1769DB),
U128A(0x695B27B0BBCA58C8AC6732C68C4F5573),
U128A(0x10FA3D98FD2183B8E1FFA35DB8F011A0),
U128A(0x9A53E479B6F845654AFCB56C2DD1D35B),
U128A(0xE1DDF2DAA4CB7E33D28E49BC4BFB9790),
U128A(0xEF20CADA36774C0162FB1341CEE4C6E8),
U128A(0x95DBDA4DAE909198D07E9EFE2BF11FB4),
U128A(0xD08ED1D0AFC725E0EAAD8E716B93D5A0),
U128A(0x8FF6E2FBF2122B648E3C5B2F8E7594B7),
U128A(0x4FAD5EA0688FC31C8888B812900DF01C),
U128A(0x2F2F2218BE0E1777D1CFF191B3A8C1AD),
U128A(0xE5A0CC0FB56F74E8EA752DFE8B021FA1),
U128A(0xB4A84FE0FD13E0B718ACF3D6CE89E299),
U128A(0x165FA266809577057CC43B81D2ADA8D9),
U128A(0xE6AD206577B5FA8693CC7314211A1477),
U128A(0xEBCDAF0C7B3E89A0C75442F5FB9D35CF),
U128A(0x00250E2D2071B35ED6411BD3AE1E7E49),
U128A(0x2464369BF009B91E226800BB57B8E0AF),
U128A(0x78C14389D95A537F5563911D59DFA6AA),
U128A(0x832603766295CFA9207D5BA202E5B9C5),
U128A(0xB3472DCA7B14A94A11C819684E734A41),
U128A(0xD60F573FBC9BC6E41B5100529A532915),
U128A(0x08BA6FB5571BE91F2B60A47681E67400),
U128A(0xB6636521E7B9F9B6F296EC6B2A0DD915),
U128A(0x53B02D5DA99F8FA1FF34052EC5855664),
U128A(0x4B7A70E9B5B3294408BA47996E85076A),
U128A(0xAD6EA6B049A7DF7DDB75092EC4192623),
U128A(0xECAA8C71699A18FF9CEE60B88FEDB266),
U128A(0x193602A575094C295664526CC2B19EE1),
U128A(0x3F54989A5B429D65A0591340E4183A3E),
U128A(0xA1D29C07EFE830F56B8FE4D699F73FD6),
U128A(0x4CDD20868470EB264D2D38E6F0255DC1),
U128A(0x09686B3F3EBAEFC96382E9C6021ECC5E),
U128A(0x687F358452A0E2863C9718146B6A70A1),
U128A(0x3E07841C7FDEAE5CB79C5305AA500737),
U128A(0xB03ADA37F0500C0D8E7D44EC5716F2B8),
U128A(0xAE0CF51A3CB574B2F01C1F040200B3FF),
U128A(0xD19113F97CA92FF625837A58DC0921BD),
U128A(0x3AE5E58137C2DADC9432477322F54701),
U128A(0xA94461460FD0030EC8B576349AF3DDA7),
U128A(0xE238CD993BEA0E2FECC8C73EA4751E41),
U128A(0x4E548B384F6DB9083280BBA1183EB331),
U128A(0x2CB8129024977C796F420D03F60A04BF),
U128A(0xDE9A771FD99308105679B072BCAF89AF),
U128A(0x5512721F2E6B7124B38BAE12DCCF3F2E),
U128A(0x7A5847187408DA17501ADDE69F84CD87),
U128A(0xEC7AEC3ADB851DFABC9F9ABCE94B7D8C),
U128A(0xEF1C18473215D80863094366C464C3D2),
U128A(0x12A14D432A65C451DD433B3724C2BA16),
U128A(0x71DFF89E10314E5550940002133AE4DD),
U128A(0x043556F1D7A3C76B81AC77D65F11199B),
U128A(0xF28FE6ED97F1FBFA3C11183B5924A509),
U128A(0x86E34570EAE96FB19EBABF2C1E153C6E),
U128A(0x771FE71C4E3D06FA860E5E0A5A3E2AB3),
U128A(0x803E89D65266C8252965DCB999E71D0F),
U128A(0xC6150EBA94E2EA782E4CC9789C10B36A),
U128A(0xF2F74EA7361D2B3DA6FC3C531E0A2DF4),
U128A(0x5223A708F71312B61939260F19C27960),
U128A(0xE3BC4595A67BC883EBADFE6EEAC31F66),
U128A(0xC332DDEFBE6C5AA5B17F37D1018CFF28),
U128A(0xEECEA50FDB2F953B6558218568AB9702),
U128A(0x1521B628290761702AEF7DAD5B6E2F84),
U128A(0x13CCA830EB61BD96ECDD4775619F1510),
U128A(0xB5735C904C70A2390334FE1EAA0363CF),
U128A(0xEECC86BC60622CA7D59E9E0BCBAADE14),
U128A(0x648B1EAF19BDF0CA9CAB5CABB2F3846E),
U128A(0x40685A323C2AB4B3A02369B9655ABB50),
U128A(0x9B540B19875FA099319EE9D5C021B8F7),
U128A(0xF837889A97E32D7795F7997E623D7DA8),
U128A(0x0E358829C7E61FD611ED935F16681281),
U128A(0x57F584A51B22726396DEDFA17858BA99),
U128A(0xCDB30AEB532E30549B83C3FF1AC24696),
U128A(0x58EBF2EF34C6FFEA8FD948E46DBC3128),
U128A(0x5D4A14D9E864B7E3FE28ED61EE7C3C73),
U128A(0x45EEE2B6A3AAABEA42105D14203E13E0),
U128A(0xC742F442EF6ABBB5DB6C4F15FACB4FD0),
U128A(0xD81E799E86854DC7654F3B1D41CD2105),
U128A(0xCF62A1F25B8D2646E44B476A3D816250),
U128A(0x7F1524C369CB7492FC8883A0C1C7B6A3),
U128A(0x095BBF00AD19489D47848A0B5692B285),
U128A(0x58428D2A0C55F5EA1462B17423820D00),
U128A(0x3372F0928D937E411DADF43E233F7061),
U128A(0x7CDE3759CBEE7460D65FECF16C223BDB),
U128A(0xA607808419F8509E4085F2A7CE77326E),
U128A(0xA969A7AAC50C06C2E8EFD85561D99735),
U128A(0x9E447A2EC34534845A04ABFC800BCADC),
U128A(0xDB73DBD3105588CDFDD567050E1E9EC9),
U128A(0xC5C43465713E38D8675FDA79E3674340),
U128A(0x153E21E78FB03D4A3D28F89EF16DFF20),
U128A(0xE93D5A68948140F7E6E39F2BDB83ADF7),
U128A(0x411520F77602D4F7F64C261C94692934),
U128A(0xD40824713320F46ABCF46B2ED4A10068),
U128A(0x1E39F62E9724454643B7D4B7500061AF),
];
pub type State = [U128A; STATE_LEN];
#[inline(always)]
fn aes_round(state: U128A, round_key: U128A) -> U128A {
unsafe { U128A::from(_mm_aesenc_si128(state.m128i(), round_key.m128i())) }
}
#[inline(always)]
fn block_shuffle(source: State) -> State {
let shuffle = [7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12];
let mut new_state = [U128A(0); STATE_LEN];
for (i, shuf) in shuffle.iter().enumerate() {
new_state[i] = source[*shuf];
}
new_state
}
#[inline(always)]
fn permute(state: &mut State) {
let mut keys = ROUND_KEYS.iter();
for _ in 0..FEISTEL_ROUNDS {
for branch in 0..FEISTEL_FUNCTIONS {
let even = state[branch * 2];
let odd = state[branch * 2 + 1];
let f1 = aes_round(even, *keys.next().unwrap());
let f2 = aes_round(f1, odd);
state[branch * 2 + 1] = f2;
}
*state = block_shuffle(*state);
}
}
#[cfg(target_endian = "little")]
pub fn randen_generate(state: &mut State) {
let prev_inner = state[0];
permute(state);
state[0] ^= prev_inner;
}
#[cfg(target_endian = "big")]
pub fn randen_generate(state: &mut State) {
unimplemented!("Big endian requires swapping the bytes in the state and round keys.");
}
pub fn randen_absorb(state: &mut State, seed: &[U128A; SEED_LEN]) {
for (seed_elem, state_elem) in seed.iter().zip(&mut state[1..]) {
*state_elem ^= *seed_elem;
}
}
#[derive(Clone, Debug)]
pub struct RandenRng {
state: State,
cursor: usize,
}
impl RandenRng {
pub fn new_unseeded() -> RandenRng {
RandenRng {
state: [U128A(0); STATE_LEN],
cursor: STATE_BYTES,
}
}
}
macro_rules! impl_next {
($func: ident, $t: ty, $size: expr) => {
fn $func(&mut self) -> $t {
if self.cursor > STATE_BYTES - $size {
randen_generate(&mut self.state);
self.cursor = CAPACITY_BYTES;
}
let index = (self.cursor + $size - 1) / $size;
self.cursor = (index + 1) * $size;
let ts: [$t; STATE_BYTES / $size] =
unsafe { mem::transmute(self.state) };
ts[index]
}
}
}
impl Rng for RandenRng {
impl_next!(next_u32, u32, 4);
impl_next!(next_u64, u64, 8);
fn fill_bytes(&mut self, dest: &mut [u8]) {
let mut i = 0;
let len = dest.len();
while i < len {
if self.cursor >= STATE_BYTES {
randen_generate(&mut self.state);
self.cursor = CAPACITY_BYTES;
}
let bytes: [u8; STATE_BYTES] = unsafe { mem::transmute(self.state) };
let consume_bytes = (len - i).min(STATE_BYTES - self.cursor);
let source = &bytes[self.cursor..self.cursor + consume_bytes];
dest[i..i + consume_bytes].copy_from_slice(source);
self.cursor += consume_bytes;
i += consume_bytes;
}
}
}
impl<'a> SeedableRng<&'a [U128A; SEED_LEN]> for RandenRng {
fn reseed(&mut self, seed: &'a [U128A; SEED_LEN]) {
self.state = [U128A(0); STATE_LEN];
self.cursor = STATE_BYTES;
randen_absorb(&mut self.state, seed);
}
fn from_seed(seed: &'a [U128A; SEED_LEN]) -> RandenRng {
let mut rng = RandenRng::new_unseeded();
randen_absorb(&mut rng.state, seed);
rng
}
}
impl Rand for RandenRng {
fn rand<R: Rng>(other: &mut R) -> RandenRng {
let mut seed = [U128A(0); SEED_LEN];
for elem in seed.iter_mut() {
*elem = U128A(other.gen());
}
SeedableRng::from_seed(&seed)
}
}
#[cfg(test)]
mod test {
use rand::{Rng, SeedableRng};
use super::{RandenRng, U128A};
#[test]
fn randen_rng_next_u64_test_vectors() {
let mut rng = RandenRng::new_unseeded();
assert_eq!(rng.next_u64(), 0xdda9f47cd90410ee);
assert_eq!(rng.next_u64(), 0xc3c14f134e433977);
assert_eq!(rng.next_u64(), 0xf0b780f545c72912);
assert_eq!(rng.next_u64(), 0x887bf3087fd8ca10);
assert_eq!(rng.next_u64(), 0x30ec63baff3c6d59);
assert_eq!(rng.next_u64(), 0x15dbb1d37696599f);
assert_eq!(rng.next_u64(), 0x2808a316f49a54c);
assert_eq!(rng.next_u64(), 0xb29f73606f7f20a6);
assert_eq!(rng.next_u64(), 0x9cbf605e3fd9de8a);
assert_eq!(rng.next_u64(), 0x3b8feaf9d5c8e50e);
assert_eq!(rng.next_u64(), 0xd8b2ffd356301ed5);
assert_eq!(rng.next_u64(), 0xc970ae1a78183bbb);
assert_eq!(rng.next_u64(), 0xcdfd8d76eb8f9a19);
assert_eq!(rng.next_u64(), 0xf4b327fe0fc73c37);
assert_eq!(rng.next_u64(), 0xd5af05dd3eff9556);
assert_eq!(rng.next_u64(), 0xc3a506eb91420c9d);
assert_eq!(rng.next_u64(), 0x7023920e0d6bfe8c);
assert_eq!(rng.next_u64(), 0x48db1bb78f83c4a1);
assert_eq!(rng.next_u64(), 0xed1ef4c26b87b840);
assert_eq!(rng.next_u64(), 0x58d3575834956d42);
assert_eq!(rng.next_u64(), 0x497cabf3431154fc);
assert_eq!(rng.next_u64(), 0x8eef32a23e0b2df3);
assert_eq!(rng.next_u64(), 0xd88b5749f090e5ea);
assert_eq!(rng.next_u64(), 0x4e24370570029a8b);
assert_eq!(rng.next_u64(), 0x78fcec2cbb6342f5);
assert_eq!(rng.next_u64(), 0xc651a582a970692f);
assert_eq!(rng.next_u64(), 0x352ee4ad1816afe3);
assert_eq!(rng.next_u64(), 0x463cb745612f55db);
assert_eq!(rng.next_u64(), 0x811ef0821c3de851);
assert_eq!(rng.next_u64(), 0x26ff374c101da7e);
assert_eq!(rng.next_u64(), 0xa0660379992d58fc);
assert_eq!(rng.next_u64(), 0x6f7e616704c4fa59);
assert_eq!(rng.next_u64(), 0x915f3445685da798);
}
#[test]
fn randen_rng_next_u32_test_vectors() {
let mut rng = RandenRng::new_unseeded();
assert_eq!(rng.next_u32(), 0xd90410ee);
assert_eq!(rng.next_u32(), 0xdda9f47c);
assert_eq!(rng.next_u32(), 0x4e433977);
assert_eq!(rng.next_u32(), 0xc3c14f13);
assert_eq!(rng.next_u32(), 0x45c72912);
assert_eq!(rng.next_u32(), 0xf0b780f5);
assert_eq!(rng.next_u32(), 0x7fd8ca10);
assert_eq!(rng.next_u32(), 0x887bf308);
assert_eq!(rng.next_u32(), 0xff3c6d59);
assert_eq!(rng.next_u32(), 0x30ec63ba);
assert_eq!(rng.next_u32(), 0x7696599f);
assert_eq!(rng.next_u32(), 0x15dbb1d3);
assert_eq!(rng.next_u32(), 0x6f49a54c);
assert_eq!(rng.next_u32(), 0x02808a31);
assert_eq!(rng.next_u32(), 0x6f7f20a6);
assert_eq!(rng.next_u32(), 0xb29f7360);
assert_eq!(rng.next_u32(), 0x3fd9de8a);
assert_eq!(rng.next_u32(), 0x9cbf605e);
assert_eq!(rng.next_u32(), 0xd5c8e50e);
assert_eq!(rng.next_u32(), 0x3b8feaf9);
assert_eq!(rng.next_u32(), 0x56301ed5);
assert_eq!(rng.next_u32(), 0xd8b2ffd3);
assert_eq!(rng.next_u32(), 0x78183bbb);
assert_eq!(rng.next_u32(), 0xc970ae1a);
assert_eq!(rng.next_u32(), 0xeb8f9a19);
assert_eq!(rng.next_u32(), 0xcdfd8d76);
assert_eq!(rng.next_u32(), 0x0fc73c37);
assert_eq!(rng.next_u32(), 0xf4b327fe);
assert_eq!(rng.next_u32(), 0x3eff9556);
assert_eq!(rng.next_u32(), 0xd5af05dd);
assert_eq!(rng.next_u32(), 0x91420c9d);
assert_eq!(rng.next_u32(), 0xc3a506eb);
assert_eq!(rng.next_u32(), 0x0d6bfe8c);
assert_eq!(rng.next_u32(), 0x7023920e);
assert_eq!(rng.next_u32(), 0x8f83c4a1);
assert_eq!(rng.next_u32(), 0x48db1bb7);
assert_eq!(rng.next_u32(), 0x6b87b840);
assert_eq!(rng.next_u32(), 0xed1ef4c2);
assert_eq!(rng.next_u32(), 0x34956d42);
assert_eq!(rng.next_u32(), 0x58d35758);
assert_eq!(rng.next_u32(), 0x431154fc);
assert_eq!(rng.next_u32(), 0x497cabf3);
assert_eq!(rng.next_u32(), 0x3e0b2df3);
assert_eq!(rng.next_u32(), 0x8eef32a2);
assert_eq!(rng.next_u32(), 0xf090e5ea);
assert_eq!(rng.next_u32(), 0xd88b5749);
assert_eq!(rng.next_u32(), 0x70029a8b);
assert_eq!(rng.next_u32(), 0x4e243705);
assert_eq!(rng.next_u32(), 0xbb6342f5);
assert_eq!(rng.next_u32(), 0x78fcec2c);
assert_eq!(rng.next_u32(), 0xa970692f);
assert_eq!(rng.next_u32(), 0xc651a582);
assert_eq!(rng.next_u32(), 0x1816afe3);
assert_eq!(rng.next_u32(), 0x352ee4ad);
assert_eq!(rng.next_u32(), 0x612f55db);
assert_eq!(rng.next_u32(), 0x463cb745);
assert_eq!(rng.next_u32(), 0x1c3de851);
assert_eq!(rng.next_u32(), 0x811ef082);
assert_eq!(rng.next_u32(), 0xc101da7e);
assert_eq!(rng.next_u32(), 0x026ff374);
assert_eq!(rng.next_u32(), 0x992d58fc);
assert_eq!(rng.next_u32(), 0xa0660379);
assert_eq!(rng.next_u32(), 0x04c4fa59);
assert_eq!(rng.next_u32(), 0x6f7e6167);
assert_eq!(rng.next_u32(), 0x685da798);
}
#[test]
fn randen_rng_fill_bytes_test_vectors() {
let mut seq_1 = [0_u8; 37];
let mut seq_2 = [0_u8; 151];
let mut seq_3 = [0_u8; 233];
let mut rng = RandenRng::new_unseeded();
rng.fill_bytes(&mut seq_1);
rng.fill_bytes(&mut seq_2);
rng.fill_bytes(&mut seq_3);
assert_eq!(seq_1[36], 186);
assert_eq!(seq_2[150], 112);
assert_eq!(seq_3[232], 24);
}
#[test]
fn randen_rng_reseed_from_seed_equivalence() {
let seed = [U128A(1); 15];
let mut reseeded = RandenRng::new_unseeded();
reseeded.reseed(&seed);
let mut constructed = RandenRng::from_seed(&seed);
for _ in 0..100 {
assert_eq!(reseeded.next_u64(), constructed.next_u64());
}
}
}