Coverage Report

Created: 2024-11-21 07:03

/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