ReactOS 0.4.17-dev-1005-g171e1de
libmain.c
Go to the documentation of this file.
1//
2// libmain.c
3// General routines for the SymCrypt library
4//
5// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
6//
7
8#include "precomp.h"
9
10#include "C_asm_shared.inc"
11
12#include "buildInfo.h"
13
14// The following global g_SymCryptFlags has to be at least 32
15// bits because the iOS environment has interlocked function
16// support for variables of size at least 32 bits.
17// The relevant function is OSAtomicOr32Barrier.
19
22
23#if SYMCRYPT_DEBUG
24
25SYMCRYPT_NOINLINE
26VOID
28SymCryptLibraryWasNotInitialized(void)
29{
30 SymCryptFatal( 'init' ); // Function name helps figure out what the problem is.
31}
32
33#endif
34
40
41VOID
44// Returns TRUE if the initialization steps have to be performed.
45{
46 UINT32 tmp;
47
48 const CHAR * p;
49
50 // Assertion that verifies that the calling application was compiled with
51 // the same version header files as the library.
53 {
54 SymCryptFatal( 'apiv' );
55 }
56
57 //
58 // Use an interlocked to set the flag in case we add other flags
59 // that are modified by different threads.
60 //
61 SYMCRYPT_ATOMIC_OR32_PRE_RELAXED( &g_SymCryptFlags, SYMCRYPT_FLAG_LIB_INITIALIZED );
62
63 //
64 // Do a forced write of our code version. This ensures that the code
65 // version is part of the binary, so we can look at a binary and figure
66 // out which version of SymCrypt it was linked with.
67 //
69
70 //
71 // Force the build string to be in memory, because otherwise the
72 // compiler might get smart and remove it.
73 // This ensures we can always track back to the SymCrypt source code from
74 // any binary that links this library
75 //
76 for( p = SymCryptBuildString; *p!=0; p++ )
77 {
78 SYMCRYPT_FORCE_WRITE8( (PBYTE) &tmp, *p );
79 }
80
81 //
82 // Make an inverted copy of the CPU detection results.
83 // This helps us diagnose corruption of our flags
84 // Force-write otherwise the compiler optimizes it away
85 //
87
88 //
89 // Test that the C and assembler code agree on the various structure member offsets.
90 // This gets optimized away in FRE builds as all the values are compile-time computable.
91 //
92#define SYMCRYPT_CHECK_ASM_OFFSET( a, b ) if( (a) != (b) ) {SymCryptFatal( b );}
93 SYMCRYPT_CHECK_ASM_OFFSETS;
94#undef SYMCRYPT_CHECK_ASM_OFFSET
95}
96
98SYMCRYPT_NOINLINE
99VOID
102//
103// This function is used by the environment-specific fatal code
104// as a last resort when none of the other fatal methods work.
105//
106{
107 UINT32 fcode;
108
109 //
110 // Put the fatal code in a location we can find
111 //
112 SYMCRYPT_FORCE_WRITE32( &fcode, fatalCode );
113
114fatalInfiniteLoop:
115 goto fatalInfiniteLoop;
116}
117
118#if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_ARM | SYMCRYPT_CPU_ARM64
119
120VOID
122SymCryptWipeAsm( _Out_writes_bytes_( cbData ) PVOID pbData, SIZE_T cbData );
123
124VOID
127{
128 SymCryptWipeAsm( pbData, cbData );
129}
130
131#else
132//
133// Generic but slow wipe routine.
134//
135VOID
138{
139 volatile BYTE * p = (volatile BYTE *) pbData;
140 SIZE_T i;
141
142 for( i=0; i<cbData; i++ ){
143 p[i] = 0;
144 }
145
146}
147#endif
148
149#if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM
150VOID
153 _In_reads_( cbBytes ) PCBYTE pbSrc1,
154 _In_reads_( cbBytes ) PCBYTE pbSrc2,
155 _Out_writes_( cbBytes ) PBYTE pbResult,
156 SIZE_T cbBytes )
157{
158 SIZE_T i;
159
160 if( cbBytes == 16 )
161 {
162 PCUINT32 s1 = (PCUINT32) pbSrc1;
163 PCUINT32 s2 = (PCUINT32) pbSrc2;
165
166 d[0] = s1[0] ^ s2[0];
167 d[1] = s1[1] ^ s2[1];
168 d[2] = s1[2] ^ s2[2];
169 d[3] = s1[3] ^ s2[3];
170 }
171 else
172 {
173 i = 0;
174 while( i + 3 < cbBytes )
175 {
176 *(UINT32 *)&pbResult[i] = *(UINT32 *)&pbSrc1[i] ^ *(UINT32 *)&pbSrc2[i];
177 i += 4;
178 }
179
180 while( i < cbBytes )
181 {
182 pbResult[i] = pbSrc1[i] ^ pbSrc2[i];
183 i++;
184 }
185 }
186}
187
188#elif SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_ARM64
189
190VOID
193 _In_reads_( cbBytes ) PCBYTE pbSrc1,
194 _In_reads_( cbBytes ) PCBYTE pbSrc2,
195 _Out_writes_( cbBytes ) PBYTE pbResult,
196 SIZE_T cbBytes )
197{
198 if( cbBytes == 16 )
199 {
200 PCUINT64 s1 = (PCUINT64) pbSrc1;
201 PCUINT64 s2 = (PCUINT64) pbSrc2;
203
204 d[0] = s1[0] ^ s2[0];
205 d[1] = s1[1] ^ s2[1];
206 }
207 else
208 {
209 while( cbBytes >= 8 )
210 {
211 *(UINT64 *)pbResult = *(UINT64 *)pbSrc1 ^ *(UINT64 *)pbSrc2;
212 pbSrc1 += 8;
213 pbSrc2 += 8;
214 pbResult += 8;
215 cbBytes -= 8;
216 }
217
218 while( cbBytes > 0 )
219 {
220 *pbResult = *pbSrc1 ^ *pbSrc2;
221 pbResult++;
222 pbSrc1++;
223 pbSrc2++;
224 cbBytes--;
225 }
226 }
227}
228
229
230#else
231//
232// Generic code
233//
234VOID
237 _In_reads_( cbBytes ) PCBYTE pbSrc1,
238 _In_reads_( cbBytes ) PCBYTE pbSrc2,
239 _Out_writes_( cbBytes ) PBYTE pbResult,
240 SIZE_T cbBytes )
241{
242 SIZE_T i;
243
244 for( i=0; i<cbBytes; i++ )
245 {
246 pbResult[i] = pbSrc1[i] ^ pbSrc2[i];
247 }
248}
249#endif
250
251
252//
253// Generic LSB/MSBfirst load/store code for variable-sized buffers.
254// These implementations are inefficient and not side-channel safe.
255// This is sufficient for the current usage (typically to allow
256// callers to read/write RSA public exponents from/to variable-sized
257// buffers).
258// Consider upgrading them in future.
259//
260
261UINT32
263//
264// Some CPUs/compilers have intrinsics for this,
265// but this is portable and works everywhere.
266//
267{
268 UINT32 res;
269
270 res = 0;
271 while( value != 0 )
272 {
273 res += 1;
274 value >>= 1;
275 }
276
277 return res;
278}
279
280UINT32
282{
283 UINT32 res;
284 UINT32 upper;
285
286 upper = (UINT32)(value >> 32);
287
288 if( upper == 0 )
289 {
291 } else {
292 res = 32 + SymCryptUint32Bitsize( upper );
293 }
294
295 return res;
296}
297
298UINT32
300{
301 if( value == 0 )
302 {
303 return 0;
304 }
305 if( value < 0x100 )
306 {
307 return 1;
308 }
309 if( value < 0x10000 )
310 {
311 return 2;
312 }
313 if( value < 0x1000000 )
314 {
315 return 3;
316 }
317 return 4;
318}
319
320UINT32
322{
323 UINT32 res;
324 UINT32 upper;
325
326 upper = (UINT32)(value >> 32);
327
328 if( upper == 0 )
329 {
331 } else {
332 res = 4 + SymCryptUint32Bytesize( upper );
333 }
334
335 return res;
336}
337
338
342 _In_reads_( cbSrc ) PCBYTE pbSrc,
343 SIZE_T cbSrc,
344 _Out_ PUINT32 pDst )
345{
346 UINT64 v64;
347 UINT32 v32;
348 SYMCRYPT_ERROR scError;
349
350 scError = SymCryptLoadLsbFirstUint64( pbSrc, cbSrc, &v64 );
351 if( scError != SYMCRYPT_NO_ERROR )
352 {
353 goto cleanup;
354 }
355
356 v32 = (UINT32) v64;
357 if( v32 != v64 )
358 {
359 scError = SYMCRYPT_VALUE_TOO_LARGE;
360 goto cleanup;
361 }
362
363 *pDst = v32;
364
365cleanup:
366 return scError;
367}
368
372 _In_reads_( cbSrc ) PCBYTE pbSrc,
373 SIZE_T cbSrc,
374 _Out_ PUINT64 pDst )
375{
376 UINT64 v;
377 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
378
379 v = 0;
380 pbSrc += cbSrc;
381 while( cbSrc > 8 )
382 {
383 if( *--pbSrc != 0 )
384 {
385 scError = SYMCRYPT_VALUE_TOO_LARGE;
386 goto cleanup;
387 }
388 cbSrc--;
389 }
390
391 while( cbSrc > 0 )
392 {
393 v = (v << 8) | *--pbSrc;
394 cbSrc--;
395 }
396
397 *pDst = v;
398
399cleanup:
400 return scError;
401}
402
406 _In_reads_( cbSrc ) PCBYTE pbSrc,
407 SIZE_T cbSrc,
408 _Out_ PUINT32 pDst )
409{
410 UINT64 v64;
411 UINT32 v32;
412 SYMCRYPT_ERROR scError;
413
414 scError = SymCryptLoadMsbFirstUint64( pbSrc, cbSrc, &v64 );
415 if( scError != SYMCRYPT_NO_ERROR )
416 {
417 goto cleanup;
418 }
419
420 v32 = (UINT32) v64;
421 if( v32 != v64 )
422 {
423 scError = SYMCRYPT_VALUE_TOO_LARGE;
424 goto cleanup;
425 }
426
427 *pDst = v32;
428
429cleanup:
430 return scError;
431}
432
433
437 _In_reads_( cbSrc ) PCBYTE pbSrc,
438 SIZE_T cbSrc,
439 _Out_ PUINT64 pDst )
440{
441 UINT64 v;
442 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
443
444 v = 0;
445 while( cbSrc > 8 )
446 {
447 if( *pbSrc++ != 0 )
448 {
449 scError = SYMCRYPT_VALUE_TOO_LARGE;
450 goto cleanup;
451 }
452 cbSrc--;
453 }
454
455 while( cbSrc > 0 )
456 {
457 v = (v << 8) | *pbSrc++;
458 cbSrc--;
459 }
460
461 *pDst = v;
462
463cleanup:
464 return scError;
465}
466
467
471 UINT32 src,
472 _Out_writes_( cbDst ) PBYTE pbDst,
473 SIZE_T cbDst )
474{
475 return SymCryptStoreLsbFirstUint64( src, pbDst, cbDst );
476}
477
481 UINT64 src,
482 _Out_writes_( cbDst ) PBYTE pbDst,
483 SIZE_T cbDst )
484{
485 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
486
487 while( cbDst > 0 )
488 {
489 *pbDst++ = (BYTE) src;
490 src >>= 8;
491 cbDst--;
492 }
493
494 if( src != 0 )
495 {
496 scError = SYMCRYPT_VALUE_TOO_LARGE;
497 goto cleanup;
498 }
499
500cleanup:
501 return scError;
502}
503
507 UINT32 src,
508 _Out_writes_( cbDst ) PBYTE pbDst,
509 SIZE_T cbDst )
510{
511 return SymCryptStoreMsbFirstUint64( src, pbDst, cbDst );
512}
513
517 UINT64 src,
518 _Out_writes_( cbDst ) PBYTE pbDst,
519 SIZE_T cbDst )
520{
521 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
522
523 pbDst += cbDst;
524 while( cbDst > 0 )
525 {
526 *--pbDst = (BYTE) src;
527 src >>= 8;
528 cbDst--;
529 }
530
531 if( src != 0 )
532 {
533 scError = SYMCRYPT_VALUE_TOO_LARGE;
534 goto cleanup;
535 }
536
537cleanup:
538 return scError;
539}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
unsigned int * PUINT32
Definition: basetsd.h:119
unsigned __int64 * PUINT64
Definition: basetsd.h:181
#define SYMCRYPT_BUILD_INFO_VERSION
Definition: buildInfo.h:7
#define SYMCRYPT_BUILD_INFO_COMMIT
Definition: buildInfo.h:6
#define SYMCRYPT_BUILD_INFO_TIMESTAMP
Definition: buildInfo.h:8
#define SYMCRYPT_BUILD_INFO_BRANCH
Definition: buildInfo.h:5
static const WCHAR version[]
Definition: asmname.c:66
static void cleanup(void)
Definition: main.c:1335
const GLdouble * v
Definition: gl.h:2040
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
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 d
Definition: ke_i.h:81
UINT32 SymCryptUint64Bytesize(UINT64 value)
Definition: libmain.c:321
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
_Analysis_noreturn_ SYMCRYPT_NOINLINE VOID SYMCRYPT_CALL SymCryptFatalHang(UINT32 fatalCode)
Definition: libmain.c:101
UINT32 SymCryptUint32Bytesize(UINT32 value)
Definition: libmain.c:299
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptStoreMsbFirstUint32(UINT32 src, _Out_writes_(cbDst) PBYTE pbDst, SIZE_T cbDst)
Definition: libmain.c:506
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptStoreLsbFirstUint64(UINT64 src, _Out_writes_(cbDst) PBYTE pbDst, SIZE_T cbDst)
Definition: libmain.c:480
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptLoadMsbFirstUint64(_In_reads_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, _Out_ PUINT64 pDst)
Definition: libmain.c:436
SYMCRYPT_CPU_FEATURES g_SymCryptCpuFeaturesNotPresent
Definition: libmain.c:20
VOID SYMCRYPT_CALL SymCryptXorBytes(_In_reads_(cbBytes) PCBYTE pbSrc1, _In_reads_(cbBytes) PCBYTE pbSrc2, _Out_writes_(cbBytes) PBYTE pbResult, SIZE_T cbBytes)
Definition: libmain.c:236
UINT32 g_SymCryptFlags
Definition: libmain.c:18
UINT32 SymCryptUint32Bitsize(UINT32 value)
Definition: libmain.c:262
const CHAR *const SymCryptBuildString
Definition: libmain.c:35
SYMCRYPT_CPU_FEATURES g_SymCryptCpuFeaturesPresentCheck
Definition: libmain.c:21
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptLoadLsbFirstUint32(_In_reads_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, _Out_ PUINT32 pDst)
Definition: libmain.c:341
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptStoreLsbFirstUint32(UINT32 src, _Out_writes_(cbDst) PBYTE pbDst, SIZE_T cbDst)
Definition: libmain.c:470
UINT32 SymCryptUint64Bitsize(UINT64 value)
Definition: libmain.c:281
VOID SYMCRYPT_CALL SymCryptInitEnvCommon(UINT32 version)
Definition: libmain.c:43
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptLoadMsbFirstUint32(_In_reads_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, _Out_ PUINT32 pDst)
Definition: libmain.c:405
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptStoreMsbFirstUint64(UINT64 src, _Out_writes_(cbDst) PBYTE pbDst, SIZE_T cbDst)
Definition: libmain.c:516
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptLoadLsbFirstUint64(_In_reads_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, _Out_ PUINT64 pDst)
Definition: libmain.c:371
struct S1 s1
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _Out_
Definition: no_sal2.h:160
#define _Analysis_noreturn_
Definition: no_sal2.h:392
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
BYTE * PBYTE
Definition: pedump.c:66
char CHAR
Definition: pedump.c:57
#define SYMCRYPT_FLAG_LIB_INITIALIZED
Definition: sc_lib.h:22
PCWSTR s2
Definition: shell32_main.h:38
static const BYTE pbResult[]
#define SYMCRYPT_FORCE_WRITE8( _p, _v)
Definition: symcrypt.h:421
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
#define SYMCRYPT_FORCE_WRITE32(_p, _v)
Definition: symcrypt.h:423
SYMCRYPT_ERROR
Definition: symcrypt.h:227
#define SYMCRYPT_API_VERSION
Definition: symcrypt.h:16
PCBYTE pbSrc
#define SYMCRYPT_CALL
const UINT64 * PCUINT64
UINT32 SYMCRYPT_CPU_FEATURES
PCBYTE PBYTE SIZE_T cbData
PCBYTE PBYTE pbDst
const BYTE * PCBYTE
const UINT32 * PCUINT32
PCBYTE pbData
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
Definition: pdh_main.c:64
unsigned char BYTE
Definition: xxhash.c:193