GNUnet 0.22.2
crypto_edx25519.c
Go to the documentation of this file.
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
30#include "platform.h"
31#include <gcrypt.h>
32#include <sodium.h>
33#include "gnunet_util_lib.h"
34
35#define CURVE "Ed25519"
36
37void
39{
40 memset (pk, 0, sizeof(struct GNUNET_CRYPTO_Edx25519PrivateKey));
41}
42
43
44void
46 const void *seed,
47 size_t seedsize,
49{
50
51 GNUNET_static_assert (sizeof(*pk) == sizeof(struct GNUNET_HashCode));
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
64void
67{
68 char seed[256 / 8];
70 seed,
71 sizeof (seed));
73 sizeof(seed),
74 pk);
75}
76
77
78void
80 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
82{
83 crypto_scalarmult_ed25519_base_noclamp (pub->q_y,
84 priv->a);
85}
86
87
104 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
105 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
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 unsigned char hram_mod[64];
117
118 crypto_hash_sha512_init (&hs);
119
123 crypto_scalarmult_ed25519_base_noclamp (P,
124 priv->a);
125
131 crypto_hash_sha512_update (&hs,
132 priv->b,
133 sizeof(priv->b));
134 crypto_hash_sha512_update (&hs,
135 (uint8_t*) purpose,
136 ntohl (purpose->size));
137 crypto_hash_sha512_final (&hs,
138 r);
139
143 memcpy (sig->s, P, 32);
144
148 crypto_core_ed25519_scalar_reduce (r_mod, r);
149
153 crypto_scalarmult_ed25519_base_noclamp (R, r_mod);
154 memcpy (sig->r, R, sizeof (R));
155
160 crypto_hash_sha512_init (&hs);
161 crypto_hash_sha512_update (&hs, (uint8_t*) sig, 64);
162 crypto_hash_sha512_update (&hs, (uint8_t*) purpose,
163 ntohl (purpose->size));
164 crypto_hash_sha512_final (&hs, hram);
165
169 crypto_core_ed25519_scalar_reduce (hram_mod, hram);
170
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
187 uint32_t purpose,
188 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
189 const struct GNUNET_CRYPTO_Edx25519Signature *sig,
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
216static void
219 const void *seed,
220 size_t seedsize,
221 struct GNUNET_HashCode *phc)
222{
229 static const char *const salt = "edx25519-derivation";
230
231 GNUNET_CRYPTO_kdf (/* output*/
232 phc, sizeof(*phc),
233 /* salt */
234 salt, strlen (salt),
235 /* ikm */
236 pub, sizeof(*pub),
237 /* ctx chunks*/
238 seed, seedsize,
239 NULL, 0);
240
241}
242
243
244void
246 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
247 const void *seed,
248 size_t seedsize,
250{
252 struct GNUNET_HashCode hc;
253 uint8_t a[32];
254 uint8_t eight[32] = { 8 };
255 uint8_t eight_inv[32];
256 uint8_t h[64] = { 0 };
257
259
260 /* Get h mod n */
261 derive_h (&pub,
262 seed,
263 seedsize,
264 &hc);
265
266 memcpy (h, &hc, 64);
267 crypto_core_ed25519_scalar_reduce (h,
268 h);
269#ifdef CHECK_RARE_CASES
277 {
278 char zero[32] = { 0 };
279 char one[32] = { 1 };
280
281 GNUNET_assert (0 != memcmp (zero, h, 32));
282 GNUNET_assert (0 != memcmp (one, h, 32));
283 }
284#endif
285
295 GNUNET_assert (0 == crypto_core_ed25519_scalar_invert (eight_inv,
296 eight));
297
298 crypto_core_ed25519_scalar_mul (a, priv->a, eight_inv);
299 crypto_core_ed25519_scalar_mul (a, a, h);
300 crypto_core_ed25519_scalar_mul (a, a, eight);
301
302#ifdef CHECK_RARE_CASES
303 /* The likelihood for a' == 0 or a' == 1 is neglegible */
304 {
305 char zero[32] = { 0 };
306 char one[32] = { 1 };
307
308 GNUNET_assert (0 != memcmp (zero, a, 32));
309 GNUNET_assert (0 != memcmp (one, a, 32));
310 }
311#endif
312
313 /* We hash the derived "h" parameter with the other half of the expanded
314 * private key (that is: priv->b). This ensures that for signature
315 * generation, the "R" is derived from the same derivation path as "h" and is
316 * not reused. */
317 {
318 struct GNUNET_HashCode hcb;
319 struct GNUNET_HashContext *hctx;
320
322 GNUNET_CRYPTO_hash_context_read (hctx, priv->b, sizeof(priv->b));
323 GNUNET_CRYPTO_hash_context_read (hctx, (unsigned char*) &hc, sizeof (hc));
325
326 /* Truncate result, effectively doing SHA512/256 */
327 for (size_t i = 0; i < 32; i++)
328 result->b[i] = ((unsigned char *) &hcb)[i];
329 }
330
331 for (size_t i = 0; i < 32; i++)
332 result->a[i] = a[i];
333
334 sodium_memzero (a, sizeof(a));
335}
336
337
338void
341 const void *seed,
342 size_t seedsize,
344{
345 struct GNUNET_HashCode hc;
346 uint8_t h[64] = { 0 };
347
348 derive_h (pub,
349 seed,
350 seedsize,
351 &hc);
352 memcpy (h,
353 &hc,
354 64);
355 crypto_core_ed25519_scalar_reduce (h,
356 h);
357 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (result->q_y,
358 h,
359 pub->q_y));
360}
static void derive_h(const struct GNUNET_CRYPTO_Edx25519PublicKey *pub, const void *seed, size_t seedsize, struct GNUNET_HashCode *phc)
Derive the 'h' value for key derivation, where 'h = H(P ∥ seed) mod n' and 'n' is the size of the cyc...
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition: gnunet-arm.c:103
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:98
static uint8_t seed
struct GNUNET_CRYPTO_PrivateKey pk
Private key from command line option, or NULL.
static char * res
Currently read line or NULL on EOF.
static int result
Global testing status.
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:47
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calculations.
Definition: gnunet-scrypt.c:34
static const struct GNUNET_CRYPTO_PrivateKey zero
Public key of all zeros.
void GNUNET_CRYPTO_edx25519_key_get_public(const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv, struct GNUNET_CRYPTO_Edx25519PublicKey *pub)
Extract the public key for the given private key.
void GNUNET_CRYPTO_edx25519_key_clear(struct GNUNET_CRYPTO_Edx25519PrivateKey *pk)
Clear memory that was used to store a private key.
void GNUNET_CRYPTO_edx25519_private_key_derive(const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv, const void *seed, size_t seedsize, struct GNUNET_CRYPTO_Edx25519PrivateKey *result)
Derive a private scalar from a given private key and a label.
void GNUNET_CRYPTO_edx25519_key_create_from_seed(const void *seed, size_t seedsize, struct GNUNET_CRYPTO_Edx25519PrivateKey *pk)
Create a new private key for Edx25519 from a given seed.
void GNUNET_CRYPTO_edx25519_public_key_derive(const struct GNUNET_CRYPTO_Edx25519PublicKey *pub, const void *seed, size_t seedsize, struct GNUNET_CRYPTO_Edx25519PublicKey *result)
Derive a public key from a given public key and a label.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
void GNUNET_CRYPTO_edx25519_key_create(struct GNUNET_CRYPTO_Edx25519PrivateKey *pk)
Create a new private key.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_edx25519_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_Edx25519Signature *sig, const struct GNUNET_CRYPTO_Edx25519PublicKey *pub)
Verify Edx25519 signature.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_edx25519_sign_(const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_Edx25519Signature *sig)
This function operates the basically same way as the signature function for EdDSA.
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_kdf(void *result, size_t out_len, const void *xts, size_t xts_len, const void *skm, size_t skm_len,...)
Derive key.
Definition: crypto_kdf.c:62
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
Definition: crypto_hash.c:363
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:387
GNUNET_GenericReturnValue
Named constants for return values.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
Definition: crypto_hash.c:347
#define GNUNET_static_assert(cond)
Assertion to be checked (if supported by C compiler) at compile time, otherwise checked at runtime an...
@ GNUNET_OK
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
unsigned char q_y[256/8]
Point Q consists of a y-value mod p (256 bits); the x-value is always positive.
Private ECC key material encoded for transmission.
unsigned char b[256/8]
b consists of 32 bytes which where originally the lower 32bytes of the key expansion.
unsigned char a[256/8]
a is a value mod n, where n has at most 256 bits.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
an ECC signature using Edx25519 (same as in EdDSA).
unsigned char s[256/8]
S value.
unsigned char r[256/8]
R value.
A 512-bit hashcode.