/src/SymCrypt/lib/fdef369_mod.c
Line | Count | Source |
1 | | // |
2 | | // fdef_int.c INT functions for default number format |
3 | | // |
4 | | // Copyright (c) Microsoft Corporation. Licensed under the MIT license. |
5 | | // |
6 | | |
7 | | #include "precomp.h" |
8 | | |
9 | | #if (SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_ARM64) |
10 | | |
11 | | #if !(SYMCRYPT_CPU_AMD64 | SYMCRYPT_CPU_ARM64) |
12 | | #error code in this file is specific to normal digits being 4 64-bit words, and here 3 64-bit words |
13 | | #endif |
14 | | |
15 | | // |
16 | | // Some of the functions in this file need to know how large the values are in # UINT32s |
17 | | // On ARM64, normal digits are 256 bits and 369 digits are 192 bits, so the answer is 6 * # digits |
18 | | // On AMD64, normal digits are 512 bits, and this code is only used for 384 and 576 bits. |
19 | | // So if nDigits = 1 then nUint32 = 12, and if nDigits=2 then nUint32 = 18. |
20 | | // |
21 | | #if SYMCRYPT_CPU_AMD64 |
22 | 3.20k | #define SYMCRYPT_FDEF369_DIGITS_TO_NUINT32( nD ) (((nD) + 1) * 6) |
23 | | #elif SYMCRYPT_CPU_ARM64 |
24 | | #define SYMCRYPT_FDEF369_DIGITS_TO_NUINT32( nD ) ((nD) * 6) |
25 | | #else |
26 | | #error ?? |
27 | | #endif |
28 | | |
29 | | VOID |
30 | | SYMCRYPT_CALL |
31 | | SymCryptFdef369ModAddGeneric( |
32 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
33 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
34 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
35 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
36 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
37 | | SIZE_T cbScratch ) |
38 | 2.24M | { |
39 | 2.24M | UINT32 c; |
40 | 2.24M | UINT32 d; |
41 | 2.24M | UINT32 nDigits = pmMod->nDigits; |
42 | | |
43 | 2.24M | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
44 | 2.24M | SYMCRYPT_ASSERT( cbScratch >= nDigits*SYMCRYPT_FDEF_DIGIT_SIZE ); |
45 | | |
46 | | // |
47 | | // Doing add/cmp/sub might be faster or not. |
48 | | // Masked add is hard because the mask operations destroy the carry flag. |
49 | | // |
50 | | // dcl - cleanup? |
51 | | // c = SymCryptFdefRawAdd( &pSrc1->uint32[0], &pSrc2->uint32[0], &pDst->uint32[0], nDigits); |
52 | | // d = SymCryptFdefRawSub( &pDst->uint32[0], &pMod->Divisor.Int.uint32[0], &pDst->uint32[0], nDigits ); |
53 | | // e = SymCryptFdefRawMaskedAdd( &pDst->uint32[0], &pMod->Divisor.Int.uint32[0], 0 - (c^d), nDigits ); |
54 | | |
55 | 2.24M | c = SymCryptFdef369RawAddAsm( &peSrc1->d.uint32[0], &peSrc2->d.uint32[0], &peDst->d.uint32[0], nDigits ); |
56 | 2.24M | d = SymCryptFdef369RawSubAsm( &peDst->d.uint32[0], SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ), (PUINT32) pbScratch, nDigits ); |
57 | 2.24M | SymCryptFdef369MaskedCopyAsm( pbScratch, (PBYTE) &peDst->d.uint32[0], nDigits, (c^d) - 1 ); |
58 | | |
59 | | // We can't have a carry in the first addition, and no carry in the subtraction. |
60 | 2.24M | SYMCRYPT_ASSERT( !( c == 1 && d == 0 ) ); |
61 | 2.24M | } |
62 | | |
63 | | |
64 | | VOID |
65 | | SYMCRYPT_CALL |
66 | | SymCryptFdef369ModSubGeneric( |
67 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
68 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
69 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
70 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
71 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
72 | | SIZE_T cbScratch ) |
73 | 2.22M | { |
74 | 2.22M | UINT32 c; |
75 | 2.22M | UINT32 d; |
76 | 2.22M | UINT32 nDigits = pmMod->nDigits; |
77 | | |
78 | 2.22M | SymCryptFdefClaimScratch( pbScratch, cbScratch, SYMCRYPT_SCRATCH_BYTES_FOR_COMMON_MOD_OPERATIONS( nDigits ) ); |
79 | 2.22M | SYMCRYPT_ASSERT( cbScratch >= nDigits*SYMCRYPT_FDEF_DIGIT_SIZE ); |
80 | | |
81 | 2.22M | c = SymCryptFdef369RawSubAsm( &peSrc1->d.uint32[0], &peSrc2->d.uint32[0], &peDst->d.uint32[0], nDigits ); |
82 | 2.22M | d = SymCryptFdef369RawAddAsm( &peDst->d.uint32[0], SYMCRYPT_FDEF_INT_PUINT32( &pmMod->Divisor.Int ), (PUINT32) pbScratch, nDigits ); |
83 | 2.22M | SymCryptFdef369MaskedCopyAsm( pbScratch, (PBYTE) &peDst->d.uint32[0], nDigits, 0 - c ); |
84 | | |
85 | 2.22M | SYMCRYPT_ASSERT( !(c == 1 && d == 0) ); |
86 | 2.22M | } |
87 | | |
88 | | VOID |
89 | | SYMCRYPT_CALL |
90 | | SymCryptFdef369ModulusInitMontgomery( |
91 | | _Inout_ PSYMCRYPT_MODULUS pmMod, |
92 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
93 | | SIZE_T cbScratch ) |
94 | 903 | { |
95 | 903 | SymCryptFdefModulusInitMontgomeryInternal( pmMod, SYMCRYPT_FDEF369_DIGITS_TO_NUINT32( pmMod->nDigits ), pbScratch, cbScratch ); |
96 | 903 | } |
97 | | |
98 | | VOID |
99 | | SYMCRYPT_CALL |
100 | | SymCryptFdef369ModMulMontgomery( |
101 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
102 | | _In_ PCSYMCRYPT_MODELEMENT peSrc1, |
103 | | _In_ PCSYMCRYPT_MODELEMENT peSrc2, |
104 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
105 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
106 | | SIZE_T cbScratch ) |
107 | 4.14M | { |
108 | 4.14M | UINT32 nDigits = pmMod->nDigits; |
109 | 4.14M | PUINT32 pTmp = (PUINT32) pbScratch; |
110 | | |
111 | 4.14M | UNREFERENCED_PARAMETER( cbScratch ); |
112 | 4.14M | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
113 | | |
114 | 4.14M | SymCryptFdef369RawMul( &peSrc1->d.uint32[0], nDigits, &peSrc2->d.uint32[0], nDigits, pTmp ); |
115 | 4.14M | SymCryptFdef369MontgomeryReduce( pmMod, pTmp, &peDst->d.uint32[0] ); |
116 | 4.14M | } |
117 | | |
118 | | VOID |
119 | | SYMCRYPT_CALL |
120 | | SymCryptFdef369ModSquareMontgomery( |
121 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
122 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
123 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
124 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
125 | | SIZE_T cbScratch ) |
126 | 1.07M | { |
127 | 1.07M | SymCryptFdef369ModMulMontgomery( pmMod, peSrc, peSrc, peDst, pbScratch, cbScratch ); |
128 | 1.07M | } |
129 | | |
130 | | VOID |
131 | | SYMCRYPT_CALL |
132 | | SymCryptFdef369ModSetPostMontgomery( |
133 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
134 | | _Inout_ PSYMCRYPT_MODELEMENT peObj, |
135 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
136 | | SIZE_T cbScratch ) |
137 | 8.92k | { |
138 | | // Montgomery representation for X is R*X mod M where R = 2^<nDigits * bits-per-digit> |
139 | | // Montgomery reduction performs an implicit division by R |
140 | | // This function converts to the internal representation by multiplying by R^2 mod M and then performing a Montgomery reduction |
141 | 8.92k | UINT32 nDigits = pmMod->nDigits; |
142 | | |
143 | | // dcl - release mode check? |
144 | 8.92k | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
145 | 8.92k | UNREFERENCED_PARAMETER( cbScratch ); |
146 | | |
147 | 8.92k | SymCryptFdef369RawMul( &peObj->d.uint32[0], nDigits, pmMod->tm.montgomery.Rsqr, nDigits, (PUINT32) pbScratch ); |
148 | 8.92k | SymCryptFdef369MontgomeryReduce( pmMod, (PUINT32) pbScratch, &peObj->d.uint32[0] ); |
149 | 8.92k | } |
150 | | |
151 | | PCUINT32 |
152 | | SYMCRYPT_CALL |
153 | | SymCryptFdef369ModPreGetMontgomery( |
154 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
155 | | _In_ PCSYMCRYPT_MODELEMENT peObj, |
156 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
157 | | SIZE_T cbScratch ) |
158 | 1.43k | { |
159 | 1.43k | PUINT32 pTmp = (PUINT32) pbScratch; |
160 | 1.43k | UINT32 nDigits = pmMod->nDigits; |
161 | 1.43k | UINT32 nUint32 = SYMCRYPT_FDEF369_DIGITS_TO_NUINT32( nDigits ); |
162 | | |
163 | | // dcl - release mode check? |
164 | 1.43k | SYMCRYPT_ASSERT( cbScratch >= nDigits * 2 * SYMCRYPT_FDEF_DIGIT_SIZE ); |
165 | 1.43k | UNREFERENCED_PARAMETER( cbScratch ); |
166 | | |
167 | 1.43k | memcpy( pTmp, &peObj->d.uint32[0], nUint32 * sizeof( UINT32 ) ); |
168 | 1.43k | SymCryptWipe( pTmp + nUint32, nUint32 * sizeof( UINT32 ) ); |
169 | 1.43k | SymCryptFdef369MontgomeryReduce( pmMod, pTmp, pTmp ); |
170 | | |
171 | | // This gives the right result, but it isn't the size that is expected. |
172 | | // Wipe the extra bytes |
173 | 1.43k | SymCryptWipe( pTmp + nUint32, nDigits * SYMCRYPT_FDEF_DIGIT_SIZE - nUint32 * sizeof( UINT32 ) ); |
174 | | |
175 | 1.43k | return pTmp; |
176 | 1.43k | } |
177 | | |
178 | | VOID |
179 | | SymCryptFdef369MontgomeryReduce( |
180 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
181 | | _Inout_ PUINT32 pSrc, |
182 | | _Out_ PUINT32 pDst ) |
183 | 4.15M | { |
184 | 4.15M | SymCryptFdef369MontgomeryReduceAsm( pmMod, pSrc, pDst ); |
185 | 4.15M | } |
186 | | |
187 | | VOID |
188 | | SYMCRYPT_CALL |
189 | | SymCryptFdef369RawMul( |
190 | | _In_reads_(nDigits1*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc1, |
191 | | UINT32 nDigits1, |
192 | | _In_reads_(nDigits2*SYMCRYPT_FDEF_DIGIT_NUINT32) PCUINT32 pSrc2, |
193 | | UINT32 nDigits2, |
194 | | _Out_writes_((nDigits1+nDigits2)*SYMCRYPT_FDEF_DIGIT_NUINT32) PUINT32 pDst ) |
195 | 4.15M | { |
196 | 4.15M | SymCryptFdef369RawMulAsm( pSrc1, nDigits1, pSrc2, nDigits2, pDst ); |
197 | 4.15M | } |
198 | | |
199 | | SYMCRYPT_ERROR |
200 | | SYMCRYPT_CALL |
201 | | SymCryptFdef369ModInvMontgomery( |
202 | | _In_ PCSYMCRYPT_MODULUS pmMod, |
203 | | _In_ PCSYMCRYPT_MODELEMENT peSrc, |
204 | | _Out_ PSYMCRYPT_MODELEMENT peDst, |
205 | | UINT32 flags, |
206 | | _Out_writes_bytes_( cbScratch ) PBYTE pbScratch, |
207 | | SIZE_T cbScratch ) |
208 | 869 | { |
209 | 869 | SYMCRYPT_ERROR scError = SYMCRYPT_NO_ERROR; |
210 | 869 | UINT32 nDigits = pmMod->nDigits; |
211 | 869 | UINT32 nBytes = SYMCRYPT_FDEF369_DIGITS_TO_NUINT32( nDigits ) * sizeof( UINT32 ); |
212 | 869 | PUINT32 pTmp = (PUINT32) pbScratch; |
213 | | |
214 | 869 | SYMCRYPT_ASSERT_ASYM_ALIGNED( pTmp ); |
215 | 869 | SYMCRYPT_ASSERT( cbScratch >= 2 * nBytes ); |
216 | | |
217 | | // |
218 | | // We have R*X; we first apply the montgomery reduction twice to get X/R, and then invert that |
219 | | // using the generic inversion to get R/X. |
220 | | // |
221 | 869 | memcpy( pTmp, &peSrc->d.uint32[0], nBytes ); |
222 | | |
223 | 869 | SymCryptWipe( (PBYTE)pTmp + nBytes, nBytes ); |
224 | 869 | SymCryptFdef369MontgomeryReduce( pmMod, pTmp, pTmp ); |
225 | | |
226 | 869 | SymCryptWipe( (PBYTE)pTmp + nBytes, nBytes ); |
227 | 869 | SymCryptFdef369MontgomeryReduce( pmMod, pTmp, &peDst->d.uint32[0] ); |
228 | | |
229 | 869 | scError = SymCryptFdefModInvGeneric( pmMod, peDst, peDst, flags, pbScratch, cbScratch ); |
230 | | |
231 | 869 | return scError; |
232 | 869 | } |
233 | | |
234 | | |
235 | | #endif // CPU_AMD64 |