Coverage Report

Created: 2026-07-25 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/relic/src/ed/relic_ed_add.c
Line
Count
Source
1
/*
2
 * RELIC is an Efficient LIbrary for Cryptography
3
 * Copyright (c) 2014 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 the point addition on prime elliptic twisted Edwards curves.
28
 *
29
 * @version $Id$
30
 * @ingroup ed
31
 */
32
33
#include <assert.h>
34
35
#include "relic_core.h"
36
#include "relic_label.h"
37
38
/*============================================================================*/
39
/* Public definitions                                                         */
40
/*============================================================================*/
41
42
#if ED_ADD == BASIC || !defined(STRIP)
43
44
0
void ed_add_basic(ed_t r, const ed_t p, const ed_t q) {
45
0
  fp_t t0, t1, t2;
46
47
0
  fp_null(t0);
48
0
  fp_null(t1);
49
0
  fp_null(t2);
50
51
0
  RLC_TRY {
52
0
    fp_new(t0);
53
0
    fp_new(t1);
54
0
    fp_new(t2);
55
56
    /* x3 = (x1*y2+y1*x2)/(1+d*x1*x2*y1*y2)
57
     * y3 = (y1*y2-a*x1*x2)/(1-d*x1*x2*y1*y2) */
58
59
0
    fp_mul(t0, p->x, q->y);
60
0
    fp_mul(t1, p->y, q->x);
61
0
    fp_add(t0, t0, t1);
62
63
0
    fp_mul(t1, p->x, q->x);
64
0
    fp_mul(t2, p->y, q->y);
65
0
    fp_mul(t1, t1, t2);
66
0
    fp_mul(t1, t1, core_get()->ed_d);
67
0
    fp_add_dig(t2, t1, 1);
68
0
    fp_inv(t2, t2);
69
0
    fp_sub_dig(t1, t1, 1);
70
0
    fp_neg(t1, t1);
71
0
    fp_inv(t1, t1);
72
73
0
    fp_mul(t0, t0, t2);
74
75
0
    fp_mul(r->y, p->y, q->y);
76
0
    fp_mul(t2, p->x, q->x);
77
0
    fp_mul(t2, t2, core_get()->ed_a);
78
0
    fp_sub(r->y, r->y, t2);
79
0
    fp_mul(r->y, r->y, t1);
80
81
0
    fp_copy(r->x, t0);
82
0
    fp_copy(r->z, p->z);
83
84
0
    r->coord = BASIC;
85
0
  }
86
0
  RLC_CATCH_ANY {
87
0
    RLC_THROW(ERR_CAUGHT);
88
0
  }
89
0
  RLC_FINALLY {
90
0
    fp_free(t0);
91
0
    fp_free(t1);
92
0
    fp_free(t2);
93
0
  }
94
0
}
95
96
0
void ed_sub_basic(ed_t r, const ed_t p, const ed_t q) {
97
0
  ed_t t;
98
99
0
  ed_null(t);
100
101
0
  if (p == q) {
102
0
    ed_set_infty(r);
103
0
    return;
104
0
  }
105
106
0
  RLC_TRY {
107
0
    ed_new(t);
108
109
0
    ed_neg_basic(t, q);
110
0
    ed_add_basic(r, p, t);
111
0
    r->coord = BASIC;
112
0
  }
113
0
  RLC_CATCH_ANY {
114
0
    RLC_THROW(ERR_CAUGHT);
115
0
  }
116
0
  RLC_FINALLY {
117
0
    ed_free(t);
118
0
  }
119
0
}
120
121
#endif /* ED_ADD == BASIC */
122
123
#if ED_ADD == PROJC || !defined(STRIP)
124
125
0
void ed_add_projc(ed_t r, const ed_t p, const ed_t q) {
126
0
  fp_t t0, t1, t2, t3, t4, t5, t6, t7;
127
128
0
  fp_null(t0);
129
0
  fp_null(t1);
130
0
  fp_null(t2);
131
0
  fp_null(t3);
132
0
  fp_null(t4);
133
0
  fp_null(t5);
134
0
  fp_null(t6);
135
0
  fp_null(t7);
136
137
0
  RLC_TRY {
138
0
    fp_new(t0);
139
0
    fp_new(t1);
140
0
    fp_new(t2);
141
0
    fp_new(t3);
142
0
    fp_new(t4);
143
0
    fp_new(t5);
144
0
    fp_new(t6);
145
0
    fp_new(t7);
146
147
    /* A = z1 * z2, B = A^2 */
148
0
    fp_mul(t0, p->z, q->z);
149
0
    fp_sqr(t1, t0);
150
151
    /* C = x1 * x2, D = y1 * y2 */
152
0
    fp_mul(t2, p->x, q->x);
153
0
    fp_mul(t3, p->y, q->y);
154
155
    /* E = d * C * D */
156
0
    fp_mul(t4, core_get()->ed_d, t2);
157
0
    fp_mul(t4, t4, t3);
158
159
    /* F = B - E */
160
0
    fp_sub(t5, t1, t4);
161
162
    /* G = B + E */
163
0
    fp_add(t6, t1, t4);
164
165
    /* x3 = A * F * ((x1 + y1) * (x2 + y2) - C - D) */
166
0
    fp_mul(t7, t0, t5);
167
0
    fp_add(r->z, p->x, p->y);
168
0
    fp_add(r->x, q->x, q->y);
169
0
    fp_mul(r->x, r->z, r->x);
170
0
    fp_sub(r->x, r->x, t2);
171
0
    fp_sub(r->x, r->x, t3);
172
0
    fp_mul(r->x, t7, r->x);
173
174
    /* y3 = A * G * (D - a * C) */
175
0
    fp_mul(r->z, t0, t6);
176
0
    fp_mul(r->y, core_get()->ed_a, t2);
177
0
    fp_sub(r->y, t3, r->y);
178
0
    fp_mul(r->y, r->z, r->y);
179
180
    /* z3 = F * G */
181
0
    fp_mul(r->z, t5, t6);
182
183
0
    r->coord = PROJC;
184
0
  } RLC_CATCH_ANY {
185
0
    RLC_THROW(ERR_CAUGHT)
186
0
  } RLC_FINALLY {
187
0
    fp_free(t0);
188
0
    fp_free(t1);
189
0
    fp_free(t2);
190
0
    fp_free(t3);
191
0
    fp_free(t4);
192
0
    fp_free(t5);
193
0
    fp_free(t6);
194
0
    fp_free(t7);
195
0
  }
196
0
}
197
198
#endif /* ED_ADD == PROJC */
199
200
#if ED_ADD == PROJC || !defined(STRIP)
201
202
0
void ed_sub_projc(ed_t r, const ed_t p, const ed_t q) {
203
0
  ed_t t;
204
205
0
  ed_null(t);
206
207
0
  if (p == q) {
208
0
    ed_set_infty(r);
209
0
    return;
210
0
  }
211
212
0
  RLC_TRY {
213
0
    ed_new(t);
214
215
0
    ed_neg_projc(t, q);
216
0
    ed_add_projc(r, p, t);
217
0
  }
218
0
  RLC_CATCH_ANY {
219
0
    RLC_THROW(ERR_CAUGHT);
220
0
  }
221
0
  RLC_FINALLY {
222
0
    ed_free(t);
223
0
  }
224
0
}
225
226
#endif /* ED_ADD == PROJC || ED_ADD == EXTND */
227
228
#if ED_ADD == EXTND || !defined(STRIP)
229
230
0
void ed_add_extnd(ed_t r, const ed_t p, const ed_t q) {
231
0
  fp_t t0;
232
0
  fp_t t1;
233
0
  fp_t t2;
234
0
  fp_t t3;
235
0
  fp_t t4;
236
237
0
  fp_null(t0);
238
0
  fp_null(t1);
239
0
  fp_null(t2);
240
0
  fp_null(t3);
241
0
  fp_null(t4);
242
243
0
  RLC_TRY {
244
0
    fp_new(t0);
245
0
    fp_new(t1);
246
0
    fp_new(t2);
247
0
    fp_new(t3);
248
0
    fp_new(t4);
249
250
    /* A = x1 * x2, B = y1 * y2 */
251
0
    fp_mul(t0, p->x, q->x);
252
0
    fp_mul(t1, p->y, q->y);
253
254
    /* C = d * t1 * t2 */
255
0
    fp_mul(t2, core_get()->ed_d, p->t);
256
0
    fp_mul(r->t, t2, q->t);
257
258
    /* D = z1 * z2 */
259
0
    fp_mul(r->z, p->z, q->z);
260
261
    /* E = (x1 + y1) * (x2 + y2) - A - B */
262
0
    fp_add(t2, p->x, p->y);
263
0
    fp_add(t3, q->x, q->y);
264
0
    fp_mul(t2, t2, t3);
265
0
    fp_sub(t2, t2, t0);
266
0
    fp_sub(t2, t2, t1);
267
268
    /* F = D - C */
269
0
    fp_sub(t3, r->z, r->t);
270
271
    /* G = D + C */
272
0
    fp_add(t4, r->z, r->t);
273
274
    /* H = B - aA */
275
0
    fp_mul(r->x, core_get()->ed_a, t0);
276
0
    fp_sub(r->z, t1, r->x);
277
278
    /* x3 = E * F, y3 = G * H, t3 = E * H, z3 = F * G */
279
0
    fp_mul(r->x, t2, t3);
280
0
    fp_mul(r->y, t4, r->z);
281
0
    fp_mul(r->t, t2, r->z);
282
0
    fp_mul(r->z, t3, t4);
283
284
0
    r->coord = EXTND;
285
0
  } RLC_CATCH_ANY {
286
0
    RLC_THROW(ERR_CAUGHT)
287
0
  } RLC_FINALLY {
288
0
    fp_free(t0);
289
0
    fp_free(t1);
290
0
    fp_free(t2);
291
0
    fp_free(t3);
292
0
    fp_free(t4);
293
0
  }
294
0
}
295
296
0
void ed_sub_extnd(ed_t r, const ed_t p, const ed_t q) {
297
0
  ed_t t;
298
299
0
  ed_null(t);
300
301
0
  if (p == q) {
302
0
    ed_set_infty(r);
303
0
    return;
304
0
  }
305
306
0
  RLC_TRY {
307
0
    ed_new(t);
308
309
0
    ed_neg_projc(t, q);
310
0
    ed_add_extnd(r, p, t);
311
0
  }
312
0
  RLC_CATCH_ANY {
313
0
    RLC_THROW(ERR_CAUGHT);
314
0
  }
315
0
  RLC_FINALLY {
316
    ed_free(t);
317
0
  }
318
0
}
319
320
#endif