-
Notifications
You must be signed in to change notification settings - Fork 2
/
x64_mult256x256_Modulo_CoordCourbeSepc256k.asm
286 lines (262 loc) · 12.8 KB
/
x64_mult256x256_Modulo_CoordCourbeSepc256k.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
; multiplication de 2 entier 256 bits modulo 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
; version 64 bits
; déclaration de l'existence d'une fonction externe
multiplication_256x256_512 PROTO C
.CODE
mult256x256_Modulo_CoordCourbeSepc256k PROC
; Proto C :
; EXPORT void mult256x256_Modulo_CoordCourbeSepc256k (byte* pNombreA, byte* pNombreB, OUT byte* pResultat)
; defines des paramètres
param1 equ rcx
param2 equ rdx
param3 equ r8
; prologue
IFDEF LINUX
mov rcx,param1 ; car le param1=rdi en linux est ecrasé par param2. NB ; rcx volatile en linux+windows
sub rsp,38h ; simule la réserve de pile de la convention windows
ENDIF
mov qword ptr [rsp+18h],param3 ; sauver pResultat dans la zone des var locales. [rsp+68h] apres les push
push rax
push rbx
push rcx
push rbp
push rsi
push rdi
push r12
push r13
push r14
push r15
IFDEF MULX_SUPPORTED ;-------------------------------------------------------------------------------------
; code si l'instruction mulx est disponible sur le processeur : Intel ADX (Multi-Precision Add-Carry Instruction Extensions)
; récupération des variables en regitres:
mov rdi,param2
mov r10,qword ptr [rcx ] ; r10 = A0
mov rsi,qword ptr [rcx+8 ] ; rsi = A1
mov rbp,qword ptr [rcx+10h] ; rbp = A2
mov r14,qword ptr [rcx+18h] ; r14 = A3
; //-------------------------------------------
; // calcul de A * B0 :
; // [ A3 ] [ A2 ] [ A1 ] [ A0 ]
; // * [ B0 ]
; // ------------------------------------------
; // [ C1 ] [ C0 ]
; // [ C2 ] [ L_ ]
; // [ C3 ] [ L _]
; // [ C4 ] [ L _]
; //-------------------------------------------
; // = [ C4 ] [ C3 ] [ C2 ] [ C1 ] [ C0 ]
;
; A0 A1 A2 A3
; r10 rsi rbp r14
; B0
; rdx
; C0 C1 C2 C3 C4
; r13 r9 r11 r12 r15
mov rdx,qword ptr [rdi] ; rdx = B0
mulx r11,rax,rsi ; (r11,rax) = rsi * rdx (C2,L_) = A1*B0
mulx r9, r13,r10 ; (r9, r13) = r10 * rdx (C1,C0) = A0*B0
add r9,rax ; (c ,C1) = C1 + L_ + c
mulx r12,rax,rbp ; (r12,rax) = rbp * rdx (C3,L_) = A2*B0
adc r11,rax ; (c ,C2) = C2 + L_ + c
mulx r15,rax,r14 ; (r15,rax) = r14 * rdx (C4,L_) = A3*B0
adc r12,rax ; (c ,C3) = C3 + L_ + c
adc r15,0 ; C4 = C4 + c
;//*B1
; //-----------------------------------------------------
; // calcul de (A * B0) + ( A * B1 ) :
; // [ A3 ] [ A2 ] [ A1 ] [ A0 ]
; // * [ B1 ]
; // -----------------------------------------------
; // [ H ] [ L ]
; // [ H ] [ L ]
; // [ H ] [ L ]
; // [ C5 ] [ L ]
; // + [ C4 ] [ C3 ] [ C2 ] [ C1 ] [ C0 ] ( A * B0 , étage précédent )
; //---------------------------------------------------
; // = [ C5 ] [ C4 ] [ C3 ] [ C2 ] [ C1 ] [ C0 ]
xor rdx,rdx ; RAZ c et of
mov rdx,qword ptr [rdi+8] ; rdx = B1
mulx rcx,rax,r10 ; (rcx,rax) = r10 * rdx (H_,L_) = A0*B1
adox r9,rax ; (of,C1) = C1 + L_
mov qword ptr [rsp+58h],r9 ; [C1] = r9
adox r11,rcx ; (of,C2) = C2 + H_ + of
mulx rcx,rax,rsi ; (rcx,rax) = rsi * rdx (H_,L_) = A1*B1
adcx r11,rax ; (c, C2) = C2 + L_
adox r12,rcx ; (of,C3) = C3 + H_ + of
mulx rcx,rax,rbp ; (rcx,rax) = rbp * rdx (H_,L_) = A2*B1
adcx r12,rax ; (c, C3) = C3 + L_
mulx rbx,rax,r14 ; (rbx,rax) = r14 * rdx (C5,L_) = A3*B1
adox r15,rcx ; (of,C4) = C4 + H_ + of
adcx r15,rax ; (c, C4) = C4 + L_
mov rdx,0 ; pas xor pour conserver c et of
adox rbx,rdx ; rdx=0 C5 += of
adcx rbx,rdx ; rdx=0 C5 += c
;//*B2
xor rdx,rdx ; RAZ c et of
mov rdx,qword ptr [rdi+10h] ; rdx = B2
mulx rcx,rax,r10 ; (rcx,rax) = r10 * rdx (H_,L_) = A0*B2
adox r11,rax ; (of,C2) = C2 + L_
mov qword ptr [rsp+60h],r11 ; [C2] = r11
adox r12,rcx ; (of,C3) = C2 + H_ + of
mulx rcx,rax,rsi ; (rcx,rax) = rsi * rdx (H_,L_) = A1*B2
adcx r12,rax ; (c, C3) = C3 + L_
adox r15,rcx ; (of,C4) = C4 + H_ + of
mulx rcx,rax,rbp ; (rcx,rax) = rbp * rdx (H_,L_) = A2*B2
adcx r15,rax ; (c, C4) = C4 + L_
mulx r11,rax,r14 ; (rbx,rax) = r14 * rdx (C6,L_) = A3*B2
adox rbx,rcx ; (of,C5) = C5 + H_ + of
adcx rbx,rax ; (c, C5) = C5 + L_
mov rdx,0 ; pas xor pour conserver c et of
adox r11,rdx ; rdx=0 C6 += of
adcx r11,rdx ; rdx=0 C6 += c
;//*B3
xor rdx,rdx ; RAZ c et of
mov rdx,qword ptr [rdi+18h] ; rdx = B3
mulx rcx,rax,r10 ; (rcx,rax) = r10 * rdx (H_,L_) = A0*B3
adox r12,rax ; (of,C3) = C3 + L_
adox r15,rcx ; (of,C4) = C4 + H_ + of
mulx rcx,rax,rsi ; (rcx,rax) = rsi * rdx (H_,L_) = A1*B3
adcx r15,rax ; (c, C4) = C4 + L_
adox rbx,rcx ; (of,C5) = C5 + H_ + of
mov rdi,qword ptr [rsp+58h] ; ---????-- rdi = C1
mulx rcx,rax,rbp ; (rcx,rax) = rbp * rdx (H_,L_) = A2*B3
adcx rbx,rax ; (c, C5) = C5 + L_
adox r11,rcx ; (of,C6) = C6 + H + of
mulx r10,rax,r14 ; (r10,rax) = r14 * rdx (C7,L_) = A3*B3
adcx r11,rax ; (c, C6) = C6 + L_
mov rdx,0 ; pas xor pour conserver c et of
adox r10,rdx ; rdx=0 C7 += of
adcx r10,rdx ; rdx=0 C7 += c
; Multiplication de partie dépasse ( C7 C6 C5 C4 ) par 2^256 modulo P : 0x1000003d1
; et ajout au résultat
xor rsi,rsi ; RAZ c et of + rsi = 0
mov rdx,1000003D1h ;
mulx rcx,rax,r15 ; (rcx,rax) = r15 * rdx (H_,L_) = C4 * 0x1000003d1
adox r13,rax ; (of,C0) = C0 + L_
adox rdi,rcx ; (of,C1) = C1 + H_ + ch
mulx rcx,rax,rbx ; (rcx,rax) = rbx * rdx (H_,C5) = C5 * 0x1000003d1
mov rbx,qword ptr [rsp+60h] ; rbx = [C2]
adcx rdi,rax ; (c, C1) = C1 + C5
adox rbx,rcx ; (of,C2) = C2 + H_ + of
mulx rcx,rax,r11 ; (rcx,rax) = r11 * rdx (H_,C5) = C6 * 0x1000003d1
adcx rbx,rax ; (c, C2) = C2 + C5
adox r12,rcx ; (of,C3) = C3 + H_ + of
mulx r8,rax,r10 ; (r8,rax) = r10 * rdx (C4,L_) = C7* 0x1000003d1
adcx r12,rax ; (c, C3) = C3 + L_ + c
adcx r8,rsi ; C4 += c
adox r8,rsi ; C4 += of
; si C4 != 0
; on doit ajouter encore H x _2pow256_mod . toujours fait pour éviter des effets de side-channel
xor rsi,rsi ; RAZ c et of
mulx rcx,rax,r8 ; (rcx,rax) = r8 * rdx (H_,L_) = C4 * 0x1000003d1
adcx r13,rax ; (c ,C0) = C0 + L_
adcx rdi,rcx ; (c ,C1) = C1 + H + c
adcx rbx,rsi ; (c ,C2) = C2 + c
adcx r12,rsi ; (c ,C3) = C3 + c
ELSE ;MULX_SUPPORTED -------------------------------------------------------------------------------------
; version si l'instruction mulx n'est pas dispo
sub rsp, 78h ; reserve pour var localed : +00h..+3Fh : AxB_512, +40h..77h: convention d'appel
; multiplication A*B => 512 bits
; UI512 AxB_512;
; multiplication_256x256_512_ASM(pNombreA, pNombreB, (PBYTE)&AxB_512);
lea param3,[rsp] ; r8 = &AxB_512
call multiplication_256x256_512 ; (rcx,rdx,r8)
; multiplication des 256 bits de poids fort par 2^256 - P => 0x1000003d1
; C1
mov rbx, 1000003d1h
mov rax, rbx
mov rcx,[rsp+20h] ; AxB_512.high.C0
mul rcx ; (rdx,rax) = rcx*rax
mov r13, rax ; C0 = rax
mov r9 , rdx ; C1 = rdx
; 1
mov rcx,[rsp+28h] ; AxB_512.high.C1
mov rax, rbx
mul rcx ; (rdx,rax) = rcx*rax
add r9, rax ; C1 += rax
mov r11, rdx ; C2 = rdx
;2
mov rcx,[rsp+30h] ; AxB_512.high.C2
pushf
mov rax, rbx
mul rcx ; (rdx,rax) = rcx*rax
popf
adc r11, rax ; C2 += rax + carry
mov r12, rdx ; C3 = rdx
; 3
mov rcx,[rsp+38h] ; AxB_512.high.C2
pushf
mov rax, rbx
mul rcx ; (rdx,rax) = rcx*rax
popf
adc r12, rax ; C3 += rax + carry
mov r15, rdx ; C5 = rdx
adc r15, 0 ; C5 += carry
; récup en registre et addition pour revernir dans le meme code que la version avec mulx
; + AxB_512.low
add r13, [rsp] ; +C0
adc r9, [rsp+08h] ; +C1
adc r11, [rsp+10h] ; +C2
adc r12, [rsp+18h] ; +C3
adc r15, 0 ; C5 += carry
; si C4 != 0
; on doit ajouter encore H x _2pow256_mod . toujours fait pour éviter des effets de side-channel
xor rsi,rsi ; RAZ c et of
mov r8, 1000003d1h
mov rax, r15
mul r8 ; (rdx,rax) = r8 * rax (H_,L_) = C4 * 0x1000003d1
add r13,rax ; (c ,C0) = C0 + L_
adc r9, rdx ; (c ,C1) = C1 + H + c
adc r11,rsi ; (c ,C2) = C2 + c
adc r12,rsi ; (c ,C3) = C3 + c
; restaure la pile
add rsp,78h
; memes registres que dans le cas mulx dispo
mov rdi,r9 ; C1
mov rbx,r11 ; C2
mov rdx,r8 ; 1000003d1h
ENDIF ;!MULX_SUPPORTED-------------------------------------------------------------------------------------
; si on dépasse P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
; on doit soustraire P, équivalent a ajouter -P (ie P complémenté a 2) = _2pow256_mod
; si( C3 == 0xffffffffffffffff
; && C2 == 0xffffffffffffffff
; && C1 == 0xffffffffffffffff
; && C0 >= 0xfffffffefffffc2f )
cmp r12,0FFFFFFFFFFFFFFFFh
jne neDepassePas;
cmp rbx,r12
jne neDepassePas
cmp rdi,r12
jne neDepassePas;
mov rax,0FFFFFFFEFFFFFC2Fh
cmp r13,rax
jb neDepassePas;
; code si on dépasse => ajout de 0x1000003d1
add r13,rdx ; C0 += 0x1000003d1
adc rbx,rsi ; C1 += c
adc rdi,rsi ; C2 += c
adc r12,rsi ; C3 += c
neDepassePas:
; affectation du résultat dans : r12 ( C3 = poids fort) , rbx, rdi, r13 (C0 = poids faible )
mov rax,qword ptr [rsp+68h] ; rax = [pResultat]
mov qword ptr [rax ],r13 ; C0 = r13
mov qword ptr [rax+8 ],rdi ; C1 = rdi
mov qword ptr [rax+10h],rbx ; C2 = rbx
mov qword ptr [rax+18h],r12 ; C3 = r12
;Epilogue
pop r15
pop r14
pop r13
pop r12
pop rdi
pop rsi
pop rbp
pop rcx
pop rbx
pop rax
IFDEF LINUX
add rsp,38h
ENDIF
ret
mult256x256_Modulo_CoordCourbeSepc256k endp
END