aboutsummaryrefslogtreecommitdiff
path: root/src/gnsrecord/gnsrecord_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnsrecord/gnsrecord_crypto.c')
-rw-r--r--src/gnsrecord/gnsrecord_crypto.c948
1 files changed, 0 insertions, 948 deletions
diff --git a/src/gnsrecord/gnsrecord_crypto.c b/src/gnsrecord/gnsrecord_crypto.c
deleted file mode 100644
index feb60ade9..000000000
--- a/src/gnsrecord/gnsrecord_crypto.c
+++ /dev/null
@@ -1,948 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2013, 2018 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
21/**
22 * @file gnsrecord/gnsrecord_crypto.c
23 * @brief API for GNS record-related crypto
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_constants.h"
31#include "gnunet_signatures.h"
32#include "gnunet_arm_service.h"
33#include "gnunet_gnsrecord_lib.h"
34#include "gnunet_dnsparser_lib.h"
35#include "gnunet_tun_lib.h"
36
37
38#define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__)
39
40ssize_t
41ecdsa_symmetric_decrypt (
42 const void *block,
43 size_t size,
44 const unsigned char *key,
45 const unsigned char *ctr,
46 void *result)
47{
48 gcry_cipher_hd_t handle;
49 int rc;
50
51 GNUNET_assert (0 == gcry_cipher_open (&handle, GCRY_CIPHER_AES256,
52 GCRY_CIPHER_MODE_CTR, 0));
53 rc = gcry_cipher_setkey (handle,
54 key,
55 GNUNET_CRYPTO_AES_KEY_LENGTH);
56 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
57 rc = gcry_cipher_setctr (handle,
58 ctr,
59 GNUNET_CRYPTO_AES_KEY_LENGTH / 2);
60 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
61 GNUNET_assert (0 == gcry_cipher_decrypt (handle, result, size, block, size));
62 gcry_cipher_close (handle);
63 return size;
64}
65
66
67ssize_t
68ecdsa_symmetric_encrypt (
69 const void *block,
70 size_t size,
71 const unsigned char *key,
72 const unsigned char *ctr,
73 void *result)
74{
75 gcry_cipher_hd_t handle;
76 int rc;
77
78 GNUNET_assert (0 == gcry_cipher_open (&handle, GCRY_CIPHER_AES256,
79 GCRY_CIPHER_MODE_CTR, 0));
80 rc = gcry_cipher_setkey (handle,
81 key,
82 GNUNET_CRYPTO_AES_KEY_LENGTH);
83 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
84 rc = gcry_cipher_setctr (handle,
85 ctr,
86 GNUNET_CRYPTO_AES_KEY_LENGTH / 2);
87 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
88 GNUNET_assert (0 == gcry_cipher_encrypt (handle, result, size, block, size));
89 gcry_cipher_close (handle);
90 return size;
91}
92
93
94enum GNUNET_GenericReturnValue
95eddsa_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 ssize_t ctlen = size - crypto_secretbox_MACBYTES;
103 if (ctlen < 0)
104 return GNUNET_SYSERR;
105 if (0 != crypto_secretbox_open_detached (result,
106 block, // Ciphertext
107 ((unsigned char*)block) + ctlen, // TAG
108 ctlen,
109 nonce, key))
110 {
111 return GNUNET_SYSERR;
112 }
113 return GNUNET_OK;
114}
115
116
117enum GNUNET_GenericReturnValue
118eddsa_symmetric_encrypt (
119 const void *block,
120 size_t size,
121 const unsigned char *key,
122 const unsigned char *nonce,
123 void *result)
124{
125 if (size > crypto_secretbox_MESSAGEBYTES_MAX)
126 return GNUNET_SYSERR;
127 crypto_secretbox_detached (result, // Ciphertext
128 result + size, // TAG
129 block, size, nonce, key);
130 return GNUNET_OK;
131}
132
133
134/**
135 * Derive session key and iv from label and public key.
136 *
137 * @param iv initialization vector to initialize
138 * @param skey session key to initialize
139 * @param label label to use for KDF
140 * @param pub public key to use for KDF
141 */
142static void
143derive_block_aes_key (unsigned char *ctr,
144 unsigned char *key,
145 const char *label,
146 uint64_t exp,
147 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
148{
149 static const char ctx_key[] = "gns-aes-ctx-key";
150 static const char ctx_iv[] = "gns-aes-ctx-iv";
151
152 GNUNET_CRYPTO_kdf (key, GNUNET_CRYPTO_AES_KEY_LENGTH,
153 ctx_key, strlen (ctx_key),
154 pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
155 label, strlen (label),
156 NULL, 0);
157 memset (ctr, 0, GNUNET_CRYPTO_AES_KEY_LENGTH / 2);
158 /** 4 byte nonce **/
159 GNUNET_CRYPTO_kdf (ctr, 4,
160 ctx_iv, strlen (ctx_iv),
161 pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
162 label, strlen (label),
163 NULL, 0);
164 /** Expiration time 64 bit. **/
165 memcpy (ctr + 4, &exp, sizeof (exp));
166 /** Set counter part to 1 **/
167 ctr[15] |= 0x01;
168}
169
170
171/**
172 * Derive session key and iv from label and public key.
173 *
174 * @param nonce initialization vector to initialize
175 * @param skey session key to initialize
176 * @param label label to use for KDF
177 * @param pub public key to use for KDF
178 */
179static void
180derive_block_xsalsa_key (unsigned char *nonce,
181 unsigned char *key,
182 const char *label,
183 uint64_t exp,
184 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
185{
186 static const char ctx_key[] = "gns-aes-ctx-key";
187 static const char ctx_iv[] = "gns-aes-ctx-iv";
188
189 GNUNET_CRYPTO_kdf (key, crypto_secretbox_KEYBYTES,
190 ctx_key, strlen (ctx_key),
191 pub, sizeof(struct GNUNET_CRYPTO_EddsaPublicKey),
192 label, strlen (label),
193 NULL, 0);
194 memset (nonce, 0, crypto_secretbox_NONCEBYTES);
195 /** 16 byte nonce **/
196 GNUNET_CRYPTO_kdf (nonce, (crypto_secretbox_NONCEBYTES - sizeof (exp)),
197 ctx_iv, strlen (ctx_iv),
198 pub, sizeof(struct GNUNET_CRYPTO_EddsaPublicKey),
199 label, strlen (label),
200 NULL, 0);
201 /** Expiration time 64 bit. **/
202 memcpy (nonce + (crypto_secretbox_NONCEBYTES - sizeof (exp)),
203 &exp, sizeof (exp));
204}
205
206
207/**
208 * Sign name and records
209 *
210 * @param key the private key
211 * @param pkey associated public key
212 * @param expire block expiration
213 * @param label the name for the records
214 * @param rd record data
215 * @param rd_count number of records
216 * @return NULL on error (block too large)
217 */
218static struct GNUNET_GNSRECORD_Block *
219block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
220 const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey,
221 struct GNUNET_TIME_Absolute expire,
222 const char *label,
223 const struct GNUNET_GNSRECORD_Data *rd,
224 unsigned int rd_count)
225{
226 ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count,
227 rd);
228 struct GNUNET_GNSRECORD_Block *block;
229 struct GNUNET_GNSRECORD_EcdsaBlock *ecblock;
230 struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey;
231 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2];
232 unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH];
233 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)];
234 uint32_t rd_count_nbo;
235 struct GNUNET_TIME_Absolute now;
236
237 if (payload_len < 0)
238 {
239 GNUNET_break (0);
240 return NULL;
241 }
242 if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE)
243 {
244 GNUNET_break (0);
245 return NULL;
246 }
247 /* convert relative to absolute times */
248 now = GNUNET_TIME_absolute_get ();
249 for (unsigned int i = 0; i < rd_count; i++)
250 {
251 rdc[i] = rd[i];
252 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
253 {
254 struct GNUNET_TIME_Relative t;
255
256 /* encrypted blocks must never have relative expiration times, convert! */
257 rdc[i].flags &= ~GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
258 t.rel_value_us = rdc[i].expiration_time;
259 rdc[i].expiration_time = GNUNET_TIME_absolute_add (now, t).abs_value_us;
260 }
261 }
262 /* serialize */
263 rd_count_nbo = htonl (rd_count);
264 {
265 char payload[sizeof(uint32_t) + payload_len];
266
267 GNUNET_memcpy (payload,
268 &rd_count_nbo,
269 sizeof(uint32_t));
270 GNUNET_assert (payload_len ==
271 GNUNET_GNSRECORD_records_serialize (rd_count,
272 rdc,
273 payload_len,
274 &payload[sizeof(uint32_t)
275 ]));
276 block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block)
277 + sizeof(uint32_t)
278 + payload_len);
279 ecblock = &block->ecdsa_block;
280 block->type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
281 ecblock->purpose.size = htonl (sizeof(uint32_t)
282 + payload_len
283 + sizeof(struct
284 GNUNET_CRYPTO_EccSignaturePurpose)
285 + sizeof(struct GNUNET_TIME_AbsoluteNBO));
286 ecblock->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
287 ecblock->expiration_time = GNUNET_TIME_absolute_hton (expire);
288 /* encrypt and sign */
289 dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key,
290 label,
291 "gns");
292 GNUNET_CRYPTO_ecdsa_key_get_public (dkey,
293 &ecblock->derived_key);
294 derive_block_aes_key (ctr,
295 skey,
296 label,
297 ecblock->expiration_time.abs_value_us__,
298 pkey);
299 GNUNET_break (payload_len + sizeof(uint32_t) ==
300 ecdsa_symmetric_encrypt (payload,
301 payload_len
302 + sizeof(uint32_t),
303 skey,
304 ctr,
305 &ecblock[1]));
306 }
307 if (GNUNET_OK !=
308 GNUNET_CRYPTO_ecdsa_sign_ (dkey,
309 &ecblock->purpose,
310 &ecblock->signature))
311 {
312 GNUNET_break (0);
313 GNUNET_free (dkey);
314 GNUNET_free (block);
315 return NULL;
316 }
317 GNUNET_free (dkey);
318 return block;
319}
320
321
322/**
323 * Sign name and records (EDDSA version)
324 *
325 * @param key the private key
326 * @param pkey associated public key
327 * @param expire block expiration
328 * @param label the name for the records
329 * @param rd record data
330 * @param rd_count number of records
331 * @return NULL on error (block too large)
332 */
333static struct GNUNET_GNSRECORD_Block *
334block_create_eddsa (const struct GNUNET_CRYPTO_EddsaPrivateKey *key,
335 const struct GNUNET_CRYPTO_EddsaPublicKey *pkey,
336 struct GNUNET_TIME_Absolute expire,
337 const char *label,
338 const struct GNUNET_GNSRECORD_Data *rd,
339 unsigned int rd_count)
340{
341 ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count,
342 rd);
343 struct GNUNET_GNSRECORD_Block *block;
344 struct GNUNET_GNSRECORD_EddsaBlock *edblock;
345 struct GNUNET_CRYPTO_EddsaPrivateScalar dkey;
346 unsigned char nonce[crypto_secretbox_NONCEBYTES];
347 unsigned char skey[crypto_secretbox_KEYBYTES];
348 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)];
349 uint32_t rd_count_nbo;
350 struct GNUNET_TIME_Absolute now;
351
352 if (payload_len < 0)
353 {
354 GNUNET_break (0);
355 return NULL;
356 }
357 if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE)
358 {
359 GNUNET_break (0);
360 return NULL;
361 }
362 /* convert relative to absolute times */
363 now = GNUNET_TIME_absolute_get ();
364 for (unsigned int i = 0; i < rd_count; i++)
365 {
366 rdc[i] = rd[i];
367 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
368 {
369 struct GNUNET_TIME_Relative t;
370
371 /* encrypted blocks must never have relative expiration times, convert! */
372 rdc[i].flags &= ~GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
373 t.rel_value_us = rdc[i].expiration_time;
374 rdc[i].expiration_time = GNUNET_TIME_absolute_add (now, t).abs_value_us;
375 }
376 }
377 /* serialize */
378 rd_count_nbo = htonl (rd_count);
379 {
380 char payload[sizeof(uint32_t) + payload_len];
381
382 GNUNET_memcpy (payload,
383 &rd_count_nbo,
384 sizeof(uint32_t));
385 GNUNET_assert (payload_len ==
386 GNUNET_GNSRECORD_records_serialize (rd_count,
387 rdc,
388 payload_len,
389 &payload[sizeof(uint32_t)
390 ]));
391 block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block)
392 + sizeof(uint32_t)
393 + payload_len
394 + crypto_secretbox_MACBYTES);
395 edblock = &block->eddsa_block;
396 block->type = htonl (GNUNET_GNSRECORD_TYPE_EDKEY);
397 edblock->purpose.size = htonl (sizeof(uint32_t)
398 + payload_len
399 + sizeof(struct
400 GNUNET_CRYPTO_EccSignaturePurpose)
401 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
402 + crypto_secretbox_MACBYTES);
403 edblock->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
404 edblock->expiration_time = GNUNET_TIME_absolute_hton (expire);
405 /* encrypt and sign */
406 GNUNET_CRYPTO_eddsa_private_key_derive (key,
407 label,
408 "gns",
409 &dkey);
410 GNUNET_CRYPTO_eddsa_key_get_public_from_scalar (&dkey,
411 &edblock->derived_key);
412 derive_block_xsalsa_key (nonce,
413 skey,
414 label,
415 edblock->expiration_time.abs_value_us__,
416 pkey);
417 GNUNET_break (GNUNET_OK ==
418 eddsa_symmetric_encrypt (payload,
419 payload_len
420 + sizeof(uint32_t),
421 skey,
422 nonce,
423 &edblock[1]));
424 }
425 GNUNET_CRYPTO_eddsa_sign_with_scalar (&dkey,
426 &edblock->purpose,
427 &edblock->signature);
428 return block;
429}
430
431
432/**
433 * Sign name and records
434 *
435 * @param key the private key
436 * @param expire block expiration
437 * @param label the name for the records
438 * @param rd record data
439 * @param rd_count number of records
440 * @return NULL on error (block too large)
441 */
442struct GNUNET_GNSRECORD_Block *
443GNUNET_GNSRECORD_block_create (const struct GNUNET_IDENTITY_PrivateKey *key,
444 struct GNUNET_TIME_Absolute expire,
445 const char *label,
446 const struct GNUNET_GNSRECORD_Data *rd,
447 unsigned int rd_count)
448{
449 struct GNUNET_IDENTITY_PublicKey pkey;
450 GNUNET_IDENTITY_key_get_public (key,
451 &pkey);
452 switch (ntohl (key->type))
453 {
454 case GNUNET_GNSRECORD_TYPE_PKEY:
455 return block_create_ecdsa (&key->ecdsa_key,
456 &pkey.ecdsa_key,
457 expire,
458 label,
459 rd,
460 rd_count);
461 case GNUNET_GNSRECORD_TYPE_EDKEY:
462 return block_create_eddsa (&key->eddsa_key,
463 &pkey.eddsa_key,
464 expire,
465 label,
466 rd,
467 rd_count);
468 default:
469 GNUNET_assert (0);
470 }
471 return NULL;
472}
473
474
475/**
476 * Line in cache mapping private keys to public keys.
477 */
478struct KeyCacheLine
479{
480 /**
481 * A private key.
482 */
483 struct GNUNET_CRYPTO_EcdsaPrivateKey key;
484
485 /**
486 * Associated public key.
487 */
488 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
489};
490
491
492/**
493 * Sign name and records, cache derived public key (also keeps the
494 * private key in static memory, so do not use this function if
495 * keeping the private key in the process'es RAM is a major issue).
496 *
497 * @param key the private key
498 * @param expire block expiration
499 * @param label the name for the records
500 * @param rd record data
501 * @param rd_count number of records
502 * @return NULL on error (block too large)
503 */
504struct GNUNET_GNSRECORD_Block *
505GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey,
506 struct GNUNET_TIME_Absolute expire,
507 const char *label,
508 const struct GNUNET_GNSRECORD_Data *rd,
509 unsigned int rd_count)
510{
511 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
512 struct GNUNET_CRYPTO_EddsaPublicKey edpubkey;
513
514 if (GNUNET_IDENTITY_TYPE_ECDSA == ntohl (pkey->type))
515 {
516 key = &pkey->ecdsa_key;
517#define CSIZE 64
518 static struct KeyCacheLine cache[CSIZE];
519 struct KeyCacheLine *line;
520
521 line = &cache[(*(unsigned int *) key) % CSIZE];
522 if (0 != memcmp (&line->key,
523 key,
524 sizeof(*key)))
525 {
526 /* cache miss, recompute */
527 line->key = *key;
528 GNUNET_CRYPTO_ecdsa_key_get_public (key,
529 &line->pkey);
530 }
531#undef CSIZE
532 return block_create_ecdsa (key,
533 &line->pkey,
534 expire,
535 label,
536 rd,
537 rd_count);
538 }
539 else if (GNUNET_IDENTITY_TYPE_EDDSA == ntohl (pkey->type))
540 {
541 GNUNET_CRYPTO_eddsa_key_get_public (&pkey->eddsa_key,
542 &edpubkey);
543 return block_create_eddsa (&pkey->eddsa_key,
544 &edpubkey,
545 expire,
546 label,
547 rd,
548 rd_count);
549 }
550 return NULL;
551}
552
553
554/**
555 * Check if a signature is valid. This API is used by the GNS Block
556 * to validate signatures received from the network.
557 *
558 * @param block block to verify
559 * @return #GNUNET_OK if the signature is valid
560 */
561enum GNUNET_GenericReturnValue
562GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block)
563{
564 switch (ntohl (block->type))
565 {
566 case GNUNET_GNSRECORD_TYPE_PKEY:
567 return GNUNET_CRYPTO_ecdsa_verify_ (
568 GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
569 &block->ecdsa_block.purpose,
570 &block->ecdsa_block.signature,
571 &block->ecdsa_block.derived_key);
572 case GNUNET_GNSRECORD_TYPE_EDKEY:
573 return GNUNET_CRYPTO_eddsa_verify_ (
574 GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
575 &block->eddsa_block.purpose,
576 &block->eddsa_block.signature,
577 &block->eddsa_block.derived_key);
578 default:
579 return GNUNET_NO;
580 }
581}
582
583
584enum GNUNET_GenericReturnValue
585block_decrypt_ecdsa (const struct GNUNET_GNSRECORD_EcdsaBlock *block,
586 const struct
587 GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
588 const char *label,
589 GNUNET_GNSRECORD_RecordCallback proc,
590 void *proc_cls)
591{
592 size_t payload_len = ntohl (block->purpose.size)
593 - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
594 - sizeof(struct GNUNET_TIME_AbsoluteNBO);
595 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2];
596 unsigned char key[GNUNET_CRYPTO_AES_KEY_LENGTH];
597
598 if (ntohl (block->purpose.size) <
599 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
600 + sizeof(struct GNUNET_TIME_AbsoluteNBO))
601 {
602 GNUNET_break_op (0);
603 return GNUNET_SYSERR;
604 }
605 derive_block_aes_key (ctr,
606 key,
607 label,
608 block->expiration_time.abs_value_us__,
609 zone_key);
610 {
611 char payload[payload_len];
612 uint32_t rd_count;
613
614 GNUNET_break (payload_len ==
615 ecdsa_symmetric_decrypt (&block[1], payload_len,
616 key, ctr,
617 payload));
618 GNUNET_memcpy (&rd_count,
619 payload,
620 sizeof(uint32_t));
621 rd_count = ntohl (rd_count);
622 if (rd_count > 2048)
623 {
624 /* limit to sane value */
625 GNUNET_break_op (0);
626 return GNUNET_SYSERR;
627 }
628 {
629 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
630 unsigned int j;
631 struct GNUNET_TIME_Absolute now;
632
633 if (GNUNET_OK !=
634 GNUNET_GNSRECORD_records_deserialize (payload_len - sizeof(uint32_t),
635 &payload[sizeof(uint32_t)],
636 rd_count,
637 rd))
638 {
639 GNUNET_break_op (0);
640 return GNUNET_SYSERR;
641 }
642 /* hide expired records */
643 now = GNUNET_TIME_absolute_get ();
644 j = 0;
645 for (unsigned int i = 0; i < rd_count; i++)
646 {
647 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
648 {
649 /* encrypted blocks must never have relative expiration times, skip! */
650 GNUNET_break_op (0);
651 continue;
652 }
653
654 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD))
655 {
656 int include_record = GNUNET_YES;
657 /* Shadow record, figure out if we have a not expired active record */
658 for (unsigned int k = 0; k < rd_count; k++)
659 {
660 if (k == i)
661 continue;
662 if (rd[i].expiration_time < now.abs_value_us)
663 include_record = GNUNET_NO; /* Shadow record is expired */
664 if ((rd[k].record_type == rd[i].record_type) &&
665 (rd[k].expiration_time >= now.abs_value_us) &&
666 (0 == (rd[k].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)))
667 {
668 include_record = GNUNET_NO; /* We have a non-expired, non-shadow record of the same type */
669 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
670 "Ignoring shadow record\n");
671 break;
672 }
673 }
674 if (GNUNET_YES == include_record)
675 {
676 rd[i].flags ^= GNUNET_GNSRECORD_RF_SHADOW_RECORD; /* Remove Flag */
677 if (j != i)
678 rd[j] = rd[i];
679 j++;
680 }
681 }
682 else if (rd[i].expiration_time >= now.abs_value_us)
683 {
684 /* Include this record */
685 if (j != i)
686 rd[j] = rd[i];
687 j++;
688 }
689 else
690 {
691 struct GNUNET_TIME_Absolute at;
692
693 at.abs_value_us = rd[i].expiration_time;
694 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
695 "Excluding record that expired %s (%llu ago)\n",
696 GNUNET_STRINGS_absolute_time_to_string (at),
697 (unsigned long long) rd[i].expiration_time
698 - now.abs_value_us);
699 }
700 }
701 rd_count = j;
702 if (NULL != proc)
703 proc (proc_cls,
704 rd_count,
705 (0 != rd_count) ? rd : NULL);
706 }
707 }
708 return GNUNET_OK;
709}
710
711
712enum GNUNET_GenericReturnValue
713block_decrypt_eddsa (const struct GNUNET_GNSRECORD_EddsaBlock *block,
714 const struct
715 GNUNET_CRYPTO_EddsaPublicKey *zone_key,
716 const char *label,
717 GNUNET_GNSRECORD_RecordCallback proc,
718 void *proc_cls)
719{
720 size_t payload_len = ntohl (block->purpose.size)
721 - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
722 - sizeof(struct GNUNET_TIME_AbsoluteNBO);
723 unsigned char nonce[crypto_secretbox_NONCEBYTES];
724 unsigned char key[crypto_secretbox_KEYBYTES];
725
726 if (ntohl (block->purpose.size) <
727 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
728 + sizeof(struct GNUNET_TIME_AbsoluteNBO))
729 {
730 GNUNET_break_op (0);
731 return GNUNET_SYSERR;
732 }
733 derive_block_xsalsa_key (nonce,
734 key,
735 label,
736 block->expiration_time.abs_value_us__,
737 zone_key);
738 {
739 char payload[payload_len];
740 uint32_t rd_count;
741
742 GNUNET_break (GNUNET_OK ==
743 eddsa_symmetric_decrypt (&block[1], payload_len,
744 key, nonce,
745 payload));
746 GNUNET_memcpy (&rd_count,
747 payload,
748 sizeof(uint32_t));
749 rd_count = ntohl (rd_count);
750 if (rd_count > 2048)
751 {
752 /* limit to sane value */
753 GNUNET_break_op (0);
754 return GNUNET_SYSERR;
755 }
756 {
757 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
758 unsigned int j;
759 struct GNUNET_TIME_Absolute now;
760
761 if (GNUNET_OK !=
762 GNUNET_GNSRECORD_records_deserialize (payload_len - sizeof(uint32_t),
763 &payload[sizeof(uint32_t)],
764 rd_count,
765 rd))
766 {
767 GNUNET_break_op (0);
768 return GNUNET_SYSERR;
769 }
770 /* hide expired records */
771 now = GNUNET_TIME_absolute_get ();
772 j = 0;
773 for (unsigned int i = 0; i < rd_count; i++)
774 {
775 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
776 {
777 /* encrypted blocks must never have relative expiration times, skip! */
778 GNUNET_break_op (0);
779 continue;
780 }
781
782 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD))
783 {
784 int include_record = GNUNET_YES;
785 /* Shadow record, figure out if we have a not expired active record */
786 for (unsigned int k = 0; k < rd_count; k++)
787 {
788 if (k == i)
789 continue;
790 if (rd[i].expiration_time < now.abs_value_us)
791 include_record = GNUNET_NO; /* Shadow record is expired */
792 if ((rd[k].record_type == rd[i].record_type) &&
793 (rd[k].expiration_time >= now.abs_value_us) &&
794 (0 == (rd[k].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)))
795 {
796 include_record = GNUNET_NO; /* We have a non-expired, non-shadow record of the same type */
797 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
798 "Ignoring shadow record\n");
799 break;
800 }
801 }
802 if (GNUNET_YES == include_record)
803 {
804 rd[i].flags ^= GNUNET_GNSRECORD_RF_SHADOW_RECORD; /* Remove Flag */
805 if (j != i)
806 rd[j] = rd[i];
807 j++;
808 }
809 }
810 else if (rd[i].expiration_time >= now.abs_value_us)
811 {
812 /* Include this record */
813 if (j != i)
814 rd[j] = rd[i];
815 j++;
816 }
817 else
818 {
819 struct GNUNET_TIME_Absolute at;
820
821 at.abs_value_us = rd[i].expiration_time;
822 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
823 "Excluding record that expired %s (%llu ago)\n",
824 GNUNET_STRINGS_absolute_time_to_string (at),
825 (unsigned long long) rd[i].expiration_time
826 - now.abs_value_us);
827 }
828 }
829 rd_count = j;
830 if (NULL != proc)
831 proc (proc_cls,
832 rd_count,
833 (0 != rd_count) ? rd : NULL);
834 }
835 }
836 return GNUNET_OK;
837}
838
839
840/**
841 * Decrypt block.
842 *
843 * @param block block to decrypt
844 * @param zone_key public key of the zone
845 * @param label the name for the records
846 * @param proc function to call with the result
847 * @param proc_cls closure for proc
848 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
849 * not well-formed
850 */
851enum GNUNET_GenericReturnValue
852GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block,
853 const struct
854 GNUNET_IDENTITY_PublicKey *zone_key,
855 const char *label,
856 GNUNET_GNSRECORD_RecordCallback proc,
857 void *proc_cls)
858{
859 switch (ntohl (zone_key->type))
860 {
861 case GNUNET_IDENTITY_TYPE_ECDSA:
862 return block_decrypt_ecdsa (&block->ecdsa_block,
863 &zone_key->ecdsa_key, label, proc, proc_cls);
864 case GNUNET_IDENTITY_TYPE_EDDSA:
865 return block_decrypt_eddsa (&block->eddsa_block,
866 &zone_key->eddsa_key, label, proc, proc_cls);
867 default:
868 return GNUNET_SYSERR;
869 }
870}
871
872
873/**
874 * Calculate the DHT query for a given @a label in a given @a zone.
875 *
876 * @param zone private key of the zone
877 * @param label label of the record
878 * @param query hash to use for the query
879 */
880void
881GNUNET_GNSRECORD_query_from_private_key (const struct
882 GNUNET_IDENTITY_PrivateKey *zone,
883 const char *label,
884 struct GNUNET_HashCode *query)
885{
886 struct GNUNET_IDENTITY_PublicKey pub;
887 switch (ntohl (zone->type))
888 {
889 case GNUNET_GNSRECORD_TYPE_PKEY:
890 case GNUNET_GNSRECORD_TYPE_EDKEY:
891
892 GNUNET_IDENTITY_key_get_public (zone,
893 &pub);
894 GNUNET_GNSRECORD_query_from_public_key (&pub,
895 label,
896 query);
897 break;
898 default:
899 GNUNET_assert (0);
900 }
901}
902
903
904/**
905 * Calculate the DHT query for a given @a label in a given @a zone.
906 * FIXME: We may want to plugin-ize this at some point.
907 *
908 * @param pub public key of the zone
909 * @param label label of the record
910 * @param query hash to use for the query
911 */
912void
913GNUNET_GNSRECORD_query_from_public_key (const struct
914 GNUNET_IDENTITY_PublicKey *pub,
915 const char *label,
916 struct GNUNET_HashCode *query)
917{
918 struct GNUNET_IDENTITY_PublicKey pd;
919
920 switch (ntohl (pub->type))
921 {
922 case GNUNET_GNSRECORD_TYPE_PKEY:
923 pd.type = pub->type;
924 GNUNET_CRYPTO_ecdsa_public_key_derive (&pub->ecdsa_key,
925 label,
926 "gns",
927 &pd.ecdsa_key);
928 GNUNET_CRYPTO_hash (&pd.ecdsa_key,
929 sizeof (pd.ecdsa_key),
930 query);
931 break;
932 case GNUNET_GNSRECORD_TYPE_EDKEY:
933 pd.type = pub->type;
934 GNUNET_CRYPTO_eddsa_public_key_derive (&pub->eddsa_key,
935 label,
936 "gns",
937 &(pd.eddsa_key));
938 GNUNET_CRYPTO_hash (&pd.eddsa_key,
939 sizeof (pd.eddsa_key),
940 query);
941 break;
942 default:
943 GNUNET_assert (0);
944 }
945}
946
947
948/* end of gnsrecord_crypto.c */