/[winpt]/trunk/PTD/wptWipeFile.cpp
ViewVC logotype

Annotation of /trunk/PTD/wptWipeFile.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 46 - (hide annotations)
Fri Oct 28 12:57:05 2005 UTC (19 years, 4 months ago) by werner
File size: 10188 byte(s)
Second set of changes to use autotools for building.
1 werner 46 /* wptWipeFile.cpp - Secure file removal
2     * Copyright (C) 2001-2005 Timo Schulz
3     * Copyright (C) 2000 Matt Gauthier
4     *
5     * WinPT software; you can redistribute it and/or modify
6     * it under the terms of the GNU General Public License as published by
7     * the Free Software Foundation; either version 2 of the License, or
8     * (at your option) any later version.
9     *
10     * WinPT is distributed in the hope that it will be useful,
11     * but WITHOUT ANY WARRANTY; without even the implied warranty of
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     * GNU General Public License for more details.
14     *
15     * You should have received a copy of the GNU General Public License
16     * along with WinPT; if not, write to the Free Software
17     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18     *
19     **************************************************************************
20     * This code based on the sunlink.c file from the SRM project, but *
21     * it was heavily modified to work with W32 and with added GCRYPT *
22     * support for gathering random bytes. *
23     * *
24     * The original code was placed under the GNU Lesser Public License, *
25     * even so I decide to put this file under the GNU General Public License.*
26     **************************************************************************
27     */
28    
29     #ifdef HAVE_CONFIG_H
30     #include <config.h>
31     #endif
32    
33     #include <windows.h>
34     #include <windows.h>
35     #include <stdio.h>
36     #include <stdlib.h>
37     #include <sys/stat.h>
38     #include <string.h>
39     #include <ctype.h>
40     #include <direct.h>
41    
42     #include "openpgp.h"
43     #include "wptW32API.h"
44     #include "wptErrors.h"
45     #include "wptTypes.h"
46     #include "wptCrypto.h"
47    
48     typedef unsigned __int64 DDWORD;
49    
50     typedef struct {
51     HANDLE fd;
52     DDWORD filesize;
53     DDWORD offset;
54     BYTE *buffer;
55     DWORD buffsize;
56     const char *name;
57     int n_passes;
58     } wipe_context_s;
59    
60    
61     void (*progress_cb) (void *, DDWORD, DDWORD);
62     static void *progress_cb_value = NULL;
63    
64     void (*unlink_cb)(void *, const char *, int, int, int) = NULL;
65     static void *unlink_cb_value = NULL;
66    
67     /* Use the file handle in the context to overwrite a file
68     with prepared buffer contents. */
69     static void
70     overwrite (wipe_context_s *ctx)
71     {
72     DDWORD blocks = 0, mod = 0;
73     DWORD nwritten = 0;
74     LONG size_high = 0;
75    
76     blocks = ctx->filesize / ctx->buffsize;
77     mod = ctx->filesize % ctx->buffsize;
78     SetFilePointer (ctx->fd, 0, &size_high, FILE_BEGIN);
79     while (blocks--) {
80     if (!WriteFile (ctx->fd, ctx->buffer, ctx->buffsize, &nwritten, NULL))
81     break;
82     ctx->offset += nwritten;
83     if (unlink_cb)
84     unlink_cb (unlink_cb_value, ctx->name, 0, (unsigned)ctx->offset,
85     (unsigned)ctx->filesize*ctx->n_passes);
86     }
87     if (mod) {
88     WriteFile (ctx->fd, ctx->buffer, (DWORD)mod, &nwritten, NULL);
89     ctx->offset += nwritten;
90     if (unlink_cb)
91     unlink_cb (unlink_cb_value, ctx->name, 0, (unsigned)ctx->offset,
92     (unsigned)ctx->filesize*ctx->n_passes);
93     }
94     FlushFileBuffers (ctx->fd);
95     SetFilePointer (ctx->fd, 0, &size_high, FILE_BEGIN);
96     }
97    
98    
99     /* fill the buffer with random of the given level. */
100     static void
101     randomize_buffer (byte *buf, size_t bufsize, int level)
102     {
103     const int blocksize = 512;
104     int blocks = bufsize / blocksize;
105     int mod = bufsize % blocksize;
106    
107     while (blocks--) {
108     gpg_randomize (buf, blocksize, level);
109     buf += blocksize;
110     }
111     if (mod)
112     gpg_randomize (buf, mod, level);
113     }
114    
115    
116     /* performs a random overwrite. */
117     static void
118     overwrite_random (int npasses, wipe_context_s * ctx)
119     {
120     int i;
121    
122     for (i = 0; i < npasses; i++) {
123     randomize_buffer (ctx->buffer, ctx->buffsize, 0);
124     overwrite (ctx);
125     }
126     }
127    
128    
129     /* perform an overwrite with a specific byte (like 0x00). */
130     static void
131     overwrite_byte (int byte, wipe_context_s * ctx)
132     {
133     memset (ctx->buffer, byte, ctx->buffsize);
134     overwrite (ctx);
135     } /* overwrite_byte */
136    
137    
138     /* perform an overwrite with a specific byte triple (like 0x00, 0xFF, 0xAA). */
139     static void
140     overwrite_bytes (int byte1, int byte2, int byte3, wipe_context_s * ctx)
141     {
142     DWORD i;
143    
144     memset (ctx->buffer, byte1, ctx->buffsize);
145     for (i = 1; i < ctx->buffsize; i += 3) {
146     ctx->buffer[i] = byte2;
147     ctx->buffer[i+1] = byte3;
148     }
149     overwrite (ctx);
150     } /* overwrite_bytes */
151    
152    
153     /* For the case the file is not a regular file (this is true for
154     devices or directories) this function tries to rename the file
155     to random pattern and then it will be delete (without random!). */
156     extern "C" int
157     rename_unlink (const char *path)
158     {
159     struct stat statbuf;
160     char *new_name = NULL, *p = NULL, c;
161     int i = 0, rc = 0;
162     int is_dir = 0;
163    
164     if (GetFileAttributes (path) & FILE_ATTRIBUTE_DIRECTORY)
165     is_dir = 1;
166    
167     new_name = new char[strlen (path)+15];
168     if (!new_name)
169     BUG (0);
170    
171     strcpy (new_name, path);
172     p = strrchr (new_name, '\\');
173     if (p != NULL) {
174     p++;
175     *p = '\0';
176     }
177     else
178     p = new_name;
179     do {
180     while (i < 14) {
181     c = gpg_random_char (1);
182     *p = c;
183     p++;
184     i++;
185     }
186     *p = '\0';
187     } while (stat (new_name, &statbuf) == 0);
188    
189     if (rename (path, new_name) == -1) {
190     rc = WPTERR_FILE_READ;
191     goto leave;
192     }
193     if (is_dir && RemoveDirectory (new_name) == FALSE)
194     rc = WPTERR_FILE_REMOVE;
195     else if (!DeleteFile (new_name))
196     rc = WPTERR_FILE_REMOVE;
197    
198     leave:
199     free_if_alloc (new_name);
200     return rc;
201     }
202    
203    
204     /* return the filesize as an 64-bit integer. */
205     static __int64
206     GetFileSize64 (const char * path)
207     {
208     FILE *fp = fopen (path, "r");
209     if (fp) {
210     struct _stati64 statbuf;
211     if (_fstati64 (fileno (fp), &statbuf) == -1)
212     return -1;
213     fclose (fp);
214     return statbuf.st_size;
215     }
216     return -1;
217     }
218    
219    
220     static int
221     _secure_unlink (const char * path, int mode, HANDLE *r_fd)
222     {
223     wipe_context_s ctx;
224     LONG size_high = 0;
225    
226     if (GetFileAttributes (path) & FILE_ATTRIBUTE_DIRECTORY)
227     return rename_unlink (path);
228    
229     memset (&ctx, 0, sizeof (ctx));
230     ctx.name = path;
231     ctx.buffsize = 16384;
232     ctx.buffer = new byte[ctx.buffsize];
233     if (!ctx.buffer)
234     BUG (0);
235    
236     ctx.filesize = GetFileSize64 (path);
237     if (!ctx.filesize) {
238     free_if_alloc (ctx.buffer);
239     unlink (path);
240     return 0;
241     }
242    
243     ctx.fd = CreateFile (path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
244     OPEN_ALWAYS, 0, NULL);
245     if (ctx.fd == INVALID_HANDLE_VALUE) {
246     free_if_alloc (ctx.buffer);
247     return WPTERR_FILE_OPEN;
248     }
249     else if (r_fd)
250     *r_fd = ctx.fd;
251    
252     gpg_quick_random_gen (1);
253     if (unlink_cb)
254     unlink_cb (unlink_cb_value, ctx.name, 0, 0, 0);
255    
256     switch (mode) {
257     case WIPE_MODE_FAST:
258     ctx.n_passes = 1;
259     overwrite_random (1, &ctx);
260     break;
261    
262     case WIPE_MODE_SIMPLE:
263     ctx.n_passes = 2;
264     overwrite_random (2, &ctx);
265     break;
266    
267     case WIPE_MODE_DOD:
268     ctx.n_passes = 5;
269     overwrite_random (1, &ctx);
270     overwrite_byte ((~1) & 0xFF, &ctx);
271     overwrite_random (1, &ctx);
272     overwrite_byte ((~4) & 0xFF, &ctx);
273     overwrite_random (1, &ctx);
274     break;
275    
276     case WIPE_MODE_GUTMANN:
277     ctx.n_passes = 39;
278     overwrite_random (4, &ctx);
279     overwrite_byte( 0x55, &ctx );
280     overwrite_byte ( 0xAA, &ctx );
281     overwrite_bytes( 0x92, 0x49, 0x24, &ctx );
282     overwrite_bytes( 0x49, 0x24, 0x92, &ctx );
283     overwrite_bytes( 0x24, 0x92, 0x49, &ctx );
284     overwrite_byte( 0x00, &ctx );
285     overwrite_byte( 0x11, &ctx );
286     overwrite_byte( 0x22, &ctx );
287     overwrite_byte( 0x33, &ctx );
288     overwrite_byte( 0x44, &ctx );
289     overwrite_byte( 0x55, &ctx );
290     overwrite_byte( 0x66, &ctx );
291     overwrite_byte( 0x77, &ctx );
292     overwrite_byte( 0x88, &ctx );
293     overwrite_byte( 0x99, &ctx );
294     overwrite_byte( 0xAA, &ctx );
295     overwrite_byte( 0xBB, &ctx );
296     overwrite_byte( 0xCC, &ctx );
297     overwrite_byte( 0xDD, &ctx );
298     overwrite_byte( 0xEE, &ctx );
299     overwrite_byte( 0xFF, &ctx );
300     overwrite_bytes( 0x92, 0x49, 0x24, &ctx );
301     overwrite_bytes( 0x49, 0x24, 0x92, &ctx );
302     overwrite_bytes( 0x24, 0x92, 0x49, &ctx );
303     overwrite_bytes( 0x6D, 0xB6, 0xDB, &ctx );
304     overwrite_bytes( 0xB6, 0xDB, 0x6D, &ctx );
305     overwrite_bytes( 0xDB, 0x6D, 0xB6, &ctx );
306     overwrite_random( 4, &ctx );
307     break;
308     }
309    
310     /* Set file length to zero so allocated clusters cannot be trailed */
311     SetFilePointer (ctx.fd, 0, &size_high, FILE_BEGIN);
312     SetEndOfFile (ctx.fd);
313     CloseHandle (ctx.fd);
314    
315     memset (ctx.buffer, 0, ctx.buffsize); /* burn the last evidence */
316     free_if_alloc (ctx.buffer);
317    
318     return rename_unlink (path);
319     }
320    
321    
322     /* Delete a file in a secure way with the given mode. */
323     extern "C" int
324     secure_unlink (const char *path, int mode)
325     {
326     return _secure_unlink (path, mode, NULL);
327     }
328    
329    
330     /* Set the callback @cb for the wipe function. The callback is call every time
331     the wipe function writes data to the file. */
332     extern "C" void
333     secure_unlink_set_cb (void (*cb)(void *, const char *, int, int, int),
334     void *cb_value)
335     {
336     unlink_cb = cb;
337     unlink_cb_value = cb_value;
338     }
339    
340    
341     /* wipe all free space of the given drive by creating a temp file
342     which has the size of the free space. This file will be then
343     overwritten with random and static pattern. */
344     extern "C" int
345     wipe_freespace (const char * drive, HANDLE *r_fd,
346     void (*cb)(void *, DDWORD, DDWORD), void * cb_value)
347     {
348     ULARGE_INTEGER caller, total, frees;
349     LONG hpart=0;
350     HANDLE fd;
351     int disktyp = GetDriveType (drive);
352     int rc;
353     char * file;
354    
355     if (disktyp != DRIVE_FIXED && disktyp != DRIVE_REMOVABLE)
356     return -1;
357     if (!GetDiskFreeSpaceEx (drive, &caller, &total, &frees))
358     return -1;
359    
360     /* disk is full */
361     if (!frees.LowPart)
362     return 0;
363     file = new char[strlen (drive)+8];
364     if (!file)
365     BUG (0);
366     sprintf (file, "%stemp_winpt.tmp", drive);
367     fd = CreateFile (file,
368     GENERIC_READ|GENERIC_WRITE,
369     FILE_SHARE_READ|FILE_SHARE_WRITE,
370     NULL, CREATE_ALWAYS, 0, NULL);
371     if (fd == INVALID_HANDLE_VALUE) {
372     free_if_alloc (file);
373     return WPTERR_FILE_OPEN;
374     }
375     hpart = frees.HighPart;
376     SetFilePointer (fd, frees.LowPart, &hpart, FILE_BEGIN);
377     SetEndOfFile (fd);
378     CloseHandle (fd);
379    
380     if (cb && cb_value) {
381     progress_cb = cb;
382     progress_cb_value = cb_value;
383     }
384     rc = _secure_unlink (file, WIPE_MODE_FAST, r_fd);
385     free_if_alloc (file);
386     return rc;
387     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26