diff --git a/src/context.h b/src/context.h index 07de9b2..1c497bc 100644 --- a/src/context.h +++ b/src/context.h @@ -128,7 +128,6 @@ typedef struct nwipe_context_t_ int device_target; // The device target. u64 eta; // The estimated number of seconds until method completion. - int entropy_fd; // The entropy source. Usually /dev/urandom. int pass_count; // The number of passes performed by the working wipe method. u64 pass_done; // The number of bytes that have already been i/o'd in this pass. u64 pass_errors; // The number of errors across all passes. diff --git a/src/method.c b/src/method.c index 259c3f3..09534b6 100644 --- a/src/method.c +++ b/src/method.c @@ -47,6 +47,52 @@ #include "options.h" #include "pass.h" #include "logging.h" +#include +#include +#include /* SYS_getrandom */ +#if defined( __linux__ ) +/* On glibc/musl with available, it's fine (optional). */ +/* #include */ +#endif + +/** + * @brief Fill a buffer with cryptographically secure random bytes using getrandom(2). + * + * This wrapper blocks until the kernel CRNG is initialized, then loops until + * @p len bytes are written (handling short reads and EINTR/EAGAIN). + * + * @param[out] buf Destination buffer. + * @param[in] len Number of bytes to generate. + * @return On success, returns (ssize_t)len. + * On error, returns -errno and leaves errno set. + */ +static ssize_t nwipe_read_entropy( void* buf, size_t len ) +{ + unsigned char* p = (unsigned char*) buf; + size_t n = len; + + while( n > 0 ) + { + /* Prefer the raw syscall to avoid libc version pitfalls. */ + ssize_t r = syscall( SYS_getrandom, p, n, 0 /* blocking */ ); + if( r < 0 ) + { + if( errno == EINTR || errno == EAGAIN ) + { + continue; /* retry */ + } + return -errno; + } + if( r == 0 ) + { + /* Extremely unlikely: treat as transient and retry. */ + continue; + } + p += r; + n -= (size_t) r; + } + return (ssize_t) len; +} /* * Comment Legend @@ -292,7 +338,7 @@ void* nwipe_dod522022m( void* ptr ) { 0, NULL } }; /* Load the array with random characters. */ - r = read( c->entropy_fd, &dod, sizeof( dod ) ); + r = nwipe_read_entropy( &dod, sizeof( dod ) ); /* NOTE: Only the random data in dod[0], dod[3], and dod[4] is actually used. */ @@ -363,7 +409,7 @@ void* nwipe_dodshort( void* ptr ) { 0, NULL } }; /* Load the array with random characters. */ - r = read( c->entropy_fd, &dod, sizeof( dod ) ); + r = nwipe_read_entropy( &dod, sizeof( dod ) ); /* NOTE: Only the random data in dod[0] is actually used. */ @@ -463,7 +509,7 @@ void* nwipe_gutmann( void* ptr ) u16 s[27]; /* Load the array with random characters. */ - ssize_t r = read( c->entropy_fd, &s, sizeof( s ) ); + ssize_t r = nwipe_read_entropy( &s, sizeof( s ) ); if( r != sizeof( s ) ) { r = errno; @@ -621,7 +667,7 @@ void* nwipe_ops2( void* ptr ) } /* Load the array of random characters. */ - r = read( c->entropy_fd, s, u ); + r = nwipe_read_entropy( s, u ); if( r != u ) { @@ -1001,13 +1047,13 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns ) c->pass_type = NWIPE_PASS_WRITE; /* Seed the PRNG. */ - r = read( c->entropy_fd, c->prng_seed.s, c->prng_seed.length ); + r = nwipe_read_entropy( c->prng_seed.s, c->prng_seed.length ); /* Check the result. */ if( r < 0 ) { c->pass_type = NWIPE_PASS_NONE; - nwipe_perror( errno, __FUNCTION__, "read" ); + nwipe_perror( errno, __FUNCTION__, "getrandom" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the PRNG." ); return -1; } @@ -1104,12 +1150,12 @@ int nwipe_runmethod( nwipe_context_t* c, nwipe_pattern_t* patterns ) c->pass_type = NWIPE_PASS_FINAL_OPS2; /* Seed the PRNG. */ - r = read( c->entropy_fd, c->prng_seed.s, c->prng_seed.length ); + r = nwipe_read_entropy( c->prng_seed.s, c->prng_seed.length ); /* Check the result. */ if( r < 0 ) { - nwipe_perror( errno, __FUNCTION__, "read" ); + nwipe_perror( errno, __FUNCTION__, "getrandom" ); nwipe_log( NWIPE_LOG_FATAL, "Unable to seed the PRNG." ); return -1; } diff --git a/src/nwipe.c b/src/nwipe.c index 6292954..55afe0f 100644 --- a/src/nwipe.c +++ b/src/nwipe.c @@ -97,9 +97,6 @@ int main( int argc, char** argv ) char module_shortform[50]; char final_cmd_modprobe[sizeof( modprobe_command ) + sizeof( module_shortform )]; - /* The entropy source file handle. */ - int nwipe_entropy; - /* The generic index variables. */ int i; int j; @@ -256,21 +253,6 @@ int main( int argc, char** argv ) exit( 1 ); } - /* Open the entropy source. */ - nwipe_entropy = open( NWIPE_KNOB_ENTROPY, O_RDONLY ); - - /* Check the result. */ - if( nwipe_entropy < 0 ) - { - nwipe_perror( errno, __FUNCTION__, "open" ); - nwipe_log( NWIPE_LOG_FATAL, "Unable to open entropy source %s.", NWIPE_KNOB_ENTROPY ); - cleanup(); - free( c2 ); - return errno; - } - - nwipe_log( NWIPE_LOG_NOTICE, "Opened entropy source '%s'.", NWIPE_KNOB_ENTROPY ); - /* Block relevant signals in main thread. Any other threads that are */ /* created after this will also block those signals. */ sigset_t sigset; @@ -359,9 +341,6 @@ int main( int argc, char** argv ) for( i = 0; i < nwipe_enumerated; i++ ) { - /* Set the entropy source. */ - c1[i]->entropy_fd = nwipe_entropy; - if( nwipe_options.autonuke ) { /* When the autonuke option is set, select all disks. */ diff --git a/src/options.h b/src/options.h index 96aeefc..dcf39f9 100644 --- a/src/options.h +++ b/src/options.h @@ -24,7 +24,6 @@ #define OPTIONS_H_ /* Program knobs. */ -#define NWIPE_KNOB_ENTROPY "/dev/urandom" #define NWIPE_KNOB_IDENTITY_SIZE 512 #define NWIPE_KNOB_LABEL_SIZE 128 #define NWIPE_KNOB_LOADAVG "/proc/loadavg"