ReactOS 0.4.17-dev-1005-g171e1de
rdrand.c
Go to the documentation of this file.
1//
2// rdrand.c Support for RdRand instruction
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7#include "precomp.h"
8
9#if (SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64) // only available on x86 and amd64 architectures
10
11#ifdef __clang__
12#pragma clang attribute push (__attribute__((target("rdrnd"))), apply_to=function)
13#else
14#pragma GCC push_options
15#pragma GCC target("rdrnd")
16#endif
17
18#if SYMCRYPT_MS_VC && _MSC_VER < 1610
19#error MSVC version lacks support for RDRAND intrinsics. Compile for the generic environment instead.
20#endif
21
22//
23// TODO: the _rdrand_u*() versions of the intrinsics can be removed once the new compiler
24// with the _rdrand*_step() intrinsics is used in all branches
25
26#if SYMCRYPT_MS_VC && _MSC_VER < 1700 // 1700 = Dev11,
27
28//
29// This is the code that uses the old intrinsics in the compiler version 16.1
30//
31
32unsigned int _rdrand_u32(void);
33unsigned __int64 _rdrand_u64(void);
34
35
36#if SYMCRYPT_CPU_X86
37#define SymCryptRdrandSizet(p) ( *(p)=(SIZE_T)_rdrand_u32(), SYMCRYPT_NO_ERROR )
38#else
39#define SymCryptRdrandSizet(p) ( *(p)=(SIZE_T)_rdrand_u64(), SYMCRYPT_NO_ERROR )
40#endif
41
42#else // _MSC_VER
43
44//
45// Code for the new Dev11 intrinsics
46//
47
48#if SYMCRYPT_CPU_X86
49#define _rdrandxx_step(_p) _rdrand32_step( (unsigned int *) (_p) )
50#else
51#define _rdrandxx_step(_p) _rdrand64_step( (UINT64 *) (_p) )
52#endif
53
57SymCryptRdrandSizet( SIZE_T * p )
58{
59 int i;
60
61 //
62 // In Win8/WinBlue we iterated 1000 times.
63 // But we got a crash bucket where we fail because of
64 // not getting any random data.
65 // I contacted the Intel people; according to them they cannot make the
66 // RDRAND instruction fail more than a dozen times in a row under any tested
67 // circumstance. They have no idea how it could fail 1000 times in a row.
68 // As a failure of this code leads to a bugcheck (it fails a security promise, and
69 // is therefore treated as a critical security bug) I have increased the
70 // iteration count to 1000000.
71 // This will not affect any machine that didn't bugcheck before, but it hopefully
72 // will remove some of the current bugchecks.
73 //
74 // Niels Ferguson (niels) 2014-04-09.
75 //
76 for( i=0; i<1000000; i++ )
77 {
78 if( _rdrandxx_step( p ) != 0 )
79 {
80 return SYMCRYPT_NO_ERROR;
81 }
82 }
83 return SYMCRYPT_HARDWARE_FAILURE;
84}
85
86#endif
87
88
91SymCryptRdrandStatus(void)
92{
93 //
94 // Check that the library is initialized; otherwise the CPUID info
95 // is all zeroes. (This check only happens in CHKed builds.)
96 //
98
99 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_RDRAND ) )
100 {
101 return SYMCRYPT_NO_ERROR;
102 }
103 else
104 {
105 return SYMCRYPT_NOT_IMPLEMENTED;
106 }
107}
108
109
112SymCryptRdrandGetBytes(
113 _Out_writes_( cbBuffer ) PBYTE pbBuffer,
116{
117 SIZE_T * pBuf;
118 SIZE_T nBuf;
119 SIZE_T i;
120 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
121
122 //
123 // Take care of the obvious errors that can happen
124 //
125 if( SymCryptRdrandStatus() != SYMCRYPT_NO_ERROR ||
126 (cbBuffer & 0xf) != 0
127 )
128 {
129 SymCryptFatal( 'rdrn' );
130 }
131
132 pBuf = (SIZE_T *) pbBuffer;
133 nBuf = cbBuffer / sizeof( SIZE_T );
134
135 for( i=0; i<nBuf; i++ )
136 {
137 scError = SymCryptRdrandSizet( &pBuf[i] );
138 if( scError != SYMCRYPT_NO_ERROR )
139 {
140 goto cleanup;
141 }
142 }
143
144 SymCryptSha512( pbBuffer, cbBuffer, pbResult );
145
146cleanup:
147 SymCryptWipe( pbBuffer, cbBuffer );
148
149 return scError;
150}
151
152
153VOID
155SymCryptRdrandGet(
156 _Out_writes_( cbBuffer ) PBYTE pbBuffer,
159{
160 if( SymCryptRdrandGetBytes( pbBuffer, cbBuffer, pbResult ) != SYMCRYPT_NO_ERROR )
161 {
162 SymCryptFatal( 'rdrx' );
163 }
164}
165
166#ifdef __clang__
167#pragma clang attribute pop
168#else
169#pragma GCC pop_options
170#endif
171
172#endif // SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64
static void cleanup(void)
Definition: main.c:1335
#define __int64
Definition: corecrt.h:72
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define _Out_writes_(s)
Definition: no_sal2.h:176
BYTE * PBYTE
Definition: pedump.c:66
FORCEINLINE VOID SYMCRYPT_CALL SymCryptCheckLibraryInitialized(void)
Definition: sc_lib.h:296
SIZE_T cbBuffer
Definition: sc_lib_mldsa.h:405
static const BYTE pbResult[]
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
VOID SYMCRYPT_CALL SymCryptSha512(_In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(SYMCRYPT_SHA512_RESULT_SIZE) PBYTE pbResult)
#define SYMCRYPT_SHA512_RESULT_SIZE
Definition: symcrypt.h:1352
SYMCRYPT_ERROR
Definition: symcrypt.h:227
#define SYMCRYPT_CALL
#define SYMCRYPT_CPU_FEATURES_PRESENT(x)
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define FORCEINLINE
Definition: wdftypes.h:67