GNUnet 0.28.0-dev.3-7-g31e20e2e6
 
Loading...
Searching...
No Matches
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 <sodium.h>
32#include "gnunet_util_lib.h"
33
34#define CURVE "Ed25519"
35
36void
41
42
43void
45 const void *seed,
46 size_t seedsize,
48{
49
50 GNUNET_static_assert (sizeof(*pk) == sizeof(struct GNUNET_HashCode));
52 seedsize,
53 (struct GNUNET_HashCode *) pk);
54
55 /* Clamp the first half of the key. The second half is used in the signature
56 * process. */
57 pk->a[0] &= 248;
58 pk->a[31] &= 127;
59 pk->a[31] |= 64;
60}
61
62
63void
74
75
76void
78 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
80{
81 crypto_scalarmult_ed25519_base_noclamp (pub->q_y,
82 priv->a);
83}
84
85
102 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
103 const struct GNUNET_CRYPTO_SignaturePurpose *purpose,
105{
106
107 crypto_hash_sha512_state hs;
108 unsigned char r[64];
109 unsigned char hram[64];
110 unsigned char P[32];
111 unsigned char r_mod[64];
112 unsigned char R[32];
113 unsigned char tmp[32];
114 unsigned char hram_mod[64];
115
116 crypto_hash_sha512_init (&hs);
117
121 crypto_scalarmult_ed25519_base_noclamp (P,
122 priv->a);
123
129 crypto_hash_sha512_update (&hs,
130 priv->b,
131 sizeof(priv->b));
132 crypto_hash_sha512_update (&hs,
133 (uint8_t*) purpose,
134 ntohl (purpose->size));
135 crypto_hash_sha512_final (&hs,
136 r);
137
141 memcpy (sig->s, P, 32);
142
146 crypto_core_ed25519_scalar_reduce (r_mod, r);
147
151 crypto_scalarmult_ed25519_base_noclamp (R, r_mod);
152 memcpy (sig->r, R, sizeof (R));
153
158 crypto_hash_sha512_init (&hs);
159 crypto_hash_sha512_update (&hs, (uint8_t*) sig, 64);
160 crypto_hash_sha512_update (&hs, (uint8_t*) purpose,
161 ntohl (purpose->size));
162 crypto_hash_sha512_final (&hs, hram);
163
167 crypto_core_ed25519_scalar_reduce (hram_mod, hram);
168
173 crypto_core_ed25519_scalar_mul (tmp, hram_mod, priv->a);
174 crypto_core_ed25519_scalar_add (sig->s, tmp, r_mod);
175
176 sodium_memzero (r, sizeof (r));
177 sodium_memzero (r_mod, sizeof (r_mod));
178
179 return GNUNET_OK;
180}
181
182
185 uint32_t purpose,
186 const struct GNUNET_CRYPTO_SignaturePurpose *validate,
187 const struct GNUNET_CRYPTO_Edx25519Signature *sig,
189{
190 const unsigned char *m = (const void *) validate;
191 size_t mlen = ntohl (validate->size);
192 const unsigned char *s = (const void *) sig;
193
194 int res;
195
196 if (purpose != ntohl (validate->purpose))
197 return GNUNET_SYSERR; /* purpose mismatch */
198
199 res = crypto_sign_verify_detached (s, m, mlen, pub->q_y);
200 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
201}
202
203
214static void
217 const void *seed,
218 size_t seedsize,
219 struct GNUNET_HashCode *phc)
220{
227 static const char *const salt = "edx25519-derivation";
228
229 GNUNET_CRYPTO_hkdf_gnunet (/* output*/
230 phc, sizeof(*phc),
231 /* salt */
232 salt, strlen (salt),
233 /* ikm */
234 pub, sizeof(*pub),
235 /* ctx chunks*/
236 GNUNET_CRYPTO_kdf_arg (seed, seedsize));
237
238}
239
240
241void
243 const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv,
244 const void *seed,
245 size_t seedsize,
247{
249 struct GNUNET_HashCode hc;
250 uint8_t a[32];
251 uint8_t eight[32] = { 8 };
252 uint8_t eight_inv[32];
253 uint8_t h[64] = { 0 };
254
256
257 /* Get h mod n */
258 derive_h (&pub,
259 seed,
260 seedsize,
261 &hc);
262
263 memcpy (h, &hc, 64);
264 crypto_core_ed25519_scalar_reduce (h,
265 h);
266#ifdef CHECK_RARE_CASES
274 {
275 char zero[32] = { 0 };
276 char one[32] = { 1 };
277
278 GNUNET_assert (0 != memcmp (zero, h, 32));
279 GNUNET_assert (0 != memcmp (one, h, 32));
280 }
281#endif
282
292 GNUNET_assert (0 == crypto_core_ed25519_scalar_invert (eight_inv,
293 eight));
294
295 crypto_core_ed25519_scalar_mul (a, priv->a, eight_inv);
296 crypto_core_ed25519_scalar_mul (a, a, h);
297 crypto_core_ed25519_scalar_mul (a, a, eight);
298
299#ifdef CHECK_RARE_CASES
300 /* The likelihood for a' == 0 or a' == 1 is neglegible */
301 {
302 char zero[32] = { 0 };
303 char one[32] = { 1 };
304
305 GNUNET_assert (0 != memcmp (zero, a, 32));
306 GNUNET_assert (0 != memcmp (one, a, 32));
307 }
308#endif
309
310 /* We hash the derived "h" parameter with the other half of the expanded
311 * private key (that is: priv->b). This ensures that for signature
312 * generation, the "R" is derived from the same derivation path as "h" and is
313 * not reused. */
314 {
315 struct GNUNET_HashCode hcb;
316 struct GNUNET_HashContext *hctx;
317
319 GNUNET_CRYPTO_hash_context_read (hctx, priv->b, sizeof(priv->b));
320 GNUNET_CRYPTO_hash_context_read (hctx, (unsigned char*) &hc, sizeof (hc));
322
323 /* Truncate result, effectively doing SHA512/256 */
324 for (size_t i = 0; i < 32; i++)
325 result->b[i] = ((unsigned char *) &hcb)[i];
326 }
327
328 for (size_t i = 0; i < 32; i++)
329 result->a[i] = a[i];
330
331 sodium_memzero (a, sizeof(a));
332}
333
334
335void
338 const void *seed,
339 size_t seedsize,
341{
342 struct GNUNET_HashCode hc;
343 uint8_t h[64] = { 0 };
344
345 derive_h (pub,
346 seed,
347 seedsize,
348 &hc);
349 memcpy (h,
350 &hc,
351 64);
352 crypto_core_ed25519_scalar_reduce (h,
353 h);
354 GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (result->q_y,
355 h,
356 pub->q_y));
357}
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_BlindablePrivateKey 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
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calculations.
static const struct GNUNET_CRYPTO_BlindablePrivateKey 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.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_edx25519_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_SignaturePurpose *validate, const struct GNUNET_CRYPTO_Edx25519Signature *sig, const struct GNUNET_CRYPTO_Edx25519PublicKey *pub)
Verify Edx25519 signature.
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(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_sign_(const struct GNUNET_CRYPTO_Edx25519PrivateKey *priv, const struct GNUNET_CRYPTO_SignaturePurpose *purpose, struct GNUNET_CRYPTO_Edx25519Signature *sig)
This function operates the basically same way as the signature function for EdDSA.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:40
#define GNUNET_CRYPTO_hkdf_gnunet(result, out_len, xts, xts_len, skm, skm_len,...)
A peculiar HKDF instantiation that tried to mimic Truncated NMAC.
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
#define GNUNET_CRYPTO_kdf_arg(d, s)
GNUNET_GenericReturnValue
Named constants for return values.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
#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.
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.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!...
A 512-bit hashcode.