Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <string.h>
4
#include <math.h>
5
#include <time.h>
6
#include "gmp.h"
7
#include "mpzutil.h"
8
#include "ffwrapper.h"
9
#include "ffpoly.h"
10
#include "hecurve.h"
11
#include "cstd.h"
12
13
14
/*
15
Copyright 2007 Andrew V. Sutherland
16
17
This file is part of smalljac.
18
19
smalljac is free software: you can redistribute it and/or modify
20
it under the terms of the GNU General Public License as published by
21
the Free Software Foundation, either version 2 of the License, or
22
(at your option) any later version.
23
24
smalljac is distributed in the hope that it will be useful,
25
but WITHOUT ANY WARRANTY; without even the implied warranty of
26
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27
GNU General Public License for more details.
28
29
You should have received a copy of the GNU General Public License
30
along with GenericGroupDemo. If not, see <http://www.gnu.org/licenses/>.
31
*/
32
33
#if HECURVE_GENUS == 3
34
35
#define _dbg_print_uv(s,u,v) if ( dbg_level >= DEBUG_LEVEL ) { printf (s); hecurve_print(u,v); }
36
37
#define sub _ff_sub
38
#define subf _ff_subfrom
39
#define add _ff_add
40
#define addt _ff_addto
41
#define mult _ff_mult
42
#define multx(a,b) ff_mult(a,a,b)
43
#define sqr _ff_square
44
#define neg _ff_neg
45
#define dbl _ff_x2
46
47
// For simplicity, we assume no initilization of field elements is required. Debug code assume ff_t fits in an unsigned long.
48
49
int hecurve_g3_compose (ff_t u[4], ff_t v[3], ff_t u1[4], ff_t v1[3], ff_t u2[4], ff_t v2[3], ff_t f[8], hecurve_ctx_t *ctx)
50
{
51
_ff_t_declare_reg d0, d1, d2, t0, w0, w1, w2, w3, w4, w5, w6, w7, r, x0, x1, x2;
52
53
if ( ctx && ctx->state == 1 ) {
54
// get invert result and restore saved variables
55
_ff_set (w1, ctx->invert); // inverted value of r*s1
56
_ff_set (r, ctx->r);
57
_ff_set (d0, ctx->s0);
58
_ff_set (d1, ctx->s1);
59
_ff_set (d2, ctx->s2);
60
/// dbg_printf ("Restored r = %lu, s2 = %lu, s1 = %lu, s0 = %lu, w1 = %lu\n", r, d2, d1, d0, w1);
61
goto hecurve_g3_compose_inverted;
62
}
63
64
#if ! HECURVE_FAST
65
if ( dbg_level >= 2 ) {
66
printf ("Compose_3_3 inputs\n"); hecurve_print(u1,v1); hecurve_print(u2,v2);
67
}
68
#endif
69
#if HECURVE_VERIFY
70
if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_g3_compose: invalid input\n"); exit (0); }
71
if ( ! hecurve_verify (u2, v2, f) ) { err_printf ("hecurve_g3_compose: invalid input\n"); exit (0); }
72
#endif
73
74
if ( ! _ff_one(u1[3]) || ! _ff_one(u2[3]) ) { hecurve_compose_cantor(u,v,u1,v1,u2,v2,f); return 1; }
75
76
// 1. Compute r = Resultant(u1,u2)
77
sub(d0,u2[0],u1[0]); // d0 = u20-u10
78
sub(d1,u2[1],u1[1]); // d1 = u21-u11
79
sub(d2,u2[2],u1[2]); // d2 = u22-u12
80
mult(w1,u1[1],u2[0]); // w1 = t3 = u11u20
81
mult(t0,u1[0],u2[1]); // t0 = t4 = u10u21
82
subf(w1,t0); // w1 = t3-t4
83
mult(w2,u1[2],u2[0]); // w2 = t5 = u12u20
84
mult(t0,u1[0],u2[2]); // t0 = t6 = u10u22
85
subf(w2,t0); // w2 = t5-t6
86
mult(w3,u1[2],u2[1]); // w3 = t1 = u12u21
87
mult(t0,u1[1],u2[2]); // t0 = t2 = u11u22
88
subf(w3,t0); // w3 = t1-t2
89
mult(w4,d1,d0); // w4 = t11
90
sqr(w5,d1); // w5 = t8
91
mult(t0,d2,w1); // t0 = t9
92
sqr(w6,d0); // w6 = t7
93
subf(w6,t0); // w6 = t7-t9
94
mult(w7,d2,w2); // w7 = t10 = (u22-u12)(t5-t6)
95
subf(w7,w4); // w7 = t10-t11
96
add(t0,d0,w3);
97
mult(r,t0,w6);
98
sub(t0,w7,w4);
99
multx(t0,w2);
100
addt(r,t0);
101
mult(t0,w5,w1);
102
addt(r,t0); // r = (d0+w3)w6+w2(w7-w4)+w5w1
103
/// dbg_printf ("r = %lu\n", r);
104
// if ( _ff_zero(r) ) { hecurve_compose_cantor(u,v,u1,v1,u2,v2,f); return 1; } // handled below
105
106
// 2. Compute inv = r/u1 mod u2
107
add(t0,w3,d0); // t0 = t1-t2+u20-u10
108
mult(w1,t0,d2);
109
subf(w1,w5); // w1 = inv2 = (t1-t2+u20-u10)(u22-u12)-t8
110
mult(w2,u2[2],w1);
111
subf(w2,w7); // w2 = inv1 = inv2u22 -t10+t11
112
mult(t0,u2[2],w7);
113
addt(t0,w6); // t0 = u22(t10-t11)+t7-t9
114
mult(w3,w1,u2[1]);
115
subf(w3,t0); // w3 = inv0 = inv2u21 - (u22(t10-t11)+t7-t9)
116
/// dbg_printf ("inv = %lux^2 + %lux + %lu\n", w1, w2, w3);
117
118
// 3. Compute s' = rs = (v2-v1)inv (mod u2) - note that we don't use Karatusba here since field mults aren't much slower than add/sub
119
sub(d0,v2[0],v1[0]); // do = v20-v10
120
sub(d1,v2[1],v1[1]); // d1 = v21-v11
121
sub(d2,v2[2],v1[2]); // d2 = v22-v12
122
mult(w5,d0,w3); // w5 = t15 = r'0
123
mult(w4,d2,w1); // w4 = t17 = r'4
124
mult(w6,d1,w3);
125
mult(t0,d0,w2);
126
addt(w6,t0); // w6 = r'1 = d1w3+d0w2
127
mult(w7,d1,w2);
128
mult(t0,d2,w3);
129
addt(w7,t0);
130
mult(t0,d0,w1);
131
addt(w7,t0); // w7 = r'2 = d1w2+d2w3+d0w1
132
mult(w3,d2,w2);
133
mult(t0,d1,w1);
134
addt(t0,w3);
135
mult(w3,u2[2],w4);
136
subf(w3,t0); // w3 = t18 = u22w4 - (d2w2+d1w2)
137
mult(w2,u2[0],w3); // w2 = t15 = u20w3
138
mult(w1,u2[1],w4); // w1 = t16 = u21w4
139
add(d0,w2,w5); // d0 = s'0 = w2+w5
140
add(d1,u2[0],u2[1]);
141
sub(t0,w4,w3);
142
multx(t0,d1);
143
sub(d1,w6,t0);
144
addt(d1,w1);
145
subf(d1,w2); // d1 = s'1 = w6 - (u20+u21)(w4-w3)+w1-w2
146
mult(d2,u2[2],w3);
147
subf(d2,w1);
148
addt(d2,w7); // d2 = s'2 = w7-w1+u22w3
149
/// dbg_printf ("s' = %lux^2 + %lux + %lu\n", d2, d1, d0);
150
151
mult(t0,r,d2);
152
if ( _ff_zero(t0) ) {
153
int sts;
154
// check for squaring and inverse cases before resorting to Cantor - caller really should use hecurve_square
155
sts = hecurve_cmp (u1,v1,u2,v2);
156
if ( sts == 1 ) return hecurve_g3_square(u,v,u1,v1,f,ctx);
157
if ( sts == -1 ) { _hecurve_set_identity(u,v); return 1; }
158
hecurve_compose_cantor(u,v,u1,v1,u2,v2,f);
159
return 1;
160
}
161
if ( ctx && ! ctx->state ) {
162
_ff_set (ctx->s0, d0);
163
_ff_set (ctx->s1, d1);
164
_ff_set (ctx->s2, d2);
165
_ff_set (ctx->r, r);
166
_ff_set (ctx->invert, t0); // return to let caller invert
167
ctx->state = 1;
168
/// dbg_printf("Returning to let caller invert %lu\n", t0);
169
return 0;
170
}
171
_ff_invert(w1,t0);
172
173
hecurve_g3_compose_inverted: // caller returns here after inverting
174
// we assume w1, r, d0, d1, and d2 are set, all others free
175
// 4. Compute s = s'/r and make monic
176
mult(w2,r,w1); // w2 = rw1 = 1/s2
177
sqr(w7,d2);
178
multx(w7,w1);
179
ff_negate(w7); // w7 = -s2/r
180
mult(w6,r,w2); // w6 = r/s2 (w4 in HECHECC)
181
sqr(w5,w6); // w5 = (r/s2)^2
182
multx(d0,w2); // d0 = s0'/s2 = s0
183
multx(d1,w2); // d1 = s1'/s2 = s1
184
/// dbg_printf ("s = x^2 + %lux + %lu\n", d1, d0);
185
186
// 5. Compute z = su1
187
mult (w0,d0,u1[0]); // w0 = z0 = s0u10
188
mult (w1,d1,u1[0]);
189
mult (t0,d0,u1[1]);
190
addt(w1,t0); // w1 = z1 = s1u10+s0u11
191
mult (w2,d0,u1[2]);
192
mult(t0,d1,u1[1]);
193
addt(w2,t0);
194
addt(w2,u1[0]); // w2 = z2 = s0u12+s1u11+u10
195
mult(w3,d1,u1[2]);
196
addt(w3,d0);
197
addt(w3,u1[1]); // w3 = z3 = s1u12+s0+u11
198
add(w4,d1,u1[2]); // w4 = z4 = u1[2],s1
199
/// dbg_printf ("z = x^5 + %lux^4 + %lux^3 + %lux^2 + %lux + %lu\n", w4, w3, w2, w1, w0);
200
201
// 6. Compute u' = [s(z+2w6v1) - w5((u20-v1^2)]/u2 note h = 0, w6 is w4 in handbook
202
add(r,w4,d1);
203
subf(r,u2[2]); // r = u'3 = z4+s1-u22
204
mult(x2,d1,w4);
205
mult(t0,r,u2[2]);
206
subf(x2,t0);
207
subf(x2,u2[1]);
208
addt(x2,w3);
209
addt(x2,d0); // x2 = u'2 = -u22u'3 - u21 + z3 + s0 + s1z4
210
mult(x1,w6,v1[2]);
211
dbl(x1);
212
mult(t0,d1,w3);
213
addt(x1,t0);
214
mult(t0,d0,w4);
215
addt(x1,t0);
216
addt(x1,w2);
217
subf(x1,w5);
218
mult(t0,x2,u2[2]);
219
subf(x1,t0);
220
mult(t0,r,u2[1]);
221
subf(x1,t0);
222
subf(x1,u2[0]); // x1 = u'1 = 2w6v12 + s1z3 + s0z4 + z2 - w5 - u22u'2 - u21u'3 - u2[0]
223
mult(x0,d1,v1[2]);
224
addt(x0,v1[1]);
225
multx(x0,w6);
226
dbl(x0);
227
mult(t0,d1,w2);
228
addt(x0,t0);
229
addt(x0,w1);
230
mult(t0,d0,w3);
231
addt(x0,t0);
232
mult(t0,w5,u1[2]);
233
addt(x0,t0);
234
mult(t0,u2[2],x1);
235
subf(x0,t0);
236
mult(t0,u2[1],x2);
237
subf(x0,t0);
238
mult(t0,u2[0],r);
239
subf(x0,t0); // x0 = u'0 = 2w6(v11+s1v12) + s1z2 + z1 + s0z3 + w5u12 - u22u'1 - u21u'2 - u20u'3
240
/// dbg_printf ("u' = x^4 + %lux^3 + %lux^2 + %lux + %lu\n", r, x2, x1, x0);
241
242
// 7. Compute v' = w7z - v1 mod u' note h = 0 and w7 is -w3 in handbook
243
sub(w5,r,w4); // w5 = t1 = u'3 - z4
244
mult(d0,x0,w5);
245
addt(d0,w0);
246
multx(d0,w7);
247
subf(d0,v1[0]); // d0 = v'0 = w7(u'0t1+z0) - v10
248
mult(d1,x1,w5);
249
subf(d1,x0);
250
addt(d1,w1);
251
multx(d1,w7);
252
subf(d1,v1[1]); // d1 =-v'1 = w7(u'1t1-u'0+z1) - v11
253
mult(d2,x2,w5);
254
subf(d2,x1);
255
addt(d2,w2);
256
multx(d2,w7);
257
subf(d2,v1[2]); // d2 = v'2 = w7(u'2t1-u'1+z2) - v12
258
mult(w0,r,w5);
259
subf(w0,x2);
260
addt(w0,w3);
261
multx(w0,w7); // w0 = v'3 = w7(u'3t1 - u'2 + z3)
262
/// dbg_printf ("v' = %lux^3 + %lux^2 + %lux + %lu\n", w0, d2, d1, d0);
263
264
// 8. reduce u' to u'' = (f-v'^2)/u'
265
_ff_set_one(u[3]);
266
sqr(t0,w0);
267
addt(t0,r);
268
neg(u[2],t0); // u[2] = u''2 = -(u'3+v'3^2) note f6 = 0
269
mult(t0,r,u[2]); // t0 = u'3u''2
270
addt(t0,x2); // t0 = u'3u''2+u'2
271
mult(w7,d2,w0);
272
dbl(w7); // w7 = 2v'2v'3
273
addt(t0,w7);
274
neg(u[1],t0);
275
#if ! HECURVE_SPARSE
276
addt(u[1],f[5]); // u[1] = u''1 = -(u'2 + u''2u'3 + 2v'2v'3) + f5
277
#endif
278
mult(t0,u[2],x2); // t0 = u''2u'2
279
addt(t0,x1); // t0 = u''2u'2+u'1
280
mult(w7,u[1],r); // w7 = u''1u'3
281
addt(t0,w7);
282
mult(w7,d1,w0);
283
dbl(w7); // w7 = 2v'1v'3
284
addt(t0,w7)
285
sqr(w7,d2); // w7 = v'2^2
286
addt(t0,w7);
287
neg(u[0],t0);
288
#if ! HECURVE_SPARSE
289
addt(u[0],f[4]); // u[0] = u''0 = -(u'1 + u''2u'2 + u''1u'3 + 2v'1v'3 + v'2^2) + f4
290
#endif
291
/// dbg_printf ("u = x^3 + %lux^2 + %lux + %lu\n", u[2], u[1], u[0]);
292
293
// 9. compute v'' = -v' mod u3 note h = 0
294
mult(t0,w0,u[2]);
295
sub(v[2],t0,d2); // v''2 = v'3u''2 - v'2
296
mult(t0,w0,u[1]);
297
sub(v[1],t0,d1); // v'1 = v'3u''1 - v'1
298
mult(t0,w0,u[0]);
299
sub(v[0],t0,d0); // v''0 = v'3u''0 - v'0
300
/// dbg_printf ("v = %lux^2 + %lux + %lu\n", v[2], v[1], v[0]);
301
302
#if HECURVE_VERIFY
303
if ( ! hecurve_verify (u, v, f) ) {
304
err_printf ("hecurve_compose_genus3 output verification failed for inputs:\n");
305
err_printf (" "); hecurve_print(u1,v1);
306
err_printf (" "); hecurve_print(u2,v2);
307
err_printf ("note that inputs may have been modified if output overlapped.\n");
308
exit (0);
309
}
310
#endif
311
312
return 1;
313
}
314
315
316
int hecurve_g3_square (ff_t u[HECURVE_GENUS+1], ff_t v[HECURVE_GENUS],
317
ff_t u1[HECURVE_GENUS+1], ff_t v1[HECURVE_GENUS], ff_t f[HECURVE_DEGREE+1], hecurve_ctx_t *ctx)
318
{
319
_ff_t_declare_reg t0, w0, w1, w2, w3, w4, w5, w6, w7, r, z0, z1, z2, g0, g1, g2, g3,g4;
320
321
if ( ctx && ctx->state == 1 ) {
322
// get invert result and restore saved variables
323
_ff_set (w1, ctx->invert); // inverted value of r*s1
324
_ff_set (r, ctx->r);
325
_ff_set (z0, ctx->s0);
326
_ff_set (z1, ctx->s1);
327
_ff_set (z2, ctx->s2);
328
/// dbg_printf ("Restored r = %lu, s2 = %lu, s1 = %lu, s0 = %lu, w1 = %lu\n", r, z2, z1, z0, w1);
329
goto hecurve_g3_square_inverted;
330
}
331
332
#if ! HECURVE_FAST
333
if ( dbg_level >= 2 ) {
334
printf ("hecurve_g3_square input\n"); hecurve_print(u1,v1);
335
}
336
#endif
337
#if HECURVE_VERIFY
338
if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_g3_square: invalid input\n"); exit (0); }
339
#endif
340
341
if ( ! _ff_one(u1[3]) ) { hecurve_compose_cantor(u,v,u1,v1,u1,v1,f); return 1; }
342
343
// 1. Compute r = Resultant(u,2v)
344
add(z0,v1[0],v1[0]); // z0 = h'0 = 2v0
345
add(z1,v1[1],v1[1]); // z1 = h'1 = 2v1
346
add(z2,v1[2],v1[2]); // z2 = h'2 = 2v2
347
mult(t0,u1[1],z2);
348
mult(w1,u1[2],z1);
349
subf(w1,t0); // w1 = t1-t2 = u2z1-u1z2
350
mult(t0,u1[0],z1);
351
mult(w2,u1[1],z0);
352
subf(w2,t0); // w2 = t3-t4 = u1z0-u0z1
353
mult(t0,u1[0],z2);
354
mult(w3,u1[2],z0);
355
subf(w3,t0); // w3 = t5-t6 = u2z0-u0z2
356
mult(t0,z2,w2);
357
sqr(w4,z0);
358
subf(w4,t0); // w4 = t7-t9 = z0^2 = z2w2
359
mult(w6,z1,z0); // w6 = t11 = z1z0
360
mult(w5,z2,w3);
361
subf(w5,w6); // w5 = t10-t11 = z2w3 - z1z0
362
sqr(w0,z1); // w0 = t8 = z1^2
363
add(r,z0,w1);
364
multx(r,w4);
365
sub(t0,w5,w6);
366
multx(t0,w3);
367
addt(r,t0);
368
mult(t0,w0,w2);
369
addt(r,t0); // r = (z0+w1)w4 + w3(w5+z1z0) + w0w2
370
/// dbg_printf ("r = %lu\n", r);
371
372
// 2. Compute inv = r/2v mod u
373
add(t0,w1,z0);
374
multx(t0,z2);
375
sub(w2,w0,t0); // w2 = inv2 = w0-z2(w1+z0)
376
mult(w1,w2,u1[2]);
377
addt(w1,w5); // w1 = inv1 = inv2u2 + w5
378
mult(w0,w2,u1[1]);
379
mult(t0,w5,u1[2]);
380
addt(w0,t0);
381
addt(w0,w4); // w0 = inv0 = inv2u1+u2w5+w4
382
/// dbg_printf ("inv = %lux^2 + %lux + %lu\n", w2, w1, w0);
383
384
// 3. Compute z = (f-v^2)/u mod u
385
mult(w5,u1[1],u1[2]); // w5 = -t13 = u1u2 note that f6 = 0 so z'3 = -u2
386
sqr(w4,u1[2]);
387
subf(w4,u1[1]);
388
#if ! HECURVE_SPARSE
389
addt(w4,f[5]); // w4 = z'2 = u2^2-u1+f5 note h and f6 = 0
390
#endif
391
sqr(w3,v1[2]);
392
subf(w3,w5);
393
mult(t0,w4,u1[2]);
394
addt(w3,t0);
395
addt(w3,u1[0]);
396
ff_negate(w3);
397
#if ! HECURVE_SPARSE
398
addt(w3,f[4]); // w3 = z'1 = -(v2^2+w5+w4u2+u0) + f4
399
#endif
400
/// dbg_printf ("z' = x^4 - %lux^3 + %lux^2 + %lux + ?, w5 = -t13 = u1u2 = %lu\n", u1[2], w4, w3, w5);
401
add(z2,u1[2],u1[2]);
402
addt(z2,u1[2]);
403
multx(z2,u1[2]);
404
add(t0,u1[1],u1[1]);
405
subf(z2,t0);
406
#if ! HECURVE_SPARSE
407
addt(z2,f[5]); // z2 = 3u2^2-2u1+f5
408
#endif
409
add(z1,w5,w5);
410
addt(z1,w3);
411
subf(z1,u1[0]); // z1 = 2u1u2+w3-u0
412
mult(t0,v1[1],v1[2]);
413
dbl(t0);
414
mult(z0,w4,u1[1]);
415
addt(t0,z0);
416
mult(z0,w3,u1[2]);
417
addt(t0,z0);
418
add(z0,u1[2],u1[2]);
419
addt(z0,u1[2]);
420
multx(z0,u1[0]);
421
subf(z0,t0);
422
#if ! HECURVE_SPARSE
423
addt(z0,f[3]); // z0 = 3u0u2 - (2v1v2+z'2u1+z'1u2) + f3
424
#endif
425
/// dbg_printf ("z = %lux^2 + %lux + %lu\n", z2, z1, z0);
426
427
// 4. Compute s' = (z inv) mod u
428
mult(t0,w1,z0);
429
mult(w3,w0,z1);
430
addt(w3,t0); // w3 = r'1 = w0z1+w1z0
431
mult(w4,w1,z1);
432
mult(t0,w0,z2);
433
addt(w4,t0);
434
mult(t0,w2,z0);
435
addt(w4,t0); // w4 = r'2 = w1z1+w0z2+w2z0
436
mult(t0,w2,z1);
437
mult(w5,w1,z2);
438
addt(w5,t0); // w5 = r'3 = w1z2+w2z1
439
multx(z2,w2); // z2 = r'4
440
mult(w6,z2,u1[2]);
441
subf(w6,w5); // w6 = t18 = u2z2-w5
442
mult(w1,w6,u1[0]); // w1 = t15
443
mult(w2,z2,u1[1]); // w2 = t16
444
multx(z0,w0);
445
addt(z0,w1); // z0 = s'0 = z0w0+w1
446
sub(t0,w6,z2);
447
add(z1,u1[0],u1[1]);
448
multx(z1,t0);
449
addt(z1,w3);
450
addt(z1,w2);
451
subf(z1,w1); // z1 = s'1 = w3+(u1+u0)(w6-z2)+w2-w1
452
mult(z2,w6,u1[2]);
453
addt(z2,w4);
454
subf(z2,w2); // z2 = s'2 = w4-w2+u2w6
455
/// dbg_printf ("s' = %lux^2 + %lux + %lu\n", z2, z1, z0);
456
457
mult(t0,r,z2);
458
if ( _ff_zero(t0) ) { hecurve_compose_cantor(u,v,u1,v1,u1,v1,f); return 1; }
459
if ( ctx && ! ctx->state ) {
460
_ff_set (ctx->s0, z0);
461
_ff_set (ctx->s1, z1);
462
_ff_set (ctx->s2, z2);
463
_ff_set (ctx->r, r);
464
_ff_set (ctx->invert, t0); // return to let caller invert
465
ctx->state = 1;
466
/// dbg_printf("Returning to let caller invert %lu\n", t0);
467
return 0;
468
}
469
_ff_invert(w1,t0);
470
471
hecurve_g3_square_inverted: // caller returns here after inverting
472
// we assume w1, r, z0, z1, and z2 are set, all others free
473
// 5. Compute s = s'/r and make s monic
474
mult(w2,w1,r); // w2 = w1r
475
sqr(w3,z2);
476
multx(w3,w1);
477
ff_negate(w3); // w3 = -w1s'2^2 (note sign change)
478
mult(w4,w2,r); // w4 = r/s'2
479
sqr(w5,w4);
480
multx(z0,w2); // z0 = s0 = w2s'0
481
multx(z1,w2); // z1 = s1 = w2s'1
482
/// dbg_printf ("s = x^2 + %lux + %lu, w3 = %lu (-), w4 = %lu, w5 = %lu\n", z1, z0, w3, w4, w5);
483
484
// 6. Compute G=su
485
mult(g0,z0,u1[0]); // g0 = z0u1
486
mult(t0,z1,u1[0]);
487
mult(g1,z0,u1[1]);
488
addt(g1,t0); // g1 = z1u0+z0u1
489
mult(g2,z0,u1[2]);
490
mult(t0,z1,u1[1]);
491
addt(g2,t0);
492
addt(g2,u1[0]); // g2 = z0u2+z1u1+u0
493
mult(g3,z1,u1[2]);
494
addt(g3,z0);
495
addt(g3,u1[1]); // g3 = z1u2+z0+u1
496
add(g4,z1,u1[2]); // g4 = z1+u2
497
/// dbg_printf ("G = su = x^5 + %lux^4 + %lux^3 + %lux^2 + %lux + %lu\n", g4, g3, g2, g1, g0);
498
499
// 7. Compute u' = [(G+w4v)^2 + w5f]/u^2
500
add(w6,z1,z1); // w6 = u'3 = 2z1
501
sqr(w2,z1);
502
add(t0,z0,z0);
503
addt(w2,t0); // w2 = u'2 = z1^2+2z0
504
mult(t0,w4,v1[2]);
505
mult(w1,z0,z1);
506
addt(w1,t0);
507
dbl(w1);
508
subf(w1,w5); // w1 = u'1 = 2(z0z1+w4v2)-w5
509
sub(t0,z1,u1[2]);
510
multx(t0,v1[2]);
511
addt(t0,v1[1]);
512
multx(t0,w4);
513
multx(w5,u1[2]);
514
addt(t0,w5);
515
dbl(t0);
516
sqr(w0,z0);
517
addt(w0,t0); // w0 = u'0 = z0^2 + 2(w4(v1+v2(z1-u2))+w5u2)
518
/// dbg_printf ("u' = x^4 + %lux^3 + %lux^2 + %lux + %lu\n", w6, w2, w1, w0);
519
520
// 8. Compute v' = -(Gw3 +v) mod u'
521
sub(w4,w6,g4); // w4 = t1 = w6-g4
522
subf(g3,w2);
523
mult(t0,w4,w6);
524
addt(g3,t0);
525
multx(g3,w3); // g3 = v'3 = w3(g3-w2+w4w6) (note w3 sign changed from HECHECC)
526
subf(g2,w1);
527
mult(t0,w4,w2);
528
addt(g2,t0);
529
multx(g2,w3);
530
subf(g2,v1[2]); // g2 = v'2 = w3(g2-w1+w4w2) - v2
531
subf(g1,w0);
532
mult(t0,w4,w1);
533
addt(g1,t0);
534
multx(g1,w3);
535
subf(g1,v1[1]); // g1 = v'1 = w3(g1-w0+w4w1) - v1
536
mult(t0,w4,w0);
537
addt(g0,t0);
538
multx(g0,w3);
539
subf(g0,v1[0]); // g0 = v'0 = w3(g0+w4w0) - v0
540
/// dbg_printf ("v' = %lux^3 + %lux^2 + %lux + %lu\n", g3, g2, g1, g0);
541
542
// 9. Compute u'' = (f-v'^2)/u'
543
_ff_set_one(u[3]);
544
sqr(t0,g3);
545
addt(t0,w6);
546
neg(u[2],t0); // u[2] = u''2 = -(w6+g3^2)
547
mult(t0,g2,g3);
548
dbl(t0);
549
mult(z0,w6,u[2]);
550
addt(z0,t0);
551
addt(z0,w2);
552
neg(u[1],z0);
553
#if ! HECURVE_SPARSE
554
addt(u[1],f[5]); // u[1] = u''1 = -(w2+w6u[2]+2g1g2) + f5
555
#endif
556
sqr(t0,g2);
557
mult(z0,g1,g3);
558
dbl(z0);
559
addt(z0,t0);
560
mult(t0,w6,u[1]);
561
addt(z0,t0);
562
mult(t0,w2,u[2]);
563
addt(z0,t0);
564
addt(z0,w1);
565
neg(u[0],z0);
566
#if ! HECURVE_SPARSE
567
addt(u[0],f[4]); // u[0] = u''0 = -(w1+w2u[2]+w6u[1] + 2g1g3+g2^2) + f4
568
#endif
569
/// dbg_printf ("u = x^3 + %lux^2 + %lux + %lu\n", u[2], u[1], u[0]);
570
571
// 10. Compute v'' = -v' mod u''
572
mult(t0,g3,u[2]);
573
sub(v[2],t0,g2); // v[2] = v''2 = g2+g3u[2]
574
mult(t0,g3,u[1]);
575
sub(v[1],t0,g1); // v[1] = v''1 = g1+g3u[1]
576
mult(t0,g3,u[0]);
577
sub(v[0],t0,g0); // v[0] = v'0 = g0+g3u[0]
578
/// dbg_printf ("v = %lux^2 + %lux + %lu\n", v[2], v[1], v[0]);
579
580
581
#if HECURVE_VERIFY
582
if ( ! hecurve_verify (u, v, f) ) {
583
err_printf ("hecurve_g3_square output verification failed for input:\n");
584
err_printf (" "); hecurve_print(u1,v1);
585
err_printf ("note that input may have been modified if output overlapped.\n");
586
exit (0);
587
}
588
#endif
589
590
return 1;
591
}
592
593
#endif
594
595