aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/crypto_ecc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/crypto_ecc.c')
-rw-r--r--src/lib/util/crypto_ecc.c956
1 files changed, 956 insertions, 0 deletions
diff --git a/src/lib/util/crypto_ecc.c b/src/lib/util/crypto_ecc.c
new file mode 100644
index 000000000..11c3e50d4
--- /dev/null
+++ b/src/lib/util/crypto_ecc.c
@@ -0,0 +1,956 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/crypto_ecc.c
23 * @brief public key cryptography (ECC) with libgcrypt
24 * @author Christian Grothoff
25 * @author Florian Dold
26 */
27
28#include "platform.h"
29#include <gcrypt.h>
30#include <sodium.h>
31#include "gnunet_util_lib.h"
32#include "benchmark.h"
33
34#define EXTRA_CHECKS 0
35
36/**
37 * IMPLEMENTATION NOTICE:
38 *
39 * ECDSA: We use a non-standard curve for ECDSA: Ed25519.
40 * For performance reasons, we use cryptographic operations from
41 * libsodium wherever we can get away with it, even though libsodium
42 * itself does not support ECDSA.
43 * This is why the sign and verifiy functionality from libgcrypt is
44 * required and used.
45 *
46 * EdDSA: We use a standard EdDSA construction.
47 * (We still use libgcrypt for hashing and RNG, but not EC)
48 *
49 * ECDHE: For both EdDSA and ECDSA keys, we use libsodium for
50 * ECDHE due to performance benefits over libgcrypt.
51 */
52
53/**
54 * Name of the curve we are using. Note that we have hard-coded
55 * structs that use 256 bits, so using a bigger curve will require
56 * changes that break stuff badly. The name of the curve given here
57 * must be agreed by all peers and be supported by libgcrypt.
58 */
59#define CURVE "Ed25519"
60
61#define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
62
63#define LOG_STRERROR(kind, syscall) \
64 GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
65
66#define LOG_STRERROR_FILE(kind, syscall, filename) \
67 GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, \
68 filename)
69
70/**
71 * Log an error message at log-level 'level' that indicates
72 * a failure of the command 'cmd' with the message given
73 * by gcry_strerror(rc).
74 */
75#define LOG_GCRY(level, cmd, rc) \
76 do \
77 { \
78 LOG (level, \
79 _ ("`%s' failed at %s:%d with error: %s\n"), \
80 cmd, \
81 __FILE__, \
82 __LINE__, \
83 gcry_strerror (rc)); \
84 } while (0)
85
86
87/**
88 * Extract values from an S-expression.
89 *
90 * @param array where to store the result(s)
91 * @param sexp S-expression to parse
92 * @param topname top-level name in the S-expression that is of interest
93 * @param elems names of the elements to extract
94 * @return 0 on success
95 */
96static int
97key_from_sexp (gcry_mpi_t *array,
98 gcry_sexp_t sexp,
99 const char *topname,
100 const char *elems)
101{
102 gcry_sexp_t list;
103 gcry_sexp_t l2;
104 unsigned int idx;
105
106 list = gcry_sexp_find_token (sexp, topname, 0);
107 if (! list)
108 return 1;
109 l2 = gcry_sexp_cadr (list);
110 gcry_sexp_release (list);
111 list = l2;
112 if (! list)
113 return 2;
114
115 idx = 0;
116 for (const char *s = elems; *s; s++, idx++)
117 {
118 l2 = gcry_sexp_find_token (list, s, 1);
119 if (! l2)
120 {
121 for (unsigned int i = 0; i < idx; i++)
122 {
123 gcry_free (array[i]);
124 array[i] = NULL;
125 }
126 gcry_sexp_release (list);
127 return 3; /* required parameter not found */
128 }
129 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
130 gcry_sexp_release (l2);
131 if (! array[idx])
132 {
133 for (unsigned int i = 0; i < idx; i++)
134 {
135 gcry_free (array[i]);
136 array[i] = NULL;
137 }
138 gcry_sexp_release (list);
139 return 4; /* required parameter is invalid */
140 }
141 }
142 gcry_sexp_release (list);
143 return 0;
144}
145
146
147/**
148 * Convert the given private key from the network format to the
149 * S-expression that can be used by libgcrypt.
150 *
151 * @param priv private key to decode
152 * @return NULL on error
153 */
154static gcry_sexp_t
155decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
156{
157 gcry_sexp_t result;
158 int rc;
159 uint8_t d[32];
160
161 for (size_t i = 0; i<32; i++)
162 d[i] = priv->d[31 - i];
163
164 rc = gcry_sexp_build (&result,
165 NULL,
166 "(private-key(ecc(curve \"" CURVE "\")"
167 "(d %b)))",
168 32,
169 d);
170 if (0 != rc)
171 {
172 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
173 GNUNET_assert (0);
174 }
175#if EXTRA_CHECKS
176 if (0 != (rc = gcry_pk_testkey (result)))
177 {
178 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
179 GNUNET_assert (0);
180 }
181#endif
182 return result;
183}
184
185
186void
187GNUNET_CRYPTO_ecdsa_key_get_public (
188 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
189 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
190{
191 BENCHMARK_START (ecdsa_key_get_public);
192 crypto_scalarmult_ed25519_base_noclamp (pub->q_y, priv->d);
193 BENCHMARK_END (ecdsa_key_get_public);
194}
195
196
197void
198GNUNET_CRYPTO_eddsa_key_get_public (
199 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
200 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
201{
202 unsigned char pk[crypto_sign_PUBLICKEYBYTES];
203 unsigned char sk[crypto_sign_SECRETKEYBYTES];
204
205 BENCHMARK_START (eddsa_key_get_public);
206 GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
207 GNUNET_memcpy (pub->q_y, pk, crypto_sign_PUBLICKEYBYTES);
208 sodium_memzero (sk, crypto_sign_SECRETKEYBYTES);
209 BENCHMARK_END (eddsa_key_get_public);
210}
211
212
213void
214GNUNET_CRYPTO_ecdhe_key_get_public (
215 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
216 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
217{
218 BENCHMARK_START (ecdhe_key_get_public);
219 GNUNET_assert (0 == crypto_scalarmult_base (pub->q_y, priv->d));
220 BENCHMARK_END (ecdhe_key_get_public);
221}
222
223
224char *
225GNUNET_CRYPTO_ecdsa_public_key_to_string (
226 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
227{
228 char *pubkeybuf;
229 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
230 char *end;
231
232 if (keylen % 5 > 0)
233 keylen += 5 - keylen % 5;
234 keylen /= 5;
235 pubkeybuf = GNUNET_malloc (keylen + 1);
236 end =
237 GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
238 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
239 pubkeybuf,
240 keylen);
241 if (NULL == end)
242 {
243 GNUNET_free (pubkeybuf);
244 return NULL;
245 }
246 *end = '\0';
247 return pubkeybuf;
248}
249
250
251char *
252GNUNET_CRYPTO_eddsa_public_key_to_string (
253 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
254{
255 char *pubkeybuf;
256 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
257 char *end;
258
259 if (keylen % 5 > 0)
260 keylen += 5 - keylen % 5;
261 keylen /= 5;
262 pubkeybuf = GNUNET_malloc (keylen + 1);
263 end =
264 GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
265 sizeof(struct GNUNET_CRYPTO_EddsaPublicKey),
266 pubkeybuf,
267 keylen);
268 if (NULL == end)
269 {
270 GNUNET_free (pubkeybuf);
271 return NULL;
272 }
273 *end = '\0';
274 return pubkeybuf;
275}
276
277
278char *
279GNUNET_CRYPTO_eddsa_private_key_to_string (
280 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
281{
282 char *privkeybuf;
283 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
284 char *end;
285
286 if (keylen % 5 > 0)
287 keylen += 5 - keylen % 5;
288 keylen /= 5;
289 privkeybuf = GNUNET_malloc (keylen + 1);
290 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
291 sizeof(
292 struct GNUNET_CRYPTO_EddsaPrivateKey),
293 privkeybuf,
294 keylen);
295 if (NULL == end)
296 {
297 GNUNET_free (privkeybuf);
298 return NULL;
299 }
300 *end = '\0';
301 return privkeybuf;
302}
303
304
305char *
306GNUNET_CRYPTO_ecdsa_private_key_to_string (
307 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
308{
309 char *privkeybuf;
310 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)) * 8;
311 char *end;
312
313 if (keylen % 5 > 0)
314 keylen += 5 - keylen % 5;
315 keylen /= 5;
316 privkeybuf = GNUNET_malloc (keylen + 1);
317 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
318 sizeof(
319 struct GNUNET_CRYPTO_EcdsaPrivateKey),
320 privkeybuf,
321 keylen);
322 if (NULL == end)
323 {
324 GNUNET_free (privkeybuf);
325 return NULL;
326 }
327 *end = '\0';
328 return privkeybuf;
329}
330
331
332enum GNUNET_GenericReturnValue
333GNUNET_CRYPTO_ecdsa_public_key_from_string (
334 const char *enc,
335 size_t enclen,
336 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
337{
338 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
339
340 if (keylen % 5 > 0)
341 keylen += 5 - keylen % 5;
342 keylen /= 5;
343 if (enclen != keylen)
344 return GNUNET_SYSERR;
345
346 if (GNUNET_OK !=
347 GNUNET_STRINGS_string_to_data (enc,
348 enclen,
349 pub,
350 sizeof(
351 struct GNUNET_CRYPTO_EcdsaPublicKey)))
352 return GNUNET_SYSERR;
353 return GNUNET_OK;
354}
355
356
357enum GNUNET_GenericReturnValue
358GNUNET_CRYPTO_eddsa_public_key_from_string (
359 const char *enc,
360 size_t enclen,
361 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
362{
363 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
364
365 if (keylen % 5 > 0)
366 keylen += 5 - keylen % 5;
367 keylen /= 5;
368 if (enclen != keylen)
369 return GNUNET_SYSERR;
370
371 if (GNUNET_OK !=
372 GNUNET_STRINGS_string_to_data (enc,
373 enclen,
374 pub,
375 sizeof(
376 struct GNUNET_CRYPTO_EddsaPublicKey)))
377 return GNUNET_SYSERR;
378 return GNUNET_OK;
379}
380
381
382enum GNUNET_GenericReturnValue
383GNUNET_CRYPTO_eddsa_private_key_from_string (
384 const char *enc,
385 size_t enclen,
386 struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
387{
388 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
389
390 if (keylen % 5 > 0)
391 keylen += 5 - keylen % 5;
392 keylen /= 5;
393 if (enclen != keylen)
394 return GNUNET_SYSERR;
395
396 if (GNUNET_OK !=
397 GNUNET_STRINGS_string_to_data (enc,
398 enclen,
399 priv,
400 sizeof(
401 struct GNUNET_CRYPTO_EddsaPrivateKey)))
402 return GNUNET_SYSERR;
403#if CRYPTO_BUG
404 if (GNUNET_OK != check_eddsa_key (priv))
405 {
406 GNUNET_break (0);
407 return GNUNET_OK;
408 }
409#endif
410 return GNUNET_OK;
411}
412
413
414void
415GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
416{
417 memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
418}
419
420
421void
422GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
423{
424 memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
425}
426
427
428void
429GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
430{
431 memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
432}
433
434
435void
436GNUNET_CRYPTO_ecdhe_key_create (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
437{
438 BENCHMARK_START (ecdhe_key_create);
439 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
440 pk,
441 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
442 BENCHMARK_END (ecdhe_key_create);
443}
444
445
446void
447GNUNET_CRYPTO_ecdsa_key_create (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
448{
449 BENCHMARK_START (ecdsa_key_create);
450 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
451 pk,
452 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
453 pk->d[0] &= 248;
454 pk->d[31] &= 127;
455 pk->d[31] |= 64;
456
457 BENCHMARK_END (ecdsa_key_create);
458}
459
460
461void
462GNUNET_CRYPTO_eddsa_key_create (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
463{
464 BENCHMARK_START (eddsa_key_create);
465 /*
466 * We do not clamp for EdDSA, since all functions that use the private key do
467 * their own clamping (just like in libsodium). What we call "private key"
468 * here, actually corresponds to the seed in libsodium.
469 *
470 * (Contrast this to ECDSA, where functions using the private key can't clamp
471 * due to properties needed for GNS. That is a worse/unsafer API, but
472 * required for the GNS constructions to work.)
473 */
474 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
475 pk,
476 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
477 BENCHMARK_END (eddsa_key_create);
478}
479
480
481const struct GNUNET_CRYPTO_EcdsaPrivateKey *
482GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
483{
484 /**
485 * 'anonymous' pseudonym (global static, d=1, public key = G
486 * (generator).
487 */
488 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
489 static int once;
490
491 if (once)
492 return &anonymous;
493 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
494 sizeof(anonymous.d),
495 GCRYMPI_CONST_ONE);
496 anonymous.d[0] &= 248;
497 anonymous.d[31] &= 127;
498 anonymous.d[31] |= 64;
499
500 once = 1;
501 return &anonymous;
502}
503
504
505/**
506 * Convert the data specified in the given purpose argument to an
507 * S-expression suitable for signature operations.
508 *
509 * @param purpose data to convert
510 * @return converted s-expression
511 */
512static gcry_sexp_t
513data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
514{
515 gcry_sexp_t data;
516 int rc;
517 /* Unlike EdDSA, libgcrypt expects a hash for ECDSA. */
518 struct GNUNET_HashCode hc;
519
520 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
521 if (0 != (rc = gcry_sexp_build (&data,
522 NULL,
523 "(data(flags rfc6979)(hash %s %b))",
524 "sha512",
525 (int) sizeof(hc),
526 &hc)))
527 {
528 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
529 return NULL;
530 }
531 return data;
532}
533
534
535enum GNUNET_GenericReturnValue
536GNUNET_CRYPTO_ecdsa_sign_ (
537 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
538 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
539 struct GNUNET_CRYPTO_EcdsaSignature *sig)
540{
541 gcry_sexp_t priv_sexp;
542 gcry_sexp_t sig_sexp;
543 gcry_sexp_t data;
544 int rc;
545 gcry_mpi_t rs[2];
546
547 BENCHMARK_START (ecdsa_sign);
548
549 priv_sexp = decode_private_ecdsa_key (priv);
550 data = data_to_ecdsa_value (purpose);
551 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
552 {
553 LOG (GNUNET_ERROR_TYPE_WARNING,
554 _ ("ECC signing failed at %s:%d: %s\n"),
555 __FILE__,
556 __LINE__,
557 gcry_strerror (rc));
558 gcry_sexp_release (data);
559 gcry_sexp_release (priv_sexp);
560 return GNUNET_SYSERR;
561 }
562 gcry_sexp_release (priv_sexp);
563 gcry_sexp_release (data);
564
565 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
566 'signature' */
567 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
568 {
569 GNUNET_break (0);
570 gcry_sexp_release (sig_sexp);
571 return GNUNET_SYSERR;
572 }
573 gcry_sexp_release (sig_sexp);
574 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
575 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
576 gcry_mpi_release (rs[0]);
577 gcry_mpi_release (rs[1]);
578
579 BENCHMARK_END (ecdsa_sign);
580
581 return GNUNET_OK;
582}
583
584
585enum GNUNET_GenericReturnValue
586GNUNET_CRYPTO_eddsa_sign_raw (
587 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
588 void *data,
589 size_t size,
590 struct GNUNET_CRYPTO_EddsaSignature *sig)
591{
592 unsigned char sk[crypto_sign_SECRETKEYBYTES];
593 unsigned char pk[crypto_sign_PUBLICKEYBYTES];
594 int res;
595
596 GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
597 res = crypto_sign_detached ((uint8_t *) sig,
598 NULL,
599 (uint8_t *) data,
600 size,
601 sk);
602 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
603}
604
605
606enum GNUNET_GenericReturnValue
607GNUNET_CRYPTO_eddsa_sign_ (
608 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
609 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
610 struct GNUNET_CRYPTO_EddsaSignature *sig)
611{
612
613 size_t mlen = ntohl (purpose->size);
614 unsigned char sk[crypto_sign_SECRETKEYBYTES];
615 unsigned char pk[crypto_sign_PUBLICKEYBYTES];
616 int res;
617
618 BENCHMARK_START (eddsa_sign);
619 GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
620 res = crypto_sign_detached ((uint8_t *) sig,
621 NULL,
622 (uint8_t *) purpose,
623 mlen,
624 sk);
625 BENCHMARK_END (eddsa_sign);
626 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
627}
628
629
630enum GNUNET_GenericReturnValue
631GNUNET_CRYPTO_ecdsa_verify_ (
632 uint32_t purpose,
633 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
634 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
635 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
636{
637 gcry_sexp_t data;
638 gcry_sexp_t sig_sexpr;
639 gcry_sexp_t pub_sexpr;
640 int rc;
641
642 BENCHMARK_START (ecdsa_verify);
643
644 if (purpose != ntohl (validate->purpose))
645 return GNUNET_SYSERR; /* purpose mismatch */
646
647 /* build s-expression for signature */
648 if (0 != (rc = gcry_sexp_build (&sig_sexpr,
649 NULL,
650 "(sig-val(ecdsa(r %b)(s %b)))",
651 (int) sizeof(sig->r),
652 sig->r,
653 (int) sizeof(sig->s),
654 sig->s)))
655 {
656 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
657 return GNUNET_SYSERR;
658 }
659 data = data_to_ecdsa_value (validate);
660 if (0 != (rc = gcry_sexp_build (&pub_sexpr,
661 NULL,
662 "(public-key(ecc(curve " CURVE ")(q %b)))",
663 (int) sizeof(pub->q_y),
664 pub->q_y)))
665 {
666 gcry_sexp_release (data);
667 gcry_sexp_release (sig_sexpr);
668 return GNUNET_SYSERR;
669 }
670 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
671 gcry_sexp_release (pub_sexpr);
672 gcry_sexp_release (data);
673 gcry_sexp_release (sig_sexpr);
674 if (0 != rc)
675 {
676 LOG (GNUNET_ERROR_TYPE_INFO,
677 _ ("ECDSA signature verification failed at %s:%d: %s\n"),
678 __FILE__,
679 __LINE__,
680 gcry_strerror (rc));
681 BENCHMARK_END (ecdsa_verify);
682 return GNUNET_SYSERR;
683 }
684 BENCHMARK_END (ecdsa_verify);
685 return GNUNET_OK;
686}
687
688
689enum GNUNET_GenericReturnValue
690GNUNET_CRYPTO_eddsa_verify_ (
691 uint32_t purpose,
692 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
693 const struct GNUNET_CRYPTO_EddsaSignature *sig,
694 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
695{
696 const unsigned char *m = (const void *) validate;
697 size_t mlen = ntohl (validate->size);
698 const unsigned char *s = (const void *) sig;
699
700 int res;
701
702 if (purpose != ntohl (validate->purpose))
703 return GNUNET_SYSERR; /* purpose mismatch */
704
705 BENCHMARK_START (eddsa_verify);
706
707 res = crypto_sign_verify_detached (s, m, mlen, pub->q_y);
708 BENCHMARK_END (eddsa_verify);
709 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
710}
711
712
713enum GNUNET_GenericReturnValue
714GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
715 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
716 struct GNUNET_HashCode *key_material)
717{
718 uint8_t p[crypto_scalarmult_BYTES];
719 if (0 != crypto_scalarmult (p, priv->d, pub->q_y))
720 return GNUNET_SYSERR;
721 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
722 return GNUNET_OK;
723}
724
725
726enum GNUNET_GenericReturnValue
727GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
728 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
729 struct GNUNET_HashCode *key_material)
730{
731 struct GNUNET_HashCode hc;
732 uint8_t a[crypto_scalarmult_SCALARBYTES];
733 uint8_t p[crypto_scalarmult_BYTES];
734
735 GNUNET_CRYPTO_hash (priv,
736 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
737 &hc);
738 memcpy (a, &hc, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
739 if (0 != crypto_scalarmult (p, a, pub->q_y))
740 return GNUNET_SYSERR;
741 GNUNET_CRYPTO_hash (p,
742 crypto_scalarmult_BYTES,
743 key_material);
744 return GNUNET_OK;
745}
746
747
748enum GNUNET_GenericReturnValue
749GNUNET_CRYPTO_eddsa_kem_decaps (const struct
750 GNUNET_CRYPTO_EddsaPrivateKey *priv,
751 const struct GNUNET_CRYPTO_EcdhePublicKey *c,
752 struct GNUNET_HashCode *key_material)
753{
754 return GNUNET_CRYPTO_eddsa_ecdh (priv, c, key_material);
755}
756
757
758enum GNUNET_GenericReturnValue
759GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
760 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
761 struct GNUNET_HashCode *key_material)
762{
763 uint8_t p[crypto_scalarmult_BYTES];
764
765 BENCHMARK_START (ecdsa_ecdh);
766 if (0 != crypto_scalarmult (p, priv->d, pub->q_y))
767 return GNUNET_SYSERR;
768 GNUNET_CRYPTO_hash (p,
769 crypto_scalarmult_BYTES,
770 key_material);
771 BENCHMARK_END (ecdsa_ecdh);
772 return GNUNET_OK;
773}
774
775
776enum GNUNET_GenericReturnValue
777GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
778 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
779 struct GNUNET_HashCode *key_material)
780{
781 uint8_t p[crypto_scalarmult_BYTES];
782 uint8_t curve25510_pk[crypto_scalarmult_BYTES];
783
784 if (0 != crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y))
785 return GNUNET_SYSERR;
786 if (0 != crypto_scalarmult (p, priv->d, curve25510_pk))
787 return GNUNET_SYSERR;
788 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
789 return GNUNET_OK;
790}
791
792
793enum GNUNET_GenericReturnValue
794GNUNET_CRYPTO_eddsa_kem_encaps (const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
795 struct GNUNET_CRYPTO_EcdhePublicKey *c,
796 struct GNUNET_HashCode *key_material)
797{
798 struct GNUNET_CRYPTO_EcdhePrivateKey sk;
799
800 GNUNET_CRYPTO_ecdhe_key_create (&sk);
801 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, c);
802 return GNUNET_CRYPTO_ecdh_eddsa (&sk, pub, key_material);
803}
804
805
806enum GNUNET_GenericReturnValue
807GNUNET_CRYPTO_ecdsa_fo_kem_encaps (const struct
808 GNUNET_CRYPTO_EcdsaPublicKey *pub,
809 struct GNUNET_CRYPTO_FoKemC *c,
810 struct GNUNET_HashCode *key_material)
811{
812 struct GNUNET_HashCode x;
813 struct GNUNET_HashCode ux;
814 struct GNUNET_HashCode w;
815 struct GNUNET_CRYPTO_EcdhePrivateKey sk;
816
817 // This is the input to the FO OWTF
818 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &x, sizeof(x));
819
820 // We build our OWTF using a FO-transformation of ElGamal:
821 // U(x)
822 GNUNET_CRYPTO_hash (&x, sizeof (x), &ux);
823 GNUNET_memcpy (&sk, &ux, sizeof (sk));
824
825 // B := g^U(x)
826 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, &c->pub);
827
828 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_ecdsa (&sk, pub, &w))
829 return -1;
830 // w xor x (one-time pad)
831 GNUNET_CRYPTO_hash_xor (&w, &x, &c->y);
832
833 // k := H(x) FIXME: U and H must be different?
834 GNUNET_memcpy (key_material, &ux, sizeof (ux));
835 return GNUNET_OK;
836}
837
838
839enum GNUNET_GenericReturnValue
840GNUNET_CRYPTO_eddsa_fo_kem_encaps (const struct
841 GNUNET_CRYPTO_EddsaPublicKey *pub,
842 struct GNUNET_CRYPTO_FoKemC *c,
843 struct GNUNET_HashCode *key_material)
844{
845 struct GNUNET_HashCode x;
846 struct GNUNET_HashCode ux;
847 struct GNUNET_HashCode w;
848 struct GNUNET_CRYPTO_EcdhePrivateKey sk;
849 enum GNUNET_GenericReturnValue ret;
850
851 // This is the input to the FO OWTF
852 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &x, sizeof(x));
853
854 // We build our OWTF using a FO-transformation of ElGamal:
855 // U(x)
856 GNUNET_CRYPTO_hash (&x, sizeof (x), &ux);
857 GNUNET_memcpy (&sk, &ux, sizeof (sk));
858
859 // B := g^U(x)
860 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, &c->pub);
861
862 ret = GNUNET_CRYPTO_ecdh_eddsa (&sk, pub, &w);
863 if (GNUNET_OK != ret)
864 return ret;
865 // w xor x (one-time pad)
866 GNUNET_CRYPTO_hash_xor (&w, &x, &c->y);
867
868 // k := H(x) FIXME: U and H must be different?
869 GNUNET_memcpy (key_material, &ux, sizeof (ux));
870 return GNUNET_OK;
871}
872
873
874static enum GNUNET_GenericReturnValue
875fo_kem_decaps (const struct GNUNET_HashCode *w,
876 const struct GNUNET_CRYPTO_FoKemC *c,
877 struct GNUNET_HashCode *key_material)
878{
879 struct GNUNET_HashCode x;
880 struct GNUNET_HashCode ux;
881 struct GNUNET_CRYPTO_EcdhePrivateKey sk;
882 struct GNUNET_CRYPTO_EcdhePublicKey pub_test;
883
884 // w xor x (one-time pad)
885 GNUNET_CRYPTO_hash_xor (w, &c->y, &x);
886
887 // We build our OWTF using a FO-transformation of ElGamal:
888 // U(x)
889 GNUNET_CRYPTO_hash (&x, sizeof (x), &ux);
890 GNUNET_memcpy (&sk, &ux, sizeof (sk));
891
892 // B := g^U(x)
893 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, &pub_test);
894
895 if (0 != memcmp (&pub_test, &c->pub, sizeof (c->pub)))
896 return GNUNET_SYSERR; // Reject
897
898 // k := H(x) FIXME: U and H must be different?
899 GNUNET_memcpy (key_material, &ux, sizeof (ux));
900 return GNUNET_OK;
901}
902
903
904/**
905 * This implementation is not testes/publicly exposed yet
906 */
907enum GNUNET_GenericReturnValue
908GNUNET_CRYPTO_eddsa_fo_kem_decaps (const struct
909 GNUNET_CRYPTO_EddsaPrivateKey *priv,
910 const struct GNUNET_CRYPTO_FoKemC *c,
911 struct GNUNET_HashCode *key_material)
912{
913 struct GNUNET_HashCode w;
914 enum GNUNET_GenericReturnValue ret;
915
916 ret = GNUNET_CRYPTO_eddsa_ecdh (priv, &c->pub, &w);
917 if (GNUNET_OK != ret)
918 return ret;
919 return fo_kem_decaps (&w, c, key_material);
920}
921
922
923enum GNUNET_GenericReturnValue
924GNUNET_CRYPTO_ecdsa_fo_kem_decaps (const struct
925 GNUNET_CRYPTO_EcdsaPrivateKey *priv,
926 struct GNUNET_CRYPTO_FoKemC *c,
927 struct GNUNET_HashCode *key_material)
928{
929 struct GNUNET_HashCode w;
930 enum GNUNET_GenericReturnValue ret;
931
932 ret = GNUNET_CRYPTO_ecdsa_ecdh (priv, &c->pub, &w);
933 if (GNUNET_OK != ret)
934 return ret;
935 return fo_kem_decaps (&w, c, key_material);
936}
937
938
939enum GNUNET_GenericReturnValue
940GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
941 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
942 struct GNUNET_HashCode *key_material)
943{
944 uint8_t p[crypto_scalarmult_BYTES];
945 uint8_t curve25510_pk[crypto_scalarmult_BYTES];
946
947 if (0 != crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y))
948 return GNUNET_SYSERR;
949 if (0 != crypto_scalarmult (p, priv->d, curve25510_pk))
950 return GNUNET_SYSERR;
951 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
952 return GNUNET_OK;
953}
954
955
956/* end of crypto_ecc.c */