aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/util/crypto_ecc_gnsrecord.c73
1 files changed, 58 insertions, 15 deletions
diff --git a/src/util/crypto_ecc_gnsrecord.c b/src/util/crypto_ecc_gnsrecord.c
index bab0ce44a..213f05863 100644
--- a/src/util/crypto_ecc_gnsrecord.c
+++ b/src/util/crypto_ecc_gnsrecord.c
@@ -42,20 +42,19 @@
42 * @param label label for deriviation 42 * @param label label for deriviation
43 * @param context additional context to use for HKDF of 'h'; 43 * @param context additional context to use for HKDF of 'h';
44 * typically the name of the subsystem/application 44 * typically the name of the subsystem/application
45 * @return h value 45 * @param hc where to write the result
46 */ 46 */
47static gcry_mpi_t 47void
48derive_h (const void *pub, 48derive_h (const void *pub,
49 size_t pubsize, 49 size_t pubsize,
50 const char *label, 50 const char *label,
51 const char *context) 51 const char *context,
52 struct GNUNET_HashCode *hc)
52{ 53{
53 gcry_mpi_t h;
54 struct GNUNET_HashCode hc;
55 static const char *const salt = "key-derivation"; 54 static const char *const salt = "key-derivation";
56 55
57 GNUNET_CRYPTO_kdf (&hc, 56 GNUNET_CRYPTO_kdf (hc,
58 sizeof(hc), 57 sizeof(*hc),
59 salt, 58 salt,
60 strlen (salt), 59 strlen (salt),
61 pub, 60 pub,
@@ -66,8 +65,6 @@ derive_h (const void *pub,
66 strlen (context), 65 strlen (context),
67 NULL, 66 NULL,
68 0); 67 0);
69 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
70 return h;
71} 68}
72 69
73 70
@@ -193,6 +190,7 @@ GNUNET_CRYPTO_ecdsa_private_key_derive (
193{ 190{
194 struct GNUNET_CRYPTO_EcdsaPublicKey pub; 191 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
195 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret; 192 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
193 struct GNUNET_HashCode hc;
196 uint8_t dc[32]; 194 uint8_t dc[32];
197 gcry_mpi_t h; 195 gcry_mpi_t h;
198 gcry_mpi_t x; 196 gcry_mpi_t x;
@@ -205,7 +203,9 @@ GNUNET_CRYPTO_ecdsa_private_key_derive (
205 n = gcry_mpi_ec_get_mpi ("n", ctx, 1); 203 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
206 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub); 204 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
207 205
208 h = derive_h (&pub, sizeof (pub), label, context); 206 derive_h (&pub, sizeof (pub), label, context, &hc);
207 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
208
209 /* Convert to big endian for libgcrypt */ 209 /* Convert to big endian for libgcrypt */
210 for (size_t i = 0; i < 32; i++) 210 for (size_t i = 0; i < 32; i++)
211 dc[i] = priv->d[31 - i]; 211 dc[i] = priv->d[31 - i];
@@ -234,6 +234,7 @@ GNUNET_CRYPTO_ecdsa_public_key_derive (
234 const char *context, 234 const char *context,
235 struct GNUNET_CRYPTO_EcdsaPublicKey *result) 235 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
236{ 236{
237 struct GNUNET_HashCode hc;
237 gcry_ctx_t ctx; 238 gcry_ctx_t ctx;
238 gcry_mpi_t q_y; 239 gcry_mpi_t q_y;
239 gcry_mpi_t h; 240 gcry_mpi_t h;
@@ -255,7 +256,8 @@ GNUNET_CRYPTO_ecdsa_public_key_derive (
255 GNUNET_assert (q); 256 GNUNET_assert (q);
256 257
257 /* calculate h_mod_n = h % n */ 258 /* calculate h_mod_n = h % n */
258 h = derive_h (pub, sizeof (pub), label, context); 259 derive_h (pub, sizeof (pub), label, context, &hc);
260 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
259 n = gcry_mpi_ec_get_mpi ("n", ctx, 1); 261 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
260 h_mod_n = gcry_mpi_new (256); 262 h_mod_n = gcry_mpi_new (256);
261 gcry_mpi_mod (h_mod_n, h, n); 263 gcry_mpi_mod (h_mod_n, h, n);
@@ -286,6 +288,7 @@ GNUNET_CRYPTO_eddsa_private_key_derive (
286 struct GNUNET_CRYPTO_EddsaPrivateScalar *result) 288 struct GNUNET_CRYPTO_EddsaPrivateScalar *result)
287{ 289{
288 struct GNUNET_CRYPTO_EddsaPublicKey pub; 290 struct GNUNET_CRYPTO_EddsaPublicKey pub;
291 struct GNUNET_HashCode hc;
289 uint8_t dc[32]; 292 uint8_t dc[32];
290 unsigned char sk[64]; 293 unsigned char sk[64];
291 gcry_mpi_t h; 294 gcry_mpi_t h;
@@ -297,20 +300,49 @@ GNUNET_CRYPTO_eddsa_private_key_derive (
297 gcry_mpi_t a2; 300 gcry_mpi_t a2;
298 gcry_ctx_t ctx; 301 gcry_ctx_t ctx;
299 302
303 /**
304 * Libsodium does not offer an API with arbitrary arithmetic.
305 * Hence we have to use libgcrypt here.
306 */
300 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519")); 307 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
301 308
309 /**
310 * Get our modulo
311 */
302 n = gcry_mpi_ec_get_mpi ("n", ctx, 1); 312 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
303 GNUNET_CRYPTO_eddsa_key_get_public (priv, &pub); 313 GNUNET_CRYPTO_eddsa_key_get_public (priv, &pub);
314
315 /**
316 * This is the standard private key expansion in Ed25519.
317 * The first 32 octets are used as a little-endian private
318 * scalar.
319 * We derive this scalar using our "h".
320 */
304 crypto_hash_sha512 (sk, priv->d, 32); 321 crypto_hash_sha512 (sk, priv->d, 32);
305 sk[0] &= 248; 322 sk[0] &= 248;
306 sk[31] &= 127; 323 sk[31] &= 127;
307 sk[31] |= 64; 324 sk[31] |= 64;
308 h = derive_h (&pub, sizeof (pub), label, context); 325
326 /**
327 * Get h mod n
328 */
329 derive_h (&pub, sizeof (pub), label, context, &hc);
330 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
331
309 h_mod_n = gcry_mpi_new (256); 332 h_mod_n = gcry_mpi_new (256);
310 gcry_mpi_mod (h_mod_n, h, n); 333 gcry_mpi_mod (h_mod_n, h, n);
311 /* Convert to big endian for libgcrypt */ 334 /* Convert scalar to big endian for libgcrypt */
312 for (size_t i = 0; i < 32; i++) 335 for (size_t i = 0; i < 32; i++)
313 dc[i] = sk[31 - i]; 336 dc[i] = sk[31 - i];
337
338 /**
339 * dc now contains the private scalar "a".
340 * We carefully remove the clamping and derive a'.
341 * Calculate:
342 * a1 := a / 8
343 * a2 := h * a1 mod n
344 * a' := a2 * 8 mod n
345 */
314 GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc)); // a 346 GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc)); // a
315 a1 = gcry_mpi_new (256); 347 a1 = gcry_mpi_new (256);
316 gcry_mpi_t eight = gcry_mpi_set_ui (NULL, 8); 348 gcry_mpi_t eight = gcry_mpi_set_ui (NULL, 8);
@@ -318,7 +350,6 @@ GNUNET_CRYPTO_eddsa_private_key_derive (
318 a2 = gcry_mpi_new (256); 350 a2 = gcry_mpi_new (256);
319 gcry_mpi_mulm (a2, h_mod_n, a1, n); // a2 := h * a1 mod n 351 gcry_mpi_mulm (a2, h_mod_n, a1, n); // a2 := h * a1 mod n
320 d = gcry_mpi_new (256); 352 d = gcry_mpi_new (256);
321 // gcry_mpi_mulm (d, a2, eight, n); // a' := a2 * 8 mod n
322 gcry_mpi_mul (d, a2, eight); // a' := a2 * 8 353 gcry_mpi_mul (d, a2, eight); // a' := a2 * 8
323 gcry_mpi_release (h); 354 gcry_mpi_release (h);
324 gcry_mpi_release (x); 355 gcry_mpi_release (x);
@@ -327,10 +358,19 @@ GNUNET_CRYPTO_eddsa_private_key_derive (
327 gcry_mpi_release (a2); 358 gcry_mpi_release (a2);
328 gcry_ctx_release (ctx); 359 gcry_ctx_release (ctx);
329 GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d); 360 GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
361 /**
362 * Note that we copy all of SHA512(d) into the result and
363 * then overrwrite the derived private scalar.
364 * This means that we re-use SHA512(d)[32..63]
365 * FIXME: Do we want to derive this part as well??
366 */
330 memcpy (result->s, sk, sizeof (sk)); 367 memcpy (result->s, sk, sizeof (sk));
331 /* Convert to little endian for libsodium */ 368 /* Convert to little endian for libsodium */
332 for (size_t i = 0; i < 32; i++) 369 for (size_t i = 0; i < 32; i++)
333 result->s[i] = dc[31 - i]; 370 result->s[i] = dc[31 - i];
371 /**
372 * Clamp the scalar
373 */
334 result->s[0] &= 248; 374 result->s[0] &= 248;
335 result->s[31] &= 127; 375 result->s[31] &= 127;
336 result->s[31] |= 64; 376 result->s[31] |= 64;
@@ -347,6 +387,7 @@ GNUNET_CRYPTO_eddsa_public_key_derive (
347 const char *context, 387 const char *context,
348 struct GNUNET_CRYPTO_EddsaPublicKey *result) 388 struct GNUNET_CRYPTO_EddsaPublicKey *result)
349{ 389{
390 struct GNUNET_HashCode hc;
350 gcry_ctx_t ctx; 391 gcry_ctx_t ctx;
351 gcry_mpi_t q_y; 392 gcry_mpi_t q_y;
352 gcry_mpi_t h; 393 gcry_mpi_t h;
@@ -368,7 +409,9 @@ GNUNET_CRYPTO_eddsa_public_key_derive (
368 GNUNET_assert (q); 409 GNUNET_assert (q);
369 410
370 /* calculate h_mod_n = h % n */ 411 /* calculate h_mod_n = h % n */
371 h = derive_h (pub, sizeof (*pub), label, context); 412 derive_h (pub, sizeof (*pub), label, context, &hc);
413 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
414
372 n = gcry_mpi_ec_get_mpi ("n", ctx, 1); 415 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
373 h_mod_n = gcry_mpi_new (256); 416 h_mod_n = gcry_mpi_new (256);
374 gcry_mpi_mod (h_mod_n, h, n); 417 gcry_mpi_mod (h_mod_n, h, n);