Skip to content
Newer
Older
100644 391 lines (321 sloc) 7.91 KB
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
1 /*
2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
34165ed @bwalex first step to porting to linux; can be broken :)
authored Jul 20, 2011
29
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
30 #include <sys/types.h>
34165ed @bwalex first step to porting to linux; can be broken :)
authored Jul 20, 2011
31 #if defined(__DragonFly__)
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
32 #include <sys/diskslice.h>
34165ed @bwalex first step to porting to linux; can be broken :)
authored Jul 20, 2011
33 #elif defined(__linux__)
34 #include <linux/fs.h>
35 #include <sys/ioctl.h>
36 #endif
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
37 #include <sys/uio.h>
46f7fdb @bwalex add prompt timeout support
authored Jul 11, 2011
38 #include <sys/select.h>
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <termios.h>
45 #include <unistd.h>
46
1af29c1 @bwalex rename tc-play => tcplay
authored Jul 3, 2011
47 #include "tcplay.h"
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
48
49 void *
50 read_to_safe_mem(const char *file, off_t offset, size_t *sz)
51 {
52 void *mem = NULL;
345e21f @bwalex minor fixes
authored Jul 12, 2011
53 ssize_t r = 0;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
54 int fd;
55
56 if ((fd = open(file, O_RDONLY)) < 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
57 tc_log(1, "Error opening file %s\n", file);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
58 return NULL;
59 }
60
61 if ((mem = alloc_safe_mem(*sz)) == NULL) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
62 tc_log(1, "Error allocating memory\n");
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
63 goto out;
64 }
65
66 if ((lseek(fd, offset, SEEK_SET) < 0)) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
67 tc_log(1, "Error seeking on file %s\n", file);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
68 goto m_err;
69 }
70
71 if ((r = read(fd, mem, *sz)) <= 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
72 tc_log(1, "Error reading from file %s\n", file);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
73 goto m_err;
74 }
75
76 out:
77 *sz = r;
78 close(fd);
79 return mem;
80 /* NOT REACHED */
81
82 m_err:
83 free_safe_mem(mem);
84 close(fd);
85 return NULL;
86 }
87
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
88 static size_t get_random_total_bytes = 0;
89 static size_t get_random_read_bytes = 0;
90
91 static
92 void
93 get_random_summary(void)
94 {
95 float pct_done;
96
97 pct_done = (1.0 * get_random_read_bytes) /
98 (1.0 * get_random_total_bytes) * 100.0;
99 tc_log(0, "Gathering true randomness, %.0f%% done.\n", pct_done);
100 }
101
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
102 int
103 get_random(unsigned char *buf, size_t len)
104 {
105 int fd;
106 ssize_t r;
107 size_t rd = 0;
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
108 size_t sz;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
109 struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; /* 10 ms */
110
111
112 if ((fd = open("/dev/random", O_RDONLY)) < 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
113 tc_log(1, "Error opening /dev/random\n");
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
114 return -1;
115 }
116
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
117 summary_fn = get_random_summary;
118 get_random_total_bytes = len;
119
120 /* Get random data in 16-byte chunks */
121 sz = 16;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
122 while (rd < len) {
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
123 get_random_read_bytes = rd;
124
125 if ((len - rd) < sz)
126 sz = (len - rd);
127
128 if ((r = read(fd, buf+rd, sz)) < 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
129 tc_log(1, "Error reading from /dev/random\n");
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
130 close(fd);
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
131 summary_fn = NULL;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
132 return -1;
133 }
134 rd += r;
135 nanosleep(&ts, NULL);
136 }
137
138 close(fd);
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
139 summary_fn = NULL;
140
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
141 return 0;
142 }
143
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
144 static size_t secure_erase_total_bytes = 0;
145 static size_t secure_erase_erased_bytes = 0;
146
147 static
148 void
149 secure_erase_summary(void)
150 {
151 float pct_done;
152
153 pct_done = (1.0 * secure_erase_erased_bytes) /
154 (1.0 * secure_erase_total_bytes) * 100.0;
155 tc_log(0, "Securely erasing, %.0f%% done.\n", pct_done);
156 }
157
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
158 int
159 secure_erase(const char *dev, size_t bytes, size_t blksz)
160 {
161 size_t erased = 0;
162 int fd_rand, fd;
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
163 char buf[ERASE_BUFFER_SIZE];
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
164 ssize_t r, w;
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
165 size_t sz;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
166
167 if (blksz > MAX_BLKSZ) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
168 tc_log(1, "blksz > MAX_BLKSZ\n");
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
169 return -1;
170 }
171
172 if ((fd_rand = open("/dev/urandom", O_RDONLY)) < 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
173 tc_log(1, "Error opening /dev/urandom\n");
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
174 return -1;
175 }
176
177 if ((fd = open(dev, O_WRONLY)) < 0) {
178 close(fd_rand);
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
179 tc_log(1, "Error opening %s\n", dev);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
180 return -1;
181 }
182
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
183 summary_fn = secure_erase_summary;
184 secure_erase_total_bytes = bytes;
185
186 sz = ERASE_BUFFER_SIZE;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
187 while (erased < bytes) {
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
188 secure_erase_erased_bytes = erased;
189 /* Switch to block size when not much is remaining */
190 if ((bytes - erased) <= ERASE_BUFFER_SIZE)
191 sz = blksz;
192
193 if ((r = read(fd_rand, buf, sz)) < 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
194 tc_log(1, "Error reading from /dev/urandom\n");
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
195 close(fd);
196 close(fd_rand);
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
197 summary_fn = NULL;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
198 return -1;
199 }
200
0c6d6a0 @bwalex big warning cleanup
authored Jul 3, 2011
201 if (r < (ssize_t)blksz)
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
202 continue;
203
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
204 if ((w = write(fd, buf, r)) < 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
205 tc_log(1, "Error writing to %s\n", dev);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
206 close(fd);
207 close(fd_rand);
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
208 summary_fn = NULL;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
209 return -1;
210 }
211
212 erased += (size_t)w;
213 }
214
215 close(fd);
216 close(fd_rand);
217
69686eb @bwalex improve secure_erase speed; add SIGINFO support
authored Jul 3, 2011
218 summary_fn = NULL;
219
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
220 return 0;
221 }
222
34165ed @bwalex first step to porting to linux; can be broken :)
authored Jul 20, 2011
223 #if defined(__DragonFly__)
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
224 int
225 get_disk_info(const char *dev, size_t *blocks, size_t *bsize)
226 {
227 struct partinfo pinfo;
228 int fd;
229
230 if ((fd = open(dev, O_RDONLY)) < 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
231 tc_log(1, "Error opening %s\n", dev);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
232 return -1;
233 }
234
235 memset(&pinfo, 0, sizeof(struct partinfo));
236
237 if (ioctl(fd, DIOCGPART, &pinfo) < 0) {
238 close(fd);
239 return -1;
240 }
241
242 *blocks = pinfo.media_blocks;
243 *bsize = pinfo.media_blksize;
244
245 close(fd);
246 return 0;
247 }
34165ed @bwalex first step to porting to linux; can be broken :)
authored Jul 20, 2011
248 #elif defined(__linux__)
249 int
250 get_disk_info(const char *dev, size_t *blocks, size_t *bsize)
251 {
252 uint64_t nbytes;
253 int blocksz;
254 int fd;
255
256 if ((fd = open(dev, O_RDONLY)) < 0) {
257 tc_log(1, "Error opening %s\n", dev);
258 return -1;
259 }
260
261 if ((ioctl(fd, BLKSSZGET, &blocksz)) < 0) {
262 close(fd);
263 return -1;
264 }
265
266 if ((ioctl(fd, BLKGETSIZE64, &nbytes)) < 0) {
267 close(fd);
268 return -1;
269 }
270
271 *blocks = (size_t)(nbytes / blocksz);
272 *bsize = (size_t)(blocksz);
273
274 close(fd);
275 return 0;
276 }
277 #endif
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
278
279 int
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
280 write_to_disk(const char *dev, off_t offset, size_t blksz, void *mem,
0c6d6a0 @bwalex big warning cleanup
authored Jul 3, 2011
281 size_t bytes)
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
282 {
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
283 unsigned char *mem_buf = NULL;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
284 ssize_t w;
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
285 size_t sz;
286 off_t internal_off;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
287 int fd;
288
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
289 /* Align to block sizes */
290 internal_off = offset % blksz;
291 #ifdef DEBUG
292 printf("offset: %"PRIu64", internal offset: %"PRIu64"\n",
293 (uint64_t)offset, (uint64_t)internal_off);
294 #endif
295 offset = (offset/blksz) * blksz;
296
297 if ((internal_off + bytes) > blksz) {
298 tc_log(1, "This should never happen: internal_off + bytes > "
299 "blksz (write_to_disk)\n");
300 return -1;
301 }
302
303 if ((bytes < blksz) || (internal_off != 0)) {
304 sz = blksz;
305 if ((mem_buf = read_to_safe_mem(dev, offset, &sz)) == NULL) {
306 tc_log(1, "Error buffering data on "
307 "write_to_disk(%s)\n", dev);
308 return -1;
309 }
310
311 memcpy(mem_buf + internal_off, mem, bytes);
312 }
313
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
314 if ((fd = open(dev, O_WRONLY)) < 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
315 tc_log(1, "Error opening device %s\n", dev);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
316 return -1;
317 }
318
319 if ((lseek(fd, offset, SEEK_SET) < 0)) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
320 tc_log(1, "Error seeking on device %s\n", dev);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
321 close(fd);
322 return -1;
323 }
324
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
325 if ((w = write(fd, (mem_buf != NULL) ? mem_buf : mem, bytes)) <= 0) {
05bf0a1 @bwalex Start C API work
authored Jul 3, 2011
326 tc_log(1, "Error writing to device %s\n", dev);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
327 close(fd);
328 return -1;
329 }
330
331 close(fd);
92f96b8 @bwalex make blksz agnostic, fix volume size
authored Jul 22, 2011
332
333 if (mem_buf != NULL)
334 free_safe_mem(mem_buf);
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
335 return 0;
336 }
337
338 int
46f7fdb @bwalex add prompt timeout support
authored Jul 11, 2011
339 read_passphrase(const char *prompt, char *pass, size_t passlen, time_t timeout)
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
340 {
341 struct termios termios_old, termios_new;
46f7fdb @bwalex add prompt timeout support
authored Jul 11, 2011
342 struct timeval to;
343 fd_set fds;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
344 ssize_t n;
46f7fdb @bwalex add prompt timeout support
authored Jul 11, 2011
345 int fd, r = 0, cfd = 0, nready;
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
346
347 if ((fd = open("/dev/tty", O_RDONLY)) == -1) {
348 fd = STDIN_FILENO;
349 cfd = 1;
350 }
351
352 printf(prompt);
353 fflush(stdout);
354
355 memset(pass, 0, passlen);
356
357 tcgetattr(fd, &termios_old);
358 memcpy(&termios_new, &termios_old, sizeof(termios_new));
359 termios_new.c_lflag &= ~ECHO;
360 tcsetattr(fd, TCSAFLUSH, &termios_new);
361
46f7fdb @bwalex add prompt timeout support
authored Jul 11, 2011
362 if (timeout > 0) {
363 memset(&to, 0, sizeof(to));
364 to.tv_sec = timeout;
365
366 FD_ZERO(&fds);
367 FD_SET(fd, &fds);
368 nready = select(fd + 1, &fds, NULL, NULL, &to);
369 if (nready <= 0) {
370 r = EINTR;
371 goto out;
372 }
373 }
374
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
375 n = read(fd, pass, passlen-1);
376 if (n > 0) {
377 pass[n-1] = '\0'; /* Strip trailing \n */
378 } else {
379 r = EIO;
380 }
381
46f7fdb @bwalex add prompt timeout support
authored Jul 11, 2011
382 out:
dedd95c @bwalex major refactoring, bugfixes
authored May 17, 2011
383 if (cfd)
384 close(fd);
385
386 tcsetattr(fd, TCSAFLUSH, &termios_old);
387 putchar('\n');
388
389 return r;
390 }
Something went wrong with that request. Please try again.