Coverage Report

Created: 2026-09-14 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/relic/src/fpx/relic_fp12_sqr.c
Line
Count
Source
1
/*
2
 * RELIC is an Efficient LIbrary for Cryptography
3
 * Copyright (c) 2012 RELIC Authors
4
 *
5
 * This file is part of RELIC. RELIC is legal property of its developers,
6
 * whose names are not listed here. Please refer to the COPYRIGHT file
7
 * for contact information.
8
 *
9
 * RELIC is free software; you can redistribute it and/or modify it under the
10
 * terms of the version 2.1 (or later) of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; or version 2.0 of the Apache
12
 * License as published by the Apache Software Foundation. See the LICENSE files
13
 * for more details.
14
 *
15
 * RELIC is distributed in the hope that it will be useful, but WITHOUT ANY
16
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17
 * A PARTICULAR PURPOSE. See the LICENSE files for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public or the
20
 * Apache License along with RELIC. If not, see <https://www.gnu.org/licenses/>
21
 * or <https://www.apache.org/licenses/>.
22
 */
23
24
/**
25
 * @file
26
 *
27
 * Implementation of squaring in a dodecic extension of a prime field.
28
 *
29
 * @ingroup fpx
30
 */
31
32
#include "relic_core.h"
33
#include "relic_fp_low.h"
34
#include "relic_fpx_low.h"
35
36
/*============================================================================*/
37
/* Public definitions                                                         */
38
/*============================================================================*/
39
40
#if FPX_RDC == BASIC || !defined(STRIP)
41
42
0
void fp12_sqr_basic(fp12_t c, const fp12_t a) {
43
0
  fp6_t t0, t1;
44
45
0
  fp6_null(t0);
46
0
  fp6_null(t1);
47
48
0
  RLC_TRY {
49
0
    fp6_new(t0);
50
0
    fp6_new(t1);
51
52
0
    fp6_add(t0, a[0], a[1]);
53
0
    fp6_mul_art(t1, a[1]);
54
0
    fp6_add(t1, a[0], t1);
55
0
    fp6_mul(t0, t0, t1);
56
0
    fp6_mul(c[1], a[0], a[1]);
57
0
    fp6_sub(c[0], t0, c[1]);
58
0
    fp6_mul_art(t1, c[1]);
59
0
    fp6_sub(c[0], c[0], t1);
60
0
    fp6_dbl(c[1], c[1]);
61
0
  } RLC_CATCH_ANY {
62
0
    RLC_THROW(ERR_CAUGHT);
63
0
  } RLC_FINALLY {
64
0
    fp6_free(t0);
65
0
    fp6_free(t1);
66
0
  }
67
0
}
68
69
0
void fp12_sqr_cyc_basic(fp12_t c, const fp12_t a) {
70
0
  fp2_t t0, t1, t2, t3, t4, t5, t6;
71
72
0
  fp2_null(t0);
73
0
  fp2_null(t1);
74
0
  fp2_null(t2);
75
0
  fp2_null(t3);
76
0
  fp2_null(t4);
77
0
  fp2_null(t5);
78
0
  fp2_null(t6);
79
80
0
  RLC_TRY {
81
0
    fp2_new(t0);
82
0
    fp2_new(t1);
83
0
    fp2_new(t2);
84
0
    fp2_new(t3);
85
0
    fp2_new(t4);
86
0
    fp2_new(t5);
87
0
    fp2_new(t6);
88
89
    /* Define z = sqrt(E) */
90
91
    /* Now a is seen as (t0,t1) + (t2,t3) * w + (t4,t5) * w^2 */
92
93
    /* (t0, t1) = (a00 + a11*z)^2. */
94
0
    fp2_sqr(t2, a[0][0]);
95
0
    fp2_sqr(t3, a[1][1]);
96
0
    fp2_add(t1, a[0][0], a[1][1]);
97
98
0
    fp2_mul_nor(t0, t3);
99
0
    fp2_add(t0, t0, t2);
100
101
0
    fp2_sqr(t1, t1);
102
0
    fp2_sub(t1, t1, t2);
103
0
    fp2_sub(t1, t1, t3);
104
105
0
    fp2_sub(c[0][0], t0, a[0][0]);
106
0
    fp2_add(c[0][0], c[0][0], c[0][0]);
107
0
    fp2_add(c[0][0], t0, c[0][0]);
108
109
0
    fp2_add(c[1][1], t1, a[1][1]);
110
0
    fp2_add(c[1][1], c[1][1], c[1][1]);
111
0
    fp2_add(c[1][1], t1, c[1][1]);
112
113
0
    fp2_sqr(t0, a[0][1]);
114
0
    fp2_sqr(t1, a[1][2]);
115
0
    fp2_add(t5, a[0][1], a[1][2]);
116
0
    fp2_sqr(t2, t5);
117
118
0
    fp2_add(t3, t0, t1);
119
0
    fp2_sub(t5, t2, t3);
120
121
0
    fp2_add(t6, a[1][0], a[0][2]);
122
0
    fp2_sqr(t3, t6);
123
0
    fp2_sqr(t2, a[1][0]);
124
125
0
    fp2_mul_nor(t6, t5);
126
0
    fp2_add(t5, t6, a[1][0]);
127
0
    fp2_dbl(t5, t5);
128
0
    fp2_add(c[1][0], t5, t6);
129
130
0
    fp2_mul_nor(t4, t1);
131
0
    fp2_add(t5, t0, t4);
132
0
    fp2_sub(t6, t5, a[0][2]);
133
134
0
    fp2_sqr(t1, a[0][2]);
135
136
0
    fp2_dbl(t6, t6);
137
0
    fp2_add(c[0][2], t6, t5);
138
139
0
    fp2_mul_nor(t4, t1);
140
0
    fp2_add(t5, t2, t4);
141
0
    fp2_sub(t6, t5, a[0][1]);
142
0
    fp2_dbl(t6, t6);
143
0
    fp2_add(c[0][1], t6, t5);
144
145
0
    fp2_add(t0, t2, t1);
146
0
    fp2_sub(t5, t3, t0);
147
0
    fp2_add(t6, t5, a[1][2]);
148
0
    fp2_dbl(t6, t6);
149
0
    fp2_add(c[1][2], t5, t6);
150
0
  } RLC_CATCH_ANY {
151
0
    RLC_THROW(ERR_CAUGHT);
152
0
  } RLC_FINALLY {
153
0
    fp2_free(t0);
154
0
    fp2_free(t1);
155
0
    fp2_free(t2);
156
0
    fp2_free(t3);
157
0
    fp2_free(t4);
158
0
    fp2_free(t5);
159
0
    fp2_free(t6);
160
0
  }
161
0
}
162
163
0
void fp12_sqr_pck_basic(fp12_t c, const fp12_t a) {
164
0
  fp2_t t0, t1, t2, t3, t4, t5, t6;
165
166
0
  fp2_null(t0);
167
0
  fp2_null(t1);
168
0
  fp2_null(t2);
169
0
  fp2_null(t3);
170
0
  fp2_null(t4);
171
0
  fp2_null(t5);
172
0
  fp2_null(t6);
173
174
0
  RLC_TRY {
175
0
    fp2_new(t0);
176
0
    fp2_new(t1);
177
0
    fp2_new(t2);
178
0
    fp2_new(t3);
179
0
    fp2_new(t4);
180
0
    fp2_new(t5);
181
0
    fp2_new(t6);
182
183
0
    fp2_sqr(t0, a[0][1]);
184
0
    fp2_sqr(t1, a[1][2]);
185
0
    fp2_add(t5, a[0][1], a[1][2]);
186
0
    fp2_sqr(t2, t5);
187
188
0
    fp2_add(t3, t0, t1);
189
0
    fp2_sub(t5, t2, t3);
190
191
0
    fp2_add(t6, a[1][0], a[0][2]);
192
0
    fp2_sqr(t3, t6);
193
0
    fp2_sqr(t2, a[1][0]);
194
195
0
    fp2_mul_nor(t6, t5);
196
0
    fp2_add(t5, t6, a[1][0]);
197
0
    fp2_dbl(t5, t5);
198
0
    fp2_add(c[1][0], t5, t6);
199
200
0
    fp2_mul_nor(t4, t1);
201
0
    fp2_add(t5, t0, t4);
202
0
    fp2_sub(t6, t5, a[0][2]);
203
204
0
    fp2_sqr(t1, a[0][2]);
205
206
0
    fp2_dbl(t6, t6);
207
0
    fp2_add(c[0][2], t6, t5);
208
209
0
    fp2_mul_nor(t4, t1);
210
0
    fp2_add(t5, t2, t4);
211
0
    fp2_sub(t6, t5, a[0][1]);
212
0
    fp2_dbl(t6, t6);
213
0
    fp2_add(c[0][1], t6, t5);
214
215
0
    fp2_add(t0, t2, t1);
216
0
    fp2_sub(t5, t3, t0);
217
0
    fp2_add(t6, t5, a[1][2]);
218
0
    fp2_dbl(t6, t6);
219
0
    fp2_add(c[1][2], t5, t6);
220
0
  } RLC_CATCH_ANY {
221
0
    RLC_THROW(ERR_CAUGHT);
222
0
  } RLC_FINALLY {
223
0
    fp2_free(t0);
224
0
    fp2_free(t1);
225
0
    fp2_free(t2);
226
0
    fp2_free(t3);
227
0
    fp2_free(t4);
228
0
    fp2_free(t5);
229
0
    fp2_free(t6);
230
0
  }
231
0
}
232
233
#endif
234
235
#if FPX_RDC == LAZYR || !defined(STRIP)
236
237
0
void fp12_sqr_unr(dv12_t c, const fp12_t a) {
238
0
  fp4_t t0, t1;
239
0
  dv4_t u0, u1, u2, u3, u4;
240
241
0
  fp4_null(t0);
242
0
  fp4_null(t1);
243
0
  dv4_null(u0);
244
0
  dv4_null(u1);
245
0
  dv4_null(u2);
246
0
  dv4_null(u3);
247
0
  dv4_null(u4);
248
249
0
  RLC_TRY {
250
0
    fp4_new(t0);
251
0
    fp4_new(t1);
252
0
    dv4_new(u0);
253
0
    dv4_new(u1);
254
0
    dv4_new(u2);
255
0
    dv4_new(u3);
256
0
    dv4_new(u4);
257
258
    /* a0 = (a00, a11). */
259
    /* a1 = (a10, a02). */
260
    /* a2 = (a01, a12). */
261
262
    /* (t0,t1) = a0^2 */
263
0
    fp2_copy(t0[0], a[0][0]);
264
0
    fp2_copy(t0[1], a[1][1]);
265
0
    fp4_sqr_unr(u0, t0);
266
267
    /* (t2,t3) = 2 * a1 * a2 */
268
0
    fp2_copy(t0[0], a[1][0]);
269
0
    fp2_copy(t0[1], a[0][2]);
270
0
    fp2_copy(t1[0], a[0][1]);
271
0
    fp2_copy(t1[1], a[1][2]);
272
0
    fp4_mul_unr(u1, t0, t1);
273
0
    fp2_addc_low(u1[0], u1[0], u1[0]);
274
0
    fp2_addc_low(u1[1], u1[1], u1[1]);
275
276
    /* (t4,t5) = a2^2. */
277
0
    fp4_sqr_unr(u2, t1);
278
279
    /* c2 = a0 + a2. */
280
0
    fp2_addm_low(t1[0], a[0][0], a[0][1]);
281
0
    fp2_addm_low(t1[1], a[1][1], a[1][2]);
282
283
    /* (t6,t7) = (a0 + a2 + a1)^2. */
284
0
    fp2_addm_low(t0[0], t1[0], a[1][0]);
285
0
    fp2_addm_low(t0[1], t1[1], a[0][2]);
286
0
    fp4_sqr_unr(u3, t0);
287
288
    /* c2 = (a0 + a2 - a1)^2. */
289
0
    fp2_subm_low(t0[0], t1[0], a[1][0]);
290
0
    fp2_subm_low(t0[1], t1[1], a[0][2]);
291
0
    fp4_sqr_unr(u4, t0);
292
293
    /* c2 = (c2 + (t6,t7))/2. */
294
#ifdef RLC_FP_ROOM
295
    fp2_addd_low(u4[0], u4[0], u3[0]);
296
    fp2_addd_low(u4[1], u4[1], u3[1]);
297
#else
298
0
    fp2_addc_low(u4[0], u4[0], u3[0]);
299
0
    fp2_addc_low(u4[1], u4[1], u3[1]);
300
0
#endif
301
0
    fp_hlvd_low(u4[0][0], u4[0][0]);
302
0
    fp_hlvd_low(u4[0][1], u4[0][1]);
303
0
    fp_hlvd_low(u4[1][0], u4[1][0]);
304
0
    fp_hlvd_low(u4[1][1], u4[1][1]);
305
306
    /* (t6,t7) = (t6,t7) - c2 - (t2,t3). */
307
0
    fp2_subc_low(u3[0], u3[0], u4[0]);
308
0
    fp2_subc_low(u3[1], u3[1], u4[1]);
309
0
    fp2_subc_low(u3[0], u3[0], u1[0]);
310
0
    fp2_subc_low(u3[1], u3[1], u1[1]);
311
312
    /* c2 = c2 - (t0,t1) - (t4,t5). */
313
0
    fp2_subc_low(u4[0], u4[0], u0[0]);
314
0
    fp2_subc_low(u4[1], u4[1], u0[1]);
315
0
    fp2_subc_low(c[0][1], u4[0], u2[0]);
316
0
    fp2_subc_low(c[1][2], u4[1], u2[1]);
317
318
    /* c1 = (t6,t7) + (t4,t5) * E. */
319
0
    fp2_nord_low(u4[1], u2[1]);
320
0
    fp2_addc_low(c[1][0], u3[0], u4[1]);
321
0
    fp2_addc_low(c[0][2], u3[1], u2[0]);
322
323
    /* c0 = (t0,t1) + (t2,t3) * E. */
324
0
    fp2_nord_low(u4[1], u1[1]);
325
0
    fp2_addc_low(c[0][0], u0[0], u4[1]);
326
0
    fp2_addc_low(c[1][1], u0[1], u1[0]);
327
0
  } RLC_CATCH_ANY {
328
0
    RLC_THROW(ERR_CAUGHT);
329
0
  } RLC_FINALLY {
330
0
    fp4_free(t0);
331
0
    fp4_free(t1);
332
0
    dv4_free(u0);
333
0
    dv4_free(u1);
334
0
    dv4_free(u2);
335
0
    dv4_free(u3);
336
0
    dv4_free(u4);
337
0
  }
338
0
}
339
340
0
void fp12_sqr_lazyr(fp12_t c, const fp12_t a) {
341
0
  dv12_t t;
342
343
0
  dv12_null(t);
344
345
0
  RLC_TRY {
346
0
    dv12_new(t);
347
0
    fp12_sqr_unr(t, a);
348
0
    for (int i = 0; i < 3; i++) {
349
0
      fp2_rdcn_low(c[0][i], t[0][i]);
350
0
      fp2_rdcn_low(c[1][i], t[1][i]);
351
0
    }
352
0
  } RLC_CATCH_ANY {
353
0
    RLC_THROW(ERR_CAUGHT);
354
0
  } RLC_FINALLY {
355
0
    dv12_free(t);
356
0
  }
357
0
}
358
359
0
void fp12_sqr_cyc_lazyr(fp12_t c, const fp12_t a) {
360
0
  fp2_t t0, t1, t2;
361
0
  dv2_t u0, u1, u2, u3;
362
363
0
  fp2_null(t0);
364
0
  fp2_null(t1);
365
0
  fp2_null(t2);
366
0
  dv2_null(u0);
367
0
  dv2_null(u1);
368
0
  dv2_null(u2);
369
0
  dv2_null(u3);
370
371
0
  RLC_TRY {
372
0
    fp2_new(t0);
373
0
    fp2_new(t1);
374
0
    fp2_new(t2);
375
0
    dv2_new(u0);
376
0
    dv2_new(u1);
377
0
    dv2_new(u2);
378
0
    dv2_new(u3);
379
380
0
    fp2_sqrn_low(u2, a[0][0]);
381
0
    fp2_sqrn_low(u3, a[1][1]);
382
0
    fp2_addm_low(t1, a[0][0], a[1][1]);
383
384
0
    fp2_nord_low(u0, u3);
385
0
    fp2_addc_low(u0, u0, u2);
386
0
    fp2_rdcn_low(t0, u0);
387
388
0
    fp2_sqrn_low(u1, t1);
389
0
    fp2_addc_low(u2, u2, u3);
390
0
    fp2_subc_low(u1, u1, u2);
391
0
    fp2_rdcn_low(t1, u1);
392
393
0
    fp2_subm_low(c[0][0], t0, a[0][0]);
394
0
    fp2_addm_low(c[0][0], c[0][0], c[0][0]);
395
0
    fp2_addm_low(c[0][0], t0, c[0][0]);
396
397
0
    fp2_addm_low(c[1][1], t1, a[1][1]);
398
0
    fp2_addm_low(c[1][1], c[1][1], c[1][1]);
399
0
    fp2_addm_low(c[1][1], t1, c[1][1]);
400
401
0
    fp2_sqrn_low(u0, a[0][1]);
402
0
    fp2_sqrn_low(u1, a[1][2]);
403
0
    fp2_addm_low(t0, a[0][1], a[1][2]);
404
0
    fp2_sqrn_low(u2, t0);
405
406
0
    fp2_addc_low(u3, u0, u1);
407
0
    fp2_subc_low(u3, u2, u3);
408
0
    fp2_rdcn_low(t0, u3);
409
410
0
    fp2_addm_low(t1, a[1][0], a[0][2]);
411
0
    fp2_sqrm_low(t2, t1);
412
0
    fp2_sqrn_low(u2, a[1][0]);
413
414
0
    fp2_norm_low(t1, t0);
415
0
    fp2_addm_low(t0, t1, a[1][0]);
416
0
    fp2_addm_low(t0, t0, t0);
417
0
    fp2_addm_low(c[1][0], t0, t1);
418
419
0
    fp2_nord_low(u3, u1);
420
0
    fp2_addc_low(u3, u0, u3);
421
0
    fp2_rdcn_low(t0, u3);
422
0
    fp2_subm_low(t1, t0, a[0][2]);
423
424
0
    fp2_sqrn_low(u1, a[0][2]);
425
426
0
    fp2_addm_low(t1, t1, t1);
427
0
    fp2_addm_low(c[0][2], t1, t0);
428
429
0
    fp2_nord_low(u3, u1);
430
0
    fp2_addc_low(u3, u2, u3);
431
0
    fp2_rdcn_low(t0, u3);
432
0
    fp2_subm_low(t1, t0, a[0][1]);
433
0
    fp2_addm_low(t1, t1, t1);
434
0
    fp2_addm_low(c[0][1], t1, t0);
435
436
0
    fp2_addc_low(u0, u2, u1);
437
0
    fp2_rdcn_low(t0, u0);
438
0
    fp2_subm_low(t0, t2, t0);
439
0
    fp2_addm_low(t1, t0, a[1][2]);
440
0
    fp2_dblm_low(t1, t1);
441
0
    fp2_addm_low(c[1][2], t0, t1);
442
0
  } RLC_CATCH_ANY {
443
0
    RLC_THROW(ERR_CAUGHT);
444
0
  } RLC_FINALLY {
445
0
    fp2_free(t0);
446
0
    fp2_free(t1);
447
0
    fp2_free(t2);
448
0
    dv2_free(u0);
449
0
    dv2_free(u1);
450
0
    dv2_free(u2);
451
0
    dv2_free(u3);
452
0
  }
453
0
}
454
455
0
void fp12_sqr_pck_lazyr(fp12_t c, const fp12_t a) {
456
0
  fp2_t t0, t1, t2;
457
0
  dv2_t u0, u1, u2, u3;
458
459
0
  fp2_null(t0);
460
0
  fp2_null(t1);
461
0
  fp2_null(t2);
462
0
  dv2_null(u0);
463
0
  dv2_null(u1);
464
0
  dv2_null(u2);
465
0
  dv2_null(u3);
466
467
0
  RLC_TRY {
468
0
    fp2_new(t0);
469
0
    fp2_new(t1);
470
0
    fp2_new(t2);
471
0
    dv2_new(u0);
472
0
    dv2_new(u1);
473
0
    dv2_new(u2);
474
0
    dv2_new(u3);
475
476
0
    fp2_sqrn_low(u0, a[0][1]);
477
0
    fp2_sqrn_low(u1, a[1][2]);
478
0
    fp2_addm_low(t0, a[0][1], a[1][2]);
479
0
    fp2_sqrn_low(u2, t0);
480
481
0
    fp2_addc_low(u3, u0, u1);
482
0
    fp2_subc_low(u3, u2, u3);
483
0
    fp2_rdcn_low(t0, u3);
484
485
0
    fp2_addm_low(t1, a[1][0], a[0][2]);
486
0
    fp2_sqrm_low(t2, t1);
487
0
    fp2_sqrn_low(u2, a[1][0]);
488
489
0
    fp2_norm_low(t1, t0);
490
0
    fp2_addm_low(t0, t1, a[1][0]);
491
0
    fp2_dblm_low(t0, t0);
492
0
    fp2_addm_low(c[1][0], t0, t1);
493
494
0
    fp2_nord_low(u3, u1);
495
0
    fp2_sqrn_low(u1, a[0][2]);
496
0
    fp2_addc_low(u3, u0, u3);
497
0
    fp2_rdcn_low(t0, u3);
498
0
    fp2_subm_low(t1, t0, a[0][2]);
499
0
    fp2_dblm_low(t1, t1);
500
0
    fp2_addm_low(c[0][2], t1, t0);
501
502
0
    fp2_addc_low(u0, u2, u1);
503
0
    fp2_rdcn_low(t0, u0);
504
0
    fp2_subm_low(t0, t2, t0);
505
0
    fp2_addm_low(t1, t0, a[1][2]);
506
0
    fp2_dblm_low(t1, t1);
507
0
    fp2_addm_low(c[1][2], t0, t1);
508
509
0
    fp2_nord_low(u3, u1);
510
0
    fp2_addc_low(u3, u2, u3);
511
0
    fp2_rdcn_low(t0, u3);
512
0
    fp2_subm_low(t1, t0, a[0][1]);
513
0
    fp2_dblm_low(t1, t1);
514
0
    fp2_addm_low(c[0][1], t1, t0);
515
0
  } RLC_CATCH_ANY {
516
0
    RLC_THROW(ERR_CAUGHT);
517
0
  } RLC_FINALLY {
518
0
    fp2_free(t0);
519
0
    fp2_free(t1);
520
0
    fp2_free(t2);
521
0
    dv2_free(u0);
522
0
    dv2_free(u1);
523
0
    dv2_free(u2);
524
0
    dv2_free(u3);
525
0
  }
526
0
}
527
528
#endif