aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_crypto_lib.h1
-rw-r--r--src/namestore/namestore_api_common.c242
2 files changed, 125 insertions, 118 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 96bbdc214..4d4455af4 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -727,6 +727,7 @@ GNUNET_CRYPTO_hmac_derive_key (struct GNUNET_CRYPTO_AuthKey *key,
727 const struct GNUNET_CRYPTO_AesSessionKey *rkey, 727 const struct GNUNET_CRYPTO_AesSessionKey *rkey,
728 const void *salt, size_t salt_len, ...); 728 const void *salt, size_t salt_len, ...);
729 729
730
730/** 731/**
731 * @brief Derive key 732 * @brief Derive key
732 * @param result buffer for the derived key, allocated by caller 733 * @param result buffer for the derived key, allocated by caller
diff --git a/src/namestore/namestore_api_common.c b/src/namestore/namestore_api_common.c
index bfab39384..397a649aa 100644
--- a/src/namestore/namestore_api_common.c
+++ b/src/namestore/namestore_api_common.c
@@ -314,6 +314,36 @@ GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
314 314
315 315
316/** 316/**
317 * Derive session key and iv from label and public key.
318 *
319 * @param iv initialization vector to initialize
320 * @param skey session key to initialize
321 * @param label label to use for KDF
322 * @param pub public key to use for KDF
323 */
324static void
325derive_block_aes_key (struct GNUNET_CRYPTO_AesInitializationVector *iv,
326 struct GNUNET_CRYPTO_AesSessionKey *skey,
327 const char *label,
328 const struct GNUNET_CRYPTO_EccPublicKey *pub)
329{
330 static const char ctx_key[] = "gns-aes-ctx-key";
331 static const char ctx_iv[] = "gns-aes-ctx-iv";
332
333 GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_AesSessionKey),
334 pub, sizeof (struct GNUNET_CRYPTO_EccPublicKey),
335 label, strlen (label),
336 ctx_key, strlen (ctx_key),
337 NULL, 0);
338 GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_AesInitializationVector),
339 pub, sizeof (struct GNUNET_CRYPTO_EccPublicKey),
340 label, strlen (label),
341 ctx_iv, strlen (ctx_iv),
342 NULL, 0);
343}
344
345
346/**
317 * Sign name and records 347 * Sign name and records
318 * 348 *
319 * @param key the private key 349 * @param key the private key
@@ -321,6 +351,7 @@ GNUNET_NAMESTORE_record_get_expiration_time (unsigned int rd_count,
321 * @param label the name for the records 351 * @param label the name for the records
322 * @param rd record data 352 * @param rd record data
323 * @param rd_count number of records 353 * @param rd_count number of records
354 * @return NULL on error (block too large)
324 */ 355 */
325struct GNUNET_NAMESTORE_Block * 356struct GNUNET_NAMESTORE_Block *
326GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key, 357GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
@@ -329,8 +360,51 @@ GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
329 const struct GNUNET_NAMESTORE_RecordData *rd, 360 const struct GNUNET_NAMESTORE_RecordData *rd,
330 unsigned int rd_count) 361 unsigned int rd_count)
331{ 362{
332 GNUNET_break (0); 363 size_t payload_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
333 return NULL; 364 char payload[sizeof (uint32_t) + payload_len];
365 struct GNUNET_NAMESTORE_Block *block;
366 struct GNUNET_CRYPTO_EccPublicKey pkey;
367 struct GNUNET_CRYPTO_EccPrivateKey *dkey;
368 struct GNUNET_CRYPTO_AesInitializationVector iv;
369 struct GNUNET_CRYPTO_AesSessionKey skey;
370 uint32_t rd_count_nbo;
371
372 if (payload_len > GNUNET_NAMESTORE_MAX_VALUE_SIZE)
373 return NULL;
374 rd_count_nbo = htonl (rd_count);
375 memcpy (payload, &rd_count_nbo, sizeof (uint32_t));
376 GNUNET_assert (payload_len ==
377 GNUNET_NAMESTORE_records_serialize (rd_count, rd,
378 payload_len, &payload[sizeof (uint32_t)]));
379 block = GNUNET_malloc (sizeof (struct GNUNET_NAMESTORE_Block) +
380 sizeof (uint32_t) + payload_len);
381 block->purpose.size = htonl (sizeof (uint32_t) + payload_len +
382 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) +
383 sizeof (struct GNUNET_TIME_AbsoluteNBO));
384 block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
385 block->expiration_time = GNUNET_TIME_absolute_hton (expire);
386 dkey = GNUNET_CRYPTO_ecc_key_derive (key,
387 label,
388 "gns");
389 GNUNET_CRYPTO_ecc_key_get_public (dkey,
390 &block->derived_key);
391 GNUNET_CRYPTO_ecc_key_get_public (key,
392 &pkey);
393 derive_block_aes_key (&iv, &skey, label, &pkey);
394 GNUNET_break (payload_len + sizeof (uint32_t) ==
395 GNUNET_CRYPTO_aes_encrypt (payload, payload_len + sizeof (uint32_t),
396 &skey, &iv,
397 &block[1]));
398 if (GNUNET_OK !=
399 GNUNET_CRYPTO_ecc_sign (dkey,
400 &block->purpose,
401 &block->signature))
402 {
403 GNUNET_break (0);
404 GNUNET_free (block);
405 return NULL;
406 }
407 return block;
334} 408}
335 409
336 410
@@ -343,9 +417,11 @@ GNUNET_NAMESTORE_block_create (const struct GNUNET_CRYPTO_EccPrivateKey *key,
343 */ 417 */
344int 418int
345GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block) 419GNUNET_NAMESTORE_block_verify (const struct GNUNET_NAMESTORE_Block *block)
346{ 420{
347 GNUNET_break (0); 421 return GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
348 return GNUNET_SYSERR; 422 &block->purpose,
423 &block->signature,
424 &block->derived_key);
349} 425}
350 426
351 427
@@ -367,125 +443,55 @@ GNUNET_NAMESTORE_block_decrypt (const struct GNUNET_NAMESTORE_Block *block,
367 GNUNET_NAMESTORE_RecordCallback proc, 443 GNUNET_NAMESTORE_RecordCallback proc,
368 void *proc_cls) 444 void *proc_cls)
369{ 445{
370 GNUNET_break (0); 446 size_t payload_len = ntohl (block->purpose.size) -
371 return GNUNET_SYSERR; 447 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
372} 448 sizeof (struct GNUNET_TIME_AbsoluteNBO);
373 449 struct GNUNET_CRYPTO_AesInitializationVector iv;
374 450 struct GNUNET_CRYPTO_AesSessionKey skey;
375#if OLD 451
376/** 452 if (ntohl (block->purpose.size) <
377 * Sign name and records 453 sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) -
378 * 454 sizeof (struct GNUNET_TIME_AbsoluteNBO))
379 * @param key the private key
380 * @param expire block expiration
381 * @param name the name
382 * @param rd record data
383 * @param rd_count number of records
384 * @param signature where to store the signature
385 */
386void
387GNUNET_NAMESTORE_create_signature (const struct GNUNET_CRYPTO_EccPrivateKey *key,
388 struct GNUNET_TIME_Absolute expire,
389 const char *name,
390 const struct GNUNET_NAMESTORE_RecordData *rd,
391 unsigned int rd_count,
392 struct GNUNET_CRYPTO_EccSignature *signature)
393
394{
395 struct GNUNET_CRYPTO_EccPrivateKey *dkey;
396 struct GNUNET_CRYPTO_EccSignaturePurpose *sig_purpose;
397 struct GNUNET_TIME_AbsoluteNBO expire_nbo;
398 size_t rd_ser_len;
399 size_t name_len;
400 struct GNUNET_TIME_AbsoluteNBO *expire_tmp;
401 char * name_tmp;
402 char * rd_tmp;
403 int res;
404 uint32_t sig_len;
405
406 dkey = GNUNET_CRYPTO_ecc_key_derive (key, name, "gns");
407 name_len = strlen (name) + 1;
408 expire_nbo = GNUNET_TIME_absolute_hton (expire);
409 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd);
410 {
411 char rd_ser[rd_ser_len];
412
413 GNUNET_assert (rd_ser_len ==
414 GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser));
415 sig_len = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len;
416 sig_purpose = GNUNET_malloc (sig_len);
417 sig_purpose->size = htonl (sig_len);
418 sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
419 expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1];
420 memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO));
421 name_tmp = (char *) &expire_tmp[1];
422 memcpy (name_tmp, name, name_len);
423 rd_tmp = &name_tmp[name_len];
424 memcpy (rd_tmp, rd_ser, rd_ser_len);
425 GNUNET_assert (GNUNET_OK ==
426 GNUNET_CRYPTO_ecc_sign (dkey, sig_purpose, signature));
427 GNUNET_free (sig_purpose);
428 }
429 GNUNET_CRYPTO_ecc_key_free (dkey);
430}
431
432
433/**
434 * Check if a signature is valid. This API is used by the GNS Block
435 * to validate signatures received from the network.
436 *
437 * @param derived_key derived key of the zone and the label
438 * @param freshness time set for block expiration
439 * @param rd_count number of entries in 'rd' array
440 * @param rd array of records with data to store
441 * @param signature signature for all the records in the zone under the given name
442 * @return GNUNET_OK if the signature is valid
443 */
444int
445GNUNET_NAMESTORE_verify_signature (const struct GNUNET_CRYPTO_EccPublicKey *derived_key,
446 const struct GNUNET_TIME_Absolute freshness,
447 unsigned int rd_count,
448 const struct GNUNET_NAMESTORE_RecordData *rd,
449 const struct GNUNET_CRYPTO_EccSignature *signature)
450{
451 size_t rd_ser_len;
452 size_t name_len;
453 char *name_tmp;
454 char *rd_ser;
455 struct GNUNET_CRYPTO_EccSignaturePurpose *sig_purpose;
456 struct GNUNET_TIME_AbsoluteNBO *expire_tmp;
457 struct GNUNET_TIME_AbsoluteNBO expire_nbo = GNUNET_TIME_absolute_hton (freshness);
458 uint32_t sig_len;
459
460 GNUNET_assert (NULL != public_key);
461 GNUNET_assert (NULL != name);
462 GNUNET_assert (NULL != rd);
463 GNUNET_assert (NULL != signature);
464 name_len = strlen (name) + 1;
465 if (name_len > MAX_NAME_LEN)
466 { 455 {
467 GNUNET_break (0); 456 GNUNET_break_op (0);
468 return GNUNET_SYSERR; 457 return GNUNET_SYSERR;
469 } 458 }
470 rd_ser_len = GNUNET_NAMESTORE_records_get_size (rd_count, rd); 459 derive_block_aes_key (&iv, &skey, label, zone_key);
471 sig_len = sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + rd_ser_len + name_len;
472 { 460 {
473 char sig_buf[sig_len] GNUNET_ALIGN; 461 char payload[payload_len];
474 462 uint32_t rd_count;
475 sig_purpose = (struct GNUNET_CRYPTO_EccSignaturePurpose *) sig_buf; 463
476 sig_purpose->size = htonl (sig_len); 464 GNUNET_break (payload_len ==
477 sig_purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); 465 GNUNET_CRYPTO_aes_decrypt (&block[1], payload_len,
478 expire_tmp = (struct GNUNET_TIME_AbsoluteNBO *) &sig_purpose[1]; 466 &skey, &iv,
479 memcpy (expire_tmp, &expire_nbo, sizeof (struct GNUNET_TIME_AbsoluteNBO)); 467 payload));
480 name_tmp = (char *) &expire_tmp[1]; 468 memcpy (&rd_count,
481 memcpy (name_tmp, name, name_len); 469 payload,
482 rd_ser = &name_tmp[name_len]; 470 sizeof (uint32_t));
483 GNUNET_assert (rd_ser_len == 471 rd_count = ntohl (rd_count);
484 GNUNET_NAMESTORE_records_serialize (rd_count, rd, rd_ser_len, rd_ser)); 472 if (rd_count > 2048)
485 return GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, sig_purpose, signature, public_key); 473 {
474 /* limit to sane value */
475 GNUNET_break_op (0);
476 return GNUNET_SYSERR;
477 }
478 {
479 struct GNUNET_NAMESTORE_RecordData rd[rd_count];
480
481 if (GNUNET_OK !=
482 GNUNET_NAMESTORE_records_deserialize (payload_len - sizeof (uint32_t),
483 &payload[sizeof (uint32_t)],
484 rd_count,
485 rd))
486 {
487 GNUNET_break_op (0);
488 return GNUNET_SYSERR;
489 }
490 proc (proc_cls, rd_count, rd);
491 }
486 } 492 }
493 return GNUNET_OK;
487} 494}
488#endif
489 495
490 496
491/** 497/**