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.c971
1 files changed, 971 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..8ea17fda0
--- /dev/null
+++ b/src/lib/util/crypto_ecc.c
@@ -0,0 +1,971 @@
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
414static void
415buffer_clear (void *buf, size_t len)
416{
417#if HAVE_MEMSET_S
418 memset_s (buf, len, 0, len);
419#elif HAVE_EXPLICIT_BZERO
420 explicit_bzero (buf, len);
421#else
422 volatile unsigned char *p = buf;
423 while (len--)
424 *p++ = 0;
425#endif
426}
427
428
429void
430GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
431{
432 buffer_clear (pk, sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
433}
434
435
436void
437GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
438{
439 buffer_clear (pk, sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
440}
441
442
443void
444GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
445{
446 buffer_clear (pk, sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
447}
448
449
450void
451GNUNET_CRYPTO_ecdhe_key_create (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
452{
453 BENCHMARK_START (ecdhe_key_create);
454 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
455 pk,
456 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
457 BENCHMARK_END (ecdhe_key_create);
458}
459
460
461void
462GNUNET_CRYPTO_ecdsa_key_create (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
463{
464 BENCHMARK_START (ecdsa_key_create);
465 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
466 pk,
467 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
468 pk->d[0] &= 248;
469 pk->d[31] &= 127;
470 pk->d[31] |= 64;
471
472 BENCHMARK_END (ecdsa_key_create);
473}
474
475
476void
477GNUNET_CRYPTO_eddsa_key_create (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
478{
479 BENCHMARK_START (eddsa_key_create);
480 /*
481 * We do not clamp for EdDSA, since all functions that use the private key do
482 * their own clamping (just like in libsodium). What we call "private key"
483 * here, actually corresponds to the seed in libsodium.
484 *
485 * (Contrast this to ECDSA, where functions using the private key can't clamp
486 * due to properties needed for GNS. That is a worse/unsafer API, but
487 * required for the GNS constructions to work.)
488 */
489 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
490 pk,
491 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
492 BENCHMARK_END (eddsa_key_create);
493}
494
495
496const struct GNUNET_CRYPTO_EcdsaPrivateKey *
497GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
498{
499 /**
500 * 'anonymous' pseudonym (global static, d=1, public key = G
501 * (generator).
502 */
503 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
504 static int once;
505
506 if (once)
507 return &anonymous;
508 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
509 sizeof(anonymous.d),
510 GCRYMPI_CONST_ONE);
511 anonymous.d[0] &= 248;
512 anonymous.d[31] &= 127;
513 anonymous.d[31] |= 64;
514
515 once = 1;
516 return &anonymous;
517}
518
519
520/**
521 * Convert the data specified in the given purpose argument to an
522 * S-expression suitable for signature operations.
523 *
524 * @param purpose data to convert
525 * @return converted s-expression
526 */
527static gcry_sexp_t
528data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
529{
530 gcry_sexp_t data;
531 int rc;
532 /* Unlike EdDSA, libgcrypt expects a hash for ECDSA. */
533 struct GNUNET_HashCode hc;
534
535 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
536 if (0 != (rc = gcry_sexp_build (&data,
537 NULL,
538 "(data(flags rfc6979)(hash %s %b))",
539 "sha512",
540 (int) sizeof(hc),
541 &hc)))
542 {
543 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
544 return NULL;
545 }
546 return data;
547}
548
549
550enum GNUNET_GenericReturnValue
551GNUNET_CRYPTO_ecdsa_sign_ (
552 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
553 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
554 struct GNUNET_CRYPTO_EcdsaSignature *sig)
555{
556 gcry_sexp_t priv_sexp;
557 gcry_sexp_t sig_sexp;
558 gcry_sexp_t data;
559 int rc;
560 gcry_mpi_t rs[2];
561
562 BENCHMARK_START (ecdsa_sign);
563
564 priv_sexp = decode_private_ecdsa_key (priv);
565 data = data_to_ecdsa_value (purpose);
566 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
567 {
568 LOG (GNUNET_ERROR_TYPE_WARNING,
569 _ ("ECC signing failed at %s:%d: %s\n"),
570 __FILE__,
571 __LINE__,
572 gcry_strerror (rc));
573 gcry_sexp_release (data);
574 gcry_sexp_release (priv_sexp);
575 return GNUNET_SYSERR;
576 }
577 gcry_sexp_release (priv_sexp);
578 gcry_sexp_release (data);
579
580 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
581 'signature' */
582 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
583 {
584 GNUNET_break (0);
585 gcry_sexp_release (sig_sexp);
586 return GNUNET_SYSERR;
587 }
588 gcry_sexp_release (sig_sexp);
589 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
590 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
591 gcry_mpi_release (rs[0]);
592 gcry_mpi_release (rs[1]);
593
594 BENCHMARK_END (ecdsa_sign);
595
596 return GNUNET_OK;
597}
598
599
600enum GNUNET_GenericReturnValue
601GNUNET_CRYPTO_eddsa_sign_raw (
602 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
603 void *data,
604 size_t size,
605 struct GNUNET_CRYPTO_EddsaSignature *sig)
606{
607 unsigned char sk[crypto_sign_SECRETKEYBYTES];
608 unsigned char pk[crypto_sign_PUBLICKEYBYTES];
609 int res;
610
611 GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
612 res = crypto_sign_detached ((uint8_t *) sig,
613 NULL,
614 (uint8_t *) data,
615 size,
616 sk);
617 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
618}
619
620
621enum GNUNET_GenericReturnValue
622GNUNET_CRYPTO_eddsa_sign_ (
623 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
624 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
625 struct GNUNET_CRYPTO_EddsaSignature *sig)
626{
627
628 size_t mlen = ntohl (purpose->size);
629 unsigned char sk[crypto_sign_SECRETKEYBYTES];
630 unsigned char pk[crypto_sign_PUBLICKEYBYTES];
631 int res;
632
633 BENCHMARK_START (eddsa_sign);
634 GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
635 res = crypto_sign_detached ((uint8_t *) sig,
636 NULL,
637 (uint8_t *) purpose,
638 mlen,
639 sk);
640 BENCHMARK_END (eddsa_sign);
641 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
642}
643
644
645enum GNUNET_GenericReturnValue
646GNUNET_CRYPTO_ecdsa_verify_ (
647 uint32_t purpose,
648 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
649 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
650 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
651{
652 gcry_sexp_t data;
653 gcry_sexp_t sig_sexpr;
654 gcry_sexp_t pub_sexpr;
655 int rc;
656
657 BENCHMARK_START (ecdsa_verify);
658
659 if (purpose != ntohl (validate->purpose))
660 return GNUNET_SYSERR; /* purpose mismatch */
661
662 /* build s-expression for signature */
663 if (0 != (rc = gcry_sexp_build (&sig_sexpr,
664 NULL,
665 "(sig-val(ecdsa(r %b)(s %b)))",
666 (int) sizeof(sig->r),
667 sig->r,
668 (int) sizeof(sig->s),
669 sig->s)))
670 {
671 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
672 return GNUNET_SYSERR;
673 }
674 data = data_to_ecdsa_value (validate);
675 if (0 != (rc = gcry_sexp_build (&pub_sexpr,
676 NULL,
677 "(public-key(ecc(curve " CURVE ")(q %b)))",
678 (int) sizeof(pub->q_y),
679 pub->q_y)))
680 {
681 gcry_sexp_release (data);
682 gcry_sexp_release (sig_sexpr);
683 return GNUNET_SYSERR;
684 }
685 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
686 gcry_sexp_release (pub_sexpr);
687 gcry_sexp_release (data);
688 gcry_sexp_release (sig_sexpr);
689 if (0 != rc)
690 {
691 LOG (GNUNET_ERROR_TYPE_INFO,
692 _ ("ECDSA signature verification failed at %s:%d: %s\n"),
693 __FILE__,
694 __LINE__,
695 gcry_strerror (rc));
696 BENCHMARK_END (ecdsa_verify);
697 return GNUNET_SYSERR;
698 }
699 BENCHMARK_END (ecdsa_verify);
700 return GNUNET_OK;
701}
702
703
704enum GNUNET_GenericReturnValue
705GNUNET_CRYPTO_eddsa_verify_ (
706 uint32_t purpose,
707 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
708 const struct GNUNET_CRYPTO_EddsaSignature *sig,
709 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
710{
711 const unsigned char *m = (const void *) validate;
712 size_t mlen = ntohl (validate->size);
713 const unsigned char *s = (const void *) sig;
714
715 int res;
716
717 if (purpose != ntohl (validate->purpose))
718 return GNUNET_SYSERR; /* purpose mismatch */
719
720 BENCHMARK_START (eddsa_verify);
721
722 res = crypto_sign_verify_detached (s, m, mlen, pub->q_y);
723 BENCHMARK_END (eddsa_verify);
724 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
725}
726
727
728enum GNUNET_GenericReturnValue
729GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
730 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
731 struct GNUNET_HashCode *key_material)
732{
733 uint8_t p[crypto_scalarmult_BYTES];
734 if (0 != crypto_scalarmult (p, priv->d, pub->q_y))
735 return GNUNET_SYSERR;
736 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
737 return GNUNET_OK;
738}
739
740
741enum GNUNET_GenericReturnValue
742GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
743 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
744 struct GNUNET_HashCode *key_material)
745{
746 struct GNUNET_HashCode hc;
747 uint8_t a[crypto_scalarmult_SCALARBYTES];
748 uint8_t p[crypto_scalarmult_BYTES];
749
750 GNUNET_CRYPTO_hash (priv,
751 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
752 &hc);
753 memcpy (a, &hc, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
754 if (0 != crypto_scalarmult (p, a, pub->q_y))
755 return GNUNET_SYSERR;
756 GNUNET_CRYPTO_hash (p,
757 crypto_scalarmult_BYTES,
758 key_material);
759 return GNUNET_OK;
760}
761
762
763enum GNUNET_GenericReturnValue
764GNUNET_CRYPTO_eddsa_kem_decaps (const struct
765 GNUNET_CRYPTO_EddsaPrivateKey *priv,
766 const struct GNUNET_CRYPTO_EcdhePublicKey *c,
767 struct GNUNET_HashCode *key_material)
768{
769 return GNUNET_CRYPTO_eddsa_ecdh (priv, c, key_material);
770}
771
772
773enum GNUNET_GenericReturnValue
774GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
775 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
776 struct GNUNET_HashCode *key_material)
777{
778 uint8_t p[crypto_scalarmult_BYTES];
779
780 BENCHMARK_START (ecdsa_ecdh);
781 if (0 != crypto_scalarmult (p, priv->d, pub->q_y))
782 return GNUNET_SYSERR;
783 GNUNET_CRYPTO_hash (p,
784 crypto_scalarmult_BYTES,
785 key_material);
786 BENCHMARK_END (ecdsa_ecdh);
787 return GNUNET_OK;
788}
789
790
791enum GNUNET_GenericReturnValue
792GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
793 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
794 struct GNUNET_HashCode *key_material)
795{
796 uint8_t p[crypto_scalarmult_BYTES];
797 uint8_t curve25510_pk[crypto_scalarmult_BYTES];
798
799 if (0 != crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y))
800 return GNUNET_SYSERR;
801 if (0 != crypto_scalarmult (p, priv->d, curve25510_pk))
802 return GNUNET_SYSERR;
803 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
804 return GNUNET_OK;
805}
806
807
808enum GNUNET_GenericReturnValue
809GNUNET_CRYPTO_eddsa_kem_encaps (const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
810 struct GNUNET_CRYPTO_EcdhePublicKey *c,
811 struct GNUNET_HashCode *key_material)
812{
813 struct GNUNET_CRYPTO_EcdhePrivateKey sk;
814
815 GNUNET_CRYPTO_ecdhe_key_create (&sk);
816 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, c);
817 return GNUNET_CRYPTO_ecdh_eddsa (&sk, pub, key_material);
818}
819
820
821enum GNUNET_GenericReturnValue
822GNUNET_CRYPTO_ecdsa_fo_kem_encaps (const struct
823 GNUNET_CRYPTO_EcdsaPublicKey *pub,
824 struct GNUNET_CRYPTO_FoKemC *c,
825 struct GNUNET_HashCode *key_material)
826{
827 struct GNUNET_HashCode x;
828 struct GNUNET_HashCode ux;
829 struct GNUNET_HashCode w;
830 struct GNUNET_CRYPTO_EcdhePrivateKey sk;
831
832 // This is the input to the FO OWTF
833 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &x, sizeof(x));
834
835 // We build our OWTF using a FO-transformation of ElGamal:
836 // U(x)
837 GNUNET_CRYPTO_hash (&x, sizeof (x), &ux);
838 GNUNET_memcpy (&sk, &ux, sizeof (sk));
839
840 // B := g^U(x)
841 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, &c->pub);
842
843 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_ecdsa (&sk, pub, &w))
844 return -1;
845 // w xor x (one-time pad)
846 GNUNET_CRYPTO_hash_xor (&w, &x, &c->y);
847
848 // k := H(x) FIXME: U and H must be different?
849 GNUNET_memcpy (key_material, &ux, sizeof (ux));
850 return GNUNET_OK;
851}
852
853
854enum GNUNET_GenericReturnValue
855GNUNET_CRYPTO_eddsa_fo_kem_encaps (const struct
856 GNUNET_CRYPTO_EddsaPublicKey *pub,
857 struct GNUNET_CRYPTO_FoKemC *c,
858 struct GNUNET_HashCode *key_material)
859{
860 struct GNUNET_HashCode x;
861 struct GNUNET_HashCode ux;
862 struct GNUNET_HashCode w;
863 struct GNUNET_CRYPTO_EcdhePrivateKey sk;
864 enum GNUNET_GenericReturnValue ret;
865
866 // This is the input to the FO OWTF
867 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &x, sizeof(x));
868
869 // We build our OWTF using a FO-transformation of ElGamal:
870 // U(x)
871 GNUNET_CRYPTO_hash (&x, sizeof (x), &ux);
872 GNUNET_memcpy (&sk, &ux, sizeof (sk));
873
874 // B := g^U(x)
875 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, &c->pub);
876
877 ret = GNUNET_CRYPTO_ecdh_eddsa (&sk, pub, &w);
878 if (GNUNET_OK != ret)
879 return ret;
880 // w xor x (one-time pad)
881 GNUNET_CRYPTO_hash_xor (&w, &x, &c->y);
882
883 // k := H(x) FIXME: U and H must be different?
884 GNUNET_memcpy (key_material, &ux, sizeof (ux));
885 return GNUNET_OK;
886}
887
888
889static enum GNUNET_GenericReturnValue
890fo_kem_decaps (const struct GNUNET_HashCode *w,
891 const struct GNUNET_CRYPTO_FoKemC *c,
892 struct GNUNET_HashCode *key_material)
893{
894 struct GNUNET_HashCode x;
895 struct GNUNET_HashCode ux;
896 struct GNUNET_CRYPTO_EcdhePrivateKey sk;
897 struct GNUNET_CRYPTO_EcdhePublicKey pub_test;
898
899 // w xor x (one-time pad)
900 GNUNET_CRYPTO_hash_xor (w, &c->y, &x);
901
902 // We build our OWTF using a FO-transformation of ElGamal:
903 // U(x)
904 GNUNET_CRYPTO_hash (&x, sizeof (x), &ux);
905 GNUNET_memcpy (&sk, &ux, sizeof (sk));
906
907 // B := g^U(x)
908 GNUNET_CRYPTO_ecdhe_key_get_public (&sk, &pub_test);
909
910 if (0 != memcmp (&pub_test, &c->pub, sizeof (c->pub)))
911 return GNUNET_SYSERR; // Reject
912
913 // k := H(x) FIXME: U and H must be different?
914 GNUNET_memcpy (key_material, &ux, sizeof (ux));
915 return GNUNET_OK;
916}
917
918
919/**
920 * This implementation is not testes/publicly exposed yet
921 */
922enum GNUNET_GenericReturnValue
923GNUNET_CRYPTO_eddsa_fo_kem_decaps (const struct
924 GNUNET_CRYPTO_EddsaPrivateKey *priv,
925 const struct GNUNET_CRYPTO_FoKemC *c,
926 struct GNUNET_HashCode *key_material)
927{
928 struct GNUNET_HashCode w;
929 enum GNUNET_GenericReturnValue ret;
930
931 ret = GNUNET_CRYPTO_eddsa_ecdh (priv, &c->pub, &w);
932 if (GNUNET_OK != ret)
933 return ret;
934 return fo_kem_decaps (&w, c, key_material);
935}
936
937
938enum GNUNET_GenericReturnValue
939GNUNET_CRYPTO_ecdsa_fo_kem_decaps (const struct
940 GNUNET_CRYPTO_EcdsaPrivateKey *priv,
941 struct GNUNET_CRYPTO_FoKemC *c,
942 struct GNUNET_HashCode *key_material)
943{
944 struct GNUNET_HashCode w;
945 enum GNUNET_GenericReturnValue ret;
946
947 ret = GNUNET_CRYPTO_ecdsa_ecdh (priv, &c->pub, &w);
948 if (GNUNET_OK != ret)
949 return ret;
950 return fo_kem_decaps (&w, c, key_material);
951}
952
953
954enum GNUNET_GenericReturnValue
955GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
956 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
957 struct GNUNET_HashCode *key_material)
958{
959 uint8_t p[crypto_scalarmult_BYTES];
960 uint8_t curve25510_pk[crypto_scalarmult_BYTES];
961
962 if (0 != crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y))
963 return GNUNET_SYSERR;
964 if (0 != crypto_scalarmult (p, priv->d, curve25510_pk))
965 return GNUNET_SYSERR;
966 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
967 return GNUNET_OK;
968}
969
970
971/* end of crypto_ecc.c */