GNUnet  0.20.0
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 
47 void
48 derive_h (const void *pub,
49  size_t pubsize,
50  const char *label,
51  const char *context,
52  struct GNUNET_HashCode *hc)
53 {
54  static const char *const salt = "key-derivation";
55 
57  sizeof(*hc),
58  salt,
59  strlen (salt),
60  pub,
61  pubsize,
62  label,
63  strlen (label),
64  context,
65  strlen (context),
66  NULL,
67  0);
68 }
69 
70 
73  const struct GNUNET_CRYPTO_EddsaPrivateKey *pkey,
74  const char *label,
75  const char *context,
76  const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
77  struct GNUNET_CRYPTO_EddsaSignature *sig)
78 {
80  crypto_hash_sha512_state hs;
81  unsigned char sk[64];
82  unsigned char r[64];
83  unsigned char hram[64];
84  unsigned char R[32];
85  unsigned char zk[32];
86  unsigned char tmp[32];
87 
92  label,
93  context,
94  &priv);
95 
96  crypto_hash_sha512_init (&hs);
97 
106  memcpy (sk, priv.s, 64);
107 
112  crypto_scalarmult_ed25519_base_noclamp (zk,
113  sk);
114 
123  crypto_hash_sha512_update (&hs, sk + 32, 32);
124  crypto_hash_sha512_update (&hs, (uint8_t*) purpose, ntohl (purpose->size));
125  crypto_hash_sha512_final (&hs, r);
126 
130  memcpy (sig->s, zk, 32);
131 
135  unsigned char r_mod[64];
136  crypto_core_ed25519_scalar_reduce (r_mod, r);
137 
141  crypto_scalarmult_ed25519_base_noclamp (R, r_mod);
142  memcpy (sig->r, R, sizeof (R));
143 
148  crypto_hash_sha512_init (&hs);
149  crypto_hash_sha512_update (&hs, (uint8_t*) sig, 64);
150  crypto_hash_sha512_update (&hs, (uint8_t*) purpose,
151  ntohl (purpose->size));
152  crypto_hash_sha512_final (&hs, hram);
153 
157  unsigned char hram_mod[64];
158  crypto_core_ed25519_scalar_reduce (hram_mod, hram);
159 
164  crypto_core_ed25519_scalar_mul (tmp, hram_mod, sk);
165  crypto_core_ed25519_scalar_add (sig->s, tmp, r_mod);
166 
167  sodium_memzero (sk, sizeof (sk));
168  sodium_memzero (r, sizeof (r));
169  sodium_memzero (r_mod, sizeof (r_mod));
170  return GNUNET_OK;
171 }
172 
173 
176  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
177  const char *label,
178  const char *context,
179  const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
180  struct GNUNET_CRYPTO_EcdsaSignature *sig)
181 {
185  label,
186  context);
188  purpose,
189  sig);
190  GNUNET_free (key);
191  return res;
192 }
193 
194 
197  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
198  const char *label,
199  const char *context)
200 {
203  struct GNUNET_HashCode hc;
204  uint8_t dc[32];
205  gcry_mpi_t h;
206  gcry_mpi_t x;
207  gcry_mpi_t d;
208  gcry_mpi_t n;
209  gcry_ctx_t ctx;
210 
211  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
212 
213  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
215 
216  derive_h (&pub, sizeof (pub), label, context, &hc);
217  GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
218 
219  /* Convert to big endian for libgcrypt */
220  for (size_t i = 0; i < 32; i++)
221  dc[i] = priv->d[31 - i];
222  GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc));
223  d = gcry_mpi_new (256);
224  gcry_mpi_mulm (d, h, x, n);
225  gcry_mpi_release (h);
226  gcry_mpi_release (x);
227  gcry_mpi_release (n);
228  gcry_ctx_release (ctx);
230  GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
231  /* Convert to big endian for libgcrypt */
232  for (size_t i = 0; i < 32; i++)
233  ret->d[i] = dc[31 - i];
234  sodium_memzero (dc, sizeof(dc));
235  gcry_mpi_release (d);
236  return ret;
237 }
238 
239 
240 void
242  const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
243  const char *label,
244  const char *context,
246 {
247  struct GNUNET_HashCode hc;
248  gcry_ctx_t ctx;
249  gcry_mpi_t q_y;
250  gcry_mpi_t h;
251  gcry_mpi_t n;
252  gcry_mpi_t h_mod_n;
253  gcry_mpi_point_t q;
254  gcry_mpi_point_t v;
255 
256  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
257 
258  /* obtain point 'q' from original public key. The provided 'q' is
259  compressed thus we first store it in the context and then get it
260  back as a (decompresssed) point. */
261  q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
262  GNUNET_assert (NULL != q_y);
263  GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
264  gcry_mpi_release (q_y);
265  q = gcry_mpi_ec_get_point ("q", ctx, 0);
266  GNUNET_assert (q);
267 
268  /* calculate h_mod_n = h % n */
269  derive_h (pub, sizeof (*pub), label, context, &hc);
270  GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
271  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
272  h_mod_n = gcry_mpi_new (256);
273  gcry_mpi_mod (h_mod_n, h, n);
274  /* calculate v = h_mod_n * q */
275  v = gcry_mpi_point_new (0);
276  gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
277  gcry_mpi_release (h_mod_n);
278  gcry_mpi_release (h);
279  gcry_mpi_release (n);
280  gcry_mpi_point_release (q);
281 
282  /* convert point 'v' to public key that we return */
283  GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
284  gcry_mpi_point_release (v);
285  q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
286  GNUNET_assert (q_y);
287  GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
288  gcry_mpi_release (q_y);
289  gcry_ctx_release (ctx);
290 }
291 
292 
293 void
295  const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
296  const char *label,
297  const char *context,
299 {
301  struct GNUNET_HashCode hc;
302  uint8_t dc[32];
303  unsigned char sk[64];
304  gcry_mpi_t h;
305  gcry_mpi_t h_mod_L;
306  gcry_mpi_t a;
307  gcry_mpi_t d;
308  gcry_mpi_t L;
309  gcry_ctx_t ctx;
310 
315  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
316 
320  L = gcry_mpi_ec_get_mpi ("n", ctx, 1);
322 
329  crypto_hash_sha512 (sk, priv->d, 32);
330  sk[0] &= 248;
331  sk[31] &= 127;
332  sk[31] |= 64;
333 
337  derive_h (&pub, sizeof (pub), label, context, &hc);
338  GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
339  h_mod_L = gcry_mpi_new (256);
340  gcry_mpi_mod (h_mod_L, h, L);
341  /* Convert scalar to big endian for libgcrypt */
342  for (size_t i = 0; i < 32; i++)
343  dc[i] = sk[31 - i];
344 
350  GNUNET_CRYPTO_mpi_scan_unsigned (&a, dc, sizeof(dc)); // a
351  d = gcry_mpi_new (256);
352  gcry_mpi_mulm (d, h_mod_L, a, L); // d := h * a mod L
353  gcry_mpi_release (h);
354  gcry_mpi_release (a);
355  gcry_mpi_release (L);
356  gcry_mpi_release (h_mod_L);
357  gcry_ctx_release (ctx);
358  GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
365  crypto_hash_sha256_state hs;
366  crypto_hash_sha256_init (&hs);
367  crypto_hash_sha256_update (&hs, sk + 32, 32);
368  crypto_hash_sha256_update (&hs, (unsigned char*) &hc, sizeof (hc));
369  crypto_hash_sha256_final (&hs, result->s + 32);
370  // memcpy (result->s, sk, sizeof (sk));
371  /* Convert to little endian for libsodium */
372  for (size_t i = 0; i < 32; i++)
373  result->s[i] = dc[31 - i];
374 
375  sodium_memzero (dc, sizeof(dc));
376  gcry_mpi_release (d);
377 }
378 
379 
380 void
382  const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
383  const char *label,
384  const char *context,
386 {
387  struct GNUNET_HashCode hc;
388  gcry_ctx_t ctx;
389  gcry_mpi_t q_y;
390  gcry_mpi_t h;
391  gcry_mpi_t n;
392  gcry_mpi_t h_mod_n;
393  gcry_mpi_point_t q;
394  gcry_mpi_point_t v;
395 
396  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
397 
398  /* obtain point 'q' from original public key. The provided 'q' is
399  compressed thus we first store it in the context and then get it
400  back as a (decompresssed) point. */
401  q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
402  GNUNET_assert (NULL != q_y);
403  GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
404  gcry_mpi_release (q_y);
405  q = gcry_mpi_ec_get_point ("q", ctx, 0);
406  GNUNET_assert (q);
407 
408  /* calculate h_mod_n = h % n */
409  derive_h (pub, sizeof (*pub), label, context, &hc);
410  GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
411 
412  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
413  h_mod_n = gcry_mpi_new (256);
414  gcry_mpi_mod (h_mod_n, h, n);
415 
416  /* calculate v = h_mod_n * q */
417  v = gcry_mpi_point_new (0);
418  gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
419  gcry_mpi_release (h_mod_n);
420  gcry_mpi_release (h);
421  gcry_mpi_release (n);
422  gcry_mpi_point_release (q);
423 
424  /* convert point 'v' to public key that we return */
425  GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
426  gcry_mpi_point_release (v);
427  q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
428  GNUNET_assert (q_y);
429  GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
430  gcry_mpi_release (q_y);
431  gcry_ctx_release (ctx);
432 
433 }
434 
435 
436 void
438  const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv,
440 {
441  unsigned char sk[32];
442 
443  memcpy (sk, priv->s, 32);
444 
449  crypto_scalarmult_ed25519_base_noclamp (pkey->q_y,
450  sk);
451 }
#define CURVE
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)'.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_ARM_Handle * h
Connection with ARM.
Definition: gnunet-arm.c:99
static int res
struct GNUNET_HashCode key
The key used in the DHT.
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 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 calcualations.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
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.
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:198
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:536
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:187
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.
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
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 ...
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.