aboutsummaryrefslogtreecommitdiff
path: root/src/util/anastasis_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/anastasis_crypto.c')
-rw-r--r--src/util/anastasis_crypto.c637
1 files changed, 637 insertions, 0 deletions
diff --git a/src/util/anastasis_crypto.c b/src/util/anastasis_crypto.c
new file mode 100644
index 0000000..ace0162
--- /dev/null
+++ b/src/util/anastasis_crypto.c
@@ -0,0 +1,637 @@
1/*
2 This file is part of Anastasis
3 Copyright (C) 2020 Taler Systems SA
4
5 Anastasis is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Lesser General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file lib/anastasis_crypto.c
18 * @brief anastasis crypto api
19 * @author Christian Grothoff
20 * @author Dominik Meister
21 * @author Dennis Neufeld
22 */
23
24#include "platform.h"
25#include "anastasis_crypto_lib.h"
26#include <gcrypt.h>
27#include <taler/taler_json_lib.h>
28#include <gnunet/gnunet_util_lib.h>
29#include <string.h>
30
31#if defined(DEBUG) || defined(DEBUG2)
32#define SCRYPT_ITERATION 1
33
34#else
35#define SCRYPT_ITERATION 1000
36#endif
37
38
39void
40ANASTASIS_hash_answer (uint64_t code,
41 struct GNUNET_HashCode *hashed_code)
42{
43 char cbuf[40];
44
45 GNUNET_snprintf (cbuf,
46 sizeof (cbuf),
47 "%llu",
48 (unsigned long long) code);
49 GNUNET_CRYPTO_hash (cbuf,
50 strlen (cbuf),
51 hashed_code);
52}
53
54
55void
56ANASTASIS_CRYPTO_secure_answer_hash (
57 const char *answer,
58 const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid,
59 const struct ANASTASIS_CRYPTO_QuestionSaltP *salt,
60 struct GNUNET_HashCode *result)
61{
62 struct GNUNET_HashCode pow;
63
64 GNUNET_CRYPTO_pow_hash (&salt->pow_salt,
65 answer,
66 strlen (answer),
67 &pow);
68 GNUNET_assert (GNUNET_YES ==
69 GNUNET_CRYPTO_kdf (
70 result,
71 sizeof (*result),
72 "Anastasis-secure-question-uuid-salting",
73 strlen ("Anastasis-secure-question-uuid-salting"),
74 &pow,
75 sizeof (pow),
76 uuid,
77 sizeof (*uuid),
78 NULL,
79 0));
80}
81
82
83/**
84 * Compute @a key and @a iv.
85 *
86 * @param key_material key for calculation
87 * @param key_m_len length of key
88 * @param nonce nonce for calculation
89 * @param salt salt value for calculation
90 * @param[out] key where to write the en-/description key
91 * @param[out] iv where to write the IV
92 */
93static void
94get_iv_key (const void *key_material,
95 size_t key_m_len,
96 const struct ANASTASIS_CRYPTO_NonceP *nonce,
97 const char *salt,
98 const struct ANASTASIS_CRYPTO_SymKeyP *key,
99 struct ANASTASIS_CRYPTO_IvP *iv)
100{
101 char res[sizeof (struct ANASTASIS_CRYPTO_SymKeyP)
102 + sizeof (struct ANASTASIS_CRYPTO_IvP)];
103
104 if (GNUNET_YES !=
105 GNUNET_CRYPTO_hkdf (res,
106 sizeof (res),
107 GCRY_MD_SHA512,
108 GCRY_MD_SHA256,
109 key_material,
110 key_m_len,
111 nonce,
112 sizeof (struct ANASTASIS_CRYPTO_NonceP),
113 salt,
114 strlen (salt),
115 NULL,
116 0))
117 {
118 GNUNET_break (0);
119 return;
120 }
121 memcpy ((void *) key,
122 res,
123 sizeof (*key));
124 memcpy (iv,
125 &res[sizeof (*key)],
126 sizeof (*iv));
127}
128
129
130/**
131 * Encryption of data like recovery document etc.
132 *
133 * @param nonce value to use for the nonce
134 * @param key key which is used to derive a key/iv pair from
135 * @param key_len length of key
136 * @param data data to encrypt
137 * @param data_size size of the data
138 * @param salt salt value which is used for key derivation
139 * @param res[out] ciphertext output
140 * @param res_size[out] size of the ciphertext
141 */
142static void
143anastasis_encrypt (const struct ANASTASIS_CRYPTO_NonceP *nonce,
144 const void *key,
145 size_t key_len,
146 const void *data,
147 size_t data_size,
148 const char *salt,
149 void **res,
150 size_t *res_size)
151{
152 struct ANASTASIS_CRYPTO_NonceP *nonceptr;
153 gcry_cipher_hd_t cipher;
154 struct ANASTASIS_CRYPTO_SymKeyP sym_key;
155 struct ANASTASIS_CRYPTO_IvP iv;
156 int rc;
157 struct ANASTASIS_CRYPTO_AesTagP *tag;
158 char *ciphertext;
159
160 *res_size = data_size
161 + sizeof (struct ANASTASIS_CRYPTO_NonceP)
162 + sizeof (struct ANASTASIS_CRYPTO_AesTagP);
163 if (*res_size <= data_size)
164 {
165 GNUNET_break (0);
166 return;
167 }
168 *res = GNUNET_malloc (*res_size);
169 if (*res_size != data_size
170 + sizeof (struct ANASTASIS_CRYPTO_NonceP)
171 + sizeof (struct ANASTASIS_CRYPTO_AesTagP))
172 {
173 GNUNET_break (0);
174 return;
175 }
176 nonceptr = (struct ANASTASIS_CRYPTO_NonceP *) *res;
177 tag = (struct ANASTASIS_CRYPTO_AesTagP *) &nonceptr[1];
178 ciphertext = (char *) &tag[1];
179 memcpy (nonceptr,
180 nonce,
181 sizeof (*nonce));
182 get_iv_key (key,
183 key_len,
184 nonce,
185 salt,
186 &sym_key,
187 &iv);
188 GNUNET_assert (0 ==
189 gcry_cipher_open (&cipher,
190 GCRY_CIPHER_AES256,
191 GCRY_CIPHER_MODE_GCM,
192 0));
193 rc = gcry_cipher_setkey (cipher,
194 &sym_key,
195 sizeof (sym_key));
196 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
197 rc = gcry_cipher_setiv (cipher,
198 &iv,
199 sizeof (iv));
200 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
201
202 GNUNET_assert (0 ==
203 gcry_cipher_encrypt (cipher,
204 ciphertext,
205 data_size,
206 data,
207 data_size));
208 GNUNET_assert (0 ==
209 gcry_cipher_gettag (cipher,
210 tag,
211 sizeof (struct ANASTASIS_CRYPTO_AesTagP)));
212 gcry_cipher_close (cipher);
213}
214
215
216/**
217 * Decryption of data like encrypted recovery document etc.
218 *
219 * @param key key which is used to derive a key/iv pair from
220 * @param key_len length of key
221 * @param data data to decrypt
222 * @param data_size size of the data
223 * @param salt salt value which is used for key derivation
224 * @param res[out] plaintext output
225 * @param res_size[out] size of the plaintext
226 */
227static void
228anastasis_decrypt (const void *key,
229 size_t key_len,
230 const void *data,
231 size_t data_size,
232 const char *salt,
233 void **res,
234 size_t *res_size)
235{
236 const struct ANASTASIS_CRYPTO_NonceP *nonce;
237 gcry_cipher_hd_t cipher;
238 const struct ANASTASIS_CRYPTO_SymKeyP sym_key;
239 struct ANASTASIS_CRYPTO_IvP iv;
240 int rc;
241 const struct ANASTASIS_CRYPTO_AesTagP *tag;
242 const char *ciphertext;
243
244 *res_size = data_size
245 - sizeof (struct ANASTASIS_CRYPTO_NonceP)
246 - sizeof (struct ANASTASIS_CRYPTO_AesTagP);
247 if (*res_size >= data_size)
248 {
249 GNUNET_break (0);
250 return;
251 }
252 *res = GNUNET_malloc (*res_size);
253 if (*res_size != data_size
254 - sizeof (struct ANASTASIS_CRYPTO_NonceP)
255 - sizeof (struct ANASTASIS_CRYPTO_AesTagP))
256 {
257 GNUNET_break (0);
258 GNUNET_free (*res);
259 return;
260 }
261
262 nonce = (const struct ANASTASIS_CRYPTO_NonceP *) data;
263 tag = (struct ANASTASIS_CRYPTO_AesTagP *) &nonce[1];
264 ciphertext = (const char *) &tag[1];
265 get_iv_key (key,
266 key_len,
267 nonce,
268 salt,
269 &sym_key,
270 &iv);
271 GNUNET_assert (0 ==
272 gcry_cipher_open (&cipher,
273 GCRY_CIPHER_AES256,
274 GCRY_CIPHER_MODE_GCM,
275 0));
276 rc = gcry_cipher_setkey (cipher,
277 &sym_key,
278 sizeof (sym_key));
279 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
280
281 rc = gcry_cipher_setiv (cipher,
282 &iv,
283 sizeof (iv));
284 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
285
286 GNUNET_assert (0 == gcry_cipher_decrypt (cipher,
287 *res,
288 *res_size,
289 ciphertext,
290 *res_size));
291 if (0 !=
292 gcry_cipher_checktag (cipher,
293 tag,
294 sizeof (struct ANASTASIS_CRYPTO_AesTagP)))
295 {
296 GNUNET_break (0);
297 GNUNET_free (*res);
298 return;
299 }
300 gcry_cipher_close (cipher);
301}
302
303
304void
305ANASTASIS_CRYPTO_user_identifier_derive (
306 const json_t *id_data,
307 const struct ANASTASIS_CRYPTO_ProviderSaltP *server_salt,
308 struct ANASTASIS_CRYPTO_UserIdentifierP *id)
309{
310 char *json_enc;
311 struct GNUNET_HashCode hash;
312
313 json_enc = json_dumps (id_data,
314 JSON_COMPACT | JSON_SORT_KEYS);
315 GNUNET_assert (NULL != json_enc);
316 GNUNET_CRYPTO_pow_hash (&server_salt->salt,
317 json_enc,
318 strlen (json_enc),
319 &hash);
320 id->hash = hash;
321 free (json_enc);
322}
323
324
325void
326ANASTASIS_CRYPTO_account_private_key_derive (
327 const struct ANASTASIS_CRYPTO_UserIdentifierP *id,
328 struct ANASTASIS_CRYPTO_AccountPrivateKeyP *priv_key)
329{
330 /* priv_key = ver_secret */
331 if (GNUNET_YES !=
332 GNUNET_CRYPTO_hkdf (&priv_key->priv,
333 sizeof (priv_key->priv),
334 GCRY_MD_SHA512,
335 GCRY_MD_SHA256,
336 id,
337 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP),
338 "ver",
339 strlen ("ver"),
340 NULL,
341 0))
342 {
343 GNUNET_break (0);
344 return;
345 }
346 /* go from ver_secret to proper private key (eddsa_d_to_a() in spec) */
347 priv_key->priv.d[0] = (priv_key->priv.d[0] & 0x7f) | 0x40;
348 priv_key->priv.d[31] &= 0xf8;
349}
350
351
352void
353ANASTASIS_CRYPTO_account_public_key_derive (
354 const struct ANASTASIS_CRYPTO_UserIdentifierP *id,
355 struct ANASTASIS_CRYPTO_AccountPublicKeyP *pub_key)
356{
357 struct ANASTASIS_CRYPTO_AccountPrivateKeyP priv;
358
359 ANASTASIS_CRYPTO_account_private_key_derive (id,
360 &priv);
361 GNUNET_CRYPTO_eddsa_key_get_public (&priv.priv,
362 &pub_key->pub);
363}
364
365
366void
367ANASTASIS_CRYPTO_recovery_document_encrypt (
368 const struct ANASTASIS_CRYPTO_UserIdentifierP *id,
369 const void *rec_doc,
370 size_t rd_size,
371 void **enc_rec_doc,
372 size_t *erd_size)
373{
374 const char *salt = "erd";
375 struct ANASTASIS_CRYPTO_NonceP nonce;
376
377 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
378 &nonce,
379 sizeof (nonce));
380 anastasis_encrypt (&nonce,
381 id,
382 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP),
383 rec_doc,
384 rd_size,
385 salt,
386 enc_rec_doc,
387 erd_size);
388}
389
390
391void
392ANASTASIS_CRYPTO_recovery_document_decrypt (
393 const struct ANASTASIS_CRYPTO_UserIdentifierP *id,
394 const void *enc_rec_doc,
395 size_t erd_size,
396 void **rec_doc,
397 size_t *rd_size)
398{
399 const char *salt = "erd";
400
401 anastasis_decrypt (id,
402 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP),
403 enc_rec_doc,
404 erd_size,
405 salt,
406 rec_doc,
407 rd_size);
408}
409
410
411void
412ANASTASIS_CRYPTO_keyshare_encrypt (
413 const struct ANASTASIS_CRYPTO_KeyShareP *key_share,
414 const struct ANASTASIS_CRYPTO_UserIdentifierP *id,
415 const char *xsalt,
416 struct ANASTASIS_CRYPTO_EncryptedKeyShareP *enc_key_share)
417{
418 const char *salt = "eks";
419 size_t eks_size = 0;
420 void *eks = NULL;
421 struct ANASTASIS_CRYPTO_NonceP nonce;
422
423 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
424 &nonce,
425 sizeof (nonce));
426 anastasis_encrypt (&nonce,
427 id,
428 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP),
429 key_share,
430 sizeof (struct ANASTASIS_CRYPTO_KeyShareP),
431 (NULL == xsalt) ? salt : xsalt,
432 &eks,
433 &eks_size);
434 GNUNET_assert (eks_size ==
435 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP));
436 memcpy (enc_key_share,
437 eks,
438 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP));
439 GNUNET_free (eks);
440}
441
442
443void
444ANASTASIS_CRYPTO_keyshare_decrypt (
445 const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *enc_key_share,
446 const struct ANASTASIS_CRYPTO_UserIdentifierP *id,
447 const char *xsalt,
448 struct ANASTASIS_CRYPTO_KeyShareP *key_share)
449{
450 const char *salt = "eks";
451 size_t ks_size = 0;
452 void *ks = NULL;
453
454 anastasis_decrypt (id,
455 sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP),
456 enc_key_share,
457 sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP),
458 (NULL == xsalt) ? salt : xsalt,
459 &ks,
460 &ks_size);
461 GNUNET_assert (ks_size ==
462 sizeof (struct ANASTASIS_CRYPTO_KeyShareP));
463 memcpy (key_share,
464 ks,
465 sizeof (struct ANASTASIS_CRYPTO_KeyShareP));
466 GNUNET_free (ks);
467}
468
469
470void
471ANASTASIS_CRYPTO_truth_encrypt (
472 const struct ANASTASIS_CRYPTO_NonceP *nonce,
473 const struct ANASTASIS_CRYPTO_TruthKeyP *truth_enc_key,
474 const void *truth,
475 size_t truth_size,
476 void **enc_truth,
477 size_t *ect_size)
478{
479 const char *salt = "ect";
480
481 anastasis_encrypt (nonce,
482 truth_enc_key,
483 sizeof (struct ANASTASIS_CRYPTO_TruthKeyP),
484 truth,
485 truth_size,
486 salt,
487 enc_truth,
488 ect_size);
489}
490
491
492void
493ANASTASIS_CRYPTO_truth_decrypt (
494 const struct ANASTASIS_CRYPTO_TruthKeyP *truth_enc_key,
495 const void *enc_truth,
496 size_t ect_size,
497 void **truth,
498 size_t *truth_size)
499{
500 const char *salt = "ect";
501
502 anastasis_decrypt (truth_enc_key,
503 sizeof (struct ANASTASIS_CRYPTO_TruthKeyP),
504 enc_truth,
505 ect_size,
506 salt,
507 truth,
508 truth_size);
509}
510
511
512void
513ANASTASIS_CRYPTO_keyshare_create (
514 struct ANASTASIS_CRYPTO_KeyShareP *key_share)
515{
516 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
517 key_share,
518 sizeof (struct ANASTASIS_CRYPTO_KeyShareP));
519}
520
521
522void
523ANASTASIS_CRYPTO_policy_key_derive (
524 const struct ANASTASIS_CRYPTO_KeyShareP *key_shares,
525 unsigned int keyshare_length,
526 const struct ANASTASIS_CRYPTO_MasterSaltP *salt,
527 struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key)
528{
529 GNUNET_CRYPTO_hkdf (policy_key,
530 sizeof (*policy_key),
531 GCRY_MD_SHA512,
532 GCRY_MD_SHA256,
533 key_shares,
534 keyshare_length * sizeof (*key_shares),
535 salt,
536 sizeof (*salt),
537 NULL, 0);
538}
539
540
541void
542ANASTASIS_CRYPTO_core_secret_encrypt (
543 const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_keys,
544 unsigned int policy_keys_length,
545 const void *core_secret,
546 size_t core_secret_size,
547 void **enc_core_secret,
548 struct ANASTASIS_CRYPTO_EncryptedMasterKeyP *encrypted_master_keys)
549{
550 struct GNUNET_CRYPTO_SymmetricSessionKey sk;
551 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
552 struct GNUNET_HashCode master_key;
553
554 *enc_core_secret = GNUNET_malloc (core_secret_size);
555 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
556 &master_key,
557 sizeof (struct GNUNET_HashCode));
558 GNUNET_CRYPTO_hash_to_aes_key (&master_key,
559 &sk,
560 &iv);
561 GNUNET_assert (GNUNET_SYSERR !=
562 GNUNET_CRYPTO_symmetric_encrypt (core_secret,
563 core_secret_size,
564 &sk,
565 &iv,
566 *enc_core_secret));
567 for (unsigned int i = 0; i < policy_keys_length; i++)
568 {
569 struct GNUNET_CRYPTO_SymmetricSessionKey i_sk;
570 struct GNUNET_CRYPTO_SymmetricInitializationVector i_iv;
571 struct GNUNET_HashCode key = policy_keys[i].key;
572
573 GNUNET_CRYPTO_hash_to_aes_key (&key,
574 &i_sk,
575 &i_iv);
576 GNUNET_assert (
577 GNUNET_SYSERR !=
578 GNUNET_CRYPTO_symmetric_encrypt (&master_key,
579 sizeof (struct GNUNET_HashCode),
580 &i_sk,
581 &i_iv,
582 &encrypted_master_keys[i]));
583 }
584}
585
586
587void
588ANASTASIS_CRYPTO_core_secret_recover (
589 const struct ANASTASIS_CRYPTO_EncryptedMasterKeyP *encrypted_master_key,
590 const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key,
591 const void *encrypted_core_secret,
592 size_t encrypted_core_secret_size,
593 void **core_secret,
594 size_t *core_secret_size)
595{
596 struct GNUNET_CRYPTO_SymmetricSessionKey mk_sk;
597 struct GNUNET_CRYPTO_SymmetricInitializationVector mk_iv;
598 struct GNUNET_CRYPTO_SymmetricSessionKey core_sk;
599 struct GNUNET_CRYPTO_SymmetricInitializationVector core_iv;
600 struct GNUNET_HashCode master_key;
601 struct GNUNET_HashCode key = policy_key->key;
602
603 *core_secret = GNUNET_malloc (encrypted_core_secret_size);
604 GNUNET_CRYPTO_hash_to_aes_key (&key,
605 &mk_sk,
606 &mk_iv);
607 GNUNET_assert (
608 GNUNET_SYSERR !=
609 GNUNET_CRYPTO_symmetric_decrypt (
610 encrypted_master_key,
611 sizeof (struct ANASTASIS_CRYPTO_EncryptedMasterKeyP),
612 &mk_sk,
613 &mk_iv,
614 &master_key));
615 GNUNET_CRYPTO_hash_to_aes_key (&master_key,
616 &core_sk,
617 &core_iv);
618 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
619 "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
620 __LINE__,
621 TALER_b2s (encrypted_core_secret, encrypted_core_secret_size),
622 (unsigned long long) encrypted_core_secret_size);
623 *core_secret_size = GNUNET_CRYPTO_symmetric_decrypt (encrypted_core_secret,
624 encrypted_core_secret_size,
625 &core_sk,
626 &core_iv,
627 *core_secret);
628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
629 "At %s:%d decrypted core secret is %s-%llu b\n", __FILE__,
630 __LINE__,
631 TALER_b2s (*core_secret, *core_secret_size),
632 (unsigned long long) *core_secret_size);
633 GNUNET_assert (GNUNET_SYSERR != *core_secret_size);
634}
635
636
637/* end of anastasis_crypto.c */