diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2021-05-01 22:05:15 +0200 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2021-05-02 10:39:55 +0200 |
commit | 572f4d6f7b19dec42d571829384ac9cd356bb092 (patch) | |
tree | cbe8bf3ae413a1aa3b71beffcbe7ce9bb83fe03f /src/gnsrecord | |
parent | ca3ebf1e59eb00ad101ba8b26e5185db4d785610 (diff) | |
download | gnunet-572f4d6f7b19dec42d571829384ac9cd356bb092.tar.gz gnunet-572f4d6f7b19dec42d571829384ac9cd356bb092.zip |
GNS: Add EDKEY support.
GNS and GNSRECORD can now handle EdDSA keys
in addition to the existing ECDSA scheme.
See also LSD0001.
Diffstat (limited to 'src/gnsrecord')
-rw-r--r-- | src/gnsrecord/gnsrecord_crypto.c | 426 | ||||
-rw-r--r-- | src/gnsrecord/gnsrecord_misc.c | 17 | ||||
-rw-r--r-- | src/gnsrecord/gnsrecord_serialization.c | 3 | ||||
-rw-r--r-- | src/gnsrecord/test_gnsrecord_crypto.c | 36 |
4 files changed, 427 insertions, 55 deletions
diff --git a/src/gnsrecord/gnsrecord_crypto.c b/src/gnsrecord/gnsrecord_crypto.c index 9c551a936..289f0e885 100644 --- a/src/gnsrecord/gnsrecord_crypto.c +++ b/src/gnsrecord/gnsrecord_crypto.c | |||
@@ -64,7 +64,6 @@ ecdsa_symmetric_decrypt ( | |||
64 | } | 64 | } |
65 | 65 | ||
66 | 66 | ||
67 | |||
68 | ssize_t | 67 | ssize_t |
69 | ecdsa_symmetric_encrypt ( | 68 | ecdsa_symmetric_encrypt ( |
70 | const void *block, | 69 | const void *block, |
@@ -92,6 +91,34 @@ ecdsa_symmetric_encrypt ( | |||
92 | } | 91 | } |
93 | 92 | ||
94 | 93 | ||
94 | enum GNUNET_GenericReturnValue | ||
95 | eddsa_symmetric_decrypt ( | ||
96 | const void *block, | ||
97 | size_t size, | ||
98 | const unsigned char *key, | ||
99 | const unsigned char *nonce, | ||
100 | void *result) | ||
101 | { | ||
102 | if (0 != crypto_secretbox_open_easy (result, block, size, nonce, key)) | ||
103 | { | ||
104 | return GNUNET_SYSERR; | ||
105 | } | ||
106 | return GNUNET_OK; | ||
107 | } | ||
108 | |||
109 | |||
110 | enum GNUNET_GenericReturnValue | ||
111 | eddsa_symmetric_encrypt ( | ||
112 | const void *block, | ||
113 | size_t size, | ||
114 | const unsigned char *key, | ||
115 | const unsigned char *nonce, | ||
116 | void *result) | ||
117 | { | ||
118 | crypto_secretbox_easy (result, block, size, nonce, key); | ||
119 | return GNUNET_OK; | ||
120 | } | ||
121 | |||
95 | 122 | ||
96 | /** | 123 | /** |
97 | * Derive session key and iv from label and public key. | 124 | * Derive session key and iv from label and public key. |
@@ -131,6 +158,42 @@ derive_block_aes_key (unsigned char *ctr, | |||
131 | 158 | ||
132 | 159 | ||
133 | /** | 160 | /** |
161 | * Derive session key and iv from label and public key. | ||
162 | * | ||
163 | * @param nonce initialization vector to initialize | ||
164 | * @param skey session key to initialize | ||
165 | * @param label label to use for KDF | ||
166 | * @param pub public key to use for KDF | ||
167 | */ | ||
168 | static void | ||
169 | derive_block_xsalsa_key (unsigned char *nonce, | ||
170 | unsigned char *key, | ||
171 | const char *label, | ||
172 | uint64_t exp, | ||
173 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub) | ||
174 | { | ||
175 | static const char ctx_key[] = "gns-aes-ctx-key"; | ||
176 | static const char ctx_iv[] = "gns-aes-ctx-iv"; | ||
177 | |||
178 | GNUNET_CRYPTO_kdf (key, crypto_secretbox_KEYBYTES, | ||
179 | ctx_key, strlen (ctx_key), | ||
180 | pub, sizeof(struct GNUNET_CRYPTO_EddsaPublicKey), | ||
181 | label, strlen (label), | ||
182 | NULL, 0); | ||
183 | memset (nonce, 0, crypto_secretbox_NONCEBYTES); | ||
184 | /** 16 byte nonce **/ | ||
185 | GNUNET_CRYPTO_kdf (nonce, (crypto_secretbox_NONCEBYTES - sizeof (exp)), | ||
186 | ctx_iv, strlen (ctx_iv), | ||
187 | pub, sizeof(struct GNUNET_CRYPTO_EddsaPublicKey), | ||
188 | label, strlen (label), | ||
189 | NULL, 0); | ||
190 | /** Expiration time 64 bit. **/ | ||
191 | memcpy (nonce + (crypto_secretbox_NONCEBYTES - sizeof (exp)), | ||
192 | &exp, sizeof (exp)); | ||
193 | } | ||
194 | |||
195 | |||
196 | /** | ||
134 | * Sign name and records | 197 | * Sign name and records |
135 | * | 198 | * |
136 | * @param key the private key | 199 | * @param key the private key |
@@ -246,6 +309,119 @@ block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, | |||
246 | 309 | ||
247 | 310 | ||
248 | /** | 311 | /** |
312 | * Sign name and records (EDDSA version) | ||
313 | * | ||
314 | * @param key the private key | ||
315 | * @param pkey associated public key | ||
316 | * @param expire block expiration | ||
317 | * @param label the name for the records | ||
318 | * @param rd record data | ||
319 | * @param rd_count number of records | ||
320 | * @return NULL on error (block too large) | ||
321 | */ | ||
322 | static struct GNUNET_GNSRECORD_Block * | ||
323 | block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key, | ||
324 | const struct GNUNET_CRYPTO_EddsaPublicKey *pkey, | ||
325 | struct GNUNET_TIME_Absolute expire, | ||
326 | const char *label, | ||
327 | const struct GNUNET_GNSRECORD_Data *rd, | ||
328 | unsigned int rd_count) | ||
329 | { | ||
330 | ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count, | ||
331 | rd); | ||
332 | struct GNUNET_GNSRECORD_Block *block; | ||
333 | struct GNUNET_GNSRECORD_EddsaBlock *edblock; | ||
334 | struct GNUNET_CRYPTO_EddsaPrivateScalar dkey; | ||
335 | unsigned char nonce[crypto_secretbox_NONCEBYTES]; | ||
336 | unsigned char skey[crypto_secretbox_KEYBYTES]; | ||
337 | struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)]; | ||
338 | uint32_t rd_count_nbo; | ||
339 | struct GNUNET_TIME_Absolute now; | ||
340 | |||
341 | if (payload_len < 0) | ||
342 | { | ||
343 | GNUNET_break (0); | ||
344 | return NULL; | ||
345 | } | ||
346 | if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE) | ||
347 | { | ||
348 | GNUNET_break (0); | ||
349 | return NULL; | ||
350 | } | ||
351 | /* convert relative to absolute times */ | ||
352 | now = GNUNET_TIME_absolute_get (); | ||
353 | for (unsigned int i = 0; i < rd_count; i++) | ||
354 | { | ||
355 | rdc[i] = rd[i]; | ||
356 | if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
357 | { | ||
358 | struct GNUNET_TIME_Relative t; | ||
359 | |||
360 | /* encrypted blocks must never have relative expiration times, convert! */ | ||
361 | rdc[i].flags &= ~GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
362 | t.rel_value_us = rdc[i].expiration_time; | ||
363 | rdc[i].expiration_time = GNUNET_TIME_absolute_add (now, t).abs_value_us; | ||
364 | } | ||
365 | } | ||
366 | /* serialize */ | ||
367 | rd_count_nbo = htonl (rd_count); | ||
368 | { | ||
369 | char payload[sizeof(uint32_t) + payload_len]; | ||
370 | |||
371 | GNUNET_memcpy (payload, | ||
372 | &rd_count_nbo, | ||
373 | sizeof(uint32_t)); | ||
374 | GNUNET_assert (payload_len == | ||
375 | GNUNET_GNSRECORD_records_serialize (rd_count, | ||
376 | rdc, | ||
377 | payload_len, | ||
378 | &payload[sizeof(uint32_t) | ||
379 | ])); | ||
380 | block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block) | ||
381 | + sizeof(uint32_t) | ||
382 | + payload_len | ||
383 | + crypto_secretbox_MACBYTES); | ||
384 | edblock = &block->eddsa_block; | ||
385 | block->type = htonl (GNUNET_GNSRECORD_TYPE_EDKEY); | ||
386 | edblock->purpose.size = htonl (sizeof(uint32_t) | ||
387 | + payload_len | ||
388 | + sizeof(struct | ||
389 | GNUNET_CRYPTO_EccSignaturePurpose) | ||
390 | + sizeof(struct GNUNET_TIME_AbsoluteNBO) | ||
391 | + crypto_secretbox_MACBYTES); | ||
392 | edblock->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); | ||
393 | edblock->expiration_time = GNUNET_TIME_absolute_hton (expire); | ||
394 | /* encrypt and sign */ | ||
395 | GNUNET_CRYPTO_eddsa_private_key_derive (key, | ||
396 | label, | ||
397 | "gns", | ||
398 | &dkey); | ||
399 | // FIXME: We may want a key_get_public_from_private_scalar function | ||
400 | struct GNUNET_CRYPTO_EddsaPublicKey test; | ||
401 | crypto_scalarmult_ed25519_base_noclamp (test.q_y, | ||
402 | dkey.s); | ||
403 | edblock->derived_key = test; | ||
404 | derive_block_xsalsa_key (nonce, | ||
405 | skey, | ||
406 | label, | ||
407 | edblock->expiration_time.abs_value_us__, | ||
408 | pkey); | ||
409 | GNUNET_break (GNUNET_OK == | ||
410 | eddsa_symmetric_encrypt (payload, | ||
411 | payload_len | ||
412 | + sizeof(uint32_t), | ||
413 | skey, | ||
414 | nonce, | ||
415 | &edblock[1])); | ||
416 | } | ||
417 | GNUNET_CRYPTO_eddsa_sign_with_scalar (&dkey, | ||
418 | &edblock->purpose, | ||
419 | &edblock->signature); | ||
420 | return block; | ||
421 | } | ||
422 | |||
423 | |||
424 | /** | ||
249 | * Sign name and records | 425 | * Sign name and records |
250 | * | 426 | * |
251 | * @param key the private key | 427 | * @param key the private key |
@@ -263,6 +439,7 @@ GNUNET_GNSRECORD_block_create (const struct GNUNET_IDENTITY_PrivateKey *key, | |||
263 | unsigned int rd_count) | 439 | unsigned int rd_count) |
264 | { | 440 | { |
265 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; | 441 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; |
442 | struct GNUNET_CRYPTO_EddsaPublicKey edkey; | ||
266 | 443 | ||
267 | switch (ntohl (key->type)) | 444 | switch (ntohl (key->type)) |
268 | { | 445 | { |
@@ -275,6 +452,15 @@ GNUNET_GNSRECORD_block_create (const struct GNUNET_IDENTITY_PrivateKey *key, | |||
275 | label, | 452 | label, |
276 | rd, | 453 | rd, |
277 | rd_count); | 454 | rd_count); |
455 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
456 | GNUNET_CRYPTO_eddsa_key_get_public (&key->eddsa_key, | ||
457 | &edkey); | ||
458 | return block_create_eddsa (&key->eddsa_key, | ||
459 | &edkey, | ||
460 | expire, | ||
461 | label, | ||
462 | rd, | ||
463 | rd_count); | ||
278 | default: | 464 | default: |
279 | GNUNET_assert (0); | 465 | GNUNET_assert (0); |
280 | } | 466 | } |
@@ -319,33 +505,45 @@ GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey, | |||
319 | unsigned int rd_count) | 505 | unsigned int rd_count) |
320 | { | 506 | { |
321 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *key; | 507 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *key; |
508 | struct GNUNET_CRYPTO_EddsaPublicKey edpubkey; | ||
322 | 509 | ||
323 | if (GNUNET_IDENTITY_TYPE_ECDSA != ntohl (pkey->type)) | 510 | if (GNUNET_IDENTITY_TYPE_ECDSA == ntohl (pkey->type)) |
324 | { | 511 | { |
325 | return NULL; // FIXME | 512 | key = &pkey->ecdsa_key; |
326 | } | ||
327 | key = &pkey->ecdsa_key; | ||
328 | #define CSIZE 64 | 513 | #define CSIZE 64 |
329 | static struct KeyCacheLine cache[CSIZE]; | 514 | static struct KeyCacheLine cache[CSIZE]; |
330 | struct KeyCacheLine *line; | 515 | struct KeyCacheLine *line; |
331 | 516 | ||
332 | line = &cache[(*(unsigned int *) key) % CSIZE]; | 517 | line = &cache[(*(unsigned int *) key) % CSIZE]; |
333 | if (0 != memcmp (&line->key, | 518 | if (0 != memcmp (&line->key, |
334 | key, | 519 | key, |
335 | sizeof(*key))) | 520 | sizeof(*key))) |
521 | { | ||
522 | /* cache miss, recompute */ | ||
523 | line->key = *key; | ||
524 | GNUNET_CRYPTO_ecdsa_key_get_public (key, | ||
525 | &line->pkey); | ||
526 | } | ||
527 | #undef CSIZE | ||
528 | return block_create_ecdsa (key, | ||
529 | &line->pkey, | ||
530 | expire, | ||
531 | label, | ||
532 | rd, | ||
533 | rd_count); | ||
534 | } | ||
535 | else if (GNUNET_IDENTITY_TYPE_EDDSA == ntohl (pkey->type)) | ||
336 | { | 536 | { |
337 | /* cache miss, recompute */ | 537 | GNUNET_CRYPTO_eddsa_key_get_public (&pkey->eddsa_key, |
338 | line->key = *key; | 538 | &edpubkey); |
339 | GNUNET_CRYPTO_ecdsa_key_get_public (key, | 539 | return block_create_eddsa (&pkey->eddsa_key, |
340 | &line->pkey); | 540 | &edpubkey, |
541 | expire, | ||
542 | label, | ||
543 | rd, | ||
544 | rd_count); | ||
341 | } | 545 | } |
342 | #undef CSIZE | 546 | return NULL; |
343 | return block_create_ecdsa (key, | ||
344 | &line->pkey, | ||
345 | expire, | ||
346 | label, | ||
347 | rd, | ||
348 | rd_count); | ||
349 | } | 547 | } |
350 | 548 | ||
351 | 549 | ||
@@ -359,21 +557,23 @@ GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey, | |||
359 | enum GNUNET_GenericReturnValue | 557 | enum GNUNET_GenericReturnValue |
360 | GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block) | 558 | GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block) |
361 | { | 559 | { |
362 | const struct GNUNET_CRYPTO_EcdsaPublicKey *key; | 560 | switch (ntohl (block->type)) |
363 | const struct GNUNET_GNSRECORD_EcdsaBlock *ecblock; | ||
364 | |||
365 | if (GNUNET_GNSRECORD_TYPE_PKEY != ntohl (block->type)) | ||
366 | { | 561 | { |
367 | GNUNET_break (0); | 562 | case GNUNET_GNSRECORD_TYPE_PKEY: |
563 | return GNUNET_CRYPTO_ecdsa_verify_ ( | ||
564 | GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, | ||
565 | &block->ecdsa_block.purpose, | ||
566 | &block->ecdsa_block.signature, | ||
567 | &block->ecdsa_block.derived_key); | ||
568 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
569 | return GNUNET_CRYPTO_eddsa_verify_ ( | ||
570 | GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, | ||
571 | &block->eddsa_block.purpose, | ||
572 | &block->eddsa_block.signature, | ||
573 | &block->eddsa_block.derived_key); | ||
574 | default: | ||
368 | return GNUNET_NO; | 575 | return GNUNET_NO; |
369 | } | 576 | } |
370 | ecblock = &block->ecdsa_block; | ||
371 | key = &ecblock->derived_key; | ||
372 | |||
373 | return GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, | ||
374 | &ecblock->purpose, | ||
375 | &ecblock->signature, | ||
376 | key); | ||
377 | } | 577 | } |
378 | 578 | ||
379 | 579 | ||
@@ -505,6 +705,134 @@ block_decrypt_ecdsa (const struct GNUNET_GNSRECORD_EcdsaBlock *block, | |||
505 | } | 705 | } |
506 | 706 | ||
507 | 707 | ||
708 | enum GNUNET_GenericReturnValue | ||
709 | block_decrypt_eddsa (const struct GNUNET_GNSRECORD_EddsaBlock *block, | ||
710 | const struct | ||
711 | GNUNET_CRYPTO_EddsaPublicKey *zone_key, | ||
712 | const char *label, | ||
713 | GNUNET_GNSRECORD_RecordCallback proc, | ||
714 | void *proc_cls) | ||
715 | { | ||
716 | size_t payload_len = ntohl (block->purpose.size) | ||
717 | - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | ||
718 | - sizeof(struct GNUNET_TIME_AbsoluteNBO); | ||
719 | unsigned char nonce[crypto_secretbox_NONCEBYTES]; | ||
720 | unsigned char key[crypto_secretbox_KEYBYTES]; | ||
721 | |||
722 | if (ntohl (block->purpose.size) < | ||
723 | sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) | ||
724 | + sizeof(struct GNUNET_TIME_AbsoluteNBO)) | ||
725 | { | ||
726 | GNUNET_break_op (0); | ||
727 | return GNUNET_SYSERR; | ||
728 | } | ||
729 | derive_block_xsalsa_key (nonce, | ||
730 | key, | ||
731 | label, | ||
732 | block->expiration_time.abs_value_us__, | ||
733 | zone_key); | ||
734 | { | ||
735 | char payload[payload_len]; | ||
736 | uint32_t rd_count; | ||
737 | |||
738 | GNUNET_break (GNUNET_OK == | ||
739 | eddsa_symmetric_decrypt (&block[1], payload_len, | ||
740 | key, nonce, | ||
741 | payload)); | ||
742 | GNUNET_memcpy (&rd_count, | ||
743 | payload, | ||
744 | sizeof(uint32_t)); | ||
745 | rd_count = ntohl (rd_count); | ||
746 | if (rd_count > 2048) | ||
747 | { | ||
748 | /* limit to sane value */ | ||
749 | GNUNET_break_op (0); | ||
750 | return GNUNET_SYSERR; | ||
751 | } | ||
752 | { | ||
753 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | ||
754 | unsigned int j; | ||
755 | struct GNUNET_TIME_Absolute now; | ||
756 | |||
757 | if (GNUNET_OK != | ||
758 | GNUNET_GNSRECORD_records_deserialize (payload_len - sizeof(uint32_t), | ||
759 | &payload[sizeof(uint32_t)], | ||
760 | rd_count, | ||
761 | rd)) | ||
762 | { | ||
763 | GNUNET_break_op (0); | ||
764 | return GNUNET_SYSERR; | ||
765 | } | ||
766 | /* hide expired records */ | ||
767 | now = GNUNET_TIME_absolute_get (); | ||
768 | j = 0; | ||
769 | for (unsigned int i = 0; i < rd_count; i++) | ||
770 | { | ||
771 | if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) | ||
772 | { | ||
773 | /* encrypted blocks must never have relative expiration times, skip! */ | ||
774 | GNUNET_break_op (0); | ||
775 | continue; | ||
776 | } | ||
777 | |||
778 | if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)) | ||
779 | { | ||
780 | int include_record = GNUNET_YES; | ||
781 | /* Shadow record, figure out if we have a not expired active record */ | ||
782 | for (unsigned int k = 0; k < rd_count; k++) | ||
783 | { | ||
784 | if (k == i) | ||
785 | continue; | ||
786 | if (rd[i].expiration_time < now.abs_value_us) | ||
787 | include_record = GNUNET_NO; /* Shadow record is expired */ | ||
788 | if ((rd[k].record_type == rd[i].record_type) && | ||
789 | (rd[k].expiration_time >= now.abs_value_us) && | ||
790 | (0 == (rd[k].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD))) | ||
791 | { | ||
792 | include_record = GNUNET_NO; /* We have a non-expired, non-shadow record of the same type */ | ||
793 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
794 | "Ignoring shadow record\n"); | ||
795 | break; | ||
796 | } | ||
797 | } | ||
798 | if (GNUNET_YES == include_record) | ||
799 | { | ||
800 | rd[i].flags ^= GNUNET_GNSRECORD_RF_SHADOW_RECORD; /* Remove Flag */ | ||
801 | if (j != i) | ||
802 | rd[j] = rd[i]; | ||
803 | j++; | ||
804 | } | ||
805 | } | ||
806 | else if (rd[i].expiration_time >= now.abs_value_us) | ||
807 | { | ||
808 | /* Include this record */ | ||
809 | if (j != i) | ||
810 | rd[j] = rd[i]; | ||
811 | j++; | ||
812 | } | ||
813 | else | ||
814 | { | ||
815 | struct GNUNET_TIME_Absolute at; | ||
816 | |||
817 | at.abs_value_us = rd[i].expiration_time; | ||
818 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
819 | "Excluding record that expired %s (%llu ago)\n", | ||
820 | GNUNET_STRINGS_absolute_time_to_string (at), | ||
821 | (unsigned long long) rd[i].expiration_time | ||
822 | - now.abs_value_us); | ||
823 | } | ||
824 | } | ||
825 | rd_count = j; | ||
826 | if (NULL != proc) | ||
827 | proc (proc_cls, | ||
828 | rd_count, | ||
829 | (0 != rd_count) ? rd : NULL); | ||
830 | } | ||
831 | } | ||
832 | return GNUNET_OK; | ||
833 | } | ||
834 | |||
835 | |||
508 | /** | 836 | /** |
509 | * Decrypt block. | 837 | * Decrypt block. |
510 | * | 838 | * |
@@ -524,17 +852,17 @@ GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block, | |||
524 | GNUNET_GNSRECORD_RecordCallback proc, | 852 | GNUNET_GNSRECORD_RecordCallback proc, |
525 | void *proc_cls) | 853 | void *proc_cls) |
526 | { | 854 | { |
527 | const struct GNUNET_CRYPTO_EcdsaPublicKey *key; | 855 | switch (ntohl (zone_key->type)) |
528 | |||
529 | if (GNUNET_IDENTITY_TYPE_ECDSA != ntohl (zone_key->type)) | ||
530 | { | 856 | { |
531 | return GNUNET_NO; | 857 | case GNUNET_IDENTITY_TYPE_ECDSA: |
858 | return block_decrypt_ecdsa (&block->ecdsa_block, | ||
859 | &zone_key->ecdsa_key, label, proc, proc_cls); | ||
860 | case GNUNET_IDENTITY_TYPE_EDDSA: | ||
861 | return block_decrypt_eddsa (&block->eddsa_block, | ||
862 | &zone_key->eddsa_key, label, proc, proc_cls); | ||
863 | default: | ||
864 | return GNUNET_SYSERR; | ||
532 | } | 865 | } |
533 | key = &zone_key->ecdsa_key; | ||
534 | |||
535 | return block_decrypt_ecdsa (&block->ecdsa_block, | ||
536 | key, label, proc, proc_cls); | ||
537 | |||
538 | } | 866 | } |
539 | 867 | ||
540 | 868 | ||
@@ -555,6 +883,7 @@ GNUNET_GNSRECORD_query_from_private_key (const struct | |||
555 | switch (ntohl (zone->type)) | 883 | switch (ntohl (zone->type)) |
556 | { | 884 | { |
557 | case GNUNET_GNSRECORD_TYPE_PKEY: | 885 | case GNUNET_GNSRECORD_TYPE_PKEY: |
886 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
558 | 887 | ||
559 | GNUNET_IDENTITY_key_get_public (zone, | 888 | GNUNET_IDENTITY_key_get_public (zone, |
560 | &pub); | 889 | &pub); |
@@ -570,6 +899,7 @@ GNUNET_GNSRECORD_query_from_private_key (const struct | |||
570 | 899 | ||
571 | /** | 900 | /** |
572 | * Calculate the DHT query for a given @a label in a given @a zone. | 901 | * Calculate the DHT query for a given @a label in a given @a zone. |
902 | * FIXME: We may want to plugin-ize this at some point. | ||
573 | * | 903 | * |
574 | * @param pub public key of the zone | 904 | * @param pub public key of the zone |
575 | * @param label label of the record | 905 | * @param label label of the record |
@@ -595,6 +925,16 @@ GNUNET_GNSRECORD_query_from_public_key (const struct | |||
595 | sizeof (pd.ecdsa_key), | 925 | sizeof (pd.ecdsa_key), |
596 | query); | 926 | query); |
597 | break; | 927 | break; |
928 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
929 | pd.type = pub->type; | ||
930 | GNUNET_CRYPTO_eddsa_public_key_derive (&pub->eddsa_key, | ||
931 | label, | ||
932 | "gns", | ||
933 | &pd.eddsa_key); | ||
934 | GNUNET_CRYPTO_hash (&pd.eddsa_key, | ||
935 | sizeof (pd.eddsa_key), | ||
936 | query); | ||
937 | break; | ||
598 | default: | 938 | default: |
599 | GNUNET_assert (0); | 939 | GNUNET_assert (0); |
600 | } | 940 | } |
diff --git a/src/gnsrecord/gnsrecord_misc.c b/src/gnsrecord/gnsrecord_misc.c index b907eed27..2fe315bd8 100644 --- a/src/gnsrecord/gnsrecord_misc.c +++ b/src/gnsrecord/gnsrecord_misc.c | |||
@@ -338,6 +338,12 @@ GNUNET_GNSRECORD_block_get_size (const struct GNUNET_GNSRECORD_Block *block) | |||
338 | + ntohl (block->ecdsa_block.purpose.size) /* Length of signed data */ | 338 | + ntohl (block->ecdsa_block.purpose.size) /* Length of signed data */ |
339 | - sizeof (block->ecdsa_block.purpose); /* Purpose already in EcdsaBlock */ | 339 | - sizeof (block->ecdsa_block.purpose); /* Purpose already in EcdsaBlock */ |
340 | break; | 340 | break; |
341 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
342 | return sizeof (uint32_t) /* zone type */ | ||
343 | + sizeof (block->eddsa_block) /* EddsaBlock */ | ||
344 | + ntohl (block->eddsa_block.purpose.size) /* Length of signed data */ | ||
345 | - sizeof (block->ecdsa_block.purpose); /* Purpose already in EcdsaBlock */ | ||
346 | |||
341 | default: | 347 | default: |
342 | return 0; | 348 | return 0; |
343 | } | 349 | } |
@@ -354,6 +360,8 @@ GNUNET_GNSRECORD_block_get_expiration (const struct | |||
354 | { | 360 | { |
355 | case GNUNET_GNSRECORD_TYPE_PKEY: | 361 | case GNUNET_GNSRECORD_TYPE_PKEY: |
356 | return GNUNET_TIME_absolute_ntoh (block->ecdsa_block.expiration_time); | 362 | return GNUNET_TIME_absolute_ntoh (block->ecdsa_block.expiration_time); |
363 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
364 | return GNUNET_TIME_absolute_ntoh (block->eddsa_block.expiration_time); | ||
357 | default: | 365 | default: |
358 | GNUNET_break (0); /* Hopefully we never get here, but we might */ | 366 | GNUNET_break (0); /* Hopefully we never get here, but we might */ |
359 | } | 367 | } |
@@ -373,6 +381,11 @@ GNUNET_GNSRECORD_query_from_block (const struct GNUNET_GNSRECORD_Block *block, | |||
373 | sizeof (block->ecdsa_block.derived_key), | 381 | sizeof (block->ecdsa_block.derived_key), |
374 | query); | 382 | query); |
375 | return GNUNET_OK; | 383 | return GNUNET_OK; |
384 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
385 | GNUNET_CRYPTO_hash (&block->eddsa_block.derived_key, | ||
386 | sizeof (block->eddsa_block.derived_key), | ||
387 | query); | ||
388 | return GNUNET_OK; | ||
376 | default: | 389 | default: |
377 | return GNUNET_SYSERR; | 390 | return GNUNET_SYSERR; |
378 | } | 391 | } |
@@ -394,6 +407,10 @@ GNUNET_GNSRECORD_record_to_identity_key (const struct GNUNET_GNSRECORD_Data *rd, | |||
394 | key->type = htonl (rd->record_type); | 407 | key->type = htonl (rd->record_type); |
395 | memcpy (&key->ecdsa_key, rd->data, sizeof (key->ecdsa_key)); | 408 | memcpy (&key->ecdsa_key, rd->data, sizeof (key->ecdsa_key)); |
396 | return GNUNET_OK; | 409 | return GNUNET_OK; |
410 | case GNUNET_GNSRECORD_TYPE_EDKEY: | ||
411 | key->type = htonl (rd->record_type); | ||
412 | memcpy (&key->eddsa_key, rd->data, sizeof (key->eddsa_key)); | ||
413 | return GNUNET_OK; | ||
397 | default: | 414 | default: |
398 | return GNUNET_SYSERR; | 415 | return GNUNET_SYSERR; |
399 | } | 416 | } |
diff --git a/src/gnsrecord/gnsrecord_serialization.c b/src/gnsrecord/gnsrecord_serialization.c index 42665e662..cb6957605 100644 --- a/src/gnsrecord/gnsrecord_serialization.c +++ b/src/gnsrecord/gnsrecord_serialization.c | |||
@@ -124,7 +124,8 @@ GNUNET_GNSRECORD_records_get_size (unsigned int rd_count, | |||
124 | return -1; | 124 | return -1; |
125 | } | 125 | } |
126 | // Do not pad PKEY | 126 | // Do not pad PKEY |
127 | if (GNUNET_GNSRECORD_TYPE_PKEY == rd->record_type) | 127 | if ((GNUNET_GNSRECORD_TYPE_PKEY == rd->record_type) || |
128 | (GNUNET_GNSRECORD_TYPE_EDKEY == rd->record_type)) | ||
128 | return ret; | 129 | return ret; |
129 | /** | 130 | /** |
130 | * Efficiently round up to the next | 131 | * Efficiently round up to the next |
diff --git a/src/gnsrecord/test_gnsrecord_crypto.c b/src/gnsrecord/test_gnsrecord_crypto.c index d541f3076..9394f562d 100644 --- a/src/gnsrecord/test_gnsrecord_crypto.c +++ b/src/gnsrecord/test_gnsrecord_crypto.c | |||
@@ -92,29 +92,22 @@ rd_decrypt_cb (void *cls, | |||
92 | res = 0; | 92 | res = 0; |
93 | } | 93 | } |
94 | 94 | ||
95 | |||
96 | static void | 95 | static void |
97 | run (void *cls, | 96 | test_with_type (struct GNUNET_IDENTITY_PrivateKey *privkey) |
98 | char *const *args, | ||
99 | const char *cfgfile, | ||
100 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
101 | { | 97 | { |
102 | struct GNUNET_GNSRECORD_Block *block; | 98 | struct GNUNET_GNSRECORD_Block *block; |
103 | struct GNUNET_IDENTITY_PublicKey pubkey; | 99 | struct GNUNET_IDENTITY_PublicKey pubkey; |
104 | struct GNUNET_HashCode query_pub; | 100 | struct GNUNET_HashCode query_pub; |
105 | struct GNUNET_HashCode query_priv; | 101 | struct GNUNET_HashCode query_priv; |
106 | struct GNUNET_TIME_Absolute expire = GNUNET_TIME_absolute_get (); | 102 | struct GNUNET_TIME_Absolute expire = GNUNET_TIME_absolute_get (); |
107 | struct GNUNET_IDENTITY_PrivateKey privkey; | ||
108 | 103 | ||
109 | 104 | ||
110 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
111 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
112 | /* get public key */ | 105 | /* get public key */ |
113 | GNUNET_IDENTITY_key_get_public (&privkey, | 106 | GNUNET_IDENTITY_key_get_public (privkey, |
114 | &pubkey); | 107 | &pubkey); |
115 | 108 | ||
116 | /* test query derivation */ | 109 | /* test query derivation */ |
117 | GNUNET_GNSRECORD_query_from_private_key (&privkey, | 110 | GNUNET_GNSRECORD_query_from_private_key (privkey, |
118 | "testlabel", | 111 | "testlabel", |
119 | &query_priv); | 112 | &query_priv); |
120 | GNUNET_GNSRECORD_query_from_public_key (&pubkey, | 113 | GNUNET_GNSRECORD_query_from_public_key (&pubkey, |
@@ -129,7 +122,7 @@ run (void *cls, | |||
129 | 122 | ||
130 | /* Create block */ | 123 | /* Create block */ |
131 | GNUNET_assert (NULL != (block = | 124 | GNUNET_assert (NULL != (block = |
132 | GNUNET_GNSRECORD_block_create (&privkey, | 125 | GNUNET_GNSRECORD_block_create (privkey, |
133 | expire, | 126 | expire, |
134 | s_name, | 127 | s_name, |
135 | s_rd, | 128 | s_rd, |
@@ -146,6 +139,27 @@ run (void *cls, | |||
146 | } | 139 | } |
147 | 140 | ||
148 | 141 | ||
142 | |||
143 | static void | ||
144 | run (void *cls, | ||
145 | char *const *args, | ||
146 | const char *cfgfile, | ||
147 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
148 | { | ||
149 | struct GNUNET_IDENTITY_PrivateKey privkey; | ||
150 | struct GNUNET_IDENTITY_PrivateKey privkey_ed; | ||
151 | |||
152 | |||
153 | privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY); | ||
154 | GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key); | ||
155 | test_with_type (&privkey); | ||
156 | |||
157 | privkey_ed.type = htonl (GNUNET_GNSRECORD_TYPE_EDKEY); | ||
158 | GNUNET_CRYPTO_eddsa_key_create (&privkey_ed.eddsa_key); | ||
159 | test_with_type(&privkey_ed); | ||
160 | } | ||
161 | |||
162 | |||
149 | int | 163 | int |
150 | main (int argc, char *argv[]) | 164 | main (int argc, char *argv[]) |
151 | { | 165 | { |