@@ -82,11 +82,6 @@ struct Jacobian
82
82
var _Monty C [3 ];
83
83
};
84
84
85
- static final function CurveParams IdToCurve (EFCEllipticCurve Curve )
86
- {
87
- return default ._PP [Curve - FCEC_Secp256r1 ];
88
- };
89
-
90
85
/*
91
86
* We use a custom interpreter that uses a dozen registers, and
92
87
* only six operations:
@@ -145,6 +140,163 @@ static final function CurveParams IdToCurve(EFCEllipticCurve Curve)
145
140
`define T9 4
146
141
`define T10 5
147
142
143
+ /*
144
+ * Doubling formulas are:
145
+ *
146
+ * s = 4*x*y^2
147
+ * m = 3*(x + z^2)*(x - z^2)
148
+ * x' = m^2 - 2*s
149
+ * y' = m*(s - x') - 8*y^4
150
+ * z' = 2*y*z
151
+ *
152
+ * If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
153
+ * should. This case should not happen anyway, because our curves have
154
+ * prime order, and thus do not contain any point of order 2.
155
+ *
156
+ * If P is infinity (z = 0), then again the formulas yield infinity,
157
+ * which is correct. Thus, this code works for all points.
158
+ *
159
+ * Cost: 8 multiplications
160
+ */
161
+ var const array <int > CodeDouble ;
162
+
163
+ /*
164
+ * Additions formulas are:
165
+ *
166
+ * u1 = x1 * z2^2
167
+ * u2 = x2 * z1^2
168
+ * s1 = y1 * z2^3
169
+ * s2 = y2 * z1^3
170
+ * h = u2 - u1
171
+ * r = s2 - s1
172
+ * x3 = r^2 - h^3 - 2 * u1 * h^2
173
+ * y3 = r * (u1 * h^2 - x3) - s1 * h^3
174
+ * z3 = h * z1 * z2
175
+ *
176
+ * If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
177
+ * z3 == 0, so the result is correct.
178
+ * If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
179
+ * not correct.
180
+ * h == 0 only if u1 == u2; this happens in two cases:
181
+ * -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
182
+ * -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
183
+ *
184
+ * Thus, the following situations are not handled correctly:
185
+ * -- P1 = 0 and P2 != 0
186
+ * -- P1 != 0 and P2 = 0
187
+ * -- P1 = P2
188
+ * All other cases are properly computed. However, even in "incorrect"
189
+ * situations, the three coordinates still are properly formed field
190
+ * elements.
191
+ *
192
+ * The returned flag is cleared if r == 0. This happens in the following
193
+ * cases:
194
+ * -- Both points are on the same horizontal line (same Y coordinate).
195
+ * -- Both points are infinity.
196
+ * -- One point is infinity and the other is on line Y = 0.
197
+ * The third case cannot happen with our curves (there is no valid point
198
+ * on line Y = 0 since that would be a point of order 2). If the two
199
+ * source points are non-infinity, then remains only the case where the
200
+ * two points are on the same horizontal line.
201
+ *
202
+ * This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
203
+ * P2 != 0:
204
+ * -- If the returned value is not the point at infinity, then it was properly
205
+ * computed.
206
+ * -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
207
+ * is indeed the point at infinity.
208
+ * -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
209
+ * use the 'double' code.
210
+ *
211
+ * Cost: 16 multiplications
212
+ */
213
+ var const array <int > CodeAdd ;
214
+
215
+ /*
216
+ * Check that the point is on the curve. This code snippet assumes the
217
+ * following conventions:
218
+ * -- Coordinates x and y have been freshly decoded in P1 (but not
219
+ * converted to Montgomery coordinates yet).
220
+ * -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
221
+ */
222
+ var const array <int > CodeCheck ;
223
+
224
+ /*
225
+ * Conversion back to affine coordinates. This code snippet assumes that
226
+ * the z coordinate of P2 is set to 1 (not in Montgomery representation).
227
+ */
228
+ var const array <int > CodeAffine ;
229
+
230
+ // TODO: finish implementation.
231
+ static final function int RunCode (
232
+ out Jacobian P1 ,
233
+ const out Jacobian P2 ,
234
+ const out CurveParams Cc ,
235
+ const out array <int> Code
236
+ )
237
+ {
238
+ local int R ;
239
+ local _Monty T [13 ];
240
+ local int U ;
241
+ local int Op ;
242
+ local int D ;
243
+ local int A ;
244
+ local int B ;
245
+ local int Ctl ;
246
+ local int PLen ;
247
+ local byte Tp [66 ]; /* (BR_MAX_EC_SIZE + 7) >> 3 */
248
+
249
+ R = 1 ;
250
+
251
+ /*
252
+ * Copy the two operands in the dedicated registers.
253
+ */
254
+ // memcpy(t[P1x], P1->c, 3 * I15_LEN * sizeof(uint16_t));
255
+ // memcpy(t[P2x], P2->c, 3 * I15_LEN * sizeof(uint16_t));
256
+ // TODO: need static memcpy for these array sizes.
257
+
258
+ /*
259
+ * Run formulas.
260
+ */
261
+ for (U = 0 ; True ; ++U )
262
+ {
263
+ Op = Code [U ];
264
+ if (Op == 0 )
265
+ {
266
+ break ;
267
+ }
268
+
269
+ D = (Op >>> 8 ) & 0x0F ;
270
+ A = (Op >>> 4 ) & 0x0F ;
271
+ B = Op & 0x0F ;
272
+ Op = Op >>> 12 ;
273
+ switch (Op )
274
+ {
275
+ case 0 :
276
+ break ;
277
+ case 1 :
278
+ break ;
279
+ case 2 :
280
+ break ;
281
+ case 3 :
282
+ break ;
283
+ case 4 :
284
+ break ;
285
+ default :
286
+ // TODO: need static variant for this too.
287
+ // R = R & (class'FCryptoBigInt'.static.BIsZero(T[D]));
288
+ break ;
289
+ }
290
+ }
291
+
292
+ return R ;
293
+ }
294
+
295
+ static final function CurveParams IdToCurve (EFCEllipticCurve Curve )
296
+ {
297
+ return default ._PP [Curve - FCEC_Secp256r1 ];
298
+ };
299
+
148
300
static function array <byte > Generator (EFCEllipticCurve Curve , out int Len )
149
301
{
150
302
local array <byte> TODO ;
@@ -215,4 +367,91 @@ DefaultProperties
215
367
_PP (0 )={(P =(`P256_P_VALUES ), B =(`P256_B_VALUES ), R2 =(`P256_R2_VALUES ), P0i =0x001 , PointLen =65 )}
216
368
_PP (1 )={(P =(`P384_P_VALUES ), B =(`P384_B_VALUES ), R2 =(`P384_R2_VALUES ), P0i =0x001 , PointLen =97 )}
217
369
_PP (2 )={(P =(`P521_P_VALUES ), B =(`P521_B_VALUES ), R2 =(`P521_R2_VALUES ), P0i =0x001 , PointLen =133 )}
370
+
371
+ CodeDouble ={(
372
+ /*
373
+ * Compute z^2 (in t1).
374
+ */
375
+ // `MMUL(`t1, `Pz, `Pz),
376
+ 13858 ,
377
+
378
+ /*
379
+ * Compute x-z^2 (in t2) and then x+z^2 (in t1).
380
+ */
381
+ // `MSET(`t2, `Px),
382
+ // `MSUB(`t2, `t1),
383
+ // `MADD(`t1, `Px),
384
+ 1792 ,
385
+ 10080 ,
386
+ 5632 ,
387
+
388
+ /*
389
+ * Compute m = 3*(x+z^2)*(x-z^2) (in t1).
390
+ */
391
+ // `MMUL(`t3, `t1, `t2),
392
+ // `MSET(`t1, `t3),
393
+ // `MADD(`t1, `t3),
394
+ // `MADD(`t1, `t3),
395
+ 14439 ,
396
+ 1664 ,
397
+ 5760 ,
398
+ 5760 ,
399
+
400
+ /*
401
+ * Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
402
+ */
403
+ // `MMUL(`t3, `Py, `Py),
404
+ // `MADD(`t3, `t3),
405
+ // `MMUL(`t2, `Px, `t3),
406
+ // `MADD(`t2, `t2),
407
+ 14353 ,
408
+ 6272 ,
409
+ 14088 ,
410
+ 6000 ,
411
+
412
+ /*
413
+ * Compute x' = m^2 - 2*s.
414
+ */
415
+ // `MMUL(`Px, `t1, `t1),
416
+ // `MSUB(`Px, `t2),
417
+ // `MSUB(`Px, `t2),
418
+ 12390 ,
419
+ 8304 ,
420
+ 8304 ,
421
+
422
+ /*
423
+ * Compute z' = 2*y*z.
424
+ */
425
+ // `MMUL(`t4, `Py, `Pz),
426
+ // `MSET(`Pz, `t4),
427
+ // `MADD(`Pz, `t4),
428
+ 14610 ,
429
+ 656 ,
430
+ 4752 ,
431
+
432
+ /*
433
+ * Compute y' = m*(s - x') - 8*y^4. Note that we already have
434
+ * 2*y^2 in t3.
435
+ */
436
+ // `MSUB(`t2, `Px),
437
+ // `MMUL(`Py, `t1, `t2),
438
+ // `MMUL(`t4, `t3, `t3),
439
+ // `MSUB(`Py, `t4),
440
+ // `MSUB(`Py, `t4),
441
+ 9984 ,
442
+ 12647 ,
443
+ 14728 ,
444
+ 8592 ,
445
+ 8592 ,
446
+
447
+ `ENDCODE
448
+ )}
449
+
450
+ CodeAdd ={(
451
+
452
+ )}
453
+
454
+ CodeCheck ={(
455
+
456
+ )}
218
457
}
0 commit comments