@@ -830,8 +830,7 @@ pub trait NewRng: SeedableRng {
830
830
#[ cfg( feature="std" ) ]
831
831
impl < R : SeedableRng > NewRng for R {
832
832
fn new ( ) -> Result < Self , Error > {
833
- let mut source = EntropySource :: new ( ) ?;
834
- R :: from_rng ( & mut source)
833
+ R :: from_rng ( EntropyRng :: new ( ) )
835
834
}
836
835
}
837
836
@@ -929,15 +928,14 @@ pub fn weak_rng() -> XorShiftRng {
929
928
#[ cfg( feature="std" ) ]
930
929
#[ derive( Clone , Debug ) ]
931
930
pub struct ThreadRng {
932
- rng : Rc < RefCell < ReseedingRng < StdRng , EntropySource > > > ,
931
+ rng : Rc < RefCell < ReseedingRng < StdRng , EntropyRng > > > ,
933
932
}
934
933
935
934
#[ cfg( feature="std" ) ]
936
935
thread_local ! (
937
- static THREAD_RNG_KEY : Rc <RefCell <ReseedingRng <StdRng , EntropySource >>> = {
936
+ static THREAD_RNG_KEY : Rc <RefCell <ReseedingRng <StdRng , EntropyRng >>> = {
938
937
const THREAD_RNG_RESEED_THRESHOLD : u64 = 32_768 ;
939
- let mut entropy_source = EntropySource :: new( )
940
- . expect( "could not initialize thread_rng" ) ;
938
+ let mut entropy_source = EntropyRng :: new( ) ;
941
939
let r = StdRng :: from_rng( & mut entropy_source)
942
940
. expect( "could not initialize thread_rng" ) ;
943
941
let rng = ReseedingRng :: new( r,
@@ -985,49 +983,42 @@ impl Rng for ThreadRng {
985
983
986
984
/// An RNG provided specifically for seeding PRNG's.
987
985
///
988
- /// `EntropySource` uses the interface for random numbers provided by the
989
- /// operating system (`OsRng`). If that returns an error, it will fall back to
990
- /// the `JitterRng` entropy collector. Occasionally it will then check if
991
- /// `OsRng` is still not available, and switch back if possible.
986
+ /// `EntropyRng` uses the interface for random numbers provided by the operating
987
+ /// system ([`OsRng`]). If that returns an error, it will fall back to the
988
+ /// [`JitterRng`] entropy collector. Occasionally it will then check if `OsRng`
989
+ /// is still not available, and switch back if possible.
990
+ ///
991
+ /// [`OsRng`]: os/struct.OsRng.html
992
+ /// [`JitterRng`]: jitter/struct.JitterRng.html
992
993
#[ cfg( feature="std" ) ]
993
994
#[ derive( Debug ) ]
994
- pub struct EntropySource {
995
- rng : EntropySourceInner ,
995
+ pub struct EntropyRng {
996
+ rng : EntropySource ,
996
997
counter : u32 ,
997
998
}
998
999
999
1000
#[ cfg( feature="std" ) ]
1000
1001
#[ derive( Debug ) ]
1001
- enum EntropySourceInner {
1002
+ enum EntropySource {
1002
1003
Os ( OsRng ) ,
1003
1004
Jitter ( JitterRng ) ,
1005
+ None ,
1004
1006
}
1005
1007
1006
1008
#[ cfg( feature="std" ) ]
1007
- impl EntropySource {
1008
- pub fn new ( ) -> Result < Self , Error > {
1009
- match OsRng :: new ( ) {
1010
- Ok ( r) =>
1011
- Ok ( EntropySource { rng : EntropySourceInner :: Os ( r) ,
1012
- counter : 0u32 } ) ,
1013
- Err ( e1) => {
1014
- match JitterRng :: new ( ) {
1015
- Ok ( r) =>
1016
- Ok ( EntropySource { rng : EntropySourceInner :: Jitter ( r) ,
1017
- counter : 0 } ) ,
1018
- Err ( _) =>
1019
- Err ( Error :: with_cause (
1020
- ErrorKind :: Unavailable ,
1021
- "Both OS and Jitter entropy sources are unavailable" ,
1022
- e1) )
1023
- }
1024
- }
1025
- }
1009
+ impl EntropyRng {
1010
+ /// Create a new `EntropyRng`.
1011
+ ///
1012
+ /// This method will do no system calls or other initialization routines,
1013
+ /// those are done on first use. This is done to make `new` infallible,
1014
+ /// and `try_fill_bytes` the only place to report errors.
1015
+ pub fn new ( ) -> Self {
1016
+ EntropyRng { rng : EntropySource :: None , counter : 0u32 }
1026
1017
}
1027
1018
}
1028
1019
1029
1020
#[ cfg( feature="std" ) ]
1030
- impl Rng for EntropySource {
1021
+ impl Rng for EntropyRng {
1031
1022
fn next_u32 ( & mut self ) -> u32 {
1032
1023
impls:: next_u32_via_fill ( self )
1033
1024
}
@@ -1041,45 +1032,66 @@ impl Rng for EntropySource {
1041
1032
}
1042
1033
1043
1034
fn try_fill_bytes ( & mut self , dest : & mut [ u8 ] ) -> Result < ( ) , Error > {
1035
+ fn try_os_new ( dest : & mut [ u8 ] ) -> Result < OsRng , Error >
1036
+ {
1037
+ let mut rng = OsRng :: new ( ) ?;
1038
+ rng. try_fill_bytes ( dest) ?;
1039
+ Ok ( rng)
1040
+ }
1041
+
1042
+ fn try_jitter_new ( dest : & mut [ u8 ] ) -> Result < JitterRng , Error >
1043
+ {
1044
+ let mut rng = JitterRng :: new ( ) ?;
1045
+ rng. try_fill_bytes ( dest) ?;
1046
+ Ok ( rng)
1047
+ }
1048
+
1044
1049
let mut switch_rng = None ;
1045
- let mut result;
1046
1050
match self . rng {
1047
- EntropySourceInner :: Os ( ref mut rng) => {
1048
- result = rng. try_fill_bytes ( dest) ;
1049
- if result. is_err ( ) {
1050
- // Fall back to JitterRng.
1051
- let mut rng2_result = JitterRng :: new ( ) ;
1052
- if let Ok ( mut rng2) = rng2_result {
1053
- result = rng2. try_fill_bytes ( dest) ; // Can't fail
1054
- switch_rng = Some ( EntropySourceInner :: Jitter ( rng2) ) ;
1051
+ EntropySource :: None => {
1052
+ let os_rng_result = try_os_new ( dest) ;
1053
+ match os_rng_result {
1054
+ Ok ( os_rng) => {
1055
+ switch_rng = Some ( EntropySource :: Os ( os_rng) ) ;
1055
1056
}
1056
- }
1057
- }
1058
- EntropySourceInner :: Jitter ( ref mut rng) => {
1059
- if self . counter < 8 {
1060
- result = rng. try_fill_bytes ( dest) ; // use JitterRng
1061
- self . counter = ( self . counter + 1 ) % 8 ;
1062
- } else {
1063
- // Try if OsRng is still unavailable
1064
- let os_rng_result = OsRng :: new ( ) ;
1065
- if let Ok ( mut os_rng) = os_rng_result {
1066
- result = os_rng. try_fill_bytes ( dest) ;
1067
- if result. is_ok ( ) {
1068
- switch_rng = Some ( EntropySourceInner :: Os ( os_rng) ) ;
1057
+ Err ( os_rng_error) => {
1058
+ if let Ok ( jitter_rng) = try_jitter_new ( dest) {
1059
+ switch_rng = Some ( EntropySource :: Jitter ( jitter_rng) ) ;
1069
1060
} else {
1070
- result = rng . try_fill_bytes ( dest ) ; // use JitterRng
1061
+ return Err ( os_rng_error ) ;
1071
1062
}
1063
+ }
1064
+ }
1065
+ }
1066
+ EntropySource :: Os ( ref mut rng) => {
1067
+ let os_rng_result = rng. try_fill_bytes ( dest) ;
1068
+ if os_rng_result. is_err ( ) {
1069
+ if let Ok ( jitter_rng) = try_jitter_new ( dest) {
1070
+ switch_rng = Some ( EntropySource :: Jitter ( jitter_rng) ) ;
1072
1071
} else {
1073
- result = rng . try_fill_bytes ( dest ) ; // use JitterRng
1072
+ return os_rng_result ;
1074
1073
}
1075
1074
}
1076
1075
}
1076
+ EntropySource :: Jitter ( ref mut rng) => {
1077
+ if self . counter >= 8 {
1078
+ if let Ok ( os_rng) = try_os_new ( dest) {
1079
+ switch_rng = Some ( EntropySource :: Os ( os_rng) ) ;
1080
+ } else {
1081
+ self . counter = ( self . counter + 1 ) % 8 ;
1082
+ return rng. try_fill_bytes ( dest) ; // use JitterRng
1083
+ }
1084
+ } else {
1085
+ self . counter = ( self . counter + 1 ) % 8 ;
1086
+ return rng. try_fill_bytes ( dest) ; // use JitterRng
1087
+ }
1088
+ }
1077
1089
}
1078
1090
if let Some ( rng) = switch_rng {
1079
1091
self . rng = rng;
1080
1092
self . counter = 0 ;
1081
1093
}
1082
- result
1094
+ Ok ( ( ) )
1083
1095
}
1084
1096
}
1085
1097
0 commit comments