ReactOS 0.4.17-dev-1005-g171e1de
mldsa_primitives.c
Go to the documentation of this file.
1//
2// mldsa_primitives.c ML-DSA low-level primitive implementations
3//
4// Copyright (c) Microsoft Corporation. Licensed under the MIT license.
5//
6
7#include "precomp.h"
8
9//
10// Q^-1 mod 2^32 - used in Montgomery reduction
11//
12#define SYMCRYPT_MLDSA_Q_INV (58728449)
13
14//
15// Inverse NTT fixup times R = (256^-1 << 32) mod Q
16//
17#define SYMCRYPT_MLDSA_INTT_FIXUP_TIMES_R (16382)
18
19//
20// R^2 mod Q - used for multiplying a factor of R into a polynomial in NTT form via
21// Montgomery multiplication
22//
23#define SYMCRYPT_MLDSA_RSQR (2365951)
24
25//
26// Size of the expanded public seed used in SymCryptMlDsaRejNttPoly
27// Defined in FIPS 204 to be 272 bits (256 bit public seed rho || 8 bit index s || 8 bit index r)
28//
29#define SYMCRYPT_MLDSA_REJNTTPOLY_SEED_SIZE (34)
30
31//
32// Size of the expanded private seed used in SymCryptMlDsaRejBoundedPoly
33// Defined in FIPS 204 to be 528 bits (512 bit private vector seed rho' || 16 bit index)
34//
35#define SYMCRYPT_MLDSA_REJBOUNDEDPOLY_SEED_SIZE (66)
36
37//
38// Number of low-order bits dropped by Power2Round. Defined as d in FIPS 204
39//
40#define SYMCRYPT_POWER2ROUND_LOW_ORDER_BITS (13)
41
42//
43// Zeta tables.
44// For ML-DSA, zeta = 1753, which is a 512th root of unity modulo Q
45//
46// In ML-DSA we use powers of zeta to convert to and from NTT form
47// and to perform multiplication between polynomials in NTT form
48//
49
50// This table is a lookup for (Zeta^(BitRev(index)) * R) mod Q
51// Used in NTT and Inverse NTT
52// i.e. element 1 is Zeta^(BitRev(1)) * (2^32) mod Q == (1753^128)*(2^32) mod 8380417 == 25847
53//
54// MLDSA_ZETA_BITREV_TIMES_R = [ (pow(1753, bitRev(i), 8380417) << 32) % 8380417 for i in range(256) ]
55//
57 4193792, 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468,
58 1826347, 2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103,
59 2725464, 1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868,
60 6262231, 4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005,
61 2706023, 95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439,
62 4519302, 5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118,
63 6681150, 6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596,
64 811944, 531354, 954230, 3881043, 3900724, 5823537, 2071892, 5582638,
65 4450022, 6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196,
66 7122806, 1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922,
67 3412210, 7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370,
68 7709315, 7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987,
69 5037034, 264944, 508951, 3097992, 44288, 7280319, 904516, 3958618,
70 4656075, 8371839, 1653064, 5130689, 2389356, 8169440, 759969, 7063561,
71 189548, 4827145, 3159746, 6529015, 5971092, 8202977, 1315589, 1341330,
72 1285669, 6795489, 7567685, 6940675, 5361315, 4499357, 4751448, 3839961,
73 2091667, 3407706, 2316500, 3817976, 5037939, 2244091, 5933984, 4817955,
74 266997, 2434439, 7144689, 3513181, 4860065, 4621053, 7183191, 5187039,
75 900702, 1859098, 909542, 819034, 495491, 6767243, 8337157, 7857917,
76 7725090, 5257975, 2031748, 3207046, 4823422, 7855319, 7611795, 4784579,
77 342297, 286988, 5942594, 4108315, 3437287, 5038140, 1735879, 203044,
78 2842341, 2691481, 5790267, 1265009, 4055324, 1247620, 2486353, 1595974,
79 4613401, 1250494, 2635921, 4832145, 5386378, 1869119, 1903435, 7329447,
80 7047359, 1237275, 5062207, 6950192, 7929317, 1312455, 3306115, 6417775,
81 7100756, 1917081, 5834105, 7005614, 1500165, 777191, 2235880, 3406031,
82 7838005, 5548557, 6709241, 6533464, 5796124, 4656147, 594136, 4603424,
83 6366809, 2432395, 2454455, 8215696, 1957272, 3369112, 185531, 7173032,
84 5196991, 162844, 1616392, 3014001, 810149, 1652634, 4686184, 6581310,
85 5341501, 3523897, 3866901, 269760, 2213111, 7404533, 1717735, 472078,
86 7953734, 1723600, 6577327, 1910376, 6712985, 7276084, 8119771, 4546524,
87 5441381, 6144432, 7959518, 6094090, 183443, 7403526, 1612842, 4834730,
88 7826001, 3919660, 8332111, 7018208, 3937738, 1400424, 7534263, 1976782
89};
90
92 4186625, 8354570, 2608894, 518909, 8143293, 777960, 876248, 7913949,
93 6554070, 6026966, 359251, 2091905, 5260684, 2884855, 5268920, 5700314,
94 5654953, 7356305, 1079900, 4794489, 549488, 1119584, 5760665, 2108549,
95 2118186, 3859737, 1399561, 3277672, 6623180, 19422, 4369920, 8100412,
96 5674394, 8284641, 5303092, 4849980, 1661693, 3592148, 2537516, 4464978,
97 3861115, 3043716, 4805995, 2867647, 4840449, 300467, 6031717, 539299,
98 1699267, 1643818, 4874723, 3821735, 4873154, 2140649, 1600420, 4680821,
99 7568473, 7849063, 7426187, 4499374, 4479693, 2556880, 6308525, 2797779,
100 3930395, 1528703, 3677745, 3041255, 1452451, 4904467, 6203962, 1585221,
101 1257611, 6441103, 4083598, 1000202, 3190144, 3157330, 3632928, 8253495,
102 4968207, 983419, 6232521, 5665122, 2967645, 3693493, 411027, 2477047,
103 671102, 1228525, 22981, 1308169, 381987, 7031341, 6527646, 1430430,
104 3343383, 8115473, 7871466, 5282425, 8336129, 1100098, 7475901, 4421799,
105 3724342, 8578, 6727353, 3249728, 5991061, 210977, 7620448, 1316856,
106 8190869, 3553272, 5220671, 1851402, 2409325, 177440, 7064828, 7039087,
107 7094748, 1584928, 812732, 1439742, 3019102, 3881060, 3628969, 4540456,
108 6288750, 4972711, 6063917, 4562441, 3342478, 6136326, 2446433, 3562462,
109 8113420, 5945978, 1235728, 4867236, 3520352, 3759364, 1197226, 3193378,
110 7479715, 6521319, 7470875, 7561383, 7884926, 1613174, 43260, 522500,
111 655327, 3122442, 6348669, 5173371, 3556995, 525098, 768622, 3595838,
112 8038120, 8093429, 2437823, 4272102, 4943130, 3342277, 6644538, 8177373,
113 5538076, 5688936, 2590150, 7115408, 4325093, 7132797, 5894064, 6784443,
114 3767016, 7129923, 5744496, 3548272, 2994039, 6511298, 6476982, 1050970,
115 1333058, 7143142, 3318210, 1430225, 451100, 7067962, 5074302, 1962642,
116 1279661, 6463336, 2546312, 1374803, 6880252, 7603226, 6144537, 4974386,
117 542412, 2831860, 1671176, 1846953, 2584293, 3724270, 7786281, 3776993,
118 2013608, 5948022, 5925962, 164721, 6423145, 5011305, 8194886, 1207385,
119 3183426, 8217573, 6764025, 5366416, 7570268, 6727783, 3694233, 1799107,
120 3038916, 4856520, 4513516, 8110657, 6167306, 975884, 6662682, 7908339,
121 426683, 6656817, 1803090, 6470041, 1667432, 1104333, 260646, 3833893,
122 2939036, 2235985, 420899, 2286327, 8196974, 976891, 6767575, 3545687,
123 554416, 4460757, 48306, 1362209, 4442679, 6979993, 846154, 6403635
124};
125
127{
133 .nRows = 4,
134 .nCols = 4,
135 .privateKeyRange = 2,
136 .encodedCoefficientBitLength = 3,
137 .nChallengeNonZeroCoeffs = 39,
138 .nHintNonZeroCoeffs = 80,
139 .maskCoefficientRangeLog2 = 17,
140 .commitmentModulus = 44,
141 .decomposeR1Factor = 11275,
142 .commitmentRoundingRange = 95232,
143 .w1EncodeCoefficientBitLength = 6, // [0, 43]
144 .cbCommitmentHash = 32,
145 .cbEncodedPrivateKey = 2560,
146 .cbEncodedPublicKey = 1312,
147 .cbEncodedSignature = SYMCRYPT_MLDSA_SIGNATURE_SIZE_MLDSA44
148};
149
151{
157 .nRows = 6,
158 .nCols = 5,
159 .privateKeyRange = 4,
160 .encodedCoefficientBitLength = 4,
161 .nChallengeNonZeroCoeffs = 49,
162 .nHintNonZeroCoeffs = 55,
163 .maskCoefficientRangeLog2 = 19,
164 .commitmentModulus = 16,
165 .decomposeR1Factor = 4100,
166 .commitmentRoundingRange = 261888,
167 .w1EncodeCoefficientBitLength = 4, // [0, 15]
168 .cbCommitmentHash = 48,
169 .cbEncodedPrivateKey = 4032,
170 .cbEncodedPublicKey = 1952,
171 .cbEncodedSignature = SYMCRYPT_MLDSA_SIGNATURE_SIZE_MLDSA65
172};
173
175{
181 .nRows = 8,
182 .nCols = 7,
183 .privateKeyRange = 2,
184 .encodedCoefficientBitLength = 3,
185 .nChallengeNonZeroCoeffs = 60,
186 .nHintNonZeroCoeffs = 75,
187 .maskCoefficientRangeLog2 = 19,
188 .commitmentModulus = 16,
189 .decomposeR1Factor = 4100,
190 .commitmentRoundingRange = 261888,
191 .w1EncodeCoefficientBitLength = 4, // [0, 15]
192 .cbCommitmentHash = 64,
193 .cbEncodedPrivateKey = 4896,
194 .cbEncodedPublicKey = 2592,
195 .cbEncodedSignature = SYMCRYPT_MLDSA_SIGNATURE_SIZE_MLDSA87
196};
197
199{
205
206//
207// Mapping of hash OIDs to SymCrypt hash algorithms. Currently this only contains the "short" hash
208// OIDs, and only for those algorithms that are approved for use in ML-DSA. In the future, we might
209// want to make this functionality more generic, but that requires more thought about the design.
210// Ideally, the SYMCRYPT_HASH structures could contain pointers to their corresponding OIDs, but
211// those structures are exposed externally, so extending them would be a breaking change.
212//
214{
224};
225
226//
227// The table above relies on the OID lists having (at least) two entries, where the second one
228// is the 11-byte encoding of the OID. If this ever changes, the table needs to be updated.
229//
239
245 PCSYMCRYPT_MLDSA_INTERNAL_PARAMS* pInternalParams )
246{
247 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
248
249 switch( params )
250 {
252 *pInternalParams = &SymCryptMlDsaInternalParams44;
253 break;
255 *pInternalParams = &SymCryptMlDsaInternalParams65;
256 break;
258 *pInternalParams = &SymCryptMlDsaInternalParams87;
259 break;
261 scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
262 break;
263 default:
264 scError = SYMCRYPT_INVALID_ARGUMENT;
265 break;
266 }
267
268 return scError;
269}
270
276 SYMCRYPT_MLDSAKEY_FORMAT mlDsakeyFormat,
277 SIZE_T* pcbKeyFormat )
278{
279 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
280 PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pInternalParams = NULL;
281
282 scError = SymCryptMlDsaGetInternalParamsFromParams( params, &pInternalParams );
283 if( scError != SYMCRYPT_NO_ERROR )
284 {
285 goto cleanup;
286 }
287
288 switch( mlDsakeyFormat )
289 {
291 *pcbKeyFormat = SYMCRYPT_MLDSA_ROOT_SEED_SIZE;
292 break;
294 *pcbKeyFormat = pInternalParams->cbEncodedPrivateKey;
295 break;
297 *pcbKeyFormat = pInternalParams->cbEncodedPublicKey;
298 break;
299 default:
300 scError = SYMCRYPT_INVALID_ARGUMENT;
301 break;
302 }
303
304cleanup:
305 return scError;
306}
307
313 SIZE_T* pcbSignature )
314{
315 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
316 PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pInternalParams = NULL;
317
318 scError = SymCryptMlDsaGetInternalParamsFromParams( params, &pInternalParams );
319 if( scError != SYMCRYPT_NO_ERROR )
320 {
321 goto cleanup;
322 }
323
324 *pcbSignature = pInternalParams->cbEncodedSignature;
325
326cleanup:
327 return scError;
328}
329
334 PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pInternalParams,
335 PBYTE pbKey,
336 UINT32 cbKey )
337{
339 SYMCRYPT_ASSERT( pkMlDsakey != NULL );
340
341 UINT8 nRows = pInternalParams->nRows;
342 UINT8 nCols = pInternalParams->nCols;
343
345
346 UINT32 cbMatrix = pInternalParams->cbMatrix; // A matrix
347 UINT32 cbRowVector = pInternalParams->cbRowVector; // s2, t vectors
348 UINT32 cbColVector = pInternalParams->cbColVector; // s1 vector
349
351
352 pkMlDsakey->pParams = pInternalParams;
353 pkMlDsakey->cbTotalSize = cbKey;
354
355 PBYTE pbCurrent = pbKey + sizeof(SYMCRYPT_MLDSAKEY);
356
357 // Public components
358 pkMlDsakey->pmA = SymCryptMlDsaMatrixCreate( pbCurrent, cbMatrix, nRows, nCols );
359 pbCurrent += cbMatrix;
360
361 pkMlDsakey->pvt1 = SymCryptMlDsaVectorCreate( pbCurrent, cbRowVector, nRows );
362 pbCurrent += cbRowVector;
363
364 // Private components
365 pkMlDsakey->pvs1 = SymCryptMlDsaVectorCreate( pbCurrent, cbColVector, nCols );
366 pbCurrent += cbColVector;
367
368 pkMlDsakey->pvs2 = SymCryptMlDsaVectorCreate( pbCurrent, cbRowVector, nRows );
369 pbCurrent += cbRowVector;
370
371 pkMlDsakey->pvt0 = SymCryptMlDsaVectorCreate( pbCurrent, cbRowVector, nRows );
372 pbCurrent += cbRowVector;
373
374 SYMCRYPT_ASSERT( pbCurrent == pbKey + cbKey );
375
376 SYMCRYPT_SET_MAGIC( pkMlDsakey );
377
378 return pkMlDsakey;
379}
380
382VOID
392{
393 // T = InvNTT(NTT(A)*NTT(s1) + NTT(s2))
394 // pvTmp := NTT(A)*NTT(s1)
396 pmA,
397 pvs1,
398 pvTmp,
399 peTmp );
400
401 // TODO: should probably do multiplication by directly in the matrix multiplication function
402 for(UINT8 i = 0; i < pvTmp->nElems; ++i)
403 {
405 }
406
407 // pvTmp := pvTmp + NTT(s2)
408 SymCryptMlDsaVectorAdd( pvTmp, pvs2, pvTmp );
409
410 // T = pvTmp := InvNTT(NTT(A)*NTT(s1) + NTT(s2))
412
413 SymCryptMlDsaVectorPower2Round( pvTmp, pvt1, pvt0 );
414}
415
416UINT32
419{
422
424 UINT32 additionMask = SYMCRYPT_MASK32_LT( res, 0 );
425
426 res = res + (SYMCRYPT_MLDSA_Q & additionMask);
428
429 return (UINT32) res;
430}
431
432UINT32
435{
438
439 return SymCryptMlDsaMontReduce((UINT64) a * b);
440}
441
442UINT32
445{
448
449 UINT32 res = a + b;
450 UINT32 subtractionMask = SYMCRYPT_MASK32_LT( SYMCRYPT_MLDSA_Q - 1, res );
451
452 // If res >= Q, subtract Q
453 res = res - (SYMCRYPT_MLDSA_Q & subtractionMask);
454
455 return res;
456}
457
458UINT32
461{
464
465 UINT32 additionMask = SYMCRYPT_MASK32_LT( a, b );
466
467 // If a < b, result is negative, so we add Q
468 return (INT32) a - (INT32) b + (SYMCRYPT_MLDSA_Q & additionMask);
469}
470
475 PBYTE pbBuffer,
477{
480
482 SYMCRYPT_ASSERT( peElement != NULL );
483
484 return peElement;
485}
486
488VOID
492{
494 {
495 peDst->coeffs[i] = 0;
496 }
497}
498
500VOID
504{
506
507 UINT32 k = 0;
508
510 {
512 {
513 k++;
514 UINT32 twiddleFactor = MLDSA_ZETA_BITREV_TIMES_R[k];
515
516 for(UINT32 j = start; j < start + len; j++)
517 {
518 //
519 // Typically for Montgomery multiplication, both operands have a factor of R.
520 // After multiplying, the product has a factor for R^2, and a reduction is then
521 // performed which divides out a factor of R, resulting in the product again having
522 // a factor of R^1, mod Q. In this case, the twiddleFactor is pre-multiplied by R,
523 // but the coefficients are not expected to have a factor of R; thus, after
524 // reduction, the result does not have a factor of R either.
525 //
526 UINT32 t = SymCryptMlDsaMontMul(twiddleFactor, peSrc->coeffs[j + len]);
527 peSrc->coeffs[j + len] = SymCryptMlDsaModSub(peSrc->coeffs[j], t);
528 peSrc->coeffs[j] = SymCryptMlDsaModAdd(peSrc->coeffs[j], t);
529 }
530 }
531 }
532}
533
535VOID
539{
541
543
545 {
547 {
548 k--;
550
551 for(UINT32 j = start; j < start + len; j++)
552 {
553 //
554 // As above, our twiddleFactor is pre-multiplied by R, but the coefficients are not,
555 // so after the reduction, the result does not have a factor of R.
556 //
557 UINT32 t = peSrc->coeffs[j];
558 peSrc->coeffs[j] = SymCryptMlDsaModAdd(t, peSrc->coeffs[j + len]);
559 peSrc->coeffs[j + len] = SymCryptMlDsaModSub(t, peSrc->coeffs[j + len]);
560 peSrc->coeffs[j + len] = SymCryptMlDsaMontMul(twiddleFactor, peSrc->coeffs[j + len]);
561 }
562 }
563 }
564
566 {
568 }
569}
570
572VOID
576{
578 {
580 }
581}
582
584VOID
590{
592 {
593 peDst->coeffs[i] = SymCryptMlDsaMontMul(peSrc1->coeffs[i], peSrc2->coeffs[i]);
594 }
595}
596
598VOID
604{
606 {
607 peDst->coeffs[i] = SymCryptMlDsaModAdd(peSrc1->coeffs[i], peSrc2->coeffs[i]);
608 }
609}
610
612VOID
618{
620 {
621 peDst->coeffs[i] = SymCryptMlDsaModSub(peSrc1->coeffs[i], peSrc2->coeffs[i]);
622 }
623}
624
629 PBYTE pbBuffer,
631 UINT8 nElems )
632{
636
638 SYMCRYPT_ASSERT( pvVector != NULL );
639
640 pvVector->nElems = nElems;
641 pvVector->cbTotalSize = cbBuffer;
642
643 PBYTE pbCurrent = pbBuffer + sizeof(SYMCRYPT_MLDSA_VECTOR);
644 for( UINT32 i = 0; i < nElems; ++i )
645 {
648 }
649
650 return pvVector;
651}
652
654VOID
659{
660 SYMCRYPT_ASSERT( pvSrc->nElems == pvDst->nElems );
661
662 memcpy( pvDst, pvSrc, pvSrc->cbTotalSize );
663}
664
666VOID
670{
671 for( UINT32 i = 0; i < pvDst->nElems; ++i )
672 {
675 }
676}
677
679VOID
685{
686 SYMCRYPT_ASSERT( pvSrc1->nElems == pvSrc2->nElems );
687 SYMCRYPT_ASSERT( pvSrc1->nElems == pvDst->nElems );
688
689 PCSYMCRYPT_MLDSA_POLYELEMENT peSrc1, peSrc2;
691
692 for( UINT32 i = 0; i < pvSrc1->nElems; ++i )
693 {
694 peSrc1 = SYMCRYPT_INTERNAL_MLDSA_VECTOR_ELEMENT( i, pvSrc1 );
695 peSrc2 = SYMCRYPT_INTERNAL_MLDSA_VECTOR_ELEMENT( i, pvSrc2 );
697
698 SymCryptMlDsaPolyElementAdd( peSrc1, peSrc2, peDst );
699 }
700}
701
703VOID
709{
710 SYMCRYPT_ASSERT( pvSrc1->nElems == pvSrc2->nElems );
711 SYMCRYPT_ASSERT( pvSrc1->nElems == pvDst->nElems );
712
713 PCSYMCRYPT_MLDSA_POLYELEMENT peSrc1, peSrc2;
715
716 for( UINT32 i = 0; i < pvSrc1->nElems; ++i )
717 {
718 peSrc1 = SYMCRYPT_INTERNAL_MLDSA_VECTOR_ELEMENT( i, pvSrc1 );
719 peSrc2 = SYMCRYPT_INTERNAL_MLDSA_VECTOR_ELEMENT( i, pvSrc2 );
721
722 SymCryptMlDsaPolyElementSub( peSrc1, peSrc2, peDst );
723 }
724}
725
727VOID
733{
734 SYMCRYPT_ASSERT( pvSrc1->nElems == pvDst->nElems );
735
736 for( UINT32 i = 0; i < pvSrc1->nElems; ++i )
737 {
740
741 SymCryptMlDsaPolyElementMontMul( peSrc1, peSrc2, peDst );
742 }
743}
744
746VOID
750{
751 for( UINT32 i = 0; i < pvSrc->nElems; ++i )
752 {
754 }
755}
756
757VOID
761{
762 for( UINT32 i = 0; i < pvSrc->nElems; ++i )
763 {
765 }
766}
767
772 PBYTE pbBuffer,
774 UINT8 nRows,
775 UINT8 nCols )
776{
782
784 SYMCRYPT_ASSERT( pMatrix != NULL );
785
786 pMatrix->nRows = nRows;
787 pMatrix->nCols = nCols;
788 pMatrix->cbTotalSize = cbBuffer;
789
790 PBYTE pbCurrent = pbBuffer + sizeof(SYMCRYPT_MLDSA_MATRIX);
791 for(UINT32 i = 0; i < (UINT32) nRows * nCols; ++i)
792 {
795 }
796
797 return pMatrix;
798}
799
801VOID
808{
809 SYMCRYPT_ASSERT( pmSrc1->nCols == pvSrc2->nElems );
810 SYMCRYPT_ASSERT( pmSrc1->nRows == pvDst->nElems );
811
812 PCSYMCRYPT_MLDSA_POLYELEMENT peSrc1, peSrc2;
814
816
817 _Analysis_assume_( pmSrc1->nRows > 0 );
818 _Analysis_assume_( pmSrc1->nCols > 0 );
819
820 for( UINT32 i = 0; i < pmSrc1->nRows; ++i )
821 {
822 // peDst = pvDst[i]
824
825 for( UINT32 j = 0; j < pmSrc1->nCols; ++j )
826 {
827 peSrc1 = SYMCRYPT_INTERNAL_MLDSA_MATRIX_ELEMENT( i, j, pmSrc1 );
828 peSrc2 = SYMCRYPT_INTERNAL_MLDSA_VECTOR_ELEMENT( j, pvSrc2 );
829
830 SymCryptMlDsaPolyElementMontMul( peSrc1, peSrc2, peTmp );
831 SymCryptMlDsaPolyElementAdd( peDst, peTmp, peDst );
832 }
833 }
834}
835
837VOID
840 PCBYTE pbRejNttPolySeed,
841 SIZE_T cbRejNttPolySeed,
843{
845
846 SYMCRYPT_SHAKE128_STATE shakeState;
847 SymCryptShake128Init( &shakeState );
848 SymCryptShake128Append( &shakeState, pbRejNttPolySeed, cbRejNttPolySeed );
849
850 UINT32 coeff = 0;
851 BYTE shakeBytes[4]; // We only use 3 bytes, but using 4 allows converting to UINT32 more easily
852
853 SymCryptWipeKnownSize( shakeBytes, sizeof(shakeBytes) );
854
856 {
857 // CoeffFromThreeBytes from FIPS 204
858 do
859 {
860 SymCryptShake128Extract( &shakeState, shakeBytes, 3, FALSE );
861 shakeBytes[2] &= 0x7F; // if b2 > 127, b2 -= 128
862 coeff = SYMCRYPT_LOAD_LSBFIRST32( shakeBytes );
863 } while (coeff >= SYMCRYPT_MLDSA_Q);
864
865 peDst->coeffs[i] = coeff;
866 }
867}
868
870VOID
873 PCBYTE pbPublicSeed,
874 SIZE_T cbPublicSeed,
876{
879
880 // The expanded seed is the public seed concatenated with one byte each for the column and row
881 // indices of the matrix element being expanded.
883 memcpy( rejNttSeed, pbPublicSeed, cbPublicSeed );
884
885 for( UINT8 i = 0; i < pmA->nRows; ++i )
886 {
887 for( UINT8 j = 0; j < pmA->nCols; ++j )
888 {
889 rejNttSeed[SYMCRYPT_MLDSA_REJNTTPOLY_SEED_SIZE - 2] = j;
890 rejNttSeed[SYMCRYPT_MLDSA_REJNTTPOLY_SEED_SIZE - 1] = i;
891
892 #pragma prefast( suppress: 6385, "False warning - reading invalid data from rejNttSeed" );
893 SymCryptMlDsaRejNttPoly( rejNttSeed, sizeof(rejNttSeed), SYMCRYPT_INTERNAL_MLDSA_MATRIX_ELEMENT( i, j, pmA ) );
894
895 }
896 }
897}
898
901INT8
905 UINT8 halfByte )
906{
907 SYMCRYPT_ASSERT( halfByte <= 15 );
908 SYMCRYPT_ASSERT( pParams->privateKeyRange == 2 || pParams->privateKeyRange == 4 );
909
910 if( pParams->privateKeyRange == 2 && halfByte < 15)
911 {
912 UINT8 halfByteDiv5 = (UINT8) ( ( halfByte * 13 ) >> 6 );
913 UINT8 halfByteMod5 = halfByte - (5 * halfByteDiv5);
914 return 2 - halfByteMod5;
915 }
916 else if( pParams->privateKeyRange == 4 && halfByte < 9 )
917 {
918 return 4 - halfByte;
919 }
920
921 return INT8_MIN;
922}
923
925VOID
929 PCBYTE pbRejBoundedPolySeed,
930 SIZE_T cbRejBoundedPolySeed,
932{
934
935 SYMCRYPT_SHAKE256_STATE shakeState;
936 SymCryptShake256Init( &shakeState );
937 SymCryptShake256Append( &shakeState, pbRejBoundedPolySeed, cbRejBoundedPolySeed );
938
939 BYTE shakeByte;
940 UINT32 i = 0;
941 INT8 z0, z1;
942
943 do
944 {
945 // Note on sidechannel safety: the rejection sampling here can leak which bytes of the SHAKE
946 // output are used and which are rejected. However, bytes themselves are not leaked. This
947 // may allow the attacker to more quickly eliminate incorrect seed values when doing an
948 // exhaustive search, but given the size of the seed this should still not make the
949 // exhaustive search computationally feasible.
950 SymCryptShake256Extract( &shakeState, &shakeByte, sizeof(shakeByte), FALSE );
951 z0 = SymCryptMlDsaCoeffFromHalfByte( pParams, shakeByte & 0x0F );
952 z1 = SymCryptMlDsaCoeffFromHalfByte( pParams, shakeByte >> 4 );
953
954 SYMCRYPT_ASSERT( z0 == INT8_MIN || (( z0 + pParams->privateKeyRange >= 0 ) && ( z0 + pParams->privateKeyRange <= 2 * pParams->privateKeyRange )) );
955 SYMCRYPT_ASSERT( z1 == INT8_MIN || (( z1 + pParams->privateKeyRange >= 0 ) && ( z1 + pParams->privateKeyRange <= 2 * pParams->privateKeyRange )) );
956
957 if(z0 != INT8_MIN)
958 {
960 i++;
961 }
962
964 {
966 i++;
967 }
968
970
971 SymCryptWipeKnownSize( &shakeState, sizeof(shakeState) );
972}
973
975VOID
979 PCBYTE pbPrivateVectorSeed,
980 SIZE_T cbPrivateVectorSeed,
983{
986
987 UINT32 nRows = pParams->nRows;
988 UINT32 nCols = pParams->nCols;
989
990 // The expanded seed is the private vector seed concatenated with the (two-byte) row/column
991 // index of the vector element being expanded.
993 memcpy( rejBoundedPolySeed, pbPrivateVectorSeed, cbPrivateVectorSeed );
994
995 for(UINT16 i = 0; i < nCols; ++i)
996 {
998 SymCryptMlDsaRejBoundedPoly( pParams, rejBoundedPolySeed, sizeof(rejBoundedPolySeed),
1000 }
1001
1002 for(UINT16 i = 0; i < nRows; ++i)
1003 {
1005 #pragma prefast( suppress: 6385, "False warning - reading invalid data from rejBoundedPolySeed" ); // Doesn't trigger in previous loop for some reason
1006 SymCryptMlDsaRejBoundedPoly( pParams, rejBoundedPolySeed, sizeof(rejBoundedPolySeed),
1008 }
1009
1010 SymCryptWipeKnownSize( rejBoundedPolySeed, sizeof(rejBoundedPolySeed) );
1011}
1012
1014VOID
1018 PCBYTE pbCommitmentHash,
1019 SIZE_T cbCommitmentHash,
1020 PSYMCRYPT_MLDSA_POLYELEMENT peChallenge )
1021{
1022 SymCryptMlDsaPolyElementSetZero( peChallenge );
1023
1024 SYMCRYPT_SHAKE256_STATE shakeState;
1025 SymCryptShake256Init( &shakeState );
1026 SymCryptShake256Append( &shakeState, pbCommitmentHash, cbCommitmentHash );
1027
1028 // The first 8 bytes are used as as powers of negative one when sampling the challenge
1029 // polynomial: c[j] = -1^(H(rho)[i + tau - 256])
1030 BYTE temp[8];
1031 SYMCRYPT_ASSERT( pParams->nChallengeNonZeroCoeffs <= 8 * sizeof(temp) );
1032 SymCryptShake256Extract( &shakeState, temp, sizeof(temp), FALSE );
1033
1034 UINT64 powersOfNegativeOne = SYMCRYPT_LOAD_LSBFIRST64( temp );
1035
1038 ++i)
1039 {
1040 BYTE j = 0;
1041 do
1042 {
1043 SymCryptShake256Extract( &shakeState, &j, sizeof(j), FALSE );
1044 } while( j > i );
1045
1046 peChallenge->coeffs[i] = peChallenge->coeffs[j];
1047
1048 UINT32 negativeMask = SYMCRYPT_MASK32_NONZERO( powersOfNegativeOne & 1 );
1049 powersOfNegativeOne >>= 1;
1050
1051 // Set the coefficient modulo Q
1052 peChallenge->coeffs[j] = ((SYMCRYPT_MLDSA_Q - 1) & negativeMask) | (1 & ~negativeMask);
1053 }
1054
1055 SymCryptWipeKnownSize( &shakeState, sizeof(shakeState) );
1056}
1057
1059VOID
1063 PSYMCRYPT_SHAKE256_STATE pShakeState,
1064 PCBYTE pbPrivateRandom,
1065 SIZE_T cbPrivateRandom,
1067 PSYMCRYPT_MLDSA_VECTOR pvMask )
1068{
1069 SYMCRYPT_ASSERT( pParams->nCols == pvMask->nElems );
1070 SYMCRYPT_ASSERT( cbPrivateRandom == SYMCRYPT_SHAKE256_RESULT_SIZE );
1071
1072 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1073 BYTE seedSuffix[2];
1074
1075 UINT32 cbShakeOutput = (pParams->maskCoefficientRangeLog2 + 1) * (SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8);
1076 BYTE shakeOutput[20 * 32]; // Maximum size of the SHAKE output
1077 SYMCRYPT_ASSERT( cbShakeOutput <= sizeof(shakeOutput) );
1078
1079 for(UINT16 i = 0; i < pvMask->nElems; ++i)
1080 {
1081 SYMCRYPT_STORE_LSBFIRST16( seedSuffix, counter + i );
1082 SymCryptShake256Append( pShakeState, pbPrivateRandom, cbPrivateRandom );
1083 SymCryptShake256Append( pShakeState, (PBYTE) &seedSuffix, sizeof(seedSuffix) );
1084 SymCryptShake256Extract( pShakeState, shakeOutput, cbShakeOutput, TRUE );
1085
1087 shakeOutput,
1088 pParams->maskCoefficientRangeLog2 + 1,
1089 1 << pParams->maskCoefficientRangeLog2,
1091 SYMCRYPT_ASSERT( scError == SYMCRYPT_NO_ERROR );
1092 }
1093
1094 SymCryptMlDsaVectorNTT( pvMask );
1095}
1096
1098VOID
1102 PSYMCRYPT_MLDSA_VECTOR pvWMinusCs2,
1103 PSYMCRYPT_MLDSA_VECTOR pvWMinusCs2PlusCt0,
1105 UINT32* nBitsSet )
1106{
1107 SYMCRYPT_ASSERT( pvWMinusCs2->nElems == pvWMinusCs2PlusCt0->nElems );
1108 SYMCRYPT_ASSERT( pvWMinusCs2->nElems == pvDst->nElems );
1109
1110 *nBitsSet = 0;
1111
1112 SymCryptMlDsaVectorHighBits( pParams, pvWMinusCs2, pvWMinusCs2 );
1113 SymCryptMlDsaVectorHighBits( pParams, pvWMinusCs2PlusCt0, pvWMinusCs2PlusCt0 );
1114
1115 for( UINT32 i = 0; i < pvDst->nElems; ++i )
1116 {
1120
1122 {
1123 peDst->coeffs[j] = 1 & ~SYMCRYPT_MASK32_EQ(peVec0->coeffs[j], peVec1->coeffs[j]);
1124 *nBitsSet += peDst->coeffs[j];
1125 }
1126 }
1127}
1128
1130VOID
1135 PSYMCRYPT_MLDSA_VECTOR pvCommitment )
1136{
1137 SYMCRYPT_ASSERT( pvHint->nElems == pvCommitment->nElems );
1138
1139 UINT32 r1, r0;
1140 UINT32 hintIsZeroMask;
1141 UINT32 tmpMask;
1142 UINT32 r0PrimeGtZeroMask;
1143 UINT32 positiveOffsetCoeff;
1144 UINT32 negativeOffsetCoeff;
1145
1146 for(UINT32 i = 0; i < pvHint->nElems; ++i)
1147 {
1150
1152 {
1153 SYMCRYPT_ASSERT( peHint->coeffs[j] == 0 || peHint->coeffs[j] == 1 );
1154
1155 SymCryptMlDsaDecompose( pParams, peCommitment->coeffs[j], &r1, &r0 );
1156
1157 //
1158 // FIPS-204 UseHint lines 3-5
1159 // r1 in range [0, commitmentModulus)
1160 // r0 in range [-commitmentRoundingRange, commitmentRoundingRange], encoded
1161 // as an unsigned integer modulo Q
1162 //
1163 // Let r0' := r0 mod+- 2*gamma_2
1164 // (This is just r0 in FIPS 204, which uses signed integers.)
1165 //
1166 // r0 - 1 < commitmentRoundingRange => r0' > 0
1167 // r0 - 1 >= commitmentRoundingRange => r0' <= 0
1168 //
1169 // There are three cases to consider:
1170 // 1. If the hint is zero, the coefficient is set to r1.
1171 // 2. Else if r0' > 0, the coefficient is (r1 + 1) mod commitmentModulus.
1172 // 3. Else (r0' <= 0), the coefficient is (r1 - 1) mod commitmentModulus.
1173 //
1174 // The hint is public so we don't have to implement this in a sidechannel-safe manner,
1175 // but avoiding branches will improve performance.
1176 //
1177
1178 // Set up masks to determine which case we fall into
1179 hintIsZeroMask = peHint->coeffs[j] - 1; // 0 if hint is 1, 0xFFFFFFFF if hint is 0
1180 r0PrimeGtZeroMask = SYMCRYPT_MASK32_LT( r0 - 1, pParams->commitmentRoundingRange );
1181
1182 // Case 2: r0' > 0, so the coefficient is (r1 + 1) mod commitmentModulus,
1183 // i.e. (r1 + 1) if r1 != commitmentModulus - 1, else 0
1184 tmpMask = ~SYMCRYPT_MASK32_EQ( r1, (UINT32) (pParams->commitmentModulus - 1) );
1185 positiveOffsetCoeff = tmpMask & (r1 + 1);
1186
1187 // Case 3: r0' <= 0, so the coefficient is (r1 - 1) mod commitmentModulus,
1188 // i.e. (r1 - 1) if r1 != 0, else commitmentModulus - 1
1189 tmpMask = SYMCRYPT_MASK32_EQ( r1, 0 );
1190 negativeOffsetCoeff = ( tmpMask & (pParams->commitmentModulus - 1) ) | ( ~tmpMask & ( r1 - 1 ) );
1191
1192 // Mask out each possible coefficient based on which case we fall into
1193 r1 &= hintIsZeroMask;
1194 positiveOffsetCoeff &= ~hintIsZeroMask & r0PrimeGtZeroMask;
1195 negativeOffsetCoeff &= ~hintIsZeroMask & ~r0PrimeGtZeroMask;
1196
1197 // Sanity check: no combination of masked values should be set simultaneously
1198 SYMCRYPT_ASSERT( (r1 & positiveOffsetCoeff) == 0 );
1199 SYMCRYPT_ASSERT( (r1 & negativeOffsetCoeff) == 0 );
1200 SYMCRYPT_ASSERT( (positiveOffsetCoeff & negativeOffsetCoeff) == 0 );
1201
1202 // Finally, we can pick the correct coefficient using our masks
1203 peCommitment->coeffs[j] = r1 | positiveOffsetCoeff | negativeOffsetCoeff;
1204 }
1205 }
1206}
1207
1212 PCSYMCRYPT_MLDSAKEY pkMlDsakey,
1213 PBYTE pbDst,
1214 SIZE_T cbDst )
1215{
1216 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1217
1218 PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams = pkMlDsakey->pParams;
1219 UINT32 cbEncodedKey = pParams->cbEncodedPublicKey;
1221
1222 if( cbDst != cbEncodedKey )
1223 {
1224 scError = SYMCRYPT_INVALID_ARGUMENT;
1225 goto cleanup;
1226 }
1227
1228 pTemps = SymCryptMlDsaTemporariesAllocateAndInitialize( pParams, 1, 0, 0, 0 );
1229 if( pTemps == NULL )
1230 {
1231 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1232 goto cleanup;
1233 }
1234
1235 {
1236 PSYMCRYPT_MLDSA_VECTOR pvT1InvNTT = pTemps->pvRowVectors[0];
1237
1238 PBYTE pbCurr = pbDst;
1239 memcpy( pbCurr, pkMlDsakey->publicSeed, SYMCRYPT_MLDSA_PUBLIC_SEED_SIZE );
1240
1242
1243 SymCryptMlDsaVectorCopy( pkMlDsakey->pvt1, pvT1InvNTT );
1244 SymCryptMlDsaVectorINTT( pvT1InvNTT );
1245
1246 // Pack each coefficient of T1 into 10 bits. Coefficients are rounded by Power2Round so they're
1247 // guaranteed to be at most 10 bits long.
1249 SymCryptMlDsaVectorEncode( pvT1InvNTT, 10, 0, pbCurr );
1250 }
1251
1252cleanup:
1253 if( pTemps != NULL)
1254 {
1256 }
1257
1258 return scError;
1259}
1260
1265 PCBYTE pbSrc,
1266 SIZE_T cbSrc,
1267 UINT32 flags,
1268 PSYMCRYPT_MLDSAKEY pkMlDsakey )
1269{
1271
1272 // Size of one encoded polynomial from t1: 256 coefficients * 10 bits per coefficient / 8 bits per byte
1273 const UINT32 cbEncodedPoly = SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS * 10 / 8;
1274
1275 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1276 PCBYTE pbCurr = pbSrc;
1278 PSYMCRYPT_SHAKE256_STATE pShakeState = NULL;
1279
1280 if( cbSrc != pkMlDsakey->pParams->cbEncodedPublicKey )
1281 {
1282 scError = SYMCRYPT_WRONG_KEY_SIZE;
1283 goto cleanup;
1284 }
1285
1286 // Allocate space for an encoded polynomial so we can copy the input, decode it, and append it
1287 // to our SHAKE state. We copy it to a local buffer so we don't violate the read-once rule when
1288 // appending to the SHAKE state.
1289 pTemps = SymCryptMlDsaTemporariesAllocateAndInitialize( pkMlDsakey->pParams, 0, 0, 0, cbEncodedPoly );
1290 if( pTemps == NULL )
1291 {
1292 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1293 goto cleanup;
1294 }
1295
1296 // Reset the private key state in case this key object is being reused
1297 if( pkMlDsakey->hasRootSeed )
1298 {
1300 pkMlDsakey->hasRootSeed = FALSE;
1301 }
1302
1303 if( pkMlDsakey->hasPrivateKey )
1304 {
1305 SymCryptWipeKnownSize( pkMlDsakey->privateSigningSeed, SYMCRYPT_MLDSA_PRIVATE_SIGNING_SEED_SIZE );
1306 SymCryptMlDsaVectorSetZero( pkMlDsakey->pvs1 );
1307 SymCryptMlDsaVectorSetZero( pkMlDsakey->pvs2 );
1308 SymCryptMlDsaVectorSetZero( pkMlDsakey->pvt0 );
1309 pkMlDsakey->hasPrivateKey = FALSE;
1310 }
1311
1312 memcpy( pkMlDsakey->publicSeed, pbCurr, SYMCRYPT_MLDSA_PUBLIC_SEED_SIZE );
1314
1315 pShakeState = &(pTemps->shake256State);
1316
1317 SymCryptShake256Init( pShakeState );
1318 SymCryptShake256Append( pShakeState, pkMlDsakey->publicSeed, SYMCRYPT_MLDSA_PUBLIC_SEED_SIZE );
1319
1320 for( UINT32 i = 0; i < pkMlDsakey->pvt1->nElems; ++i )
1321 {
1322 memcpy( pTemps->pbScratch, pbCurr, cbEncodedPoly );
1323
1325
1327 pTemps->pbScratch,
1328 10,
1329 0,
1330 peElement );
1331 if( scError != SYMCRYPT_NO_ERROR )
1332 {
1333 goto cleanup;
1334 }
1335
1336 SymCryptShake256Append( pShakeState, pTemps->pbScratch, cbEncodedPoly );
1337
1338 pbCurr += cbEncodedPoly;
1339 }
1340
1341 SYMCRYPT_ASSERT( pbCurr == pbSrc + cbSrc );
1342
1343 SymCryptMlDsaVectorNTT( pkMlDsakey->pvt1 );
1344
1346 pkMlDsakey->publicSeed,
1348 pkMlDsakey->pmA );
1349
1350 SymCryptShake256Result( pShakeState, pkMlDsakey->publicKeyHash );
1351
1352cleanup:
1353 if( pTemps != NULL )
1354 {
1356 }
1357
1358 return scError;
1359}
1360
1365 PCSYMCRYPT_MLDSAKEY pkMlDsakey,
1366 PBYTE pbDst,
1367 SIZE_T cbDst )
1368{
1369 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1370 PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams = pkMlDsakey->pParams;
1371 UINT32 cbEncodedKey = pParams->cbEncodedPrivateKey;
1373 PBYTE pbCurr = pbDst;
1374
1375 if( !pkMlDsakey->hasPrivateKey )
1376 {
1377 scError = SYMCRYPT_INCOMPATIBLE_FORMAT;
1378 goto cleanup;
1379 }
1380
1381 if( cbDst != cbEncodedKey )
1382 {
1383 scError = SYMCRYPT_INVALID_ARGUMENT;
1384 goto cleanup;
1385 }
1386
1387 pTemps = SymCryptMlDsaTemporariesAllocateAndInitialize( pParams, 1, 1, 0, 0 );
1388 if( pTemps == NULL )
1389 {
1390 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1391 goto cleanup;
1392 }
1393
1394 memcpy( pbCurr, pkMlDsakey->publicSeed, SYMCRYPT_MLDSA_PUBLIC_SEED_SIZE );
1396
1397 memcpy( pbCurr, pkMlDsakey->privateSigningSeed, SYMCRYPT_MLDSA_PRIVATE_SIGNING_SEED_SIZE );
1399
1400 memcpy( pbCurr, pkMlDsakey->publicKeyHash, SYMCRYPT_MLDSA_PUBLIC_KEY_HASH_SIZE );
1402
1403 {
1404 // Inverse NTT and encode s1
1405 PSYMCRYPT_MLDSA_VECTOR pvs1InvNTT = pTemps->pvColVectors[0];
1406 SymCryptMlDsaVectorCopy( pkMlDsakey->pvs1, pvs1InvNTT );
1407 SymCryptMlDsaVectorINTT( pvs1InvNTT );
1408
1410 pvs1InvNTT,
1412 pParams->privateKeyRange,
1413 pbCurr );
1415 }
1416
1417 {
1418 // Inverse NTT and encode s2
1419 PSYMCRYPT_MLDSA_VECTOR pvs2InvNTT = pTemps->pvRowVectors[0];
1420 SymCryptMlDsaVectorCopy( pkMlDsakey->pvs2, pvs2InvNTT );
1421 SymCryptMlDsaVectorINTT( pvs2InvNTT );
1422
1424 pvs2InvNTT,
1426 pParams->privateKeyRange,
1427 pbCurr );
1429 }
1430
1431 {
1432 // Inverse NTT and encode t0
1433 // Can re-use the previous temporary row vector as it's no longer needed
1434 PSYMCRYPT_MLDSA_VECTOR pvt0InvNTT = pTemps->pvRowVectors[0];
1435 SymCryptMlDsaVectorCopy( pkMlDsakey->pvt0, pvt0InvNTT );
1436 SymCryptMlDsaVectorINTT( pvt0InvNTT );
1437
1439 pvt0InvNTT,
1442 pbCurr );
1444 }
1445
1446 SYMCRYPT_ASSERT( pbCurr == pbDst + cbDst );
1447
1448cleanup:
1449 if( pTemps != NULL)
1450 {
1452 }
1453
1454 return scError;
1455}
1456
1461 PCBYTE pbSrc,
1462 SIZE_T cbSrc,
1463 UINT32 flags,
1464 PSYMCRYPT_MLDSAKEY pkMlDsakey )
1465{
1467
1468 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1469 PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams = pkMlDsakey->pParams;
1471 PCBYTE pbCurr = pbSrc;
1473
1474 if( cbSrc != pkMlDsakey->pParams->cbEncodedPrivateKey )
1475 {
1476 scError = SYMCRYPT_WRONG_KEY_SIZE;
1477 goto cleanup;
1478 }
1479
1481 pParams,
1482 2, // row vectors - t, t0
1483 0, // column vectors
1484 1, // poly elements - temporary space
1485 pkMlDsakey->pParams->cbEncodedPublicKey ); // scratch space
1486 if( pTemps == NULL )
1487 {
1488 scError = SYMCRYPT_MEMORY_ALLOCATION_FAILURE;
1489 goto cleanup;
1490 }
1491
1492 // We use temporaries to recalculate t, t0, t1 and the public key hash from the import values
1493 // for A (derived from the public seed), s1 and s2. This is not strictly necessary for callers
1494 // who just want to import a private key and use it for signing, but it allows the private
1495 // key to also be used for verification, and more importantly, provides extra robustness by
1496 // ensuring that the derived values are consistent with the encoded values. If the perf of
1497 // importing a key becomes a concern, we can move this recalculation to the first time the key
1498 // is used for verification.
1499 PSYMCRYPT_MLDSA_VECTOR pvtTmp = pTemps->pvRowVectors[0];
1500 PSYMCRYPT_MLDSA_VECTOR pvt0Tmp = pTemps->pvRowVectors[1];
1501 PSYMCRYPT_MLDSA_POLYELEMENT peTmp = pTemps->pePolyElements[0];
1502 PBYTE pbEncodedPubKeyTmp = pTemps->pbScratch;
1503
1504 // Reset the key state in case this key is being reused
1505 pkMlDsakey->hasRootSeed = FALSE;
1506 pkMlDsakey->hasPrivateKey = FALSE;
1508
1509 memcpy( pkMlDsakey->publicSeed, pbCurr, SYMCRYPT_MLDSA_PUBLIC_SEED_SIZE );
1511
1512 memcpy( pkMlDsakey->privateSigningSeed, pbCurr, SYMCRYPT_MLDSA_PRIVATE_SIGNING_SEED_SIZE );
1514
1515 memcpy( pubKeyHashTmp, pbCurr, SYMCRYPT_MLDSA_PUBLIC_KEY_HASH_SIZE );
1517
1518 // Expand A matrix
1519 SymCryptMlDsaExpandA( pkMlDsakey->publicSeed, SYMCRYPT_MLDSA_PUBLIC_SEED_SIZE, pkMlDsakey->pmA );
1520
1521 scError = SymCryptMlDsaVectorDecode(
1522 pbCurr,
1524 pParams->privateKeyRange,
1525 pkMlDsakey->pvs1 );
1526 if( scError != SYMCRYPT_NO_ERROR )
1527 {
1528 goto cleanup;
1529 }
1530 pbCurr += SYMCRYPT_INTERNAL_MLDSA_SIZEOF_ENCODED_VECTOR( pkMlDsakey->pvs1, pParams->encodedCoefficientBitLength );
1531
1532
1533 scError = SymCryptMlDsaVectorDecode(
1534 pbCurr,
1536 pParams->privateKeyRange,
1537 pkMlDsakey->pvs2 );
1538 if( scError != SYMCRYPT_NO_ERROR )
1539 {
1540 goto cleanup;
1541 }
1542 pbCurr += SYMCRYPT_INTERNAL_MLDSA_SIZEOF_ENCODED_VECTOR( pkMlDsakey->pvs2, pParams->encodedCoefficientBitLength );
1543
1544 scError = SymCryptMlDsaVectorDecode(
1545 pbCurr,
1548 pvt0Tmp );
1549 if( scError != SYMCRYPT_NO_ERROR )
1550 {
1551 goto cleanup;
1552 }
1554
1555 SYMCRYPT_ASSERT( pbCurr == pbSrc + cbSrc );
1556
1557 // Convert s1 and s2 to NTT form
1558 SymCryptMlDsaVectorNTT( pkMlDsakey->pvs1 );
1559 SymCryptMlDsaVectorNTT( pkMlDsakey->pvs2 );
1560
1562 pkMlDsakey->pmA,
1563 pkMlDsakey->pvs1,
1564 pkMlDsakey->pvs2,
1565 pkMlDsakey->pvt0,
1566 pkMlDsakey->pvt1,
1567 pvtTmp,
1568 peTmp );
1569
1570 // If the recalculated t0 doesn't match, the imported key is invalid.
1571 // Note: SymCryptMlDsakeyComputeT sets t0 and t1 in NTT form.
1572 if( memcmp( pkMlDsakey->pvt0, pvt0Tmp, pvt0Tmp->cbTotalSize ) != 0 )
1573 {
1574 scError = SYMCRYPT_INVALID_BLOB;
1575 goto cleanup;
1576 }
1577
1578 // Convert t0 and t1 to NTT form
1579 SymCryptMlDsaVectorNTT( pkMlDsakey->pvt0 );
1580 SymCryptMlDsaVectorNTT( pkMlDsakey->pvt1 );
1581
1582 scError = SymCryptMlDsaPkEncode( pkMlDsakey, pbEncodedPubKeyTmp, pParams->cbEncodedPublicKey );
1583 if( scError != SYMCRYPT_NO_ERROR )
1584 {
1585 goto cleanup;
1586 }
1587
1588 // Recalculate the public key hash and compare it to the imported value. If they don't match,
1589 // the imported key is invalid.
1591 pbEncodedPubKeyTmp,
1592 pParams->cbEncodedPublicKey,
1593 pkMlDsakey->publicKeyHash,
1595
1596 if( memcmp( pkMlDsakey->publicKeyHash, pubKeyHashTmp, SYMCRYPT_MLDSA_PUBLIC_KEY_HASH_SIZE ) != 0 )
1597 {
1598 scError = SYMCRYPT_INVALID_BLOB;
1599 goto cleanup;
1600 }
1601
1602 pkMlDsakey->hasPrivateKey = TRUE;
1603
1604cleanup:
1605 if( pTemps != NULL )
1606 {
1608 }
1609
1610 // Wipe private state on error as defense-in-depth
1611 if( scError != SYMCRYPT_NO_ERROR )
1612 {
1613 SymCryptWipeKnownSize( pkMlDsakey->privateSigningSeed, SYMCRYPT_MLDSA_PRIVATE_SIGNING_SEED_SIZE );
1614 SymCryptMlDsaVectorSetZero( pkMlDsakey->pvs1 );
1615 SymCryptMlDsaVectorSetZero( pkMlDsakey->pvs2 );
1616 SymCryptMlDsaVectorSetZero( pkMlDsakey->pvt0 );
1617 }
1618
1619 return scError;
1620}
1621
1623VOID
1627 PBYTE pbCommitmentHash,
1628 SIZE_T cbCommitmentHash,
1629 PCSYMCRYPT_MLDSA_VECTOR pvResponse,
1631 PBYTE pbDst,
1632 SIZE_T cbDst )
1633{
1634 SYMCRYPT_ASSERT( cbDst == pParams->cbEncodedSignature );
1635 UNREFERENCED_PARAMETER( cbDst );
1636
1637 const SIZE_T cbEncodedHint = pParams->nHintNonZeroCoeffs + pvHint->nElems;
1638
1639 PBYTE pbCurr = pbDst;
1640
1641 memcpy( pbCurr, pbCommitmentHash, cbCommitmentHash );
1642 pbCurr += cbCommitmentHash;
1643
1645 pvResponse,
1646 pParams->maskCoefficientRangeLog2 + 1,
1647 1 << pParams->maskCoefficientRangeLog2,
1648 pbCurr );
1649
1650 pbCurr += SYMCRYPT_INTERNAL_MLDSA_SIZEOF_ENCODED_VECTOR( pvResponse, pParams->maskCoefficientRangeLog2 + 1 );
1651
1652 SymCryptMlDsaHintBitPack( pParams, pvHint, pbCurr );
1653 pbCurr += cbEncodedHint;
1654
1655 SYMCRYPT_ASSERT( pbCurr == pbDst + cbDst );
1656}
1657
1663 PCBYTE pbSig,
1664 SIZE_T cbSig,
1665 PBYTE pbCommitmentHash,
1666 SIZE_T cbCommitmentHash,
1667 PSYMCRYPT_MLDSA_VECTOR pvResponse,
1668 PSYMCRYPT_MLDSA_VECTOR pvHint )
1669{
1670 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1671
1672 if( cbSig != pParams->cbEncodedSignature )
1673 {
1674 scError = SYMCRYPT_WRONG_DATA_SIZE;
1675 goto cleanup;
1676 }
1677
1678 SYMCRYPT_ASSERT( cbCommitmentHash == pParams->cbCommitmentHash );
1679
1680 PCBYTE pbCurr = pbSig;
1681
1682 memcpy( pbCommitmentHash, pbSig, cbCommitmentHash );
1683 pbCurr += cbCommitmentHash;
1684
1686 pbCurr,
1687 pParams->maskCoefficientRangeLog2 + 1,
1688 1 << pParams->maskCoefficientRangeLog2,
1689 pvResponse );
1690 pbCurr += SYMCRYPT_INTERNAL_MLDSA_SIZEOF_ENCODED_VECTOR( pvResponse, pParams->maskCoefficientRangeLog2 + 1 );
1691
1692 SYMCRYPT_ASSERT( cbSig - (pbCurr - pbSig) == (SIZE_T) pParams->nHintNonZeroCoeffs + pvHint->nElems );
1693
1694 scError = SymCryptMlDsaHintBitUnpack( pParams, pbCurr, pvHint );
1695 if( scError != SYMCRYPT_NO_ERROR )
1696 {
1697 goto cleanup;
1698 }
1699
1700cleanup:
1701 return scError;
1702}
1703
1705VOID
1710 PBYTE pbDst )
1711{
1713
1714 UINT32 index = 0;
1715 for( UINT32 i = 0; i < pvSrc->nElems; ++i )
1716 {
1719 {
1720 // Side channel safety: the hint is public (part of the signature) so it's okay to
1721 // leak information here
1722 if( peElement->coeffs[j] != 0 )
1723 {
1724 // Each byte in the hint is the index of a non-zero coefficient
1725 pbDst[index] = (BYTE) j;
1726 index++;
1727 }
1728 }
1729
1730 // The number of non-zero coefficients in polynomials 0..i is stored in the
1731 // (nHintNonZeroCoeffs + i)th byte. This allows us to determine which indices correspond
1732 // to which polynomials during decoding while still only using one byte per index.
1733 SYMCRYPT_ASSERT( index <= pParams->nHintNonZeroCoeffs );
1734 pbDst[pParams->nHintNonZeroCoeffs + i] = (BYTE) index;
1735 }
1736}
1737
1743 PCBYTE pbSrc,
1745{
1746 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1747 UINT32 index = 0;
1748 UINT32 maxIndex = 0;
1749 UINT32 first = 0;
1750
1751 for( UINT32 i = 0; i < pvDst->nElems; ++i )
1752 {
1754
1755 // Ensure pvDst is zeroed out before unpacking
1757
1758 maxIndex = pbSrc[pParams->nHintNonZeroCoeffs + i];
1759 if( ( maxIndex < index) ||
1760 ( maxIndex > pParams->nHintNonZeroCoeffs) )
1761 {
1762 // Invalid input
1763 scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1764 goto cleanup;
1765 }
1766
1767 first = index;
1768 while( index < maxIndex )
1769 {
1770 if( index > first && pbSrc[index - 1] >= pbSrc[index])
1771 {
1772 // Invalid input
1773 scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1774 goto cleanup;
1775 }
1776
1777 peElement->coeffs[pbSrc[index]] = 1;
1778 index++;
1779 }
1780 }
1781
1782 for(UINT32 leftover = index; leftover < pParams->nHintNonZeroCoeffs; ++leftover)
1783 {
1784 if( pbSrc[leftover] != 0 )
1785 {
1786 // Invalid input
1787 scError = SYMCRYPT_SIGNATURE_VERIFICATION_FAILURE;
1788 goto cleanup;
1789 }
1790 }
1791
1792cleanup:
1793 return scError;
1794}
1795
1801 SYMCRYPT_PQDSA_HASH_ID hashAlg,
1802 SIZE_T cbHash,
1803 PCSYMCRYPT_OID* ppOid )
1804{
1805 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
1806 PCSYMCRYPT_OID pHashOid = NULL;
1807 BOOLEAN fFound = FALSE;
1808 BOOLEAN fIsXof = FALSE;
1809 SIZE_T cbHashExpected = 0;
1810
1811 for( UINT32 i = 0; i < SYMCRYPT_ARRAY_SIZE(g_hashOidMap); ++i )
1812 {
1813 if( g_hashOidMap[i].hashId == hashAlg )
1814 {
1815 fFound = TRUE;
1816 pHashOid = g_hashOidMap[i].pOid;
1817 fIsXof = g_hashOidMap[i].fIsXof;
1818 cbHashExpected = g_hashOidMap[i].pHashAlgorithm->resultSize;
1819 break;
1820 }
1821 }
1822
1823 if( !fFound )
1824 {
1825 scError = SYMCRYPT_INVALID_ARGUMENT;
1826 goto cleanup;
1827 }
1828
1830
1831 // For traditional hash algorithms (non-XOFs), the hash length must exactly match the expected
1832 // value. For XOFs, the output length is arbitrary, and any length is acceptable as long as it
1833 // meets the minimum collision strength specified by the parameter set (cbCommitmentHash)
1834 if( (!fIsXof && cbHash != cbHashExpected ) ||
1835 ( cbHash < pParams->cbCommitmentHash ) )
1836 {
1837 scError = SYMCRYPT_INVALID_ARGUMENT;
1838 goto cleanup;
1839 }
1840
1841 *ppOid = pHashOid;
1842
1843cleanup:
1844 return scError;
1845}
1846
1848INT32
1851{
1853
1854 // In most cases this function is used with even moduli, e.g. with Power2Round.
1855 // However, it's okay if the modulus is odd. FIPS 204 specifies that the output is in the range
1856 // (-ceil(modulus/2), floor(modulus/2) ]
1857 // = ( -((modulus + 1) // 2), modulus // 2 ]
1858 // = [ -modulus // 2, modulus // 2 ]
1859 const INT32 halfModulus = modulus >> 1;
1860
1861 // Mask for conditional subtraction: 0 if r <= (modulus/2), 0xFFFFFFFF otherwise
1862 UINT32 subtractionMask = SYMCRYPT_MASK32_LT( halfModulus, r );
1863
1864 INT32 r0 = (INT32) r - (modulus & subtractionMask);
1865 SYMCRYPT_ASSERT( r0 > -halfModulus && r0 <= halfModulus);
1866
1867 return r0;
1868}
1869
1872UINT32
1875{
1876 UINT32 norm = 0;
1877 UINT32 mask;
1878 INT32 curr;
1880 {
1881 // Convert the coefficient to signed form
1883
1884 // If the coefficient is less than 0, negate it
1885 mask = SYMCRYPT_MASK32_LT( curr, 0 );
1886 curr = (curr & ~mask) | ((curr * -1) & mask);
1887
1888 // If the coefficient is greater than the current norm, update the norm
1889 mask = SYMCRYPT_MASK32_LT( norm, curr );
1890 norm = (norm & ~mask) | (curr & mask);
1891 }
1892
1893 return norm;
1894}
1895
1897UINT32
1900{
1901 UINT32 norm = 0;
1902 UINT32 curr;
1903 INT32 mask;
1904 for( UINT32 i = 0; i < pvSrc->nElems; i++ )
1905 {
1907 mask = SYMCRYPT_MASK32_LT( norm, curr );
1908 norm = (norm & ~mask) | (curr & mask);
1909 }
1910
1911 return norm;
1912}
1913
1916VOID
1920 UINT32 r,
1921 UINT32 *puR1,
1922 UINT32 *puR0 )
1923{
1925 SYMCRYPT_ASSERT( puR1 != NULL || puR0 != NULL );
1926
1927 UINT32 r1 = 0;
1928 UINT32 mask = 0;
1929 INT32 r0 = 0;
1930
1931 // Some tricks for calculating this are borrowed from the reference implementation
1932 // https://github.com/pq-crystals/dilithium/blob/master/ref/rounding.c
1933 //
1934 // The multiplication constants for calculating r1 are in the PCSYMCRYPT_MLDSA_INTERNAL_PARAMS
1935 // structure. They are calculated as follows.
1936 //
1937 // To keep intermediate values in the 32-bit range, instead of using r directly, we calculate
1938 // ceil( r/128 ). We likewise divide the commitment rounding range by 128.
1939 //
1940 // For ML-DSA 44:
1941 // 2*commmitmentRoundingRange = 2 * 95,232 = 190,464
1942 // 190464 // 128 = 1488
1943 // 1 / 1488 ~= floor(2^24 // 1488) * 2^24 = 11,275 // 2^24
1944 // For ML-DSA 65 and 87:
1945 // 2*commmitmentRoundingRange = 2*261888 = 523776
1946 // 523776 // 128 = 4092
1947 // 1 / 4092 ~= floor(2^22 // 4092) * 2^22 = 1025 // 2^22 = 4100 // 2^24
1948 //
1949
1950 UINT32 rdiv128 = (r + 127) >> 7;
1951 r1 = ( rdiv128 * pParams->decomposeR1Factor + (1 << 23)) >> 24;
1952
1953 // Handle corner case: if r1 is outside of the expected range, set it to 0
1955 r1 &= mask;
1956
1957 r0 = r - ( r1 * 2 * pParams->commitmentRoundingRange );
1958
1959 // Handle corner case for r0
1960 r0 -= ((((SYMCRYPT_MLDSA_Q - 1) >> 1) - r0) >> 31) & SYMCRYPT_MLDSA_Q;
1962
1963 if( puR1 != NULL )
1964 {
1965 *puR1 = r1;
1966 }
1967
1968 if( puR0 != NULL )
1969 {
1970 *puR0 = r0;
1971 }
1972}
1973
1975VOID
1981{
1982 SYMCRYPT_ASSERT( pvSrc->nElems == pvDst->nElems );
1983
1984 for(UINT32 i = 0; i < pvSrc->nElems; i++)
1985 {
1987 {
1989 pParams,
1992 NULL );
1993 }
1994 }
1995}
1996
1998VOID
2004{
2005 SYMCRYPT_ASSERT( pvSrc->nElems == pvDst->nElems );
2006
2007 for(UINT32 i = 0; i < pvSrc->nElems; i++)
2008 {
2010 {
2012 pParams,
2014 NULL,
2016 }
2017 }
2018}
2019
2021VOID
2024 UINT32 r,
2025 UINT32* puR1,
2026 UINT32* puR0 )
2027{
2029
2030 UINT32 rPrime = r & ( (1 << SYMCRYPT_POWER2ROUND_LOW_ORDER_BITS) - 1 ); // r mod 2^d
2032
2034
2035 *puR1 = r1;
2036 *puR0 = SymCryptMlDsaSignedCoefficientModQ( r0 ); //, 4096 );
2037}
2038
2040VOID
2046{
2047 UINT32 r1, r0;
2048
2050 {
2051 SymCryptMlDsaPower2Round( peSrc->coeffs[i], &r1, &r0 );
2052 peDst1->coeffs[i] = r1;
2053 peDst0->coeffs[i] = r0;
2054 }
2055}
2056
2058VOID
2063 PSYMCRYPT_MLDSA_VECTOR pvDst0 )
2064{
2065 SYMCRYPT_ASSERT( pvSrc->nElems == pvDst1->nElems );
2066 SYMCRYPT_ASSERT( pvSrc->nElems == pvDst0->nElems );
2067
2068 for(UINT32 i = 0; i < pvSrc->nElems; i++)
2069 {
2074 }
2075}
2076
2078UINT32
2081{
2083
2084 UINT32 result;
2085 UINT32 negativeMask = SYMCRYPT_MASK32_LT( coefficient, 0 );
2086
2087 result = coefficient + (SYMCRYPT_MLDSA_Q & negativeMask);
2089
2090 return result;
2091}
2092
2094VOID
2098 UINT32 nBitsPerCoefficient,
2099 UINT32 signedCoefficientBound,
2100 PBYTE pbDst )
2101{
2102 SYMCRYPT_ASSERT( nBitsPerCoefficient > 0 );
2103 SYMCRYPT_ASSERT( nBitsPerCoefficient <= 20 ); // Maximum number of bits per coefficient across all encodings
2104
2106 UINT32 nBitsInCoefficient;
2107 UINT32 bitsToEncode;
2108 UINT32 nBitsToEncode;
2109 UINT32 cbDstWritten = 0;
2110 UINT32 accumulator = 0;
2111 UINT32 nBitsInAccumulator = 0;
2112
2114 {
2115 nBitsInCoefficient = nBitsPerCoefficient;
2116 coefficient = peSrc->coeffs[i];
2117
2119
2120 // If the coefficient is greater than the signedCoefficientBound, that means it is
2121 // a negative value modulo Q, so we need to subtract Q to get the original value.
2122 coefficient -= ( SYMCRYPT_MLDSA_Q & SYMCRYPT_MASK32_LT( signedCoefficientBound, coefficient ) );
2123
2124 // The coefficient is now in the range [-signedCoefficientBound, signedCoefficientBound],
2125 // we need to map it to the range [0, 2*signedCoefficientBound] for encoding.
2127
2128 // Some coefficients are always positive and so do not need any special encoding. In this
2129 // case, we revert to the original value from the source polynomial.
2130 coefficient = ( peSrc->coeffs[i] & SYMCRYPT_MASK32_ZERO( signedCoefficientBound ) ) |
2131 ( coefficient & SYMCRYPT_MASK32_NONZERO( signedCoefficientBound ) );
2132
2134 SYMCRYPT_ASSERT( signedCoefficientBound == 0 || (UINT32) coefficient <= signedCoefficientBound * 2 );
2135 SYMCRYPT_ASSERT( (UINT32) coefficient < (1ul << nBitsPerCoefficient) );
2136
2137 // encode the coefficient
2138 // simple loop to add bits to accumulator and write accumulator to output
2139 do
2140 {
2141 nBitsToEncode = SYMCRYPT_MIN( nBitsInCoefficient, 32 - nBitsInAccumulator );
2142
2143 bitsToEncode = coefficient & ( ( 1UL << nBitsToEncode ) - 1 );
2144 coefficient >>= nBitsToEncode;
2145 nBitsInCoefficient -= nBitsToEncode;
2146
2147 accumulator |= ( bitsToEncode << nBitsInAccumulator );
2148 nBitsInAccumulator += nBitsToEncode;
2149 if(nBitsInAccumulator == 32)
2150 {
2151 SYMCRYPT_STORE_LSBFIRST32( pbDst + cbDstWritten, accumulator );
2152 cbDstWritten += 4;
2153 accumulator = 0;
2154 nBitsInAccumulator = 0;
2155 }
2156 } while( nBitsInCoefficient > 0 );
2157 }
2158
2159 SYMCRYPT_ASSERT(nBitsInAccumulator == 0);
2160 SYMCRYPT_ASSERT(cbDstWritten == (nBitsPerCoefficient*(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8)));
2161}
2162
2167 PCBYTE pbSrc,
2168 UINT32 nBitsPerCoefficient,
2169 UINT32 signedCoefficientBound,
2171{
2172 SYMCRYPT_ASSERT( nBitsPerCoefficient > 0 );
2173 SYMCRYPT_ASSERT( nBitsPerCoefficient <= 20 ); // Maximum number of bits per coefficient across all encodings
2174
2176 UINT32 nBitsInCoefficient;
2177 UINT32 bitsToDecode;
2178 UINT32 nBitsToDecode;
2179 UINT32 cbSrcRead = 0;
2180 UINT32 accumulator = 0;
2181 UINT32 nBitsInAccumulator = 0;
2182
2184 {
2185 coefficient = 0;
2186 nBitsInCoefficient = 0;
2187
2188 // first gather and decode bits from pbSrc
2189 do
2190 {
2191 if(nBitsInAccumulator == 0)
2192 {
2193 accumulator = SYMCRYPT_LOAD_LSBFIRST32( pbSrc+cbSrcRead );
2194 cbSrcRead += 4;
2195 nBitsInAccumulator = 32;
2196 }
2197
2198 nBitsToDecode = SYMCRYPT_MIN(nBitsPerCoefficient-nBitsInCoefficient, nBitsInAccumulator);
2199 SYMCRYPT_ASSERT(nBitsToDecode <= nBitsInAccumulator);
2200
2201 bitsToDecode = accumulator & ((1UL<<nBitsToDecode)-1);
2202 accumulator >>= nBitsToDecode;
2203 nBitsInAccumulator -= nBitsToDecode;
2204
2205 coefficient |= (bitsToDecode << nBitsInCoefficient);
2206 nBitsInCoefficient += nBitsToDecode;
2207 } while( nBitsPerCoefficient > nBitsInCoefficient );
2208 SYMCRYPT_ASSERT( nBitsInCoefficient == nBitsPerCoefficient );
2209
2210 // Coefficient should always be positive at this point since it's encoded in <= 20 bits
2212
2213 if( ( signedCoefficientBound != 0 ) && ( (UINT32) coefficient > 2 * signedCoefficientBound ) )
2214 {
2215 // Most of the encoded components of ML-DSA keys and signatures cannot be outside the
2216 // valid range, because the number of bits in their encodings do not permit invalid
2217 // values. However, the private key components s1 and s2 have encodings that do allow
2218 // for invalid values (because their valid ranges are [-2, 2] or [-4, 4]). If any
2219 // coefficient is outside this range, the key is invalid and we return an error.
2220 // We do not need to do this check in constant time because we treat the validity of an
2221 // imported key as public information.
2222 return SYMCRYPT_INVALID_BLOB;
2223 }
2224
2225 // If this coefficient is intended to be signed, we need to decode it into its original
2226 // signed form and then map it modulo Q.
2227 // Side-channel safety: signedCoefficientBound just indicates which component we are
2228 // decoding, so it's public information
2229 if( signedCoefficientBound != 0 )
2230 {
2233 }
2234
2235 peDst->coeffs[i] = coefficient;
2236 }
2237
2238 SYMCRYPT_ASSERT(nBitsInAccumulator == 0);
2239 SYMCRYPT_ASSERT(cbSrcRead == (nBitsPerCoefficient*(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8)));
2240
2241 return SYMCRYPT_NO_ERROR;
2242}
2243
2245VOID
2249 UINT32 nBitsPerCoefficient,
2250 UINT32 signedCoefficientBound,
2251 PBYTE pbDst )
2252{
2253 PBYTE pbCurr = pbDst;
2254 const SIZE_T cbEncodedPoly = nBitsPerCoefficient * ( SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8 );
2255
2256 for( UINT32 i = 0; i < pvSrc->nElems; ++i )
2257 {
2259
2261 peElement,
2262 nBitsPerCoefficient,
2263 signedCoefficientBound,
2264 pbCurr );
2265
2266 pbCurr += cbEncodedPoly;
2267 }
2268
2269 SYMCRYPT_ASSERT( pbCurr == pbDst + ( pvSrc->nElems * cbEncodedPoly ) );
2270}
2271
2275 _In_reads_bytes_( pvDst->nElems * nBitsPerCoefficient * (SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8) )
2276 PCBYTE pbSrc,
2277 UINT32 nBitsPerCoefficient,
2278 UINT32 signedCoefficientBound,
2280{
2281 SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR;
2282 PCBYTE pbCurr = pbSrc;
2283 const SIZE_T cbEncodedPoly = nBitsPerCoefficient * ( SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS / 8 );
2284
2285 for( UINT32 i = 0; i < pvDst->nElems; ++i )
2286 {
2288
2290 pbCurr,
2291 nBitsPerCoefficient,
2292 signedCoefficientBound,
2293 peElement );
2294 if( scError != SYMCRYPT_NO_ERROR )
2295 {
2296 // Side-channel safety: the validity of an imported key is public information.
2297 // See comment in SymCryptMlDsaPolyElementDecode.
2298 goto cleanup;
2299 }
2300
2301 pbCurr += cbEncodedPoly;
2302 }
2303
2304 SYMCRYPT_ASSERT( pbCurr == pbSrc + ( pvDst->nElems * cbEncodedPoly ) );
2305
2306cleanup:
2307 return scError;
2308}
2309
2319{
2320 // Round scratch space to nearest multiple of 8 for alignment
2321 cbScratch = (cbScratch + 7) & ~7;
2322
2324 ( nRowVectors * sizeof( PSYMCRYPT_MLDSA_VECTOR ) ) + // Row vector pointers
2325 ( nColVectors * sizeof( PSYMCRYPT_MLDSA_VECTOR ) ) + // Col vector pointers
2326 ( nPolyElements * sizeof( PSYMCRYPT_MLDSA_POLYELEMENT ) ) + // Poly element pointers
2327 ( nRowVectors * pParams->cbRowVector ) + // Row vector buffer
2328 ( nColVectors * pParams->cbColVector ) + // Col vector buffer
2329 ( nPolyElements * pParams->cbPolyElement ) + // Poly element buffer
2330 ( cbScratch ); // Scratch buffer
2331
2333 if( pbBuffer == NULL )
2334 {
2335 return NULL;
2336 }
2337
2338 SymCryptWipe( pbBuffer, cbTotalSize );
2339
2342
2343 pTemporaries->cbTotalSize = cbTotalSize;
2344 pTemporaries->nRowVectors = nRowVectors;
2345 pTemporaries->nColVectors = nColVectors;
2346 pTemporaries->nPolyElements = nPolyElements;
2347 pTemporaries->cbScratch = cbScratch;
2348
2349 PBYTE pbCurrent = pbBuffer + sizeof( SYMCRYPT_MLDSA_INTERNAL_COMPUTATION_TEMPORARIES );
2350
2351 if( nRowVectors > 0 )
2352 {
2353 pTemporaries->pvRowVectors = (PSYMCRYPT_MLDSA_VECTOR *) pbCurrent;
2354 pbCurrent += nRowVectors * sizeof( PSYMCRYPT_MLDSA_VECTOR );
2355 }
2356
2357 if( nColVectors > 0 )
2358 {
2359 pTemporaries->pvColVectors = (PSYMCRYPT_MLDSA_VECTOR *) pbCurrent;
2360 pbCurrent += nColVectors * sizeof( PSYMCRYPT_MLDSA_VECTOR );
2361 }
2362
2363 if( nPolyElements > 0 )
2364 {
2365 pTemporaries->pePolyElements = (PSYMCRYPT_MLDSA_POLYELEMENT *) pbCurrent;
2366 pbCurrent += nPolyElements * sizeof( PSYMCRYPT_MLDSA_POLYELEMENT );
2367 }
2368
2369 for(UINT32 i = 0; i < nRowVectors; i++)
2370 {
2371 pTemporaries->pvRowVectors[i] = SymCryptMlDsaVectorCreate( pbCurrent, pParams->cbRowVector, pParams->nRows );
2372 pbCurrent += pParams->cbRowVector;
2373 }
2374
2375 for(UINT32 i = 0; i < nColVectors; i++)
2376 {
2377 pTemporaries->pvColVectors[i] = SymCryptMlDsaVectorCreate( pbCurrent, pParams->cbColVector, pParams->nCols );
2378 pbCurrent += pParams->cbColVector;
2379 }
2380
2381 for(UINT32 i = 0; i < nPolyElements; i++)
2382 {
2383 pTemporaries->pePolyElements[i] = SymCryptMlDsaPolyElementCreate( pbCurrent, pParams->cbPolyElement );
2384 pbCurrent += pParams->cbPolyElement;
2385 }
2386
2387 if( cbScratch > 0 )
2388 {
2389 pTemporaries->pbScratch = pbCurrent;
2390 pbCurrent += cbScratch;
2391 }
2392
2393 SYMCRYPT_ASSERT( pbCurrent == pbBuffer + cbTotalSize );
2394
2395 SYMCRYPT_SET_MAGIC( pTemporaries );
2396
2397 return pTemporaries;
2398}
2399
2401VOID
2405{
2406 SYMCRYPT_CHECK_MAGIC( pTemporaries );
2407
2408 SymCryptWipe( pTemporaries, pTemporaries->cbTotalSize );
2409 SymCryptCallbackFree( pTemporaries );
2410}
_Tp _STLP_CALL norm(const complex< _Tp > &__z)
Definition: _complex.h:741
unsigned short UINT16
Definition: actypes.h:129
unsigned char BOOLEAN
Definition: actypes.h:127
unsigned char UINT8
Definition: actypes.h:128
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
int nCols
Definition: appswitch.c:55
#define index(s, c)
Definition: various.h:29
signed char INT8
Definition: basetsd.h:183
BYTE coefficient[512/16]
Definition: bcrypt.c:2463
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static void cleanup(void)
Definition: main.c:1335
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
#define INT8_MIN
Definition: stdint.h:73
static const uint32_t k[]
Definition: sha256.c:24
GLuint start
Definition: gl.h:1545
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble t
Definition: gl.h:2047
GLuint res
Definition: glext.h:9613
GLenum GLenum const GLfloat * coeffs
Definition: glext.h:11733
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLbitfield flags
Definition: glext.h:7161
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
const GLint * first
Definition: glext.h:5794
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLenum const GLfloat * params
Definition: glext.h:5645
const GLfloat * m
Definition: glext.h:10848
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
void SYMCRYPT_CALL SymCryptCallbackFree(void *ptr)
Definition: implglue.c:42
void *SYMCRYPT_CALL SymCryptCallbackAlloc(SIZE_T size)
Definition: implglue.c:37
#define C_ASSERT(e)
Definition: intsafe.h:73
#define b
Definition: ke_i.h:79
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementEncode(PCSYMCRYPT_MLDSA_POLYELEMENT peSrc, UINT32 nBitsPerCoefficient, UINT32 signedCoefficientBound, PBYTE pbDst)
UINT32 SYMCRYPT_CALL SymCryptMlDsaModSub(UINT32 a, UINT32 b)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaSkEncode(PCSYMCRYPT_MLDSAKEY pkMlDsakey, PBYTE pbDst, SIZE_T cbDst)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaGetInternalParamsFromParams(SYMCRYPT_MLDSA_PARAMS params, PCSYMCRYPT_MLDSA_INTERNAL_PARAMS *pInternalParams)
struct _SYMCRYPT_HASH_OID_MAPPING * PSYMCRYPT_HASH_OID_MAPPING
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorSetZero(PSYMCRYPT_MLDSA_VECTOR pvDst)
_Use_decl_annotations_ FORCEINLINE VOID SYMCRYPT_CALL SymCryptMlDsaDecompose(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, UINT32 r, UINT32 *puR1, UINT32 *puR0)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorEncode(PCSYMCRYPT_MLDSA_VECTOR pvSrc, UINT32 nBitsPerCoefficient, UINT32 signedCoefficientBound, PBYTE pbDst)
#define SYMCRYPT_MLDSA_Q_INV
#define SYMCRYPT_POWER2ROUND_LOW_ORDER_BITS
#define SYMCRYPT_MLDSA_REJNTTPOLY_SEED_SIZE
FORCEINLINE UINT32 SYMCRYPT_CALL SymCryptMlDsaSignedCoefficientModQ(INT32 coefficient)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaMatrixVectorMontMul(PCSYMCRYPT_MLDSA_MATRIX pmSrc1, PCSYMCRYPT_MLDSA_VECTOR pvSrc2, PSYMCRYPT_MLDSA_VECTOR pvDst, PSYMCRYPT_MLDSA_POLYELEMENT peTmp)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaExpandS(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCBYTE pbPrivateVectorSeed, SIZE_T cbPrivateVectorSeed, PSYMCRYPT_MLDSA_VECTOR pvs1, PSYMCRYPT_MLDSA_VECTOR pvs2)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementSub(PCSYMCRYPT_MLDSA_POLYELEMENT peSrc1, PCSYMCRYPT_MLDSA_POLYELEMENT peSrc2, PSYMCRYPT_MLDSA_POLYELEMENT peDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementINTT(PSYMCRYPT_MLDSA_POLYELEMENT peSrc)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaSizeofKeyFormatFromParams(SYMCRYPT_MLDSA_PARAMS params, SYMCRYPT_MLDSAKEY_FORMAT mlDsakeyFormat, SIZE_T *pcbKeyFormat)
SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaVectorDecode(_In_reads_bytes_(pvDst->nElems *nBitsPerCoefficient *(SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS/8)) PCBYTE pbSrc, UINT32 nBitsPerCoefficient, UINT32 signedCoefficientBound, _Inout_ PSYMCRYPT_MLDSA_VECTOR pvDst)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaHintBitUnpack(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCBYTE pbSrc, PSYMCRYPT_MLDSA_VECTOR pvDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorAdd(PCSYMCRYPT_MLDSA_VECTOR pvSrc1, PCSYMCRYPT_MLDSA_VECTOR pvSrc2, PSYMCRYPT_MLDSA_VECTOR pvDst)
#define SYMCRYPT_MLDSA_RSQR
_Use_decl_annotations_ PSYMCRYPT_MLDSA_MATRIX SYMCRYPT_CALL SymCryptMlDsaMatrixCreate(PBYTE pbBuffer, UINT32 cbBuffer, UINT8 nRows, UINT8 nCols)
UINT32 SYMCRYPT_CALL SymCryptMlDsaModAdd(UINT32 a, UINT32 b)
const UINT32 MLDSA_NEGATIVE_ZETA_BITREV_TIMES_R[SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS]
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaSkDecode(PCBYTE pbSrc, SIZE_T cbSrc, UINT32 flags, PSYMCRYPT_MLDSAKEY pkMlDsakey)
const UINT32 MLDSA_ZETA_BITREV_TIMES_R[SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS]
UINT32 SYMCRYPT_CALL SymCryptMlDsaMontMul(UINT32 a, UINT32 b)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorPower2Round(PCSYMCRYPT_MLDSA_VECTOR pvSrc, PSYMCRYPT_MLDSA_VECTOR pvDst1, PSYMCRYPT_MLDSA_VECTOR pvDst0)
#define SYMCRYPT_MLDSA_REJBOUNDEDPOLY_SEED_SIZE
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPower2Round(UINT32 r, UINT32 *puR1, UINT32 *puR0)
_Use_decl_annotations_ PSYMCRYPT_MLDSA_INTERNAL_COMPUTATION_TEMPORARIES SYMCRYPT_CALL SymCryptMlDsaTemporariesAllocateAndInitialize(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, UINT32 nRowVectors, UINT32 nColVectors, UINT32 nPolyElements, UINT32 cbScratch)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaRejNttPoly(PCBYTE pbRejNttPolySeed, SIZE_T cbRejNttPolySeed, PSYMCRYPT_MLDSA_POLYELEMENT peDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorPolyElementMontMul(PCSYMCRYPT_MLDSA_VECTOR pvSrc1, PCSYMCRYPT_MLDSA_POLYELEMENT peSrc2, PSYMCRYPT_MLDSA_VECTOR pvDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaExpandMask(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PSYMCRYPT_SHAKE256_STATE pShakeState, PCBYTE pbPrivateRandom, SIZE_T cbPrivateRandom, UINT16 counter, PSYMCRYPT_MLDSA_VECTOR pvMask)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaPkDecode(PCBYTE pbSrc, SIZE_T cbSrc, UINT32 flags, PSYMCRYPT_MLDSAKEY pkMlDsakey)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaTemporariesFree(PSYMCRYPT_MLDSA_INTERNAL_COMPUTATION_TEMPORARIES pTemporaries)
const SYMCRYPT_HASH_OID_MAPPING g_hashOidMap[]
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementPower2Round(PCSYMCRYPT_MLDSA_POLYELEMENT peSrc, PSYMCRYPT_MLDSA_POLYELEMENT peDst1, PSYMCRYPT_MLDSA_POLYELEMENT peDst0)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsakeyComputeT(PCSYMCRYPT_MLDSA_MATRIX pmA, PCSYMCRYPT_MLDSA_VECTOR pvs1, PCSYMCRYPT_MLDSA_VECTOR pvs2, PSYMCRYPT_MLDSA_VECTOR pvt0, PSYMCRYPT_MLDSA_VECTOR pvt1, PSYMCRYPT_MLDSA_VECTOR pvTmp, PSYMCRYPT_MLDSA_POLYELEMENT peTmp)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementSetZero(PSYMCRYPT_MLDSA_POLYELEMENT peDst)
const SYMCRYPT_MLDSA_INTERNAL_PARAMS SymCryptMlDsaInternalParams65
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaHintBitPack(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCSYMCRYPT_MLDSA_VECTOR pvSrc, PBYTE pbDst)
_Use_decl_annotations_ FORCEINLINE INT8 SYMCRYPT_CALL SymCryptMlDsaCoeffFromHalfByte(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, UINT8 halfByte)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaPolyElementDecode(PCBYTE pbSrc, UINT32 nBitsPerCoefficient, UINT32 signedCoefficientBound, PSYMCRYPT_MLDSA_POLYELEMENT peDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorCopy(PCSYMCRYPT_MLDSA_VECTOR pvSrc, PSYMCRYPT_MLDSA_VECTOR pvDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementAdd(PCSYMCRYPT_MLDSA_POLYELEMENT peSrc1, PCSYMCRYPT_MLDSA_POLYELEMENT peSrc2, PSYMCRYPT_MLDSA_POLYELEMENT peDst)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaSigDecode(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCBYTE pbSig, SIZE_T cbSig, PBYTE pbCommitmentHash, SIZE_T cbCommitmentHash, PSYMCRYPT_MLDSA_VECTOR pvResponse, PSYMCRYPT_MLDSA_VECTOR pvHint)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaUseHint(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCSYMCRYPT_MLDSA_VECTOR pvHint, PSYMCRYPT_MLDSA_VECTOR pvCommitment)
_Use_decl_annotations_ UINT32 SYMCRYPT_CALL SymCryptMlDsaVectorInfinityNorm(PCSYMCRYPT_MLDSA_VECTOR pvSrc)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementMulR(PSYMCRYPT_MLDSA_POLYELEMENT peSrc)
struct _SYMCRYPT_HASH_OID_MAPPING SYMCRYPT_HASH_OID_MAPPING
_Use_decl_annotations_ PSYMCRYPT_MLDSA_POLYELEMENT SYMCRYPT_CALL SymCryptMlDsaPolyElementCreate(PBYTE pbBuffer, SIZE_T cbBuffer)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementMontMul(PCSYMCRYPT_MLDSA_POLYELEMENT peSrc1, PCSYMCRYPT_MLDSA_POLYELEMENT peSrc2, PSYMCRYPT_MLDSA_POLYELEMENT peDst)
FORCEINLINE INT32 SYMCRYPT_CALL SymCryptMlDsaModPlusMinus(UINT32 r, UINT32 modulus)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaSigEncode(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PBYTE pbCommitmentHash, SIZE_T cbCommitmentHash, PCSYMCRYPT_MLDSA_VECTOR pvResponse, PCSYMCRYPT_MLDSA_VECTOR pvHint, PBYTE pbDst, SIZE_T cbDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorSub(PCSYMCRYPT_MLDSA_VECTOR pvSrc1, PCSYMCRYPT_MLDSA_VECTOR pvSrc2, PSYMCRYPT_MLDSA_VECTOR pvDst)
_Use_decl_annotations_ FORCEINLINE UINT32 SYMCRYPT_CALL SymCryptMlDsaPolyElementInfinityNorm(PCSYMCRYPT_MLDSA_POLYELEMENT peSrc)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaSampleInBall(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCBYTE pbCommitmentHash, SIZE_T cbCommitmentHash, PSYMCRYPT_MLDSA_POLYELEMENT peChallenge)
_Use_decl_annotations_ PSYMCRYPT_MLDSAKEY SYMCRYPT_CALL SymCryptMlDsakeyInitialize(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pInternalParams, PBYTE pbKey, UINT32 cbKey)
_Use_decl_annotations_ PSYMCRYPT_MLDSA_VECTOR SYMCRYPT_CALL SymCryptMlDsaVectorCreate(PBYTE pbBuffer, UINT32 cbBuffer, UINT8 nElems)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaRejBoundedPoly(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCBYTE pbRejBoundedPolySeed, SIZE_T cbRejBoundedPolySeed, PSYMCRYPT_MLDSA_POLYELEMENT peDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaExpandA(PCBYTE pbPublicSeed, SIZE_T cbPublicSeed, PSYMCRYPT_MLDSA_MATRIX pmA)
VOID SYMCRYPT_CALL SymCryptMlDsaVectorINTT(_Inout_ PSYMCRYPT_MLDSA_VECTOR pvSrc)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaSizeofSignatureFromParams(SYMCRYPT_MLDSA_PARAMS params, SIZE_T *pcbSignature)
const SYMCRYPT_MLDSA_INTERNAL_PARAMS SymCryptMlDsaInternalParams44
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorHighBits(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCSYMCRYPT_MLDSA_VECTOR pvSrc, PSYMCRYPT_MLDSA_VECTOR pvDst)
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptMlDsaPkEncode(PCSYMCRYPT_MLDSAKEY pkMlDsakey, PBYTE pbDst, SIZE_T cbDst)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorNTT(PSYMCRYPT_MLDSA_VECTOR pvSrc)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaMakeHint(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PSYMCRYPT_MLDSA_VECTOR pvWMinusCs2, PSYMCRYPT_MLDSA_VECTOR pvWMinusCs2PlusCt0, PSYMCRYPT_MLDSA_VECTOR pvDst, UINT32 *nBitsSet)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaPolyElementNTT(PSYMCRYPT_MLDSA_POLYELEMENT peSrc)
UINT32 SYMCRYPT_CALL SymCryptMlDsaMontReduce(UINT64 a)
_Use_decl_annotations_ VOID SYMCRYPT_CALL SymCryptMlDsaVectorLowBits(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, PCSYMCRYPT_MLDSA_VECTOR pvSrc, PSYMCRYPT_MLDSA_VECTOR pvDst)
#define SYMCRYPT_MLDSA_INTT_FIXUP_TIMES_R
const SYMCRYPT_MLDSA_INTERNAL_PARAMS SymCryptMlDsaInternalParams87
_Use_decl_annotations_ SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptHashMlDsaValidateHashAlgAndGetOid(PCSYMCRYPT_MLDSA_INTERNAL_PARAMS pParams, SYMCRYPT_PQDSA_HASH_ID hashAlg, SIZE_T cbHash, PCSYMCRYPT_OID *ppOid)
static DNS_RECORDW r1
Definition: record.c:37
static double float double int float z1
Definition: server.c:81
static double float z0
Definition: server.c:81
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Inout_
Definition: no_sal2.h:162
#define _Use_decl_annotations_
Definition: no_sal2.h:92
#define _Analysis_assume_
Definition: no_sal2.h:388
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
BYTE * PBYTE
Definition: pedump.c:66
static calc_node_t temp
Definition: rpn_ieee.c:38
const SYMCRYPT_HASH SymCryptSha3_384Algorithm_default
Definition: sha3_384.c:14
#define SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS
Definition: sc_lib.h:4347
const SYMCRYPT_HASH SymCryptSha512_256Algorithm_default
Definition: sha512.c:156
const SYMCRYPT_HASH SymCryptSha256Algorithm_default
Definition: sha256.c:32
const SYMCRYPT_HASH SymCryptSha512Algorithm_default
Definition: sha512.c:130
const SYMCRYPT_HASH SymCryptSha3_512Algorithm_default
Definition: sha3_512.c:14
const SYMCRYPT_HASH SymCryptShake128HashAlgorithm_default
Definition: shake.c:28
const SYMCRYPT_HASH SymCryptSha3_256Algorithm_default
Definition: sha3_256.c:14
const SYMCRYPT_HASH SymCryptSha384Algorithm_default
Definition: sha512.c:117
const SYMCRYPT_HASH SymCryptShake256HashAlgorithm_default
Definition: shake.c:80
#define SYMCRYPT_ARRAY_SIZE(_x)
Definition: sc_lib.h:342
#define SYMCRYPT_MLDSA_Q
Definition: sc_lib_mldsa.h:13
UINT32 nRowVectors
SYMCRYPT_MLDSA_VECTOR
Definition: sc_lib_mldsa.h:80
#define SYMCRYPT_MLDSA_PRIVATE_VECTOR_SEED_SIZE
Definition: sc_lib_mldsa.h:43
#define SYMCRYPT_MLDSA_PUBLIC_KEY_HASH_SIZE
Definition: sc_lib_mldsa.h:33
#define SYMCRYPT_MLDSA_PUBLIC_SEED_SIZE
Definition: sc_lib_mldsa.h:28
SYMCRYPT_MLDSA_INTERNAL_COMPUTATION_TEMPORARIES
Definition: sc_lib_mldsa.h:206
#define SYMCRYPT_MLDSA_MATRIX_MAX_NCOLS
Definition: sc_lib_mldsa.h:71
const SYMCRYPT_MLDSA_MATRIX * PCSYMCRYPT_MLDSA_MATRIX
Definition: sc_lib_mldsa.h:93
UINT32 UINT32 UINT32 nPolyElements
#define SYMCRYPT_INTERNAL_MLDSA_SIZEOF_VECTOR(_nElems)
Definition: sc_lib_mldsa.h:209
SYMCRYPT_MLDSA_MATRIX
Definition: sc_lib_mldsa.h:92
struct _SYMCRYPT_MLDSA_POLYELEMENT * PSYMCRYPT_MLDSA_POLYELEMENT
const SYMCRYPT_MLDSA_VECTOR * PCSYMCRYPT_MLDSA_VECTOR
Definition: sc_lib_mldsa.h:81
#define SYMCRYPT_MLDSA_ROOT_SEED_SIZE
Definition: sc_lib_mldsa.h:23
#define SYMCRYPT_INTERNAL_MLDSA_SIZEOF_ENCODED_VECTOR(_pVector, _nBitsPerCoeff)
Definition: sc_lib_mldsa.h:221
#define SYMCRYPT_INTERNAL_MLDSA_MATRIX_ELEMENT(_row, _col, _pMatrix)
Definition: sc_lib_mldsa.h:219
#define SYMCRYPT_INTERNAL_MLDSA_SIZEOF_MATRIX(_nRows, _nCols)
Definition: sc_lib_mldsa.h:210
UINT32 UINT32 nColVectors
#define SYMCRYPT_MLDSA_VECTOR_MAX_LENGTH
Definition: sc_lib_mldsa.h:69
UINT32 UINT32 UINT32 UINT32 cbScratch
SIZE_T cbBuffer
Definition: sc_lib_mldsa.h:405
#define SYMCRYPT_INTERNAL_MLDSA_SHORT_COEFFICIENT_ENCODE_DECODE(_val, _bound)
Definition: sc_lib_mldsa.h:228
#define SYMCRYPT_INTERNAL_MLDSA_SIZEOF_KEY(_nRows, _nCols)
Definition: sc_lib_mldsa.h:211
UINT32 UINT8 nElems
Definition: sc_lib_mldsa.h:495
* PSYMCRYPT_MLDSA_VECTOR
Definition: sc_lib_mldsa.h:80
#define SYMCRYPT_INTERNAL_MLDSA_VECTOR_ELEMENT(_row, _pVector)
Definition: sc_lib_mldsa.h:217
* PSYMCRYPT_MLDSA_INTERNAL_COMPUTATION_TEMPORARIES
Definition: sc_lib_mldsa.h:206
#define SYMCRYPT_MLDSA_SUPPORTED_HASH_OID_SIZE
Definition: sc_lib_mldsa.h:55
#define SYMCRYPT_MLDSA_PRIVATE_SIGNING_SEED_SIZE
Definition: sc_lib_mldsa.h:38
#define SYMCRYPT_INTERNAL_MLDSA_SIZEOF_POLYELEMENT
Definition: sc_lib_mldsa.h:208
* PSYMCRYPT_MLDSA_MATRIX
Definition: sc_lib_mldsa.h:92
#define SYMCRYPT_MLDSA_R_LOG2
Definition: sc_lib_mldsa.h:18
#define SYMCRYPT_MLDSA_MATRIX_MAX_NROWS
Definition: sc_lib_mldsa.h:70
UINT8 nRows
Definition: sc_lib_mlkem.h:69
UINT32 cbMatrix
Definition: sc_lib_mlkem.h:67
const PCSYMCRYPT_HASH pHashAlgorithm
SYMCRYPT_PQDSA_HASH_ID hashId
UINT32 coeffs[SYMCRYPT_MLWE_POLYNOMIAL_COEFFICIENTS]
Definition: sc_lib_mldsa.h:64
#define SYMCRYPT_ASSERT(_x)
Definition: symcrypt.h:10807
VOID SYMCRYPT_CALL SymCryptShake256(_In_reads_(cbData) PCBYTE pbData, SIZE_T cbData, _Out_writes_(cbResult) PBYTE pbResult, SIZE_T cbResult)
@ SYMCRYPT_MLDSA_PARAMS_MLDSA44
Definition: symcrypt.h:10417
@ SYMCRYPT_MLDSA_PARAMS_MLDSA65
Definition: symcrypt.h:10418
@ SYMCRYPT_MLDSA_PARAMS_NULL
Definition: symcrypt.h:10416
@ SYMCRYPT_MLDSA_PARAMS_MLDSA87
Definition: symcrypt.h:10419
#define SYMCRYPT_SHAKE256_RESULT_SIZE
Definition: symcrypt.h:1964
VOID SYMCRYPT_CALL SymCryptShake128Append(_Inout_ PSYMCRYPT_SHAKE128_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
@ SYMCRYPT_MLDSAKEY_FORMAT_PRIVATE_KEY
Definition: symcrypt.h:10407
@ SYMCRYPT_MLDSAKEY_FORMAT_PRIVATE_SEED
Definition: symcrypt.h:10403
@ SYMCRYPT_MLDSAKEY_FORMAT_PUBLIC_KEY
Definition: symcrypt.h:10410
FORCEINLINE VOID SYMCRYPT_CALL SymCryptWipeKnownSize(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
#define SYMCRYPT_MLDSA_SIGNATURE_SIZE_MLDSA44
Definition: symcrypt.h:10457
VOID SYMCRYPT_CALL SymCryptShake128Init(_Out_ PSYMCRYPT_SHAKE128_STATE pState)
#define SYMCRYPT_STORE_LSBFIRST16(p, v)
Definition: symcrypt.h:306
VOID SYMCRYPT_CALL SymCryptWipe(_Out_writes_bytes_(cbData) PVOID pbData, SIZE_T cbData)
Definition: libmain.c:137
enum _SYMCRYPT_PQDSA_HASH_ID SYMCRYPT_PQDSA_HASH_ID
#define SYMCRYPT_LOAD_LSBFIRST64(p)
Definition: symcrypt.h:300
VOID SYMCRYPT_CALL SymCryptShake256Result(_Inout_ PSYMCRYPT_SHAKE256_STATE pState, _Out_writes_(SYMCRYPT_SHAKE256_RESULT_SIZE) PBYTE pbResult)
@ SYMCRYPT_PQDSA_HASH_ID_SHA512
Definition: symcrypt.h:10427
@ SYMCRYPT_PQDSA_HASH_ID_SHA256
Definition: symcrypt.h:10425
@ SYMCRYPT_PQDSA_HASH_ID_SHA3_512
Definition: symcrypt.h:10431
@ SYMCRYPT_PQDSA_HASH_ID_SHAKE256
Definition: symcrypt.h:10433
@ SYMCRYPT_PQDSA_HASH_ID_SHA3_384
Definition: symcrypt.h:10430
@ SYMCRYPT_PQDSA_HASH_ID_SHA384
Definition: symcrypt.h:10426
@ SYMCRYPT_PQDSA_HASH_ID_SHA512_256
Definition: symcrypt.h:10428
@ SYMCRYPT_PQDSA_HASH_ID_SHA3_256
Definition: symcrypt.h:10429
@ SYMCRYPT_PQDSA_HASH_ID_SHAKE128
Definition: symcrypt.h:10432
VOID SYMCRYPT_CALL SymCryptShake256Append(_Inout_ PSYMCRYPT_SHAKE256_STATE pState, _In_reads_(cbData) PCBYTE pbData, SIZE_T cbData)
#define SYMCRYPT_MLDSA_SIGNATURE_SIZE_MLDSA65
Definition: symcrypt.h:10458
VOID SYMCRYPT_CALL SymCryptShake256Extract(_Inout_ PSYMCRYPT_SHAKE256_STATE pState, _Out_writes_(cbResult) PBYTE pbResult, SIZE_T cbResult, BOOLEAN bWipe)
#define SYMCRYPT_LOAD_LSBFIRST32(p)
Definition: symcrypt.h:299
VOID SYMCRYPT_CALL SymCryptShake256Init(_Out_ PSYMCRYPT_SHAKE256_STATE pState)
VOID SYMCRYPT_CALL SymCryptShake128Extract(_Inout_ PSYMCRYPT_SHAKE128_STATE pState, _Out_writes_(cbResult) PBYTE pbResult, SIZE_T cbResult, BOOLEAN bWipe)
#define SYMCRYPT_MLDSA_SIGNATURE_SIZE_MLDSA87
Definition: symcrypt.h:10459
#define SYMCRYPT_STORE_LSBFIRST32(p, v)
Definition: symcrypt.h:307
enum _SYMCRYPT_MLDSA_PARAMS SYMCRYPT_MLDSA_PARAMS
enum _SYMCRYPT_MLDSAKEY_FORMAT SYMCRYPT_MLDSAKEY_FORMAT
SYMCRYPT_ERROR
Definition: symcrypt.h:227
#define SYMCRYPT_MASK32_NONZERO(_v)
PCBYTE pbSrc
UINT32 cbTotalSize
#define SYMCRYPT_CALL
#define SYMCRYPT_SHA512_256_OID_COUNT
const SYMCRYPT_MLDSAKEY * PCSYMCRYPT_MLDSAKEY
PCBYTE pbKey
#define SYMCRYPT_MASK32_EQ(_a, _b)
#define SYMCRYPT_SHA3_256_OID_COUNT
const SYMCRYPT_OID SymCryptSha3_384OidList[SYMCRYPT_SHA3_384_OID_COUNT]
Definition: rsa_padding.c:79
const SYMCRYPT_OID SymCryptShake256OidList[SYMCRYPT_SHAKE256_OID_COUNT]
Definition: rsa_padding.c:97
#define SYMCRYPT_SHAKE256_OID_COUNT
SYMCRYPT_MAGIC_FIELD SYMCRYPT_SHAKE256_STATE
const SYMCRYPT_OID SymCryptSha384OidList[SYMCRYPT_SHA384_OID_COUNT]
Definition: rsa_padding.c:43
struct _SYMCRYPT_MLDSAKEY SYMCRYPT_MLDSAKEY
#define SYMCRYPT_SHA384_OID_COUNT
PCBYTE SIZE_T cbKey
const SYMCRYPT_OID SymCryptSha512OidList[SYMCRYPT_SHA512_OID_COUNT]
Definition: rsa_padding.c:49
const SYMCRYPT_HASH * PCSYMCRYPT_HASH
#define SYMCRYPT_MIN(_a, _b)
#define SYMCRYPT_SHA3_384_OID_COUNT
const SYMCRYPT_OID SymCryptSha3_256OidList[SYMCRYPT_SHA3_256_OID_COUNT]
Definition: rsa_padding.c:73
#define SYMCRYPT_SET_MAGIC(p)
const SYMCRYPT_OID SymCryptSha512_256OidList[SYMCRYPT_SHA512_256_OID_COUNT]
Definition: rsa_padding.c:61
PCBYTE PBYTE pbDst
#define SYMCRYPT_SHA512_OID_COUNT
#define SYMCRYPT_SHA3_512_OID_COUNT
SYMCRYPT_MAGIC_FIELD SYMCRYPT_SHAKE128_STATE
const BYTE * PCBYTE
SYMCRYPT_MLDSAKEY * PSYMCRYPT_MLDSAKEY
const SYMCRYPT_OID SymCryptSha256OidList[SYMCRYPT_SHA256_OID_COUNT]
Definition: rsa_padding.c:37
#define SYMCRYPT_MASK32_ZERO(_v)
#define SYMCRYPT_MASK32_LT(_a, _b)
#define SYMCRYPT_CHECK_MAGIC(p)
const SYMCRYPT_OID SymCryptShake128OidList[SYMCRYPT_SHAKE128_OID_COUNT]
Definition: rsa_padding.c:91
#define SYMCRYPT_SHAKE128_OID_COUNT
SYMCRYPT_MAGIC_FIELD * PSYMCRYPT_SHAKE256_STATE
#define SYMCRYPT_SHA256_OID_COUNT
const SYMCRYPT_OID SymCryptSha3_512OidList[SYMCRYPT_SHA3_512_OID_COUNT]
Definition: rsa_padding.c:85
int32_t INT32
Definition: typedefs.h:58
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