Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
6783afcc
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6783afcc
编写于
11月 06, 2014
作者:
A
Alex Crichton
浏览文件
操作
浏览文件
下载
差异文件
rollup merge of #18664 : klutzy/getrandom
上级
fa530fff
fdf5195f
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
120 addition
and
12 deletion
+120
-12
src/libstd/rand/mod.rs
src/libstd/rand/mod.rs
+6
-2
src/libstd/rand/os.rs
src/libstd/rand/os.rs
+114
-10
未找到文件。
src/libstd/rand/mod.rs
浏览文件 @
6783afcc
...
...
@@ -45,8 +45,12 @@
//! so the "quality" of `/dev/random` is not better than `/dev/urandom` in most cases.
//! However, this means that `/dev/urandom` can yield somewhat predictable randomness
//! if the entropy pool is very small, such as immediately after first booting.
//! If an application likely to be run soon after first booting, or on a system with very
//! few entropy sources, one should consider using `/dev/random` via `ReaderRng`.
//! Linux 3,17 added `getrandom(2)` system call which solves the issue: it blocks if entropy
//! pool is not initialized yet, but it does not block once initialized.
//! `OsRng` tries to use `getrandom(2)` if available, and use `/dev/urandom` fallback if not.
//! If an application does not have `getrandom` and likely to be run soon after first booting,
//! or on a system with very few entropy sources, one should consider using `/dev/random` via
//! `ReaderRng`.
//! - On some systems (e.g. FreeBSD, OpenBSD and Mac OS X) there is no difference
//! between the two sources. (Also note that, on some systems e.g. FreeBSD, both `/dev/random`
//! and `/dev/urandom` may block once if the CSPRNG has not seeded yet.)
...
...
src/libstd/rand/os.rs
浏览文件 @
6783afcc
...
...
@@ -15,45 +15,149 @@
#[cfg(all(unix,
not(target_os
=
"ios"
)))]
mod
imp
{
extern
crate
libc
;
use
io
::{
IoResult
,
File
};
use
path
::
Path
;
use
rand
::
Rng
;
use
rand
::
reader
::
ReaderRng
;
use
result
::{
Ok
,
Err
};
use
slice
::{
ImmutableSlice
,
MutableSlice
};
use
mem
;
use
os
::
errno
;
#[cfg(all(target_os
=
"linux"
,
any(target_arch
=
"x86_64"
,
target_arch
=
"x86"
,
target_arch
=
"arm"
)))]
fn
getrandom
(
buf
:
&
mut
[
u8
])
->
libc
::
c_long
{
extern
"C"
{
fn
syscall
(
number
:
libc
::
c_long
,
...
)
->
libc
::
c_long
;
}
#[cfg(target_arch
=
"x86_64"
)]
const
NR_GETRANDOM
:
libc
::
c_long
=
318
;
#[cfg(target_arch
=
"x86"
)]
const
NR_GETRANDOM
:
libc
::
c_long
=
355
;
#[cfg(target_arch
=
"arm"
)]
const
NR_GETRANDOM
:
libc
::
c_long
=
384
;
unsafe
{
syscall
(
NR_GETRANDOM
,
buf
.as_mut_ptr
(),
buf
.len
(),
0u
)
}
}
#[cfg(not(all(target_os
=
"linux"
,
any(target_arch
=
"x86_64"
,
target_arch
=
"x86"
,
target_arch
=
"arm"
))))]
fn
getrandom
(
_
buf
:
&
mut
[
u8
])
->
libc
::
c_long
{
-
1
}
fn
getrandom_fill_bytes
(
v
:
&
mut
[
u8
])
{
let
mut
read
=
0
;
let
len
=
v
.len
();
while
read
<
len
{
let
result
=
getrandom
(
v
[
mut
read
..
]);
if
result
==
-
1
{
let
err
=
errno
()
as
libc
::
c_int
;
if
err
==
libc
::
EINTR
{
continue
;
}
else
{
panic!
(
"unexpected getrandom error: {}"
,
err
);
}
}
else
{
read
+=
result
as
uint
;
}
}
}
fn
getrandom_next_u32
()
->
u32
{
let
mut
buf
:
[
u8
,
..
4
]
=
[
0u8
,
..
4
];
getrandom_fill_bytes
(
&
mut
buf
);
unsafe
{
mem
::
transmute
::
<
[
u8
,
..
4
],
u32
>
(
buf
)
}
}
fn
getrandom_next_u64
()
->
u64
{
let
mut
buf
:
[
u8
,
..
8
]
=
[
0u8
,
..
8
];
getrandom_fill_bytes
(
&
mut
buf
);
unsafe
{
mem
::
transmute
::
<
[
u8
,
..
8
],
u64
>
(
buf
)
}
}
#[cfg(all(target_os
=
"linux"
,
any(target_arch
=
"x86_64"
,
target_arch
=
"x86"
,
target_arch
=
"arm"
)))]
fn
is_getrandom_available
()
->
bool
{
use
sync
::
atomic
::{
AtomicBool
,
INIT_ATOMIC_BOOL
,
Relaxed
};
static
GETRANDOM_CHECKED
:
AtomicBool
=
INIT_ATOMIC_BOOL
;
static
GETRANDOM_AVAILABLE
:
AtomicBool
=
INIT_ATOMIC_BOOL
;
if
!
GETRANDOM_CHECKED
.load
(
Relaxed
)
{
let
mut
buf
:
[
u8
,
..
0
]
=
[];
let
result
=
getrandom
(
&
mut
buf
);
let
available
=
if
result
==
-
1
{
let
err
=
errno
()
as
libc
::
c_int
;
err
!=
libc
::
ENOSYS
}
else
{
true
};
GETRANDOM_AVAILABLE
.store
(
available
,
Relaxed
);
GETRANDOM_CHECKED
.store
(
true
,
Relaxed
);
available
}
else
{
GETRANDOM_AVAILABLE
.load
(
Relaxed
)
}
}
#[cfg(not(all(target_os
=
"linux"
,
any(target_arch
=
"x86_64"
,
target_arch
=
"x86"
,
target_arch
=
"arm"
))))]
fn
is_getrandom_available
()
->
bool
{
false
}
/// A random number generator that retrieves randomness straight from
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`.
/// `/dev/urandom`
, or from `getrandom(2)` system call if available
.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
/// This does not block.
#[cfg(unix)]
pub
struct
OsRng
{
inner
:
ReaderRng
<
File
>
inner
:
OsRngInner
,
}
enum
OsRngInner
{
OsGetrandomRng
,
OsReaderRng
(
ReaderRng
<
File
>
),
}
impl
OsRng
{
/// Create a new `OsRng`.
pub
fn
new
()
->
IoResult
<
OsRng
>
{
if
is_getrandom_available
()
{
return
Ok
(
OsRng
{
inner
:
OsGetrandomRng
});
}
let
reader
=
try!
(
File
::
open
(
&
Path
::
new
(
"/dev/urandom"
)));
let
reader_rng
=
ReaderRng
::
new
(
reader
);
Ok
(
OsRng
{
inner
:
reader_rng
})
Ok
(
OsRng
{
inner
:
OsReaderRng
(
reader_rng
)
})
}
}
impl
Rng
for
OsRng
{
fn
next_u32
(
&
mut
self
)
->
u32
{
self
.inner
.next_u32
()
match
self
.inner
{
OsGetrandomRng
=>
getrandom_next_u32
(),
OsReaderRng
(
ref
mut
rng
)
=>
rng
.next_u32
(),
}
}
fn
next_u64
(
&
mut
self
)
->
u64
{
self
.inner
.next_u64
()
match
self
.inner
{
OsGetrandomRng
=>
getrandom_next_u64
(),
OsReaderRng
(
ref
mut
rng
)
=>
rng
.next_u64
(),
}
}
fn
fill_bytes
(
&
mut
self
,
v
:
&
mut
[
u8
])
{
self
.inner
.fill_bytes
(
v
)
match
self
.inner
{
OsGetrandomRng
=>
getrandom_fill_bytes
(
v
),
OsReaderRng
(
ref
mut
rng
)
=>
rng
.fill_bytes
(
v
)
}
}
}
}
...
...
@@ -75,7 +179,7 @@ mod imp {
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`.
/// `/dev/urandom`
, or from `getrandom(2)` system call if available
.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
...
...
@@ -145,10 +249,10 @@ mod imp {
/// the operating system. Platform sources:
///
/// - Unix-like systems (Linux, Android, Mac OSX): read directly from
/// `/dev/urandom`.
/// `/dev/urandom`
, or from `getrandom(2)` system call if available
.
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
/// service provider with the `PROV_RSA_FULL` type.
///
///
- iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
/// This does not block.
pub
struct
OsRng
{
hcryptprov
:
HCRYPTPROV
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录