GNUnet 0.22.2
crypto_ecc_gnsrecord.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2015 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
29#include "platform.h"
30#include <gcrypt.h>
31#include <sodium.h>
32#include "gnunet_util_lib.h"
33
34#define CURVE "Ed25519"
35
47static void
48derive_h (const void *pub,
49 size_t pubsize,
50 const char *label,
51 const char *context,
52 struct GNUNET_HashCode *hc)
53{
60 static const char *const salt = "key-derivation";
61
63 sizeof(*hc),
64 salt,
65 strlen (salt),
66 pub,
67 pubsize,
68 label,
69 strlen (label),
70 context,
71 strlen (context),
72 NULL,
73 0);
74}
75
76
80 const char *label,
81 const char *context,
82 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
84{
86 crypto_hash_sha512_state hs;
87 unsigned char sk[64];
88 unsigned char r[64];
89 unsigned char hram[64];
90 unsigned char R[32];
91 unsigned char zk[32];
92 unsigned char tmp[32];
93 unsigned char r_mod[64];
94 unsigned char hram_mod[64];
95
100 label,
101 context,
102 &priv);
103
104 crypto_hash_sha512_init (&hs);
105
114 memcpy (sk, priv.s, 64);
115
120 crypto_scalarmult_ed25519_base_noclamp (zk,
121 sk);
122
131 crypto_hash_sha512_update (&hs, sk + 32, 32);
132 crypto_hash_sha512_update (&hs, (uint8_t*) purpose, ntohl (purpose->size));
133 crypto_hash_sha512_final (&hs, r);
134
138 memcpy (sig->s, zk, 32);
139
143 crypto_core_ed25519_scalar_reduce (r_mod, r);
144
148 crypto_scalarmult_ed25519_base_noclamp (R, r_mod);
149 memcpy (sig->r, R, sizeof (R));
150
155 crypto_hash_sha512_init (&hs);
156 crypto_hash_sha512_update (&hs, (uint8_t*) sig, 64);
157 crypto_hash_sha512_update (&hs, (uint8_t*) purpose,
158 ntohl (purpose->size));
159 crypto_hash_sha512_final (&hs, hram);
160
164 crypto_core_ed25519_scalar_reduce (hram_mod, hram);
165
170 crypto_core_ed25519_scalar_mul (tmp, hram_mod, sk);
171 crypto_core_ed25519_scalar_add (sig->s, tmp, r_mod);
172
173 sodium_memzero (sk, sizeof (sk));
174 sodium_memzero (r, sizeof (r));
175 sodium_memzero (r_mod, sizeof (r_mod));
176 return GNUNET_OK;
177}
178
179
182 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
183 const char *label,
184 const char *context,
185 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
187{
191 label,
192 context);
194 purpose,
195 sig);
197 return res;
198}
199
200
203 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
204 const char *label,
205 const char *context)
206{
209 struct GNUNET_HashCode hc;
210 uint8_t dc[32];
211 gcry_mpi_t h;
212 gcry_mpi_t x;
213 gcry_mpi_t d;
214 gcry_mpi_t n;
215 gcry_ctx_t ctx;
216
217 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
218
219 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
221
222 derive_h (&pub, sizeof (pub), label, context, &hc);
223 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
224
225 /* Convert to big endian for libgcrypt */
226 for (size_t i = 0; i < 32; i++)
227 dc[i] = priv->d[31 - i];
229 d = gcry_mpi_new (256);
230 gcry_mpi_mulm (d, h, x, n);
231 gcry_mpi_release (h);
232 gcry_mpi_release (x);
233 gcry_mpi_release (n);
234 gcry_ctx_release (ctx);
237 /* Convert to big endian for libgcrypt */
238 for (size_t i = 0; i < 32; i++)
239 ret->d[i] = dc[31 - i];
240 sodium_memzero (dc, sizeof(dc));
241 gcry_mpi_release (d);
242 return ret;
243}
244
245
246void
248 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
249 const char *label,
250 const char *context,
252{
253 struct GNUNET_HashCode hc;
254 gcry_ctx_t ctx;
255 gcry_mpi_t q_y;
256 gcry_mpi_t h;
257 gcry_mpi_t n;
258 gcry_mpi_t h_mod_n;
259 gcry_mpi_point_t q;
260 gcry_mpi_point_t v;
261
262 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
263
264 /* obtain point 'q' from original public key. The provided 'q' is
265 compressed thus we first store it in the context and then get it
266 back as a (decompresssed) point. */
267 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
268 GNUNET_assert (NULL != q_y);
269 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
270 gcry_mpi_release (q_y);
271 q = gcry_mpi_ec_get_point ("q", ctx, 0);
273
274 /* calculate h_mod_n = h % n */
275 derive_h (pub, sizeof (*pub), label, context, &hc);
276 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
277 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
278 h_mod_n = gcry_mpi_new (256);
279 gcry_mpi_mod (h_mod_n, h, n);
280 /* calculate v = h_mod_n * q */
281 v = gcry_mpi_point_new (0);
282 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
283 gcry_mpi_release (h_mod_n);
284 gcry_mpi_release (h);
285 gcry_mpi_release (n);
286 gcry_mpi_point_release (q);
287
288 /* convert point 'v' to public key that we return */
289 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
290 gcry_mpi_point_release (v);
291 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
292 GNUNET_assert (q_y);
293 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
294 gcry_mpi_release (q_y);
295 gcry_ctx_release (ctx);
296}
297
298
299void
301 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
302 const char *label,
303 const char *context,
305{
307 struct GNUNET_HashCode hc;
308 uint8_t dc[32];
309 unsigned char sk[64];
310 gcry_mpi_t h;
311 gcry_mpi_t h_mod_L;
312 gcry_mpi_t a;
313 gcry_mpi_t d;
314 gcry_mpi_t L;
315 gcry_ctx_t ctx;
316
321 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
322
326 L = gcry_mpi_ec_get_mpi ("n", ctx, 1);
328
335 crypto_hash_sha512 (sk, priv->d, 32);
336 sk[0] &= 248;
337 sk[31] &= 127;
338 sk[31] |= 64;
339
343 derive_h (&pub, sizeof (pub), label, context, &hc);
344 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
345 h_mod_L = gcry_mpi_new (256);
346 gcry_mpi_mod (h_mod_L, h, L);
347 /* Convert scalar to big endian for libgcrypt */
348 for (size_t i = 0; i < 32; i++)
349 dc[i] = sk[31 - i];
350
356 GNUNET_CRYPTO_mpi_scan_unsigned (&a, dc, sizeof(dc)); // a
357 d = gcry_mpi_new (256);
358 gcry_mpi_mulm (d, h_mod_L, a, L); // d := h * a mod L
359 gcry_mpi_release (h);
360 gcry_mpi_release (a);
361 gcry_mpi_release (L);
362 gcry_mpi_release (h_mod_L);
363 gcry_ctx_release (ctx);
365 {
372 crypto_hash_sha256_state hs;
373 crypto_hash_sha256_init (&hs);
374 crypto_hash_sha256_update (&hs, sk + 32, 32);
375 crypto_hash_sha256_update (&hs, (unsigned char*) &hc, sizeof (hc));
376 crypto_hash_sha256_final (&hs, result->s + 32);
377 }
378 /* Convert to little endian for libsodium */
379 for (size_t i = 0; i < 32; i++)
380 result->s[i] = dc[31 - i];
381
382 sodium_memzero (dc, sizeof(dc));
383 gcry_mpi_release (d);
384}
385
386
387void
389 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
390 const char *label,
391 const char *context,
393{
394 struct GNUNET_HashCode hc;
395 gcry_ctx_t ctx;
396 gcry_mpi_t q_y;
397 gcry_mpi_t h;
398 gcry_mpi_t n;
399 gcry_mpi_t h_mod_n;
400 gcry_mpi_point_t q;
401 gcry_mpi_point_t v;
402
403 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
404
405 /* obtain point 'q' from original public key. The provided 'q' is
406 compressed thus we first store it in the context and then get it
407 back as a (decompresssed) point. */
408 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
409 GNUNET_assert (NULL != q_y);
410 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
411 gcry_mpi_release (q_y);
412 q = gcry_mpi_ec_get_point ("q", ctx, 0);
414
415 /* calculate h_mod_n = h % n */
416 derive_h (pub, sizeof (*pub), label, context, &hc);
417 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
418
419 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
420 h_mod_n = gcry_mpi_new (256);
421 gcry_mpi_mod (h_mod_n, h, n);
422
423 /* calculate v = h_mod_n * q */
424 v = gcry_mpi_point_new (0);
425 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
426 gcry_mpi_release (h_mod_n);
427 gcry_mpi_release (h);
428 gcry_mpi_release (n);
429 gcry_mpi_point_release (q);
430
431 /* convert point 'v' to public key that we return */
432 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
433 gcry_mpi_point_release (v);
434 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
435 GNUNET_assert (q_y);
436 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
437 gcry_mpi_release (q_y);
438 gcry_ctx_release (ctx);
439
440}
441
442
443void
445 const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv,
447{
448 unsigned char sk[32];
449
450 memcpy (sk, priv->s, 32);
451
456 crypto_scalarmult_ed25519_base_noclamp (pkey->q_y,
457 sk);
458}
static void derive_h(const void *pub, size_t pubsize, const char *label, const char *context, struct GNUNET_HashCode *hc)
Derive the 'h' value for key derivation, where 'h = H(l,P)'.
#define CURVE
static mp_limb_t d[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:98
static int ret
Final status code.
Definition: gnunet-arm.c:93
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_FS_Handle * ctx
static struct GNUNET_FS_DownloadContext * dc
static pa_context * context
Pulseaudio context.
static char * pkey
Public key of the zone to look in, in ASCII.
static char * res
Currently read line or NULL on EOF.
static int result
Global testing status.
static struct GNUNET_REVOCATION_Query * q
Handle for revocation query.
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
void GNUNET_CRYPTO_ecdsa_public_key_derive(const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, const char *context, struct GNUNET_CRYPTO_EcdsaPublicKey *result)
Derive a public key from a given public key and a label.
struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_private_key_derive(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const char *label, const char *context)
Derive a private key from a given private key and a label.
void GNUNET_CRYPTO_eddsa_private_key_derive(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const char *label, const char *context, struct GNUNET_CRYPTO_EddsaPrivateScalar *result)
Derive a private scalar from a given private key and a label.
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:201
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdsa_sign_(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EcdsaSignature *sig)
ECDSA Sign a given block.
Definition: crypto_ecc.c:554
void GNUNET_CRYPTO_eddsa_public_key_derive(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, const char *label, const char *context, struct GNUNET_CRYPTO_EddsaPublicKey *result)
Derive a public key from a given public key and a label.
void GNUNET_CRYPTO_ecdsa_key_get_public(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:190
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_mpi_scan_unsigned(gcry_mpi_t *result, const void *data, size_t size)
Convert data buffer into MPI value.
Definition: crypto_mpi.c:132
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_derived(const struct GNUNET_CRYPTO_EddsaPrivateKey *pkey, const char *label, const char *context, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
This is a signature function for EdDSA which takes a private key and derives it using the label and c...
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdsa_sign_derived(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const char *label, const char *context, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EcdsaSignature *sig)
This is a signature function for ECDSA which takes a private key, derives/blinds it and signs the mes...
void GNUNET_CRYPTO_mpi_print_unsigned(void *buf, size_t size, gcry_mpi_t val)
Output the given MPI value to the given buffer in network byte order.
Definition: crypto_mpi.c:79
void GNUNET_CRYPTO_eddsa_key_get_public_from_scalar(const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pkey)
Extract the public key of the given private scalar.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
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 (!...
Private ECC key encoded for transmission.
unsigned char d[256/8]
d is a value mod n, where n has at most 256 bits.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
an ECC signature using ECDSA
Private ECC key encoded for transmission.
unsigned char d[256/8]
d is a value mod n, where n has at most 256 bits.
Private ECC scalar encoded for transmission.
unsigned char s[512/8]
s is the expandedprivate 512-bit scalar of a private key.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
unsigned char q_y[256/8]
Point Q consists of a y-value mod p (256 bits); the x-value is always positive.
an ECC signature using EdDSA.
unsigned char s[256/8]
S value.
unsigned char r[256/8]
R value.
A 512-bit hashcode.