Hello everybody!
I have developed a portable secure file deletion utility. I want to ask you if you think my approach is enough in terms of ensuring the adequate security. If so, I could extend my application to support recursive directories structures, as well as multiple files selection.
Another question would be how to implement secure overwriting of free space on the disc. Can it be done in a portable manner? Even if not, what are my options?
Thank you for reading my post!
Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* 4 MB buffer */
#define BUFFER_SIZE (4 * 1024 * 1024)
#define MAX_UNSIGNED_CHAR_VAL 255
#define MAX_DELETE_ITERATIONS 32
/* Securely erases a file on the disc, by overwriting,
a given number of times, its content with a random
sequence of bytes. */
int DeleteFile(const char* const fileName, unsigned int overwriteCount)
{
FILE* fileToErase;
long fileSize, filePosition;
unsigned char* buffer;
size_t bytesToWrite;
unsigned int i, j;
if ((fileToErase = fopen(fileName, "rb+")) == NULL)
return -1;
if (overwriteCount > MAX_DELETE_ITERATIONS)
overwriteCount = MAX_DELETE_ITERATIONS;
/* Sets the file stream to be unbuffered */
setbuf(fileToErase, NULL);
/* Determines the file length */
fseek(fileToErase, 0, SEEK_END);
fileSize = ftell(fileToErase);
printf("\nStarting the wipe of file \"%s\" ...\n", fileName);
if (fileSize > 0)
{
/* Allocates the buffer on the heap */
buffer = (unsigned char*)malloc(BUFFER_SIZE * sizeof(unsigned char));
/* Data overwrite iteration */
for (i = 0; i < overwriteCount; i++)
{
/* Initializes the random generator */
srand((unsigned int)time(NULL));
/* Initializes the random buffer */
for (j = 0; j < BUFFER_SIZE; j++)
buffer[j] = (unsigned char)(rand() % (MAX_UNSIGNED_CHAR_VAL + 1));
printf("\nWipe iteration %u ... ", i + 1);
/* Moves the file pointer to the beginning of the file */
fseek(fileToErase, 0, SEEK_SET);
filePosition = 0;
/* Data overwriting block */
while (filePosition < fileSize)
{
if (filePosition + BUFFER_SIZE <= fileSize)
bytesToWrite = BUFFER_SIZE;
else
bytesToWrite = (size_t)(fileSize - filePosition);
fwrite(buffer, sizeof(unsigned char), bytesToWrite, fileToErase);
printf("#");
filePosition += (long)bytesToWrite;
}
printf(" Done\n");
}
free(buffer);
}
fclose(fileToErase);
if (remove(fileName) < 0)
return -2;
return 0;
}
int main(int argc, char** argv)
{
unsigned int iterationsCount;
if ( (argc != 3) || ((iterationsCount = (unsigned int)atoi(argv[2])) == 0) )
{
fprintf(stderr, "\nUsage: wipeit file_path iterations_count\n");
return -1;
}
if (DeleteFile(argv[1], iterationsCount) < 0)
{
fprintf(stderr, "\nCould not delete the file \"%s\".\n", argv[1]);
return -2;
}
printf("\nFile \"%s\" deleted successfully.\n", argv[1]);
return 0;
}