Always pad fingerprints to 16 characters
[project/usign.git] / ed25519.c
1 /* Edwards curve operations
2 * Daniel Beer <dlbeer@gmail.com>, 9 Jan 2014
3 *
4 * This file is in the public domain.
5 */
6
7 #include "ed25519.h"
8
9 /* Base point is (numbers wrapped):
10 *
11 * x = 151122213495354007725011514095885315114
12 * 54012693041857206046113283949847762202
13 * y = 463168356949264781694283940034751631413
14 * 07993866256225615783033603165251855960
15 *
16 * y is derived by transforming the original Montgomery base (u=9). x
17 * is the corresponding positive coordinate for the new curve equation.
18 * t is x*y.
19 */
20 const struct ed25519_pt ed25519_base = {
21 .x = {
22 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9,
23 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69,
24 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
25 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
26 },
27 .y = {
28 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
29 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
30 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
31 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66
32 },
33 .t = {
34 0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d,
35 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20,
36 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66,
37 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67
38 },
39 .z = {1, 0}
40 };
41
42 static const struct ed25519_pt ed25519_neutral = {
43 .x = {0},
44 .y = {1, 0},
45 .t = {0},
46 .z = {1, 0}
47 };
48
49 /* Conversion to and from projective coordinates */
50 void ed25519_project(struct ed25519_pt *p,
51 const uint8_t *x, const uint8_t *y)
52 {
53 f25519_copy(p->x, x);
54 f25519_copy(p->y, y);
55 f25519_load(p->z, 1);
56 f25519_mul__distinct(p->t, x, y);
57 }
58
59 void ed25519_unproject(uint8_t *x, uint8_t *y,
60 const struct ed25519_pt *p)
61 {
62 uint8_t z1[F25519_SIZE];
63
64 f25519_inv__distinct(z1, p->z);
65 f25519_mul__distinct(x, p->x, z1);
66 f25519_mul__distinct(y, p->y, z1);
67
68 f25519_normalize(x);
69 f25519_normalize(y);
70 }
71
72 /* Compress/uncompress points. We compress points by storing the x
73 * coordinate and the parity of the y coordinate.
74 *
75 * Rearranging the curve equation, we obtain explicit formulae for the
76 * coordinates:
77 *
78 * x = sqrt((y^2-1) / (1+dy^2))
79 * y = sqrt((x^2+1) / (1-dx^2))
80 *
81 * Where d = (-121665/121666), or:
82 *
83 * d = 370957059346694393431380835087545651895
84 * 42113879843219016388785533085940283555
85 */
86
87 static const uint8_t ed25519_d[F25519_SIZE] = {
88 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
89 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
90 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
91 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
92 };
93
94 void ed25519_pack(uint8_t *c, const uint8_t *x, const uint8_t *y)
95 {
96 uint8_t tmp[F25519_SIZE];
97 uint8_t parity;
98
99 f25519_copy(tmp, x);
100 f25519_normalize(tmp);
101 parity = (tmp[0] & 1) << 7;
102
103 f25519_copy(c, y);
104 f25519_normalize(c);
105 c[31] |= parity;
106 }
107
108 uint8_t ed25519_try_unpack(uint8_t *x, uint8_t *y, const uint8_t *comp)
109 {
110 const int parity = comp[31] >> 7;
111 uint8_t a[F25519_SIZE];
112 uint8_t b[F25519_SIZE];
113 uint8_t c[F25519_SIZE];
114
115 /* Unpack y */
116 f25519_copy(y, comp);
117 y[31] &= 127;
118
119 /* Compute c = y^2 */
120 f25519_mul__distinct(c, y, y);
121
122 /* Compute b = (1+dy^2)^-1 */
123 f25519_mul__distinct(b, c, ed25519_d);
124 f25519_add(a, b, f25519_one);
125 f25519_inv__distinct(b, a);
126
127 /* Compute a = y^2-1 */
128 f25519_sub(a, c, f25519_one);
129
130 /* Compute c = a*b = (y^2-1)/(1-dy^2) */
131 f25519_mul__distinct(c, a, b);
132
133 /* Compute a, b = +/-sqrt(c), if c is square */
134 f25519_sqrt(a, c);
135 f25519_neg(b, a);
136
137 /* Select one of them, based on the compressed parity bit */
138 f25519_select(x, a, b, (a[0] ^ parity) & 1);
139
140 /* Verify that x^2 = c */
141 f25519_mul__distinct(a, x, x);
142 f25519_normalize(a);
143 f25519_normalize(c);
144
145 return f25519_eq(a, c);
146 }
147
148 /* k = 2d */
149 static const uint8_t ed25519_k[F25519_SIZE] = {
150 0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb,
151 0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00,
152 0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19,
153 0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24
154 };
155
156 void ed25519_add(struct ed25519_pt *r,
157 const struct ed25519_pt *p1, const struct ed25519_pt *p2)
158 {
159 /* Explicit formulas database: add-2008-hwcd-3
160 *
161 * source 2008 Hisil--Wong--Carter--Dawson,
162 * http://eprint.iacr.org/2008/522, Section 3.1
163 * appliesto extended-1
164 * parameter k
165 * assume k = 2 d
166 * compute A = (Y1-X1)(Y2-X2)
167 * compute B = (Y1+X1)(Y2+X2)
168 * compute C = T1 k T2
169 * compute D = Z1 2 Z2
170 * compute E = B - A
171 * compute F = D - C
172 * compute G = D + C
173 * compute H = B + A
174 * compute X3 = E F
175 * compute Y3 = G H
176 * compute T3 = E H
177 * compute Z3 = F G
178 */
179 uint8_t a[F25519_SIZE];
180 uint8_t b[F25519_SIZE];
181 uint8_t c[F25519_SIZE];
182 uint8_t d[F25519_SIZE];
183 uint8_t e[F25519_SIZE];
184 uint8_t f[F25519_SIZE];
185 uint8_t g[F25519_SIZE];
186 uint8_t h[F25519_SIZE];
187
188 /* A = (Y1-X1)(Y2-X2) */
189 f25519_sub(c, p1->y, p1->x);
190 f25519_sub(d, p2->y, p2->x);
191 f25519_mul__distinct(a, c, d);
192
193 /* B = (Y1+X1)(Y2+X2) */
194 f25519_add(c, p1->y, p1->x);
195 f25519_add(d, p2->y, p2->x);
196 f25519_mul__distinct(b, c, d);
197
198 /* C = T1 k T2 */
199 f25519_mul__distinct(d, p1->t, p2->t);
200 f25519_mul__distinct(c, d, ed25519_k);
201
202 /* D = Z1 2 Z2 */
203 f25519_mul__distinct(d, p1->z, p2->z);
204 f25519_add(d, d, d);
205
206 /* E = B - A */
207 f25519_sub(e, b, a);
208
209 /* F = D - C */
210 f25519_sub(f, d, c);
211
212 /* G = D + C */
213 f25519_add(g, d, c);
214
215 /* H = B + A */
216 f25519_add(h, b, a);
217
218 /* X3 = E F */
219 f25519_mul__distinct(r->x, e, f);
220
221 /* Y3 = G H */
222 f25519_mul__distinct(r->y, g, h);
223
224 /* T3 = E H */
225 f25519_mul__distinct(r->t, e, h);
226
227 /* Z3 = F G */
228 f25519_mul__distinct(r->z, f, g);
229 }
230
231 static void ed25519_double(struct ed25519_pt *r, const struct ed25519_pt *p)
232 {
233 /* Explicit formulas database: dbl-2008-hwcd
234 *
235 * source 2008 Hisil--Wong--Carter--Dawson,
236 * http://eprint.iacr.org/2008/522, Section 3.3
237 * compute A = X1^2
238 * compute B = Y1^2
239 * compute C = 2 Z1^2
240 * compute D = a A
241 * compute E = (X1+Y1)^2-A-B
242 * compute G = D + B
243 * compute F = G - C
244 * compute H = D - B
245 * compute X3 = E F
246 * compute Y3 = G H
247 * compute T3 = E H
248 * compute Z3 = F G
249 */
250 uint8_t a[F25519_SIZE];
251 uint8_t b[F25519_SIZE];
252 uint8_t c[F25519_SIZE];
253 uint8_t e[F25519_SIZE];
254 uint8_t f[F25519_SIZE];
255 uint8_t g[F25519_SIZE];
256 uint8_t h[F25519_SIZE];
257
258 /* A = X1^2 */
259 f25519_mul__distinct(a, p->x, p->x);
260
261 /* B = Y1^2 */
262 f25519_mul__distinct(b, p->y, p->y);
263
264 /* C = 2 Z1^2 */
265 f25519_mul__distinct(c, p->z, p->z);
266 f25519_add(c, c, c);
267
268 /* D = a A (alter sign) */
269 /* E = (X1+Y1)^2-A-B */
270 f25519_add(f, p->x, p->y);
271 f25519_mul__distinct(e, f, f);
272 f25519_sub(e, e, a);
273 f25519_sub(e, e, b);
274
275 /* G = D + B */
276 f25519_sub(g, b, a);
277
278 /* F = G - C */
279 f25519_sub(f, g, c);
280
281 /* H = D - B */
282 f25519_neg(h, b);
283 f25519_sub(h, h, a);
284
285 /* X3 = E F */
286 f25519_mul__distinct(r->x, e, f);
287
288 /* Y3 = G H */
289 f25519_mul__distinct(r->y, g, h);
290
291 /* T3 = E H */
292 f25519_mul__distinct(r->t, e, h);
293
294 /* Z3 = F G */
295 f25519_mul__distinct(r->z, f, g);
296 }
297
298 void ed25519_smult(struct ed25519_pt *r_out, const struct ed25519_pt *p,
299 const uint8_t *e)
300 {
301 struct ed25519_pt r;
302 int i;
303
304 ed25519_copy(&r, &ed25519_neutral);
305
306 for (i = 255; i >= 0; i--) {
307 const uint8_t bit = (e[i >> 3] >> (i & 7)) & 1;
308 struct ed25519_pt s;
309
310 ed25519_double(&r, &r);
311 ed25519_add(&s, &r, p);
312
313 f25519_select(r.x, r.x, s.x, bit);
314 f25519_select(r.y, r.y, s.y, bit);
315 f25519_select(r.z, r.z, s.z, bit);
316 f25519_select(r.t, r.t, s.t, bit);
317 }
318
319 ed25519_copy(r_out, &r);
320 }