GNUnet  0.11.x
gnsrecord_crypto.c
Go to the documentation of this file.
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 
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 
40 
49 static void
52  const char *label,
53  const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
54 {
55  static const char ctx_key[] = "gns-aes-ctx-key";
56  static const char ctx_iv[] = "gns-aes-ctx-iv";
62 #ifdef LSD001
64  ctx_key, strlen (ctx_key),
65  pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
66  label, strlen (label),
67  NULL, 0);
68  GNUNET_CRYPTO_kdf (iv, sizeof(struct
70  ctx_iv, strlen (ctx_iv),
71  pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
72  label, strlen (label),
73  NULL, 0);
74 #else
76  pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
77  label, strlen (label),
78  ctx_key, strlen (ctx_key),
79  NULL, 0);
80  GNUNET_CRYPTO_kdf (iv, sizeof(struct
82  pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
83  label, strlen (label),
84  ctx_iv, strlen (ctx_iv),
85  NULL, 0);
86 #endif
87 }
88 
89 
101 struct GNUNET_GNSRECORD_Block *
103  const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey,
105  const char *label,
106  const struct GNUNET_GNSRECORD_Data *rd,
107  unsigned int rd_count)
108 {
109  ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count,
110  rd);
111  struct GNUNET_GNSRECORD_Block *block;
112  struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey;
115  struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)];
116  uint32_t rd_count_nbo;
117  struct GNUNET_TIME_Absolute now;
118 
119  if (payload_len < 0)
120  {
121  GNUNET_break (0);
122  return NULL;
123  }
124  if (payload_len > GNUNET_GNSRECORD_MAX_BLOCK_SIZE)
125  {
126  GNUNET_break (0);
127  return NULL;
128  }
129  /* convert relative to absolute times */
130  now = GNUNET_TIME_absolute_get ();
131  for (unsigned int i = 0; i < rd_count; i++)
132  {
133  rdc[i] = rd[i];
134  if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
135  {
136  struct GNUNET_TIME_Relative t;
137 
138  /* encrypted blocks must never have relative expiration times, convert! */
139  rdc[i].flags &= ~GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
140  t.rel_value_us = rdc[i].expiration_time;
142  }
143  }
144  /* serialize */
145  rd_count_nbo = htonl (rd_count);
146  {
147  char payload[sizeof(uint32_t) + payload_len];
148 
150  &rd_count_nbo,
151  sizeof(uint32_t));
152  GNUNET_assert (payload_len ==
154  rdc,
155  payload_len,
156  &payload[sizeof(uint32_t)
157  ]));
158  block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block)
159  + sizeof(uint32_t)
160  + payload_len);
161  block->purpose.size = htonl (sizeof(uint32_t)
162  + payload_len
163  + sizeof(struct
165  + sizeof(struct GNUNET_TIME_AbsoluteNBO));
167  block->expiration_time = GNUNET_TIME_absolute_hton (expire);
168  /* encrypt and sign */
170  label,
171  "gns");
173  &block->derived_key);
175  &skey,
176  label,
177  pkey);
178  GNUNET_break (payload_len + sizeof(uint32_t) ==
180  payload_len
181  + sizeof(uint32_t),
182  &skey,
183  &iv,
184  &block[1]));
185  }
186  if (GNUNET_OK !=
188  &block->purpose,
189  &block->signature))
190  {
191  GNUNET_break (0);
192  GNUNET_free (dkey);
193  GNUNET_free (block);
194  return NULL;
195  }
196  GNUNET_free (dkey);
197  return block;
198 }
199 
200 
211 struct GNUNET_GNSRECORD_Block *
214  const char *label,
215  const struct GNUNET_GNSRECORD_Data *rd,
216  unsigned int rd_count)
217 {
218  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
219 
221  &pkey);
222  return block_create (key,
223  &pkey,
224  expire,
225  label,
226  rd,
227  rd_count);
228 }
229 
230 
235 {
240 
245 };
246 
247 
260 struct GNUNET_GNSRECORD_Block *
263  const char *label,
264  const struct GNUNET_GNSRECORD_Data *rd,
265  unsigned int rd_count)
266 {
267 #define CSIZE 64
268  static struct KeyCacheLine cache[CSIZE];
269  struct KeyCacheLine *line;
270 
271  line = &cache[(*(unsigned int *) key) % CSIZE];
272  if (0 != memcmp (&line->key,
273  key,
274  sizeof(*key)))
275  {
276  /* cache miss, recompute */
277  line->key = *key;
279  &line->pkey);
280  }
281 #undef CSIZE
282  return block_create (key,
283  &line->pkey,
284  expire,
285  label,
286  rd,
287  rd_count);
288 }
289 
290 
298 int
300 {
302  &block->purpose,
303  &block->signature,
304  &block->derived_key);
305 }
306 
307 
319 int
321  const struct
323  const char *label,
325  void *proc_cls)
326 {
327  size_t payload_len = ntohl (block->purpose.size)
328  - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
329  - sizeof(struct GNUNET_TIME_AbsoluteNBO);
332 
333  if (ntohl (block->purpose.size) <
334  sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
335  + sizeof(struct GNUNET_TIME_AbsoluteNBO))
336  {
337  GNUNET_break_op (0);
338  return GNUNET_SYSERR;
339  }
341  &skey,
342  label,
343  zone_key);
344  {
345  char payload[payload_len];
346  uint32_t rd_count;
347 
348  GNUNET_break (payload_len ==
349  GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len,
350  &skey, &iv,
351  payload));
352  GNUNET_memcpy (&rd_count,
353  payload,
354  sizeof(uint32_t));
355  rd_count = ntohl (rd_count);
356  if (rd_count > 2048)
357  {
358  /* limit to sane value */
359  GNUNET_break_op (0);
360  return GNUNET_SYSERR;
361  }
362  {
363  struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
364  unsigned int j;
365  struct GNUNET_TIME_Absolute now;
366 
367  if (GNUNET_OK !=
368  GNUNET_GNSRECORD_records_deserialize (payload_len - sizeof(uint32_t),
369  &payload[sizeof(uint32_t)],
370  rd_count,
371  rd))
372  {
373  GNUNET_break_op (0);
374  return GNUNET_SYSERR;
375  }
376  /* hide expired records */
377  now = GNUNET_TIME_absolute_get ();
378  j = 0;
379  for (unsigned int i = 0; i < rd_count; i++)
380  {
381  if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
382  {
383  /* encrypted blocks must never have relative expiration times, skip! */
384  GNUNET_break_op (0);
385  continue;
386  }
387 
388  if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD))
389  {
390  int include_record = GNUNET_YES;
391  /* Shadow record, figure out if we have a not expired active record */
392  for (unsigned int k = 0; k < rd_count; k++)
393  {
394  if (k == i)
395  continue;
396  if (rd[i].expiration_time < now.abs_value_us)
397  include_record = GNUNET_NO; /* Shadow record is expired */
398  if ((rd[k].record_type == rd[i].record_type) &&
399  (rd[k].expiration_time >= now.abs_value_us) &&
400  (0 == (rd[k].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)))
401  {
402  include_record = GNUNET_NO; /* We have a non-expired, non-shadow record of the same type */
404  "Ignoring shadow record\n");
405  break;
406  }
407  }
408  if (GNUNET_YES == include_record)
409  {
410  rd[i].flags ^= GNUNET_GNSRECORD_RF_SHADOW_RECORD; /* Remove Flag */
411  if (j != i)
412  rd[j] = rd[i];
413  j++;
414  }
415  }
416  else if (rd[i].expiration_time >= now.abs_value_us)
417  {
418  /* Include this record */
419  if (j != i)
420  rd[j] = rd[i];
421  j++;
422  }
423  else
424  {
425  struct GNUNET_TIME_Absolute at;
426 
427  at.abs_value_us = rd[i].expiration_time;
429  "Excluding record that expired %s (%llu ago)\n",
431  (unsigned long long) rd[i].expiration_time
432  - now.abs_value_us);
433  }
434  }
435  rd_count = j;
436  if (NULL != proc)
437  proc (proc_cls,
438  rd_count,
439  (0 != rd_count) ? rd : NULL);
440  }
441  }
442  return GNUNET_OK;
443 }
444 
445 
453 void
456  const char *label,
457  struct GNUNET_HashCode *query)
458 {
459  struct GNUNET_CRYPTO_EcdsaPublicKey pub;
460 
462  &pub);
464  label,
465  query);
466 }
467 
468 
476 void
479  const char *label,
480  struct GNUNET_HashCode *query)
481 {
484  label,
485  "gns",
486  &pd);
487  GNUNET_CRYPTO_hash (&pd,
488  sizeof(pd),
489  query);
490 }
491 
492 
493 /* end of gnsrecord_crypto.c */
GNUNET_NETWORK_STRUCT_END typedef void(* GNUNET_GNSRECORD_RecordCallback)(void *cls, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Process a records that were decrypted from a block.
struct GNUNET_TIME_AbsoluteNBO expiration_time
Expiration time of the block.
This record should not be used unless all (other) records with an absolute expiration time have expir...
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.
Definition: crypto_ecc.c:1338
GNUNET_NETWORK_STRUCT_END ssize_t GNUNET_GNSRECORD_records_get_size(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Calculate how many bytes we will need to serialize the given records.
uint64_t rel_value_us
The actual value.
static char * pkey
Public key of the zone to look in, in ASCII.
struct GNUNET_CRYPTO_EcdsaPublicKey pkey
Associated public key.
int GNUNET_CRYPTO_ecdsa_verify(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EcdsaSignature *sig, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Verify ECDSA signature.
Definition: crypto_ecc.c:1046
struct GNUNET_GNSRECORD_Block * GNUNET_GNSRECORD_block_create(const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Sign name and records.
uint32_t purpose
What does this signature vouch for? This must contain a GNUNET_SIGNATURE_PURPOSE_XXX constant (from g...
ssize_t GNUNET_GNSRECORD_records_serialize(unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, size_t dest_size, char *dest)
Serialize the given records to the given destination buffer.
static void expire(void *cls)
Expire a PooledConnection object.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_GNSRECORD_Block * GNUNET_GNSRECORD_block_create2(const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Sign name and records, cache derived public key (also keeps the private key in static memory...
#define GNUNET_GNSRECORD_MAX_BLOCK_SIZE
Maximum size of a value that can be stored in a GNS block.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct GNUNET_GNSRECORD_Block * block_create(const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey, struct GNUNET_TIME_Absolute expire, const char *label, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Sign name and records.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:395
Private ECC key encoded for transmission.
int GNUNET_GNSRECORD_records_deserialize(size_t len, const char *src, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest)
Deserialize the given records to the given destination.
Information we have in an encrypted block with record data (i.e.
Time for absolute time used by GNUnet, in microseconds and in network byte order. ...
uint64_t abs_value_us
The actual value.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static char * zone
Name of the zone we manage.
void GNUNET_GNSRECORD_query_from_private_key(const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
int GNUNET_CRYPTO_ecdsa_sign(const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EcdsaSignature *sig)
ECDSA Sign a given block.
Definition: crypto_ecc.c:929
static char * line
Desired phone line (string to be converted to a hash).
struct GNUNET_CRYPTO_EcdsaPrivateKey key
A private key.
#define CSIZE
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
ssize_t GNUNET_CRYPTO_symmetric_encrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Encrypt a block using a symmetric sessionkey.
uint64_t expiration_time
Expiration time for the DNS record.
uint32_t size
How many bytes does this signature sign? (including this purpose header); in network byte order (!)...
A 512-bit hashcode.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
int GNUNET_GNSRECORD_block_verify(const struct GNUNET_GNSRECORD_Block *block)
Check if a signature is valid.
struct GNUNET_HashCode key
The key used in the DHT.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
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:239
static unsigned long long payload
How much data are we currently storing in the database?
static void derive_block_aes_key(struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, struct GNUNET_CRYPTO_SymmetricSessionKey *skey, const char *label, const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
Derive session key and iv from label and public key.
struct GNUNET_CRYPTO_EcdsaSignature signature
Signature of the block.
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:39
int GNUNET_GNSRECORD_block_decrypt(const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls)
Decrypt block.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and ECDS...
#define GNUNET_log(kind,...)
#define GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN
Signature of a gnunet naming system record block.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_GNSRECORD_query_from_public_key(const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, const char *label, struct GNUNET_HashCode *query)
Calculate the DHT query for a given label in a given zone.
Line in cache mapping private keys to public keys.
enum GNUNET_GNSRECORD_Flags flags
Flags for the record.
This flag is currently unused; former RF_PENDING flag.
const char * GNUNET_STRINGS_absolute_time_to_string(struct GNUNET_TIME_Absolute t)
Like asctime, except for GNUnet time.
Definition: strings.c:742
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.
Definition: crypto_ecc.c:1294
ssize_t GNUNET_CRYPTO_symmetric_decrypt(const void *block, size_t size, const struct GNUNET_CRYPTO_SymmetricSessionKey *sessionkey, const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, void *result)
Decrypt a given block using a symmetric sessionkey.
struct GNUNET_CRYPTO_EccSignaturePurpose purpose
Number of bytes signed; also specifies the number of bytes of encrypted data that follow...
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:657
struct GNUNET_CRYPTO_EcdsaPublicKey derived_key
Derived key used for signing; hash of this is the query.
int 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:89
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.