GNUnet  0.11.x
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 
28 #include "platform.h"
29 #include <gcrypt.h>
30 #include <sodium.h>
31 #include "gnunet_crypto_lib.h"
32 #include "gnunet_strings_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 
86 void
88  const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv,
89  const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
90  struct GNUNET_CRYPTO_EddsaSignature *sig)
91 {
92 
93  crypto_hash_sha512_state hs;
94  unsigned char sk[64];
95  unsigned char r[64];
96  unsigned char hram[64];
97  unsigned char R[32];
98  unsigned char zk[32];
99  unsigned char tmp[32];
100 
101  crypto_hash_sha512_init (&hs);
102 
111  memcpy (sk, priv->s, 64);
112 
117  crypto_scalarmult_ed25519_base_noclamp (zk,
118  sk);
119 
128  crypto_hash_sha512_update (&hs, sk + 32, 32);
129  crypto_hash_sha512_update (&hs, (uint8_t*) purpose, ntohl (purpose->size));
130  crypto_hash_sha512_final (&hs, r);
131 
135  memcpy (sig->s, zk, 32);
136 
140  unsigned char r_mod[64];
141  crypto_core_ed25519_scalar_reduce (r_mod, r);
142 
146  crypto_scalarmult_ed25519_base_noclamp (R, r_mod);
147  memcpy (sig->r, R, sizeof (R));
148 
153  crypto_hash_sha512_init (&hs);
154  crypto_hash_sha512_update (&hs, (uint8_t*) sig, 64);
155  crypto_hash_sha512_update (&hs, (uint8_t*) purpose,
156  ntohl (purpose->size));
157  crypto_hash_sha512_final (&hs, hram);
158 
162  unsigned char hram_mod[64];
163  crypto_core_ed25519_scalar_reduce (hram_mod, hram);
164 
169  crypto_core_ed25519_scalar_mul (tmp, hram_mod, sk);
170  crypto_core_ed25519_scalar_add (sig->s, tmp, r_mod);
171 
172  sodium_memzero (sk, sizeof (sk));
173  sodium_memzero (r, sizeof (r));
174  sodium_memzero (r_mod, sizeof (r_mod));
175 }
176 
177 
180  const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
181  const char *label,
182  const char *context)
183 {
186  struct GNUNET_HashCode hc;
187  uint8_t dc[32];
188  gcry_mpi_t h;
189  gcry_mpi_t x;
190  gcry_mpi_t d;
191  gcry_mpi_t n;
192  gcry_ctx_t ctx;
193 
194  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
195 
196  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
198 
199  derive_h (&pub, sizeof (pub), label, context, &hc);
200  GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
201 
202  /* Convert to big endian for libgcrypt */
203  for (size_t i = 0; i < 32; i++)
204  dc[i] = priv->d[31 - i];
205  GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc));
206  d = gcry_mpi_new (256);
207  gcry_mpi_mulm (d, h, x, n);
208  gcry_mpi_release (h);
209  gcry_mpi_release (x);
210  gcry_mpi_release (n);
211  gcry_ctx_release (ctx);
213  GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
214  /* Convert to big endian for libgcrypt */
215  for (size_t i = 0; i < 32; i++)
216  ret->d[i] = dc[31 - i];
217  sodium_memzero (dc, sizeof(dc));
218  gcry_mpi_release (d);
219  return ret;
220 }
221 
222 
223 void
225  const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
226  const char *label,
227  const char *context,
229 {
230  struct GNUNET_HashCode hc;
231  gcry_ctx_t ctx;
232  gcry_mpi_t q_y;
233  gcry_mpi_t h;
234  gcry_mpi_t n;
235  gcry_mpi_t h_mod_n;
236  gcry_mpi_point_t q;
237  gcry_mpi_point_t v;
238 
239  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
240 
241  /* obtain point 'q' from original public key. The provided 'q' is
242  compressed thus we first store it in the context and then get it
243  back as a (decompresssed) point. */
244  q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
245  GNUNET_assert (NULL != q_y);
246  GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
247  gcry_mpi_release (q_y);
248  q = gcry_mpi_ec_get_point ("q", ctx, 0);
249  GNUNET_assert (q);
250 
251  /* calculate h_mod_n = h % n */
252  derive_h (pub, sizeof (*pub), label, context, &hc);
253  GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
254  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
255  h_mod_n = gcry_mpi_new (256);
256  gcry_mpi_mod (h_mod_n, h, n);
257  /* calculate v = h_mod_n * q */
258  v = gcry_mpi_point_new (0);
259  gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
260  gcry_mpi_release (h_mod_n);
261  gcry_mpi_release (h);
262  gcry_mpi_release (n);
263  gcry_mpi_point_release (q);
264 
265  /* convert point 'v' to public key that we return */
266  GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
267  gcry_mpi_point_release (v);
268  q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
269  GNUNET_assert (q_y);
270  GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
271  gcry_mpi_release (q_y);
272  gcry_ctx_release (ctx);
273 }
274 
275 
276 void
278  const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
279  const char *label,
280  const char *context,
282 {
284  struct GNUNET_HashCode hc;
285  uint8_t dc[32];
286  unsigned char sk[64];
287  gcry_mpi_t h;
288  gcry_mpi_t h_mod_n;
289  gcry_mpi_t x;
290  gcry_mpi_t d;
291  gcry_mpi_t n;
292  gcry_mpi_t a1;
293  gcry_mpi_t a2;
294  gcry_ctx_t ctx;
295 
300  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
301 
305  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
307 
314  crypto_hash_sha512 (sk, priv->d, 32);
315  sk[0] &= 248;
316  sk[31] &= 127;
317  sk[31] |= 64;
318 
322  derive_h (&pub, sizeof (pub), label, context, &hc);
323  GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
324  h_mod_n = gcry_mpi_new (256);
325  gcry_mpi_mod (h_mod_n, h, n);
326  /* Convert scalar to big endian for libgcrypt */
327  for (size_t i = 0; i < 32; i++)
328  dc[i] = sk[31 - i];
329 
338  GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc)); // a
339  a1 = gcry_mpi_new (256);
340  gcry_mpi_t eight = gcry_mpi_set_ui (NULL, 8);
341  gcry_mpi_div (a1, NULL, x, eight, 0); // a1 := a / 8
342  a2 = gcry_mpi_new (256);
343  gcry_mpi_mulm (a2, h_mod_n, a1, n); // a2 := h * a1 mod n
344  d = gcry_mpi_new (256);
345  gcry_mpi_mul (d, a2, eight); // a' := a2 * 8
346  gcry_mpi_release (h);
347  gcry_mpi_release (x);
348  gcry_mpi_release (n);
349  gcry_mpi_release (a1);
350  gcry_mpi_release (a2);
351  gcry_ctx_release (ctx);
352  GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
359  crypto_hash_sha256_state hs;
360  crypto_hash_sha256_init (&hs);
361  crypto_hash_sha256_update (&hs, sk + 32, 32);
362  crypto_hash_sha256_update (&hs, (unsigned char*) &hc, sizeof (hc));
363  crypto_hash_sha256_final (&hs, result->s + 32);
364  //memcpy (result->s, sk, sizeof (sk));
365  /* Convert to little endian for libsodium */
366  for (size_t i = 0; i < 32; i++)
367  result->s[i] = dc[31 - i];
368 
369  sodium_memzero (dc, sizeof(dc));
370  gcry_mpi_release (d);
371 }
372 
373 
374 void
376  const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
377  const char *label,
378  const char *context,
380 {
381  struct GNUNET_HashCode hc;
382  gcry_ctx_t ctx;
383  gcry_mpi_t q_y;
384  gcry_mpi_t h;
385  gcry_mpi_t n;
386  gcry_mpi_t h_mod_n;
387  gcry_mpi_point_t q;
388  gcry_mpi_point_t v;
389 
390  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
391 
392  /* obtain point 'q' from original public key. The provided 'q' is
393  compressed thus we first store it in the context and then get it
394  back as a (decompresssed) point. */
395  q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
396  GNUNET_assert (NULL != q_y);
397  GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
398  gcry_mpi_release (q_y);
399  q = gcry_mpi_ec_get_point ("q", ctx, 0);
400  GNUNET_assert (q);
401 
402  /* calculate h_mod_n = h % n */
403  derive_h (pub, sizeof (*pub), label, context, &hc);
404  GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
405 
406  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
407  h_mod_n = gcry_mpi_new (256);
408  gcry_mpi_mod (h_mod_n, h, n);
409 
410  /* calculate v = h_mod_n * q */
411  v = gcry_mpi_point_new (0);
412  gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
413  gcry_mpi_release (h_mod_n);
414  gcry_mpi_release (h);
415  gcry_mpi_release (n);
416  gcry_mpi_point_release (q);
417 
418  /* convert point 'v' to public key that we return */
419  GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
420  gcry_mpi_point_release (v);
421  q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
422  GNUNET_assert (q_y);
423  GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
424  gcry_mpi_release (q_y);
425  gcry_ctx_release (ctx);
426 
427 }
428 
429 
430 void
432  const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv,
434 {
435  unsigned char sk[32];
436 
437  memcpy (sk, priv->s, 32);
438 
443  crypto_scalarmult_ed25519_base_noclamp (pkey->q_y,
444  sk);
445 }
#define CURVE
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.
void GNUNET_CRYPTO_eddsa_sign_with_scalar(const struct GNUNET_CRYPTO_EddsaPrivateScalar *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
This is a signature function for EdDSA which takes the secret scalar sk instead of the private seed w...
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 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:46
static struct GNUNET_CRYPTO_PowSalt salt
Salt for PoW calcualations.
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
cryptographic primitives for GNUnet
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:131
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:78
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:197
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:186
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:90
#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.
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...
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.