// Copyright 2018 Developers of the Rand project.
// Copyright 2013 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A wrapper around another PRNG that reseeds it after it
//! generates a certain number of random bytes.

use core::mem::size_of;

use rand_core::{RngCore, CryptoRng, SeedableRng, Error, ErrorKind};
use rand_core::block::{BlockRngCore, BlockRng};

/// A wrapper around any PRNG that implements [`BlockRngCore`], that adds the
/// ability to reseed it.
///
/// `ReseedingRng` reseeds the underlying PRNG in the following cases:
///
/// - On a manual call to [`reseed()`].
/// - After `clone()`, the clone will be reseeded on first use.
/// - After a process is forked, the RNG in the child process is reseeded within
///   the next few generated values, depending on the block size of the
///   underlying PRNG. For [`ChaChaCore`] and [`Hc128Core`] this is a maximum of
///   15 `u32` values before reseeding.
/// - After the PRNG has generated a configurable number of random bytes.
///
/// # When should reseeding after a fixed number of generated bytes be used?
///
/// Reseeding after a fixed number of generated bytes is never strictly
/// *necessary*. Cryptographic PRNGs don't have a limited number of bytes they
/// can output, or at least not a limit reachable in any practical way. There is
/// no such thing as 'running out of entropy'.
///
/// Occasionally reseeding can be seen as some form of 'security in depth'. Even
/// if in the future a cryptographic weakness is found in the CSPRNG being used,
/// or a flaw in the implementation, occasionally reseeding should make
/// exploiting it much more difficult or even impossible.
///
/// Use [`ReseedingRng::new`] with a `threshold` of `0` to disable reseeding
/// after a fixed number of generated bytes.
///
/// # Error handling
///
/// Although unlikely, reseeding the wrapped PRNG can fail. `ReseedingRng` will
/// never panic but try to handle the error intelligently through some
/// combination of retrying and delaying reseeding until later.
/// If handling the source error fails `ReseedingRng` will continue generating
/// data from the wrapped PRNG without reseeding.
///
/// Manually calling [`reseed()`] will not have this retry or delay logic, but
/// reports the error.
///
/// # Example
///
/// ```
/// # extern crate rand;
/// # extern crate rand_chacha;
/// # fn main() {
/// use rand::prelude::*;
/// use rand_chacha::ChaChaCore; // Internal part of ChaChaRng that
///                              // implements BlockRngCore
/// use rand::rngs::OsRng;
/// use rand::rngs::adapter::ReseedingRng;
///
/// let prng = ChaChaCore::from_entropy();
// FIXME: it is better to use EntropyRng as reseeder, but that doesn't implement
// clone yet.
/// let reseeder = OsRng::new().unwrap();
/// let mut reseeding_rng = ReseedingRng::new(prng, 0, reseeder);
///
/// println!("{}", reseeding_rng.gen::<u64>());
///
/// let mut cloned_rng = reseeding_rng.clone();
/// assert!(reseeding_rng.gen::<u64>() != cloned_rng.gen::<u64>());
/// # }
/// ```
///
/// [`ChaChaCore`]: rand_chacha::ChaChaCore
/// [`Hc128Core`]: rand_hc::Hc128Core
/// [`BlockRngCore`]: rand_core::block::BlockRngCore
/// [`ReseedingRng::new`]: ReseedingRng::new
/// [`reseed()`]: ReseedingRng::reseed
#[derive(Debug)]
pub struct ReseedingRng<R, Rsdr>(BlockRng<ReseedingCore<R, Rsdr>>)
where R: BlockRngCore + SeedableRng,
      Rsdr: RngCore;

impl<R, Rsdr> ReseedingRng<R, Rsdr>
where R: BlockRngCore + SeedableRng,
      Rsdr: RngCore
{
    /// Create a new `ReseedingRng` from an existing PRNG, combined with a RNG
    /// to use as reseeder.
    ///
    /// `threshold` sets the number of generated bytes after which to reseed the
    /// PRNG. Set it to zero to never reseed based on the number of generated
    /// values.
    pub fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
        ReseedingRng(BlockRng::new(ReseedingCore::new(rng, threshold, reseeder)))
    }

    /// Reseed the internal PRNG.
    pub fn reseed(&mut self) -> Result<(), Error> {
        self.0.core.reseed()
    }
}

