1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of gsignond
6 * Copyright (C) 2013 Intel Corporation.
8 * Contact: Jussi Laako <jussi.laako@linux.intel.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
33 #include "gsignond/gsignond-utils.h"
34 #include "gsignond/gsignond-log.h"
37 * SECTION:gsignond-utils
38 * @title: Utility functions
39 * @short_description: miscellaneous utility functions
40 * @include: gsignond/gsignond-utils.h
42 * Miscellaneous utility functions are described below.
45 typedef struct __nonce_ctx_t
53 static size_t pagesize = 0;
54 static _nonce_ctx_t _nonce_ctx = { 0, };
55 G_LOCK_DEFINE_STATIC (_nonce_lock);
59 * @filename: filename to wipe
61 * This function securely wipes the contents of the file, by overwriting it with
62 * 0's, then 1's, then random data. The file is then removed.
64 * Returns: TRUE if wiping and removal was successful.
67 gsignond_wipe_file (const gchar *filename)
69 gboolean retval = FALSE;
79 long confval = sysconf (_SC_PAGE_SIZE);
82 pagesize = (size_t) confval;
85 rngfd = open ("/dev/urandom", O_RDONLY);
89 wipefd = open (filename, O_WRONLY | O_SYNC);
92 wipebuf = g_malloc (pagesize);
93 if (fstat (wipefd, &filestat))
97 sizeleft = filestat.st_size;
98 memset (wipebuf, 0xff, pagesize);
100 writesize = (sizeleft < pagesize) ? sizeleft : pagesize;
101 sizewritten = write (wipefd, wipebuf, writesize);
102 if (sizewritten != (ssize_t) writesize)
104 sizeleft -= sizewritten;
107 if (lseek (wipefd, 0, SEEK_SET) == (off_t) -1)
111 sizeleft = filestat.st_size;
112 memset (wipebuf, 0x00, pagesize);
114 writesize = (sizeleft < pagesize) ? sizeleft : pagesize;
115 sizewritten = write (wipefd, wipebuf, writesize);
116 if (sizewritten != (ssize_t) writesize)
118 sizeleft -= sizewritten;
121 if (lseek (wipefd, 0, SEEK_SET) == (off_t) -1)
125 sizeleft = filestat.st_size;
127 writesize = (sizeleft < pagesize) ? sizeleft : pagesize;
128 if (read (rngfd, wipebuf, writesize) != (ssize_t) writesize)
130 sizewritten = write (wipefd, wipebuf, writesize);
131 if (sizewritten != (ssize_t) writesize)
133 sizeleft -= sizewritten;
136 /* don't leave traces of last pattern to the memory */
137 memset (wipebuf, 0x00, pagesize);
139 /* remove the file and set return value on success */
140 if (unlink (filename) == 0) {
142 DBG ("successfully wiped file %s", filename);
154 * gsignond_wipe_directory:
155 * @dirname: directory to wipe
157 * This function securely wipes the contents of the directory by calling
158 * gsignond_wipe_file() on each file. It also removes links and empty directories but
159 * does not recursively wipe them.
161 * Returns: TRUE if wiping and removal was successful.
164 gsignond_wipe_directory (const gchar *dirname)
166 gboolean retval = FALSE;
168 const gchar *filename;
171 struct stat stat_entry;
173 DBG ("wipe directory %s", dirname);
174 dirctx = g_dir_open (dirname, 0, NULL);
177 while ((filename = g_dir_read_name (dirctx))) {
178 filepath = g_build_filename (dirname, filename, NULL);
179 if (lstat(filepath, &stat_entry))
181 if (S_ISDIR (stat_entry.st_mode) ||
182 S_ISLNK (stat_entry.st_mode)) {
183 DBG ("remove directory or link %s", filepath);
184 wiperes = (remove (filepath) == 0);
186 DBG ("wipe file %s", filepath);
187 wiperes = gsignond_wipe_file (filepath);
196 g_dir_close (dirctx);
203 if (G_LIKELY(_nonce_ctx.initialized))
208 fd = open ("/dev/urandom", O_RDONLY);
211 if (read (fd, _nonce_ctx.key, sizeof (_nonce_ctx.key)) !=
212 sizeof (_nonce_ctx.key))
214 if (read (fd, _nonce_ctx.entropy, sizeof(_nonce_ctx.entropy)) !=
215 sizeof (_nonce_ctx.entropy))
218 _nonce_ctx.serial = 0;
220 _nonce_ctx.initialized = TRUE;
226 return _nonce_ctx.initialized;
230 * gsignond_generate_nonce:
232 * This function generates a random secure nonce using SHA1 HMAC.
234 * Returns: (transfer full): the nonce in lowercase hexadecimal format, 40 bytes long.
237 gsignond_generate_nonce ()
243 G_LOCK (_nonce_lock);
245 if (G_UNLIKELY (!_init_nonce_gen()))
248 hmac = g_hmac_new (G_CHECKSUM_SHA1,
249 _nonce_ctx.key, sizeof (_nonce_ctx.key));
250 g_hmac_update (hmac, _nonce_ctx.entropy, sizeof (_nonce_ctx.entropy));
253 (const guchar *) &_nonce_ctx.serial,
254 sizeof (_nonce_ctx.serial));
255 if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
256 g_hmac_update (hmac, (const guchar *) &ts, sizeof (ts));
257 memset (&ts, 0x00, sizeof(ts));
258 nonce = g_strdup (g_hmac_get_string (hmac));
262 G_UNLOCK (_nonce_lock);