forked from rust-random/rand
-
Notifications
You must be signed in to change notification settings - Fork 2
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
Commits on Nov 4, 2017
-
Implement
JitterRng
, based onjitterentropy-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.
Configuration menu - View commit details
-
Copy full SHA for 07e1d58 - Browse repository at this point
Copy the full SHA 07e1d58View commit details -
> 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.
Configuration menu - View commit details
-
Copy full SHA for 6e40910 - Browse repository at this point
Copy the full SHA 6e40910View commit details
Commits on Nov 8, 2017
-
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
Configuration menu - View commit details
-
Copy full SHA for 49e9bb0 - Browse repository at this point
Copy the full SHA 49e9bb0View commit details -
Configuration menu - View commit details
-
Copy full SHA for ed358de - Browse repository at this point
Copy the full SHA ed358deView commit details -
Configuration menu - View commit details
-
Copy full SHA for c57aa1a - Browse repository at this point
Copy the full SHA c57aa1aView commit details
Commits on Nov 11, 2017
-
Configuration menu - View commit details
-
Copy full SHA for 08dc010 - Browse repository at this point
Copy the full SHA 08dc010View commit details -
Configuration menu - View commit details
-
Copy full SHA for 14136e7 - Browse repository at this point
Copy the full SHA 14136e7View commit details
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.