// TODO: this should be implemented for any type where the inner type
// implements RngCore, but we can't specify that because ReseedingCore is private
impl<R, Rsdr: RngCore> RngCore for ReseedingRng<R, Rsdr>
where R: BlockRngCore<Item = u32> + SeedableRng,
    <R as BlockRngCore>::Results: AsRef<[u32]> + AsMut<[u32]>
{
    #[inline(always)]
    fn next_u32(&mut self) -> u32 {
        self.0.next_u32()
    }

    #[inline(always)]
    fn next_u64(&mut self) -> u64 {
        self.0.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.0.fill_bytes(dest)
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.0.try_fill_bytes(dest)
    }
}

impl<R, Rsdr> Clone for ReseedingRng<R, Rsdr>
where R: BlockRngCore + SeedableRng + Clone,
      Rsdr: RngCore + Clone
{
    fn clone(&self) -> ReseedingRng<R, Rsdr> {
        // Recreating `BlockRng` seems easier than cloning it and resetting
        // the index.
        ReseedingRng(BlockRng::new(self.0.core.clone()))
    }
}

impl<R, Rsdr> CryptoRng for ReseedingRng<R, Rsdr>
where R: BlockRngCore + SeedableRng + CryptoRng,
      Rsdr: RngCore + CryptoRng {}

#[derive(Debug)]
struct ReseedingCore<R, Rsdr> {
    inner: R,
    reseeder: Rsdr,
    threshold: i64,
    bytes_until_reseed: i64,
    fork_counter: usize,
}

impl<R, Rsdr> BlockRngCore for ReseedingCore<R, Rsdr>
where R: BlockRngCore + SeedableRng,
      Rsdr: RngCore
{
    type Item = <R as BlockRngCore>::Item;
    type Results = <R as BlockRngCore>::Results;

    fn generate(&mut self, results: &mut Self::Results) {
        let global_fork_counter = fork::get_fork_counter();
        if self.bytes_until_reseed <= 0 ||
           self.is_forked(global_fork_counter) {
            // We get better performance by not calling only `reseed` here
            // and continuing with the rest of the function, but by directly
            // returning from a non-inlined function.
            return self.reseed_and_generate(results, global_fork_counter);
        }
        let num_bytes = results.as_ref().len() * size_of::<Self::Item>();
        self.bytes_until_reseed -= num_bytes as i64;
        self.inner.generate(results);
    }
}

impl<R, Rsdr> ReseedingCore<R, Rsdr>
where R: BlockRngCore + SeedableRng,
      Rsdr: RngCore
{
    /// Create a new `ReseedingCore`.
    fn new(rng: R, threshold: u64, reseeder: Rsdr) -> Self {
        use ::core::i64::MAX;
        fork::register_fork_handler();

        // Because generating more values than `i64::MAX` takes centuries on
        // current hardware, we just clamp to that value.
        // Also we set a threshold of 0, which indicates no limit, to that
        // value.
        let threshold =
            if threshold == 0 { MAX }
            else if threshold <= MAX as u64 { threshold as i64 }
            else { MAX };

        ReseedingCore {
            inner: rng,
            reseeder,
            threshold: threshold as i64,
            bytes_until_reseed: threshold as i64,
            fork_counter: 0,
        }
    }

    /// Reseed the internal PRNG.
    fn reseed(&mut self) -> Result<(), Error> {
        R::from_rng(&mut self.reseeder).map(|result| {
            self.bytes_until_reseed = self.threshold;
            self.inner = result
        })
    }

    fn is_forked(&self, global_fork_counter: usize) -> bool {
        // In theory, on 32-bit platforms, it is possible for
        // `global_fork_counter` to wrap around after ~4e9 forks.
        //
        // This check will detect a fork in the normal case where
        // `fork_counter < global_fork_counter`, and also when the difference
        // between both is greater than `isize::MAX` (wrapped around).
        //
        // It will still fail to detect a fork if there have been more than
        // `isize::MAX` forks, without any reseed in between. Seems unlikely
        // enough.
        (self.fork_counter.wrapping_sub(global_fork_counter) as isize) < 0
    }

    #[inline(never)]
    fn reseed_and_generate(&mut self,
                           results: &mut <Self as BlockRngCore>::Results,
                           global_fork_counter: usize)
    {
        if self.is_forked(global_fork_counter) {
            info!("Fork detected, reseeding RNG");
        } else {
            trace!("Reseeding RNG (periodic reseed)");
        }

        let num_bytes =
            results.as_ref().len() * size_of::<<R as BlockRngCore>::Item>();

        let threshold = if let Err(e) = self.reseed() {
            let delay = match e.kind {
                ErrorKind::Transient => num_bytes as i64,
                kind @ _ if kind.should_retry() => self.threshold >> 8,
                _ => self.threshold,
            };
            warn!("Reseeding RNG delayed reseeding by {} bytes due to \
                   error from source: {}", delay, e);
            delay
        } else {
            self.fork_counter = global_fork_counter;
            self.threshold
        };

        self.bytes_until_reseed = threshold - num_bytes as i64;
        self.inner.generate(results);
    }
}

