2
\$\begingroup\$

When giving away or selling a PC, one should be careful not to send personal data with it. I'm in such a situation and was using dd if=/dev/urandom of=/dev/sdb bs=8M, but it was only averaging 22MB/s. Way too slow since I have to drop it at the post office next morning. So I decided to write my own and see what kinds of results I would get.

First I dropped /dev/urandom in favor of hashing a secret key and feeding back the output as state. The second thing I did was to use O_DIRECT to avoid buffering.

My program reports an average of 48MiB/s, much better than what I got with plain old dd unless it has a bug.

#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <openssl/sha.h>
#define BLOCK_SIZE (1024 * 1024 * 8)
#define ALIGNMENT 512
typedef struct {
 unsigned char state[64];
 unsigned char key[32];
 __uint128_t counter;
} RandomCtx;
static void _xor64(uint64_t* a, uint64_t* b)
{
 for(int i = 0; i < 8; ++i)
 *a++ ^= *b++;
}
static void _cipher(RandomCtx* ctx, unsigned char* data, unsigned int len)
{
 unsigned int runs = len >> 6;
 while(runs){
 // get value to XOR
 unsigned char x[64];
 SHA512((unsigned char const*)ctx, sizeof(RandomCtx), x);
 // XOR with data
 _xor64((uint64_t*)data, (uint64_t*)x);
 // feed the XORed result back as state and update counter
 memcpy(ctx->state, data, 64);
 ++ctx->counter;
 // move on
 data += 64;
 --runs;
 }
}
int main(int argc, char* argv[])
{
 if(2 != argc){
 fprintf(stderr, "Usage: %s /dev/sdb\n", argv[0]);
 return EXIT_FAILURE;
 }
 // open disk
 int disk = open(argv[1], O_WRONLY|O_DIRECT);
 if(-1 == disk){
 perror("open()");
 return EXIT_FAILURE;
 }
 // allocate memory enough
 char* raw = malloc(BLOCK_SIZE + ALIGNMENT - 1);
 if(!raw){
 perror("malloc()");
 return EXIT_FAILURE;
 }
 // align
 unsigned char* aligned = (unsigned char*)
 ((size_t)(raw + (ALIGNMENT-1)) & ~(ALIGNMENT-1));
 // open random source
 int urandom = open("/dev/urandom", O_RDONLY);
 if(-1 == urandom){
 perror("open()");
 return EXIT_FAILURE;
 }
 // init random ctx
 RandomCtx ctx;
 if(sizeof ctx != read(urandom, &ctx, sizeof ctx)){
 perror("read()");
 return EXIT_FAILURE;
 }
 // init buffer
 if(BLOCK_SIZE != read(urandom, aligned, BLOCK_SIZE)){
 perror("read()");
 return EXIT_FAILURE;
 }
 // we are done with urandom
 close(urandom);
 // now run until there's no more space
 time_t ti0 = time(NULL);
 size_t to0 = 0;
 size_t to1 = 0;
 int gib = 0;
 while(BLOCK_SIZE == write(disk, aligned, BLOCK_SIZE)){
 to1 += BLOCK_SIZE;
 if((to1 - to0) >= (1024*1024*1024)){
 to0 = to1;
 ++gib;
 size_t secs = time(NULL) - ti0; 
 printf("Total: %d GiB in %zu secs. %.2f MiB/s\n", gib, secs,
 (double)gib*1024/secs);
 }
 _cipher(&ctx, aligned, BLOCK_SIZE);
 }
}
asked Nov 17, 2016 at 18:07
\$\endgroup\$
1
  • 1
    \$\begingroup\$ These days, you would probably be better off using whole-disk encryption. Then, to "wipe" the disk, you just throw away the key. It also protects you in case of hardware failure, where it's not even possible to execute the wipe. (Not that this helps you if you already have an unencrypted disk that you need to wipe.) \$\endgroup\$ Commented Nov 21, 2016 at 18:42

1 Answer 1

1
\$\begingroup\$

If you actually need to securely wipe your non-SSD drive consider using shred, or look at some of the linked pages too.

Also I don't see much point in the pseudo-random data generation given that you just want to make the previous content unrecoverable. If you a want faster program you could probably use a faster hash too.


For the code I only want to note that write might write less than the specified number of bytes and that's not immediately an error.

answered Nov 21, 2016 at 18:12
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.