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

Diff of /trunk/PTD/wptWipeFile.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 55 by twoaday, Wed Nov 2 09:31:16 2005 UTC revision 273 by twoaday, Fri Dec 8 10:22:17 2006 UTC
# Line 1  Line 1 
1  /* wptWipeFile.cpp - Secure file removal  /* wptWipeFile.cpp - Secure file removal
2   *      Copyright (C) 2001-2005 Timo Schulz   *      Copyright (C) 2001-2006 Timo Schulz
3   *      Copyright (C) 2000 Matt Gauthier   *      Copyright (C) 2000 Matt Gauthier
4   *   *
5     * (This code based on the sunlink.c file from the SRM project)
6     *
7   * WinPT software; you can redistribute it and/or modify   * WinPT software; you can redistribute it and/or modify
8   * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
9   * the Free Software Foundation; either version 2 of the License, or   * the Free Software Foundation; either version 2 of the License, or
# Line 15  Line 17 
17   * You should have received a copy of the GNU General Public License   * You should have received a copy of the GNU General Public License
18   * along with WinPT; if not, write to the Free Software   * along with WinPT; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  *  
  **************************************************************************  
  * This code based on the sunlink.c file from the SRM project, but        *  
  * it was heavily modified to work with W32 and with added GCRYPT         *  
  * support for gathering random bytes.                                    *  
  *                                                                        *  
  * The original code was placed under the GNU Lesser Public License,      *  
  * even so I decide to put this file under the GNU General Public License.*  
  **************************************************************************  
20   */   */
   
21  #ifdef HAVE_CONFIG_H  #ifdef HAVE_CONFIG_H
22  #include <config.h>  #include <config.h>
23  #endif  #endif
# Line 38  Line 30 
30  #include <ctype.h>  #include <ctype.h>
31  #include <direct.h>  #include <direct.h>
32    
 #include "openpgp.h"  
33  #include "wptW32API.h"  #include "wptW32API.h"
34  #include "wptErrors.h"  #include "wptErrors.h"
35  #include "wptTypes.h"  #include "wptTypes.h"
36  #include "wptCrypto.h"  
37    /* WARNING: Because modern file systems, for example NTFS, use a lot of
38                features to provide better performance and journaling to recover
39                the FS after a crash, secure file deleting is extremly
40                difficult. It can happen that parts of the file are still in
41                plaintext after wiping the file. To avoid information leakage,
42                it is recommend to wipe the free space of the disk to destroy
43                left over pattern. */
44    
45  #ifdef _MSC_VER  #ifdef _MSC_VER
46  typedef unsigned __int64 DDWORD;  typedef unsigned __int64 DDWORD;
# Line 51  typedef unsigned long long DDWORD; Line 49  typedef unsigned long long DDWORD;
49  #endif  #endif
50    
51  typedef struct {  typedef struct {
52      HANDLE fd;      HANDLE fd;          /* file descriptor. */
53      DDWORD filesize;      DDWORD filesize;    /* file size of the file. */
54      DDWORD offset;      DDWORD offset;
55      BYTE  *buffer;      BYTE  *buffer;
56      DWORD  buffsize;      DWORD  buffsize;
# Line 60  typedef struct { Line 58  typedef struct {
58      int    n_passes;      int    n_passes;
59  } wipe_context_s;  } wipe_context_s;
60    
61    #define SBOX_SIZE 256
62  struct arcfour_s {  struct arcfour_s {
63      BYTE *seed;      BYTE *seed;
64      int  pos;      int  pos;
65      BYTE sbox[256];      BYTE sbox[SBOX_SIZE];
66      DWORD i;      DWORD i;
67      DWORD j;      DWORD j;
68  };  };
# Line 83  static struct arcfour_s rnd; Line 82  static struct arcfour_s rnd;
82     into the seed @seed. The seed length (256) used to     into the seed @seed. The seed length (256) used to
83     emulate a circular movment. */     emulate a circular movment. */
84  static void  static void
85  add_random (unsigned char *seed, int *seed_pos,  add_random (BYTE *seed, int *seed_pos, BYTE *buf, int buf_len)
             unsigned char *buf, int buf_len)  
