Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement JitterRng, based on jitterentropy-library. #28

Merged
merged 7 commits into from
Nov 17, 2017

Commits on Nov 4, 2017

  1. Implement JitterRng, based on jitterentropy-library.

    This is a pretty direct translation from C to Rust.
    
    Some notes per function:
    
    ### `random_loop_cnt` (`jent_loop_shuffle`)
    Because the `min` argument was always `0`, I removed that argument.
    
    The C code did not seem to fold the time optimally. When `bits` is set to `7`,
    as `mem_access` does, it will fold `64 / 7 = 9` times, leaving 1 bit unused. It
    is minor, but we use `folds = (64 + n_bits - 1) / n_bits;`, so all is used.
    
    We do not add 1 to the resulting loop count, this should be done in the calling
    code. `memaccess` already adds 128 anyway. For `lfsr_time` we use the loop count
    on a `throw_away` value, and then run the real calculation once.
    
    
    ### `lfsr_time` (`jent_lfsr_time`)
    We do not allow overriding `loop_cnt`, and also do not return the actual
    `loop_cnt` used. This only had some use in testing the C code, but was 'not
    needed during runtime'.
    
    Only the last round of the outer loop (in C) effect `self.data`. In Rust the
    inner loop is part of the `lfsr` helper function. All but the last round operate
    on a `throw_away` function, that does not get reset between the loop rounds.
    
    ### `memaccess` (`jent_memaccess`)
    We do not allow overriding `loop_cnt`, and also do not return the actual
    `loop_cnt` used. This only had some use in testing the C code, but was 'not
    needed during runtime'.
    
    We do not do NULL pointer checks, and running `JitterRng` without the Memory
    Access noise source is (currently) not supported.
    
    We (currently) do not support changing `memblocksize` and `memblocks` except by
    changing the constants `MEMORY_BLOCKS` and `MEMORY_BLOCKSIZE`. So instead of
    recalculating `wrap`, we can just re-use MEMORY_SIZE.
    
    Instead of a `memlocation` pointer we use indexing. The `index` is calculated
    before accessing `self.mem[index] instead of after. This convinces the compiler
    indexing is safe, and eliminates bounds checks.
    
    
    ### `stuck` (`jent_stuck`)
    For all delta's we use an `i64`, instead of an `u64` for the first delta in the
    C implementation. This handles a clock that may not be entirely monotonic (for
    example due to NTP) slightly better.
    
    Also, we return a `bool` instead of an `u64`.
    
    
    ### `measure_jitter` (`jent_measure_jitter`)
    It seemed clearer here to not return an `u64` or `bool`, but `Option<()>`.
    `Some` and `None` indicate clearly whether we have been able to add some
    entropy.
    
    For `current_delta` we use an `i64` instead of an `u64`. It is cast back to an
    `u64` for `lfsr_time`, which only cares about bits.
    
    
    ### `stir_pool` (`jent_stir_pool`)
    The C code does something difficult with initializing an `u64` with two `u32`'s
    in an `union`. The numbers it uses for initialization are from SHA-1, and the
    order does not really matter. The Rust code just sets the `u64`'s directly, and
    uses the constants in the order they appear in FIPS 180-4 section 5.3.1.
    
    The function tries to be constant time to prevent leaking timing information
    about the generated random number. Using a `trow_away` value like it does is
    optimised out, and I don't trust branches to be constant time. I used a bit mask
    trick instead, and verified the assembly does not include anything conditional.
    Not sure it matters anything, we just went through a lot of effort to have as
    much timing variance as possible to generate the random number.
    
    
    ### `gen_entropy` (`jent_gen_entropy`)
    We do not support oversampling, so no need to repeat the loop more times.
    
    `self.memaccess()` in `measure_jitter` is easily optimised out, because LLVM
    recognises we never read the results. Therefore we do a single read from
    `self.mem`, hidden to the optimizer with `black_box()`.
    
    We return `self.data`  instead of requiring the calling code to read from it.
    
    ### (not included) `jent_read_entropy`
    Here we have the convienent `fill_bytes_via_u64` for.
    
    The C code calls `jent_gen_entropy` one last time after filling the buffer, to
    make sure that something reading the processes memory can not read the last
    generated random number. 'This call reduces the speed of the RNG by up to half`.
    It seems to me setting it to 0 is just as good.
    
    I did not bother with this. As an alternative a user caring very much about this
    can just call `next_u64` after receiving a result.
    
    
    ### `entropy_init` (`jent_entropy_init`)
    Wrap `lfsr_time` in the loop in a `black_box` to make sure it is not optimised
    out.
    
    For delta we use an `i64` instead of an `u64`.
    
    Instead of `lowdelta` we just use `delta`. It seems a hack to compile on some
    32-bit architectures.
    pitdicker committed Nov 4, 2017
    Configuration menu
    Copy the full SHA
    07e1d58 View commit details
    Browse the repository at this point in the history
  2. Relicensing permission

    > One question about the license. All libraries in the Rust ecosystem try
    > to be dual-licensed with the permissive Apache 2.0 license and the MIT
    > license. I am not sure it is ok for me to do so, because your code used
    > the 3-clause BSD. The difference seems to be in the third clause: "The
    > name of the author may not be used to endorse or promote products
    > derived from this software without specific prior written permission."
    > Can you maybe give permission to license this Rust translation under the
    > MIT license?
    
    Granted. I am fine with the mentioned license as long as there is a reference
    to my code.
    pitdicker committed Nov 4, 2017
    Configuration menu
    Copy the full SHA
    6e40910 View commit details
    Browse the repository at this point in the history

Commits on Nov 8, 2017

  1. Provide statistics function

    Add the function `timer_stats` (`jent_lfsr_var_stat` in C). Like in other the
    other functions we use a `int64` to represent a time delta instead of a `u64`.
    
    Instead of the `min` variable to indicate how many times the noice source loops
    should run at least, we use a `var_rounds` boolean. Setting `min` seems like an
    historic leftover, and does not fit `memaccess`. A simple bool covers everything
    needed for testing. This effects `timer_stats`, `lfsr_time` and `memaccess`.
    
    It is useful to be able to run the statistics function, even when initializing
    `JitterRng` might fail because of the `test_timer` function. Therefore
    `new_with_timer` does not automatically test the timer jitter, and expects the
    user code to do so.
    
    Now that `new_with_timer` calls `gen_entropy`, it was possible to move
    `black_box(ec.mem[0])` here instead of `measure_jitter`, so it is executed even
    less.
    
    # Conflicts:
    #	src/jitter_rng.rs
    pitdicker committed Nov 8, 2017
    Configuration menu
    Copy the full SHA
    49e9bb0 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    ed358de View commit details
    Browse the repository at this point in the history
  3. Address review comments

    pitdicker committed Nov 8, 2017
    Configuration menu
    Copy the full SHA
    c57aa1a View commit details
    Browse the repository at this point in the history

Commits on Nov 11, 2017

  1. Configuration menu
    Copy the full SHA
    08dc010 View commit details
    Browse the repository at this point in the history
  2. Fix no_std errors

    pitdicker committed Nov 11, 2017
    Configuration menu
    Copy the full SHA
    14136e7 View commit details
    Browse the repository at this point in the history