ReactOS 0.4.17-dev-1005-g171e1de
ghash.c
Go to the documentation of this file.
1//
2// GHASH.c
3//
4// Implementation of the NIST SP800-38D GHASH function which is the
5// core authentication function for the GCM and GMAC modes.
6//
7// This implementation was done by Niels Ferguson for the RSA32.lib library in 2008,
8// and adapted to the SymCrypt library in 2009.
9//
10// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
11//
12
13#include "precomp.h"
14#include "ghash_definitions.h"
15
17// Platform-independent code
18//
19
20//
21// GHashExpandKeyC
22// Generic GHash key expansion routine, works on all platforms.
23// This function computes a table of H, Hx, Hx^2, Hx^3, ..., Hx^127
24//
25VOID
30{
31 UINT64 H0, H1, t;
32 UINT32 i;
33
34 //
35 // (H1, H0) form a 128-bit integer, H1 is the upper part, H0 the lower part.
36 // Convert pH[] to (H1, H0) using MSByte first convention.
37 //
38 H1 = SYMCRYPT_LOAD_MSBFIRST64( &pH[0] );
39 H0 = SYMCRYPT_LOAD_MSBFIRST64( &pH[8] );
40
41 for( i=0; i<SYMCRYPT_GF128_FIELD_SIZE; i++ )
42 {
43 expandedKey[i].ull[0] = H0;
44 expandedKey[i].ull[1] = H1;
45 //
46 // Multiply (H1,H0) by x in the GF(2^128) field using the field encoding from SP800-38D
47 //
48 t = UINT64_NEG(H0 & 1) & ((UINT64)GF128_FIELD_R_BYTE << (8 * ( sizeof( UINT64 ) - 1 )) ) ;
49 H0 = (H0 >> 1) | (H1 << 63);
50 H1 = (H1 >> 1) ^ t;
51 }
52}
53
54
55//
56// GHashAppendDataC
57// Generic GHash routine, works on all platforms.
58//
59VOID
66{
67 UINT64 R0, R1;
69 SYMCRYPT_ALIGN UINT32 state32[4];
70 UINT32 t;
71 int i,j;
73 {
74 R0 = R1 = 0;
75
76 //
77 // We have two nested loops so that we can do most of our operations
78 // on 32-bit words. 64-bit rotates/shifts can be really slow on a 32-bit CPU.
79 // On AMD64 we use the XMM version which is much faster.
80 //
81 state32[0] = (UINT32)pState->ull[0];
82 state32[1] = (UINT32)(pState->ull[0] >> 32);
83 state32[2] = (UINT32)pState->ull[1];
84 state32[3] = (UINT32)(pState->ull[1] >> 32);
85 for( i=0; i<4; i++ )
86 {
87 t = SYMCRYPT_LOAD_MSBFIRST32( &pbData[4*i] ) ^ state32[3-i];
88 for( j=31; j>=0; j-- )
89 {
90 mask = (UINT64)( -(INT64)(t & 1 ));
91 R0 ^= expandedKeyTable[32*i+j].ull[0] & mask;
92 R1 ^= expandedKeyTable[32*i+j].ull[1] & mask;
93 t >>= 1;
94 }
95 }
96 pState->ull[0] = R0;
97 pState->ull[1] = R1;
100 }
101
102 SymCryptWipeKnownSize( state32, sizeof( state32 ) );
103}
104
105
106VOID
111{
114}
115
117// XMM code
118//
119
120VOID
125{
126 //
127 // We use the same layout for XMM code as we did for C code, so we can use the same key
128 // expansion code.
129 // Improvement: we can add an expansion routine that uses the XMM registers for speed.
130 //
131
132 SymCryptGHashExpandKeyC( expandedKey, pH );
133}
134
135#if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64
136
137#ifdef __clang__
138#pragma clang attribute push (__attribute__((target("sse2"))), apply_to=function)
139#else
140#pragma GCC push_options
141#pragma GCC target("sse2")
142#endif
143
144//
145// The XMM-based GHash append data function, only on AMD64 & X86
146//
147VOID
153 SIZE_T cbData )
154{
155 __m128i R;
156 __m128i cmpValue;
157 __m128i mask;
158 __m128i T;
159 __m128i tmp;
160
163 UINT32 t;
164 int i;
165
166 cmpValue = _mm_setzero_si128(); // cmpValue = 0
167
169 {
171
172 //
173 // The amd64 compiler can't optimize array indices in a loop where
174 // you use _mm intrinsics,
175 // so we do all the pointer arithmetic for the compiler.
176 //
177 p = &expandedKeyTable[0];
178 pLimit = &expandedKeyTable[32];
179
180 for( i=0; i<4; i++ )
181 {
182 //
183 // Set up our XMM register with 4 identical 32-bit integers so that
184 // we can generate the mask from the individual bits of the 32-bit value.
185 // Note the use of tmp; if we assign directly to the fields of T the
186 // compiler no longer caches T in an XMM register, which is bad.
187 //
188 // There are XMM instructions where we can do the duplication in the XMM
189 // registers, but they require SSE3 support, and this code only requires
190 // SSE2. As the inner loop consumes most of the time, it isn't worth
191 // using the SSE3 instructions.
192 //
193 // Note that accessing the state as an array of UINT32s depends on the
194 // endianness of the CPU, but this is XMM code that only runs on
195 // little endian machines.
196 //
197 t = SYMCRYPT_LOAD_MSBFIRST32( &pbData[4*i] ) ^ pState->ul[3-i];
198 tmp = _mm_set_epi32(t, t, t, t);
199
200 T = tmp;
201 while( p < pLimit )
202 {
203 //
204 // p and plimit are always at indexes that are multiples of 4 from
205 // the start of the array.
206 // We need to explain to prefast that this means that p <= pLimit - 4
207 //
208 SYMCRYPT_ASSERT( p <= pLimit - 4 );
209
210 mask = _mm_cmpgt_epi32( cmpValue, T );
211 T = _mm_add_epi32( T, T );
212 mask = _mm_and_si128( mask, p[0].m128i );
213 R = _mm_xor_si128( R, mask );
214
215 mask = _mm_cmpgt_epi32( cmpValue, T );
216 T = _mm_add_epi32( T, T );
217 mask = _mm_and_si128( mask, p[1].m128i );
218 R = _mm_xor_si128( R, mask );
219
220 mask = _mm_cmpgt_epi32( cmpValue, T );
221 T = _mm_add_epi32( T, T );
222 mask = _mm_and_si128( mask, p[2].m128i );
223 R = _mm_xor_si128( R, mask );
224
225 mask = _mm_cmpgt_epi32( cmpValue, T );
226 T = _mm_add_epi32( T, T );
227 mask = _mm_and_si128( mask, p[3].m128i );
228 R = _mm_xor_si128( R, mask );
229
230 p += 4;
231 }
232 pLimit += 32;
233 }
234
235 pState->m128i = R;
238 }
239}
240
241#ifdef __clang__
242#pragma clang attribute pop
243#else
244#pragma GCC pop_options
245#endif
246
247#endif
248
249#if SYMCRYPT_CPU_ARM | SYMCRYPT_CPU_ARM64
250//
251// The NEON-based GHash append data function, only on ARM & ARM64
252//
253VOID
259 SIZE_T cbData )
260{
261 // Room for improvement: replace non-crypto NEON code below, based on a bit by bit lookup with
262 // pmull on 8b elements - 8x(8bx8b) -> 8x(16b) pmull is NEON instruction since Armv7
263 //
264 // When properly unrolled:
265 // 1 (64bx64b -> 128b) pmull instruction and 1 eor instruction can be replaced by
266 // 8 (8x(8bx8b) -> 8x(16b)) pmull instructions and 8 eor instructions
267 // so each 128b of data could be processed by less than 64 instructions (using karatsuba)
268 // rather than ~512 instructions (bit by bit)
269 //
270 // Not a priority, expect that AES-GCM performance will be dominated by AES on these platforms
271
272 __n128 R;
273 __n128 cmpValue;
274 __n128 mask;
275 __n128 T;
276
279 UINT32 t;
280 int i;
281
282 cmpValue = vdupq_n_u32(0); // cmpValue = 0
283
285 {
286 R = cmpValue;
287
288 //
289 // Do all the pointer arithmetic for the compiler.
290 //
291 p = &expandedKeyTable[0];
292 pLimit = &expandedKeyTable[32];
293
294 for( i=0; i<4; i++ )
295 {
296 //
297 // Set up our XMM register with 4 identical 32-bit integers so that
298 // we can generate the mask from the individual bits of the 32-bit value.
299 // Note the use of tmp; if we assign directly to the fields of T the
300 // compiler no longer caches T in an XMM register, which is bad.
301 //
302 // Note that accessing the state as an array of UINT32s depends on the
303 // endianness of the CPU, but Arm code is always expected to execute in
304 // little endian mode.
305 //
306 t = SYMCRYPT_LOAD_MSBFIRST32( &pbData[4*i] ) ^ pState->ul[3-i];
307 T = vdupq_n_u32( t );
308
309 while( p < pLimit )
310 {
311 //
312 // p and plimit are always at indexes that are multiples of 4 from
313 // the start of the array.
314 // We need to explain to prefast that this means that p <= pLimit - 4
315 //
316 SYMCRYPT_ASSERT( p <= pLimit - 4 );
317
318 mask = vcgtq_s32( cmpValue, T );
319 T = vaddq_u32( T, T );
320 mask = vandq_u32( mask, p[0].n128 );
321 R = veorq_u32( R, mask );
322
323 mask = vcgtq_s32( cmpValue, T );
324 T = vaddq_u32( T, T );
325 mask = vandq_u32( mask, p[1].n128 );
326 R = veorq_u32( R, mask );
327
328 mask = vcgtq_s32( cmpValue, T );
329 T = vaddq_u32( T, T );
330 mask = vandq_u32( mask, p[2].n128 );
331 R = veorq_u32( R, mask );
332
333 mask = vcgtq_s32( cmpValue, T );
334 T = vaddq_u32( T, T );
335 mask = vandq_u32( mask, p[3].n128 );
336 R = veorq_u32( R, mask );
337
338 p += 4;
339 }
340 pLimit += 32;
341 }
342
343 pState->n128 = R;
346 }
347}
348#endif
349
350
352// Pclmulqdq implementation
353//
354
355/*
356GHASH GF(2^128) multiplication using PCLMULQDQ
357
358The GF(2^128) field used in GHASH is GF(2)[x]/p(x) where p(x) is the primitive polynomial
359 x^128 + x^7 + x^2 + x + 1
360
361Notation: We use the standard mathematical notation '+' for the addition in the field,
362which corresponds to a xor of the bits.
363
364Multiplication:
365Given two field elements A and B (represented as 128-bit values),
366we first compute the polynomial product
367 (C,D) := A * B
368where C and D are also 128-bit values.
369
370The PCLMULQDQ instruction performs a 64 x 64 -> 128 bit carryless multiplication.
371To multiply 128-bit values we write A = (A1, A0) and B = (B1, B0) in two 64-bit halves.
372
373The schoolbook multiplication is computed by
374 (C, D) = (A1 * B1)x^128 + (A1 * B0 + A0 * B1)x^64 + (A0 * B0)
375This require four PCLMULQDQ instructions. The middle 128-bit result has to be shifted
376left and right, and each half added to the upper and lower 128-bit result to get (C,D).
377
378Alternatively, the middle 128-bit intermediate result be computed using Karatsuba:
379 (A1*B0 + A0*B1) = (A1 + A0) * (B1 + B0) + (A1*B1) + (A0*B0)
380This requires only one PCLMULQDQ instruction to multiply (A1 + A0) by (B1 + B0)
381as the other two products are already computed.
382Whether this is faster depends on the relative speed of shift/xor verses PCLMULQDQ.
383
384Both multiplication algorithms produce three 128-bit intermediate results (R1, Rmid, R0),
385with the full result defined by R1 x^128 + Rmid x^64 + R0.
386If we do Multiply-Accumulate then we can accumulate the three 128-bit intermediate results
387directly. As there are no carries, there is no overflow, and the combining of the three
388intermediate results into a 256-bit result can be shared amongst all multiplications.
389
390
391Modulo reduction:
392We use << and >> to denote shifts on 128-bit values.
393The modulo reduction can now be done as follows:
394given a 256-bit value (C,D) representing C x^128 + D we compute
395 (T1,T0) := C + C*x + C * x^2 + C * x^7
396 R := D + T0 + T1 + (T1 << 1) + (T1 << 2) + (T1 << 7)
397
398(T1,T0) is just the value C x^128 reduced one step modulo p(x).The value T1 is at most 7 bits,
399so in the next step the reduction, which computes the result R, is easy. The
400expression T1 + (T1 << 1) + (T1 << 2) + (T1 << 7) is just T1 * x^128 reduced modulo p(x).
401
402Let's first get rid of the polynomial arithmetic and write this completely using shifts on
403128-bit values.
404
405T0 := C + (C << 1) + (C << 2) + (C << 7)
406T1 := (C >> 127) + (C >> 126) + (C >> 121)
407R := D + T0 + T1 + (T1 << 1) + (T1 << 2) + (T1 << 7)
408
409We can optimize this by rewriting the equations
410
411T2 := T1 + C
412 = C + (C>>127) + (C>>126) + (C>>121)
413R = D + T0 + T1 + (T1 << 1) + (T1 << 2) + (T1 << 7)
414 = D + C + (C << 1) + (C << 2) + (C << 7) + T1 + (T1 << 1) + (T1 << 2) + (T1 << 7)
415 = D + T2 + (T2 << 1) + (T2 << 2) + (T2 << 7)
416
417Thus
418T2 = C + (C>>127) + (C>>126) + (C>>121)
419R = D + T2 + (T2 << 1) + (T2 << 2) + (T2 << 7)
420
421Gets the right result and uses only 6 shifts.
422
423The SSE instruction set does not implement bit-shifts of 128-bit values. Instead, we will
424use bit-shifts of the 32-bit subvalues, and byte shifts (shifts by a multiple of 8 bits)
425on the full 128-bit values.
426We use the <<<< and >>>> operators to denote shifts on 32-bit subwords.
427
428We can now do the modulo reduction by
429
430t1 := (C >> 127) = (C >>>> 31) >> 96
431t2 := (C >> 126) = (C >>>> 30) >> 96
432t3 := (C >> 121) = (C >>>> 25) >> 96
433T2 = C + t1 + t2 + t3
434
435left-shifts in the computation of R are a bit more involved as we have to move bits from
436one subword to the next
437
438u1 := (T2 << 1) = (T2 <<<< 1) + ((T2 >>>> 31) << 32)
439u2 := (T2 << 2) = (T2 <<<< 2) + ((T2 >>>> 30) << 32)
440u3 := (T2 << 7) = (T2 <<<< 7) + ((T2 >>>> 25) << 32)
441R = D + T2 + u1 + u2 + u3
442
443We can eliminate some common subexpressions. For any k we have
444(T2 >>>> k) = ((C + r) >>>> k)
445where r is a 7-bit value. If k>7 then this is equal to (C >>>> k). This means that
446the value (T2 >>>> 31) is equal to (C >>>> 31) so we don't have to compute it again.
447
448So we can rewrite our formulas as
449t4 := (C >>>> 31)
450t5 := (C >>>> 30)
451t6 := (C >>>> 25)
452ts = t4 + t5 + t6
453T2 = C + (ts >> 96)
454
455Note that ts = (C >>>> 31) + (C >>>> 30) + (C >>>> 25)
456which is equal to (T2 >>>> 31) + (T2 >>>> 30) + (T2 >>>> 25)
457
458R = D + T2 + u1 + u2 + u3
459 = D + T2 + (T2 <<<< 1) + (T2 <<<< 2) + (T2 <<<< 7) + (ts << 32)
460
461All together, we can do the modulo reduction using the following formulas
462
463ts := (C >>>> 31) + (C >>>> 30) + (C >>>> 25)
464T2 := C + (ts >> 96)
465R = D + T2 + (T2 <<<< 1) + (T2 <<<< 2) + (T2 <<<< 7) + (ts << 32)
466
467Using a total of 16 operations. (6 subword shifts, 2 byte shifts, and 8 additions)
468
469Reversed bit order:
470There is one more complication. GHASH uses the bits in the reverse order from normal representation.
471The bits b_0, b_1, ..., b_127 represent the polynomial b_0 + b_1 * x + ... + b_127 * x^127.
472This means that the most significant bit in each byte is actually the least significant bit in the
473polynomial.
474
475SSE CPUs use the LSBFirst convention. This means that the bits b_0, b_1, ..., b_127 of the polynomial
476end up at positions 7, 6, 5, ..., 1, 0, 15, 14, ..., 9, 8, 23, 22, ... of our XMM register.
477This is obviously not a useful representation to do arithmetic in.
478The first step is to BSWAP the value so that the bits appear in pure reverse order.
479That is at least algebraically useful.
480
481To compute the multiplication we use the fact that GF(2)[x] multiplication has no carries and
482thus no preference for bit order. After the BSWAP we don't have the values A and B, but rather
483rev(A) and rev(B) where rev() is a function that reverses the bit order. We can now compute
484
485 rev(A) * rev(B) = rev( A*B ) >> 1
486
487where the shift operator is on the 256-bit product.
488
489The modulo reduction remains the same, except that we change all the shifts to be the other direction.
490
491This gives us finally the outline of our multiplication:
492
493- Apply BSWAP to all values loaded from memory.
494 A := BSWAP( Abytes )
495 B := BSWAP( Bbytes )
496- Compute the 256-bit product, possibly using Karatsuba.
497 (P1, P0) := A * B // 128x128 carryless multiplication
498- Shift the result left one bit.
499 (Q1, Q0) := (P1, P0) << 1
500 which is computed as
501 Q0 = (P0 <<<< 1) + (P0 >>>> 31) << 32
502 Q1 = (P1 <<<< 1) + (P1 >>>> 31) << 32 + (P0 >>>> 31) >> 96
503- Perform the modulo reduction, with reversed bit order
504 ts := (Q0 <<<< 31) + (Q0 <<<< 30) + (Q0 <<<< 25)
505 T2 := Q0 + (ts << 96)
506 R = Q1 + T2 + (T2 >>>> 1) + (T2 >>>> 2) + (T2 >>>> 7) + (ts >> 32)
507
508Future work:
509It might be possible to construct a faster solution by merging the leftshift of (P1,P0)
510with the modulo reduction.
511
512*/
513
514#if SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_AMD64
515
516#ifdef __clang__
517#pragma clang attribute push (__attribute__((target("ssse3,pclmul"))), apply_to=function)
518#else
519#pragma GCC push_options
520#pragma GCC target("ssse3,pclmul")
521#endif
522
523VOID
525SymCryptGHashExpandKeyPclmulqdq(
528{
529 int i;
530 __m128i H, Hx, H2, H2x;
531 __m128i t0, t1, t2, t3, t4, t5;
532 __m128i Hi_even, Hix_even, Hi_odd, Hix_odd;
533 __m128i BYTE_REVERSE_ORDER = _mm_set_epi8(
534 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 );
535 __m128i vMultiplicationConstant = _mm_set_epi32( 0, 0, 0xc2000000, 0 );
536
537 //
538 // Our expanded key consists of a list of N=SYMCRYPT_GHASH_PCLMULQDQ_HPOWERS
539 // powers of H. The first entry is H^N, the next H^(N-1), then H^(N-2), ...
540 //
541 // For each power we store two 128-bit values. The first is H^i (Hi) and the second
542 // contains the two halves of H^i xorred with each other in the lower 64 bits (Hix).
543 //
544 // We keep all of the Hi entries together in the first half of the expanded key
545 // table, and all of the Hix entries together in the second half of the table.
546 //
547 // This ordering allow for efficient vectorization with arbitrary vector width, as
548 // many multiplication constants can be loaded into wider vectors with the correct
549 // alignment. Not maintaining different layouts for different vector lengths does
550 // leave a small amount of performance on the table, but experimentally it seems to
551 // <1% difference, and using a single layout reduces complexity significantly.
552 //
553 C_ASSERT( 2*SYMCRYPT_GHASH_PCLMULQDQ_HPOWERS <= SYMCRYPT_GF128_FIELD_SIZE );
554
555 H = _mm_loadu_si128((__m128i *) pH );
556 H = _mm_shuffle_epi8( H, BYTE_REVERSE_ORDER );
557 Hx = _mm_xor_si128( H, _mm_srli_si128( H, 8 ) );
558
559 _mm_store_si128( &GHASH_H_POWER(expandedKey, 1), H );
560 _mm_store_si128( &GHASH_Hx_POWER(expandedKey, 1), Hx );
561
562 CLMUL_X_3( H, Hx, H, Hx, t0, t1, t2 );
563 CLMUL_3_POST( t0, t1, t2 );
564 MODREDUCE( vMultiplicationConstant, t0, t1, t2, H2 );
565 H2x = _mm_xor_si128( H2, _mm_srli_si128( H2, 8 ) );
566 _mm_store_si128( &GHASH_H_POWER(expandedKey, 2), H2 );
567 _mm_store_si128( &GHASH_Hx_POWER(expandedKey, 2), H2x );
568
569 Hi_even = H2;
570 Hix_even = H2x;
571
572 for( i=2; i<SYMCRYPT_GHASH_PCLMULQDQ_HPOWERS; i+=2 )
573 {
574 CLMUL_X_3( H, Hx, Hi_even, Hix_even, t0, t1, t2 );
575 CLMUL_3_POST( t0, t1, t2 );
576 CLMUL_X_3( H2, H2x, Hi_even, Hix_even, t3, t4, t5 );
577 CLMUL_3_POST( t3, t4, t5 );
578 MODREDUCE( vMultiplicationConstant, t0, t1, t2, Hi_odd );
579 MODREDUCE( vMultiplicationConstant, t3, t4, t5, Hi_even );
580 Hix_odd = _mm_xor_si128( Hi_odd, _mm_srli_si128( Hi_odd, 8 ) );
581 Hix_even = _mm_xor_si128( Hi_even, _mm_srli_si128( Hi_even, 8 ) );
582
583 _mm_store_si128( &GHASH_H_POWER(expandedKey, i + 1), Hi_odd );
584 _mm_store_si128( &GHASH_H_POWER(expandedKey, i + 2), Hi_even );
585 _mm_store_si128( &GHASH_Hx_POWER(expandedKey, i + 1), Hix_odd );
586 _mm_store_si128( &GHASH_Hx_POWER(expandedKey, i + 2), Hix_even );
587 }
588}
589
590
591
592VOID
598 SIZE_T cbData )
599{
600 __m128i state;
601 __m128i data;
602 __m128i a0, a1, a2;
603 __m128i Hi, Hix;
604 SIZE_T i;
606 SIZE_T todo;
607
608 //
609 // To do a BSWAP we need an __m128i value with the bytes
610 //
611
612 __m128i BYTE_REVERSE_ORDER = _mm_set_epi8(
613 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 );
614 __m128i vMultiplicationConstant = _mm_set_epi32( 0, 0, 0xc2000000, 0 );
615
616 state = _mm_loadu_si128( (__m128i *) pState );
617
618 while( nBlocks > 0 )
619 {
620 //
621 // We process the data in blocks of up to SYMCRYPT_GHASH_PCLMULQDQ_HPOWERS blocks
622 //
623 todo = SYMCRYPT_MIN( nBlocks, SYMCRYPT_GHASH_PCLMULQDQ_HPOWERS );
624
625 //
626 // The first block is xorred with the state before multiplying it with a power of H
627 //
628 data = _mm_loadu_si128( (__m128i *) pbData );
629 data = _mm_shuffle_epi8( data, BYTE_REVERSE_ORDER );
631
633 CLMUL_3( state, GHASH_H_POWER(expandedKeyTable, todo), GHASH_Hx_POWER(expandedKeyTable, todo), a0, a1, a2 );
634
635 //
636 // Then we just do an improduct
637 //
638 for( i=1; i<todo; i++ )
639 {
640 data = _mm_loadu_si128( (__m128i *) pbData );
641 data = _mm_shuffle_epi8( data, BYTE_REVERSE_ORDER );
643
644 Hi = _mm_load_si128( &GHASH_H_POWER(expandedKeyTable, todo - i) );
645 Hix = _mm_load_si128( &GHASH_Hx_POWER(expandedKeyTable, todo - i) );
646 CLMUL_ACC_3( data, Hi, Hix, a0, a1, a2 );
647 }
648
649 CLMUL_3_POST( a0, a1, a2 );
650 MODREDUCE( vMultiplicationConstant, a0, a1, a2, state );
651 nBlocks -= todo;
652 }
653
654 _mm_storeu_si128((__m128i *)pState, state );
655}
656
657#ifdef __clang__
658#pragma clang attribute pop
659#else
660#pragma GCC pop_options
661#endif
662
663#endif // CPU_X86 || CPU_AMD64
664
665#if SYMCRYPT_CPU_ARM64
666
667#ifdef __clang__
668#pragma clang attribute push (__attribute__((target("aes"))), apply_to=function)
669#else
670#pragma GCC push_options
671#pragma GCC target("aes")
672#endif
673
674VOID
676SymCryptGHashExpandKeyPmull(
679{
680 int i;
681 __n128 H, Hx, H2, H2x;
682 __n128 t0, t1, t2, t3, t4, t5;
683 __n128 Hi_even, Hix_even, Hi_odd, Hix_odd;
684 const __n64 vMultiplicationConstant = SYMCRYPT_SET_N64_U64(0xc200000000000000);
685 //
686 // Our expanded key consists of a list of N=SYMCRYPT_GHASH_PMULL_HPOWERS
687 // powers of H. The first entry is H^N, the next H^(N-1), then H^(N-2), ...
688 //
689 // For each power we store two 128-bit values. The first is H^i (Hi) and the second
690 // contains the two halves of H^i xorred with each other in the lower 64 bits (Hix).
691 //
692 // We keep all of the Hi entries together in the first half of the expanded key
693 // table, and all of the Hix entries together in the second half of the table.
694 //
695 // This ordering allow for efficient vectorization with arbitrary vector width, as
696 // many multiplication constants can be loaded into wider vectors with the correct
697 // alignment. Not maintaining different layouts for different vector lengths does
698 // leave a small amount of performance on the table, but experimentally it seems to
699 // <1% difference, and using a single layout reduces complexity significantly.
700 //
701 C_ASSERT( 2*SYMCRYPT_GHASH_PMULL_HPOWERS <= SYMCRYPT_GF128_FIELD_SIZE );
702
703 H = *(__n128 *) pH;
704 Hx = vrev64q_u8( H );
705 H = vextq_u8( Hx, Hx, 8 );
706 Hx = veorq_u8( H, Hx );
707
708 GHASH_H_POWER(expandedKey, 1) = H;
709 GHASH_Hx_POWER(expandedKey, 1) = Hx;
710
711 CLMUL_X_3( H, Hx, H, Hx, t0, t1, t2 );
712 CLMUL_3_POST( t0, t1, t2 );
713 MODREDUCE( vMultiplicationConstant, t0, t1, t2, H2 );
714 H2x = veorq_u8( H2, vextq_u8( H2, H2, 8 ) );
715 GHASH_H_POWER(expandedKey, 2) = H2;
716 GHASH_Hx_POWER(expandedKey, 2) = H2x;
717
718 Hi_even = H2;
719 Hix_even = H2x;
720
721 for( i=2; i<SYMCRYPT_GHASH_PMULL_HPOWERS; i+=2 )
722 {
723 CLMUL_X_3( H, Hx, Hi_even, Hix_even, t0, t1, t2 );
724 CLMUL_3_POST( t0, t1, t2 );
725 CLMUL_X_3( H2, H2x, Hi_even, Hix_even, t3, t4, t5 );
726 CLMUL_3_POST( t3, t4, t5 );
727 MODREDUCE( vMultiplicationConstant, t0, t1, t2, Hi_odd );
728 MODREDUCE( vMultiplicationConstant, t3, t4, t5, Hi_even );
729 Hix_odd = veorq_u8( Hi_odd, vextq_u8( Hi_odd, Hi_odd, 8 ) );
730 Hix_even = veorq_u8( Hi_even, vextq_u8( Hi_even, Hi_even, 8 ) );
731
732 GHASH_H_POWER(expandedKey, i + 1) = Hi_odd;
733 GHASH_H_POWER(expandedKey, i + 2) = Hi_even;
734 GHASH_Hx_POWER(expandedKey, i + 1) = Hix_odd;
735 GHASH_Hx_POWER(expandedKey, i + 2) = Hix_even;
736 }
737}
738
739VOID
741SymCryptGHashAppendDataPmull(
745 SIZE_T cbData )
746{
747 __n128 state;
748 __n128 data, datax;
749 __n128 a0, a1, a2;
750 __n128 Hi, Hix;
751 const __n64 vMultiplicationConstant = SYMCRYPT_SET_N64_U64(0xc200000000000000);
752 SIZE_T i;
754 SIZE_T todo;
755
756 state = *(__n128 *) pState;
757
758 while( nBlocks > 0 )
759 {
760 //
761 // We process the data in blocks of up to SYMCRYPT_GHASH_PMULL_HPOWERS blocks
762 //
763 todo = SYMCRYPT_MIN( nBlocks, SYMCRYPT_GHASH_PMULL_HPOWERS );
764
765 //
766 // The first block is xorred with the state before multiplying it with a power of H
767 //
768 data = *(__n128 *)pbData;
771
772 state = veorq_u8( state, data );
773 CLMUL_3( state, GHASH_H_POWER(expandedKeyTable, todo), GHASH_Hx_POWER(expandedKeyTable, todo), a0, a1, a2 );
774
775 //
776 // Then we just do an improduct
777 //
778 for( i=1; i<todo; i++ )
779 {
780 // we can avoid an EXT here by precomputing datax for CLMUL_ACCX_3
781 datax = vrev64q_u8( *(__n128 *)pbData );
782 data = vextq_u8( datax, datax, 8 );
783 datax = veorq_u8( data, datax );
785
786 Hi = GHASH_H_POWER(expandedKeyTable, todo - i);
787 Hix = GHASH_Hx_POWER(expandedKeyTable, todo - i);
788 CLMUL_ACCX_3( data, datax, Hi, Hix, a0, a1, a2 );
789 }
790
791 CLMUL_3_POST( a0, a1, a2 );
792 MODREDUCE( vMultiplicationConstant, a0, a1, a2, state );
793 nBlocks -= todo;
794 }
795
796 *(__n128 *) pState = state;
797}
798
799#ifdef __clang__
800#pragma clang attribute pop
801#else
802#pragma GCC pop_options
803#endif
804
805#endif // CPU_ARM64
806
807
808
810// Stuff around the core algorithm implementation functions
811//
812
813
814VOID
819{
820#if SYMCRYPT_CPU_X86
821 PSYMCRYPT_GF128_ELEMENT pExpandedKeyTable;
822 SYMCRYPT_EXTENDED_SAVE_DATA SaveData;
823
824 //
825 // Initialize offset into table space for 16-alignment.
826 //
827 expandedKey->tableOffset = (0 -((UINT_PTR) &expandedKey->tableSpace[0])) % sizeof(SYMCRYPT_GF128_ELEMENT);
828
829 pExpandedKeyTable = (PSYMCRYPT_GF128_ELEMENT)&expandedKey->tableSpace[expandedKey->tableOffset];
830
832 {
833 //
834 // We can only use the PCLMULQDQ data representation if the SaveXmm never fails.
835 // This is one of the CPU features required.
836 // We check anyway...
837 //
838 if( SymCryptSaveXmm( &SaveData ) != SYMCRYPT_NO_ERROR )
839 {
840 SymCryptFatal( 'pclm' );
841 }
842 SymCryptGHashExpandKeyPclmulqdq( pExpandedKeyTable, pH );
843 SymCryptRestoreXmm( &SaveData );
844 } else if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_SSE2 ) && SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR )
845 {
846 SymCryptGHashExpandKeyXmm( pExpandedKeyTable, pH );
847 SymCryptRestoreXmm( &SaveData );
848 } else {
849 SymCryptGHashExpandKeyC( pExpandedKeyTable, pH );
850 }
851
852#elif SYMCRYPT_CPU_AMD64
853 PSYMCRYPT_GF128_ELEMENT pExpandedKeyTable;
854 pExpandedKeyTable = &expandedKey->table[0];
855
857 {
858 SymCryptGHashExpandKeyPclmulqdq( pExpandedKeyTable, pH );
859 } else if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_SSE2 ) )
860 {
861 SymCryptGHashExpandKeyXmm( pExpandedKeyTable, pH );
862 } else {
863 SymCryptGHashExpandKeyC( pExpandedKeyTable, pH );
864 }
865
866#elif SYMCRYPT_CPU_ARM64
867 PSYMCRYPT_GF128_ELEMENT pExpandedKeyTable;
868 pExpandedKeyTable = &expandedKey->table[0];
869
870 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_PMULL ) )
871 {
872 SymCryptGHashExpandKeyPmull( pExpandedKeyTable, pH );
873 } else {
874 SymCryptGHashExpandKeyC( pExpandedKeyTable, pH );
875 }
876
877#else
878 SymCryptGHashExpandKeyC( &expandedKey->table[0], pH ); // Default expansion (does not need alignment)
879#endif
880}
881
882VOID
888 SIZE_T cbData )
889{
890#if SYMCRYPT_CPU_X86
891 PCSYMCRYPT_GF128_ELEMENT pExpandedKeyTable;
892 SYMCRYPT_EXTENDED_SAVE_DATA SaveData;
893
894 pExpandedKeyTable = (PSYMCRYPT_GF128_ELEMENT)&expandedKey->tableSpace[expandedKey->tableOffset];
895
897 {
898 if( SymCryptSaveXmm( &SaveData ) != SYMCRYPT_NO_ERROR )
899 {
900 SymCryptFatal( 'pclm' );
901 }
903 SymCryptRestoreXmm( &SaveData );
904 } else if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_SSE2 ) && SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR )
905 {
906 SymCryptGHashAppendDataXmm( pExpandedKeyTable, pState, pbData, cbData );
907 SymCryptRestoreXmm( &SaveData );
908 } else {
909 SymCryptGHashAppendDataC( pExpandedKeyTable, pState, pbData, cbData );
910 }
911
912#elif SYMCRYPT_CPU_AMD64
913 PCSYMCRYPT_GF128_ELEMENT pExpandedKeyTable;
914
915 pExpandedKeyTable = &expandedKey->table[0];
917 {
919 } else if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_SSE2 ) )
920 {
921 SymCryptGHashAppendDataXmm( pExpandedKeyTable, pState, pbData, cbData );
922 } else {
923 SymCryptGHashAppendDataC( pExpandedKeyTable, pState, pbData, cbData );
924 }
925#elif SYMCRYPT_CPU_ARM
926 PCSYMCRYPT_GF128_ELEMENT pExpandedKeyTable;
927
928 pExpandedKeyTable = &expandedKey->table[0];
929 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON ) )
930 {
931 SymCryptGHashAppendDataNeon( pExpandedKeyTable, pState, pbData, cbData );
932 } else {
933 SymCryptGHashAppendDataC( pExpandedKeyTable, pState, pbData, cbData );
934 }
935#elif SYMCRYPT_CPU_ARM64
936 PCSYMCRYPT_GF128_ELEMENT pExpandedKeyTable;
937
938 pExpandedKeyTable = &expandedKey->table[0];
939 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON_PMULL ) )
940 {
941 SymCryptGHashAppendDataPmull( pExpandedKeyTable, pState, pbData, cbData );
942 } else if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON ) )
943 {
944 SymCryptGHashAppendDataNeon( pExpandedKeyTable, pState, pbData, cbData );
945 } else {
946 SymCryptGHashAppendDataC( pExpandedKeyTable, pState, pbData, cbData );
947 }
948#else
949 SymCryptGHashAppendDataC( &expandedKey->table[0], pState, pbData, cbData );
950#endif
951}
COMPILER_DEPENDENT_INT64 INT64
Definition: actypes.h:132
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
static int state
Definition: maze.c:121
@ R
Definition: bidi.c:79
VOID SaveData(HWND hwndDlg)
Definition: volume.c:368
void _mm_storeu_si128(__m128i_u *p, __m128i b)
Definition: emmintrin.h:1684
__m128i _mm_set_epi8(char b15, char b14, char b13, char b12, char b11, char b10, char b9, char b8, char b7, char b6, char b5, char b4, char b3, char b2, char b1, char b0)
Definition: emmintrin.h:1610
__m128i _mm_set_epi32(int i3, int i2, int i1, int i0)
Definition: emmintrin.h:1598
void _mm_store_si128(__m128i *p, __m128i b)
Definition: emmintrin.h:1679
__m128i _mm_setzero_si128(void)
Definition: emmintrin.h:1674
__m128i _mm_xor_si128(__m128i a, __m128i b)
Definition: emmintrin.h:1345
__m128i _mm_load_si128(__m128i const *p)
Definition: emmintrin.h:1556
__m128i _mm_and_si128(__m128i a, __m128i b)
Definition: emmintrin.h:1330
__m128i _mm_srli_si128(__m128i a, int imm)
Definition: emmintrin.h:1414
__m128i _mm_add_epi32(__m128i a, __m128i b)
Definition: emmintrin.h:1137
__m128i _mm_cmpgt_epi32(__m128i a, __m128i b)
Definition: emmintrin.h:1477
__m128i _mm_loadu_si128(__m128i_u const *p)
Definition: emmintrin.h:1561
VOID SYMCRYPT_CALL SymCryptGHashAppendDataC(_In_reads_(SYMCRYPT_GF128_FIELD_SIZE) PCSYMCRYPT_GF128_ELEMENT expandedKeyTable, _Inout_ PSYMCRYPT_GF128_ELEMENT pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: ghash.c:61
VOID SYMCRYPT_CALL SymCryptGHashExpandKeyC(_Out_writes_(SYMCRYPT_GF128_FIELD_SIZE) PSYMCRYPT_GF128_ELEMENT expandedKey, _In_reads_(SYMCRYPT_GF128_BLOCK_SIZE) PCBYTE pH)
Definition: ghash.c:27
VOID SYMCRYPT_CALL SymCryptGHashResult(_In_ PCSYMCRYPT_GF128_ELEMENT pState, _Out_writes_(SYMCRYPT_GF128_BLOCK_SIZE) PBYTE pbResult)
Definition: ghash.c:108
VOID SYMCRYPT_CALL SymCryptGHashExpandKey(_Out_ PSYMCRYPT_GHASH_EXPANDED_KEY expandedKey, _In_reads_(SYMCRYPT_GF128_BLOCK_SIZE) PCBYTE pH)
Definition: ghash.c:816
VOID SYMCRYPT_CALL SymCryptGHashAppendData(_In_ PCSYMCRYPT_GHASH_EXPANDED_KEY expandedKey, _Inout_ PSYMCRYPT_GF128_ELEMENT pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
Definition: ghash.c:884
VOID SYMCRYPT_CALL SymCryptGHashExpandKeyXmm(_Out_writes_(SYMCRYPT_GF128_FIELD_SIZE) PSYMCRYPT_GF128_ELEMENT expandedKey, _In_reads_(SYMCRYPT_GF128_BLOCK_SIZE) PCBYTE pH)
Definition: ghash.c:122
#define UINT64_NEG(x)
#define GF128_FIELD_R_BYTE
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble t
Definition: gl.h:2047
GLenum GLint GLuint mask
Definition: glext.h:6028
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
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 GLint GLint j
Definition: glfuncs.h:250
#define C_ASSERT(e)
Definition: intsafe.h:73
BOOL todo
Definition: filedlg.c:313
static const struct update_accum a1
Definition: msg.c:534
static const struct update_accum a2
Definition: msg.c:542
#define H
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_(s)
Definition: no_sal2.h:176
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
BYTE * PBYTE
Definition: pedump.c:66
#define T(num)
Definition: thunks.c:311
#define SYMCRYPT_CPU_FEATURES_FOR_PCLMULQDQ_CODE
Definition: sc_lib.h:305
VOID SYMCRYPT_CALL SymCryptGHashAppendDataXmm(_In_reads_(SYMCRYPT_GF128_FIELD_SIZE) PCSYMCRYPT_GF128_ELEMENT expandedKeyTable, _Inout_ PSYMCRYPT_GF128_ELEMENT pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptGHashAppendDataPclmulqdq(_In_reads_(SYMCRYPT_GF128_FIELD_SIZE) PCSYMCRYPT_GF128_ELEMENT expandedKeyTable, _Inout_ PSYMCRYPT_GF128_ELEMENT pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptGHashAppendDataNeon(_In_reads_(SYMCRYPT_GF128_FIELD_SIZE) PCSYMCRYPT_GF128_ELEMENT expandedKeyTable, _Inout_ PSYMCRYPT_GF128_ELEMENT pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
#define REVERSE_BYTES(Destination, Source)
Definition: scsi.h:3511
#define H2(x, y, z)
Definition: md5.c:54
#define R1(v, w, x, y, z, i)
Definition: sha1.c:36
#define R0(v, w, x, y, z, i)
Definition: sha1.c:35
static const BYTE pbResult[]
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
#define SYMCRYPT_LOAD_MSBFIRST32(p)
Definition: symcrypt.h:303
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
_Analysis_noreturn_ VOID SYMCRYPT_CALL SymCryptFatal(UINT32 fatalCode)
#define SYMCRYPT_LOAD_MSBFIRST64(p)
Definition: symcrypt.h:304
#define SYMCRYPT_STORE_MSBFIRST64(p, v)
Definition: symcrypt.h:312
#define SYMCRYPT_ALIGN
#define SYMCRYPT_CALL
const SYMCRYPT_GF128_ELEMENT * PCSYMCRYPT_GF128_ELEMENT
#define SYMCRYPT_CPU_FEATURES_PRESENT(x)
#define SYMCRYPT_GF128_FIELD_SIZE
#define SYMCRYPT_GF128_BLOCK_SIZE
#define SYMCRYPT_MIN(_a, _b)
* PSYMCRYPT_GF128_ELEMENT
PCBYTE PBYTE SIZE_T cbData
const SYMCRYPT_GHASH_EXPANDED_KEY * PCSYMCRYPT_GHASH_EXPANDED_KEY
SYMCRYPT_GF128_ELEMENT
PSYMCRYPT_COMMON_HASH_STATE pState
const BYTE * PCBYTE
PCBYTE pbData
* PSYMCRYPT_GHASH_EXPANDED_KEY
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59