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, 2020 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 
64 static int
65 read_from_file (const char *filename,
66  void *buf,
67  size_t buf_size)
68 {
69  int fd;
70  struct stat sb;
71 
72  fd = open (filename,
73  O_RDONLY);
74  if (-1 == fd)
75  {
76  memset (buf,
77  0,
78  buf_size);
79  return GNUNET_SYSERR;
80  }
81  if (0 != fstat (fd,
82  &sb))
83  {
85  "stat",
86  filename);
87  GNUNET_assert (0 == close (fd));
88  memset (buf,
89  0,
90  buf_size);
91  return GNUNET_SYSERR;
92  }
93  if (sb.st_size != buf_size)
94  {
96  "File `%s' has wrong size (%llu), expected %llu bytes\n",
97  filename,
98  (unsigned long long) sb.st_size,
99  (unsigned long long) buf_size);
100  GNUNET_assert (0 == close (fd));
101  memset (buf,
102  0,
103  buf_size);
104  return GNUNET_SYSERR;
105  }
106  if (buf_size !=
107  read (fd,
108  buf,
109  buf_size))
110  {
112  "read",
113  filename);
114  GNUNET_assert (0 == close (fd));
115  memset (buf,
116  0,
117  buf_size);
118  return GNUNET_SYSERR;
119  }
120  GNUNET_assert (0 == close (fd));
121  return GNUNET_OK;
122 }
123 
124 
138 static int
140  const void *buf,
141  size_t buf_size)
142 {
143  char *tmpl;
144  int fd;
145 
146  if (GNUNET_OK !=
148  {
150  "mkstemp",
151  filename);
152  return GNUNET_SYSERR;
153  }
154  {
155  char *dname;
156 
157  dname = GNUNET_strdup (filename);
158  GNUNET_asprintf (&tmpl,
159  "%s/XXXXXX",
160  dirname (dname));
161  GNUNET_free (dname);
162  }
163  fd = mkstemp (tmpl);
164  if (-1 == fd)
165  {
167  "mkstemp",
168  tmpl);
169  GNUNET_free (tmpl);
170  return GNUNET_SYSERR;
171  }
172  if (0 != fchmod (fd,
173  S_IRUSR))
174  {
176  "chmod",
177  tmpl);
178  GNUNET_assert (0 == close (fd));
179  if (0 != unlink (tmpl))
181  "unlink",
182  tmpl);
183  GNUNET_free (tmpl);
184  return GNUNET_SYSERR;
185  }
186  if (buf_size !=
187  write (fd,
188  buf,
189  buf_size))
190  {
192  "write",
193  tmpl);
194  GNUNET_assert (0 == close (fd));
195  if (0 != unlink (tmpl))
197  "unlink",
198  tmpl);
199  GNUNET_free (tmpl);
200  return GNUNET_SYSERR;
201  }
202  GNUNET_assert (0 == close (fd));
203 
204  if (0 != link (tmpl,
205  filename))
206  {
207  if (0 != unlink (tmpl))
209  "unlink",
210  tmpl);
211  GNUNET_free (tmpl);
212  return GNUNET_NO;
213  }
214  if (0 != unlink (tmpl))
216  "unlink",
217  tmpl);
218  GNUNET_free (tmpl);
219  return GNUNET_OK;
220 }
221 
222 
238 int
240  int do_create,
242 {
243  int ret;
244 
245  if (GNUNET_OK ==
246  read_from_file (filename,
247  pkey,
248  sizeof (*pkey)))
249  {
250  /* file existed, report that we didn't create it... */
251  return (do_create) ? GNUNET_NO : GNUNET_OK;
252  }
254  ret = atomic_write_to_file (filename,
255  pkey,
256  sizeof (*pkey));
257  if ( (GNUNET_OK == ret) ||
258  (GNUNET_SYSERR == ret) )
259  return ret;
260  /* maybe another process succeeded in the meantime, try reading one more time */
261  if (GNUNET_OK ==
262  read_from_file (filename,
263  pkey,
264  sizeof (*pkey)))
265  {
266  /* file existed, report that *we* didn't create it... */
267  return (do_create) ? GNUNET_NO : GNUNET_OK;
268  }
269  /* give up */
270  return GNUNET_SYSERR;
271 }
272 
273 
289 int
291  int do_create,
293 {
294  if (GNUNET_OK ==
295  read_from_file (filename,
296  pkey,
297  sizeof (*pkey)))
298  {
299  /* file existed, report that we didn't create it... */
300  return (do_create) ? GNUNET_NO : GNUNET_OK;
301  }
303  if (GNUNET_OK ==
304  atomic_write_to_file (filename,
305  pkey,
306  sizeof (*pkey)))
307  return GNUNET_OK;
308  /* maybe another process succeeded in the meantime, try reading one more time */
309  if (GNUNET_OK ==
310  read_from_file (filename,
311  pkey,
312  sizeof (*pkey)))
313  {
314  /* file existed, report that *we* didn't create it... */
315  return (do_create) ? GNUNET_NO : GNUNET_OK;
316  }
317  /* give up */
318  return GNUNET_SYSERR;
319 }
320 
321 
332  const struct GNUNET_CONFIGURATION_Handle *cfg)
333 {
334  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
335  char *fn;
336 
337  if (GNUNET_OK !=
339  "PEER",
340  "PRIVATE_KEY",
341  &fn))
342  return NULL;
345  GNUNET_YES,
346  priv);
347  GNUNET_free (fn);
348  return priv;
349 }
350 
351 
360 int
362  struct GNUNET_PeerIdentity *dst)
363 {
364  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
365 
366  if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
367  {
369  _ ("Could not load peer's private key\n"));
370  return GNUNET_SYSERR;
371  }
373  &dst->public_key);
374  GNUNET_free (priv);
375  return GNUNET_OK;
376 }
377 
378 
387 void
388 GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
389 {
391  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
392 
394  (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
396  if (NULL != priv)
397  GNUNET_free (priv);
399 }
400 
401 
402 /* end of crypto_ecc_setup.c */
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static char * pkey
Public key of the zone to look in, in ASCII.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int GNUNET_CRYPTO_ecdsa_key_from_file(const char *filename, int do_create, struct GNUNET_CRYPTO_EcdsaPrivateKey *pkey)
Create a new private key by reading it from a file.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:684
#define GNUNET_new(type)
Allocate a struct or union of the given type.
Private ECC key encoded for transmission.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_CONFIGURATION_load(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Load configuration.
#define _(String)
GNU gettext support macro.
Definition: platform.h:184
static int atomic_write_to_file(const char *filename, const void *buf, size_t buf_size)
Write contents of buf atomically to filename.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static char * fn
Filename of the unique file.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
static char buf[2048]
static char * filename
int GNUNET_CRYPTO_eddsa_key_from_file(const char *filename, int do_create, struct GNUNET_CRYPTO_EddsaPrivateKey *pkey)
Create a new private key by reading it from a file.
void GNUNET_CRYPTO_eddsa_key_create(struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
Create a new private key.
Definition: crypto_ecc.c:544
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:193
Private ECC key encoded for transmission.
The identity of the host (wraps the signing key of the peer).
configuration data
Definition: configuration.c:84
void GNUNET_CRYPTO_ecdsa_key_create(struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
Create a new private key.
Definition: crypto_ecc.c:524
#define GNUNET_log(kind,...)
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...
static int read_from_file(const char *filename, void *buf, size_t buf_size)
Read file to buf.
#define GNUNET_free(ptr)
Wrapper around free.
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 (!).