GNUnet  0.10.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) GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
33 
34 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
35 
41 #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
42 
43 
51 static void
53 {
54  struct GNUNET_TIME_Relative timeout;
55 
57  (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
58 }
59 
60 
77 {
78  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
79  struct GNUNET_DISK_FileHandle *fd;
80  unsigned int cnt;
81  int ec;
82  uint64_t fs;
83  ssize_t sret;
84 
86  return NULL;
87  while (GNUNET_YES != GNUNET_DISK_file_test (filename))
88  {
89  fd = GNUNET_DISK_file_open (filename,
94  if (NULL == fd)
95  {
96  if (EEXIST == errno)
97  {
98  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
99  {
100  /* must exist but not be accessible, fail for good! */
101  if (0 != ACCESS (filename, R_OK))
102  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
103  else
104  GNUNET_break (0); /* what is going on!? */
105  return NULL;
106  }
107  continue;
108  }
109  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
110  return NULL;
111  }
112  cnt = 0;
113  while (GNUNET_YES !=
114  GNUNET_DISK_file_lock (fd, 0,
115  sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
116  GNUNET_YES))
117  {
118  short_wait ();
119  if (0 == ++cnt % 10)
120  {
121  ec = errno;
123  _("Could not acquire lock on file `%s': %s...\n"),
124  filename,
125  STRERROR (ec));
126  }
127  }
129  _("Creating a new private key. This may take a while.\n"));
131  GNUNET_assert (NULL != priv);
132  GNUNET_assert (sizeof (*priv) ==
133  GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
135  if (GNUNET_YES !=
137  sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
138  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
140  return priv;
141  }
142  /* key file exists already, read it! */
145  if (NULL == fd)
146  {
147  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
148  return NULL;
149  }
150  cnt = 0;
151  while (1)
152  {
153  if (GNUNET_YES !=
154  GNUNET_DISK_file_lock (fd, 0,
155  sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
156  GNUNET_NO))
157  {
158  if (0 == ++cnt % 60)
159  {
160  ec = errno;
162  _("Could not acquire lock on file `%s': %s...\n"), filename,
163  STRERROR (ec));
165  _
166  ("This may be ok if someone is currently generating a private key.\n"));
167  }
168  short_wait ();
169  continue;
170  }
171  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
172  {
173  /* eh, what!? File we opened is now gone!? */
174  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
175  if (GNUNET_YES !=
177  sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
178  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
180 
181  return NULL;
182  }
183  if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
184  fs = 0;
185  if (fs < sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))
186  {
187  /* maybe we got the read lock before the key generating
188  * process had a chance to get the write lock; give it up! */
189  if (GNUNET_YES !=
191  sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
192  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
193  if (0 == ++cnt % 10)
194  {
196  _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
197  filename,
198  (unsigned int) fs,
199  (unsigned int) sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
201  _("This may be ok if someone is currently generating a key.\n"));
202  }
203  short_wait (); /* wait a bit longer! */
204  continue;
205  }
206  break;
207  }
208  fs = sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey);
209  priv = GNUNET_malloc (fs);
210  sret = GNUNET_DISK_file_read (fd,
211  priv,
212  fs);
213  GNUNET_assert ( (sret >= 0) &&
214  (fs == (size_t) sret) );
215  if (GNUNET_YES !=
217  0,
218  sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
220  "fcntl",
221  filename);
224 #if CRYPTO_BUG
225  if (GNUNET_OK !=
226  check_eddsa_key (priv))
227  {
228  GNUNET_break (0);
229  GNUNET_free (priv);
230  return NULL;
231  }
232 #endif
233  return priv;
234 }
235 
236 
253 {
254  struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
255  struct GNUNET_DISK_FileHandle *fd;
256  unsigned int cnt;
257  int ec;
258  uint64_t fs;
259  ssize_t sret;
260 
261  if (GNUNET_SYSERR ==
263  return NULL;
264  while (GNUNET_YES != GNUNET_DISK_file_test (filename))
265  {
266  fd = GNUNET_DISK_file_open (filename,
271  if (NULL == fd)
272  {
273  if (EEXIST == errno)
274  {
275  if (GNUNET_YES != GNUNET_DISK_file_test (filename))
276  {
277  /* must exist but not be accessible, fail for good! */
278  if (0 != ACCESS (filename, R_OK))
280  "access",
281  filename);
282  else
283  GNUNET_break (0); /* what is going on!? */
284  return NULL;
285  }
286  continue;
287  }
289  "open",
290  filename);
291  return NULL;
292  }
293  cnt = 0;
294  while (GNUNET_YES !=
296  0,
297  sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
298  GNUNET_YES))
299  {
300  short_wait ();
301  if (0 == ++cnt % 10)
302  {
303  ec = errno;
305  _("Could not acquire lock on file `%s': %s...\n"),
306  filename,
307  STRERROR (ec));
308  }
309  }
311  _("Creating a new private key. This may take a while.\n"));
313  GNUNET_assert (NULL != priv);
314  GNUNET_assert (sizeof (*priv) ==
316  priv,
317  sizeof (*priv)));
319  if (GNUNET_YES !=
321  sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
323  "fcntl",
324  filename);
327  return priv;
328  }
329  /* key file exists already, read it! */
330  fd = GNUNET_DISK_file_open (filename,
333  if (NULL == fd)
334  {
336  "open",
337  filename);
338  return NULL;
339  }
340  cnt = 0;
341  while (1)
342  {
343  if (GNUNET_YES !=
344  GNUNET_DISK_file_lock (fd, 0,
345  sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
346  GNUNET_NO))
347  {
348  if (0 == ++cnt % 60)
349  {
350  ec = errno;
352  _("Could not acquire lock on file `%s': %s...\n"),
353  filename,
354  STRERROR (ec));
356  _("This may be ok if someone is currently generating a private key.\n"));
357  }
358  short_wait ();
359  continue;
360  }
361  if (GNUNET_YES !=
362  GNUNET_DISK_file_test (filename))
363  {
364  /* eh, what!? File we opened is now gone!? */
366  "stat",
367  filename);
368  if (GNUNET_YES !=
370  sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
372  "fcntl",
373  filename);
376 
377  return NULL;
378  }
379  if (GNUNET_OK !=
380  GNUNET_DISK_file_size (filename,
381  &fs,
382  GNUNET_YES,
383  GNUNET_YES))
384  fs = 0;
385  if (fs < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
386  {
387  /* maybe we got the read lock before the key generating
388  * process had a chance to get the write lock; give it up! */
389  if (GNUNET_YES !=
391  sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
393  "fcntl",
394  filename);
395  if (0 == ++cnt % 10)
396  {
398  _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
399  filename, (unsigned int) fs,
400  (unsigned int) sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
402  _("This may be ok if someone is currently generating a key.\n"));
403  }
404  short_wait (); /* wait a bit longer! */
405  continue;
406  }
407  break;
408  }
409  fs = sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
410  priv = GNUNET_malloc (fs);
411  sret = GNUNET_DISK_file_read (fd,
412  priv,
413  fs);
414  GNUNET_assert ( (sret >= 0) &&
415  (fs == (size_t) sret) );
416  if (GNUNET_YES !=
418  sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
420  "fcntl",
421  filename);
424  return priv;
425 }
426 
427 
438 {
439  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
440  char *fn;
441 
442  if (GNUNET_OK !=
443  GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
444  return NULL;
446  GNUNET_free (fn);
447  return priv;
448 }
449 
450 
459 int
461  struct GNUNET_PeerIdentity *dst)
462 {
463  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
464 
465  if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
466  {
468  _("Could not load peer's private key\n"));
469  return GNUNET_SYSERR;
470  }
472  GNUNET_free (priv);
473  return GNUNET_OK;
474 }
475 
476 
485 void
486 GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
487 {
489  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
490 
492  (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
494  if (NULL != priv)
495  GNUNET_free (priv);
497 }
498 
499 /* 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:669
Open the file for reading.
int GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:2133
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:1817
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:1618
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:881
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define STRERROR(i)
Definition: plibc.h:676
struct GNUNET_CRYPTO_EcdsaPrivateKey * GNUNET_CRYPTO_ecdsa_key_create(void)
Create a new private key.
Definition: crypto_ecc.c:691
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:833
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:208
struct GNUNET_CRYPTO_EddsaPrivateKey * GNUNET_CRYPTO_eddsa_key_create(void)
Create a new private key.
Definition: crypto_ecc.c:746
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:1049
#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:439
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
static struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
Definition: gnunet-arm.c:104
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:1812
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:1564
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
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:289
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:272
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:80
int fd
File handle on other OSes.
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:1673
#define ACCESS(p, m)
Definition: plibc.h:656
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 (!).