/src/libgcrypt/cipher/ecc-misc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ecc-misc.c - Elliptic Curve miscellaneous functions |
2 | | * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc. |
3 | | * Copyright (C) 2013 g10 Code GmbH |
4 | | * |
5 | | * This file is part of Libgcrypt. |
6 | | * |
7 | | * Libgcrypt is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as |
9 | | * published by the Free Software Foundation; either version 2.1 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * Libgcrypt is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public |
18 | | * License along with this program; if not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include <config.h> |
22 | | #include <stdio.h> |
23 | | #include <stdlib.h> |
24 | | #include <string.h> |
25 | | #include <errno.h> |
26 | | |
27 | | #include "g10lib.h" |
28 | | #include "mpi.h" |
29 | | #include "cipher.h" |
30 | | #include "context.h" |
31 | | #include "ec-context.h" |
32 | | #include "ecc-common.h" |
33 | | |
34 | | |
35 | | /* |
36 | | * Release a curve object. |
37 | | */ |
38 | | void |
39 | | _gcry_ecc_curve_free (elliptic_curve_t *E) |
40 | 0 | { |
41 | 0 | mpi_free (E->p); E->p = NULL; |
42 | 0 | mpi_free (E->a); E->a = NULL; |
43 | 0 | mpi_free (E->b); E->b = NULL; |
44 | 0 | _gcry_mpi_point_free_parts (&E->G); |
45 | 0 | mpi_free (E->n); E->n = NULL; |
46 | 0 | } |
47 | | |
48 | | |
49 | | /* |
50 | | * Return a copy of a curve object. |
51 | | */ |
52 | | elliptic_curve_t |
53 | | _gcry_ecc_curve_copy (elliptic_curve_t E) |
54 | 0 | { |
55 | 0 | elliptic_curve_t R; |
56 | |
|
57 | 0 | R.model = E.model; |
58 | 0 | R.dialect = E.dialect; |
59 | 0 | R.name = E.name; |
60 | 0 | R.p = mpi_copy (E.p); |
61 | 0 | R.a = mpi_copy (E.a); |
62 | 0 | R.b = mpi_copy (E.b); |
63 | 0 | _gcry_mpi_point_init (&R.G); |
64 | 0 | point_set (&R.G, &E.G); |
65 | 0 | R.n = mpi_copy (E.n); |
66 | 0 | R.h = E.h; |
67 | |
|
68 | 0 | return R; |
69 | 0 | } |
70 | | |
71 | | |
72 | | /* |
73 | | * Return a description of the curve model. |
74 | | */ |
75 | | const char * |
76 | | _gcry_ecc_model2str (enum gcry_mpi_ec_models model) |
77 | 0 | { |
78 | 0 | const char *str = "?"; |
79 | 0 | switch (model) |
80 | 0 | { |
81 | 0 | case MPI_EC_WEIERSTRASS: str = "Weierstrass"; break; |
82 | 0 | case MPI_EC_MONTGOMERY: str = "Montgomery"; break; |
83 | 0 | case MPI_EC_EDWARDS: str = "Edwards"; break; |
84 | 0 | } |
85 | 0 | return str; |
86 | 0 | } |
87 | | |
88 | | |
89 | | /* |
90 | | * Return a description of the curve dialect. |
91 | | */ |
92 | | const char * |
93 | | _gcry_ecc_dialect2str (enum ecc_dialects dialect) |
94 | 0 | { |
95 | 0 | const char *str = "?"; |
96 | 0 | switch (dialect) |
97 | 0 | { |
98 | 0 | case ECC_DIALECT_STANDARD: str = "Standard"; break; |
99 | 0 | case ECC_DIALECT_ED25519: str = "Ed25519"; break; |
100 | 0 | case ECC_DIALECT_SAFECURVE: str = "SafeCurve"; break; |
101 | 0 | } |
102 | 0 | return str; |
103 | 0 | } |
104 | | |
105 | | |
106 | | /* Return an uncompressed point (X,Y) in P as a malloced buffer with |
107 | | * its byte length stored at R_LENGTH. May not be used for sensitive |
108 | | * data. */ |
109 | | unsigned char * |
110 | | _gcry_ecc_ec2os_buf (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p, |
111 | | unsigned int *r_length) |
112 | 0 | { |
113 | 0 | gpg_err_code_t rc; |
114 | 0 | int pbytes = (mpi_get_nbits (p)+7)/8; |
115 | 0 | size_t n; |
116 | 0 | unsigned char *buf, *ptr; |
117 | |
|
118 | 0 | buf = xmalloc ( 1 + 2*pbytes ); |
119 | 0 | *buf = 04; /* Uncompressed point. */ |
120 | 0 | ptr = buf+1; |
121 | 0 | rc = _gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, x); |
122 | 0 | if (rc) |
123 | 0 | log_fatal ("mpi_print failed: %s\n", gpg_strerror (rc)); |
124 | 0 | if (n < pbytes) |
125 | 0 | { |
126 | 0 | memmove (ptr+(pbytes-n), ptr, n); |
127 | 0 | memset (ptr, 0, (pbytes-n)); |
128 | 0 | } |
129 | 0 | ptr += pbytes; |
130 | 0 | rc = _gcry_mpi_print (GCRYMPI_FMT_USG, ptr, pbytes, &n, y); |
131 | 0 | if (rc) |
132 | 0 | log_fatal ("mpi_print failed: %s\n", gpg_strerror (rc)); |
133 | 0 | if (n < pbytes) |
134 | 0 | { |
135 | 0 | memmove (ptr+(pbytes-n), ptr, n); |
136 | 0 | memset (ptr, 0, (pbytes-n)); |
137 | 0 | } |
138 | |
|
139 | 0 | *r_length = 1 + 2*pbytes; |
140 | 0 | return buf; |
141 | 0 | } |
142 | | |
143 | | |
144 | | gcry_mpi_t |
145 | | _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) |
146 | 0 | { |
147 | 0 | unsigned char *buf; |
148 | 0 | unsigned int buflen; |
149 | |
|
150 | 0 | buf = _gcry_ecc_ec2os_buf (x, y, p, &buflen); |
151 | 0 | return mpi_set_opaque (NULL, buf, 8*buflen); |
152 | 0 | } |
153 | | |
154 | | /* Convert POINT into affine coordinates using the context CTX and |
155 | | return a newly allocated MPI. If the conversion is not possible |
156 | | NULL is returned. This function won't print an error message. */ |
157 | | gcry_mpi_t |
158 | | _gcry_mpi_ec_ec2os (gcry_mpi_point_t point, mpi_ec_t ec) |
159 | 0 | { |
160 | 0 | gcry_mpi_t g_x, g_y, result; |
161 | |
|
162 | 0 | g_x = mpi_new (0); |
163 | 0 | g_y = mpi_new (0); |
164 | 0 | if (_gcry_mpi_ec_get_affine (g_x, g_y, point, ec)) |
165 | 0 | result = NULL; |
166 | 0 | else |
167 | 0 | result = _gcry_ecc_ec2os (g_x, g_y, ec->p); |
168 | 0 | mpi_free (g_x); |
169 | 0 | mpi_free (g_y); |
170 | |
|
171 | 0 | return result; |
172 | 0 | } |
173 | | |
174 | | |
175 | | /* Decode octet string in VALUE into RESULT, in the format defined by SEC 1. |
176 | | RESULT must have been initialized and is set on success to the |
177 | | point given by VALUE. */ |
178 | | gpg_err_code_t |
179 | | _gcry_ecc_sec_decodepoint (gcry_mpi_t value, mpi_ec_t ec, mpi_point_t result) |
180 | 0 | { |
181 | 0 | gpg_err_code_t rc; |
182 | 0 | size_t n; |
183 | 0 | const unsigned char *buf; |
184 | 0 | unsigned char *buf_memory; |
185 | 0 | gcry_mpi_t x, y; |
186 | |
|
187 | 0 | if (mpi_is_opaque (value)) |
188 | 0 | { |
189 | 0 | unsigned int nbits; |
190 | |
|
191 | 0 | buf = mpi_get_opaque (value, &nbits); |
192 | 0 | if (!buf) |
193 | 0 | return GPG_ERR_INV_OBJ; |
194 | 0 | n = (nbits + 7)/8; |
195 | 0 | buf_memory = NULL; |
196 | 0 | } |
197 | 0 | else |
198 | 0 | { |
199 | 0 | n = (mpi_get_nbits (value)+7)/8; |
200 | 0 | buf_memory = xmalloc (n); |
201 | 0 | rc = _gcry_mpi_print (GCRYMPI_FMT_USG, buf_memory, n, &n, value); |
202 | 0 | if (rc) |
203 | 0 | { |
204 | 0 | xfree (buf_memory); |
205 | 0 | return rc; |
206 | 0 | } |
207 | 0 | buf = buf_memory; |
208 | 0 | } |
209 | | |
210 | 0 | if (n < 1) |
211 | 0 | { |
212 | 0 | xfree (buf_memory); |
213 | 0 | return GPG_ERR_INV_OBJ; |
214 | 0 | } |
215 | | |
216 | 0 | if (*buf == 2 || *buf == 3) |
217 | 0 | { |
218 | 0 | gcry_mpi_t x3; |
219 | 0 | gcry_mpi_t t; |
220 | 0 | gcry_mpi_t p1_4; |
221 | 0 | int y_bit = (*buf == 3); |
222 | |
|
223 | 0 | if (!mpi_test_bit (ec->p, 1)) |
224 | 0 | { |
225 | 0 | xfree (buf_memory); |
226 | 0 | return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ |
227 | 0 | } |
228 | | |
229 | 0 | n = n - 1; |
230 | 0 | rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL); |
231 | 0 | xfree (buf_memory); |
232 | 0 | if (rc) |
233 | 0 | return rc; |
234 | | |
235 | | /* |
236 | | * Recover Y. The Weierstrass curve: y^2 = x^3 + a*x + b |
237 | | */ |
238 | | |
239 | 0 | x3 = mpi_new (0); |
240 | 0 | t = mpi_new (0); |
241 | 0 | p1_4 = mpi_new (0); |
242 | 0 | y = mpi_new (0); |
243 | | |
244 | | /* Compute right hand side. */ |
245 | 0 | mpi_powm (x3, x, mpi_const (MPI_C_THREE), ec->p); |
246 | 0 | mpi_mul (t, ec->a, x); |
247 | 0 | mpi_mod (t, t, ec->p); |
248 | 0 | mpi_add (t, t, ec->b); |
249 | 0 | mpi_mod (t, t, ec->p); |
250 | 0 | mpi_add (t, t, x3); |
251 | 0 | mpi_mod (t, t, ec->p); |
252 | | |
253 | | /* |
254 | | * When p mod 4 = 3, modular square root of A can be computed by |
255 | | * A^((p+1)/4) mod p |
256 | | */ |
257 | | |
258 | | /* Compute (p+1)/4 into p1_4 */ |
259 | 0 | mpi_rshift (p1_4, ec->p, 2); |
260 | 0 | _gcry_mpi_add_ui (p1_4, p1_4, 1); |
261 | |
|
262 | 0 | mpi_powm (y, t, p1_4, ec->p); |
263 | |
|
264 | 0 | if (y_bit != mpi_test_bit (y, 0)) |
265 | 0 | mpi_sub (y, ec->p, y); |
266 | |
|
267 | 0 | mpi_free (p1_4); |
268 | 0 | mpi_free (t); |
269 | 0 | mpi_free (x3); |
270 | 0 | } |
271 | 0 | else if (*buf == 4) |
272 | 0 | { |
273 | 0 | if ( ((n-1)%2) ) |
274 | 0 | { |
275 | 0 | xfree (buf_memory); |
276 | 0 | return GPG_ERR_INV_OBJ; |
277 | 0 | } |
278 | 0 | n = (n-1)/2; |
279 | 0 | rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL); |
280 | 0 | if (rc) |
281 | 0 | { |
282 | 0 | xfree (buf_memory); |
283 | 0 | return rc; |
284 | 0 | } |
285 | 0 | rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL); |
286 | 0 | xfree (buf_memory); |
287 | 0 | if (rc) |
288 | 0 | { |
289 | 0 | mpi_free (x); |
290 | 0 | return rc; |
291 | 0 | } |
292 | 0 | } |
293 | 0 | else |
294 | 0 | { |
295 | 0 | xfree (buf_memory); |
296 | 0 | return GPG_ERR_INV_OBJ; |
297 | 0 | } |
298 | | |
299 | 0 | mpi_set (result->x, x); |
300 | 0 | mpi_set (result->y, y); |
301 | 0 | mpi_set_ui (result->z, 1); |
302 | |
|
303 | 0 | mpi_free (x); |
304 | 0 | mpi_free (y); |
305 | |
|
306 | 0 | return 0; |
307 | 0 | } |
308 | | |
309 | | |
310 | | /* Compute the public key from the the context EC. Obviously a |
311 | | requirement is that the secret key is available in EC. On success |
312 | | Q is returned; on error NULL. If Q is NULL a newly allocated point |
313 | | is returned. If G or D are given they override the values taken |
314 | | from EC. */ |
315 | | mpi_point_t |
316 | | _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec) |
317 | 0 | { |
318 | 0 | if (!ec->d || !ec->G || !ec->p || !ec->a) |
319 | 0 | return NULL; |
320 | 0 | if (ec->model == MPI_EC_EDWARDS && !ec->b) |
321 | 0 | return NULL; |
322 | | |
323 | 0 | if ((ec->dialect == ECC_DIALECT_ED25519 && (ec->flags & PUBKEY_FLAG_EDDSA)) |
324 | 0 | || (ec->model == MPI_EC_EDWARDS && ec->dialect == ECC_DIALECT_SAFECURVE)) |
325 | 0 | { |
326 | 0 | gcry_mpi_t a; |
327 | 0 | unsigned char *digest; |
328 | |
|
329 | 0 | if (_gcry_ecc_eddsa_compute_h_d (&digest, ec)) |
330 | 0 | return NULL; |
331 | | |
332 | 0 | a = mpi_snew (0); |
333 | 0 | _gcry_mpi_set_buffer (a, digest, 32, 0); |
334 | 0 | xfree (digest); |
335 | | |
336 | | /* And finally the public key. */ |
337 | 0 | if (!Q) |
338 | 0 | Q = mpi_point_new (0); |
339 | 0 | if (Q) |
340 | 0 | _gcry_mpi_ec_mul_point (Q, a, ec->G, ec); |
341 | 0 | mpi_free (a); |
342 | 0 | } |
343 | 0 | else |
344 | 0 | { |
345 | 0 | if (!Q) |
346 | 0 | Q = mpi_point_new (0); |
347 | 0 | if (Q) |
348 | 0 | _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec); |
349 | 0 | } |
350 | | |
351 | 0 | return Q; |
352 | 0 | } |
353 | | |
354 | | |
355 | | gpg_err_code_t |
356 | | _gcry_ecc_mont_encodepoint (gcry_mpi_t x, unsigned int nbits, |
357 | | int with_prefix, |
358 | | unsigned char **r_buffer, unsigned int *r_buflen) |
359 | 0 | { |
360 | 0 | unsigned char *rawmpi; |
361 | 0 | unsigned int rawmpilen; |
362 | |
|
363 | 0 | rawmpi = _gcry_mpi_get_buffer_extra (x, (nbits+7)/8, |
364 | 0 | with_prefix? -1 : 0, &rawmpilen, NULL); |
365 | 0 | if (rawmpi == NULL) |
366 | 0 | return gpg_err_code_from_syserror (); |
367 | | |
368 | 0 | if (with_prefix) |
369 | 0 | { |
370 | 0 | rawmpi[0] = 0x40; |
371 | 0 | rawmpilen++; |
372 | 0 | } |
373 | |
|
374 | 0 | *r_buffer = rawmpi; |
375 | 0 | *r_buflen = rawmpilen; |
376 | 0 | return 0; |
377 | 0 | } |
378 | | |
379 | | |
380 | | gpg_err_code_t |
381 | | _gcry_ecc_mont_decodepoint (gcry_mpi_t pk, mpi_ec_t ec, mpi_point_t result) |
382 | 0 | { |
383 | 0 | unsigned char *rawmpi; |
384 | 0 | unsigned int rawmpilen; |
385 | 0 | unsigned int nbytes = (ec->nbits+7)/8; |
386 | | |
387 | | /* |
388 | | * It is not reliable to assume that the first byte of 0x40 |
389 | | * means the prefix. |
390 | | * |
391 | | * For newer implementation, it is reliable since we always put |
392 | | * 0x40 for x-only coordinate. |
393 | | * |
394 | | * For data by older implementation (non-released development |
395 | | * version in 2015), there is no 0x40 prefix added. |
396 | | * |
397 | | * So, it is possible to have shorter length of data when it was |
398 | | * handled as MPI, removing preceding zeros. |
399 | | * |
400 | | * Besides, when data was parsed as MPI, we might have 0x00 |
401 | | * prefix (when the MSB in the first byte is set). |
402 | | */ |
403 | |
|
404 | 0 | if (mpi_is_opaque (pk)) |
405 | 0 | { |
406 | 0 | const unsigned char *buf; |
407 | 0 | unsigned char *p; |
408 | |
|
409 | 0 | buf = mpi_get_opaque (pk, &rawmpilen); |
410 | 0 | if (!buf) |
411 | 0 | return GPG_ERR_INV_OBJ; |
412 | 0 | rawmpilen = (rawmpilen + 7)/8; |
413 | |
|
414 | 0 | if (rawmpilen == nbytes + 1 |
415 | 0 | && (buf[0] == 0x00 || buf[0] == 0x40)) |
416 | 0 | { |
417 | 0 | rawmpilen--; |
418 | 0 | buf++; |
419 | 0 | } |
420 | 0 | else if (rawmpilen > nbytes) |
421 | 0 | return GPG_ERR_INV_OBJ; |
422 | | |
423 | 0 | rawmpi = xtrymalloc (nbytes); |
424 | 0 | if (!rawmpi) |
425 | 0 | return gpg_err_code_from_syserror (); |
426 | | |
427 | 0 | p = rawmpi + rawmpilen; |
428 | 0 | while (p > rawmpi) |
429 | 0 | *--p = *buf++; |
430 | |
|
431 | 0 | if (rawmpilen < nbytes) |
432 | 0 | memset (rawmpi + nbytes - rawmpilen, 0, nbytes - rawmpilen); |
433 | 0 | } |
434 | 0 | else |
435 | 0 | { |
436 | 0 | rawmpi = _gcry_mpi_get_buffer (pk, nbytes, &rawmpilen, NULL); |
437 | 0 | if (!rawmpi) |
438 | 0 | return gpg_err_code_from_syserror (); |
439 | 0 | if (rawmpilen > nbytes + BYTES_PER_MPI_LIMB) |
440 | 0 | { |
441 | 0 | xfree (rawmpi); |
442 | 0 | return GPG_ERR_INV_OBJ; |
443 | 0 | } |
444 | | /* |
445 | | * When we have the prefix (0x40 or 0x00), it comes at the end, |
446 | | * since it is taken by _gcry_mpi_get_buffer with little endian. |
447 | | * Just setting RAWMPILEN to NBYTES is enough in this case. |
448 | | * Othewise, RAWMPILEN is NBYTES already. |
449 | | */ |
450 | 0 | rawmpilen = nbytes; |
451 | 0 | } |
452 | | |
453 | 0 | if ((ec->nbits % 8)) |
454 | 0 | rawmpi[0] &= (1 << (ec->nbits % 8)) - 1; |
455 | 0 | _gcry_mpi_set_buffer (result->x, rawmpi, rawmpilen, 0); |
456 | 0 | xfree (rawmpi); |
457 | 0 | mpi_set_ui (result->z, 1); |
458 | |
|
459 | 0 | return 0; |
460 | 0 | } |