error handling
[oweals/gnunet.git] / src / util / crypto_pow.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2013, 2019 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  * @file util/crypto_pow.c
22  * @brief proof-of-work hashing
23  * @author Christian Grothoff
24  * @author Bart Polot
25  */
26 #include "platform.h"
27 #include "gnunet_crypto_lib.h"
28 #include <gcrypt.h>
29
30 /**
31  * Calculate the 'proof-of-work' hash (an expensive hash).
32  * We're using a non-standard formula to avoid issues with
33  * ASICs appearing (see #3795).
34  *
35  * @param salt salt for the hash
36  * @param buf data to hash
37  * @param buf_len number of bytes in @a buf
38  * @param result where to write the resulting hash
39  */
40 void
41 GNUNET_CRYPTO_pow_hash (const char *salt,
42                         const void *buf,
43                         size_t buf_len,
44                         struct GNUNET_HashCode *result)
45 {
46 #ifdef LSD001
47   char twofish_iv[128 / 8]; //128 bit IV
48   char twofish_key[256 / 8]; //256 bit Key
49   char rbuf[buf_len];
50   int rc;
51   gcry_cipher_hd_t handle;
52
53   GNUNET_break (0 == gcry_kdf_derive (buf,
54                                       buf_len,
55                                       GCRY_KDF_SCRYPT,
56                                       1 /* subalgo */,
57                                       salt,
58                                       strlen (salt),
59                                       2 /* iterations; keep cost of individual op small */,
60                                       sizeof(twofish_key),
61                                       &twofish_key));
62
63   GNUNET_CRYPTO_kdf (twofish_iv,
64                      sizeof (twofish_iv),
65                      "gnunet-proof-of-work-iv",
66                      strlen ("gnunet-proof-of-work-iv"),
67                      twofish_key,
68                      sizeof(twofish_key),
69                      salt,
70                      strlen (salt),
71                      NULL, 0);
72   GNUNET_assert (0 ==
73                  gcry_cipher_open (&handle, GCRY_CIPHER_TWOFISH,
74                                    GCRY_CIPHER_MODE_CFB, 0));
75   rc = gcry_cipher_setkey (handle,
76                            twofish_key,
77                            sizeof(twofish_key));
78   GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
79   rc = gcry_cipher_setiv (handle,
80                           twofish_iv,
81                           sizeof(twofish_iv));
82   GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
83   GNUNET_assert (0 == gcry_cipher_encrypt (handle, &rbuf, buf_len, buf, buf_len));
84   gcry_cipher_close (handle);
85 #else
86   struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
87   struct GNUNET_CRYPTO_SymmetricSessionKey skey;
88   char rbuf[buf_len];
89
90   GNUNET_break (0 == gcry_kdf_derive (buf,
91                                       buf_len,
92                                       GCRY_KDF_SCRYPT,
93                                       1 /* subalgo */,
94                                       salt,
95                                       strlen (salt),
96                                       2 /* iterations; keep cost of individual op small */,
97                                       sizeof(skey),
98                                       &skey));
99   GNUNET_CRYPTO_symmetric_derive_iv (&iv,
100                                      &skey,
101                                      "gnunet-proof-of-work-iv",
102                                      strlen ("gnunet-proof-of-work-iv"),
103                                      salt,
104                                      strlen (salt),
105                                      NULL, 0);
106   GNUNET_CRYPTO_symmetric_encrypt (buf,
107                                    buf_len,
108                                    &skey,
109                                    &iv,
110                                    &rbuf);
111 #endif
112   GNUNET_break (0 == gcry_kdf_derive (rbuf,
113                                       buf_len,
114                                       GCRY_KDF_SCRYPT,
115                                       1 /* subalgo */,
116                                       salt,
117                                       strlen (salt),
118                                       2 /* iterations; keep cost of individual op small */,
119                                       sizeof(struct GNUNET_HashCode),
120                                       result));
121 }
122
123
124 /* end of crypto_pow.c */