aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/crypto_pkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/crypto_pkey.c')
-rw-r--r--src/lib/util/crypto_pkey.c618
1 files changed, 618 insertions, 0 deletions
diff --git a/src/lib/util/crypto_pkey.c b/src/lib/util/crypto_pkey.c
new file mode 100644
index 000000000..0a55b3b65
--- /dev/null
+++ b/src/lib/util/crypto_pkey.c
@@ -0,0 +1,618 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2016, 2021 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_pkey.c
23 * @brief api to interact handle generic public keys
24 * @author Martin Schanzenbach
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29
30
31static enum GNUNET_GenericReturnValue
32check_key_type (uint32_t type)
33{
34 switch (type)
35 {
36 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
37 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
38 return GNUNET_OK;
39 default:
40 return GNUNET_SYSERR;
41 }
42 return GNUNET_SYSERR;
43}
44
45
46ssize_t
47GNUNET_CRYPTO_private_key_get_length (const struct
48 GNUNET_CRYPTO_PrivateKey *key)
49{
50 switch (ntohl (key->type))
51 {
52 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
53 return sizeof (key->type) + sizeof (key->ecdsa_key);
54 break;
55 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
56 return sizeof (key->type) + sizeof (key->eddsa_key);
57 break;
58 default:
59 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
60 "Got key type %u\n", ntohl (key->type));
61 GNUNET_break (0);
62 }
63 return -1;
64}
65
66
67ssize_t
68GNUNET_CRYPTO_public_key_get_length (const struct
69 GNUNET_CRYPTO_PublicKey *key)
70{
71 switch (ntohl (key->type))
72 {
73 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
74 return sizeof (key->type) + sizeof (key->ecdsa_key);
75 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
76 return sizeof (key->type) + sizeof (key->eddsa_key);
77 default:
78 GNUNET_break (0);
79 }
80 return -1;
81}
82
83
84ssize_t
85GNUNET_CRYPTO_private_key_length_by_type (enum GNUNET_CRYPTO_KeyType kt)
86{
87 switch (kt)
88 {
89 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
90 return sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
91 break;
92 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
93 return sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
94 break;
95 default:
96 GNUNET_break (0);
97 }
98 return -1;
99}
100
101
102enum GNUNET_GenericReturnValue
103GNUNET_CRYPTO_read_public_key_from_buffer (const void *buffer,
104 size_t len,
105 struct GNUNET_CRYPTO_PublicKey *
106 key,
107 size_t *kb_read)
108{
109 if (len < sizeof (key->type))
110 return GNUNET_SYSERR;
111 GNUNET_memcpy (&key->type,
112 buffer,
113 sizeof (key->type));
114 ssize_t length = GNUNET_CRYPTO_public_key_get_length (key);
115 if (len < length)
116 return GNUNET_SYSERR;
117 if (length < 0)
118 return GNUNET_SYSERR;
119 GNUNET_memcpy (&key->ecdsa_key,
120 buffer + sizeof (key->type),
121 length - sizeof (key->type));
122 *kb_read = length;
123 return GNUNET_OK;
124}
125
126
127ssize_t
128GNUNET_CRYPTO_write_public_key_to_buffer (const struct
129 GNUNET_CRYPTO_PublicKey *key,
130 void*buffer,
131 size_t len)
132{
133 const ssize_t length = GNUNET_CRYPTO_public_key_get_length (key);
134 if (len < length)
135 return -1;
136 if (length < 0)
137 return -2;
138 GNUNET_memcpy (buffer, &(key->type), sizeof (key->type));
139 GNUNET_memcpy (buffer + sizeof (key->type), &(key->ecdsa_key), length
140 - sizeof (key->type));
141 return length;
142}
143
144
145enum GNUNET_GenericReturnValue
146GNUNET_CRYPTO_read_private_key_from_buffer (const void *buffer,
147 size_t len,
148 struct
149 GNUNET_CRYPTO_PrivateKey *key,
150 size_t *kb_read)
151{
152 if (len < sizeof (key->type))
153 return GNUNET_SYSERR;
154 GNUNET_memcpy (&key->type,
155 buffer,
156 sizeof (key->type));
157 ssize_t length = GNUNET_CRYPTO_private_key_get_length (key);
158 if (len < length)
159 return GNUNET_SYSERR;
160 if (length < 0)
161 return GNUNET_SYSERR;
162 GNUNET_memcpy (&key->ecdsa_key,
163 buffer + sizeof (key->type),
164 length - sizeof (key->type));
165 *kb_read = length;
166 return GNUNET_OK;
167}
168
169
170ssize_t
171GNUNET_CRYPTO_write_private_key_to_buffer (const struct
172 GNUNET_CRYPTO_PrivateKey *key,
173 void *buffer,
174 size_t len)
175{
176 const ssize_t length = GNUNET_CRYPTO_private_key_get_length (key);
177 if (len < length)
178 return -1;
179 if (length < 0)
180 return -2;
181 GNUNET_memcpy (buffer, &(key->type), sizeof (key->type));
182 GNUNET_memcpy (buffer + sizeof (key->type), &(key->ecdsa_key), length
183 - sizeof (key->type));
184 return length;
185}
186
187
188ssize_t
189GNUNET_CRYPTO_signature_get_length (const struct
190 GNUNET_CRYPTO_Signature *sig)
191{
192 switch (ntohl (sig->type))
193 {
194 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
195 return sizeof (sig->type) + sizeof (sig->ecdsa_signature);
196 break;
197 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
198 return sizeof (sig->type) + sizeof (sig->eddsa_signature);
199 break;
200 default:
201 GNUNET_break (0);
202 }
203 return -1;
204}
205
206
207ssize_t
208GNUNET_CRYPTO_signature_get_raw_length_by_type (uint32_t type)
209{
210 switch (ntohl (type))
211 {
212 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
213 return sizeof (struct GNUNET_CRYPTO_EcdsaSignature);
214 break;
215 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
216 return sizeof (struct GNUNET_CRYPTO_EddsaSignature);
217 break;
218 default:
219 GNUNET_break (0);
220 }
221 return -1;
222}
223
224
225ssize_t
226GNUNET_CRYPTO_read_signature_from_buffer (struct
227 GNUNET_CRYPTO_Signature *sig,
228 const void*buffer,
229 size_t len)
230{
231 if (len < sizeof (sig->type))
232 return -1;
233 GNUNET_memcpy (&(sig->type), buffer, sizeof (sig->type));
234 const ssize_t length = GNUNET_CRYPTO_signature_get_length (sig);
235 if (len < length)
236 return -1;
237 if (length < 0)
238 return -2;
239 GNUNET_memcpy (&(sig->ecdsa_signature), buffer + sizeof (sig->type), length
240 - sizeof (sig->type));
241 return length;
242}
243
244
245ssize_t
246GNUNET_CRYPTO_write_signature_to_buffer (const struct
247 GNUNET_CRYPTO_Signature *sig,
248 void*buffer,
249 size_t len)
250{
251 const ssize_t length = GNUNET_CRYPTO_signature_get_length (sig);
252 if (len < length)
253 return -1;
254 if (length < 0)
255 return -2;
256 GNUNET_memcpy (buffer, &(sig->type), sizeof (sig->type));
257 GNUNET_memcpy (buffer + sizeof (sig->type), &(sig->ecdsa_signature), length
258 - sizeof (sig->type));
259 return length;
260}
261
262
263enum GNUNET_GenericReturnValue
264GNUNET_CRYPTO_sign_raw_ (const struct
265 GNUNET_CRYPTO_PrivateKey *priv,
266 const struct
267 GNUNET_CRYPTO_EccSignaturePurpose *purpose,
268 unsigned char *sig)
269{
270 switch (ntohl (priv->type))
271 {
272 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
273 return GNUNET_CRYPTO_ecdsa_sign_ (&(priv->ecdsa_key), purpose,
274 (struct
275 GNUNET_CRYPTO_EcdsaSignature*) sig);
276 break;
277 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
278 return GNUNET_CRYPTO_eddsa_sign_ (&(priv->eddsa_key), purpose,
279 (struct
280 GNUNET_CRYPTO_EddsaSignature*) sig);
281 break;
282 default:
283 GNUNET_break (0);
284 }
285
286 return GNUNET_SYSERR;
287}
288
289
290enum GNUNET_GenericReturnValue
291GNUNET_CRYPTO_sign_ (const struct
292 GNUNET_CRYPTO_PrivateKey *priv,
293 const struct
294 GNUNET_CRYPTO_EccSignaturePurpose *purpose,
295 struct GNUNET_CRYPTO_Signature *sig)
296{
297 sig->type = priv->type;
298 switch (ntohl (priv->type))
299 {
300 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
301 return GNUNET_CRYPTO_ecdsa_sign_ (&(priv->ecdsa_key), purpose,
302 &(sig->ecdsa_signature));
303 break;
304 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
305 return GNUNET_CRYPTO_eddsa_sign_ (&(priv->eddsa_key), purpose,
306 &(sig->eddsa_signature));
307 break;
308 default:
309 GNUNET_break (0);
310 }
311
312 return GNUNET_SYSERR;
313}
314
315
316enum GNUNET_GenericReturnValue
317GNUNET_CRYPTO_signature_verify_ (uint32_t purpose,
318 const struct
319 GNUNET_CRYPTO_EccSignaturePurpose *validate,
320 const struct GNUNET_CRYPTO_Signature *sig,
321 const struct GNUNET_CRYPTO_PublicKey *pub)
322{
323 /* check type matching of 'sig' and 'pub' */
324 GNUNET_assert (ntohl (pub->type) == ntohl (sig->type));
325 switch (ntohl (pub->type))
326 {
327 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
328 return GNUNET_CRYPTO_ecdsa_verify_ (purpose, validate,
329 &(sig->ecdsa_signature),
330 &(pub->ecdsa_key));
331 break;
332 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
333 return GNUNET_CRYPTO_eddsa_verify_ (purpose, validate,
334 &(sig->eddsa_signature),
335 &(pub->eddsa_key));
336 break;
337 default:
338 GNUNET_break (0);
339 }
340
341 return GNUNET_SYSERR;
342}
343
344
345enum GNUNET_GenericReturnValue
346GNUNET_CRYPTO_signature_verify_raw_ (uint32_t purpose,
347 const struct
348 GNUNET_CRYPTO_EccSignaturePurpose *
349 validate,
350 const unsigned char *sig,
351 const struct
352 GNUNET_CRYPTO_PublicKey *pub)
353{
354 switch (ntohl (pub->type))
355 {
356 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
357 return GNUNET_CRYPTO_ecdsa_verify_ (purpose, validate,
358 (struct
359 GNUNET_CRYPTO_EcdsaSignature*) sig,
360 &(pub->ecdsa_key));
361 break;
362 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
363 return GNUNET_CRYPTO_eddsa_verify_ (purpose, validate,
364 (struct
365 GNUNET_CRYPTO_EddsaSignature*) sig,
366 &(pub->eddsa_key));
367 break;
368 default:
369 GNUNET_break (0);
370 }
371
372 return GNUNET_SYSERR;
373}
374
375
376ssize_t
377GNUNET_CRYPTO_encrypt_old (const void *block,
378 size_t size,
379 const struct GNUNET_CRYPTO_PublicKey *pub,
380 struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
381 void *result)
382{
383 struct GNUNET_CRYPTO_EcdhePrivateKey pk;
384 GNUNET_CRYPTO_ecdhe_key_create (&pk);
385 struct GNUNET_HashCode hash;
386 switch (ntohl (pub->type))
387 {
388 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
389 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_ecdsa (&pk, &(pub->ecdsa_key),
390 &hash))
391 return -1;
392 break;
393 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
394 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdh_eddsa (&pk, &(pub->eddsa_key),
395 &hash))
396 return -1;
397 break;
398 default:
399 return -1;
400 }
401 GNUNET_CRYPTO_ecdhe_key_get_public (&pk, ecc);
402 GNUNET_CRYPTO_ecdhe_key_clear (&pk);
403 struct GNUNET_CRYPTO_SymmetricSessionKey key;
404 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
405 GNUNET_CRYPTO_hash_to_aes_key (&hash, &key, &iv);
406 GNUNET_CRYPTO_zero_keys (&hash, sizeof(hash));
407 const ssize_t encrypted = GNUNET_CRYPTO_symmetric_encrypt (block, size, &key,
408 &iv, result);
409 GNUNET_CRYPTO_zero_keys (&key, sizeof(key));
410 GNUNET_CRYPTO_zero_keys (&iv, sizeof(iv));
411 return encrypted;
412}
413
414
415enum GNUNET_GenericReturnValue
416GNUNET_CRYPTO_encrypt (const void *pt,
417 size_t pt_size,
418 const struct GNUNET_CRYPTO_PublicKey *pub,
419 void *ct_buf,
420 size_t ct_size)
421{
422 struct GNUNET_HashCode k;
423 struct GNUNET_CRYPTO_FoKemC kemc;
424 struct GNUNET_CRYPTO_FoKemC *kemc_buf = (struct GNUNET_CRYPTO_FoKemC*) ct_buf;
425 unsigned char *encrypted_data = (unsigned char*) &kemc_buf[1];
426 unsigned char nonce[crypto_secretbox_NONCEBYTES];
427 unsigned char key[crypto_secretbox_KEYBYTES];
428
429 if (ct_size < pt_size + GNUNET_CRYPTO_ENCRYPT_OVERHEAD_BYTES)
430 {
431 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
432 "Output buffer size for ciphertext too small: Got %lu, want >=%lu\n",
433 ct_size, pt_size + GNUNET_CRYPTO_ENCRYPT_OVERHEAD_BYTES);
434 return GNUNET_SYSERR;
435 }
436 switch (ntohl (pub->type))
437 {
438 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
439 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_fo_kem_encaps (&(pub->ecdsa_key),
440 &kemc,
441 &k))
442 return GNUNET_SYSERR;
443 break;
444 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
445 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_fo_kem_encaps (&pub->eddsa_key,
446 &kemc,
447 &k))
448 return GNUNET_SYSERR;
449 break;
450 default:
451 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported key type\n");
452 return GNUNET_SYSERR;
453 }
454 memcpy (key, &k, crypto_secretbox_KEYBYTES);
455 memcpy (nonce, ((char* ) &k) + crypto_secretbox_KEYBYTES,
456 crypto_secretbox_NONCEBYTES);
457 if (crypto_secretbox_easy (encrypted_data, pt, pt_size, nonce, key))
458 return GNUNET_SYSERR;
459 memcpy (kemc_buf, &kemc, sizeof (kemc));
460 return GNUNET_OK;
461}
462
463
464enum GNUNET_GenericReturnValue
465GNUNET_CRYPTO_decrypt (const void *ct_buf,
466 size_t ct_size,
467 const struct GNUNET_CRYPTO_PrivateKey *priv,
468 void *pt,
469 size_t pt_size)
470{
471 struct GNUNET_HashCode k;
472 struct GNUNET_CRYPTO_FoKemC *kemc = (struct GNUNET_CRYPTO_FoKemC*) ct_buf;
473 unsigned char *encrypted_data = (unsigned char*) &kemc[1];
474 unsigned char nonce[crypto_secretbox_NONCEBYTES];
475 unsigned char key[crypto_secretbox_KEYBYTES];
476 size_t expected_pt_len = ct_size - GNUNET_CRYPTO_ENCRYPT_OVERHEAD_BYTES;
477
478 if (pt_size < expected_pt_len)
479 {
480 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
481 "Output buffer size for plaintext too small: Got %lu, want >=%lu\n",
482 pt_size, expected_pt_len);
483 return GNUNET_SYSERR;
484 }
485 switch (ntohl (priv->type))
486 {
487 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
488 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_fo_kem_decaps (&(priv->ecdsa_key),
489 kemc,
490 &k))
491 return GNUNET_SYSERR;
492 break;
493 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
494 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_fo_kem_decaps (&(priv->eddsa_key),
495 kemc,
496 &k))
497 return GNUNET_SYSERR;
498 break;
499 default:
500 return GNUNET_SYSERR;
501 }
502 memcpy (key, &k, crypto_secretbox_KEYBYTES);
503 memcpy (nonce, ((char* ) &k) + crypto_secretbox_KEYBYTES,
504 crypto_secretbox_NONCEBYTES);
505 if (crypto_secretbox_open_easy (pt, encrypted_data, ct_size - sizeof (*kemc),
506 nonce, key))
507 return GNUNET_SYSERR;
508 return GNUNET_OK;
509}
510
511
512ssize_t
513GNUNET_CRYPTO_decrypt_old (const void *block,
514 size_t size,
515 const struct GNUNET_CRYPTO_PrivateKey *priv,
516 const struct GNUNET_CRYPTO_EcdhePublicKey *ecc,
517 void *result)
518{
519 struct GNUNET_HashCode hash;
520 switch (ntohl (priv->type))
521 {
522 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
523 if (GNUNET_SYSERR == GNUNET_CRYPTO_ecdsa_ecdh (&(priv->ecdsa_key), ecc,
524 &hash))
525 return -1;
526 break;
527 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
528 if (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_ecdh (&(priv->eddsa_key), ecc,
529 &hash))
530 return -1;
531 break;
532 default:
533 return -1;
534 }
535 struct GNUNET_CRYPTO_SymmetricSessionKey key;
536 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
537 GNUNET_CRYPTO_hash_to_aes_key (&hash, &key, &iv);
538 GNUNET_CRYPTO_zero_keys (&hash, sizeof(hash));
539 const ssize_t decrypted = GNUNET_CRYPTO_symmetric_decrypt (block, size, &key,
540 &iv, result);
541 GNUNET_CRYPTO_zero_keys (&key, sizeof(key));
542 GNUNET_CRYPTO_zero_keys (&iv, sizeof(iv));
543 return decrypted;
544}
545
546
547char *
548GNUNET_CRYPTO_public_key_to_string (const struct
549 GNUNET_CRYPTO_PublicKey *key)
550{
551 size_t size = GNUNET_CRYPTO_public_key_get_length (key);
552 return GNUNET_STRINGS_data_to_string_alloc (key,
553 size);
554}
555
556
557char *
558GNUNET_CRYPTO_private_key_to_string (const struct
559 GNUNET_CRYPTO_PrivateKey *key)
560{
561 size_t size = GNUNET_CRYPTO_private_key_get_length (key);
562 return GNUNET_STRINGS_data_to_string_alloc (key,
563 size);
564}
565
566
567enum GNUNET_GenericReturnValue
568GNUNET_CRYPTO_public_key_from_string (const char *str,
569 struct GNUNET_CRYPTO_PublicKey *key)
570{
571 enum GNUNET_GenericReturnValue ret;
572 ret = GNUNET_STRINGS_string_to_data (str,
573 strlen (str),
574 key,
575 sizeof (*key));
576 if (GNUNET_OK != ret)
577 return GNUNET_SYSERR;
578 return check_key_type (ntohl (key->type));
579
580}
581
582
583enum GNUNET_GenericReturnValue
584GNUNET_CRYPTO_private_key_from_string (const char *str,
585 struct GNUNET_CRYPTO_PrivateKey *key)
586{
587 enum GNUNET_GenericReturnValue ret;
588 ret = GNUNET_STRINGS_string_to_data (str,
589 strlen (str),
590 key,
591 sizeof (*key));
592 if (GNUNET_OK != ret)
593 return GNUNET_SYSERR;
594 return check_key_type (ntohl (key->type));
595}
596
597enum GNUNET_GenericReturnValue
598GNUNET_CRYPTO_key_get_public (const struct
599 GNUNET_CRYPTO_PrivateKey *privkey,
600 struct GNUNET_CRYPTO_PublicKey *key)
601{
602 key->type = privkey->type;
603 switch (ntohl (privkey->type))
604 {
605 case GNUNET_PUBLIC_KEY_TYPE_ECDSA:
606 GNUNET_CRYPTO_ecdsa_key_get_public (&privkey->ecdsa_key,
607 &key->ecdsa_key);
608 break;
609 case GNUNET_PUBLIC_KEY_TYPE_EDDSA:
610 GNUNET_CRYPTO_eddsa_key_get_public (&privkey->eddsa_key,
611 &key->eddsa_key);
612 break;
613 default:
614 GNUNET_break (0);
615 return GNUNET_SYSERR;
616 }
617 return GNUNET_OK;
618}