Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
btwise
OpenCorePKG_MOD
提交
50e5878e
O
OpenCorePKG_MOD
项目概览
btwise
/
OpenCorePKG_MOD
通知
26
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
OpenCorePKG_MOD
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
50e5878e
编写于
1月 07, 2020
作者:
V
vit9696
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
OcRngLib: Implement CPRNG based on ChaCha seeded via RDRAND or jitter
上级
b2f85d51
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
326 addition
and
112 deletion
+326
-112
Include/Library/OcRngLib.h
Include/Library/OcRngLib.h
+6
-0
Library/OcRngLib/OcRngInternals.h
Library/OcRngLib/OcRngInternals.h
+81
-0
Library/OcRngLib/OcRngLib.c
Library/OcRngLib/OcRngLib.c
+182
-112
Library/OcRngLib/OcRngLib.inf
Library/OcRngLib/OcRngLib.inf
+5
-0
Library/OcRngLib/X64/RngDelay.nasm
Library/OcRngLib/X64/RngDelay.nasm
+52
-0
未找到文件。
Include/Library/OcRngLib.h
浏览文件 @
50e5878e
...
...
@@ -19,6 +19,8 @@
/**
Generates a 16-bit pseudo random number.
This generator is still guaranteed to be cryptographically secure
by the use of CPRNG with entropy.
@retval 16-bit pseudo random number.
**/
...
...
@@ -30,6 +32,8 @@ GetPseudoRandomNumber16 (
/**
Generates a 32-bit pseudo random number.
This generator is still guaranteed to be cryptographically secure
by the use of CPRNG with entropy.
@retval 32-bit pseudo random number.
**/
...
...
@@ -41,6 +45,8 @@ GetPseudoRandomNumber32 (
/**
Generates a 64-bit pseudo random number.
This generator is still guaranteed to be cryptographically secure
by the use of CPRNG with entropy.
@retval 64-bit pseudo random number.
**/
...
...
Library/OcRngLib/OcRngInternals.h
0 → 100644
浏览文件 @
50e5878e
/** @file
Copyright (C) 2020, vit9696. All rights reserved.
All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef OC_RNG_INTERNALS_H
#define OC_RNG_INTERNALS_H
#include <Library/OcCryptoLib.h>
/**
Performs delay on target platform to cause microoperating scheduling
and introduce timing entropy.
@param[in] Value Dummy value.
@retval Dummy value.
**/
UINT64
EFIAPI
AsmAddRngJitter
(
IN
UINT64
Value
);
//
// Limited retry number when valid random data is returned.
// Uses the recommended value defined in Section 7.3.17 of "Intel 64 and IA-32
// Architectures Software Developer's Mannual".
//
#define RDRAND_RETRY_LIMIT 10
//
// Maximum amount of bytes emitted by PRNG before next reseed.
//
#define MAX_BYTES_TO_EMIT 1600000
//
// Maximum bytes in one buffer.
//
#define MAX_BYTES_IN_BUF (16*64)
/**
Random Number Generator context.
**/
typedef
struct
OC_RNG_CONTEXT_
{
//
// Hardware random number generator available.
//
BOOLEAN
HardwareRngAvailable
;
//
// Done initialising pseudo random number generator.
//
BOOLEAN
PrngInitialised
;
//
// Amount of bytes to emit before next reseed.
//
UINT32
BytesTillReseed
;
//
// Amount of bytes in the current buffer.
//
UINT32
BytesInBuffer
;
//
// Current CPRNG buffer.
//
UINT8
Buffer
[
MAX_BYTES_IN_BUF
];
//
// ChaCha context.
//
CHACHA_CONTEXT
ChaCha
;
}
OC_RNG_CONTEXT
;
#endif // OC_RNG_INTERNALS_H
Library/OcRngLib/OcRngLib.c
浏览文件 @
50e5878e
...
...
@@ -21,87 +21,168 @@
**/
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcCryptoLib.h>
#include <Library/OcRngLib.h>
/**
Written in 2019 by David Blackman and Sebastiano Vigna (vigna@acm.org)
#include <Register/Intel/Cpuid.h>
To the extent possible under law, the author has dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
#include "OcRngInternals.h"
See <http://creativecommons.org/publicdomain/zero/1.0/>.
STATIC
OC_RNG_CONTEXT
mRng
;
This is xoshiro256** 1.0, one of our all-purpose, rock-solid
generators. It has excellent (sub-ns) speed, a state (256 bits) that is
large enough for any parallel application, and it passes all tests we
are aware of.
STATIC
VOID
ChaChaRngStir
(
IN
UINT32
BytesNeeded
)
{
//
// Implementation design based on arc4random from FreeBSD.
//
For generating just floating-point numbers, xoshiro256+ is even faster.
UINTN
Index
;
UINT32
KeySeed
[
CHACHA_KEY_SIZE
/
sizeof
(
UINT32
)];
UINT32
IvSeed
[
CHACHA_IV_SIZE
/
sizeof
(
UINT32
)];
BOOLEAN
Result
;
The state must be seeded so that it is not everywhere zero. If you have
a 64-bit seed, we suggest to seed a splitmix64 generator and use its
output to fill mXorShiroState.
**/
STATIC_ASSERT
(
CHACHA_KEY_SIZE
%
sizeof
(
UINT32
)
==
0
,
"Unexpected key size"
);
STATIC_ASSERT
(
CHACHA_IV_SIZE
%
sizeof
(
UINT32
)
==
0
,
"Unexpected key size"
);
STATIC
UINT64
mXorShiroState
[
4
]
;
ASSERT
(
BytesNeeded
<=
MAX_BYTES_TO_EMIT
)
;
VOID
XorShiro256Init
(
VOID
)
{
UINTN
Index
;
//
// Do not reseed if we are initialised and do not yet need a reseed.
//
if
(
mRng
.
PrngInitialised
&&
mRng
.
BytesTillReseed
>=
BytesNeeded
)
{
mRng
.
BytesTillReseed
-=
BytesNeeded
;
return
;
}
//
// TODO: Try to find better entropy source and consider using CSPRNG
// in some future (e.g. ChaCha20).
// Generate seeds.
//
for
(
Index
=
0
;
Index
<
sizeof
(
mXorShiroState
);
++
Index
)
{
((
UINT8
*
)
mXorShiroState
)[
Index
]
=
(
UINT8
)
(
AsmReadTsc
()
&
0xFFU
);
for
(
Index
=
0
;
Index
<
ARRAY_SIZE
(
KeySeed
);
++
Index
)
{
Result
=
GetRandomNumber32
(
&
KeySeed
[
Index
]);
if
(
!
Result
)
{
ASSERT
(
FALSE
);
CpuDeadLoop
();
}
}
for
(
Index
=
0
;
Index
<
ARRAY_SIZE
(
IvSeed
);
++
Index
)
{
Result
=
GetRandomNumber32
(
&
IvSeed
[
Index
]);
if
(
!
Result
)
{
ASSERT
(
FALSE
);
CpuDeadLoop
();
}
}
//
// Reinitialize if we are making a second loop.
//
if
(
mRng
.
PrngInitialised
)
{
ZeroMem
(
mRng
.
Buffer
,
sizeof
(
mRng
.
Buffer
));
//
// Fill buffer with keystream.
//
ChaChaCryptBuffer
(
&
mRng
.
ChaCha
,
mRng
.
Buffer
,
mRng
.
Buffer
,
sizeof
(
mRng
.
Buffer
));
//
// Mix in RNG data.
//
for
(
Index
=
0
;
Index
<
ARRAY_SIZE
(
KeySeed
);
++
Index
)
{
mRng
.
Buffer
[
Index
]
^=
KeySeed
[
Index
];
}
for
(
Index
=
0
;
Index
<
ARRAY_SIZE
(
IvSeed
);
++
Index
)
{
mRng
.
Buffer
[
ARRAY_SIZE
(
KeySeed
)
+
Index
]
^=
KeySeed
[
Index
];
}
}
else
{
mRng
.
PrngInitialised
=
TRUE
;
}
//
// Setup ChaCha context.
//
ChaChaInitCtx
(
&
mRng
.
ChaCha
,
(
UINT8
*
)
KeySeed
,
(
UINT8
*
)
IvSeed
,
0
);
SecureZeroMem
(
KeySeed
,
sizeof
(
KeySeed
));
SecureZeroMem
(
IvSeed
,
sizeof
(
IvSeed
));
mRng
.
BytesTillReseed
=
MAX_BYTES_TO_EMIT
-
BytesNeeded
;
mRng
.
BytesInBuffer
=
0
;
ZeroMem
(
mRng
.
Buffer
,
sizeof
(
mRng
.
Buffer
));
}
UINT64
XorShiro256Next
(
VOID
STATIC
VOID
ChaChaRngGenerate
(
OUT
UINT8
*
Data
,
IN
UINT32
Size
)
{
UINT64
Result
;
UINT64
T
;
UINT32
CurrentSize
;
Result
=
LRotU64
(
mXorShiroState
[
1
]
*
5
,
7
)
*
9
;
T
=
mXorShiroState
[
1
]
<<
17
;
ASSERT
(
Size
<=
MAX_BYTES_TO_EMIT
);
mXorShiroState
[
2
]
^=
mXorShiroState
[
0
];
mXorShiroState
[
3
]
^=
mXorShiroState
[
1
];
mXorShiroState
[
1
]
^=
mXorShiroState
[
2
];
mXorShiroState
[
0
]
^=
mXorShiroState
[
3
];
ChaChaRngStir
(
Size
);
mXorShiroState
[
2
]
^=
T
;
while
(
Size
>
0
)
{
if
(
mRng
.
BytesInBuffer
>
0
)
{
CurrentSize
=
MIN
(
Size
,
mRng
.
BytesInBuffer
);
mXorShiroState
[
3
]
=
LRotU64
(
mXorShiroState
[
3
],
45
);
CopyMem
(
Data
,
mRng
.
Buffer
+
sizeof
(
mRng
.
Buffer
)
-
mRng
.
BytesInBuffer
,
CurrentSize
);
ZeroMem
(
mRng
.
Buffer
+
sizeof
(
mRng
.
Buffer
)
-
mRng
.
BytesInBuffer
,
CurrentSize
);
return
Result
;
Data
+=
CurrentSize
;
Size
-=
CurrentSize
;
mRng
.
BytesInBuffer
-=
CurrentSize
;
}
if
(
mRng
.
BytesInBuffer
==
0
)
{
ZeroMem
(
mRng
.
Buffer
,
sizeof
(
mRng
.
Buffer
));
//
// Fill buffer with keystream.
//
ChaChaCryptBuffer
(
&
mRng
.
ChaCha
,
mRng
.
Buffer
,
mRng
.
Buffer
,
sizeof
(
mRng
.
Buffer
));
//
// Immediately reinit for backtracking resistance.
//
ChaChaInitCtx
(
&
mRng
.
ChaCha
,
&
mRng
.
Buffer
[
0
],
&
mRng
.
Buffer
[
CHACHA_KEY_SIZE
],
0
);
ZeroMem
(
mRng
.
Buffer
,
CHACHA_KEY_SIZE
+
CHACHA_IV_SIZE
);
mRng
.
BytesInBuffer
=
sizeof
(
mRng
.
Buffer
)
-
CHACHA_KEY_SIZE
-
CHACHA_IV_SIZE
;
}
}
}
//
// Hardware RNG generator availability.
//
STATIC
BOOLEAN
mRdRandAvailable
=
FALSE
;
STATIC
UINT64
GetEntropyBits
(
IN
UINT64
Bits
)
{
UINT64
Index
;
UINT64
Entropy
;
UINT64
Tmp
;
//
// Bit mask used to determine if RdRand instruction is supported.
//
#define RDRAND_MASK BIT30
//
// Uses non-deterministic CPU execution.
// REF: https://static.lwn.net/images/conf/rtlws11/random-hardware.pdf
// REF: https://www.osadl.org/fileadmin/dam/presentations/RTLWS11/okech-inherent-randomness.pdf
// REF: http://lkml.iu.edu/hypermail/linux/kernel/1909.3/03714.html
//
Entropy
=
0
;
for
(
Index
=
0
;
Index
<
Bits
;
++
Index
)
{
Tmp
=
AsmReadTsc
()
+
AsmAddRngJitter
(
AsmReadTsc
());
if
((
Tmp
&
BIT0
)
!=
0
)
{
Entropy
|=
(
1U
<<
Index
);
}
}
//
// Limited retry number when valid random data is returned.
// Uses the recommended value defined in Section 7.3.17 of "Intel 64 and IA-32
// Architectures Software Developer's Mannual".
//
#define RDRAND_RETRY_LIMIT 10
return
Entropy
;
}
/**
The constructor function checks whether or not RDRAND instruction is supported
...
...
@@ -120,19 +201,19 @@ OcRngLibConstructor (
VOID
)
{
UINT32
RegEcx
;
CPUID_VERSION_INFO_ECX
RegEcx
;
//
// Determine RDRAND support by examining bit 30 of the ECX register returned by
// CPUID. A value of 1 indicates that processor support RDRAND instruction.
//
AsmCpuid
(
1
,
0
,
0
,
&
RegEcx
,
0
);
mR
dRandAvailable
=
(
RegEcx
&
RDRAND_MASK
)
==
RDRAND_MASK
;
AsmCpuid
(
1
,
0
,
0
,
&
RegEcx
.
Uint32
,
0
);
mR
ng
.
HardwareRngAvailable
=
RegEcx
.
Bits
.
RDRAND
;
//
// Initialize PRNG.
//
XorShiro256Init
(
);
ChaChaRngStir
(
0
);
return
RETURN_SUCCESS
;
}
...
...
@@ -158,20 +239,19 @@ GetRandomNumber16 (
ASSERT
(
Rand
!=
NULL
);
if
(
!
mRdRandAvailable
)
{
return
FALSE
;
}
//
// A loop to fetch a 16 bit random value with a retry count limit.
//
for
(
Index
=
0
;
Index
<
RDRAND_RETRY_LIMIT
;
Index
++
)
{
if
(
AsmRdRand16
(
Rand
))
{
return
TRUE
;
if
(
mRng
.
HardwareRngAvailable
)
{
//
// A loop to fetch a 16 bit random value with a retry count limit.
//
for
(
Index
=
0
;
Index
<
RDRAND_RETRY_LIMIT
;
Index
++
)
{
if
(
AsmRdRand16
(
Rand
))
{
return
TRUE
;
}
}
}
return
FALSE
;
*
Rand
=
(
UINT16
)
GetEntropyBits
(
sizeof
(
UINT16
)
*
OC_CHAR_BIT
);
return
TRUE
;
}
/**
...
...
@@ -195,19 +275,18 @@ GetRandomNumber32 (
ASSERT
(
Rand
!=
NULL
);
if
(
!
mRdRandAvailable
)
{
return
FALSE
;
}
//
// A loop to fetch a 32 bit random value with a retry count limit.
//
for
(
Index
=
0
;
Index
<
RDRAND_RETRY_LIMIT
;
Index
++
)
{
if
(
AsmRdRand32
(
Rand
))
{
return
TRUE
;
if
(
mRng
.
HardwareRngAvailable
)
{
//
// A loop to fetch a 32 bit random value with a retry count limit.
//
for
(
Index
=
0
;
Index
<
RDRAND_RETRY_LIMIT
;
Index
++
)
{
if
(
AsmRdRand32
(
Rand
))
{
return
TRUE
;
}
}
}
*
Rand
=
(
UINT32
)
GetEntropyBits
(
sizeof
(
UINT32
)
*
OC_CHAR_BIT
);
return
FALSE
;
}
...
...
@@ -232,20 +311,19 @@ GetRandomNumber64 (
ASSERT
(
Rand
!=
NULL
);
if
(
!
mRdRandAvailable
)
{
return
FALSE
;
}
//
// A loop to fetch a 64 bit random value with a retry count limit.
//
for
(
Index
=
0
;
Index
<
RDRAND_RETRY_LIMIT
;
Index
++
)
{
if
(
AsmRdRand64
(
Rand
))
{
return
TRUE
;
if
(
mRng
.
HardwareRngAvailable
)
{
//
// A loop to fetch a 64 bit random value with a retry count limit.
//
for
(
Index
=
0
;
Index
<
RDRAND_RETRY_LIMIT
;
Index
++
)
{
if
(
AsmRdRand64
(
Rand
))
{
return
TRUE
;
}
}
}
return
FALSE
;
*
Rand
=
GetEntropyBits
(
sizeof
(
UINT64
)
*
OC_CHAR_BIT
);
return
TRUE
;
}
/**
...
...
@@ -267,21 +345,19 @@ GetRandomNumber128 (
{
ASSERT
(
Rand
!=
NULL
);
if
(
!
mRdRandAvailable
)
{
return
FALSE
;
}
//
// Read first 64 bits
//
if
(
!
GetRandomNumber64
(
Rand
))
{
return
FALSE
;
if
(
mRng
.
HardwareRngAvailable
)
{
//
// Read 64 bits twice
//
if
(
GetRandomNumber64
(
&
Rand
[
0
])
&&
GetRandomNumber64
(
&
Rand
[
1
]))
{
return
TRUE
;
}
}
//
// Read second 64 bits
//
return
GetRandomNumber64
(
++
Rand
);
Rand
[
0
]
=
GetEntropyBits
(
sizeof
(
UINT64
)
*
OC_CHAR_BIT
);
Rand
[
1
]
=
GetEntropyBits
(
sizeof
(
UINT64
)
*
OC_CHAR_BIT
);
return
TRUE
;
}
/**
...
...
@@ -297,9 +373,7 @@ GetPseudoRandomNumber16 (
{
UINT16
Rand
;
if
(
!
GetRandomNumber16
(
&
Rand
))
{
Rand
=
(
UINT16
)
(
XorShiro256Next
()
&
0xFFFFULL
);
}
ChaChaRngGenerate
((
UINT8
*
)
&
Rand
,
sizeof
(
Rand
));
return
Rand
;
}
...
...
@@ -317,9 +391,7 @@ GetPseudoRandomNumber32 (
{
UINT32
Rand
;
if
(
!
GetRandomNumber32
(
&
Rand
))
{
Rand
=
(
UINT32
)
(
XorShiro256Next
()
&
0xFFFFFFFFULL
);
}
ChaChaRngGenerate
((
UINT8
*
)
&
Rand
,
sizeof
(
Rand
));
return
Rand
;
}
...
...
@@ -337,9 +409,7 @@ GetPseudoRandomNumber64 (
{
UINT64
Rand
;
if
(
!
GetRandomNumber64
(
&
Rand
))
{
Rand
=
XorShiro256Next
();
}
ChaChaRngGenerate
((
UINT8
*
)
&
Rand
,
sizeof
(
Rand
));
return
Rand
;
}
Library/OcRngLib/OcRngLib.inf
浏览文件 @
50e5878e
...
...
@@ -30,6 +30,10 @@
[Sources.Ia32, Sources.X64]
OcRngLib.c
OcRngInternals.h
[Sources.X64]
X64/RngDelay.nasm
[Packages]
OcSupportPkg/OcSupportPkg.dec
...
...
@@ -38,3 +42,4 @@
[LibraryClasses]
BaseLib
DebugLib
OcCryptoLib
Library/OcRngLib/X64/RngDelay.nasm
0 → 100644
浏览文件 @
50e5878e
;------------------------------------------------------------------------------
; @file
; Copyright (C) 2020, vit9696. All rights reserved.
;
; All rights reserved.
;
; This program and the accompanying materials
; are licensed and made available under the terms and conditions of the BSD License
; which accompanies this distribution. The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php
;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
;------------------------------------------------------------------------------
BITS 64
DEFAULT REL
;------------------------------------------------------------------------------
; UINT64
; EFIAPI
; AsmAddRngJitter (
; IN UINT64 Value
; );
;------------------------------------------------------------------------------
align 8
global ASM_PFX(AsmAddRngJitter)
ASM_PFX(AsmAddRngJitter):
BITS 64
; This assembly code corresponds to Hamming Weight implementation for targets
; with fast multiplication.
; REF: https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation
mov rax, rcx
shr rax, 1
mov rdx, 5555555555555555h
and rdx, rax
sub rcx, rdx
mov rax, 3333333333333333h
mov rdx, rcx
and rdx, rax
shr rcx, 2
and rcx, rax
add rcx, rdx
mov rax, rcx
shr rax, 4
lea rax, [rax+rcx]
mov rcx, 0F0F0F0F0F0F0F0Fh
and rcx, rax
mov rax, 101010101010101h
imul rax, rcx
shr rax, 38h
ret
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录