diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/.gitignore | 1 | ||||
-rw-r--r-- | src/util/Makefile.am | 8 | ||||
-rw-r--r-- | src/util/crypto_ecc_gnsrecord.c | 55 | ||||
-rw-r--r-- | src/util/crypto_edx25519.c | 418 | ||||
-rw-r--r-- | src/util/crypto_hkdf.c | 118 | ||||
-rw-r--r-- | src/util/crypto_kdf.c | 61 | ||||
-rw-r--r-- | src/util/crypto_rsa.c | 28 | ||||
-rw-r--r-- | src/util/test_crypto_eddsa.c | 8 | ||||
-rw-r--r-- | src/util/test_crypto_edx25519.c | 326 | ||||
-rw-r--r-- | src/util/time.c | 30 |
10 files changed, 918 insertions, 135 deletions
diff --git a/src/util/.gitignore b/src/util/.gitignore index 51eab71db..0e3449fed 100644 --- a/src/util/.gitignore +++ b/src/util/.gitignore | |||
@@ -36,6 +36,7 @@ test_crypto_ecdh_eddsa | |||
36 | test_crypto_ecdhe | 36 | test_crypto_ecdhe |
37 | test_crypto_ecdsa | 37 | test_crypto_ecdsa |
38 | test_crypto_eddsa | 38 | test_crypto_eddsa |
39 | test_crypto_edx25519 | ||
39 | test_crypto_hash | 40 | test_crypto_hash |
40 | test_crypto_hash_context | 41 | test_crypto_hash_context |
41 | test_crypto_hkdf | 42 | test_crypto_hkdf |
diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 406d42b1e..9cb7da15b 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am | |||
@@ -66,6 +66,7 @@ libgnunetutil_la_SOURCES = \ | |||
66 | crypto_ecc_gnsrecord.c \ | 66 | crypto_ecc_gnsrecord.c \ |
67 | $(DLOG) \ | 67 | $(DLOG) \ |
68 | crypto_ecc_setup.c \ | 68 | crypto_ecc_setup.c \ |
69 | crypto_edx25519.c \ | ||
69 | crypto_hash.c \ | 70 | crypto_hash.c \ |
70 | crypto_hash_file.c \ | 71 | crypto_hash_file.c \ |
71 | crypto_hkdf.c \ | 72 | crypto_hkdf.c \ |
@@ -297,6 +298,7 @@ check_PROGRAMS = \ | |||
297 | test_crypto_ecdhe \ | 298 | test_crypto_ecdhe \ |
298 | test_crypto_ecdh_eddsa \ | 299 | test_crypto_ecdh_eddsa \ |
299 | test_crypto_ecdh_ecdsa \ | 300 | test_crypto_ecdh_ecdsa \ |
301 | test_crypto_edx25519 \ | ||
300 | $(DLOG_TEST) \ | 302 | $(DLOG_TEST) \ |
301 | test_crypto_hash \ | 303 | test_crypto_hash \ |
302 | test_crypto_hash_context \ | 304 | test_crypto_hash_context \ |
@@ -470,6 +472,12 @@ test_crypto_eddsa_LDADD = \ | |||
470 | libgnunetutil.la \ | 472 | libgnunetutil.la \ |
471 | $(LIBGCRYPT_LIBS) | 473 | $(LIBGCRYPT_LIBS) |
472 | 474 | ||
475 | test_crypto_edx25519_SOURCES = \ | ||
476 | test_crypto_edx25519.c | ||
477 | test_crypto_edx25519_LDADD = \ | ||
478 | libgnunetutil.la \ | ||
479 | $(LIBGCRYPT_LIBS) | ||
480 | |||
473 | test_crypto_ecc_dlog_SOURCES = \ | 481 | test_crypto_ecc_dlog_SOURCES = \ |
474 | test_crypto_ecc_dlog.c | 482 | test_crypto_ecc_dlog.c |
475 | test_crypto_ecc_dlog_LDADD = \ | 483 | test_crypto_ecc_dlog_LDADD = \ |
diff --git a/src/util/crypto_ecc_gnsrecord.c b/src/util/crypto_ecc_gnsrecord.c index ce41a4699..0ee0570c0 100644 --- a/src/util/crypto_ecc_gnsrecord.c +++ b/src/util/crypto_ecc_gnsrecord.c | |||
@@ -68,28 +68,15 @@ derive_h (const void *pub, | |||
68 | } | 68 | } |
69 | 69 | ||
70 | 70 | ||
71 | /** | 71 | enum GNUNET_GenericReturnValue |
72 | * This is a signature function for EdDSA which takes the | 72 | GNUNET_CRYPTO_eddsa_sign_derived ( |
73 | * secret scalar sk instead of the private seed which is | 73 | const struct GNUNET_CRYPTO_EddsaPrivateKey *pkey, |
74 | * usually the case for crypto APIs. We require this functionality | 74 | const char *label, |
75 | * in order to use derived private keys for signatures we | 75 | const char *context, |
76 | * cannot calculate the inverse of a sk to find the seed | ||
77 | * efficiently. | ||
78 | * | ||
79 | * The resulting signature is a standard EdDSA signature | ||
80 | * which can be verified using the usual APIs. | ||
81 | * | ||
82 | * @param sk the secret scalar | ||
83 | * @param purp the signature purpose | ||
84 | * @param sig the resulting signature | ||
85 | */ | ||
86 | void | ||
87 | GNUNET_CRYPTO_eddsa_sign_with_scalar ( | ||
88 | const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv, | ||
89 | const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, | 76 | const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, |
90 | struct GNUNET_CRYPTO_EddsaSignature *sig) | 77 | struct GNUNET_CRYPTO_EddsaSignature *sig) |
91 | { | 78 | { |
92 | 79 | struct GNUNET_CRYPTO_EddsaPrivateScalar priv; | |
93 | crypto_hash_sha512_state hs; | 80 | crypto_hash_sha512_state hs; |
94 | unsigned char sk[64]; | 81 | unsigned char sk[64]; |
95 | unsigned char r[64]; | 82 | unsigned char r[64]; |
@@ -98,6 +85,14 @@ GNUNET_CRYPTO_eddsa_sign_with_scalar ( | |||
98 | unsigned char zk[32]; | 85 | unsigned char zk[32]; |
99 | unsigned char tmp[32]; | 86 | unsigned char tmp[32]; |
100 | 87 | ||
88 | /** | ||
89 | * Derive the private key | ||
90 | */ | ||
91 | GNUNET_CRYPTO_eddsa_private_key_derive (pkey, | ||
92 | label, | ||
93 | context, | ||
94 | &priv); | ||
95 | |||
101 | crypto_hash_sha512_init (&hs); | 96 | crypto_hash_sha512_init (&hs); |
102 | 97 | ||
103 | /** | 98 | /** |
@@ -108,7 +103,7 @@ GNUNET_CRYPTO_eddsa_sign_with_scalar ( | |||
108 | * sk[0..31] = h * SHA512 (d)[0..31] | 103 | * sk[0..31] = h * SHA512 (d)[0..31] |
109 | * sk[32..63] = SHA512 (d)[32..63] | 104 | * sk[32..63] = SHA512 (d)[32..63] |
110 | */ | 105 | */ |
111 | memcpy (sk, priv->s, 64); | 106 | memcpy (sk, priv.s, 64); |
112 | 107 | ||
113 | /** | 108 | /** |
114 | * Calculate the derived zone key zk' from the | 109 | * Calculate the derived zone key zk' from the |
@@ -172,8 +167,28 @@ GNUNET_CRYPTO_eddsa_sign_with_scalar ( | |||
172 | sodium_memzero (sk, sizeof (sk)); | 167 | sodium_memzero (sk, sizeof (sk)); |
173 | sodium_memzero (r, sizeof (r)); | 168 | sodium_memzero (r, sizeof (r)); |
174 | sodium_memzero (r_mod, sizeof (r_mod)); | 169 | sodium_memzero (r_mod, sizeof (r_mod)); |
170 | return GNUNET_OK; | ||
175 | } | 171 | } |
176 | 172 | ||
173 | enum GNUNET_GenericReturnValue | ||
174 | GNUNET_CRYPTO_ecdsa_sign_derived ( | ||
175 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, | ||
176 | const char *label, | ||
177 | const char *context, | ||
178 | const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, | ||
179 | struct GNUNET_CRYPTO_EcdsaSignature *sig) | ||
180 | { | ||
181 | struct GNUNET_CRYPTO_EcdsaPrivateKey *key; | ||
182 | enum GNUNET_GenericReturnValue res; | ||
183 | key = GNUNET_CRYPTO_ecdsa_private_key_derive (priv, | ||
184 | label, | ||
185 | context); | ||
186 | res = GNUNET_CRYPTO_ecdsa_sign_ (key, | ||
187 | purpose, | ||
188 | sig); | ||
189 | GNUNET_free (key); | ||
190 | return res; | ||
191 | } | ||
177 | 192 | ||
178 | struct GNUNET_CRYPTO_EcdsaPrivateKey * | 193 | struct GNUNET_CRYPTO_EcdsaPrivateKey * |
179 | GNUNET_CRYPTO_ecdsa_private_key_derive ( | 194 | GNUNET_CRYPTO_ecdsa_private_key_derive ( |
diff --git a/src/util/crypto_edx25519.c b/src/util/crypto_edx25519.c new file mode 100644 index 000000000..26b45407e --- /dev/null +++ b/src/util/crypto_edx25519.c | |||
@@ -0,0 +1,418 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2022 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_edx25519.c | ||
23 | * @brief An variant of EdDSA which allows for iterative derivation of key pairs. | ||
24 | * @author Özgür Kesim | ||
25 | * @author Christian Grothoff | ||
26 | * @author Florian Dold | ||
27 | * @author Martin Schanzenbach | ||
28 | */ | ||
29 | #include "platform.h" | ||
30 | #include <gcrypt.h> | ||
31 | #include <sodium.h> | ||
32 | #include "gnunet_crypto_lib.h" | ||
33 | #include "gnunet_strings_lib.h" | ||
34 | |||
35 | #define CURVE "Ed25519" | ||
36 | |||
37 | void | ||
38 | GNUNET_CRYPTO_edx25519_key_clear (struct GNUNET_CRYPTO_Edx25519PrivateKey *pk) | ||
39 | { | ||
40 | memset (pk, 0, sizeof(struct GNUNET_CRYPTO_Edx25519PrivateKey)); | ||
41 | } | ||
42 | |||
43 | |||
44 | void | ||
45 | GNUNET_CRYPTO_edx25519_key_create_from_seed ( | ||
46 | const void *seed, | ||
47 | size_t seedsize, | ||
48 | struct GNUNET_CRYPTO_Edx25519PrivateKey *pk) | ||
49 | { | ||
50 | |||
51 | GNUNET_static_assert (sizeof(*pk) == sizeof(struct GNUNET_HashCode)); | ||
52 | GNUNET_CRYPTO_hash (seed, | ||
53 | seedsize, | ||
54 | (struct GNUNET_HashCode *) pk); | ||
55 | |||
56 | /* Clamp the first half of the key. The second half is used in the signature | ||
57 | * process. */ | ||
58 | pk->a[0] &= 248; | ||
59 | pk->a[31] &= 127; | ||
60 | pk->a[31] |= 64; | ||
61 | } | ||
62 | |||
63 | |||
64 | void | ||
65 | GNUNET_CRYPTO_edx25519_key_create ( | ||
66 | struct GNUNET_CRYPTO_Edx25519PrivateKey *pk) | ||
67 | { | ||
68 | char seed[256 / 8]; | ||
69 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
70 | seed, | ||
71 | sizeof (seed)); | ||
72 | GNUNET_CRYPTO_edx25519_key_create_from_seed (seed, | ||
73 | sizeof(seed), | ||
74 | pk); | ||
75 | } | ||
76 | |||
77 | |||
78 | void | ||
79 | GNUNET_CRYPTO_edx25519_key_get_public ( | ||
80 | const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv, | ||
81 | struct GNUNET_CRYPTO_Edx25519PublicKey *pub) | ||
82 | { | ||
83 | crypto_scalarmult_ed25519_base_noclamp (pub->q_y, | ||
84 | priv->a); | ||
85 | } | ||
86 | |||
87 | |||
88 | /** | ||
89 | * This function operates the basically same way as the signature function for | ||
90 | * EdDSA. But instead of expanding a private seed (which is usually the case | ||
91 | * for crypto APIs) and using the resulting scalars, it takes the scalars | ||
92 | * directly from Edx25519PrivateKey. We require this functionality in order to | ||
93 | * use derived private keys for signatures. | ||
94 | * | ||
95 | * The resulting signature is a standard EdDSA signature | ||
96 | * which can be verified using the usual APIs. | ||
97 | * | ||
98 | * @param priv the private key (containing two scalars .a and .b) | ||
99 | * @param purp the signature purpose | ||
100 | * @param sig the resulting signature | ||
101 | */ | ||
102 | enum GNUNET_GenericReturnValue | ||
103 | GNUNET_CRYPTO_edx25519_sign_ ( | ||
104 | const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv, | ||
105 | const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, | ||
106 | struct GNUNET_CRYPTO_Edx25519Signature *sig) | ||
107 | { | ||
108 | |||
109 | crypto_hash_sha512_state hs; | ||
110 | unsigned char r[64]; | ||
111 | unsigned char hram[64]; | ||
112 | unsigned char P[32]; | ||
113 | unsigned char r_mod[64]; | ||
114 | unsigned char R[32]; | ||
115 | unsigned char tmp[32]; | ||
116 | |||
117 | crypto_hash_sha512_init (&hs); | ||
118 | |||
119 | /** | ||
120 | * Calculate the public key P from the private scalar in the key. | ||
121 | */ | ||
122 | crypto_scalarmult_ed25519_base_noclamp (P, | ||
123 | priv->a); | ||
124 | |||
125 | /** | ||
126 | * Calculate r: | ||
127 | * r = SHA512 (b ∥ M) | ||
128 | * where M is our message (purpose). | ||
129 | */ | ||
130 | crypto_hash_sha512_update (&hs, | ||
131 | priv->b, | ||
132 | sizeof(priv->b)); | ||
133 | crypto_hash_sha512_update (&hs, | ||
134 | (uint8_t*) purpose, | ||
135 | ntohl (purpose->size)); | ||
136 | crypto_hash_sha512_final (&hs, | ||
137 | r); | ||
138 | |||
139 | /** | ||
140 | * Temporarily put P into S | ||
141 | */ | ||
142 | memcpy (sig->s, P, 32); | ||
143 | |||
144 | /** | ||
145 | * Reduce the scalar value r | ||
146 | */ | ||
147 | crypto_core_ed25519_scalar_reduce (r_mod, r); | ||
148 | |||
149 | /** | ||
150 | * Calculate R := r * G of the signature | ||
151 | */ | ||
152 | crypto_scalarmult_ed25519_base_noclamp (R, r_mod); | ||
153 | memcpy (sig->r, R, sizeof (R)); | ||
154 | |||
155 | /** | ||
156 | * Calculate | ||
157 | * hram := SHA512 (R ∥ P ∥ M) | ||
158 | */ | ||
159 | crypto_hash_sha512_init (&hs); | ||
160 | crypto_hash_sha512_update (&hs, (uint8_t*) sig, 64); | ||
161 | crypto_hash_sha512_update (&hs, (uint8_t*) purpose, | ||
162 | ntohl (purpose->size)); | ||
163 | crypto_hash_sha512_final (&hs, hram); | ||
164 | |||
165 | /** | ||
166 | * Reduce the resulting scalar value | ||
167 | */ | ||
168 | unsigned char hram_mod[64]; | ||
169 | crypto_core_ed25519_scalar_reduce (hram_mod, hram); | ||
170 | |||
171 | /** | ||
172 | * Calculate | ||
173 | * S := r + hram * s mod L | ||
174 | */ | ||
175 | crypto_core_ed25519_scalar_mul (tmp, hram_mod, priv->a); | ||
176 | crypto_core_ed25519_scalar_add (sig->s, tmp, r_mod); | ||
177 | |||
178 | sodium_memzero (r, sizeof (r)); | ||
179 | sodium_memzero (r_mod, sizeof (r_mod)); | ||
180 | |||
181 | return GNUNET_OK; | ||
182 | } | ||
183 | |||
184 | |||
185 | enum GNUNET_GenericReturnValue | ||
186 | GNUNET_CRYPTO_edx25519_verify_ ( | ||
187 | uint32_t purpose, | ||
188 | const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, | ||
189 | const struct GNUNET_CRYPTO_Edx25519Signature *sig, | ||
190 | const struct GNUNET_CRYPTO_Edx25519PublicKey *pub) | ||
191 | { | ||
192 | const unsigned char *m = (const void *) validate; | ||
193 | size_t mlen = ntohl (validate->size); | ||
194 | const unsigned char *s = (const void *) sig; | ||
195 | |||
196 | int res; | ||
197 | |||
198 | if (purpose != ntohl (validate->purpose)) | ||
199 | return GNUNET_SYSERR; /* purpose mismatch */ | ||
200 | |||
201 | res = crypto_sign_verify_detached (s, m, mlen, pub->q_y); | ||
202 | return (res == 0) ? GNUNET_OK : GNUNET_SYSERR; | ||
203 | } | ||
204 | |||
205 | |||
206 | /** | ||
207 | * Derive the 'h' value for key derivation, where | ||
208 | * 'h = H(P ∥ seed) mod n' and 'n' is the size of the cyclic subroup. | ||
209 | * | ||
210 | * @param pub public key for deriviation | ||
211 | * @param seed seed for key the deriviation | ||
212 | * @param seedsize the size of the seed | ||
213 | * @param n The value for the modulus 'n' | ||
214 | * @param[out] phc if not NULL, the output of H() will be written into | ||
215 | * return h_mod_n (allocated by this function) | ||
216 | */ | ||
217 | static gcry_mpi_t | ||
218 | derive_h_mod_n ( | ||
219 | const struct GNUNET_CRYPTO_Edx25519PublicKey *pub, | ||
220 | const void *seed, | ||
221 | size_t seedsize, | ||
222 | const gcry_mpi_t n, | ||
223 | struct GNUNET_HashCode *phc) | ||
224 | { | ||
225 | static const char *const salt = "edx2559-derivation"; | ||
226 | struct GNUNET_HashCode hc; | ||
227 | gcry_mpi_t h; | ||
228 | gcry_mpi_t h_mod_n; | ||
229 | |||
230 | if (NULL == phc) | ||
231 | phc = &hc; | ||
232 | |||
233 | GNUNET_CRYPTO_kdf (phc, sizeof(*phc), | ||
234 | salt, strlen (salt), | ||
235 | pub, sizeof(*pub), | ||
236 | seed, seedsize, | ||
237 | NULL, 0); | ||
238 | |||
239 | /* calculate h_mod_n = h % n */ | ||
240 | GNUNET_CRYPTO_mpi_scan_unsigned (&h, | ||
241 | (unsigned char *) phc, | ||
242 | sizeof(*phc)); | ||
243 | h_mod_n = gcry_mpi_new (256); | ||
244 | gcry_mpi_mod (h_mod_n, h, n); | ||
245 | |||
246 | #ifdef CHECK_RARE_CASES | ||
247 | /** | ||
248 | * Note that the following cases would be problematic: | ||
249 | * 1.) h == 0 mod n | ||
250 | * 2.) h == 1 mod n | ||
251 | * 3.) [h] * P == E | ||
252 | * We assume that the probalities for these cases to occur are neglegible. | ||
253 | */ | ||
254 | GNUNET_assert (! gcry_mpi_cmp_ui (h_mod_n, 0)); | ||
255 | GNUNET_assert (! gcry_mpi_cmp_ui (h_mod_n, 1)); | ||
256 | #endif | ||
257 | |||
258 | gcry_mpi_release(h); | ||
259 | return h_mod_n; | ||
260 | } | ||
261 | |||
262 | |||
263 | void | ||
264 | GNUNET_CRYPTO_edx25519_private_key_derive ( | ||
265 | const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv, | ||
266 | const void *seed, | ||
267 | size_t seedsize, | ||
268 | struct GNUNET_CRYPTO_Edx25519PrivateKey *result) | ||
269 | { | ||
270 | struct GNUNET_CRYPTO_Edx25519PublicKey pub; | ||
271 | struct GNUNET_HashCode hc; | ||
272 | uint8_t a[32]; | ||
273 | gcry_ctx_t ctx; | ||
274 | gcry_mpi_t h_mod_n; | ||
275 | gcry_mpi_t x; | ||
276 | gcry_mpi_t n; | ||
277 | gcry_mpi_t a1; | ||
278 | gcry_mpi_t a2; | ||
279 | gcry_mpi_t ap; // a' | ||
280 | |||
281 | GNUNET_CRYPTO_edx25519_key_get_public (priv, &pub); | ||
282 | |||
283 | /** | ||
284 | * Libsodium does not offer an API with arbitrary arithmetic. | ||
285 | * Hence we have to use libgcrypt here. | ||
286 | */ | ||
287 | GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519")); | ||
288 | |||
289 | /** | ||
290 | * Get our modulo | ||
291 | */ | ||
292 | n = gcry_mpi_ec_get_mpi ("n", ctx, 1); | ||
293 | GNUNET_assert (NULL != n); | ||
294 | |||
295 | /** | ||
296 | * Get h mod n | ||
297 | */ | ||
298 | h_mod_n = derive_h_mod_n (&pub, | ||
299 | seed, | ||
300 | seedsize, | ||
301 | n, | ||
302 | &hc); | ||
303 | |||
304 | /* Convert priv->a scalar to big endian for libgcrypt */ | ||
305 | for (size_t i = 0; i < 32; i++) | ||
306 | a[i] = priv->a[31 - i]; | ||
307 | |||
308 | /** | ||
309 | * dc now contains the private scalar "a". | ||
310 | * We carefully remove the clamping and derive a'. | ||
311 | * Calculate: | ||
312 | * a1 := a / 8 | ||
313 | * a2 := h * a1 mod n | ||
314 | * a' := a2 * 8 mod n | ||
315 | */ | ||
316 | GNUNET_CRYPTO_mpi_scan_unsigned (&x, a, sizeof(a)); // a | ||
317 | a1 = gcry_mpi_new (256); | ||
318 | gcry_mpi_t eight = gcry_mpi_set_ui (NULL, 8); | ||
319 | gcry_mpi_div (a1, NULL, x, eight, 0); // a1 := a / 8 | ||
320 | a2 = gcry_mpi_new (256); | ||
321 | gcry_mpi_mulm (a2, h_mod_n, a1, n); // a2 := h * a1 mod n | ||
322 | ap = gcry_mpi_new (256); | ||
323 | gcry_mpi_mul (ap, a2, eight); // a' := a2 * 8 | ||
324 | |||
325 | #ifdef CHECK_RARE_CASES | ||
326 | /* The likelihood for a' == 0 or a' == 1 is neglegible */ | ||
327 | GNUNET_assert (! gcry_mpi_cmp_ui (ap, 0)); | ||
328 | GNUNET_assert (! gcry_mpi_cmp_ui (ap, 1)); | ||
329 | #endif | ||
330 | |||
331 | gcry_mpi_release (h_mod_n); | ||
332 | gcry_mpi_release (eight); | ||
333 | gcry_mpi_release (x); | ||
334 | gcry_mpi_release (n); | ||
335 | gcry_mpi_release (a1); | ||
336 | gcry_mpi_release (a2); | ||
337 | gcry_ctx_release (ctx); | ||
338 | GNUNET_CRYPTO_mpi_print_unsigned (a, sizeof(a), ap); | ||
339 | gcry_mpi_release (ap); | ||
340 | |||
341 | /** | ||
342 | * We hash the derived "h" parameter with the other half of the expanded | ||
343 | * private key (that is: priv->b). This ensures that for signature | ||
344 | * generation, the "R" is derived from the same derivation path as "h" and is | ||
345 | * not reused. | ||
346 | */ | ||
347 | { | ||
348 | crypto_hash_sha256_state hs; | ||
349 | crypto_hash_sha256_init (&hs); | ||
350 | crypto_hash_sha256_update (&hs, priv->b, sizeof(priv->b)); | ||
351 | crypto_hash_sha256_update (&hs, (unsigned char*) &hc, sizeof (hc)); | ||
352 | crypto_hash_sha256_final (&hs, result->b); | ||
353 | } | ||
354 | |||
355 | /* Convert to little endian for libsodium */ | ||
356 | for (size_t i = 0; i < 32; i++) | ||
357 | result->a[i] = a[31 - i]; | ||
358 | |||
359 | sodium_memzero (a, sizeof(a)); | ||
360 | } | ||
361 | |||
362 | |||
363 | void | ||
364 | GNUNET_CRYPTO_edx25519_public_key_derive ( | ||
365 | const struct GNUNET_CRYPTO_Edx25519PublicKey *pub, | ||
366 | const void *seed, | ||
367 | size_t seedsize, | ||
368 | struct GNUNET_CRYPTO_Edx25519PublicKey *result) | ||
369 | { | ||
370 | gcry_ctx_t ctx; | ||
371 | gcry_mpi_t q_y; | ||
372 | gcry_mpi_t n; | ||
373 | gcry_mpi_t h_mod_n; | ||
374 | gcry_mpi_point_t q; | ||
375 | gcry_mpi_point_t v; | ||
376 | |||
377 | GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519")); | ||
378 | |||
379 | /* obtain point 'q' from original public key. The provided 'q' is | ||
380 | compressed thus we first store it in the context and then get it | ||
381 | back as a (decompresssed) point. */ | ||
382 | q_y = gcry_mpi_set_opaque_copy (NULL, | ||
383 | pub->q_y, | ||
384 | 8 * sizeof(pub->q_y)); | ||
385 | GNUNET_assert (NULL != q_y); | ||
386 | GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx)); | ||
387 | gcry_mpi_release (q_y); | ||
388 | q = gcry_mpi_ec_get_point ("q", ctx, 0); | ||
389 | GNUNET_assert (q); | ||
390 | |||
391 | /** | ||
392 | * Get h mod n | ||
393 | */ | ||
394 | n = gcry_mpi_ec_get_mpi ("n", ctx, 1); | ||
395 | GNUNET_assert (NULL != n); | ||
396 | GNUNET_assert (NULL != pub); | ||
397 | h_mod_n = derive_h_mod_n (pub, | ||
398 | seed, | ||
399 | seedsize, | ||
400 | n, | ||
401 | NULL /* We don't need hc here */); | ||
402 | |||
403 | /* calculate v = h_mod_n * q */ | ||
404 | v = gcry_mpi_point_new (0); | ||
405 | gcry_mpi_ec_mul (v, h_mod_n, q, ctx); | ||
406 | gcry_mpi_release (h_mod_n); | ||
407 | gcry_mpi_release (n); | ||
408 | gcry_mpi_point_release (q); | ||
409 | |||
410 | /* convert point 'v' to public key that we return */ | ||
411 | GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx)); | ||
412 | gcry_mpi_point_release (v); | ||
413 | q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0); | ||
414 | GNUNET_assert (q_y); | ||
415 | GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y); | ||
416 | gcry_mpi_release (q_y); | ||
417 | gcry_ctx_release (ctx); | ||
418 | } | ||
diff --git a/src/util/crypto_hkdf.c b/src/util/crypto_hkdf.c index 4e4496819..838e37d8d 100644 --- a/src/util/crypto_hkdf.c +++ b/src/util/crypto_hkdf.c | |||
@@ -74,16 +74,21 @@ | |||
74 | * @return HMAC, freed by caller via gcry_md_close/_reset | 74 | * @return HMAC, freed by caller via gcry_md_close/_reset |
75 | */ | 75 | */ |
76 | static const void * | 76 | static const void * |
77 | doHMAC (gcry_md_hd_t mac, const void *key, size_t key_len, const void *buf, | 77 | doHMAC (gcry_md_hd_t mac, |
78 | const void *key, | ||
79 | size_t key_len, | ||
80 | const void *buf, | ||
78 | size_t buf_len) | 81 | size_t buf_len) |
79 | { | 82 | { |
80 | if (GPG_ERR_NO_ERROR != gcry_md_setkey (mac, key, key_len)) | 83 | if (GPG_ERR_NO_ERROR != |
84 | gcry_md_setkey (mac, key, key_len)) | ||
81 | { | 85 | { |
82 | GNUNET_break (0); | 86 | GNUNET_break (0); |
83 | return NULL; | 87 | return NULL; |
84 | } | 88 | } |
85 | gcry_md_write (mac, buf, buf_len); | 89 | gcry_md_write (mac, |
86 | 90 | buf, | |
91 | buf_len); | ||
87 | return (const void *) gcry_md_read (mac, 0); | 92 | return (const void *) gcry_md_read (mac, 0); |
88 | } | 93 | } |
89 | 94 | ||
@@ -98,9 +103,13 @@ doHMAC (gcry_md_hd_t mac, const void *key, size_t key_len, const void *buf, | |||
98 | * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes) | 103 | * @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes) |
99 | * @return #GNUNET_YES on success | 104 | * @return #GNUNET_YES on success |
100 | */ | 105 | */ |
101 | static int | 106 | static enum GNUNET_GenericReturnValue |
102 | getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm, | 107 | getPRK (gcry_md_hd_t mac, |
103 | size_t skm_len, void *prk) | 108 | const void *xts, |
109 | size_t xts_len, | ||
110 | const void *skm, | ||
111 | size_t skm_len, | ||
112 | void *prk) | ||
104 | { | 113 | { |
105 | const void *ret; | 114 | const void *ret; |
106 | size_t dlen; | 115 | size_t dlen; |
@@ -114,9 +123,10 @@ getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm, | |||
114 | * salt - optional salt value (a non-secret random value); | 123 | * salt - optional salt value (a non-secret random value); |
115 | * if not provided, it is set to a string of HashLen zeros. */ | 124 | * if not provided, it is set to a string of HashLen zeros. */ |
116 | 125 | ||
117 | if (xts_len == 0) | 126 | if (0 == xts_len) |
118 | { | 127 | { |
119 | char zero_salt[dlen]; | 128 | char zero_salt[dlen]; |
129 | |||
120 | memset (zero_salt, 0, dlen); | 130 | memset (zero_salt, 0, dlen); |
121 | ret = doHMAC (mac, zero_salt, dlen, skm, skm_len); | 131 | ret = doHMAC (mac, zero_salt, dlen, skm, skm_len); |
122 | } | 132 | } |
@@ -124,22 +134,23 @@ getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm, | |||
124 | { | 134 | { |
125 | ret = doHMAC (mac, xts, xts_len, skm, skm_len); | 135 | ret = doHMAC (mac, xts, xts_len, skm, skm_len); |
126 | } | 136 | } |
127 | if (ret == NULL) | 137 | if (NULL == ret) |
128 | return GNUNET_SYSERR; | 138 | return GNUNET_SYSERR; |
129 | GNUNET_memcpy (prk, ret, dlen); | 139 | GNUNET_memcpy (prk, |
130 | 140 | ret, | |
141 | dlen); | ||
131 | return GNUNET_YES; | 142 | return GNUNET_YES; |
132 | } | 143 | } |
133 | 144 | ||
134 | 145 | ||
135 | #if DEBUG_HKDF | 146 | #if DEBUG_HKDF |
136 | static void | 147 | static void |
137 | dump (const char *src, const void *p, unsigned int l) | 148 | dump (const char *src, |
149 | const void *p, | ||
150 | unsigned int l) | ||
138 | { | 151 | { |
139 | unsigned int i; | ||
140 | |||
141 | printf ("\n%s: ", src); | 152 | printf ("\n%s: ", src); |
142 | for (i = 0; i < l; i++) | 153 | for (unsigned int i = 0; i < l; i++) |
143 | { | 154 | { |
144 | printf ("%2x", (int) ((const unsigned char *) p)[i]); | 155 | printf ("%2x", (int) ((const unsigned char *) p)[i]); |
145 | } | 156 | } |
@@ -150,23 +161,16 @@ dump (const char *src, const void *p, unsigned int l) | |||
150 | #endif | 161 | #endif |
151 | 162 | ||
152 | 163 | ||
153 | /** | 164 | enum GNUNET_GenericReturnValue |
154 | * @brief Derive key | 165 | GNUNET_CRYPTO_hkdf_v (void *result, |
155 | * @param result buffer for the derived key, allocated by caller | 166 | size_t out_len, |
156 | * @param out_len desired length of the derived key | 167 | int xtr_algo, |
157 | * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... | 168 | int prf_algo, |
158 | * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... | 169 | const void *xts, |
159 | * @param xts salt | 170 | size_t xts_len, |
160 | * @param xts_len length of @a xts | 171 | const void *skm, |
161 | * @param skm source key material | 172 | size_t skm_len, |
162 | * @param skm_len length of @a skm | 173 | va_list argp) |
163 | * @param argp va_list of void * & size_t pairs for context chunks | ||
164 | * @return #GNUNET_YES on success | ||
165 | */ | ||
166 | int | ||
167 | GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, | ||
168 | const void *xts, size_t xts_len, const void *skm, | ||
169 | size_t skm_len, va_list argp) | ||
170 | { | 174 | { |
171 | gcry_md_hd_t xtr; | 175 | gcry_md_hd_t xtr; |
172 | gcry_md_hd_t prf; | 176 | gcry_md_hd_t prf; |
@@ -186,10 +190,14 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, | |||
186 | if (0 == k) | 190 | if (0 == k) |
187 | return GNUNET_SYSERR; | 191 | return GNUNET_SYSERR; |
188 | if (GPG_ERR_NO_ERROR != | 192 | if (GPG_ERR_NO_ERROR != |
189 | gcry_md_open (&xtr, xtr_algo, GCRY_MD_FLAG_HMAC)) | 193 | gcry_md_open (&xtr, |
194 | xtr_algo, | ||
195 | GCRY_MD_FLAG_HMAC)) | ||
190 | return GNUNET_SYSERR; | 196 | return GNUNET_SYSERR; |
191 | if (GPG_ERR_NO_ERROR != | 197 | if (GPG_ERR_NO_ERROR != |
192 | gcry_md_open (&prf, prf_algo, GCRY_MD_FLAG_HMAC)) | 198 | gcry_md_open (&prf, |
199 | prf_algo, | ||
200 | GCRY_MD_FLAG_HMAC)) | ||
193 | { | 201 | { |
194 | gcry_md_close (xtr); | 202 | gcry_md_close (xtr); |
195 | return GNUNET_SYSERR; | 203 | return GNUNET_SYSERR; |
@@ -221,7 +229,8 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, | |||
221 | } | 229 | } |
222 | 230 | ||
223 | memset (result, 0, out_len); | 231 | memset (result, 0, out_len); |
224 | if (getPRK (xtr, xts, xts_len, skm, skm_len, prk) != GNUNET_YES) | 232 | if (GNUNET_YES != |
233 | getPRK (xtr, xts, xts_len, skm, skm_len, prk)) | ||
225 | goto hkdf_error; | 234 | goto hkdf_error; |
226 | #if DEBUG_HKDF | 235 | #if DEBUG_HKDF |
227 | dump ("PRK", prk, xtr_len); | 236 | dump ("PRK", prk, xtr_len); |
@@ -276,7 +285,7 @@ GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo, | |||
276 | dump ("K(i+1)", plain, plain_len); | 285 | dump ("K(i+1)", plain, plain_len); |
277 | #endif | 286 | #endif |
278 | hc = doHMAC (prf, prk, xtr_len, plain, plain_len); | 287 | hc = doHMAC (prf, prk, xtr_len, plain, plain_len); |
279 | if (hc == NULL) | 288 | if (NULL == hc) |
280 | { | 289 | { |
281 | GNUNET_free (plain); | 290 | GNUNET_free (plain); |
282 | goto hkdf_error; | 291 | goto hkdf_error; |
@@ -327,32 +336,31 @@ hkdf_ok: | |||
327 | } | 336 | } |
328 | 337 | ||
329 | 338 | ||
330 | /** | 339 | enum GNUNET_GenericReturnValue |
331 | * @brief Derive key | 340 | GNUNET_CRYPTO_hkdf (void *result, |
332 | * @param result buffer for the derived key, allocated by caller | 341 | size_t out_len, |
333 | * @param out_len desired length of the derived key | 342 | int xtr_algo, |
334 | * @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_... | 343 | int prf_algo, |
335 | * @param prf_algo hash algorithm for the expansion phase, GCRY_MD_... | 344 | const void *xts, |
336 | * @param xts salt | 345 | size_t xts_len, |
337 | * @param xts_len length of @a xts | 346 | const void *skm, |
338 | * @param skm source key material | ||
339 | * @param skm_len length of @a skm | ||
340 | * @return #GNUNET_YES on success | ||
341 | */ | ||
342 | int | ||
343 | GNUNET_CRYPTO_hkdf (void *result, size_t out_len, int xtr_algo, int prf_algo, | ||
344 | const void *xts, size_t xts_len, const void *skm, | ||
345 | size_t skm_len, ...) | 347 | size_t skm_len, ...) |
346 | { | 348 | { |
347 | va_list argp; | 349 | va_list argp; |
348 | int ret; | 350 | enum GNUNET_GenericReturnValue ret; |
349 | 351 | ||
350 | va_start (argp, skm_len); | 352 | va_start (argp, skm_len); |
351 | ret = | 353 | ret = |
352 | GNUNET_CRYPTO_hkdf_v (result, out_len, xtr_algo, prf_algo, xts, xts_len, | 354 | GNUNET_CRYPTO_hkdf_v (result, |
353 | skm, skm_len, argp); | 355 | out_len, |
356 | xtr_algo, | ||
357 | prf_algo, | ||
358 | xts, | ||
359 | xts_len, | ||
360 | skm, | ||
361 | skm_len, | ||
362 | argp); | ||
354 | va_end (argp); | 363 | va_end (argp); |
355 | |||
356 | return ret; | 364 | return ret; |
357 | } | 365 | } |
358 | 366 | ||
diff --git a/src/util/crypto_kdf.c b/src/util/crypto_kdf.c index 0dc734549..f577e0f7a 100644 --- a/src/util/crypto_kdf.c +++ b/src/util/crypto_kdf.c | |||
@@ -32,18 +32,8 @@ | |||
32 | 32 | ||
33 | #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-kdf", __VA_ARGS__) | 33 | #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-kdf", __VA_ARGS__) |
34 | 34 | ||
35 | /** | 35 | |
36 | * @brief Derive key | 36 | enum GNUNET_GenericReturnValue |
37 | * @param result buffer for the derived key, allocated by caller | ||
38 | * @param out_len desired length of the derived key | ||
39 | * @param xts salt | ||
40 | * @param xts_len length of @a xts | ||
41 | * @param skm source key material | ||
42 | * @param skm_len length of @a skm | ||
43 | * @param argp va_list of void * & size_t pairs for context chunks | ||
44 | * @return #GNUNET_YES on success | ||
45 | */ | ||
46 | int | ||
47 | GNUNET_CRYPTO_kdf_v (void *result, | 37 | GNUNET_CRYPTO_kdf_v (void *result, |
48 | size_t out_len, | 38 | size_t out_len, |
49 | const void *xts, | 39 | const void *xts, |
@@ -62,7 +52,7 @@ GNUNET_CRYPTO_kdf_v (void *result, | |||
62 | * hash function." | 52 | * hash function." |
63 | * | 53 | * |
64 | * http://eprint.iacr.org/2010/264 | 54 | * http://eprint.iacr.org/2010/264 |
65 | */// | 55 | */ |
66 | return GNUNET_CRYPTO_hkdf_v (result, | 56 | return GNUNET_CRYPTO_hkdf_v (result, |
67 | out_len, | 57 | out_len, |
68 | GCRY_MD_SHA512, | 58 | GCRY_MD_SHA512, |
@@ -75,18 +65,7 @@ GNUNET_CRYPTO_kdf_v (void *result, | |||
75 | } | 65 | } |
76 | 66 | ||
77 | 67 | ||
78 | /** | 68 | enum GNUNET_GenericReturnValue |
79 | * @brief Derive key | ||
80 | * @param result buffer for the derived key, allocated by caller | ||
81 | * @param out_len desired length of the derived key | ||
82 | * @param xts salt | ||
83 | * @param xts_len length of @a xts | ||
84 | * @param skm source key material | ||
85 | * @param skm_len length of @a skm | ||
86 | * @param ... void * & size_t pairs for context chunks | ||
87 | * @return #GNUNET_YES on success | ||
88 | */ | ||
89 | int | ||
90 | GNUNET_CRYPTO_kdf (void *result, | 69 | GNUNET_CRYPTO_kdf (void *result, |
91 | size_t out_len, | 70 | size_t out_len, |
92 | const void *xts, | 71 | const void *xts, |
@@ -111,18 +90,6 @@ GNUNET_CRYPTO_kdf (void *result, | |||
111 | } | 90 | } |
112 | 91 | ||
113 | 92 | ||
114 | /** | ||
115 | * Deterministically generate a pseudo-random number uniformly from the | ||
116 | * integers modulo a libgcrypt mpi. | ||
117 | * | ||
118 | * @param[out] r MPI value set to the FDH | ||
119 | * @param n MPI to work modulo | ||
120 | * @param xts salt | ||
121 | * @param xts_len length of @a xts | ||
122 | * @param skm source key material | ||
123 | * @param skm_len length of @a skm | ||
124 | * @param ctx context string | ||
125 | */ | ||
126 | void | 93 | void |
127 | GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r, | 94 | GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r, |
128 | gcry_mpi_t n, | 95 | gcry_mpi_t n, |
@@ -137,32 +104,34 @@ GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r, | |||
137 | 104 | ||
138 | nbits = gcry_mpi_get_nbits (n); | 105 | nbits = gcry_mpi_get_nbits (n); |
139 | /* GNUNET_assert (nbits > 512); */ | 106 | /* GNUNET_assert (nbits > 512); */ |
140 | |||
141 | ctr = 0; | 107 | ctr = 0; |
142 | while (1) | 108 | while (1) |
143 | { | 109 | { |
144 | /* Ain't clear if n is always divisible by 8 */ | 110 | /* Ain't clear if n is always divisible by 8 */ |
145 | uint8_t buf[ (nbits - 1) / 8 + 1 ]; | 111 | size_t bsize = (nbits - 1) / 8 + 1; |
112 | uint8_t buf[bsize]; | ||
146 | uint16_t ctr_nbo = htons (ctr); | 113 | uint16_t ctr_nbo = htons (ctr); |
147 | 114 | ||
148 | rc = GNUNET_CRYPTO_kdf (buf, | 115 | rc = GNUNET_CRYPTO_kdf (buf, |
149 | sizeof(buf), | 116 | bsize, |
150 | xts, xts_len, | 117 | xts, xts_len, |
151 | skm, skm_len, | 118 | skm, skm_len, |
152 | ctx, strlen (ctx), | 119 | ctx, strlen (ctx), |
153 | &ctr_nbo, sizeof(ctr_nbo), | 120 | &ctr_nbo, sizeof(ctr_nbo), |
154 | NULL, 0); | 121 | NULL, 0); |
155 | GNUNET_assert (GNUNET_YES == rc); | 122 | GNUNET_assert (GNUNET_YES == rc); |
156 | |||
157 | rc = gcry_mpi_scan (r, | 123 | rc = gcry_mpi_scan (r, |
158 | GCRYMPI_FMT_USG, | 124 | GCRYMPI_FMT_USG, |
159 | (const unsigned char *) buf, | 125 | (const unsigned char *) buf, |
160 | sizeof(buf), | 126 | bsize, |
161 | &rsize); | 127 | &rsize); |
162 | GNUNET_assert (0 == rc); /* Allocation error? */ | 128 | GNUNET_assert (GPG_ERR_NO_ERROR == rc); /* Allocation error? */ |
163 | 129 | GNUNET_assert (rsize == bsize); | |
164 | gcry_mpi_clear_highbit (*r, nbits); | 130 | gcry_mpi_clear_highbit (*r, |
165 | GNUNET_assert (0 == gcry_mpi_test_bit (*r, nbits)); | 131 | nbits); |
132 | GNUNET_assert (0 == | ||
133 | gcry_mpi_test_bit (*r, | ||
134 | nbits)); | ||
166 | ++ctr; | 135 | ++ctr; |
167 | /* We reject this FDH if either *r > n and retry with another ctr */ | 136 | /* We reject this FDH if either *r > n and retry with another ctr */ |
168 | if (0 > gcry_mpi_cmp (*r, n)) | 137 | if (0 > gcry_mpi_cmp (*r, n)) |
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c index 43e6eedac..4b8e5a5ce 100644 --- a/src/util/crypto_rsa.c +++ b/src/util/crypto_rsa.c | |||
@@ -497,7 +497,8 @@ GNUNET_CRYPTO_rsa_public_key_decode (const char *buf, | |||
497 | * @return True if gcd(r,n) = 1, False means RSA key is malicious | 497 | * @return True if gcd(r,n) = 1, False means RSA key is malicious |
498 | */ | 498 | */ |
499 | static int | 499 | static int |
500 | rsa_gcd_validate (gcry_mpi_t r, gcry_mpi_t n) | 500 | rsa_gcd_validate (gcry_mpi_t r, |
501 | gcry_mpi_t n) | ||
501 | { | 502 | { |
502 | gcry_mpi_t g; | 503 | gcry_mpi_t g; |
503 | int t; | 504 | int t; |
@@ -520,29 +521,34 @@ static struct RsaBlindingKey * | |||
520 | rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, | 521 | rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, |
521 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks) | 522 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks) |
522 | { | 523 | { |
523 | char *xts = "Blinding KDF extractor HMAC key"; /* Trusts bks' randomness more */ | 524 | const char *xts = "Blinding KDF extractor HMAC key"; /* Trusts bks' randomness more */ |
524 | struct RsaBlindingKey *blind; | 525 | struct RsaBlindingKey *blind; |
525 | gcry_mpi_t n; | 526 | gcry_mpi_t n; |
526 | 527 | ||
527 | blind = GNUNET_new (struct RsaBlindingKey); | 528 | blind = GNUNET_new (struct RsaBlindingKey); |
528 | GNUNET_assert (NULL != blind); | ||
529 | 529 | ||
530 | /* Extract the composite n from the RSA public key */ | 530 | /* Extract the composite n from the RSA public key */ |
531 | GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n")); | 531 | GNUNET_assert (0 == |
532 | key_from_sexp (&n, | ||
533 | pkey->sexp, | ||
534 | "rsa", | ||
535 | "n")); | ||
532 | /* Assert that it at least looks like an RSA key */ | 536 | /* Assert that it at least looks like an RSA key */ |
533 | GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE)); | 537 | GNUNET_assert (0 == |
534 | 538 | gcry_mpi_get_flag (n, | |
539 | GCRYMPI_FLAG_OPAQUE)); | ||
535 | GNUNET_CRYPTO_kdf_mod_mpi (&blind->r, | 540 | GNUNET_CRYPTO_kdf_mod_mpi (&blind->r, |
536 | n, | 541 | n, |
537 | xts, strlen (xts), | 542 | xts, strlen (xts), |
538 | bks, sizeof(*bks), | 543 | bks, sizeof(*bks), |
539 | "Blinding KDF"); | 544 | "Blinding KDF"); |
540 | if (0 == rsa_gcd_validate (blind->r, n)) | 545 | if (0 == rsa_gcd_validate (blind->r, |
546 | n)) | ||
541 | { | 547 | { |
548 | gcry_mpi_release (blind->r); | ||
542 | GNUNET_free (blind); | 549 | GNUNET_free (blind); |
543 | blind = NULL; | 550 | blind = NULL; |
544 | } | 551 | } |
545 | |||
546 | gcry_mpi_release (n); | 552 | gcry_mpi_release (n); |
547 | return blind; | 553 | return blind; |
548 | } | 554 | } |
@@ -760,8 +766,9 @@ rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, | |||
760 | /* We key with the public denomination key as a homage to RSA-PSS by * | 766 | /* We key with the public denomination key as a homage to RSA-PSS by * |
761 | * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree * | 767 | * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree * |
762 | * of the hypothetical polyomial-time attack on RSA-KTI created by a * | 768 | * of the hypothetical polyomial-time attack on RSA-KTI created by a * |
763 | * polynomial-time one-more forgary attack. Yey seeding! */ | 769 | * polynomial-time one-more forgary attack. Yey seeding! */ |
764 | xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts); | 770 | xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, |
771 | &xts); | ||
765 | 772 | ||
766 | GNUNET_CRYPTO_kdf_mod_mpi (&r, | 773 | GNUNET_CRYPTO_kdf_mod_mpi (&r, |
767 | n, | 774 | n, |
@@ -769,7 +776,6 @@ rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, | |||
769 | hash, sizeof(*hash), | 776 | hash, sizeof(*hash), |
770 | "RSA-FDA FTpsW!"); | 777 | "RSA-FDA FTpsW!"); |
771 | GNUNET_free (xts); | 778 | GNUNET_free (xts); |
772 | |||
773 | ok = rsa_gcd_validate (r, n); | 779 | ok = rsa_gcd_validate (r, n); |
774 | gcry_mpi_release (n); | 780 | gcry_mpi_release (n); |
775 | if (ok) | 781 | if (ok) |
diff --git a/src/util/test_crypto_eddsa.c b/src/util/test_crypto_eddsa.c index 459619ff2..e9573a307 100644 --- a/src/util/test_crypto_eddsa.c +++ b/src/util/test_crypto_eddsa.c | |||
@@ -130,9 +130,11 @@ testDeriveSignVerify (void) | |||
130 | return GNUNET_SYSERR; | 130 | return GNUNET_SYSERR; |
131 | } | 131 | } |
132 | 132 | ||
133 | GNUNET_CRYPTO_eddsa_sign_with_scalar (&dpriv, | 133 | GNUNET_CRYPTO_eddsa_sign_derived (&key, |
134 | &purp, | 134 | "test-derive", |
135 | &sig); | 135 | "test-CTX", |
136 | &purp, | ||
137 | &sig); | ||
136 | if (GNUNET_SYSERR == | 138 | if (GNUNET_SYSERR == |
137 | GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST, | 139 | GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST, |
138 | &purp, | 140 | &purp, |
diff --git a/src/util/test_crypto_edx25519.c b/src/util/test_crypto_edx25519.c new file mode 100644 index 000000000..ead6f0bb9 --- /dev/null +++ b/src/util/test_crypto_edx25519.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2022 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/test_crypto_edx25519.c | ||
23 | * @brief testcase for ECC public key crypto for edx25519 | ||
24 | * @author Özgür Kesim | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_signatures.h" | ||
29 | #include <gcrypt.h> | ||
30 | |||
31 | #define ITER 25 | ||
32 | |||
33 | #define KEYFILE "/tmp/test-gnunet-crypto-edx25519.key" | ||
34 | |||
35 | #define PERF GNUNET_YES | ||
36 | |||
37 | |||
38 | static struct GNUNET_CRYPTO_Edx25519PrivateKey key; | ||
39 | |||
40 | |||
41 | static int | ||
42 | testSignVerify (void) | ||
43 | { | ||
44 | struct GNUNET_CRYPTO_Edx25519Signature sig; | ||
45 | struct GNUNET_CRYPTO_EccSignaturePurpose purp; | ||
46 | struct GNUNET_CRYPTO_Edx25519PublicKey pkey; | ||
47 | struct GNUNET_TIME_Absolute start; | ||
48 | int ok = GNUNET_OK; | ||
49 | |||
50 | fprintf (stderr, "%s", "W"); | ||
51 | GNUNET_CRYPTO_edx25519_key_get_public (&key, | ||
52 | &pkey); | ||
53 | start = GNUNET_TIME_absolute_get (); | ||
54 | purp.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)); | ||
55 | purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); | ||
56 | |||
57 | for (unsigned int i = 0; i < ITER; i++) | ||
58 | { | ||
59 | fprintf (stderr, "%s", "."); fflush (stderr); | ||
60 | if (GNUNET_SYSERR == GNUNET_CRYPTO_edx25519_sign_ (&key, | ||
61 | &purp, | ||
62 | &sig)) | ||
63 | { | ||
64 | fprintf (stderr, | ||
65 | "GNUNET_CRYPTO_edx25519_sign returned SYSERR\n"); | ||
66 | ok = GNUNET_SYSERR; | ||
67 | continue; | ||
68 | } | ||
69 | if (GNUNET_SYSERR == | ||
70 | GNUNET_CRYPTO_edx25519_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST, | ||
71 | &purp, | ||
72 | &sig, | ||
73 | &pkey)) | ||
74 | { | ||
75 | fprintf (stderr, | ||
76 | "GNUNET_CRYPTO_edx25519_verify failed!\n"); | ||
77 | ok = GNUNET_SYSERR; | ||
78 | continue; | ||
79 | } | ||
80 | if (GNUNET_SYSERR != | ||
81 | GNUNET_CRYPTO_edx25519_verify_ ( | ||
82 | GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, | ||
83 | &purp, | ||
84 | &sig, | ||
85 | &pkey)) | ||
86 | { | ||
87 | fprintf (stderr, | ||
88 | "GNUNET_CRYPTO_edx25519_verify failed to fail!\n"); | ||
89 | ok = GNUNET_SYSERR; | ||
90 | continue; | ||
91 | } | ||
92 | } | ||
93 | fprintf (stderr, "\n"); | ||
94 | printf ("%d EdDSA sign/verify operations %s\n", | ||
95 | ITER, | ||
96 | GNUNET_STRINGS_relative_time_to_string ( | ||
97 | GNUNET_TIME_absolute_get_duration (start), | ||
98 | GNUNET_YES)); | ||
99 | return ok; | ||
100 | } | ||
101 | |||
102 | |||
103 | static int | ||
104 | testDeriveSignVerify (void) | ||
105 | { | ||
106 | struct GNUNET_CRYPTO_EccSignaturePurpose purp; | ||
107 | struct GNUNET_CRYPTO_Edx25519Signature sig; | ||
108 | struct GNUNET_CRYPTO_Edx25519PrivateKey dkey; | ||
109 | struct GNUNET_CRYPTO_Edx25519PublicKey pub; | ||
110 | struct GNUNET_CRYPTO_Edx25519PublicKey dpub; | ||
111 | struct GNUNET_CRYPTO_Edx25519PublicKey dpub2; | ||
112 | |||
113 | GNUNET_CRYPTO_edx25519_key_get_public (&key, &pub); | ||
114 | GNUNET_CRYPTO_edx25519_private_key_derive (&key, | ||
115 | "test-derive", | ||
116 | sizeof("test-derive"), | ||
117 | &dkey); | ||
118 | GNUNET_CRYPTO_edx25519_public_key_derive (&pub, | ||
119 | "test-derive", | ||
120 | sizeof("test-derive"), | ||
121 | &dpub); | ||
122 | GNUNET_CRYPTO_edx25519_key_get_public (&dkey, &dpub2); | ||
123 | |||
124 | if (0 != GNUNET_memcmp (&dpub.q_y, &dpub2.q_y)) | ||
125 | { | ||
126 | fprintf (stderr, "key deriviation failed\n"); | ||
127 | return GNUNET_SYSERR; | ||
128 | } | ||
129 | |||
130 | purp.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)); | ||
131 | purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); | ||
132 | |||
133 | GNUNET_CRYPTO_edx25519_sign_ (&dkey, | ||
134 | &purp, | ||
135 | &sig); | ||
136 | |||
137 | if (GNUNET_SYSERR == | ||
138 | GNUNET_CRYPTO_edx25519_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST, | ||
139 | &purp, | ||
140 | &sig, | ||
141 | &dpub)) | ||
142 | { | ||
143 | fprintf (stderr, | ||
144 | "GNUNET_CRYPTO_edx25519_verify failed after derivation!\n"); | ||
145 | return GNUNET_SYSERR; | ||
146 | } | ||
147 | |||
148 | if (GNUNET_SYSERR != | ||
149 | GNUNET_CRYPTO_edx25519_verify_ (GNUNET_SIGNATURE_PURPOSE_TEST, | ||
150 | &purp, | ||
151 | &sig, | ||
152 | &pub)) | ||
153 | { | ||
154 | fprintf (stderr, | ||
155 | "GNUNET_CRYPTO_edx25519_verify failed to fail after derivation!\n"); | ||
156 | return GNUNET_SYSERR; | ||
157 | } | ||
158 | |||
159 | if (GNUNET_SYSERR != | ||
160 | GNUNET_CRYPTO_edx25519_verify_ ( | ||
161 | GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, | ||
162 | &purp, | ||
163 | &sig, | ||
164 | &dpub)) | ||
165 | { | ||
166 | fprintf (stderr, | ||
167 | "GNUNET_CRYPTO_edx25519_verify failed to fail after derivation!\n"); | ||
168 | return GNUNET_SYSERR; | ||
169 | } | ||
170 | return GNUNET_OK; | ||
171 | } | ||
172 | |||
173 | |||
174 | #if PERF | ||
175 | static int | ||
176 | testSignPerformance () | ||
177 | { | ||
178 | struct GNUNET_CRYPTO_EccSignaturePurpose purp; | ||
179 | struct GNUNET_CRYPTO_Edx25519Signature sig; | ||
180 | struct GNUNET_CRYPTO_Edx25519PublicKey pkey; | ||
181 | struct GNUNET_TIME_Absolute start; | ||
182 | int ok = GNUNET_OK; | ||
183 | |||
184 | purp.size = htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)); | ||
185 | purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); | ||
186 | fprintf (stderr, "%s", "W"); | ||
187 | GNUNET_CRYPTO_edx25519_key_get_public (&key, | ||
188 | &pkey); | ||
189 | start = GNUNET_TIME_absolute_get (); | ||
190 | for (unsigned int i = 0; i < ITER; i++) | ||
191 | { | ||
192 | fprintf (stderr, "%s", "."); | ||
193 | fflush (stderr); | ||
194 | if (GNUNET_SYSERR == | ||
195 | GNUNET_CRYPTO_edx25519_sign_ (&key, | ||
196 | &purp, | ||
197 | &sig)) | ||
198 | { | ||
199 | fprintf (stderr, "%s", "GNUNET_CRYPTO_edx25519_sign returned SYSERR\n"); | ||
200 | ok = GNUNET_SYSERR; | ||
201 | continue; | ||
202 | } | ||
203 | } | ||
204 | fprintf (stderr, "\n"); | ||
205 | printf ("%d EdDSA sign operations %s\n", | ||
206 | ITER, | ||
207 | GNUNET_STRINGS_relative_time_to_string ( | ||
208 | GNUNET_TIME_absolute_get_duration (start), | ||
209 | GNUNET_YES)); | ||
210 | return ok; | ||
211 | } | ||
212 | |||
213 | |||
214 | #endif | ||
215 | |||
216 | |||
217 | #if 0 /* not implemented */ | ||
218 | static int | ||
219 | testCreateFromFile (void) | ||
220 | { | ||
221 | struct GNUNET_CRYPTO_Edx25519PublicKey p1; | ||
222 | struct GNUNET_CRYPTO_Edx25519PublicKey p2; | ||
223 | |||
224 | /* do_create == GNUNET_YES and non-existing file MUST return GNUNET_YES */ | ||
225 | GNUNET_assert (0 == unlink (KEYFILE) || ENOENT == errno); | ||
226 | GNUNET_assert (GNUNET_YES == | ||
227 | GNUNET_CRYPTO_edx25519_key_from_file (KEYFILE, | ||
228 | GNUNET_YES, | ||
229 | &key)); | ||
230 | GNUNET_CRYPTO_edx25519_key_get_public (&key, | ||
231 | &p1); | ||
232 | |||
233 | /* do_create == GNUNET_YES and _existing_ file MUST return GNUNET_NO */ | ||
234 | GNUNET_assert (GNUNET_NO == | ||
235 | GNUNET_CRYPTO_edx25519_key_from_file (KEYFILE, | ||
236 | GNUNET_YES, | ||
237 | &key)); | ||
238 | GNUNET_CRYPTO_edx25519_key_get_public (&key, | ||
239 | &p2); | ||
240 | GNUNET_assert (0 == | ||
241 | GNUNET_memcmp (&p1, | ||
242 | &p2)); | ||
243 | |||
244 | /* do_create == GNUNET_NO and non-existing file MUST return GNUNET_SYSERR */ | ||
245 | GNUNET_assert (0 == unlink (KEYFILE)); | ||
246 | GNUNET_assert (GNUNET_SYSERR == | ||
247 | GNUNET_CRYPTO_edx25519_key_from_file (KEYFILE, | ||
248 | GNUNET_NO, | ||
249 | &key)); | ||
250 | return GNUNET_OK; | ||
251 | } | ||
252 | |||
253 | |||
254 | #endif | ||
255 | |||
256 | |||
257 | static void | ||
258 | perf_keygen (void) | ||
259 | { | ||
260 | struct GNUNET_TIME_Absolute start; | ||
261 | struct GNUNET_CRYPTO_Edx25519PrivateKey pk; | ||
262 | |||
263 | fprintf (stderr, "%s", "W"); | ||
264 | start = GNUNET_TIME_absolute_get (); | ||
265 | for (unsigned int i = 0; i < 10; i++) | ||
266 | { | ||
267 | fprintf (stderr, "."); | ||
268 | fflush (stderr); | ||
269 | GNUNET_CRYPTO_edx25519_key_create (&pk); | ||
270 | } | ||
271 | fprintf (stderr, "\n"); | ||
272 | printf ("10 EdDSA keys created in %s\n", | ||
273 | GNUNET_STRINGS_relative_time_to_string ( | ||
274 | GNUNET_TIME_absolute_get_duration (start), GNUNET_YES)); | ||
275 | } | ||
276 | |||
277 | |||
278 | int | ||
279 | main (int argc, char *argv[]) | ||
280 | { | ||
281 | int failure_count = 0; | ||
282 | |||
283 | if (! gcry_check_version ("1.6.0")) | ||
284 | { | ||
285 | fprintf (stderr, | ||
286 | "libgcrypt has not the expected version (version %s is required).\n", | ||
287 | "1.6.0"); | ||
288 | return 0; | ||
289 | } | ||
290 | if (getenv ("GNUNET_GCRYPT_DEBUG")) | ||
291 | gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); | ||
292 | GNUNET_log_setup ("test-crypto-edx25519", | ||
293 | "WARNING", | ||
294 | NULL); | ||
295 | GNUNET_CRYPTO_edx25519_key_create (&key); | ||
296 | if (GNUNET_OK != testDeriveSignVerify ()) | ||
297 | { | ||
298 | failure_count++; | ||
299 | fprintf (stderr, | ||
300 | "\n\n%d TESTS FAILED!\n\n", failure_count); | ||
301 | return -1; | ||
302 | } | ||
303 | #if PERF | ||
304 | if (GNUNET_OK != testSignPerformance ()) | ||
305 | failure_count++; | ||
306 | #endif | ||
307 | if (GNUNET_OK != testSignVerify ()) | ||
308 | failure_count++; | ||
309 | #if 0 /* not implemented */ | ||
310 | if (GNUNET_OK != testCreateFromFile ()) | ||
311 | failure_count++; | ||
312 | #endif | ||
313 | perf_keygen (); | ||
314 | |||
315 | if (0 != failure_count) | ||
316 | { | ||
317 | fprintf (stderr, | ||
318 | "\n\n%d TESTS FAILED!\n\n", | ||
319 | failure_count); | ||
320 | return -1; | ||
321 | } | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | |||
326 | /* end of test_crypto_edx25519.c */ | ||
diff --git a/src/util/time.c b/src/util/time.c index 68a6937a0..cf072aebf 100644 --- a/src/util/time.c +++ b/src/util/time.c | |||
@@ -58,6 +58,22 @@ GNUNET_TIME_get_offset () | |||
58 | } | 58 | } |
59 | 59 | ||
60 | 60 | ||
61 | bool | ||
62 | GNUNET_TIME_absolute_approx_eq (struct GNUNET_TIME_Absolute a1, | ||
63 | struct GNUNET_TIME_Absolute a2, | ||
64 | struct GNUNET_TIME_Relative t) | ||
65 | { | ||
66 | struct GNUNET_TIME_Relative delta; | ||
67 | |||
68 | delta = GNUNET_TIME_relative_min ( | ||
69 | GNUNET_TIME_absolute_get_difference (a1, a2), | ||
70 | GNUNET_TIME_absolute_get_difference (a2, a1)); | ||
71 | return GNUNET_TIME_relative_cmp (delta, | ||
72 | <=, | ||
73 | t); | ||
74 | } | ||
75 | |||
76 | |||
61 | struct GNUNET_TIME_Timestamp | 77 | struct GNUNET_TIME_Timestamp |
62 | GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at) | 78 | GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at) |
63 | { | 79 | { |
@@ -370,6 +386,20 @@ GNUNET_TIME_timestamp_min (struct GNUNET_TIME_Timestamp t1, | |||
370 | } | 386 | } |
371 | 387 | ||
372 | 388 | ||
389 | struct GNUNET_TIME_Absolute | ||
390 | GNUNET_TIME_absolute_round_down (struct GNUNET_TIME_Absolute at, | ||
391 | struct GNUNET_TIME_Relative rt) | ||
392 | { | ||
393 | struct GNUNET_TIME_Absolute ret; | ||
394 | |||
395 | GNUNET_assert (! GNUNET_TIME_relative_is_zero (rt)); | ||
396 | ret.abs_value_us | ||
397 | = at.abs_value_us | ||
398 | - at.abs_value_us % rt.rel_value_us; | ||
399 | return ret; | ||
400 | } | ||
401 | |||
402 | |||
373 | struct GNUNET_TIME_Relative | 403 | struct GNUNET_TIME_Relative |
374 | GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future) | 404 | GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future) |
375 | { | 405 | { |