GNUnet  0.20.0
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 
37 void
39 {
40  memset (pk, 0, sizeof(struct GNUNET_CRYPTO_Edx25519PrivateKey));
41 }
42 
43 
44 void
46  const void *seed,
47  size_t seedsize,
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
67 {
68  char seed[256 / 8];
70  seed,
71  sizeof (seed));
73  sizeof(seed),
74  pk);
75 }
76 
77 
78 void
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 
117  crypto_hash_sha512_init (&hs);
118 
122  crypto_scalarmult_ed25519_base_noclamp (P,
123  priv->a);
124 
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 
142  memcpy (sig->s, P, 32);
143 
147  crypto_core_ed25519_scalar_reduce (r_mod, r);
148 
152  crypto_scalarmult_ed25519_base_noclamp (R, r_mod);
153  memcpy (sig->r, R, sizeof (R));
154 
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 
168  unsigned char hram_mod[64];
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,
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 
216 static void
218  const struct GNUNET_CRYPTO_Edx25519PublicKey *pub,
219  const void *seed,
220  size_t seedsize,
221  struct GNUNET_HashCode *phc)
222 {
223  static const char *const salt = "edx25519-derivation";
224 
225  GNUNET_CRYPTO_kdf (/* output*/
226  phc, sizeof(*phc),
227  /* salt */
228  seed, seedsize,
229  /* ikm */
230  pub, sizeof(*pub),
231  /* ctx chunks*/
232  salt, strlen (salt),
233  NULL, 0);
234 
235 }
236 
237 
238 void
240  const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
241  const void *seed,
242  size_t seedsize,
244 {
246  struct GNUNET_HashCode hc;
247  uint8_t a[32];
248  uint8_t eight[32] = { 8 };
249  uint8_t eight_inv[32];
250  uint8_t h[64] = { 0 };
251 
253 
254  /* Get h mod n */
255  derive_h (&pub,
256  seed,
257  seedsize,
258  &hc);
259 
260  memcpy (h, &hc, 64);
261  crypto_core_ed25519_scalar_reduce (h,
262  h);
263 #ifdef CHECK_RARE_CASES
271  {
272  char zero[32] = { 0 };
273  char one[32] = { 1 };
274 
275  GNUNET_assert (0 != memcmp (zero, h, 32));
276  GNUNET_assert (0 != memcmp (one, h, 32));
277  }
278 #endif
279 
289  GNUNET_assert (0 == crypto_core_ed25519_scalar_invert (eight_inv,
290  eight));
291 
292  crypto_core_ed25519_scalar_mul (a, priv->a, eight_inv);
293  crypto_core_ed25519_scalar_mul (a, a, h);
294  crypto_core_ed25519_scalar_mul (a, a, eight);
295 
296 #ifdef CHECK_RARE_CASES
297  /* The likelihood for a' == 0 or a' == 1 is neglegible */
298  {
299  char zero[32] = { 0 };
300  char one[32] = { 1 };
301 
302  GNUNET_assert (0 != memcmp (zero, a, 32));
303  GNUNET_assert (0 != memcmp (one, a, 32));
304  }
305 #endif
306 
307  /* We hash the derived "h" parameter with the other half of the expanded
308  * private key (that is: priv->b). This ensures that for signature
309  * generation, the "R" is derived from the same derivation path as "h" and is
310  * not reused. */
311  {
312  struct GNUNET_HashCode hcb;
313  struct GNUNET_HashContext *hctx;
314 
316  GNUNET_CRYPTO_hash_context_read (hctx, priv->b, sizeof(priv->b));
317  GNUNET_CRYPTO_hash_context_read (hctx, (unsigned char*) &hc, sizeof (hc));
319 
320  /* Truncate result, effectively doing SHA512/256 */
321  for (size_t i = 0; i < 32; i++)
322  result->b[i] = ((unsigned char *) &hcb)[i];
323  }
324 
325  for (size_t i = 0; i < 32; i++)
326  result->a[i] = a[i];
327 
328  sodium_memzero (a, sizeof(a));
329 }
330 
331 
332 void
334  const struct GNUNET_CRYPTO_Edx25519PublicKey *pub,
335  const void *seed,
336  size_t seedsize,
338 {
339  struct GNUNET_HashCode hc;
340  uint8_t h[64] = { 0 };
341 
342  derive_h (pub,
343  seed,
344  seedsize,
345  &hc);
346  memcpy (h,
347  &hc,
348  64);
349  crypto_core_ed25519_scalar_reduce (h,
350  h);
351  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (result->q_y,
352  h,
353  pub->q_y));
354 }
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:104
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static int res
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
static int result
Global testing status.
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:47
static const struct GNUNET_IDENTITY_PrivateKey zero
Public key of all zeros.
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
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:70
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
Definition: crypto_hash.c:350
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:366
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
Definition: crypto_hash.c:390
GNUNET_GenericReturnValue
Named constants for return values.
#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.