86  {  {
87      int i, s_pos = *seed_pos;      int i, s_pos = *seed_pos;
88    
89      for (i=0; i < buf_len; i++)      for (i=0; i < buf_len; i++)
90          seed[(s_pos++ % 256)] ^= buf[i];          seed[(s_pos++ % SBOX_SIZE)] ^= buf[i];
91      *seed_pos = s_pos % 256;      *seed_pos = s_pos % SBOX_SIZE;
92  }  }
93    
94    
# Line 106  child_proc (HWND h, LPARAM l) Line 104  child_proc (HWND h, LPARAM l)
104      char buf[256];      char buf[256];
105      int n;      int n;
106    
107      n  = GetWindowText (h, buf, 255);      n  = GetWindowText (h, buf, DIM (buf)-1);
108      if (n > 0)      if (n > 0)
109          add_random (cb->seed, &cb->pos, (BYTE*)buf, n);          add_random (cb->seed, &cb->pos, (BYTE*)buf, n);
110      add_random (cb->seed, &cb->pos, (BYTE*)&a, 4);      add_random (cb->seed, &cb->pos, (BYTE*)&a, 4);
# Line 193  init_arcfour (struct arcfour_s *ctx, BYT Line 191  init_arcfour (struct arcfour_s *ctx, BYT
191    
192      ctx->i = 0;      ctx->i = 0;
193      ctx->j = 0;      ctx->j = 0;
194      for (ctx->i=0; ctx->i < 256; ctx->i++)      for (ctx->i=0; ctx->i < SBOX_SIZE; ctx->i++)
195          ctx->sbox[ctx->i] = (BYTE)ctx->i;          ctx->sbox[ctx->i] = (BYTE)ctx->i;
196      for (ctx->i=0; ctx->i < 256; ctx->i++) {      for (ctx->i=0; ctx->i < SBOX_SIZE; ctx->i++) {
197          ctx->j += (ctx->j+ctx->sbox[ctx->i]+key[ctx->i]);          ctx->j += (ctx->j+ctx->sbox[ctx->i]+key[ctx->i]);
198          ctx->j &= 255;          ctx->j &= 255;
199          t = ctx->sbox[ctx->i];          t = ctx->sbox[ctx->i];
# Line 214  rnd_byte (void) Line 212  rnd_byte (void)
212      BYTE t;      BYTE t;
213    
214      if (!init_done) {      if (!init_done) {
215          BYTE buf[256];          BYTE buf[SBOX_SIZE];
216    
217          init_random (buf);          init_random (buf);
218          init_arcfour (ctx, buf);          init_arcfour (ctx, buf);
219          init_done = 1;          init_done = 1;
# Line 233  rnd_byte (void) Line 232  rnd_byte (void)
232  static char  static char
233  random_char (void)  random_char (void)
234  {        {      
235      byte c = 0;      BYTE c = 0;
236    
237      while  (!isalnum(c))      while  (!isalnum ((int)c))
238          c = rnd_byte ();          c = rnd_byte ();
239      return c % 127;      return c % 127;
240  }  }
241    
242    
# Line 275  overwrite (wipe_context_s *ctx) Line 274  overwrite (wipe_context_s *ctx)
274    
275  /* fill the buffer with random of the given level. */  /* fill the buffer with random of the given level. */
276  static void  static void
277  randomize_buffer (byte *buf, size_t bufsize)  randomize_buffer (BYTE *buf, size_t bufsize)
278  {  {
279      const int blocksize = 512;      const int blocksize = 512;
280      int blocks = bufsize / blocksize;      int blocks = bufsize / blocksize;
# Line 311  overwrite_byte (int byte, wipe_context_s Line 310  overwrite_byte (int byte, wipe_context_s
310  {  {
311      memset (ctx->buffer, byte, ctx->buffsize);      memset (ctx->buffer, byte, ctx->buffsize);
312      overwrite (ctx);      overwrite (ctx);
313  } /* overwrite_byte */  }
314    
315    
316  /* perform an overwrite with a specific byte triple (like 0x00, 0xFF, 0xAA). */  /* perform an overwrite with a specific byte triple (like 0x00, 0xFF, 0xAA). */
# Line 326  overwrite_bytes (int byte1, int byte2, i Line 325  overwrite_bytes (int byte1, int byte2, i
325          ctx->buffer[i+1] = byte3;          ctx->buffer[i+1] = byte3;
326      }      }
327      overwrite (ctx);      overwrite (ctx);
328  } /* overwrite_bytes */  }
329    
330    
331  /* For the case the file is not a regular file (this is true for  /* For the case the file is not a regular file (this is true for
# Line 397  GetFileSize64 (const char * path) Line 396  GetFileSize64 (const char * path)
396    
397    
398  static int  static int
399  _secure_unlink (const char * path, int mode, HANDLE *r_fd)  _secure_unlink (const char *path, const int mode,
400                    const int passes, HANDLE *r_fd)
401  {  {
402      wipe_context_s ctx;      wipe_context_s ctx;
403      LONG size_high = 0;      LONG size_high = 0;
# Line 408  _secure_unlink (const char * path, int m Line 408  _secure_unlink (const char * path, int m
408      memset (&ctx, 0, sizeof (ctx));      memset (&ctx, 0, sizeof (ctx));
409      ctx.name = path;      ctx.name = path;
410      ctx.buffsize = 16384;      ctx.buffsize = 16384;
411      ctx.buffer = new byte[ctx.buffsize];      ctx.buffer = new BYTE[ctx.buffsize];
412      if (!ctx.buffer)      if (!ctx.buffer)
413          BUG (0);          BUG (NULL);
414            
415      ctx.filesize = GetFileSize64 (path);      ctx.filesize = GetFileSize64 (path);
416      if (!ctx.filesize) {      if (!ctx.filesize) {
417          free_if_alloc (ctx.buffer);          free_if_alloc (ctx.buffer);
418          unlink (path);          remove (path);
419          return 0;          return 0;
420      }      }
421    
# Line 423  _secure_unlink (const char * path, int m Line 423  _secure_unlink (const char * path, int m
423                           OPEN_ALWAYS, 0, NULL);                           OPEN_ALWAYS, 0, NULL);
424      if (ctx.fd == INVALID_HANDLE_VALUE) {      if (ctx.fd == INVALID_HANDLE_VALUE) {
425          free_if_alloc (ctx.buffer);          free_if_alloc (ctx.buffer);
426          return WPTERR_FILE_OPEN;          return WPTERR_FILE_CREAT;
427      }      }
428      else if (r_fd)      else if (r_fd)
429          *r_fd = ctx.fd;          *r_fd = ctx.fd;
# Line 432  _secure_unlink (const char * path, int m Line 432  _secure_unlink (const char * path, int m
432          unlink_cb (unlink_cb_value, ctx.name, 0, 0, 0);          unlink_cb (unlink_cb_value, ctx.name, 0, 0, 0);
433    
434      switch (mode) {      switch (mode) {
435        case WIPE_MODE_PASSES:
436            ctx.n_passes = passes;
437            overwrite_random (passes, &ctx);
438            break;
439    
440      case WIPE_MODE_FAST:      case WIPE_MODE_FAST:
441          ctx.n_passes = 1;          ctx.n_passes = 1;
442          overwrite_random (1, &ctx);          overwrite_random (1, &ctx);
# Line 490  _secure_unlink (const char * path, int m Line 495  _secure_unlink (const char * path, int m
495      SetEndOfFile (ctx.fd);      SetEndOfFile (ctx.fd);
496      CloseHandle (ctx.fd);      CloseHandle (ctx.fd);
497            
498      memset (ctx.buffer, 0, ctx.buffsize); /* burn the last evidence */        wipememory (ctx.buffer, ctx.buffsize); /* burn the last evidence */
499      free_if_alloc (ctx.buffer);      free_if_alloc (ctx.buffer);
500    
501      return rename_unlink (path);      return rename_unlink (path);
502  }  }
503    
504    
505  /* Delete a file in a secure way with the given mode @mode. */  /* Try to delete a file in a secure way with the given mode @mode. */
506  extern "C" int  extern "C" int
507  secure_unlink (const char *path, int mode)  secure_unlink (const char *path, const int mode, const int passes)
508  {  {
509      /* If the file has one of the following attributes, the      /* If the file has one of the following attributes, the
510         chance the file really gets overwritten is very low so         chance the file really gets overwritten is very low so
# Line 509  secure_unlink (const char *path, int mod Line 514  secure_unlink (const char *path, int mod
514          (attr & FILE_ATTRIBUTE_ENCRYPTED) ||          (attr & FILE_ATTRIBUTE_ENCRYPTED) ||
515          (attr & FILE_ATTRIBUTE_SPARSE_FILE))          (attr & FILE_ATTRIBUTE_SPARSE_FILE))
516          return DeleteFile (path); /* XXX */          return DeleteFile (path); /* XXX */
517      return _secure_unlink (path, mode, NULL);      return _secure_unlink (path, mode, passes, NULL);
518  }  }
519    
520    
# Line 528  secure_unlink_set_cb (void (*cb)(void *, Line 533  secure_unlink_set_cb (void (*cb)(void *,
533     which has the size of the free space. This file will be then     which has the size of the free space. This file will be then
534     overwritten with random and static pattern. */     overwritten with random and static pattern. */
535  extern "C" int  extern "C" int
536  wipe_freespace (const char * drive, HANDLE *r_fd,  wipe_freespace (const char *drive, HANDLE *r_fd,
537                  void (*cb)(void *, DDWORD, DDWORD), void * cb_value)                  void (*cb)(void *, DDWORD, DDWORD), void * cb_value)
538  {  {
539      ULARGE_INTEGER caller, total, frees;      ULARGE_INTEGER caller, total, frees;
540      LONG hpart=0;      LONG hpart=0;
541      HANDLE fd;      HANDLE fd;
542        const char *fmt;
543        char *file;
544      int disktyp = GetDriveType (drive);      int disktyp = GetDriveType (drive);
545      int rc;      int rc;
     char * file;  
546    
547        /* XXX: needs to be modernized or better extracted to a separate
548                program module. */
549      if (disktyp != DRIVE_FIXED && disktyp != DRIVE_REMOVABLE)      if (disktyp != DRIVE_FIXED && disktyp != DRIVE_REMOVABLE)
550          return -1;          return -1;
551      if (!GetDiskFreeSpaceEx (drive, &caller, &total, &frees))      if (!GetDiskFreeSpaceEx (drive, &caller, &total, &frees))
# Line 546  wipe_freespace (const char * drive, HAND Line 554  wipe_freespace (const char * drive, HAND
554      /* disk is full */      /* disk is full */
555      if (!frees.LowPart)      if (!frees.LowPart)
556          return 0;          return 0;
557      file = new char[strlen (drive)+8];      fmt = "%stemp_winpt.tmp";
558        file = new char[strlen (drive)+strlen (fmt)+8+1];
559      if (!file)      if (!file)
560          BUG (0);          BUG (0);
561      sprintf (file, "%stemp_winpt.tmp", drive);      sprintf (file, fmt, drive);
562      fd = CreateFile (file,      fd = CreateFile (file,
563                      GENERIC_READ|GENERIC_WRITE,                       GENERIC_READ|GENERIC_WRITE,
564                      FILE_SHARE_READ|FILE_SHARE_WRITE,                       FILE_SHARE_READ|FILE_SHARE_WRITE,
565                      NULL, CREATE_ALWAYS, 0, NULL);                       NULL, CREATE_ALWAYS, 0, NULL);
566      if (fd == INVALID_HANDLE_VALUE) {      if (fd == INVALID_HANDLE_VALUE) {
567          free_if_alloc (file);          free_if_alloc (file);
568          return WPTERR_FILE_OPEN;          return WPTERR_FILE_CREAT;
569      }      }
570      hpart = frees.HighPart;      hpart = frees.HighPart;
571      SetFilePointer (fd, frees.LowPart, &hpart, FILE_BEGIN);      SetFilePointer (fd, frees.LowPart, &hpart, FILE_BEGIN);
# Line 567  wipe_freespace (const char * drive, HAND Line 576  wipe_freespace (const char * drive, HAND
576          progress_cb = cb;          progress_cb = cb;
577          progress_cb_value = cb_value;          progress_cb_value = cb_value;
578      }      }
579      rc = _secure_unlink (file, WIPE_MODE_FAST, r_fd);      rc = _secure_unlink (file, WIPE_MODE_PASSES, 2, r_fd);
580      free_if_alloc (file);      free_if_alloc (file);
581      return rc;      return rc;
582  }  }

Legend:
Removed from v.55  
changed lines
  Added in v.273

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26