GNUnet  0.11.x
crypto_ecc_setup.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2012, 2013, 2015 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 
26 #include "platform.h"
27 #include <gcrypt.h>
28 #include "gnunet_util_lib.h"
29 
30 #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
31 
32 #define LOG_STRERROR(kind, syscall) \
33  GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
34 
35 #define LOG_STRERROR_FILE(kind, syscall, filename) \
36  GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
37 
43 #define LOG_GCRY(level, cmd, rc) \
44  do \
45  { \
46  LOG (level, \
47  _ ("`%s' failed at %s:%d with error: %s\n"), \
48  cmd, \
49  __FILE__, \
50  __LINE__, \
51  gcry_strerror (rc)); \
52  } while (0)
53 
54 
62 static void
64 {
65  struct GNUNET_TIME_Relative timeout;
66 
68  (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
69 }
70 
71 
88 {
89  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
90  struct GNUNET_DISK_FileHandle *fd;
91  unsigned int cnt;
92  int ec;
93  uint64_t fs;
94  ssize_t sret;
95 
97  return NULL;
98  while (GNUNET_YES != GNUNET_DISK_file_test (filename))
99  {
100  fd =
101  GNUNET_DISK_file_open (filename,
106  if (NULL == fd)
107  {
108  if (EEXIST == errno)
109  {
110  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
111  {
112  /* must exist but not be accessible, fail for good! */
113  if (0 != access (filename, R_OK))
114  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
115  else
116  GNUNET_break (0); /* what is going on!? */
117  return NULL;
118  }
119  continue;
120  }
121  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
122  return NULL;
123  }
124  cnt = 0;
125  while (GNUNET_YES !=
127  0,
128  sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey),
129  GNUNET_YES))
130  {
131  short_wait ();
132  if (0 == ++cnt % 10)
133  {
134  ec = errno;
136  _ ("Could not acquire lock on file `%s': %s...\n"),
137  filename,
138  strerror (ec));
139  }
140  }
142  _ ("Creating a new private key. This may take a while.\n"));
144  GNUNET_assert (NULL != priv);
145  GNUNET_assert (sizeof(*priv) ==
146  GNUNET_DISK_file_write (fd, priv, sizeof(*priv)));
148  if (GNUNET_YES !=
150  0,
151  sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)))
152  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
154  return priv;
155  }
156  /* key file exists already, read it! */
157  fd = GNUNET_DISK_file_open (filename,
160  if (NULL == fd)
161  {
162  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
163  return NULL;
164  }
165  cnt = 0;
166  while (1)
167  {
168  if (GNUNET_YES !=
170  0,
171  sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey),
172  GNUNET_NO))
173  {
174  if (0 == ++cnt % 60)
175  {
176  ec = errno;
178  _ ("Could not acquire lock on file `%s': %s...\n"),
179  filename,
180  strerror (ec));
181  LOG (
183  _ (
184  "This may be ok if someone is currently generating a private key.\n"));
185  }
186  short_wait ();
187  continue;
188  }
189  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
190  {
191  /* eh, what!? File we opened is now gone!? */
192  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
193  if (GNUNET_YES !=
195  0,
196  sizeof(
198  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
200 
201  return NULL;
202  }
203  if (GNUNET_OK !=
204  GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
205  fs = 0;
206  if (fs < sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey))
207  {
208  /* maybe we got the read lock before the key generating
209  * process had a chance to get the write lock; give it up! */
210  if (GNUNET_YES !=
212  0,
213  sizeof(
215  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
216  if (0 == ++cnt % 10)
217  {
219  _ (
220  "When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
221  filename,
222  (unsigned int) fs,
223  (unsigned int) sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
225  _ ("This may be ok if someone is currently generating a key.\n"));
226  }
227  short_wait (); /* wait a bit longer! */
228  continue;
229  }
230  break;
231  }
232  fs = sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey);
233  priv = GNUNET_malloc (fs);
234  sret = GNUNET_DISK_file_read (fd, priv, fs);
235  GNUNET_assert ((sret >= 0) && (fs == (size_t) sret));
236  if (GNUNET_YES !=
238  0,
239  sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)))
240  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
242 #if CRYPTO_BUG
243  if (GNUNET_OK != check_eddsa_key (priv))
244  {
245  GNUNET_break (0);
246  GNUNET_free (priv);
247  return NULL;
248  }
249 #endif
250  return priv;
251 }
252 
253 
270 {
271  struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
272  struct GNUNET_DISK_FileHandle *fd;
273  unsigned int cnt;
274  int ec;
275  uint64_t fs;
276  ssize_t sret;
277 
279  return NULL;
280  while (GNUNET_YES != GNUNET_DISK_file_test (filename))
281  {
282  fd =
283  GNUNET_DISK_file_open (filename,
288  if (NULL == fd)
289  {
290  if (EEXIST == errno)
291  {
292  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
293  {
294  /* must exist but not be accessible, fail for good! */
295  if (0 != access (filename, R_OK))
296  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
297  else
298  GNUNET_break (0); /* what is going on!? */
299  return NULL;
300  }
301  continue;
302  }
303  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
304  return NULL;
305  }
306  cnt = 0;
307  while (GNUNET_YES !=
309  0,
310  sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey),
311  GNUNET_YES))
312  {
313  short_wait ();
314  if (0 == ++cnt % 10)
315  {
316  ec = errno;
318  _ ("Could not acquire lock on file `%s': %s...\n"),
319  filename,
320  strerror (ec));
321  }
322  }
324  _ ("Creating a new private key. This may take a while.\n"));
326  GNUNET_assert (NULL != priv);
327  GNUNET_assert (sizeof(*priv) ==
328  GNUNET_DISK_file_write (fd, priv, sizeof(*priv)));
330  if (GNUNET_YES !=
332  0,
333  sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)))
334  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
336  return priv;
337  }
338  /* key file exists already, read it! */
339  fd = GNUNET_DISK_file_open (filename,
342  if (NULL == fd)
343  {
344  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
345  return NULL;
346  }
347  cnt = 0;
348  while (1)
349  {
350  if (GNUNET_YES !=
352  0,
353  sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey),
354  GNUNET_NO))
355  {
356  if (0 == ++cnt % 60)
357  {
358  ec = errno;
360  _ ("Could not acquire lock on file `%s': %s...\n"),
361  filename,
362  strerror (ec));
363  LOG (
365  _ (
366  "This may be ok if someone is currently generating a private key.\n"));
367  }
368  short_wait ();
369  continue;
370  }
371  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
372  {
373  /* eh, what!? File we opened is now gone!? */
374  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
375  if (GNUNET_YES !=
377  0,
378  sizeof(
380  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
382 
383  return NULL;
384  }
385  if (GNUNET_OK !=
386  GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
387  fs = 0;
388  if (fs < sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey))
389  {
390  /* maybe we got the read lock before the key generating
391  * process had a chance to get the write lock; give it up! */
392  if (GNUNET_YES !=
394  0,
395  sizeof(
397  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
398  if (0 == ++cnt % 10)
399  {
401  _ (
402  "When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
403  filename,
404  (unsigned int) fs,
405  (unsigned int) sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
407  _ ("This may be ok if someone is currently generating a key.\n"));
408  }
409  short_wait (); /* wait a bit longer! */
410  continue;
411  }
412  break;
413  }
414  fs = sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey);
415  priv = GNUNET_malloc (fs);
416  sret = GNUNET_DISK_file_read (fd, priv, fs);
417  GNUNET_assert ((sret >= 0) && (fs == (size_t) sret));
418  if (GNUNET_YES !=
420  0,
421  sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)))
422  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
424  return priv;
425 }
426 
427 
438  const struct GNUNET_CONFIGURATION_Handle *cfg)
439 {
440  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
441  char *fn;
442 
443  if (GNUNET_OK !=
444  GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
445  return NULL;
447  GNUNET_free (fn);
448  return priv;
449 }
450 
451 
460 int
462  struct GNUNET_PeerIdentity *dst)
463 {
464  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
465 
466  if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
467  {
469  _ ("Could not load peer's private key\n"));
470  return GNUNET_SYSERR;
471  }
473  GNUNET_free (priv);
474  return GNUNET_OK;
475 }
476 
477 
486 void
487 GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
488 {
490  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
491 
493  (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
495  if (NULL != priv)
496  GNUNET_free (priv);
498 }
499 
500 
501 /* end of crypto_ecc_setup.c */
#define LOG_STRERROR_FILE(kind, syscall, filename)
static void short_wait()
Wait for a short time (we&#39;re trying to lock a file or want to give another process a shot at finishin...
int GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory)...
Definition: disk.c:544
Open the file for reading.
int GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1500
Create file if it doesn&#39;t exist.
int GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1345
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
int GNUNET_DISK_file_unlock(struct GNUNET_DISK_FileHandle *fh, off_t unlock_start, off_t unlock_end)
Unlock a part of a file.
Definition: disk.c:1233
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:732
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_create(void)
Create a new private key.
Definition: crypto_ecc.c:688
Nobody is allowed to do anything to the file.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:684
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
Private ECC key encoded for transmission.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
int GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create(void)
Create a new private key.
Definition: crypto_ecc.c:744
static char * fn
Filename of the unique file.
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:820
#define LOG(kind,...)
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
static char * filename
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:442
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
int GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds, struct GNUNET_NETWORK_FDSet *wfds, struct GNUNET_NETWORK_FDSet *efds, struct GNUNET_TIME_Relative timeout)
Check if sockets meet certain conditions.
Definition: network.c:1340
int GNUNET_DISK_file_lock(struct GNUNET_DISK_FileHandle *fh, off_t lock_start, off_t lock_end, int excl)
Lock a part of a file.
Definition: disk.c:1201
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_create_from_file(const char *filename)
Create a new private key by reading it from a file.
Open the file for writing.
static struct GNUNET_FS_Handle * fs
Handle to FS service.
Definition: gnunet-fs.c:36
int GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:257
void GNUNET_CRYPTO_eddsa_key_get_public(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Extract the public key for the given private key.
Definition: crypto_ecc.c:270
Private ECC key encoded for transmission.
The identity of the host (wraps the signing key of the peer).
configuration data
Definition: configuration.c:85
#define GNUNET_log(kind,...)
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_file(const char *filename)
Create a new private key by reading it from a file.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
int GNUNET_CRYPTO_get_peer_identity(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst)
Retrieve the identity of the host&#39;s peer.
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create_from_configuration(const struct GNUNET_CONFIGURATION_Handle *cfg)
Create a new private key by reading our peer&#39;s key from the file specified in the configuration...
#define GNUNET_YES
Definition: gnunet_common.h:77
int fd
File handle on Unix-like systems.
Fail if file already exists.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1268
Handle used to access files (and pipes).
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
void GNUNET_CRYPTO_eddsa_setup_key(const char *cfg_name)
Setup a key file for a peer given the name of the configuration file (!).