/src/nettle/ecc-nonsec-add-jjj.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ecc-non-sec-add-jjj.c |
2 | | |
3 | | Copyright (C) 2013, 2022 Niels Möller |
4 | | |
5 | | This file is part of GNU Nettle. |
6 | | |
7 | | GNU Nettle is free software: you can redistribute it and/or |
8 | | modify it under the terms of either: |
9 | | |
10 | | * the GNU Lesser General Public License as published by the Free |
11 | | Software Foundation; either version 3 of the License, or (at your |
12 | | option) any later version. |
13 | | |
14 | | or |
15 | | |
16 | | * the GNU General Public License as published by the Free |
17 | | Software Foundation; either version 2 of the License, or (at your |
18 | | option) any later version. |
19 | | |
20 | | or both in parallel, as here. |
21 | | |
22 | | GNU Nettle is distributed in the hope that it will be useful, |
23 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
24 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
25 | | General Public License for more details. |
26 | | |
27 | | You should have received copies of the GNU General Public License and |
28 | | the GNU Lesser General Public License along with this program. If |
29 | | not, see http://www.gnu.org/licenses/. |
30 | | */ |
31 | | |
32 | | /* Development of Nettle's ECC support was funded by the .SE Internet Fund. */ |
33 | | |
34 | | #if HAVE_CONFIG_H |
35 | | # include "config.h" |
36 | | #endif |
37 | | |
38 | | #include "ecc.h" |
39 | | #include "ecc-internal.h" |
40 | | |
41 | | /* Similar to ecc_add_jjj, but checks if x coordinates are equal (H = |
42 | | 0) below, and if so, performs doubling if also y coordinates are |
43 | | equal, or returns 0 (failure) indicating that the result is the |
44 | | infinity point. */ |
45 | | int |
46 | | ecc_nonsec_add_jjj (const struct ecc_curve *ecc, |
47 | | mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q, |
48 | | mp_limb_t *scratch) |
49 | 0 | { |
50 | 0 | #define x1 p |
51 | 0 | #define y1 (p + ecc->p.size) |
52 | 0 | #define z1 (p + 2*ecc->p.size) |
53 | |
|
54 | 0 | #define x2 q |
55 | 0 | #define y2 (q + ecc->p.size) |
56 | 0 | #define z2 (q + 2*ecc->p.size) |
57 | |
|
58 | 0 | #define x3 r |
59 | 0 | #define y3 (r + ecc->p.size) |
60 | 0 | #define z3 (r + 2*ecc->p.size) |
61 | | /* Formulas, from djb, |
62 | | http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl: |
63 | | |
64 | | Computation Operation Live variables |
65 | | |
66 | | Z1Z1 = Z1^2 sqr Z1Z1 |
67 | | Z2Z2 = Z2^2 sqr Z1Z1, Z2Z2 |
68 | | U1 = X1*Z2Z2 mul Z1Z1, Z2Z2, U1 |
69 | | U2 = X2*Z1Z1 mul Z1Z1, Z2Z2, U1, U2 |
70 | | H = U2-U1 Z1Z1, Z2Z2, U1, H |
71 | | Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2)*H sqr, mul Z1Z1, Z2Z2, U1, H |
72 | | S1 = Y1*Z2*Z2Z2 mul, mul Z1Z1, U1, H, S1 |
73 | | S2 = Y2*Z1*Z1Z1 mul, mul U1, H, S1, S2 |
74 | | W = 2*(S2-S1) (djb: r) U1, H, S1, W |
75 | | I = (2*H)^2 sqr U1, H, S1, W, I |
76 | | J = H*I mul U1, S1, W, J, V |
77 | | V = U1*I mul S1, W, J, V |
78 | | X3 = W^2-J-2*V sqr S1, W, J, V |
79 | | Y3 = W*(V-X3)-2*S1*J mul, mul |
80 | | */ |
81 | |
|
82 | 0 | #define h scratch |
83 | 0 | #define z1z1 (scratch + ecc->p.size) |
84 | 0 | #define z2z2 z1z1 |
85 | 0 | #define z1z2 (scratch + 2*ecc->p.size) |
86 | |
|
87 | 0 | #define w (scratch + ecc->p.size) |
88 | 0 | #define i (scratch + 2*ecc->p.size) |
89 | 0 | #define j h |
90 | 0 | #define v i |
91 | |
|
92 | 0 | #define tp (scratch + 3*ecc->p.size) |
93 | |
|
94 | 0 | ecc_mod_sqr (&ecc->p, z2z2, z2, tp); /* z2z2 */ |
95 | | /* Store u1 at x3 */ |
96 | 0 | ecc_mod_mul (&ecc->p, x3, x1, z2z2, tp); /* z2z2 */ |
97 | |
|
98 | 0 | ecc_mod_add (&ecc->p, z1z2, z1, z2); /* z2z2, z1z2 */ |
99 | 0 | ecc_mod_sqr (&ecc->p, z1z2, z1z2, tp); |
100 | 0 | ecc_mod_sub (&ecc->p, z1z2, z1z2, z2z2); /* z2z2, z1z2 */ |
101 | | |
102 | | /* Do s1 early, store at y3 */ |
103 | 0 | ecc_mod_mul (&ecc->p, z2z2, z2z2, z2, tp); /* z2z2, z1z2 */ |
104 | 0 | ecc_mod_mul (&ecc->p, y3, z2z2, y1, tp); /* z1z2 */ |
105 | |
|
106 | 0 | ecc_mod_sqr (&ecc->p, z1z1, z1, tp); /* z1z1, z1z2 */ |
107 | 0 | ecc_mod_sub (&ecc->p, z1z2, z1z2, z1z1); |
108 | 0 | ecc_mod_mul (&ecc->p, h, x2, z1z1, tp); /* z1z1, z1z2, h */ |
109 | 0 | ecc_mod_sub (&ecc->p, h, h, x3); |
110 | | |
111 | | /* z1^3 */ |
112 | 0 | ecc_mod_mul (&ecc->p, z1z1, z1z1, z1, tp); |
113 | | |
114 | | /* z3 <-- h z1 z2 delayed until now, since that may clobber z1. */ |
115 | 0 | ecc_mod_mul (&ecc->p, z3, z1z2, h, tp); /* z1z1, h */ |
116 | | /* w = 2 (s2 - s1) */ |
117 | 0 | ecc_mod_mul (&ecc->p, w, z1z1, y2, tp); /* h, w */ |
118 | 0 | ecc_mod_sub (&ecc->p, w, w, y3); |
119 | | |
120 | | /* Note that use of ecc_mod_zero_p depends 0 <= h,w < 2p. */ |
121 | 0 | if (ecc_mod_zero_p (&ecc->p, h)) |
122 | 0 | { |
123 | | /* X1 == X2 */ |
124 | 0 | if (ecc_mod_zero_p (&ecc->p, w)) { |
125 | | /* Y1 == Y2. Do point duplication. Note that q input is |
126 | | unclobbered, and that scratch need is smaller. Implies some |
127 | | unnecessary recomputation, but performance it not so |
128 | | important for this very unlikely corner case. */ |
129 | 0 | ecc_dup_jj (ecc, r, q, scratch); |
130 | 0 | return 1; |
131 | 0 | } |
132 | | |
133 | | /* We must have Y1 == -Y2, and then the result is the infinity |
134 | | point, */ |
135 | 0 | mpn_zero (r, 3*ecc->p.size); |
136 | 0 | return 0; |
137 | 0 | } |
138 | 0 | ecc_mod_add (&ecc->p, w, w, w); |
139 | | |
140 | | /* i = (2h)^2 */ |
141 | 0 | ecc_mod_add (&ecc->p, i, h, h); /* h, w, i */ |
142 | 0 | ecc_mod_sqr (&ecc->p, i, i, tp); |
143 | | |
144 | | /* j and h can overlap */ |
145 | 0 | ecc_mod_mul (&ecc->p, j, h, i, tp); /* j, w, i */ |
146 | | |
147 | | /* v and i can overlap */ |
148 | 0 | ecc_mod_mul (&ecc->p, v, x3, i, tp); /* j, w, v */ |
149 | | |
150 | | /* x3 <-- w^2 - j - 2v */ |
151 | 0 | ecc_mod_sqr (&ecc->p, x3, w, tp); |
152 | 0 | ecc_mod_sub (&ecc->p, x3, x3, j); |
153 | 0 | ecc_mod_submul_1 (&ecc->p, x3, v, 2); |
154 | | |
155 | | /* y3 <-- w (v - x3) - 2 s1 j */ |
156 | 0 | ecc_mod_mul (&ecc->p, j, j, y3, tp); |
157 | 0 | ecc_mod_sub (&ecc->p, v, v, x3); |
158 | 0 | ecc_mod_mul (&ecc->p, y3, v, w, tp); |
159 | 0 | ecc_mod_submul_1 (&ecc->p, y3, j, 2); |
160 | |
|
161 | 0 | return 1; |
162 | 0 | } |