diff --git a/include/drive.h b/include/drive.h index a2b66c6..efe38fc 100644 --- a/include/drive.h +++ b/include/drive.h @@ -69,10 +69,6 @@ public: void setTaskPercentage(uint8_t u8TaskPercentage); uint8_t getTaskPercentage(void); - -private: - - }; #endif // DRIVE_H_ \ No newline at end of file diff --git a/include/reHDD.h b/include/reHDD.h index 793a77e..7a7399e 100644 --- a/include/reHDD.h +++ b/include/reHDD.h @@ -8,13 +8,18 @@ #ifndef REHDD_H_ #define REHDD_H_ -#define DRYRUN +//#define DRYRUN #define WORSE_HOURS 19200 //mark drive if at this limit or beyond #define WORSE_POWERUP 4000 //mark drive if at this limit or beyond +#define SHRED_ITERATIONS 1 + #define SELECTED_DRIVE vecDrives.at(i32SelectedEntry) +#define READ 0 +#define WRITE 1 + #include #include #include @@ -27,16 +32,17 @@ #include #include #include -#include +#include #include #include #include +#include using namespace std; #include "drive.h" #include "smart.h" -#include "shred.h" +#include "shred/shred.h" #include "delete.h" #include "tui.h" diff --git a/include/shred.h b/include/shred.h deleted file mode 100644 index eba5cc8..0000000 --- a/include/shred.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file shred.h - * @brief shred drive - * @author hendrik schutter - * @date 03.05.2020 - */ - -#ifndef SHRED_H_ -#define SHRED_H_ - -#include "reHDD.h" - -class Shred -{ -protected: - -public: - static void shredDrive(Drive* drive, int* fdInformPipeWrite); - -private: - Shred(void); - -}; - -#endif // SHRED_H_ \ No newline at end of file diff --git a/include/shred/machdefs.h b/include/shred/machdefs.h new file mode 100644 index 0000000..a99d0eb --- /dev/null +++ b/include/shred/machdefs.h @@ -0,0 +1,19 @@ +#ifndef _MACHINE_DEFINITIONS_HEADER +#define _MACHINE_DEFINITIONS_HEADER + +#include +#include + +#undef MACHINE_16BIT +#undef MACHINE_32BIT +#undef MACHINE_64BIT + +#if UINTPTR_MAX == UINT32_MAX +#define MACHINE_32BIT +#elif UINTPTR_MAX == UINT64_MAX +#define MACHINE_64BIT +#elif UINTPTR_MAX == UINT16_MAX +#define MACHINE_16BIT +#endif + +#endif diff --git a/include/shred/shred.h b/include/shred/shred.h new file mode 100644 index 0000000..12ccbfd --- /dev/null +++ b/include/shred/shred.h @@ -0,0 +1,92 @@ +/** + * @file shred.h + * @brief shred drive + * @author hendrik schutter + * @date 03.05.2020 + */ + +#ifndef SHRED_H_ +#define SHRED_H_ + +#include "../reHDD.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "tfdef.h" +#include "tfcore.h" +//#include "tfe.h" + +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif +#ifndef _BSD_SOURCE +#define _BSD_SOURCE +#endif +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 700 +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +#ifndef _TFNG_STREAM_CIPHER_DEFS +#define _TFNG_STREAM_CIPHER_DEFS +#endif + +#define PROCESS_BLOCKP(x,k1,k2,k3,k4,k5,k6) \ + do { \ + KE_MIX(Y, X, k1 + k2, k3, TFS_KS01); \ + KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS02); \ + \ + BE_MIX(X, T, TFS_BS01); BE_MIX(Z, Y, TFS_BS02); \ + BE_MIX(X, Y, TFS_BS03); BE_MIX(Z, T, TFS_BS04); \ + BE_MIX(X, T, TFS_BS05); BE_MIX(Z, Y, TFS_BS06); \ + } while (0) + +#define PROCESS_BLOCKN(x,k1,k2,k3,k4,k5,k6) \ + do { \ + KE_MIX(Y, X, k1 + k2, k3, TFS_KS03); \ + KE_MIX(T, Z, k4 + x, k5 + k6, TFS_KS04); \ + \ + BE_MIX(X, T, TFS_BS07); BE_MIX(Z, Y, TFS_BS08); \ + BE_MIX(X, Y, TFS_BS09); BE_MIX(Z, T, TFS_BS10); \ + BE_MIX(X, T, TFS_BS11); BE_MIX(Z, Y, TFS_BS12); \ + } while (0) + + +#define NOSIZE ((size_t)-1) + +#define XRET(x) if (!xret && xret < x) xret = x + +class Shred +{ +protected: + +public: + static void shredDrive(Drive* drive, int* ipSignalFd); + +private: + Shred(void); + static inline uint8_t calcProgress(); + static inline void tfnge_init_iv(struct tfnge_stream *tfe, const void *key, const void *iv); + static inline void tfnge_init(struct tfnge_stream *tfe, const void *key); + static inline void tfng_encrypt_rawblk(TFNG_UNIT_TYPE *O, const TFNG_UNIT_TYPE *I, const TFNG_UNIT_TYPE *K); + static inline void tfnge_emit(void *dst, size_t szdst, struct tfnge_stream *tfe); + + +}; + +#endif // SHRED_H_ diff --git a/include/shred/tfcore.h b/include/shred/tfcore.h new file mode 100644 index 0000000..2d9d53e --- /dev/null +++ b/include/shred/tfcore.h @@ -0,0 +1,51 @@ +#ifndef _THREEFISH_NOISE_GENERATOR_CIPHER_CORE_HEADER +#define _THREEFISH_NOISE_GENERATOR_CIPHER_CORE_HEADER + +#ifndef _THREEFISH_NOISE_GENERATOR_CIPHER_DEFINITIONS_HEADER +#error Threefish definitions header is required! Include tfdef.h first. +#endif + +#define ROL(x, s, max) ((x << s) | (x >> (-s & (max-1)))) +#define ROR(x, s, max) ((x >> s) | (x << (-s & (max-1)))) + +#define KE_MIX(x, y, k1, k2, sl) \ + do { \ + x += k1; \ + y += x; \ + y += k2; \ + x = ROL(x, sl, TFNG_UNIT_BITS); \ + x ^= y; \ + } while (0) + +#define BE_MIX(x, y, sl) \ + do { \ + x += y; \ + y = ROL(y, sl, TFNG_UNIT_BITS); \ + y ^= x; \ + } while (0) + +#define KD_MIX(x, y, k1, k2, sr) \ + do { \ + x ^= y; \ + x = ROR(x, sr, TFNG_UNIT_BITS); \ + y -= x; \ + y -= k2; \ + x -= k1; \ + } while (0) + +#define BD_MIX(x, y, sr) \ + do { \ + y ^= x; \ + y = ROR(y, sr, TFNG_UNIT_BITS); \ + x -= y; \ + } while (0) + +enum tfng_rotations +{ + TFS_KS01 = 7, TFS_KS02 = 25, TFS_KS03 = 19, TFS_KS04 = 7, + TFS_BS01 = 5, TFS_BS02 = 27, TFS_BS03 = 26, TFS_BS04 = 6, + TFS_BS05 = 14, TFS_BS06 = 11, TFS_BS07 = 24, TFS_BS08 = 18, + TFS_BS09 = 9, TFS_BS10 = 24, TFS_BS11 = 6, TFS_BS12 = 7, +}; + +#endif diff --git a/include/shred/tfdef.h b/include/shred/tfdef.h new file mode 100644 index 0000000..ea0bd0b --- /dev/null +++ b/include/shred/tfdef.h @@ -0,0 +1,39 @@ +#ifndef _THREEFISH_NOISE_GENERATOR_CIPHER_DEFINITIONS_HEADER +#define _THREEFISH_NOISE_GENERATOR_CIPHER_DEFINITIONS_HEADER + +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif + +#ifndef _BSD_SOURCE +#define _BSD_SOURCE +#endif + +#include +#include +#include "machdefs.h" + +#if defined(MACHINE_64BIT) +#define TFNG_UNIT_TYPE uint64_t +#define TFNG_NR_BLOCK_BITS 256 +#define TFNG_NR_KEY_BITS 512 +#else +#define TFNG_UNIT_TYPE uint32_t +#define TFNG_NR_BLOCK_BITS 128 +#define TFNG_NR_KEY_BITS 256 +#endif + +#define TFNG_NR_BLOCK_UNITS 4 +#define TFNG_NR_KEY_UNITS 8 + +#define TFNG_BYTE_TYPE uint8_t +#define TFNG_SIZE_UNIT (sizeof(TFNG_UNIT_TYPE)) +#define TFNG_BLOCK_SIZE (TFNG_SIZE_UNIT * TFNG_NR_BLOCK_UNITS) +#define TFNG_KEY_SIZE (TFNG_SIZE_UNIT * TFNG_NR_KEY_UNITS) + +#define TFNG_TO_BITS(x) ((x) * 8) +#define TFNG_FROM_BITS(x) ((x) / 8) +#define TFNG_MAX_BITS TFNG_NR_BLOCK_BITS +#define TFNG_UNIT_BITS (TFNG_SIZE_UNIT * 8) + +#endif diff --git a/out.txt b/out.txt new file mode 100644 index 0000000..60fffd1 --- /dev/null +++ b/out.txt @@ -0,0 +1 @@ +date diff --git a/shred_dummy.sh b/shred_dummy.sh index bbdfed9..afc4268 100644 --- a/shred_dummy.sh +++ b/shred_dummy.sh @@ -4,7 +4,8 @@ echo "starting SHRED DUMMY" for i in {0..100..10} do - echo "DUMMY shred $i%" + #echo "DUMMY shred $i%" + echo $date > out.txt sleep 1 done diff --git a/src/reHDD.cpp b/src/reHDD.cpp index bfaf6c8..084ee5f 100644 --- a/src/reHDD.cpp +++ b/src/reHDD.cpp @@ -50,8 +50,6 @@ void reHDD::app_logic(void) pipe(fdNewDrivesInformPipe); pipe(fdShredInformPipe); - - thread thDevices(ThreadScannDevices); //start thread that scanns for drives thread thUserInput(ThreadUserInput); //start thread that reads user input @@ -425,7 +423,6 @@ void reHDD::handleAbort() } } - void reHDD::checkShredComplete(vector * pvecDrives) { vector ::iterator it; @@ -438,4 +435,5 @@ void reHDD::checkShredComplete(vector * pvecDrives) it->state = Drive::NONE; //reset for an other task } } -} \ No newline at end of file +} + diff --git a/src/shred.cpp b/src/shred.cpp deleted file mode 100644 index 32fc92b..0000000 --- a/src/shred.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @file shred.cpp - * @brief shred drive - * @author hendrik schutter - * @date 03.05.2020 - */ - -#include "../include/reHDD.h" - -/** - * \brief shred drive with shred - * \param pointer of Drive instance - * \return void - */ -void Shred::shredDrive(Drive* drive, int* fdInformPipeWrite) - -{ - size_t len = 0; //lenght of found line - char* cLine = NULL; //found line - -#ifndef DRYRUN - string sCMD = ("shred -v "); - sCMD.append(drive->getPath()); -#endif - -#ifdef DRYRUN - //cout << "dryrun for " << drive->getPath() << endl; - string sCMD = ("bash shred_dummy.sh"); -#endif - - const char* cpComand = sCMD.c_str(); - //cout << "shred: " << cpComand << endl; - - FILE* shredCmdOutput = popen(cpComand, "r"); - - while ((getline(&cLine, &len, shredCmdOutput)) != -1) - { - if(drive->state == Drive::SHRED_ACTIVE) - { - string sLine = string(cLine); - string search("%"); - size_t found = sLine.find(search); - if (found!=string::npos) - { - sLine.erase(0, sLine.find("%")-3); - sLine.erase(std::remove(sLine.begin(), sLine.end(), '\n'), sLine.end()); - drive->setTaskPercentage(stoi(sLine)); - write(*fdInformPipeWrite, "A",1); - } - } - else - { - return; //end shredding task - } - } - fclose(shredCmdOutput); -} diff --git a/src/shred/shred.cpp b/src/shred/shred.cpp new file mode 100644 index 0000000..2f90949 --- /dev/null +++ b/src/shred/shred.cpp @@ -0,0 +1,368 @@ +/** + * @file shred.cpp + * @brief shred drive + * @author hendrik schutter + * @date 03.05.2020 + */ + +#include "../../include/reHDD.h" + +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; + +static unsigned long blockcount = 0UL; +static long blockcount_max; +static uint8_t u8Percent; + +/** + * \brief shred drive with shred + * \param pointer of Drive instance + * \return void + */ +void Shred::shredDrive(Drive* drive, int* ipSignalFd) +{ + +#ifdef DRYRUN +//TODO +#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); + + u8Percent = 0U; + + 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; + /* + if (howmany != -1) + { + l = ll = howmany; + noround = 1; + } + */ + 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) + { + + if(drive->state != Drive::SHRED_ACTIVE){ + goto _return; + } + + uint8_t u8TmpPercent = calcProgress(); + + if(u8Percent != u8TmpPercent){ + drive->setTaskPercentage(u8TmpPercent); + u8Percent = u8TmpPercent; + write(*ipSignalFd, "A",1); + } + + 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); +#endif +} + + +uint8_t Shred::calcProgress(){ +blockcount++; + 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); + } +} \ No newline at end of file