ReactOS 0.4.17-dev-1005-g171e1de
mlkem_primitives.c
Go to the documentation of this file.
1//
2// mlkem_primitives.c ML-KEM related functionality
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7#include "precomp.h"
8
9//
10// Current approach is to represent polynomial ring elements as a 512-byte buffer (256 UINT16s).
11//
12
13// Coefficients are added and subtracted when polynomials are in the NTT domain and in the lattice domain.
14//
15// Coefficients are only multiplied in the NTT/INTT operations, and in MulAdd which only operates on
16// polynomials in NTT form.
17// We choose to perform modular multiplication exclusively using Montgomery multiplication, that is, we choose
18// a Montgomery divisor R, and modular multiplication always divides by R, as this make reduction logic easy
19// and quick.
20// i.e. MontMul(a,b) -> ((a*b) / R) mod Q
21//
22// For powers of Zeta used in as multiplication twiddle factors in NTT/INTT and base polynomial multiplication,
23// we pre-multiply the constants by R s.t.
24// MontMul(x, twiddleForZetaToTheK) -> x*(Zeta^K) mod Q.
25//
26// Most other modular multiplication can be done with a fixup deferred until the INTT. The one exception is in key
27// generation, where A o s + e = t, we need to pre-multiply s'
28
29// R = 2^16
32
33// NegQInvModR = -Q^(-1) mod R
35
36// Rsqr = R^2 = (1<<32) mod Q
38// RsqrTimesNegQInvModR = R^2 = ((1<<32) mod Q) * -Q^(-1) mod R
40
41//
42// Zeta tables.
43// Zeta = 17, which is a primitive 256-th root of unity modulo Q
44//
45// In ML-KEM we use powers of zeta to convert to and from NTT form
46// and to perform multiplication between polynomials in NTT form
47//
48
49// This table is a lookup for (Zeta^(BitRev(index)) * R) mod Q
50// Used in NTT and INTT
51// i.e. element 1 is Zeta^(BitRev(1)) * (2^16) mod Q == (17^64)*(2^16) mod 3329 == 2571
52//
53// MlKemZetaBitRevTimesR = [ (pow(17, bitRev(i), 3329) << 16) % 3329 for i in range(128) ]
55{
56 2285, 2571, 2970, 1812, 1493, 1422, 287, 202,
57 3158, 622, 1577, 182, 962, 2127, 1855, 1468,
58 573, 2004, 264, 383, 2500, 1458, 1727, 3199,
59 2648, 1017, 732, 608, 1787, 411, 3124, 1758,
60 1223, 652, 2777, 1015, 2036, 1491, 3047, 1785,
61 516, 3321, 3009, 2663, 1711, 2167, 126, 1469,
62 2476, 3239, 3058, 830, 107, 1908, 3082, 2378,
63 2931, 961, 1821, 2604, 448, 2264, 677, 2054,
64 2226, 430, 555, 843, 2078, 871, 1550, 105,
65 422, 587, 177, 3094, 3038, 2869, 1574, 1653,
66 3083, 778, 1159, 3182, 2552, 1483, 2727, 1119,
67 1739, 644, 2457, 349, 418, 329, 3173, 3254,
68 817, 1097, 603, 610, 1322, 2044, 1864, 384,
69 2114, 3193, 1218, 1994, 2455, 220, 2142, 1670,
70 2144, 1799, 2051, 794, 1819, 2475, 2459, 478,
71 3221, 3021, 996, 991, 958, 1869, 1522, 1628,
72};
73
74// This table is a lookup for ((Zeta^(BitRev(index)) * R) mod Q) * -Q^(-1) mod R
75// Used in NTT and INTT
76//
77// MlKemZetaBitRevTimesRTimesNegQInvModR = [ (((pow(17, bitRev(i), Q) << 16) % Q) * 3327) & 0xffff for i in range(128) ]
79{
80 19, 34037, 50790, 64748, 52011, 12402, 37345, 16694,
81 20906, 37778, 3799, 15690, 54846, 64177, 11201, 34372,
82 5827, 48172, 26360, 29057, 59964, 1102, 44097, 26241,
83 28072, 41223, 10532, 56736, 47109, 56677, 38860, 16162,
84 5689, 6516, 64039, 34569, 23564, 45357, 44825, 40455,
85 12796, 38919, 49471, 12441, 56401, 649, 25986, 37699,
86 45652, 28249, 15886, 8898, 28309, 56460, 30198, 47286,
87 52109, 51519, 29155, 12756, 48704, 61224, 24155, 17914,
88 334, 54354, 11477, 52149, 32226, 14233, 45042, 21655,
89 27738, 52405, 64591, 4586, 14882, 42443, 59354, 60043,
90 33525, 32502, 54905, 35218, 36360, 18741, 28761, 52897,
91 18485, 45436, 47975, 47011, 14430, 46007, 5275, 12618,
92 31183, 45239, 40101, 63390, 7382, 50180, 41144, 32384,
93 20926, 6279, 54590, 14902, 41321, 11044, 48546, 51066,
94 55200, 21497, 7933, 20198, 22501, 42325, 54629, 17442,
95 33899, 23859, 36892, 20257, 41538, 57779, 17422, 42404,
96};
97
98// This table is a lookup for ((Zeta^(2*BitRev(index) + 1) * R) mod Q)
99// Used in multiplication of 2 NTT-form polynomials
100//
101// zetaTwoTimesBitRevPlus1TimesR = [ (pow(17, 2*bitRev(i)+1, 3329) << 16) % 3329 for i in range(128) ]
103{
104 2226, 1103, 430, 2899, 555, 2774, 843, 2486,
105 2078, 1251, 871, 2458, 1550, 1779, 105, 3224,
106 422, 2907, 587, 2742, 177, 3152, 3094, 235,
107 3038, 291, 2869, 460, 1574, 1755, 1653, 1676,
108 3083, 246, 778, 2551, 1159, 2170, 3182, 147,
109 2552, 777, 1483, 1846, 2727, 602, 1119, 2210,
110 1739, 1590, 644, 2685, 2457, 872, 349, 2980,
111 418, 2911, 329, 3000, 3173, 156, 3254, 75,
112 817, 2512, 1097, 2232, 603, 2726, 610, 2719,
113 1322, 2007, 2044, 1285, 1864, 1465, 384, 2945,
114 2114, 1215, 3193, 136, 1218, 2111, 1994, 1335,
115 2455, 874, 220, 3109, 2142, 1187, 1670, 1659,
116 2144, 1185, 1799, 1530, 2051, 1278, 794, 2535,
117 1819, 1510, 2475, 854, 2459, 870, 478, 2851,
118 3221, 108, 3021, 308, 996, 2333, 991, 2338,
119 958, 2371, 1869, 1460, 1522, 1807, 1628, 1701,
120};
121
127{
129
131
134
135 return pDst;
136}
137
143{
145
147
150
151 return pDst;
152}
153
159 UINT32 nRows )
160{
164 UINT32 i;
165 PBYTE pbTmp = pbBuffer + sizeof(SYMCRYPT_MLKEM_VECTOR);
166
168
169 SYMCRYPT_ASSERT( nRows > 0 );
171
172 pVector->nRows = nRows;
173 pVector->cbTotalSize = cbBuffer;
174
175 for( i=0; i<nRows; i++ )
176 {
178 if( peTmp == NULL )
179 {
180 goto cleanup;
181 }
182
184 }
185
186 SYMCRYPT_ASSERT( pbTmp == (pbBuffer + cbBuffer) );
187
188 pDst = pVector;
189
190cleanup:
191 return pDst;
192}
193
199 UINT32 nRows )
200{
203 UINT32 i;
204 PBYTE pbTmp = pbBuffer + sizeof(SYMCRYPT_MLKEM_MATRIX);
205
207
208 SYMCRYPT_ASSERT( nRows > 0 );
210
211 pMatrix->nRows = nRows;
212 pMatrix->cbTotalSize = cbBuffer;
213
214 for( i=0; i<(nRows*nRows); i++ )
215 {
217 if( pMatrix->apPolyElements[i] == NULL )
218 {
219 goto cleanup;
220 }
221
223 }
224
225 SYMCRYPT_ASSERT( pbTmp == (pbBuffer + cbBuffer) );
226
227 pDst = pMatrix;
228
229cleanup:
230 return pDst;
231}
232
233#if SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_X86 | SYMCRYPT_CPU_ARM64
234
235#if SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_X86
236
237#ifdef __clang__
238#pragma clang attribute push (__attribute__((target("sse2"))), apply_to=function)
239#else
240#pragma GCC push_options
241#pragma GCC target("sse2")
242#endif
243
244#define VEC128_TYPE_UINT16 __m128i
245
246#define VEC128_LOAD_UINT16( addr ) _mm_loadu_si128( (__m128i*) (addr) )
247#define VEC64_LOAD_UINT16( addr ) _mm_loadl_epi64( (__m128i const*) (addr) )
248#define VEC32_LOAD_UINT16( addr ) _mm_cvtsi32_si128( SYMCRYPT_LOAD_LSBFIRST32( addr ) )
249
250#define VEC128_STORE_UINT16( addr, vec ) _mm_storeu_si128( (__m128i*) (addr), (vec) )
251#define VEC64_STORE_UINT16( addr, vec ) _mm_storel_epi64( (__m128i*) (addr), (vec) )
252#define VEC32_STORE_UINT16( addr, vec ) SYMCRYPT_STORE_LSBFIRST32( (addr), _mm_cvtsi128_si32( vec ) )
253
254#define VEC128_SET_UINT16( value ) _mm_set1_epi16( (value) )
255
256#define VEC128_MOD_SUB_UINT16( res, a, b, Q, zero, tmp1 ) \
257 /* res = a - b */ \
258 res = _mm_sub_epi16( a, b ); \
259 /* tmp1 = (a - b) < 0 ? -1 : 0 */ \
260 tmp1 = _mm_cmpgt_epi16( zero, res ); \
261 /* tmp1 = (a - b) < 0 ? Q : 0 */ \
262 tmp1 = _mm_and_si128( tmp1, Q ); \
263 /* res = (a - b) mod Q */ \
264 res = _mm_add_epi16( res, tmp1 );
265
266#define VEC128_MOD_ADD_UINT16( res, a, b, Q, tmp1 ) \
267 /* res = a + b */ \
268 res = _mm_add_epi16( a, b ); \
269 /* tmp1 = (a + b) < Q ? -1 : 0 */ \
270 tmp1 = _mm_cmpgt_epi16( Q, res ); \
271 /* tmp1 = (a + b) < Q ? 0 : Q */ \
272 tmp1 = _mm_andnot_si128( tmp1, Q ); \
273 /* res = (a + b) mod Q */ \
274 res = _mm_sub_epi16( res, tmp1 );
275
276#define VEC128_MONTGOMERY_MUL_UINT16( res, a, b, bTimesNegQInvModR, Q, zero, one, tmp1, tmp2 ) \
277 /* tmp1 = a *low bTimesNegQInvModR */ \
278 tmp1 = _mm_mullo_epi16( a, bTimesNegQInvModR ); \
279 /* res = a *high b */ \
280 res = _mm_mulhi_epu16( a, b ); \
281 /* tmp2 = (tmp1 == 0) ? -1 : 0 */ \
282 tmp2 = _mm_cmpeq_epi16( tmp1, zero ); \
283 /* tmp1 = (a *low bTimesNegQInvModR) *high Q */ \
284 tmp1 = _mm_mulhi_epu16( tmp1, Q ); \
285 /* res = a *high b + 1 */ \
286 res = _mm_add_epi16( res, one ); \
287 /* res = a *high b (+ 1 if a != 0) */ \
288 res = _mm_add_epi16( res, tmp2 ); \
289 /* res = a *high b + inv*Q (+ 1 if a != 0) */ \
290 res = _mm_add_epi16( res, tmp1 ); \
291 /* res = (a*b + inv*Q >> 16) mod Q */ \
292 VEC128_MOD_SUB_UINT16( res, res, Q, Q, zero, tmp1 );
293
294#elif SYMCRYPT_CPU_ARM64
295
296#define VEC128_TYPE_UINT16 uint16x8_t
297
298#define VEC128_LOAD_UINT16( addr ) vld1q_u16( addr )
299#define VEC64_LOAD_UINT16( addr ) vld1q_dup_u64( addr )
300#define VEC32_LOAD_UINT16( addr ) vld1q_dup_u32( addr )
301
302#define VEC128_STORE_UINT16( addr, vec ) vst1q_u16( (addr), (vec) )
303#define VEC64_STORE_UINT16( addr, vec ) vst1_u16( (uint16_t*) (addr), vget_low_u16(vec) )
304#define VEC32_STORE_UINT16( addr, vec ) vst1_lane_u32( (PBYTE) (addr), vget_low_u32(vec), 0 )
305
306#define VEC128_SET_UINT16( value ) vdupq_n_u16( (value) )
307
308#define VEC128_MOD_SUB_UINT16( res, a, b, Q, zero, tmp1 ) \
309 /* res = a - b */ \
310 res = vsubq_u16( a, b ); \
311 /* tmp1 = (a - b) < 0 ? -1 : 0 */ \
312 tmp1 = vcltzq_s16( res ); \
313 /* tmp1 = (a - b) < 0 ? Q : 0 */ \
314 tmp1 = vandq_u16( tmp1, Q ); \
315 /* res = (a - b) mod Q */ \
316 res = vaddq_u16( res, tmp1 );
317
318#define VEC128_MOD_ADD_UINT16( res, a, b, Q, tmp1 ) \
319 /* res = a + b */ \
320 res = vaddq_u16( a, b ); \
321 /* tmp1 = (a + b) >= Q ? -1 : 0 */ \
322 tmp1 = vcgeq_u16( res, Q ); \
323 /* tmp1 = (a + b) >= Q ? Q : 0 */ \
324 tmp1 = vandq_u16( tmp1, Q ); \
325 /* res = (a + b) mod Q */ \
326 res = vsubq_u16( res, tmp1 );
327
328#define VEC128_MONTGOMERY_MUL_UINT16( res, a, b, bTimesNegQInvModR, Q, zero, one, tmp1, tmp2 ) \
329 /* tmp1 = a *low bTimesNegQInvModR */ \
330 tmp1 = vmulq_u16( a, bTimesNegQInvModR ); \
331 /* tmp2 = a*b [0-3]*/ \
332 tmp2 = vmull_u16( vget_low_u16(a), vget_low_u16(b) ); \
333 /* res = a*b [4-7]*/ \
334 res = vmull_high_u16( a, b ); \
335 /* tmp2 = a*b + inv*Q [0-3]*/ \
336 tmp2 = vmlal_u16( tmp2, vget_low_u16(tmp1), vget_low_u16(Q) ); \
337 /* res = a*b + inv*Q [4-7]*/ \
338 res = vmlal_high_u16( res, tmp1, Q ); \
339 /* res = a*b + inv*Q >> 16 */ \
340 res = vuzp2q_u16( tmp2, res ); \
341 /* res = (a*b + inv*Q >> 16) mod Q */ \
342 VEC128_MOD_SUB_UINT16( res, res, Q, Q, zero, tmp1 );
343
344#endif
345
347VOID
349SymCryptMlKemPolyElementNTTLayerVec128(
351 UINT32 k,
352 UINT32 len )
353{
354 UINT32 start, j;
355 VEC128_TYPE_UINT16 vc0, vc1, vTmp0, vTmp1, vc1Twiddle, vTwiddleFactor, vTwiddleFactorMont, vQ, vZero, vOne;
356
357 SYMCRYPT_ASSERT( len >= 2 );
358
359 vQ = VEC128_SET_UINT16( SYMCRYPT_MLKEM_Q );
360 vZero = VEC128_SET_UINT16( 0 );
361 vOne = VEC128_SET_UINT16( 1 );
362
363 for( start=0; start<256; start+=(2*len) )
364 {
365 vTwiddleFactor = VEC128_SET_UINT16( MlKemZetaBitRevTimesR[k] );
366 vTwiddleFactorMont = VEC128_SET_UINT16( MlKemZetaBitRevTimesRTimesNegQInvModR[k] );
367 k++;
368 for( j=0; j<len; j+=8 )
369 {
370 if( len >= 8 )
371 {
372 vc0 = VEC128_LOAD_UINT16( &(peSrc->coeffs[start+j] ) );
373 vc1 = VEC128_LOAD_UINT16( &(peSrc->coeffs[start+j+len]) );
374 }
375 else if ( len == 4 )
376 {
377 vc0 = VEC64_LOAD_UINT16( &(peSrc->coeffs[start+j] ) );
378 vc1 = VEC64_LOAD_UINT16( &(peSrc->coeffs[start+j+len]) );
379 }
380 else /*if ( len == 2 )*/
381 {
382 vc0 = VEC32_LOAD_UINT16( &(peSrc->coeffs[start+j] ) );
383 vc1 = VEC32_LOAD_UINT16( &(peSrc->coeffs[start+j+len]) );
384 }
385
386 // c1TimesTwiddle = twiddleFactor * c1 mod Q;
387 VEC128_MONTGOMERY_MUL_UINT16( vc1Twiddle, vc1, vTwiddleFactor, vTwiddleFactorMont, vQ, vZero, vOne, vTmp0, vTmp1 );
388 // c1 = c0 - c1TimesTwiddle mod Q
389 VEC128_MOD_SUB_UINT16( vc1, vc0, vc1Twiddle, vQ, vZero, vTmp0 );
390 // c0 = c0 + c1TimesTwiddle mod Q
391 VEC128_MOD_ADD_UINT16( vc0, vc0, vc1Twiddle, vQ, vTmp1 );
392
393 if( len >= 8 )
394 {
395 VEC128_STORE_UINT16( &(peSrc->coeffs[start+j] ), vc0 );
396 VEC128_STORE_UINT16( &(peSrc->coeffs[start+j+len]), vc1 );
397 }
398 else if ( len == 4 )
399 {
400 VEC64_STORE_UINT16( &(peSrc->coeffs[start+j] ), vc0 );
401 VEC64_STORE_UINT16( &(peSrc->coeffs[start+j+len]), vc1 );
402 }
403 else /*if ( len == 2 )*/
404 {
405 VEC32_STORE_UINT16( &(peSrc->coeffs[start+j] ), vc0 );
406 VEC32_STORE_UINT16( &(peSrc->coeffs[start+j+len]), vc1 );
407 }
408 }
409 }
410}
411
413VOID
415SymCryptMlKemPolyElementINTTLayerVec128(
417 UINT32 k,
418 UINT32 len )
419{
420 UINT32 start, j;
421 VEC128_TYPE_UINT16 vc0, vc1, vTmp0, vTmp1, vTmp2, vTwiddleFactor, vTwiddleFactorMont, vQ, vZero, vOne;
422
423 SYMCRYPT_ASSERT( len >= 2 );
424
425 vQ = VEC128_SET_UINT16( SYMCRYPT_MLKEM_Q );
426 vZero = VEC128_SET_UINT16( 0 );
427 vOne = VEC128_SET_UINT16( 1 );
428
429 for( start=0; start<256; start+=(2*len) )
430 {
431 vTwiddleFactor = VEC128_SET_UINT16( MlKemZetaBitRevTimesR[k] );
432 vTwiddleFactorMont = VEC128_SET_UINT16( MlKemZetaBitRevTimesRTimesNegQInvModR[k] );
433 k--;
434 for( j=0; j<len; j+=8 )
435 {
436 if( len >= 8 )
437 {
438 vc0 = VEC128_LOAD_UINT16( &(peSrc->coeffs[start+j] ) );
439 vc1 = VEC128_LOAD_UINT16( &(peSrc->coeffs[start+j+len]) );
440 }
441 else if ( len == 4 )
442 {
443 vc0 = VEC64_LOAD_UINT16( &(peSrc->coeffs[start+j] ) );
444 vc1 = VEC64_LOAD_UINT16( &(peSrc->coeffs[start+j+len]) );
445 }
446 else /*if ( len == 2 )*/
447 {
448 vc0 = VEC32_LOAD_UINT16( &(peSrc->coeffs[start+j] ) );
449 vc1 = VEC32_LOAD_UINT16( &(peSrc->coeffs[start+j+len]) );
450 }
451
452 // tmp = c0 + c1 mod Q
453 VEC128_MOD_ADD_UINT16( vTmp2, vc0, vc1, vQ, vTmp0 );
454 // c1 = c1 - c0 mod Q
455 VEC128_MOD_SUB_UINT16( vc1, vc1, vc0, vQ, vZero, vTmp1 );
456 // c1 = twiddleFactor * c1;
457 VEC128_MONTGOMERY_MUL_UINT16( vc1, vc1, vTwiddleFactor, vTwiddleFactorMont, vQ, vZero, vOne, vTmp0, vTmp1 );
458
459 if( len >= 8 )
460 {
461 VEC128_STORE_UINT16( &(peSrc->coeffs[start+j] ), vTmp2 );
462 VEC128_STORE_UINT16( &(peSrc->coeffs[start+j+len]), vc1 );
463 }
464 else if ( len == 4 )
465 {
466 VEC64_STORE_UINT16( &(peSrc->coeffs[start+j] ), vTmp2 );
467 VEC64_STORE_UINT16( &(peSrc->coeffs[start+j+len]), vc1 );
468 }
469 else /*if ( len == 2 )*/
470 {
471 VEC32_STORE_UINT16( &(peSrc->coeffs[start+j] ), vTmp2 );
472 VEC32_STORE_UINT16( &(peSrc->coeffs[start+j+len]), vc1 );
473 }
474 }
475 }
476}
477
478#endif
479
481UINT32
484 UINT32 a,
485 UINT32 b )
486{
487 UINT32 res;
488
491
492 res = a + b - SYMCRYPT_MLKEM_Q;
493 SYMCRYPT_ASSERT( ((res >> 16) == 0) || ((res >> 16) == 0xffff) );
494 res = res + (SYMCRYPT_MLKEM_Q & (res >> 16));
496
497 return res;
498}
499
501UINT32
504 UINT32 a,
505 UINT32 b )
506{
507 UINT32 res;
508
511
512 res = a - b;
513 SYMCRYPT_ASSERT( ((res >> 16) == 0) || ((res >> 16) == 0xffff) );
514 res = res + (SYMCRYPT_MLKEM_Q & (res >> 16));
516
517 return res;
518}
519
521UINT32
524 UINT32 a,
525 UINT32 b,
526 UINT32 bMont )
527{
528 UINT32 res, inv;
529
534
535 res = a * b;
536 inv = (a * bMont) & SYMCRYPT_MLKEM_Rmask;
537 res += inv * SYMCRYPT_MLKEM_Q;
540
542}
543
544VOID
548 UINT32 k,
549 UINT32 len )
550{
551 UINT32 start, j;
552 UINT32 twiddleFactor, twiddleFactorMont, c0, c1, c1TimesTwiddle;
553
554 for( start=0; start<256; start+=(2*len) )
555 {
556 twiddleFactor = MlKemZetaBitRevTimesR[k];
557 twiddleFactorMont = MlKemZetaBitRevTimesRTimesNegQInvModR[k];
558 k++;
559 for( j=0; j<len; j++ )
560 {
561 c0 = peSrc->coeffs[start+j];
563 c1 = peSrc->coeffs[start+j+len];
565
566 c1TimesTwiddle = SymCryptMlKemMontMul( c1, twiddleFactor, twiddleFactorMont );
567 c1 = SymCryptMlKemModSub( c0, c1TimesTwiddle );
568 c0 = SymCryptMlKemModAdd( c0, c1TimesTwiddle );
569
570 peSrc->coeffs[start+j] = (UINT16) c0;
571 peSrc->coeffs[start+j+len] = (UINT16) c1;
572 }
573 }
574}
575
576VOID
580 UINT32 k,
581 UINT32 len )
582{
583 UINT32 start, j;
584 UINT32 twiddleFactor, twiddleFactorMont, c0, c1, tmp;
585
586 for( start=0; start<256; start+=(2*len) )
587 {
588 twiddleFactor = MlKemZetaBitRevTimesR[k];
589 twiddleFactorMont = MlKemZetaBitRevTimesRTimesNegQInvModR[k];
590 k--;
591 for( j=0; j<len; j++ )
592 {
593 c0 = peSrc->coeffs[start+j];
595 c1 = peSrc->coeffs[start+j+len];
597
598 tmp = SymCryptMlKemModAdd( c0, c1 );
599 c1 = SymCryptMlKemModSub( c1, c0 );
600 c1 = SymCryptMlKemMontMul( c1, twiddleFactor, twiddleFactorMont );
601
602 peSrc->coeffs[start+j] = (UINT16) tmp;
603 peSrc->coeffs[start+j+len] = (UINT16) c1;
604 }
605 }
606}
607
609VOID
613 UINT32 k,
614 UINT32 len )
615{
616#if SYMCRYPT_CPU_X86
617 SYMCRYPT_EXTENDED_SAVE_DATA SaveData;
618 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_SSE2 ) && SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR )
619 {
620 SymCryptMlKemPolyElementNTTLayerVec128( peSrc, k, len );
621 SymCryptRestoreXmm( &SaveData );
622 } else {
624 }
625#elif SYMCRYPT_CPU_AMD64
626 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_SSE2 ) )
627 {
628 SymCryptMlKemPolyElementNTTLayerVec128( peSrc, k, len );
629 } else {
631 }
632#elif SYMCRYPT_CPU_ARM64
633 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON ) )
634 {
635 SymCryptMlKemPolyElementNTTLayerVec128( peSrc, k, len );
636 } else {
638 }
639#else
641#endif
642}
643
645VOID
649 UINT32 k,
650 UINT32 len )
651{
652#if SYMCRYPT_CPU_X86
653 SYMCRYPT_EXTENDED_SAVE_DATA SaveData;
654 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_SSE2 ) && SymCryptSaveXmm( &SaveData ) == SYMCRYPT_NO_ERROR )
655 {
656 SymCryptMlKemPolyElementINTTLayerVec128( peSrc, k, len );
657 SymCryptRestoreXmm( &SaveData );
658 } else {
660 }
661#elif SYMCRYPT_CPU_AMD64
662 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_SSE2 ) )
663 {
664 SymCryptMlKemPolyElementINTTLayerVec128( peSrc, k, len );
665 } else {
667 }
668#elif SYMCRYPT_CPU_ARM64
669 if( SYMCRYPT_CPU_FEATURES_PRESENT( SYMCRYPT_CPU_FEATURE_NEON ) )
670 {
671 SymCryptMlKemPolyElementINTTLayerVec128( peSrc, k, len );
672 } else {
674 }
675#else
677#endif
678}
679
680#define SYMCRYPT_MLKEM_MaxCoeff (SYMCRYPT_MLKEM_Q - 1)
681#define SYMCRYPT_MLKEM_MaxCoeffProduct (SYMCRYPT_MLKEM_MaxCoeff*SYMCRYPT_MLKEM_MaxCoeff)
682
683// max([ ((i*j) + ((((i*j)*NegQInvModR) & Rmask)*Q)) >> Rlog2 for i in range(Q) for j in range(Q) ])
684#define SYMCRYPT_MLKEM_MaxFirstStepReduction (3494)
685// max([ ( pow(17, (2*i)+1, Q) << Rlog2 ) % Q for i in range(128) ])
686#define SYMCRYPT_MLKEM_MaxZetaTwoTimesPlus1TimesR (3254)
687#define SYMCRYPT_MLKEM_MaxA1B1ZetaPow (SYMCRYPT_MLKEM_MaxFirstStepReduction*SYMCRYPT_MLKEM_MaxZetaTwoTimesPlus1TimesR)
688
689VOID
695{
696 UINT32 i;
697 UINT32 a0, a1, b0, b1, c0, c1;
698 UINT32 a0b0, a1b1, a0b1, a1b0, a1b1zetapow, inv;
699
700 for( i=0; i<(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 2); i++ )
701 {
702 a0 = peSrc1->coeffs[(2*i) ];
704 a1 = peSrc1->coeffs[(2*i)+1];
706
707 b0 = peSrc2->coeffs[(2*i) ];
709 b1 = peSrc2->coeffs[(2*i)+1];
711
712 c0 = paDst->coeffs[(2*i) ];
714 c1 = paDst->coeffs[(2*i)+1];
716
717 // multiplication results in range [0, MaxCoeffProduct = 3328*3328]
718 a0b0 = a0 * b0;
719 a1b1 = a1 * b1;
720 a0b1 = a0 * b1;
721 a1b0 = a1 * b0;
722
723 // we need a1*b1*zetaTwoTimesBitRevPlus1TimesR[i]
724 // eagerly reduce a1*b1 with montgomery reduction
725 // a1b1 = red(a1*b1) -> range [0, MaxFirstStepReduction = 3494]
726 // (3494 is maximum result of first step of montgomery reduction of x*y for x,y in [0, 3328])
727 // we do not need to do final reduction yet
729 a1b1 = (a1b1 + (inv * SYMCRYPT_MLKEM_Q)) >> SYMCRYPT_MLKEM_Rlog2; // in range [0, MaxFirstStepReduction]
731
732 // now multiply a1b1 by power of zeta
733 a1b1zetapow = a1b1 * zetaTwoTimesBitRevPlus1TimesR[i];
734 // MaxZetaTwoTimesPlus1TimesR = 3254
735 // MaxA1B1ZetaPow = MaxFirstStepReduction*MaxZetaTwoTimesPlus1TimesR = 3494*3254
737
738 // sum pairs of products
739 a0b0 += a1b1zetapow; // a0*b0 + red(a1*b1)*zetapower in range [0, MaxCoeffProduct + MaxA1B1ZetaPow]
741 a0b1 += a1b0; // a0*b1 + a1*b0 in range [0, 2*MaxCoeffProduct]
743
744 // We sum at most 4 pairs of products into an accumulator in ML-KEM
746 c0 += a0b0; // in range [0,4*MaxCoeffProduct + 4*MaxA1B1ZetaPow]
748 c1 += a0b1; // in range [0,5*MaxCoeffProduct + 3*MaxA1B1ZetaPow]
750
751 paDst->coeffs[(2*i) ] = c0;
752 paDst->coeffs[(2*i)+1] = c1;
753 }
754}
755
756VOID
761{
762 UINT32 i;
763 UINT32 a, c, inv;
764
766 {
767 a = paSrc->coeffs[i];
769 paSrc->coeffs[i] = 0;
770
771 c = peDst->coeffs[i];
773
774 // montgomery reduce sum of products
776 a = (a + (inv * SYMCRYPT_MLKEM_Q)) >> SYMCRYPT_MLKEM_Rlog2; // in range [0, 4711]
777 SYMCRYPT_ASSERT( a <= 4711 );
778
779 // add destination
780 c += a;
781 SYMCRYPT_ASSERT( c <= 8039 );
782
783 // subtraction and conditional additions for constant time range reduction
784 c -= 2*SYMCRYPT_MLKEM_Q; // in range [-2Q, 1381]
785 SYMCRYPT_ASSERT( (c >= ((UINT32)(-2*SYMCRYPT_MLKEM_Q))) || (c < 1381) );
786 c += SYMCRYPT_MLKEM_Q & (c >> 16); // in range [-Q, Q-1]
788 c += SYMCRYPT_MLKEM_Q & (c >> 16); // in range [0, Q-1]
790
791 peDst->coeffs[i] = (UINT16) c;
792 }
793}
794
795VOID
800{
801 UINT32 i;
803 {
804 peDst->coeffs[i] = (UINT16) SymCryptMlKemMontMul(
806 }
807}
808
809VOID
815{
816 UINT32 i;
818 {
819 peDst->coeffs[i] = (UINT16) SymCryptMlKemModAdd( peSrc1->coeffs[i], peSrc2->coeffs[i] );
820 }
821}
822
823VOID
829{
830 UINT32 i;
832 {
833 peDst->coeffs[i] = (UINT16) SymCryptMlKemModSub( peSrc1->coeffs[i], peSrc2->coeffs[i] );
834 }
835}
836
837VOID
841{
842 SymCryptMlKemPolyElementNTTLayer( peSrc, 1, 128 );
843 SymCryptMlKemPolyElementNTTLayer( peSrc, 2, 64 );
844 SymCryptMlKemPolyElementNTTLayer( peSrc, 4, 32 );
845 SymCryptMlKemPolyElementNTTLayer( peSrc, 8, 16 );
846 SymCryptMlKemPolyElementNTTLayer( peSrc, 16, 8 );
847 SymCryptMlKemPolyElementNTTLayer( peSrc, 32, 4 );
848 SymCryptMlKemPolyElementNTTLayer( peSrc, 64, 2 );
849}
850
851// INTTFixupTimesRsqr = R^2 * 3303 = (3303<<32) mod Q
852// 3303 constant is fixup from FIPS 203
853// Multiplied by R^2 to additionally multiply coefficients by R after montgomery reduction
856
857VOID
861{
862 UINT32 i;
863
864 SymCryptMlKemPolyElementINTTLayer( peSrc, 127, 2 );
865 SymCryptMlKemPolyElementINTTLayer( peSrc, 63, 4 );
866 SymCryptMlKemPolyElementINTTLayer( peSrc, 31, 8 );
867 SymCryptMlKemPolyElementINTTLayer( peSrc, 15, 16 );
868 SymCryptMlKemPolyElementINTTLayer( peSrc, 7, 32 );
869 SymCryptMlKemPolyElementINTTLayer( peSrc, 3, 64 );
870 SymCryptMlKemPolyElementINTTLayer( peSrc, 1, 128 );
871
873 {
874 peSrc->coeffs[i] = (UINT16) SymCryptMlKemMontMul(
876 }
877}
878
879// ((1<<33) / SYMCRYPT_MLKEM_Q) rounded to nearest integer
880//
881// 1<<33 is the smallest power of 2 s.t. the constant has sufficient precision to round
882// all inputs correctly in compression for all nBitsPerCoefficient < 12. A smaller
883// constant could be used for smaller nBitsPerCoefficient for a small performance gain
884//
887
888VOID
892 UINT32 nBitsPerCoefficient,
894 PBYTE pbDst )
895{
896 UINT32 i;
897 UINT64 multiplication;
899 UINT32 nBitsInCoefficient;
900 UINT32 bitsToEncode;
901 UINT32 nBitsToEncode;
902 UINT32 cbDstWritten = 0;
903 UINT32 accumulator = 0;
904 UINT32 nBitsInAccumulator = 0;
905
906 SYMCRYPT_ASSERT( nBitsPerCoefficient > 0 );
907 SYMCRYPT_ASSERT( nBitsPerCoefficient <= 12 );
908
910 {
911 nBitsInCoefficient = nBitsPerCoefficient;
912 coefficient = peSrc->coeffs[i]; // in range [0, Q-1]
914
915 // first compress the coefficient
916 // when nBitsPerCoefficient < 12 we compress per Compress_d in FIPS 203;
917 if(nBitsPerCoefficient < 12)
918 {
919 // Multiply by 2^(nBitsPerCoefficient+1) / Q by multiplying by constant and shifting right
920 multiplication = SYMCRYPT_MUL32x32TO64(coefficient, SYMCRYPT_MLKEM_COMPRESS_MULCONSTANT);
921 coefficient = (UINT32) (multiplication >> (SYMCRYPT_MLKEM_COMPRESS_SHIFTCONSTANT-(nBitsPerCoefficient+1)));
922
923 // add "half" to round to nearest integer
924 coefficient++;
925
926 // final divide by two to get multiplication by 2^nBitsPerCoefficient / Q
927 coefficient >>= 1; // in range [0, 2^nBitsPerCoefficient]
928 SYMCRYPT_ASSERT(coefficient <= (1UL<<nBitsPerCoefficient));
929
930 // modular reduction by masking
931 coefficient &= (1UL<<nBitsPerCoefficient)-1; // in range [0, 2^nBitsPerCoefficient - 1]
932 SYMCRYPT_ASSERT(coefficient < (1UL<<nBitsPerCoefficient));
933 }
934
935 // encode the coefficient
936 // simple loop to add bits to accumulator and write accumulator to output
937 do
938 {
939 nBitsToEncode = SYMCRYPT_MIN(nBitsInCoefficient, 32-nBitsInAccumulator);
940
941 bitsToEncode = coefficient & ((1UL<<nBitsToEncode)-1);
942 coefficient >>= nBitsToEncode;
943 nBitsInCoefficient -= nBitsToEncode;
944
945 accumulator |= (bitsToEncode << nBitsInAccumulator);
946 nBitsInAccumulator += nBitsToEncode;
947 if(nBitsInAccumulator == 32)
948 {
949 SYMCRYPT_STORE_LSBFIRST32( pbDst+cbDstWritten, accumulator );
950 cbDstWritten += 4;
951 accumulator = 0;
952 nBitsInAccumulator = 0;
953 }
954 } while( nBitsInCoefficient > 0 );
955 }
956
957 SYMCRYPT_ASSERT(nBitsInAccumulator == 0);
958 SYMCRYPT_ASSERT(cbDstWritten == (nBitsPerCoefficient*(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8)));
959}
960
966 UINT32 nBitsPerCoefficient,
968{
969 UINT32 i;
971 UINT32 nBitsInCoefficient;
972 UINT32 bitsToDecode;
973 UINT32 nBitsToDecode;
974 UINT32 cbSrcRead = 0;
975 UINT32 accumulator = 0;
976 UINT32 nBitsInAccumulator = 0;
977
978 SYMCRYPT_ASSERT( nBitsPerCoefficient > 0 );
979 SYMCRYPT_ASSERT( nBitsPerCoefficient <= 12 );
980
982 {
983 coefficient = 0;
984 nBitsInCoefficient = 0;
985
986 // first gather and decode bits from pbSrc
987 do
988 {
989 if(nBitsInAccumulator == 0)
990 {
991 accumulator = SYMCRYPT_LOAD_LSBFIRST32( pbSrc+cbSrcRead );
992 cbSrcRead += 4;
993 nBitsInAccumulator = 32;
994 }
995
996 nBitsToDecode = SYMCRYPT_MIN(nBitsPerCoefficient-nBitsInCoefficient, nBitsInAccumulator);
997 SYMCRYPT_ASSERT(nBitsToDecode <= nBitsInAccumulator);
998
999 bitsToDecode = accumulator & ((1UL<<nBitsToDecode)-1);
1000 accumulator >>= nBitsToDecode;
1001 nBitsInAccumulator -= nBitsToDecode;
1002
1003 coefficient |= (bitsToDecode << nBitsInCoefficient);
1004 nBitsInCoefficient += nBitsToDecode;
1005 } while( nBitsPerCoefficient > nBitsInCoefficient );
1006 SYMCRYPT_ASSERT(nBitsInCoefficient == nBitsPerCoefficient);
1007
1008 // decompress the coefficient
1009 // when nBitsPerCoefficient < 12 we decompress per Decompress_d in FIPS 203
1010 // otherwise we perform input validation per 203 6.2 Input validation 2 (Modulus check)
1011 if(nBitsPerCoefficient < 12)
1012 {
1013 // Multiply by Q / 2^(nBitsPerCoefficient-1) by multiplying by constant and shifting right
1015 coefficient >>= (nBitsPerCoefficient-1);
1016
1017 // add "half" to round to nearest integer
1018 coefficient++;
1019
1020 // final divide by two to get multiplication by Q / 2^nBitsPerCoefficient
1021 coefficient >>= 1; // in range [0, Q]
1022
1023 // modular reduction by conditional subtraction
1026 }
1027 else if( coefficient >= SYMCRYPT_MLKEM_Q )
1028 {
1029 // input validation failure - this can happen with a malformed or corrupt encapsulation
1030 // or decapsulation key; we do not need to be constant time because we treat the
1031 // validity of an imported key as public information.
1032 return SYMCRYPT_INVALID_BLOB;
1033 }
1034
1035 peDst->coeffs[i] = (UINT16) coefficient;
1036 }
1037
1038 SYMCRYPT_ASSERT(nBitsInAccumulator == 0);
1039 SYMCRYPT_ASSERT(cbSrcRead == (nBitsPerCoefficient*(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8)));
1040
1041 return SYMCRYPT_NO_ERROR;
1042}
1043
1044VOID
1049{
1050 UINT32 i=0;
1051 BYTE shakeOutputBuf[3*8]; // Keccak likes extracting multiples of 8-bytes
1052 UINT32 currBufIndex = sizeof(shakeOutputBuf);
1053 UINT16 sample0, sample1;
1054
1056 {
1057 SYMCRYPT_ASSERT(currBufIndex <= sizeof(shakeOutputBuf));
1058 if( currBufIndex == sizeof(shakeOutputBuf) )
1059 {
1060 SymCryptShake128Extract(pState, shakeOutputBuf, sizeof(shakeOutputBuf), FALSE);
1061 currBufIndex = 0;
1062 }
1063
1064 sample0 = SYMCRYPT_LOAD_LSBFIRST16( shakeOutputBuf+currBufIndex ) & 0xfff;
1065 sample1 = SYMCRYPT_LOAD_LSBFIRST16( shakeOutputBuf+currBufIndex+1 ) >> 4;
1066 currBufIndex += 3;
1067
1068 peDst->coeffs[i] = sample0;
1069 i += sample0 < SYMCRYPT_MLKEM_Q;
1070
1072 {
1073 peDst->coeffs[i] = sample1;
1074 i += sample1 < SYMCRYPT_MLKEM_Q;
1075 }
1076 }
1077}
1078
1079VOID
1083 PCBYTE pbSrc,
1084 _In_range_(2,3) UINT32 eta,
1086{
1087 UINT32 i, j;
1088 UINT32 sampleBits;
1090
1091 SYMCRYPT_ASSERT((eta == 2) || (eta == 3));
1092 if( eta == 3 )
1093 {
1095 {
1096 // unconditionally load 4 bytes into sampleBits, but only treat the load
1097 // as being 3 bytes (24-bits -> 4 coefficients) for eta==3 to align to
1098 // byte boundaries. Source buffer must be 1 byte larger than shake output
1099 sampleBits = SYMCRYPT_LOAD_LSBFIRST32( pbSrc );
1100 pbSrc += 3;
1101
1102 // sum bit samples - each consecutive slice of eta bits is summed together
1103 sampleBits = (sampleBits&0x249249) + ((sampleBits>>1)&0x249249) + ((sampleBits>>2)&0x249249);
1104
1105 for( j=0; j<4; j++ )
1106 {
1107 // each coefficient is formed by taking the difference of two consecutive slices of eta bits
1108 // the first eta bits are positive, the second eta bits are negative
1109 coefficient = sampleBits & 0x3f;
1110 sampleBits >>= 6;
1111 coefficient = (coefficient&3) - (coefficient>>3);
1112 SYMCRYPT_ASSERT((coefficient >= ((UINT32)-3)) || (coefficient <= 3));
1113
1114 coefficient = coefficient + (SYMCRYPT_MLKEM_Q & (coefficient >> 16)); // in range [0, Q-1]
1116
1117 peDst->coeffs[i+j] = (UINT16) coefficient;
1118 }
1119 }
1120 }
1121 else
1122 {
1124 {
1125 // unconditionally load 4 bytes (32-bits -> 8 coefficients) into sampleBits
1126 sampleBits = SYMCRYPT_LOAD_LSBFIRST32( pbSrc );
1127 pbSrc += 4;
1128
1129 // sum bit samples - each consecutive slice of eta bits is summed together
1130 sampleBits = (sampleBits&0x55555555) + ((sampleBits>>1)&0x55555555);
1131
1132 for( j=0; j<8; j++ )
1133 {
1134 // each coefficient is formed by taking the difference of two consecutive slices of eta bits
1135 // the first eta bits are positive, the second eta bits are negative
1136 coefficient = sampleBits & 0xf;
1137 sampleBits >>= 4;
1138 coefficient = (coefficient&3) - (coefficient>>2);
1139 SYMCRYPT_ASSERT((coefficient >= ((UINT32)-2)) || (coefficient <= 2));
1140
1141 coefficient = coefficient + (SYMCRYPT_MLKEM_Q & (coefficient >> 16)); // in range [0, Q-1]
1143
1144 peDst->coeffs[i+j] = (UINT16) coefficient;
1145 }
1146 }
1147 }
1148}
1149
1150VOID
1154{
1155 UINT32 i, j;
1157 const UINT32 nRows = pmSrc->nRows;
1158
1159 SYMCRYPT_ASSERT( nRows > 0 );
1161
1162 for( i=0; i<nRows; i++ )
1163 {
1164 for( j=i+1; j<nRows; j++ )
1165 {
1166 swap = pmSrc->apPolyElements[(i*nRows) + j];
1167 pmSrc->apPolyElements[(i*nRows) + j] = pmSrc->apPolyElements[(j*nRows) + i];
1168 pmSrc->apPolyElements[(j*nRows) + i] = swap;
1169 }
1170 }
1171}
1172
1173VOID
1180{
1181 UINT32 i, j;
1182 const UINT32 nRows = pmSrc1->nRows;
1183 PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, peSrc2;
1185
1186 SYMCRYPT_ASSERT( nRows > 0 );
1188 SYMCRYPT_ASSERT( pvSrc2->nRows == nRows );
1189 SYMCRYPT_ASSERT( pvDst->nRows == nRows );
1190
1191 // Zero paTmp
1193
1194 for( i=0; i<nRows; i++ )
1195 {
1196 for( j=0; j<nRows; j++ )
1197 {
1198 peSrc1 = pmSrc1->apPolyElements[(i*nRows) + j];
1199 peSrc2 = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( j, pvSrc2 );
1200 SymCryptMlKemPolyElementMulAndAccumulate( peSrc1, peSrc2, paTmp );
1201 }
1202
1203 // write accumulator to dest and zero accumulator
1204 peDst = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvDst );
1206 }
1207}
1208
1209VOID
1216{
1217 UINT32 i;
1218 const UINT32 nRows = pvSrc1->nRows;
1219 PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, peSrc2;
1220
1221 SYMCRYPT_ASSERT( nRows > 0 );
1223 SYMCRYPT_ASSERT( pvSrc2->nRows == nRows );
1224
1225 // Zero paTmp and peDst
1228
1229 for( i=0; i<nRows; i++ )
1230 {
1231 peSrc1 = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvSrc1 );
1232 peSrc2 = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvSrc2 );
1233 SymCryptMlKemPolyElementMulAndAccumulate( peSrc1, peSrc2, paTmp );
1234 }
1235
1236 // write accumulator to dest and zero accumulator
1238}
1239
1240VOID
1244{
1245 const UINT32 nRows = pvSrc->nRows;
1246
1247 SYMCRYPT_ASSERT( nRows > 0 );
1249
1251}
1252
1253VOID
1258{
1259 UINT32 i;
1260 const UINT32 nRows = pvSrc->nRows;
1261
1262 SYMCRYPT_ASSERT( nRows > 0 );
1264 SYMCRYPT_ASSERT( pvDst->nRows == nRows );
1265
1266 for( i=0; i<nRows; i++ )
1267 {
1271 }
1272}
1273
1274VOID
1280{
1281 UINT32 i;
1282 const UINT32 nRows = pvSrc1->nRows;
1283 PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, peSrc2;
1285
1286 SYMCRYPT_ASSERT( nRows > 0 );
1288 SYMCRYPT_ASSERT( pvSrc2->nRows == nRows );
1289 SYMCRYPT_ASSERT( pvDst->nRows == nRows );
1290
1291 for( i=0; i<nRows; i++ )
1292 {
1293 peSrc1 = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvSrc1 );
1294 peSrc2 = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvSrc2 );
1295 peDst = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvDst );
1296 SymCryptMlKemPolyElementAdd( peSrc1, peSrc2, peDst );
1297 }
1298}
1299
1300VOID
1306{
1307 UINT32 i;
1308 const UINT32 nRows = pvSrc1->nRows;
1309 PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, peSrc2;
1311
1312 SYMCRYPT_ASSERT( nRows > 0 );
1314 SYMCRYPT_ASSERT( pvSrc2->nRows == nRows );
1315 SYMCRYPT_ASSERT( pvDst->nRows == nRows );
1316
1317 for( i=0; i<nRows; i++ )
1318 {
1319 peSrc1 = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvSrc1 );
1320 peSrc2 = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvSrc2 );
1321 peDst = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvDst );
1322 SymCryptMlKemPolyElementSub( peSrc1, peSrc2, peDst );
1323 }
1324}
1325
1326VOID
1330{
1331 UINT32 i;
1332 const UINT32 nRows = pvSrc->nRows;
1333
1334 SYMCRYPT_ASSERT( nRows > 0 );
1336
1337 for( i=0; i<nRows; i++ )
1338 {
1340 }
1341}
1342
1343VOID
1347{
1348 UINT32 i;
1349 const UINT32 nRows = pvSrc->nRows;
1350
1351 SYMCRYPT_ASSERT( nRows > 0 );
1353
1354 for( i=0; i<nRows; i++ )
1355 {
1357 }
1358}
1359
1360VOID
1364 UINT32 nBitsPerCoefficient,
1366 SIZE_T cbDst )
1367{
1368 UINT32 i;
1369 const UINT32 nRows = pvSrc->nRows;
1371
1372 SYMCRYPT_ASSERT( nRows > 0 );
1374 SYMCRYPT_ASSERT( nBitsPerCoefficient > 0 );
1375 SYMCRYPT_ASSERT( nBitsPerCoefficient <= 12 );
1376 SYMCRYPT_ASSERT( cbDst == nRows*nBitsPerCoefficient*(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8) );
1377
1378 UNREFERENCED_PARAMETER( cbDst );
1379
1380 for( i=0; i<nRows; i++ )
1381 {
1382 peSrc = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvSrc );
1383 SymCryptMlKemPolyElementCompressAndEncode( peSrc, nBitsPerCoefficient, pbDst );
1384 pbDst += nBitsPerCoefficient*(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8);
1385 }
1386}
1387
1392 SIZE_T cbSrc,
1393 UINT32 nBitsPerCoefficient,
1395{
1396 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1397 UINT32 i;
1398 const UINT32 nRows = pvDst->nRows;
1400
1401 SYMCRYPT_ASSERT( nRows > 0 );
1403 SYMCRYPT_ASSERT( nBitsPerCoefficient > 0 );
1404 SYMCRYPT_ASSERT( nBitsPerCoefficient <= 12 );
1405 SYMCRYPT_ASSERT( cbSrc == nRows*nBitsPerCoefficient*(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8) );
1406
1407 UNREFERENCED_PARAMETER( cbSrc );
1408
1409 for( i=0; i<nRows; i++ )
1410 {
1411 peDst = SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT( i, pvDst );
1412 scError = SymCryptMlKemPolyElementDecodeAndDecompress( pbSrc, nBitsPerCoefficient, peDst );
1413 if( scError != SYMCRYPT_NO_ERROR )
1414 {
1415 goto cleanup;
1416 }
1417 pbSrc += nBitsPerCoefficient*(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8);
1418 }
1419
1420cleanup:
1421 return scError;
1422}
1423
1424VOID
1428{
1430 SymCryptWipeKnownSize( pkMlKemkey->privateRandom, sizeof(pkMlKemkey->privateRandom) );
1431 SymCryptWipeKnownSize( pkMlKemkey->privateSeed, sizeof(pkMlKemkey->privateSeed) );
1432 pkMlKemkey->hasPrivateKey = FALSE;
1433 pkMlKemkey->hasPrivateSeed = FALSE;
1434}
1435
1436#if SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_X86
1437#ifdef __clang__
1438#pragma clang attribute pop
1439#else
1440#pragma GCC pop_options
1441#endif
1442#endif
unsigned short UINT16
Definition: actypes.h:129
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
BYTE coefficient[512/16]
Definition: bcrypt.c:2463
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
VOID SaveData(HWND hwndDlg)
Definition: volume.c:368
static void cleanup(void)
Definition: main.c:1335
static const uint32_t k[]
Definition: sha256.c:24
GLuint start
Definition: gl.h:1545
GLuint res
Definition: glext.h:9613
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
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
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementSub(_In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, _In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc2, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
VOID SYMCRYPT_CALL SymCryptMlKemVectorMulR(_In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc, _Out_ PSYMCRYPT_MLKEM_VECTOR pvDst)
VOID SYMCRYPT_CALL SymCryptMlKemVectorCompressAndEncode(_In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc, UINT32 nBitsPerCoefficient, _Out_writes_bytes_(cbDst) PBYTE pbDst, SIZE_T cbDst)
FORCEINLINE VOID SYMCRYPT_CALL SymCryptMlKemPolyElementNTTLayer(_Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peSrc, UINT32 k, UINT32 len)
VOID SYMCRYPT_CALL SymCryptMlKemMatrixVectorMontMulAndAdd(_In_ PCSYMCRYPT_MLKEM_MATRIX pmSrc1, _In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc2, _Inout_ PSYMCRYPT_MLKEM_VECTOR pvDst, _Inout_ PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR paTmp)
const UINT16 MlKemZetaBitRevTimesR[128]
FORCEINLINE VOID SYMCRYPT_CALL SymCryptMlKemPolyElementINTTLayer(_Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peSrc, UINT32 k, UINT32 len)
VOID SYMCRYPT_CALL SymCryptMlKemVectorSetZero(_Inout_ PSYMCRYPT_MLKEM_VECTOR pvSrc)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementNTTLayerC(_Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peSrc, UINT32 k, UINT32 len)
#define SYMCRYPT_MLKEM_MaxFirstStepReduction
const UINT32 SYMCRYPT_MLKEM_Rsqr
VOID SYMCRYPT_CALL SymCryptMlKemVectorAdd(_In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc1, _In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc2, _Out_ PSYMCRYPT_MLKEM_VECTOR pvDst)
PSYMCRYPT_MLKEM_VECTOR SYMCRYPT_CALL SymCryptMlKemVectorCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, UINT32 cbBuffer, UINT32 nRows)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementAdd(_In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, _In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc2, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementSampleCBDFromBytes(_In_reads_bytes_(eta *2 *(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS/8)+1) PCBYTE pbSrc, _In_range_(2, 3) UINT32 eta, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
VOID SYMCRYPT_CALL SymCryptMlKemMatrixTranspose(_Inout_ PSYMCRYPT_MLKEM_MATRIX pmSrc)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementNTT(_Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peSrc)
PSYMCRYPT_MLKEM_POLYELEMENT SYMCRYPT_CALL SymCryptMlKemPolyElementCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, UINT32 cbBuffer)
FORCEINLINE UINT32 SYMCRYPT_CALL SymCryptMlKemModSub(UINT32 a, UINT32 b)
const UINT16 zetaTwoTimesBitRevPlus1TimesR[128]
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementSampleNTTFromShake128(_Inout_ PSYMCRYPT_SHAKE128_STATE pState, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
const UINT32 SYMCRYPT_MLKEM_COMPRESS_MULCONSTANT
#define SYMCRYPT_MLKEM_MaxA1B1ZetaPow
FORCEINLINE UINT32 SYMCRYPT_CALL SymCryptMlKemModAdd(UINT32 a, UINT32 b)
VOID SYMCRYPT_CALL SymCryptMlKemVectorSub(_In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc1, _In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc2, _Out_ PSYMCRYPT_MLKEM_VECTOR pvDst)
VOID SYMCRYPT_CALL SymCryptMlKemMontgomeryReduceAndAddPolyElementAccumulatorToPolyElement(_Inout_ PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR paSrc, _Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementINTTAndMulR(_Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peSrc)
const UINT32 SYMCRYPT_MLKEM_INTTFixupTimesRsqrTimesNegQInvModR
VOID SYMCRYPT_CALL SymCryptMlKemVectorNTT(_Inout_ PSYMCRYPT_MLKEM_VECTOR pvSrc)
const UINT32 SYMCRYPT_MLKEM_Rlog2
const UINT32 SYMCRYPT_MLKEM_Rmask
VOID SYMCRYPT_CALL SymCryptMlKemkeyWipePrivateState(_Inout_ PSYMCRYPT_MLKEMKEY pkMlKemkey)
FORCEINLINE UINT32 SYMCRYPT_CALL SymCryptMlKemMontMul(UINT32 a, UINT32 b, UINT32 bMont)
const UINT32 SYMCRYPT_MLKEM_COMPRESS_SHIFTCONSTANT
PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR SYMCRYPT_CALL SymCryptMlKemPolyElementAccumulatorCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, UINT32 cbBuffer)
const UINT32 SYMCRYPT_MLKEM_RsqrTimesNegQInvModR
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementMulR(_In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemPolyElementDecodeAndDecompress(_In_reads_bytes_(nBitsPerCoefficient *(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS/8)) PCBYTE pbSrc, UINT32 nBitsPerCoefficient, _Out_ PSYMCRYPT_MLKEM_POLYELEMENT peDst)
const UINT32 SYMCRYPT_MLKEM_INTTFixupTimesRsqr
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementINTTLayerC(_Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peSrc, UINT32 k, UINT32 len)
#define SYMCRYPT_MLKEM_MaxCoeffProduct
const UINT16 MlKemZetaBitRevTimesRTimesNegQInvModR[128]
VOID SYMCRYPT_CALL SymCryptMlKemVectorMontDotProduct(_In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc1, _In_ PCSYMCRYPT_MLKEM_VECTOR pvSrc2, _Inout_ PSYMCRYPT_MLKEM_POLYELEMENT peDst, _Inout_ PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR paTmp)
VOID SYMCRYPT_CALL SymCryptMlKemVectorINTTAndMulR(_Inout_ PSYMCRYPT_MLKEM_VECTOR pvSrc)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementCompressAndEncode(_In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc, UINT32 nBitsPerCoefficient, _Out_writes_bytes_(nBitsPerCoefficient *(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS/8)) PBYTE pbDst)
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlKemVectorDecodeAndDecompress(_In_reads_bytes_(cbSrc) PCBYTE pbSrc, SIZE_T cbSrc, UINT32 nBitsPerCoefficient, _Out_ PSYMCRYPT_MLKEM_VECTOR pvDst)
VOID SYMCRYPT_CALL SymCryptMlKemPolyElementMulAndAccumulate(_In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc1, _In_ PCSYMCRYPT_MLKEM_POLYELEMENT peSrc2, _Inout_ PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR paDst)
const UINT32 SYMCRYPT_MLKEM_NegQInvModR
PSYMCRYPT_MLKEM_MATRIX SYMCRYPT_CALL SymCryptMlKemMatrixCreate(_Out_writes_bytes_(cbBuffer) PBYTE pbBuffer, UINT32 cbBuffer, UINT32 nRows)
static const struct update_accum a1
Definition: msg.c:534
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:529
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_range_(l, h)
Definition: no_sal2.h:368
#define _Out_writes_bytes_(s)
Definition: no_sal2.h:178
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
BYTE * PBYTE
Definition: pedump.c:66
#define swap(a, b)
Definition: qsort.c:63
#define SYMCRYPT_ASSERT_ASYM_ALIGNED(_p)
Definition: sc_lib.h:1912
#define SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS
Definition: sc_lib.h:4347
PSYMCRYPT_MLKEMKEY pkMlKemkey
Definition: sc_lib.h:4444
SIZE_T cbBuffer
Definition: sc_lib_mldsa.h:405
SYMCRYPT_MLKEM_MATRIX
Definition: sc_lib_mlkem.h:53
SYMCRYPT_MLKEM_POLYELEMENT * PSYMCRYPT_MLKEM_POLYELEMENT
Definition: sc_lib_mlkem.h:18
SYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR * PSYMCRYPT_MLKEM_POLYELEMENT_ACCUMULATOR
Definition: sc_lib_mlkem.h:25
#define SYMCRYPT_MLKEM_Q
Definition: sc_lib_mlkem.h:123
#define SYMCRYPT_INTERNAL_MLKEM_SIZEOF_POLYRINGELEMENT
Definition: sc_lib_mlkem.h:125
#define SYMCRYPT_INTERNAL_MLKEM_SIZEOF_POLYRINGELEMENT_ACCUMULATOR
Definition: sc_lib_mlkem.h:126
UINT8 nRows
Definition: sc_lib_mlkem.h:69
#define SYMCRYPT_INTERNAL_MLKEM_VECTOR_ELEMENT(_row, _pVector)
Definition: sc_lib_mlkem.h:129
* PSYMCRYPT_MLKEM_VECTOR
Definition: sc_lib_mlkem.h:37
* PSYMCRYPT_MLKEM_MATRIX
Definition: sc_lib_mlkem.h:53
const SYMCRYPT_MLKEM_MATRIX * PCSYMCRYPT_MLKEM_MATRIX
Definition: sc_lib_mlkem.h:54
#define SYMCRYPT_MLKEM_MATRIX_MAX_NROWS
Definition: sc_lib_mlkem.h:28
SYMCRYPT_MLKEM_VECTOR
Definition: sc_lib_mlkem.h:37
const SYMCRYPT_MLKEM_VECTOR * PCSYMCRYPT_MLKEM_VECTOR
Definition: sc_lib_mlkem.h:38
const SYMCRYPT_MLKEM_POLYELEMENT * PCSYMCRYPT_MLKEM_POLYELEMENT
Definition: sc_lib_mlkem.h:19
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
#define SYMCRYPT_LOAD_LSBFIRST16(p)
Definition: symcrypt.h:298
#define SYMCRYPT_LOAD_LSBFIRST32(p)
Definition: symcrypt.h:299
VOID SYMCRYPT_CALL SymCryptShake128Extract(_Inout_ PSYMCRYPT_SHAKE128_STATE pState, _Out_writes_(cbResult) PBYTE pbResult, SIZE_T cbResult, BOOLEAN bWipe)
#define SYMCRYPT_STORE_LSBFIRST32(p, v)
Definition: symcrypt.h:307
SYMCRYPT_ERROR
Definition: symcrypt.h:227
PCBYTE pbSrc
#define SYMCRYPT_CALL
#define SYMCRYPT_CPU_FEATURES_PRESENT(x)
SYMCRYPT_MLKEMKEY * PSYMCRYPT_MLKEMKEY
#define SYMCRYPT_MIN(_a, _b)
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_SHAKE128_STATE
PCBYTE PBYTE pbDst
PSYMCRYPT_COMMON_HASH_STATE pState
const BYTE * PCBYTE
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t UINT32
Definition: typedefs.h:59
#define FORCEINLINE
Definition: wdftypes.h:67
unsigned char BYTE
Definition: xxhash.c:193