2020-08-26 00:12:39 +02:00
/**
* @ file shred . cpp
* @ brief shred drive
* @ author hendrik schutter
* @ date 03.05 .2020
*/
# include "../../include/reHDD.h"
2020-08-26 15:07:53 +02:00
# ifndef DRYRUN
2020-08-26 00:12:39 +02:00
static char * randsrc = ( char * ) " /dev/urandom " ;
static int force = 0 , rmf = 0 , zrf = 0 , noround = 0 , verbose = 0 , syncio = 0 , alwaysrand = 0 , reqrand = 0 ;
static char sfbuf [ PATH_MAX * 2 ] ;
struct tfnge_stream
{
TFNG_UNIT_TYPE key [ TFNG_NR_KEY_UNITS ] ;
TFNG_UNIT_TYPE iv [ TFNG_NR_BLOCK_UNITS ] ;
TFNG_BYTE_TYPE carry_block [ TFNG_BLOCK_SIZE ] ;
size_t carry_bytes ;
} ;
static struct tfnge_stream tfnge ;
2020-09-11 17:18:53 +02:00
# endif
2020-08-26 00:12:39 +02:00
2020-09-08 13:01:09 +02:00
Shred : : Shred ( )
{
}
Shred : : ~ Shred ( )
{
}
2020-09-11 17:18:53 +02:00
2020-08-26 00:12:39 +02:00
/**
* \ brief shred drive with shred
* \ param pointer of Drive instance
* \ return void
*/
void Shred : : shredDrive ( Drive * drive , int * ipSignalFd )
{
# ifdef DRYRUN
2020-08-30 12:03:37 +02:00
for ( int i = 0 ; i < = 100 ; i + + )
2020-08-26 15:07:53 +02:00
{
if ( drive - > state ! = Drive : : SHRED_ACTIVE )
{
return ;
}
2020-08-30 12:03:37 +02:00
drive - > setTaskPercentage ( i + 0.05 ) ;
2020-08-26 15:07:53 +02:00
write ( * ipSignalFd , " A " , 1 ) ;
2020-08-30 12:03:37 +02:00
usleep ( 20000 ) ;
2020-08-26 15:07:53 +02:00
}
2020-08-26 00:12:39 +02:00
# endif
# ifndef DRYRUN
struct stat st ;
char * buf , * s , * d , rc = 0 ;
int f , rsf ;
int xret = 0 , pat = 0 , last = 0 , special = 0 , iIteration = 0 ;
size_t blksz = 0 , x , y ;
size_t l , ll = NOSIZE ;
const char * cpDrivePath = drive - > getPath ( ) . c_str ( ) ;
blockcount_max = SHRED_ITERATIONS * ( drive - > getCapacity ( ) / 4096 ) ;
2020-09-08 13:01:09 +02:00
# ifdef LOG_LEVEL_HIGH
Logger : : logThis ( ) - > info ( " Shred-Task: Max-BlockCount: " + to_string ( blockcount_max ) + " - Drive: " + drive - > getSerial ( ) ) ;
# endif
2020-08-28 15:28:57 +02:00
d32Percent = 0U ;
2020-08-26 00:12:39 +02:00
rsf = open ( randsrc , O_RDONLY | O_LARGEFILE ) ;
if ( rsf = = - 1 )
{
perror ( randsrc ) ;
exit ( 1 ) ;
}
special = pat = 0 ;
iIteration = SHRED_ITERATIONS ;
if ( verbose ) fprintf ( stderr , " destroying %s ... \n " , cpDrivePath ) ;
if ( stat ( cpDrivePath , & st ) = = - 1 )
{
perror ( cpDrivePath ) ;
XRET ( 1 ) ;
goto _return ;
}
if ( ! blksz ) blksz = ( size_t ) st . st_blksize ;
2020-09-08 13:01:09 +02:00
2020-08-26 00:12:39 +02:00
else l = ll = st . st_size ;
if ( l = = 0 & & ! S_ISREG ( st . st_mode ) ) special = 1 ;
memset ( & st , 0 , sizeof ( struct stat ) ) ;
if ( force ) if ( chmod ( cpDrivePath , S_IRUSR | S_IWUSR ) = = - 1 )
{
perror ( cpDrivePath ) ;
XRET ( 1 ) ;
}
f = open ( cpDrivePath , O_WRONLY | O_LARGEFILE | O_NOCTTY | syncio ) ;
if ( f = = - 1 )
{
XRET ( 1 ) ;
perror ( cpDrivePath ) ;
goto _return ;
}
buf = ( char * ) malloc ( blksz ) ;
if ( ! buf )
{
perror ( " malloc " ) ;
XRET ( 2 ) ;
fprintf ( stderr , " Continuing with fixed buffer (%zu bytes long) \n " , sizeof ( sfbuf ) ) ;
buf = sfbuf ;
blksz = sizeof ( sfbuf ) ;
}
memset ( buf , 0 , blksz ) ;
if ( read ( rsf , buf , blksz ) < = 0 ) fprintf ( stderr , " %s: read 0 bytes (wanted %zu) \n " , randsrc , blksz ) ;
tfnge_init ( & tfnge , buf ) ;
//iteration loop
while ( iIteration )
{
lseek ( f , 0L , SEEK_SET ) ;
if ( iIteration < = 1 & & zrf )
{
pat = 1 ;
rc = 0 ;
}
else if ( iIteration = = SHRED_ITERATIONS & & reqrand )
{
pat = 0 ;
}
else if ( ! alwaysrand )
{
if ( read ( rsf , & rc , 1 ) < = 0 ) fprintf ( stderr , " %s: read 0 bytes (wanted 1) \n " , randsrc ) ;
pat = rc % 2 ;
if ( read ( rsf , & rc , 1 ) < = 0 ) fprintf ( stderr , " %s: read 0 bytes (wanted 1) \n " , randsrc ) ;
}
else pat = 0 ;
if ( verbose )
{
if ( pat ) fprintf ( stderr , " iteration (pat) %d (%02hhx%02hhx%02hhx) ... \n " , SHRED_ITERATIONS - iIteration + 1 , rc , rc , rc ) ;
else fprintf ( stderr , " iteration (!pat) % d ( random ) . . . \ n " , SHRED_ITERATIONS-iIteration+1) ;
}
// write block loop
while ( 1 )
{
2020-08-26 15:07:53 +02:00
if ( drive - > state ! = Drive : : SHRED_ACTIVE )
{
2020-08-30 12:03:37 +02:00
drive - > setTaskPercentage ( 0 ) ;
2020-09-08 13:01:09 +02:00
d32Percent = 0.00 ;
blockcount = 0 ;
blockcount_max = 0 ;
Logger : : logThis ( ) - > info ( " Aborted shred for: " + drive - > getModelName ( ) + " - " + drive - > getSerial ( ) ) ;
2020-08-26 15:07:53 +02:00
goto _return ;
}
2020-08-26 00:12:39 +02:00
2020-08-28 15:28:57 +02:00
double d32TmpPercent = calcProgress ( ) ;
2020-08-26 00:12:39 +02:00
2020-09-08 13:01:09 +02:00
2020-08-28 15:28:57 +02:00
if ( ( d32TmpPercent - d32Percent ) > = 0.09 )
2020-08-26 15:07:53 +02:00
{
2020-08-28 15:28:57 +02:00
drive - > setTaskPercentage ( d32TmpPercent ) ;
d32Percent = d32TmpPercent ;
2020-09-08 13:01:09 +02:00
# ifdef LOG_LEVEL_HIGH
Logger : : logThis ( ) - > info ( " Shred-Task: BlockCount: " + to_string ( blockcount ) + " - progress: " + to_string ( d32Percent ) + " - Drive: " + drive - > getSerial ( ) ) ;
# endif
2020-08-26 15:07:53 +02:00
write ( * ipSignalFd , " A " , 1 ) ;
}
2020-08-26 00:12:39 +02:00
if ( ! pat )
{
tfnge_emit ( buf , blksz , & tfnge ) ;
}
else
{
memset ( buf , rc , blksz ) ;
}
if ( l < = blksz & & ! special )
{
last = 1 ;
}
errno = 0 ;
l - = write ( f , buf , ( noround & & last ) ? l : blksz ) ;
if ( errno )
{
perror ( cpDrivePath ) ;
errno = 0 ;
break ;
}
if ( last )
{
last = 0 ;
break ;
}
}
// write block loop end
l = ll ;
fdatasync ( f ) ;
iIteration - - ;
} //iteration loop end
if ( rmf )
{
close ( f ) ;
f = open ( cpDrivePath , O_WRONLY | O_TRUNC | O_LARGEFILE | O_NOCTTY | syncio ) ;
if ( verbose ) fprintf ( stderr , " removing %s ... \n " , cpDrivePath ) ;
x = strnlen ( cpDrivePath , sizeof ( sfbuf ) / 2 ) ;
s = sfbuf + ( sizeof ( sfbuf ) / 2 ) ;
memcpy ( sfbuf , cpDrivePath , x ) ;
* ( sfbuf + x ) = 0 ;
d = strrchr ( sfbuf , ' / ' ) ;
if ( d )
{
d + + ;
y = d - sfbuf ;
memset ( d , ' 0 ' , x - ( d - sfbuf ) ) ;
}
else
{
y = 0 ;
memset ( sfbuf , ' 0 ' , x ) ;
}
memcpy ( s , sfbuf , x ) ;
* ( s + x ) = 0 ;
/* Somehow I need to rename original to destination */
if ( access ( s , R_OK ) ! = - 1 )
{
fprintf ( stderr , " %s already exists! \n " , s ) ;
unlink ( cpDrivePath ) ;
goto _return ;
}
if ( verbose ) fprintf ( stderr , " %s -> %s \n " , cpDrivePath , s ) ;
if ( rename ( cpDrivePath , s ) = = - 1 )
{
perror ( s ) ;
goto _return ;
}
while ( x > y + 1 )
{
* ( sfbuf + x ) = 0 ;
x - - ;
* ( s + x ) = 0 ;
if ( access ( s , R_OK ) ! = - 1 )
{
fprintf ( stderr , " %s already exists! \n " , s ) ;
unlink ( sfbuf ) ;
goto _return ;
}
if ( verbose ) fprintf ( stderr , " %s -> %s \n " , sfbuf , s ) ;
if ( rename ( sfbuf , s ) = = - 1 )
{
perror ( s ) ;
goto _return ;
}
}
if ( verbose ) fprintf ( stderr , " remove %s \n " , s ) ;
unlink ( s ) ;
if ( verbose ) fprintf ( stderr , " done away with %s. \n " , cpDrivePath ) ;
}
tfnge_emit ( NULL , 0 , & tfnge ) ;
if ( buf & & buf ! = sfbuf ) free ( buf ) ;
if ( f ! = - 1 ) close ( f ) ;
_return :
optind + + ;
close ( rsf ) ;
2020-08-30 12:03:37 +02:00
# endif
2020-08-28 15:28:57 +02:00
if ( drive - > state = = Drive : : SHRED_ACTIVE )
{
drive - > bWasShredded = true ;
2020-08-30 12:03:37 +02:00
drive - > state = Drive : : NONE ;
drive - > setTaskPercentage ( 0 ) ;
2020-09-09 16:11:25 +02:00
Logger : : logThis ( ) - > info ( " Finished shred for: " + drive - > getModelName ( ) + " - " + drive - > getSerial ( ) ) ;
2020-08-28 15:28:57 +02:00
}
2020-08-26 00:12:39 +02:00
}
2020-08-26 15:07:53 +02:00
# ifndef DRYRUN
2020-08-26 00:12:39 +02:00
2020-08-28 15:28:57 +02:00
double Shred : : calcProgress ( )
2020-08-26 15:07:53 +02:00
{
blockcount + + ;
2020-08-26 00:12:39 +02:00
return ( ( ( ( double ) blockcount / ( double ) blockcount_max ) ) * 100 ) ;
}
void Shred : : tfnge_init_iv ( struct tfnge_stream * tfe , const void * key , const void * iv )
{
memset ( tfe , 0 , sizeof ( struct tfnge_stream ) ) ;
memcpy ( tfe - > key , key , TFNG_KEY_SIZE ) ;
if ( iv ) memcpy ( tfe - > iv , iv , TFNG_BLOCK_SIZE ) ;
tfe - > carry_bytes = 0 ;
}
void Shred : : tfnge_init ( struct tfnge_stream * tfe , const void * key )
{
tfnge_init_iv ( tfe , key , NULL ) ;
}
void Shred : : tfng_encrypt_rawblk ( TFNG_UNIT_TYPE * O , const TFNG_UNIT_TYPE * I , const TFNG_UNIT_TYPE * K )
{
TFNG_UNIT_TYPE X , Y , Z , T ;
TFNG_UNIT_TYPE K0 , K1 , K2 , K3 ;
TFNG_UNIT_TYPE K4 , T0 , T1 , T2 ;
X = I [ 0 ] ;
Y = I [ 1 ] ;
Z = I [ 2 ] ;
T = I [ 3 ] ;
K0 = K [ 0 ] ;
K1 = K [ 1 ] ;
K2 = K [ 2 ] ;
K3 = K [ 3 ] ;
K4 = K [ 4 ] ;
T0 = K [ 5 ] ;
T1 = K [ 6 ] ;
T2 = K [ 7 ] ;
PROCESS_BLOCKP ( 1 , K1 , T0 , K0 , K3 , K2 , T1 ) ;
PROCESS_BLOCKN ( 2 , K2 , T1 , K1 , K4 , K3 , T2 ) ;
PROCESS_BLOCKP ( 3 , K3 , T2 , K2 , K0 , K4 , T0 ) ;
PROCESS_BLOCKN ( 4 , K4 , T0 , K3 , K1 , K0 , T1 ) ;
PROCESS_BLOCKP ( 5 , K0 , T1 , K4 , K2 , K1 , T2 ) ;
PROCESS_BLOCKN ( 6 , K1 , T2 , K0 , K3 , K2 , T0 ) ;
PROCESS_BLOCKP ( 7 , K2 , T0 , K1 , K4 , K3 , T1 ) ;
PROCESS_BLOCKN ( 8 , K3 , T1 , K2 , K0 , K4 , T2 ) ;
PROCESS_BLOCKP ( 9 , K4 , T2 , K3 , K1 , K0 , T0 ) ;
PROCESS_BLOCKN ( 10 , K0 , T0 , K4 , K2 , K1 , T1 ) ;
PROCESS_BLOCKP ( 11 , K1 , T1 , K0 , K3 , K2 , T2 ) ;
PROCESS_BLOCKN ( 12 , K2 , T2 , K1 , K4 , K3 , T0 ) ;
O [ 0 ] = X + K3 ;
O [ 1 ] = Y + K4 + T0 ;
O [ 2 ] = Z + K0 + T1 ;
O [ 3 ] = T + K1 + 18 ;
}
void Shred : : tfnge_emit ( void * dst , size_t szdst , struct tfnge_stream * tfe )
{
TFNG_BYTE_TYPE * udst = ( uint8_t * ) dst ;
size_t sz = szdst ;
if ( ! dst & & szdst = = 0 )
{
memset ( tfe , 0 , sizeof ( struct tfnge_stream ) ) ;
return ;
}
if ( tfe - > carry_bytes > 0 )
{
if ( tfe - > carry_bytes > szdst )
{
memcpy ( udst , tfe - > carry_block , szdst ) ;
memmove ( tfe - > carry_block , tfe - > carry_block + szdst , tfe - > carry_bytes - szdst ) ;
tfe - > carry_bytes - = szdst ;
return ;
}
memcpy ( udst , tfe - > carry_block , tfe - > carry_bytes ) ;
udst + = tfe - > carry_bytes ;
sz - = tfe - > carry_bytes ;
tfe - > carry_bytes = 0 ;
}
if ( sz > = TFNG_BLOCK_SIZE )
{
do
{
tfng_encrypt_rawblk ( tfe - > iv , tfe - > iv , tfe - > key ) ;
memcpy ( udst , tfe - > iv , TFNG_BLOCK_SIZE ) ;
udst + = TFNG_BLOCK_SIZE ;
}
while ( ( sz - = TFNG_BLOCK_SIZE ) > = TFNG_BLOCK_SIZE ) ;
}
if ( sz )
{
tfng_encrypt_rawblk ( tfe - > iv , tfe - > iv , tfe - > key ) ;
memcpy ( udst , tfe - > iv , sz ) ;
udst = ( TFNG_BYTE_TYPE * ) tfe - > iv ;
tfe - > carry_bytes = TFNG_BLOCK_SIZE - sz ;
memcpy ( tfe - > carry_block , udst + sz , tfe - > carry_bytes ) ;
}
2020-08-26 15:07:53 +02:00
}
# endif