Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241852 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 smalljac. If not, see <http://www.gnu.org/licenses/>.
31
*/
32
33
#if HECURVE_GENUS == 2
34
35
static char buf[4096];
36
37
#define _deg_u(u) (_ff_nonzero(u[2])?2:(_ff_nonzero(u[1])?1:0))
38
#define _deg_v(v) (_ff_nonzero(v[1])?1:(_ff_nonzero(v[0])?0:-1))
39
#define _dbg_print_uv(s,u,v) if ( dbg_level >= DEBUG_LEVEL ) { printf (s); hecurve_print(u,v); }
40
41
void hecurve_g2_square_1 (ff_t u[3], ff_t v[2], ff_t u0, ff_t v0, ff_t f[6]);
42
void hecurve_g2_square_2_r0 (ff_t u[3], ff_t v[2], ff_t u1[3], ff_t v1[2], ff_t f[6]);
43
void hecurve_g2_compose_1_2 (ff_t u[3], ff_t v[2], ff_t u1[3], ff_t v1[2], ff_t u2[3], ff_t v2[2], ff_t f[6]);
44
int hecurve_g2_compose_special (ff_t u[3], ff_t v[2], ff_t u1[3], ff_t v1[2], ff_t u2[3], ff_t v2[3], ff_t f[6]);
45
46
/*
47
TODO: Clean up code to not use quite so many variables. Useful for debugging at the moment.
48
*/
49
// note that (u,v) may be equal to (u1,v1) or (u2,v2) but we assume overlap is aligned.
50
int hecurve_g2_compose (ff_t u[3], ff_t v[2], ff_t u1[3], ff_t v1[2], ff_t u2[3], ff_t v2[2], ff_t f[6], hecurve_ctx_t *ctx)
51
{
52
_ff_t_declare_reg r, inv0, inv1, w0, w1, w2, w3, w4, w5, s0, s1, t1, L0, L1, L2;
53
54
if ( ctx && ctx->state == 1 ) {
55
// get invert result and restore saved variables
56
_ff_set (w1, ctx->invert); // inverted value of r*s1
57
_ff_set (r, ctx->r);
58
_ff_set (s0, ctx->s0);
59
_ff_set (s1, ctx->s1);
60
_ff_set (inv1, ctx->inv1);
61
/// dbg_printf ("Restored r = %Zd, s1 = %Zd, s0 = %Zd, inv1 = %Zd, w1 = %Zd\n",_ff_wrap_mpz(r,0), _ff_wrap_mpz(s1,0), _ff_wrap_mpz(s0,0), _ff_wrap_mpz(inv1,0), _ff_wrap_mpz(w1,0));
62
goto hecurve_g2_compose_2_2_inverted;
63
}
64
if ( _ff_nonzero(f[4]) ) { hecurve_compose_cantor (u, v, u1, v1, u2, v2, f); return 1; } // revert to Cantor if f4 is non-zero - should only happen over F_5
65
if ( _ff_zero(u1[2]) || _ff_zero(u2[2]) ) { hecurve_g2_compose_special (u, v, u1, v1, u2, v2, f); return 1; }
66
#if ! HECURVE_FAST
67
dbg_printf ("Compose_2_2: (%Zdx^2+%Zdx+%Zd, %Zdx+%Zd) * (%Zdx^2+%Zdx+%Zd, %Zdx+%Zd)\n",
68
_ff_wrap_mpz(u1[2],0), _ff_wrap_mpz(u1[1],1), _ff_wrap_mpz(u1[0],2), _ff_wrap_mpz(v1[1],3), _ff_wrap_mpz(v1[0],4),
69
_ff_wrap_mpz(u2[2],5), _ff_wrap_mpz(u2[1],6), _ff_wrap_mpz(u2[0],7), _ff_wrap_mpz(v2[1],8), _ff_wrap_mpz(v2[0],9));
70
if ( !_ff_one(u1[2]) || !_ff_one(u2[2]) ) { err_printf ("u1 or u2 not monic deg 2 in hecurve_compose_2_2!\n"); exit (0); }
71
#endif
72
#if HECURVE_VERIFY
73
if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_compose: invalid input\n"); exit (0); }
74
if ( ! hecurve_verify (u2, v2, f) ) { err_printf ("hecurve_compose: invalid input\n"); exit (0); }
75
#endif
76
77
// 1. compute r = Resultant(u1,u2) and save z1=inv1 and z3=inv0
78
_ff_sub(inv1,u1[1],u2[1]); // reduce inv1
79
_ff_qsub(w0,u2[0],u1[0]); // w0 = z2 (unreduced)
80
_ff_multadd(inv0,u1[1],inv1,w0); // z3 = inv0 = u1[1]*inv1+w0 = u1[1]*z1+z2
81
_ff_mult(w1,inv1,inv1);
82
ff_mult(w1,w1,u1[0]);
83
_ff_multadd(r,w0,inv0,w1);
84
/// dbg_printf ("r = %Zd\n",_ff_wrap_mpz(r,0));
85
// if ( _ff_zero(r) ) { hecurve_compose_special (u, v, u1, v1, u2, v2, f); return 1; } this is checked below
86
87
// 2. compute almost inverse of u2 mod u1, i.e. inv = (r/u2) mod u1
88
// nothing to do, simply note that inv = inv1x + inv0, i.e. inv1 = z1 and inv0 = z3
89
/// dbg_printf ("inv = %Zdx + %Zd\n",_ff_wrap_mpz(inv1,0), _ff_wrap_mpz(inv0,1));
90
91
// 3. compute s' = rs = ((v1-v2)inv) mod u1
92
_ff_qsub(w0,v1[0],v2[0]);
93
_ff_mult(w2,inv0,w0);
94
_ff_qsub(w1,v1[1],v2[1]);
95
_ff_mult(w3,inv1,w1);
96
_ff_incmult(t1,u1[1],w3);
97
_ff_qadd (w4,inv0,inv1);
98
_ff_qadd (w5,w0,w1);
99
_ff_qnegsum(w0,w2,t1);
100
_ff_multadd(s1,w4,w5,w0);
101
_ff_mult(t1,u1[0],w3);
102
_ff_qsub(s0,w2,t1);
103
/// dbg_printf ("w0 = %Zd, w1 = %Zd, w2 = %Zd, w3 = %Zd, w4 = %Zd, w5 = %Zd, s\' = rs = %Zdx + %Zd\n",
104
/// _ff_wrap_mpz(w0,0), _ff_wrap_mpz(w1,1), _ff_wrap_mpz(w2,2), _ff_wrap_mpz(w3,3), _ff_wrap_mpz(w4,4), _ff_wrap_mpz(w5,5), _ff_wrap_mpz(s1,6), _ff_wrap_mpz(s0,7));
105
106
// Note that we need to save w3, w4, and w5, but w0, w1, and w2 are free
107
// if ( _ff_zero(s1) ) goto hecurve_compose_s1_zero; this is checked below
108
109
// 4. compute s'' = x+s0/s1 = x + s'0/s'1 and s1
110
_ff_mult(w2,r,s1); // assume r and s1 both non-zero - this is the usual case
111
if ( _ff_zero(w2) ) {
112
if ( _ff_nonzero(r) ) goto hecurve_g2_compose_s1_zero;
113
hecurve_g2_compose_special (u, v, u1, v1, u2, v2, f); return 1;
114
}
115
if ( ctx && ! ctx->state ) {
116
_ff_set (ctx->s0, s0);
117
_ff_set (ctx->s1, s1);
118
_ff_set (ctx->r, r);
119
_ff_set(ctx->inv1, inv1);
120
_ff_set (ctx->invert, w2); // return to let caller invert
121
ctx->state = 1;
122
return 0;
123
}
124
_ff_invert(w1,w2);
125
126
hecurve_g2_compose_2_2_inverted: // caller returns here after inverting
127
// we assume w1, r, s0, s1, and inv1 are set, all others free, s0 is unreduced, the rest are reduced
128
_ff_mult(w2,w1,r);
129
_ff_square(w3,s1);
130
ff_mult(w3,w3,w1);
131
_ff_mult(w4,r,w2);
132
_ff_square(w5,w4);
133
_ff_mult(s0,s0,w2);
134
/// dbg_printf ("s\'\' = x + %Zd, s1 = %Zd\n",_ff_wrap_mpz(s0,0), _ff_wrap_mpz(w3,1));
135
136
// 5. compute L = s''0*u2 = x^3 + L2*x^2 + L1*x + L0
137
_ff_qadd(L2,u2[1],s0); // ok to leave unreduced
138
_ff_multadd(L1,u2[1],s0,u2[0]);
139
_ff_mult(L0,u2[0],s0);
140
/// dbg_printf ("L = x^3 + %Zdx^2 + %Zdx + %Zd\n",_ff_wrap_mpz(L2,0), _ff_wrap_mpz(L1,1), _ff_wrap_mpz(L0,2));
141
142
// 6. compute u = (s(L+2v2)-t)/u1 = x^2 + u[1]*x + u[0] note h = 0
143
_ff_qsub(w0,s0,u1[1]);
144
_ff_qsub(w1,s0,inv1);
145
_ff_mult(w2,w0,w1); // w2 = (s0-u1[1])(s0-inv1)
146
_ff_qadd(w1,u2[1],u2[1]);
147
_ff_qaddto(w1,inv1);
148
ff_mult(w1,w1,w5);
149
_ff_qaddto (w2,w1);
150
_ff_qneg(w1,u1[0]);
151
_ff_qaddto(w2,w1);
152
_ff_addto(w2,L1);
153
_ff_qadd(w0,v2[1],v2[1]);
154
_ff_multadd(u[0],w0,w4,w2); // potentially destroys u1[0] and u2[0]
155
// no mults to work with so we are better off reducing as we go to compute u[1]
156
_ff_add(w0,s0,s0);
157
_ff_subfrom(w0,inv1);
158
_ff_sub(u[1],w0,w5);
159
_ff_set_one(u[2]);
160
/// dbg_printf ("u = %Zdx^2 + %Zdx + %Zd\n",_ff_wrap_mpz(u[2],0), _ff_wrap_mpz(u[1],1), _ff_wrap_mpz(u[0],2));
161
162
// 7. compute v = (-(L+v2)mod u = v[1]*x + v[0] note h = 0
163
_ff_qsub(w1,L2,u[1]);
164
_ff_qsub(w0,u[0],L1);
165
_ff_multadd(w2,w1,u[1],w0);
166
_ff_qneg(w0,v2[1]);
167
_ff_multadd (v[1],w2,w3,w0);
168
_ff_qneg(w0,L0);
169
_ff_multadd(w2,w1,u[0],w0);
170
_ff_qneg(w0,v2[0]);
171
_ff_multadd(v[0],w2,w3,w0);
172
/// dbg_printf ("v = %Zdx + %Zd\n",_ff_wrap_mpz(v[1],0), _ff_wrap_mpz(v[0],1));
173
#if ! HECURVE_FAST
174
_dbg_print_uv ("Compose_2 Result: ", u, v);
175
#endif
176
#if HECURVE_VERIFY
177
if ( ! hecurve_verify (u, v, f) ) {
178
err_printf ("hecurve_compose output verification failed for inputs:\n");
179
err_printf (" "); hecurve_print(u1,v1);
180
err_printf (" "); hecurve_print(u2,v2);
181
err_printf ("note that inputs have been modified if output overlapped.\n");
182
exit (0);
183
}
184
#endif
185
return 1;
186
187
// Special case is not optimized
188
hecurve_g2_compose_s1_zero:
189
/// dbg_printf ("Special case, s\'\'1 == 0\n");
190
191
// 4'. compute s
192
_ff_invert(inv0,r);
193
ff_mult(s0,s0,inv0);
194
/// dbg_printf ("s = %Zd\n",_ff_wrap_mpz(s0,0));
195
196
// Part of 6' moved here incase u2[0] gets overwritten below
197
_ff_mult(w2,u2[0],s0);
198
_ff_addto(w2,v2[0]);
199
200
// 5'. compute u = (t-s(L+2v2))/u1 = x + u[0] note h = 0
201
_ff_square(w1,s0);
202
_ff_addto(w1,u2[1]);
203
_ff_addto(w1,u1[1]);
204
_ff_neg(u[0],w1); // this potentially destroys u1[0] and u2[0], we assume u2[1] is ok
205
/// dbg_printf ("u = x + %Zd\n",_ff_wrap_mpz(u[0],0));
206
207
// 6. compute v = -(L+v2) mod u = v[0] note h = 0
208
_ff_sub (w1,u2[1],u[0]); // BUG FIX - handbook has w1 = s0(u21+u[0]) (+ SHOULD BE -)
209
ff_mult(w1,w1,s0);
210
_ff_addto(w1,v2[1]);
211
ff_mult(w1,w1,u[0]);
212
_ff_sub(v[0],w1,w2);
213
_ff_set_zero(v[1]);
214
215
_ff_set_zero(u[2]); _ff_set_one(u[1]); // set these last to avoid overlap issues
216
217
/// dbg_printf ("v = %Zd\n",_ff_wrap_mpz(v[0],0));
218
#if ! HECURVE_FAST
219
_dbg_print_uv ("Compose_2 Result: ", u, v);
220
#endif
221
#if HECURVE_VERIFY
222
if ( ! hecurve_verify (u, v, f) ) {
223
err_printf ("hecurve_compose output verification failed for inputs:\n");
224
err_printf (" "); hecurve_print(u1,v1);
225
err_printf (" "); hecurve_print(u2,v2);
226
err_printf ("note that inputs have been modified if output overlapped.\n");
227
exit (0);
228
}
229
#endif
230
return 1;
231
}
232
233
234
int hecurve_g2_square (ff_t u[3], ff_t v[2], ff_t u1[3], ff_t v1[2], ff_t f[6], hecurve_ctx_t *ctx)
235
{
236
_ff_t_declare_reg w0, w1, w2, w3, w4, w5, inv0, inv1, L0, L1, L2, r, s0, s1, t0, t1;
237
238
#if ! HECURVE_FAST
239
_dbg_print_uv ("Square_2: ", u, v);
240
#endif
241
#if HECURVE_VERIFY
242
if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_square: invalid input\n"); exit (0); }
243
#endif
244
245
if ( ctx && ctx->state == 1 ) {
246
// get invert result and restore saved variables
247
_ff_set (w1, ctx->invert); // inverted value of r*s1
248
_ff_set (r, ctx->r);
249
_ff_set (s0, ctx->s0);
250
_ff_set (s1, ctx->s1);
251
/// dbg_printf ("Restored r = %Zd, s1 = %Zd, s0 = %Zd, w1 = %Zd\n",_ff_wrap_mpz(r,0), _ff_wrap_mpz(s1,1), _ff_wrap_mpz(s0,2), _ff_wrap_mpz(w1,3));
252
goto hecurve_g2_square_2_2_inverted;
253
}
254
if ( _ff_nonzero(f[4]) ) { hecurve_compose_cantor (u, v, u1, v1, u1, v1, f); return 1; } // revert to Cantor if f4 is non-zero - should only happen over F_5
255
if ( _ff_zero(u1[2]) ) { hecurve_g2_square_1 (u, v, u1[0], v1[0], f); return 1; }
256
257
// 1. compute v' = 2v mod u = v1*x + v0 note h = 0, we use w5=~v1, inv0=~v0
258
_ff_add(w5,v1[1],v1[1]); // w5 gets negated below, must be reduced
259
_ff_qadd(inv0,v1[0],v1[0]);
260
/// dbg_printf ("2v = %Zdx + %Zd\n",_ff_wrap_mpz(w5,0), _ff_wrap_mpz(inv0,1));
261
262
// 2. compute resultant r = Resultant(2v,u)
263
_ff_square(w0,v1[1]);
264
_ff_square(w1,u1[1]);
265
_ff_qadd(w2,w0,w0);
266
_ff_qadd(w2,w2,w2);
267
_ff_mult(w3,u1[1],w5);
268
_ff_qsub(w4,inv0,w3);
269
ff_mult(w4,w4,inv0);
270
_ff_multadd(r,u1[0],w2,w4);
271
// _ff_addto(r,w4);
272
/// dbg_printf ("w0 = %Zd, w1 = %Zd, w2 = %Zd, w3 = %Zd, w4 = %Zd r = res(2v,u) = %Zd\n",
273
/// _ff_wrap_mpz(w0,0), _ff_wrap_mpz(w1,1), _ff_wrap_mpz(w2,2), _ff_wrap_mpz(w3,3), _ff_wrap_mpz(w4,4), _ff_wrap_mpz(r,5));
274
// if ( _ff_zero(r) ) { hecurve_square_2_r0 (u, v, u1, v1, f); return 1; } handled below
275
276
// 3. compute almost inverse invv = r*inv
277
_ff_neg(inv1,w5);
278
_ff_subfrom(inv0,w3);
279
/// dbg_printf ("inv = %Zdx + %Zd\n", _ff_wrap_mpz(inv1,0), _ff_wrap_mpz(inv0,1));
280
281
// 4. compute t = ((f-v^2)/u) mod u = tt1*x+tt0 note h = 0
282
// this code could be improved further when f[3] == 0
283
#if HECURVE_SPARSE
284
_ff_set (w3,w1); // this could be further optimized
285
#else
286
_ff_add(w3,f[3],w1);
287
#endif
288
_ff_add(w4,u1[0],u1[0]);
289
_ff_qadd(t1,w1,w1);
290
_ff_qaddto(t1,w3);
291
_ff_qsubfrom(t1,w4);
292
_ff_qadd(t0,w4,w4);
293
_ff_qsubfrom(t0,w3);
294
_ff_qneg(w5,w0);
295
_ff_multadd(t0,t0,u1[1],w5);
296
#if ! HECURVE_SPARSE
297
_ff_addto(t0,f[2]);
298
#endif
299
/// dbg_printf ("t = %Zdx + %Zd\n", _ff_wrap_mpz(t1,0), _ff_wrap_mpz(t0,1));
300
301
// 5. compute ss = (tt*invv) mod u
302
_ff_mult(w0,t0,inv0);
303
_ff_mult(w1,t1,inv1);
304
_ff_add(s1,inv0,inv1); // need s1 reduced to keep mult from getting too big
305
_ff_add(w2,t0,t1);
306
_ff_qneg(w5,w0);
307
_ff_multadd(s1,s1,w2,w5);
308
_ff_incmult(w2,u1[1],w1);
309
_ff_qsubfrom(s1,w2);
310
_ff_mult(w5,w1,u1[0]);
311
_ff_qsub(s0,w0,w5);
312
/// dbg_printf ("s' = %Zdx + %Zd\n",_ff_wrap_mpz(s1,0), _ff_wrap_mpz(s0,1));
313
// if ( _ff_zero(s1) ) goto hecurve_square_s1_zero; handled below
314
315
// 6. compute s'' = x + s0/s1 and s1
316
_ff_mult(w0,r,s1); // assume non-zero r and s1 is usual case
317
if ( _ff_zero(w0) ) {
318
if ( _ff_nonzero(r) ) goto hecurve_g2_square_s1_zero;
319
hecurve_g2_square_2_r0 (u, v, u1, v1, f);
320
return 1;
321
}
322
if ( ctx && ! ctx->state ) {
323
_ff_set (ctx->s0, s0);
324
_ff_set (ctx->s1, s1);
325
_ff_set (ctx->r, r);
326
_ff_set (ctx->invert, w0);
327
ctx->state = 1; // return to let caller invert
328
return 0;
329
}
330
_ff_invert(w1,w0);
331
332
hecurve_g2_square_2_2_inverted: // caller returns here after inverting
333
// we assume w0, s0, s1, and r are set and everything else is free
334
_ff_mult(w2,w1,r);
335
_ff_square(w3,s1);
336
ff_mult(w3,w3,w1);
337
_ff_mult(w4,w2,r);
338
_ff_square(w5,w4);
339
ff_mult(s0,s0,w2);
340
/// dbg_printf ("s\'\'0 = %Zd, w0 = %Zd, w1 = %Zd, w2 = %Zd, w3 = %Zd, w4 = %Zd, w5 = %Zd\n",
341
/// _ff_wrap_mpz(s0,0), _ff_wrap_mpz(w0,1), _ff_wrap_mpz(w1,2), _ff_wrap_mpz(w2,3), _ff_wrap_mpz(w3,4), _ff_wrap_mpz(w4,5), _ff_wrap_mpz(w5,6));
342
// note that w3, w4, and w5, need to be saved, but w0, w1 and w2 are free
343
344
// 7. compute LL = sss*u = x^3 + LL2*x^2 + LL1*x + LL0
345
_ff_qadd(L2,s0,u1[1]);
346
_ff_multadd(L1,s0,u1[1],u1[0]);
347
_ff_mult(L0,s0,u1[0]);
348
/// dbg_printf ("L' = s''u = x^3 + %Zdx^2 + %Zdx + %Zd\n",_ff_wrap_mpz(L2,0), _ff_wrap_mpz(L1,1), _ff_wrap_mpz(L0,2));
349
350
// 8. compute u = s^2 + 2vs/u + (v^2-f)/u1^2 note h = 0
351
_ff_square(w0,s0);
352
_ff_qadd(w1,v1[1],v1[1]);
353
ff_mult(w1,w1,w4);
354
_ff_qaddto(w0,w1);
355
_ff_qadd(w1,u1[1],u1[1]);
356
_ff_multadd(u[0],w1,w5,w0); // potentially destroys u1[0] and u2[0]
357
_ff_add(w0,s0,s0); // no mult to absorb so stay reduced
358
_ff_sub(u[1],w0,w5); // potentially destroys u1[1] and u2[1]
359
_ff_set_one(u[2]);
360
/// dbg_printf ("u = x^2 + %Zdx + %Zd\n",_ff_wrap_mpz(u[1],0), _ff_wrap_mpz(u[0],1));
361
362
// 9. compute v = -(L+v1) mod u = v[1]x + v[0] note h = 0
363
_ff_qsub(w1,L2,u[1]);
364
_ff_qsub (w0,u[0],L1);
365
_ff_multadd(w2,w1,u[1], w0);
366
_ff_qneg(w0,v1[1]); // v1[1] could overlap v[1]
367
_ff_multadd(v[1],w2,w3,w0);
368
_ff_qneg(w0,L0);
369
_ff_multadd(w2,w1,u[0],w0);
370
_ff_qneg(w0,v1[0]); // v1[0] could overlap v[0]
371
_ff_multadd(v[0],w2,w3,w0);
372
/// dbg_printf ("v = %Zdx + %Zd\n",_ff_wrap_mpz(v[1],0), _ff_wrap_mpz(v[0],1));
373
#if HECURVE_VERIFY
374
if ( ! hecurve_verify (u, v, f) ) {
375
err_printf ("hecurve_square: output verification failed for inputs:\n");
376
err_printf (" "); hecurve_print(u1,v1);
377
err_printf ("note that input has been modified if output overlapped.\n");
378
exit (0);
379
}
380
#endif
381
return 1;
382
383
hecurve_g2_square_s1_zero:
384
/// dbg_printf ("Special case, s'1 == 0\n");
385
// 6'. compute s and precomputations
386
_ff_invert(w1,r);
387
ff_mult(s0,s0,w1);
388
_ff_mult(w2,s0,u1[0]);
389
_ff_addto(w2,v1[0]);
390
/// dbg_printf ("w1 = %Zd, w2 = %Zd, s0 = %Zd\n",_ff_wrap_mpz(w1,0), _ff_wrap_mpz(w2,1), _ff_wrap_mpz(s0,2));
391
392
// 7'. compute u' = (f-v^2)/u^2 - 2vs/u - s^2 note h =0
393
_ff_square(w3,s0);
394
_ff_add(w4,u1[1],u1[1]);
395
_ff_addto(w3,w4);
396
_ff_neg(u[0],w3); // potentially destroys u1[0] and u2[0]
397
/// dbg_printf ("u = x + %Zd\n",_ff_wrap_mpz(u[0],0));
398
399
// 8'. compute v' = -(su+v) mod u
400
_ff_sub(w1,u1[1],u[0]);
401
ff_mult(w1,w1,s0);
402
_ff_addto(w1,v1[1]);
403
ff_mult(w1,w1,u[0]);
404
_ff_sub(v[0],w1,w2);
405
_ff_set_zero(v[1]);
406
/// dbg_printf ("v = %Zd\n",_ff_wrap_mpz(v[0],0));
407
408
_ff_set_one(u[1]); // set these last in case of overlap
409
_ff_set_zero(u[2]);
410
#if HECURVE_VERIFY
411
if ( ! hecurve_verify (u, v,f) ) {
412
err_printf ("hecurve_square output: verification failed for inputs:\n");
413
err_printf (" "); hecurve_print(u1,v1);
414
err_printf ("note that input has been modified if output overlapped.\n");
415
exit (0);
416
}
417
#endif
418
return 1;
419
}
420
421
// Note that (u,v) == (u1,v1) or (u2,v2) (or both) are possible. We do assume that any overlap is aligned.
422
// Thus modifying u[1] shouldn't effect u1[0] or u2[0] but may destory u1[1] and/or u2[1]
423
//
424
// This algorithm handles all the unusual cases - it assumes that either u1 or u2 has degree < 2
425
// or that Resultant(u1,u2) = 0, otherwise hecurve_compose would have handled it
426
int hecurve_g2_compose_special (ff_t u[3], ff_t v[2], ff_t u1[3], ff_t v1[2], ff_t u2[3], ff_t v2[3], ff_t f[6])
427
{
428
_ff_t_declare_reg t1, t2, t3, r;
429
_ff_t_declare *swap;
430
int d1, d2, swapd, sts;
431
432
#if ! HECURVE_FAST
433
dbg_printf ("Compose Special: (%Zdx^2+%Zdx+%Zd, %Zdx+%Zd) * (%Zdx^2+%Zdx+%Zd, %Zdx+%Zd)\n",
434
_ff_wrap_mpz(u1[2],0), _ff_wrap_mpz(u1[1],1), _ff_wrap_mpz(u1[0],2), _ff_wrap_mpz(v1[1],3), _ff_wrap_mpz(v1[0],4),
435
_ff_wrap_mpz(u2[2],5), _ff_wrap_mpz(u2[1],6), _ff_wrap_mpz(u2[0],7), _ff_wrap_mpz(v2[1],8), _ff_wrap_mpz(v2[0],9));
436
#endif
437
#if HECURVE_VERIFY
438
if ( ! hecurve_verify (u1, v1, f) ) { err_printf ("hecurve_compose_special: invalid input\n"); exit (0); }
439
if ( ! hecurve_verify (u2, v2, f) ) { err_printf ("hecurve_compose_special: invalid input\n"); exit (0); }
440
#endif
441
d1 = _deg_u(u1);
442
d2 = _deg_u(u2);
443
if ( d1 > d2 ) {
444
swap = u2; u2 = u1; u1 = swap;
445
swap = v2; v2 = v1; v1 = swap;
446
swapd = d2; d2 = d1; d1 = swapd;
447
/// dbg_printf ("swapped u1 = x + %Zd, v1 = %Zd.\n",_ff_wrap_mpz(u1[0],0), _ff_wrap_mpz(v1[0],1));
448
/// dbg_printf ("swapped u2 = x^2 + %Zdx + %Zd, v2 = %Zdx + %Zd.\n",
449
/// _ff_wrap_mpz(u2[1],0), _ff_wrap_mpz(u2[0],1), _ff_wrap_mpz(v2[1],2), _ff_wrap_mpz(v2[0],3));
450
}
451
switch(d1){
452
case 0: // deg u1 == 0, i.e. u1 is the identity
453
/// dbg_printf ("Case 1, deg(u1) == 0\n");
454
_hecurve_set (u, v, u2, v2);
455
break;
456
case 1: // deg u1 == 1
457
// case 2
458
/// dbg_printf ("Case 2, deg(u1) == 1\n");
459
if ( d2 == 1 ) { // deg u1 == dege u2 == 1
460
/// dbg_printf ("Case 2.A, deg(u1) == deg(u2) == 1\n");
461
// case 2.A
462
if ( _ff_equal(u1[0],u2[0]) && _ff_equal(u1[1],u2[1]) ) {
463
if ( _ff_zero(v1[0]) && _ff_zero(v2[0]) ) {
464
/// dbg_printf ("Case 2.A.i.a D1 == -D2 == D1\n");
465
_hecurve_set_identity(u,v);
466
break;
467
}
468
_ff_neg(t1,v2[0]);
469
if ( _ff_equal(v1[0],t1) ) {
470
/// dbg_printf ("Case 2.A.i.b D1 == -D2\n");
471
_hecurve_set_identity(u,v);
472
break;
473
}
474
if ( _ff_equal(v1[0],v2[0]) ) {
475
/// dbg_printf ("Case 2.A.ii D1 == D2\n");
476
hecurve_g2_square_1 (u, v, u1[0], v1[0], f);
477
break;
478
}
479
}
480
/// dbg_printf ("Case 2.A.iii D1 != +- D2\n");
481
if ( _ff_equal(u1[0],u2[0]) ) { err_printf ("u1[0] == u2[0] in case 2.A.iii of hecurve_compose!\n"); exit(0); }
482
483
// u = u1*u2 and v = ((v2-v1)x+v2u1[0]-v1u2[0])/(u1[0]-u2[0]) note that v1 and v2 are constants (deg 0)
484
_ff_sub(t1,u1[0],u2[0]);
485
ff_invert(t1,t1);
486
_ff_sub(t2,v2[0],v1[0]);
487
_ff_mult(v[1],t2,t1); // we assume writing [1] doesn't hurt [0]
488
_ff_mult(t2,v2[0],u1[0]);
489
_ff_mult(t3,v1[0],u2[0]);
490
_ff_subfrom(t2,t3);
491
_ff_mult(v[0],t2,t1);
492
_ff_set_one(u[2]); // update u last to handle overlap
493
_ff_add(u[1],u1[0],u2[0]); // we assume writing [1] doesn't hurt [0]
494
ff_mult(u[0],u1[0],u2[0]); // mult should be safe
495
break;
496
} else { // deg u1 == 1, deg u2 == 2
497
/// dbg_printf ("Case 2.B, deg(u1) == 1, deg(u2) == 2\n");
498
// compute u2(-u1[0]) = (-u1[0])(-u1[0] + u2[1]) + u2[0]
499
_ff_neg(t1,u1[0]); // save t1 = -u1[0] for later
500
_ff_add(t2,t1,u2[1]);
501
ff_mult(t2,t2,t1);
502
_ff_addto(t2,u2[0]);
503
if ( _ff_nonzero(t2) ) {
504
/// dbg_printf ("Case 2.B.i, u2(-u1[0]) != 0\n");
505
hecurve_g2_compose_1_2 (u, v, u1, v1, u2, v2, f);
506
break;
507
}
508
/// dbg_printf ("Case 2.B.ii\n");
509
_ff_add(t2,u1[0],u1[0]);
510
if ( _ff_equal(u2[1],t2) ) {
511
_ff_square(t2,u1[0]);
512
if ( _ff_equal(u2[0],t2) ) {
513
/// dbg_printf ("Case 2.B.ii.a, u2[1] == 2u1[0] and u2[0] == u1[0]^2\n");
514
// compute v2(-u1[0])
515
_ff_mult(t2,v2[1],t1);
516
_ff_addto(t2,v2[0]);
517
if ( _ff_equal(t2,v1[0]) ) {
518
_ff_t_declare_dynamic u3[3], v3[2], v4[2];
519
520
// this is expensive, but this is a special case - may optimize later to handle recursion more elegantly
521
_ff_init(u3[0]); _ff_init(u3[1]); _ff_init(u3[2]);
522
_ff_init(v3[0]); _ff_init(v3[1]); _ff_init(v4[0]); _ff_init(v4[1]);
523
524
/// dbg_printf ("Case 2.B.ii.a.I D2 = 2D1\n");
525
// Double D2 then subtract D1
526
// this is slightly inefficient but easier and is a rare case anyway
527
hecurve_square (u3, v3, u2, v2, f, 0); // double D2
528
// Bug fix - need to avoid infinite recursion on order 3 elements, this occurs when 2D2 == -D2
529
if ( _ff_equal(u3[0],u2[0]) && _ff_equal(u3[1],u2[1]) && _ff_equal(u3[2],u2[2]) ) {
530
_ff_neg(t2,v2[0]);
531
_ff_neg(t3,v2[1]);
532
if ( _ff_equal(v3[0],t2) && _ff_equal(v3[1],t3) ) {
533
hecurve_compose_cantor (u, v, u1, v1, u2, v2, f);
534
break;
535
// err_printf ("Attempt to compute 2D+D for D with order 6 - unable to handle this case\n");
536
// exit (0);
537
}
538
}
539
/// dbg_printf ("2D2 != -2D1, computing 2D2-D1\n");
540
_ff_neg(v4[0],v1[0]);
541
_ff_neg(v4[1],v1[1]); // D4 = invert D1, note u4 = u1
542
hecurve_compose (u, v, u1, v4, u3, v3, f, 0); // compute D2+D2-D1
543
_ff_clear(u3[0]); _ff_clear(u3[1]); _ff_clear(u3[2]);
544
_ff_clear(v3[0]); _ff_clear(v3[1]); _ff_clear(v4[0]); _ff_clear(v4[1]);
545
} else {
546
/// dbg_printf ("Case 2.B.ii.a.II, D2 = -2P1\n");
547
_hecurve_set (u, v, u1, v1);
548
hecurve_invert (u, v); // compute inverse of D1
549
}
550
break;
551
}
552
} else {
553
/// dbg_printf ("Case 2.B.ii.b, u2[1] != 2u1[0] or u2[0] != u1[0]^2\n");
554
// compute -v2(-u1[0]) - this is a bug fix - p. 314/315 of handbook uses v2(-u1[0]) (or not)
555
_ff_mult(t3,v2[1],t1); // t1 = -u1[0]
556
_ff_addto(t3,v2[0]);
557
_ff_neg(t2,t3);
558
// we need to compute v2(u1[0]-u2[1]) either way
559
_ff_sub(t3,u1[0],u2[1]);
560
ff_mult(t3,t3,v2[1]);
561
_ff_addto(t3,v2[0]);
562
/// dbg_printf ("t3 = v2[1]*(u1[0]-u2[1]) + v2[0] = %Zd\n",_ff_wrap_mpz(t3,0));
563
if ( _ff_equal(t2,v1[0]) ) {
564
/// dbg_printf ("Case 2.B.ii.b.I, -P1 occurs in D2\n");
565
_ff_add(u[0],u2[1],t1); // t1 = -u1[0]
566
_ff_set_zero(u[2]); _ff_set_one(u[1]); // u[1] must get set here, could destory u2[1]
567
_ff_set_zero(v[1]);
568
_ff_set(v[0],t3);
569
} else {
570
_ff_t_declare_dynamic u3[3], v3[2], u4[3], v4[2];
571
572
// this is expensive, but this is a special case - may optimize later to handle recursion more elegantly
573
_ff_init(u3[0]); _ff_init(u3[1]); _ff_init(u3[2]); _ff_init(v3[0]); _ff_init(v3[1]);
574
_ff_init(u4[0]); _ff_init(u4[1]); _ff_init(u4[2]); _ff_init(v4[0]); _ff_init(v4[1]);
575
576
/// dbg_printf ("Case 2.B.ii.b.II, Doubling D1 and composing with (x+u21-u10, v2(u10-u21)),\n");
577
hecurve_g2_square_1 (u3, v3, u1[0], v1[0], f);
578
_ff_set_zero(u4[2]); _ff_set_one(u4[1]);
579
_ff_sub(u4[0],u2[1],u1[0]);
580
_ff_set_zero(v4[1]);
581
_ff_set(v4[0],t3);
582
hecurve_compose (u, v, u4, v4, u3, v3, f, 0);
583
_ff_clear(u3[0]); _ff_clear(u3[1]); _ff_clear(u3[2]); _ff_clear(v3[0]); _ff_clear(v3[1]);
584
_ff_clear(u4[0]); _ff_clear(u4[1]); _ff_clear(u4[2]); _ff_clear(v4[0]); _ff_clear(v4[1]);
585
}
586
}
587
}
588
break;
589
case 2: // deg u1 == deg u2 == 2 (case 3)
590
/// dbg_printf ("Case 3, deg(u1) == deg(u2) == 2\n");
591
if ( _ff_equal(u1[0],u2[0]) && _ff_equal(u1[1],u2[1]) ) {
592
/// dbg_printf ("Case 3.A, u1 == u2\n");
593
if ( _ff_equal(v1[1],v2[1]) && _ff_equal(v1[0],v2[0]) ) {
594
// catch inverse case for order 2 elements
595
if ( _ff_zero(v1[1]) && _ff_zero(v1[0]) ) {
596
/// dbg_printf ("Case 3.A.i*, v1 == -v2 == 0\n");
597
_hecurve_set_identity (u, v);
598
break;
599
}
600
/// dbg_printf ("Case 3.A.ii, v1 == v2\n");
601
hecurve_square (u, v, u1, v1, f, 0); // handles case 3.A.ii.b (zero resultant) also
602
break;
603
}
604
_ff_neg(t1,v2[0]);
605
_ff_neg(t2,v2[1]);
606
if ( _ff_equal(v1[0],t1) && _ff_equal(v1[1],t2) ) {
607
/// dbg_printf ("Case 3.A.i, v1 == -v2\n");
608
_hecurve_set_identity (u, v);
609
break;
610
}
611
/// dbg_printf ("Case 3.A.iii v1 != +- v2\n");
612
// case 3.A.iii
613
_ff_sub(t1,v2[1],v1[1]);
614
#if ! HECURVE_FAST
615
if ( _ff_zero(t1) ) { err_printf ("v2[1] == v1[1] in case 3.A.iii of hecurve_compose_special\n"); exit (0); }
616
#endif
617
_ff_invert(t2,t1);
618
_ff_sub(t1,v1[0],v2[0]);
619
ff_mult(t1,t1,t2);
620
_ff_neg(t2,t1);
621
_ff_mult(t3,v1[1],t1);
622
_ff_addto(t3,v1[0]);
623
hecurve_g2_square_1 (u, v, t2, t3, f);
624
} else { // u1 != u2
625
/// dbg_printf ("Case 3.B, u1 != u2\n");
626
// case 3.B
627
// We can assume Resultant(u1,u2) == 0, since otherwise we wouldn't have been called
628
_ff_t_declare_dynamic x2, y2, x3, y3;
629
630
// this is expensive, but this is a special case - may optimize later to handle recursion more elegantly
631
_ff_init(x2); _ff_init(x3);
632
_ff_init(y2); _ff_init(y3);
633
634
/// dbg_printf ("Case 3.B.ii, res(u1,u2) == 0\n");
635
// need to compute gcd(u1,u2) = x-x1 where x1 = (u1[1]-u2[1])/(u2[0]-u1[0]))
636
_ff_sub(t1,u1[1],u2[1]);
637
#if ! HECURVE_FAST
638
if ( _ff_zero(t1) ) { err_printf ("u1[1] == u2[1] in case 3.B.ii of hecurve_compose_special\n"); exit (0); }
639
#endif
640
_ff_invert(t2,t1);
641
_ff_sub(t1,u2[0],u1[0]);
642
_ff_mult(t3,t1,t2);
643
/// dbg_printf ("gcd(u1,u2) = x-%Zd\n", _ff_wrap_mpz(t3,0));
644
// compute v1(x1) and v2(x1) and compare
645
_ff_mult(t1,v1[1],t3);
646
_ff_addto(t1,v1[0]);
647
_ff_mult(t2,v2[1],t3);
648
_ff_addto(t2,v2[0]);
649
// Need to extract coords of P2 and P3 in either case, so compute them here
650
// This code could be cleaned up a bit - there is some double negation, but it is a special case...
651
_ff_add(y2,u1[1],t3);
652
_ff_neg(x2,y2);
653
_ff_mult(y2,v1[1],x2);
654
_ff_addto(y2,v1[0]);
655
_ff_add(y3,u2[1],t3);
656
_ff_neg(x3,y3);
657
_ff_mult(y3,v2[1],x3);
658
_ff_addto(y3,v2[0]);
659
/// dbg_printf ("P2 = (%Zd,%Zd), P3 = (%Zd,%Zd)\n", _ff_wrap_mpz(x2,0), _ff_wrap_mpz(y2,1), _ff_wrap_mpz(x3,2), _ff_wrap_mpz(y3,3));
660
if ( _ff_equal(t1,t2) ) {
661
_ff_t_declare_dynamic u3[3], v3[2], u4[3], v4[2], u5[3], v5[2];
662
663
// this is expensive, but this is a special case - may optimize later to handle recursion more elegantly
664
_ff_init(u3[0]); _ff_init(u3[1]); _ff_init(u3[2]); _ff_init(v3[0]); _ff_init(v3[1]);
665
_ff_init(u4[0]); _ff_init(u4[1]); _ff_init(u4[2]); _ff_init(v4[0]); _ff_init(v4[1]);
666
_ff_init(u5[0]); _ff_init(u5[1]); _ff_init(u5[2]); _ff_init(v5[0]); _ff_init(v5[1]);
667
668
/// dbg_printf ("Case 3.B.ii.a, v1(x1) == v2(x1)\n");
669
_ff_neg(t1,t3);
670
_ff_mult(t2,v1[1],t3);
671
_ff_add(t2,t2,v1[0]);
672
hecurve_g2_square_1 (u4, v4, t1, t2, f); // D' = 2(P1)
673
/// dbg_printf ("D' = (%Zdx^2 + %Zdx + %Zd, %Zdx + %Zd)\n",_ff_wrap_mpz(u4[2],0), _ff_wrap_mpz(u4[1],1), _ff_wrap_mpz(u4[0],2), _ff_wrap_mpz(v4[1],3), _ff_wrap_mpz(v4[0],4));
674
// could we use hecurve_compose_1_2 here?
675
_ff_set_zero(u3[2]); _ff_set_one(u3[1]);
676
_ff_neg(u3[0],x2);
677
_ff_set_zero(v3[1]);
678
_ff_set(v3[0],y2);
679
hecurve_compose (u5, v5, u3, v3, u4, v4, f, 0); // D'' = D' + (P2)
680
/// dbg_printf ("D'' = (%Zdx^2 + %Zdx + %Zd, %Zdx + %Zd)\n",_ff_wrap_mpz(u5[2],0), _ff_wrap_mpz(u5[1],1), _ff_wrap_mpz(u5[0],2), _ff_wrap_mpz(v5[1],3), _ff_wrap_mpz(v5[0],4));
681
_ff_neg(u3[0],x3);
682
_ff_set(v3[0],y3);
683
hecurve_compose (u, v, u3, v3, u5, v5, f, 0); // D = D'' + (P3)
684
_ff_clear(u3[0]); _ff_clear(u3[1]); _ff_clear(u3[2]); _ff_clear(v3[0]); _ff_clear(v3[1]);
685
_ff_clear(u4[0]); _ff_clear(u4[1]); _ff_clear(u4[2]); _ff_clear(v4[0]); _ff_clear(v4[1]);
686
_ff_clear(u5[0]); _ff_clear(u5[1]); _ff_clear(u5[2]); _ff_clear(v5[0]); _ff_clear(v5[1]);
687
} else {
688
/// dbg_printf ("Case 3.B.ii.a, v1(x1) != v2(x1)\n");
689
hecurve_make_2 (u, v, x2, y2, x3, y3);
690
}
691
_ff_clear(x2); _ff_clear(x3);
692
_ff_clear(y2); _ff_clear(y3);
693
}
694
break;
695
default:
696
err_printf ("Invalid degree in hecurve_compose!\n"); exit (0);
697
}
698
#if ! HECURVE_FAST
699
_dbg_print_uv ("Compose Special Result: ", u, v);
700
#endif
701
#if HECURVE_VERIFY
702
if ( ! hecurve_verify (u, v, f) ) {
703
err_printf ("hecurve_compose_special output verification failed for inputs:\n");
704
err_printf (" "); hecurve_print(u1,v1);
705
err_printf (" "); hecurve_print(u2,v2);
706
err_printf ("note that inputs have been modified if output overlapped.\n");
707
exit (0);
708
}
709
#endif
710
return 1;
711
}
712
713
714
// Algorithm 14.20 p.318
715
// As above, handle aligned overlap of (u,v) with (u1,v1) and/or (u2,v2)
716
void hecurve_g2_compose_1_2 (ff_t u[3], ff_t v[2], ff_t u1[3], ff_t v1[2], ff_t u2[3], ff_t v2[2], ff_t f[6])
717
{
718
_ff_t_declare_reg r, inv, t1, t2, w1, L0, L1, s0;
719
720
/// dbg_printf ("Compose_1_2\n");
721
722
// 1. compute r = u2 mod u1
723
_ff_sub(w1,u2[1],u1[0]);
724
ff_mult(w1,w1,u1[0]);
725
_ff_sub(r,u2[0],w1);
726
/// dbg_printf ("r = %Zd\n",_ff_wrap_mpz(r,0));
727
728
// 2. compute inverse of u2 mod u1
729
_ff_invert(inv, r);
730
/// dbg_printf ("inv = %Zd\n",_ff_wrap_mpz(inv,0));
731
732
// 3. compute s = ((v1-v2)inv) mod u1
733
_ff_mult(w1,v2[1],u1[0]); // BUG FIX - handbook incorrectly uses -v2[1]u1[0] - should be positive
734
_ff_addto(w1,v1[0]);
735
_ff_subfrom(w1,v2[0]);
736
_ff_mult(s0,w1,inv);
737
/// dbg_printf ("s = %Zd\n", _ff_wrap_mpz(s0,0));
738
739
// 4. compute L = su2 = s0*x^2 + L1*x + L0
740
_ff_mult(L1,s0,u2[1]);
741
_ff_mult(L0,s0,u2[0]);
742
// no reduction required for L coeffs
743
/// dbg_printf ("L = su2 = %Zdx^2 + %Zdx + %Zd\n",_ff_wrap_mpz(s0,0), _ff_wrap_mpz(L1,1), _ff_wrap_mpz(L0,2));
744
745
// 5. compute t = (f - v2^2)/u2 = x^3 + t2*x2 + t1*x + t0 note h = 0
746
_ff_neg(t2,u2[1]);
747
_ff_square(t1,u2[1]);
748
_ff_subfrom(t1,u2[0]);
749
if ( _ff_nonzero(f[3]) ) _ff_addto(t1,f[3]);
750
/// dbg_printf ("t = x^3 + %Zdx^2 + %Zdx + t0\n",_ff_wrap_mpz(t2,0), _ff_wrap_mpz(t1,1));
751
752
// 6. compute u = (t-s(L+2v2))/u1 = x^2 + u[1]*x + u[0] note h = 0
753
_ff_set_one(u[2]);
754
_ff_square(r,s0);
755
_ff_sub(w1,t2,r);
756
_ff_sub(u[1],w1,u1[0]); // ther should be no overlap - potentially destroys u1[1] and u2[1]
757
_ff_add(w1,v2[1],v2[1]);
758
_ff_addto(w1,L1);
759
ff_mult(w1,w1,s0);
760
_ff_sub(r,t1,w1);
761
_ff_mult(t2,u1[0],u[1]);
762
_ff_sub(u[0],r,t2); // potentially destroys u1[0] and u2[0]
763
/// dbg_printf ("u = x^2 + %Zdx + %Zd\n",_ff_wrap_mpz(u[1],0), _ff_wrap_mpz(u[0],1));
764
765
// 7. compute v = (-(L+v2)) mod u = v[1]x + v[0] note h = 0
766
_ff_mult(w1,s0,u[1]);
767
_ff_subfrom(w1,L1);
768
_ff_subfrom(w1,v2[1]); // v2[1] could overlap v[1]
769
_ff_set (v[1],w1);
770
_ff_mult(w1,s0,u[0]);
771
_ff_subfrom(w1,L0);
772
_ff_subfrom(w1,v2[0]); // v2[0] could overlap v[0]
773
_ff_set(v[0],w1);
774
/// dbg_printf ("v = %Zdx + %Zd\n",_ff_wrap_mpz(v[1],0), _ff_wrap_mpz(v[0],1));
775
}
776
777
778
// This code would benefit from precomputing f' - todo later
779
// Note that overlap of u[0] and u0 (and v[0] and v0) is possible!
780
void hecurve_g2_square_1 (ff_t u[3], ff_t v[2], ff_t u0, ff_t v0, ff_t f[6])
781
{
782
_ff_t_declare_reg x, y, t1, t2, t3;
783
784
if ( _ff_zero(v0) ) { _hecurve_set_identity (u, v); return; }
785
// The code below corresponds to (14.9) on p. 314 of Handbook of E+HE Crypto
786
/// dbg_printf ("Square_1 (x + %Zd,%Zd)\n",_ff_wrap_mpz(u0,0),_ff_wrap_mpz(v0,0));
787
// u = u1^2
788
_ff_set (t3, u0); // save t3=u0 since we need it later and may overwrite it here.
789
_ff_set_one(u[2]);
790
_ff_add(u[1],t3,t3);
791
_ff_square(u[0],t3);
792
/// dbg_printf ("u = x^2 + %Zdx + %Zd\n",_ff_wrap_mpz(u[1],0), _ff_wrap_mpz(u[0],1));
793
// v = (f'(-u1[0])x + f'(-u1[0])u1[0])/(2v1) + v1
794
// Compute y = f'(-u1[0]) - note that this code assumes that 5* max coeff of f fits in an ff_t
795
_ff_neg(x,t3);
796
_ff_set(y,f[1]);
797
if ( _ff_nonzero(f[2]) ) {
798
_ff_add(t2,f[2],f[2]);
799
ff_mult(t2,t2,x);
800
_ff_addto(y,t2);
801
}
802
_ff_square(t1,x);
803
if ( _ff_nonzero(f[3]) ) {
804
_ff_add(t2,f[3],f[3]);
805
_ff_addto(t2,f[3]);
806
ff_mult(t2,t2,t1);
807
_ff_addto(y,t2);
808
}
809
#if FF_WORDS == 1
810
if ( _ff_p != 5 ) {
811
#endif
812
ff_square(t1,t1);
813
_ff_add(t2,t1,t1);
814
_ff_x2(t2);
815
_ff_addto(t2,t1);
816
_ff_addto(y,t2);
817
#if FF_WORDS == 1
818
}
819
#endif
820
/// dbg_printf ("f'(-u0) = %Zd\n",_ff_wrap_mpz(y,0));
821
_ff_add(t2,v0,v0);
822
_ff_invert(t1,t2);
823
_ff_mult(v[1],t1,y);
824
_ff_mult(t1,v[1],t3);
825
_ff_add(v[0],t1,v0);
826
/// dbg_printf ("v = %Zdx + %Zd\n",_ff_wrap_mpz(v[1],0), _ff_wrap_mpz(v[0],0));
827
}
828
829
/*
830
This algorithm handles squaring a degree 2 element where Resultant(2v,u) = 0.
831
In this case the divisor contains a point with order 2 and we simply want to square the other point.
832
This corresponds to case 3.A.ii.b in the general algorithm, but may also be detected in hecurve_square
833
*/
834
void hecurve_g2_square_2_r0 (ff_t u[3], ff_t v[2], ff_t u1[3], ff_t v1[2], ff_t f[6])
835
{
836
_ff_t_declare_reg t1, t2;
837
838
// Since h = 0, we simply need gcd(2v1, u1) which must be (x+v1[0]/v1[1]) hence x1 = -v1[0]/v1[1] is the x-coord of P1
839
// We want to then double P2 = (-u1[1]-x1,v1(-u1[1]-x1)) see p. 315 of the handbook
840
if ( _ff_zero(v1[1]) ) {
841
if ( _ff_zero(v1[0]) ) { _hecurve_set_identity (u, v); return; }
842
// this should be impossible if Results(u,2v) = 0
843
err_printf ("v1[1] = 0 and v1[0] != 0 in hecurve_square_2_r0!");
844
exit (0);
845
}
846
_ff_invert(t1,v1[1]);
847
_ff_neg(t2,v1[0]);
848
ff_mult(t1,t1,t2);
849
_ff_addto(t1,u1[1]);
850
_ff_neg(t2,t1);
851
ff_mult(t2,t2,v1[1]);
852
_ff_addto(t2,v1[0]);
853
hecurve_g2_square_1 (u, v, t1, t2, f);
854
}
855
856
857
#endif
858
859