impl<R, Rsdr> Clone for ReseedingCore<R, Rsdr>
where R: BlockRngCore + SeedableRng + Clone,
      Rsdr: RngCore + Clone
{
    fn clone(&self) -> ReseedingCore<R, Rsdr> {
        ReseedingCore {
            inner: self.inner.clone(),
            reseeder: self.reseeder.clone(),
            threshold: self.threshold,
            bytes_until_reseed: 0, // reseed clone on first use
            fork_counter: self.fork_counter,
        }
    }
}

impl<R, Rsdr> CryptoRng for ReseedingCore<R, Rsdr>
where R: BlockRngCore + SeedableRng + CryptoRng,
      Rsdr: RngCore + CryptoRng {}


#[cfg(all(feature="std", unix, not(target_os="emscripten")))]
mod fork {
    extern crate libc;

    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
    use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};

    // Fork protection
    //
    // We implement fork protection on Unix using `pthread_atfork`.
    // When the process is forked, we increment `RESEEDING_RNG_FORK_COUNTER`.
    // Every `ReseedingRng` stores the last known value of the static in
    // `fork_counter`. If the cached `fork_counter` is less than
    // `RESEEDING_RNG_FORK_COUNTER`, it is time to reseed this RNG.
    //
    // If reseeding fails, we don't deal with this by setting a delay, but just
    // don't update `fork_counter`, so a reseed is attempted as soon as
    // possible.

    static RESEEDING_RNG_FORK_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;

    pub fn get_fork_counter() -> usize {
        RESEEDING_RNG_FORK_COUNTER.load(Ordering::Relaxed)
    }

    static FORK_HANDLER_REGISTERED: AtomicBool = ATOMIC_BOOL_INIT;

    extern fn fork_handler() {
        // Note: fetch_add is defined to wrap on overflow
        // (which is what we want).
        RESEEDING_RNG_FORK_COUNTER.fetch_add(1, Ordering::Relaxed);
    }

    pub fn register_fork_handler() {
        if FORK_HANDLER_REGISTERED.load(Ordering::Relaxed) == false {
            unsafe { libc::pthread_atfork(None, None, Some(fork_handler)) };
            FORK_HANDLER_REGISTERED.store(true, Ordering::Relaxed);
        }
    }
}

#[cfg(not(all(feature="std", unix, not(target_os="emscripten"))))]
mod fork {
    pub fn get_fork_counter() -> usize { 0 }
    pub fn register_fork_handler() {}
}


#[cfg(test)]
mod test {
    use {Rng, SeedableRng};
    use rand_chacha::ChaChaCore;
    use rngs::mock::StepRng;
    use super::ReseedingRng;

    #[test]
    fn test_reseeding() {
        let mut zero = StepRng::new(0, 0);
        let rng = ChaChaCore::from_rng(&mut zero).unwrap();
        let mut reseeding = ReseedingRng::new(rng, 32*4, zero);

        // Currently we only support for arrays up to length 32.
        // TODO: cannot generate seq via Rng::gen because it uses different alg
        let mut buf = [0u32; 32]; // Needs to be a multiple of the RNGs result
                                  // size to test exactly.
        reseeding.fill(&mut buf);
        let seq = buf;
        for _ in 0..10 {
            reseeding.fill(&mut buf);
            assert_eq!(buf, seq);
        }
    }

    #[test]
    fn test_clone_reseeding() {
        let mut zero = StepRng::new(0, 0);
        let rng = ChaChaCore::from_rng(&mut zero).unwrap();
        let mut rng1 = ReseedingRng::new(rng, 32*4, zero);

        let first: u32 = rng1.gen();
        for _ in 0..10 { let _ = rng1.gen::<u32>(); }

        let mut rng2 = rng1.clone();
        assert_eq!(first, rng2.gen::<u32>());
    }
}
