From d0efd4316b41fbbbd9575427cd45ddb97b35fdb4 Mon Sep 17 00:00:00 2001 From: circulosmeos Date: Mon, 5 Oct 2015 20:13:56 +0200 Subject: [PATCH] v7.3 --- Changes.md | 6 ++ Makefile | 2 +- README.md | 5 +- triops.c | 157 ++++++++++++++++++++++++++++++++++++++--------------- triops.h | 13 ++++- 5 files changed, 131 insertions(+), 52 deletions(-) diff --git a/Changes.md b/Changes.md index 2b0a8b1..d4903af 100644 --- a/Changes.md +++ b/Changes.md @@ -1,3 +1,9 @@ +v7.3 + +* Large file support (LFS): no limit on the size of the files read/written (up to 8 EiB = 2^63 bytes, or the max filesystem file size). +* patch: files to read/write are tested after password check and before any other operation, so no empty or overwritten file is created. +* patch: (since v7.2) no valid password files resulted in abnormal program termination (nothing were overwritten, though). + v7.2.2 * patches: password was not correctly overwritten in memory after it wasn't needed. IVs weren't as random as intended. Both failures didn't compromise security of the encrypted file, AFAIK. diff --git a/Makefile b/Makefile index 6707296..a2b731d 100644 --- a/Makefile +++ b/Makefile @@ -1 +1 @@ -gcc -iquote . triops.c -I chacha20 -I chacha20/e -I chacha20/include chacha20/chacha.c chacha20/api.c -I keccak keccak/hash.c keccak/keccak.c -o triops.exe -Ofast \ No newline at end of file +gcc -iquote . triops.c -I chacha20 -I chacha20/e -I chacha20/include chacha20/chacha.c chacha20/api.c -I keccak keccak/hash.c keccak/keccak.c -o triops.exe -O3 \ No newline at end of file diff --git a/README.md b/README.md index c9b003d..8c0dce2 100644 --- a/README.md +++ b/README.md @@ -19,15 +19,12 @@ Features: * Encrypted files are appended the extension .$#3 to filename, so they can be recognized. * Password can be obtained from keyboard, command line or from a file. Caution: usually text files end with a "return" (line feed, \n, \r\n, \r) which will be used as the rest of chars in the file as part of the password. (Use $ cat > password + Ctrl+D to avoid this). Also note that there's a limit on v7.1 on the number of characters that will be read from the file: 255 chars. This limit disappears on v7.2. * Binary files can be used as passwords (from v7.2): for example jpg images, etc. Caution: do not lose this 'password' file and do not modify it! +* From v7.3, there's no limit on the size on files read/written (up to 8 EiB = 2^63 bytes, or the max filesystem file size). * Speed is extremely high, as CHACHA20 is a very fast encryption algorithm: it is as fast as RC4. * Reduced program size: < 100 kiB on all platforms. * [easily portable to Android](https://www.github.com/circulosmeos/triops.apk) as a JNI library. Check "ANDROID_LIBRARY" in the source code. * Licensed as GPL v3. -Known limitations: - -* Files higher than 4 GiB cannot be managed and will produce unexpected outputs in Windows: be warned! - Before compiling, check in triops.h that next values correctly adjust to your platform, modifying them as convenient: diff --git a/triops.c b/triops.c index b0b276c..a8aa4bd 100644 --- a/triops.c +++ b/triops.c @@ -75,7 +75,7 @@ int getch(void); -#define TRIOPS_VERSION "7.2.2" +#define TRIOPS_VERSION "7.3" #define PROGRAM_NAME "triops" #define BUFFERSIZE 16384 // for CHACHA20: multiple of 64 bytes to avoid bad implementation (http://goo.gl/DHCLz1) @@ -344,13 +344,6 @@ int local_triops (int argc, char* const argv[static 4]) } #endif - // obtain password from file: - if (!obtainPassword (szPassFile, szPass)) - { - printf ("\nCould not obtain password.\nAborted.\n\n"); - return 1; - } - // if output is to the same file, modification timestamp is preserved if (bOutputToTheSameFile) { #ifndef WINDOWS_PLATFORM @@ -373,6 +366,71 @@ int local_triops (int argc, char* const argv[static 4]) return 1; } + + // encrypting: + // Add encrypted file extension to file's name if we're written to another file. + // If we're written to the same file, this process is made at the end. + if (bEncrypt && !bOutputToTheSameFile) { + szNewFile[strlen(szNewFile)+4]=0x0; // the end of string after the extension addition + if (triopsVersion==TRIOPS_V3) + memcpy(szNewFile+strlen(szNewFile), TRIOPS_V3_EXTENSION, 4); + } + + // encrypting/decrypting to a new file: + // check that destination file does not exist yet (do not overwrite in that case): + if (!bOutputToTheSameFile) { + hFileOut = fopen(szNewFile, "rb" ); + if (hFileOut != NULL) + { + printf ("\nError: Destination file already exists: %s\n" + "\tProcess aborted (nothing has been done).\n\n", szNewFile); + fclose(hFileOut); + return 1; + } + // once checked that destination file doesn't exist, open said destination file: + // moved AFTER password has been checked, not to create a superfluous empty file. + /*hFileOut = fopen(szNewFile, "wb" ); + if (hFileOut == NULL) + { + printf ("\nError opening %s\n\n", szNewFile); + return 1; + }*/ + } + else + { + // encrypting/decrypting to the "same" file: + // check that destination file does not exist yet (do not overwrite in that case): + char szDestinationFile [MAX_PATH]; + strcpy(szDestinationFile, szFile); + if (!bEncrypt) { + // !bEncrypt && bOutputToTheSameFile + szDestinationFile[strlen(szDestinationFile)-4]=0x0; + } else { + // bEncrypt && bOutputToTheSameFile + if (triopsVersion==TRIOPS_V3) + memcpy(szDestinationFile+strlen(szDestinationFile), TRIOPS_V3_EXTENSION, 4); + szDestinationFile[strlen(szDestinationFile)+4]=0x0; + } + // check that destination file does not exist yet (do not overwrite in that case): + hFileOut = fopen(szDestinationFile, "rb" ); + if (hFileOut != NULL) + { + printf ( "\nError: Destination file exists: %s\n" + "\tProcess aborted (nothing has been done).\n\n", szDestinationFile ); + fclose(hFileOut); + return 1; + } + } + + + // obtain password from file: + if (!obtainPassword (szPassFile, szPass)) + { + printf ("\nCould not obtain password.\nProcess aborted.\n\n"); + return 1; + } + + if (!bEncrypt) { if (triopsVersion==TRIOPS_V3) LoadIVandHash_v3 (hFile, iv_v3.byteIV, hashedKey_v3.keyB, szFile); @@ -406,6 +464,17 @@ int local_triops (int argc, char* const argv[static 4]) // password isn't needed anymore: overwrite variables as a paranoic security measure: EliminatePasswords(szPassFile, szPass); + // AFTER password has been checked, (not to create a superfluous empty file), and + // once checked that destination file doesn't exist (upper code), open said destination file: + if (!bOutputToTheSameFile) { + hFileOut = fopen(szNewFile, "wb" ); + if (hFileOut == NULL) + { + printf ("\nError opening %s\n\n", szNewFile); + return 1; + } + } + // if process arrives here, the password has been checked as correct and // it's gonna decrypt, so hash can be erased from tail now. if (!bEncrypt && bOutputToTheSameFile) { @@ -420,31 +489,6 @@ int local_triops (int argc, char* const argv[static 4]) } } - // Add encrypted file extension to file's name if we're written to another file. - // If we're written to the same file, this process is made at the end. - if (bEncrypt && !bOutputToTheSameFile) { - szNewFile[strlen(szNewFile)+4]=0x0; // the end of string after the extension addition - if (triopsVersion==TRIOPS_V3) - memcpy(szNewFile+strlen(szNewFile), TRIOPS_V3_EXTENSION, 4); - } - - // check that destination file does not exist yet (do not overwrite in that case): - if (!bOutputToTheSameFile) { - hFileOut = fopen(szNewFile, "rb" ); - if (hFileOut != NULL) - { - printf ("\nError: Destination file already exists: %s\n\n", szNewFile); - fclose(hFileOut); - return 1; - } - // once checked that destination file doesn't exist, open said destination file: - hFileOut = fopen(szNewFile, "wb" ); - if (hFileOut == NULL) - { - printf ("\nError opening %s\n\n", szNewFile); - return 1; - } - } // use the IV to create a unique key for this file if (triopsVersion==TRIOPS_V3) { @@ -455,6 +499,7 @@ int local_triops (int argc, char* const argv[static 4]) for (i=0; irand1=rand()*rand(); iv->rand1=rand()*rand(); + lFileSize=FileSize( szFile ); + iv->rand1=rand()*rand(); + /*printf("\n = %02lx",iv->rand1);*/ iv->fileTime=fileStat.st_atime; + /*printf("\n = %02lx",iv->fileTime);*/ + + memcpy( cTempData, (unsigned char *)&lFileSize, 8 ); + memcpy( cTempData+8, (unsigned char *)&(iv->rand1), 4 ); + memcpy( cTempData+8+4, (unsigned char *)&(iv->fileTime), 4 ); + /* + printf ("\niv: "); + for (i=0; i<16; i++) printf(" %02lx",cTempData[i]); + */ // ok, now let's hash iv in order to obscure IV: // hash from iv, in cTempHash: - crypto_hash(cTempHash, (unsigned char *)iv, IVSIZE_v3); + crypto_hash(cTempHash, cTempData, 8+4+4); // as KECCAK-512 produces 512 bits, let's get just some bytes: for (i=0; i < 8; i++) { ((unsigned char*)iv)[i] = cTempHash[i*4]; } + /* + printf ("\niv: "); + for (i=0; i<2; i++) printf(" %02lx",((uint32_t*)iv)[i]); + */ // test IV: //+++++++++++++++++++++++++++++++++++++++++++ diff --git a/triops.h b/triops.h index 2a26189..c237b19 100644 --- a/triops.h +++ b/triops.h @@ -8,6 +8,14 @@ #ifndef TRIOPS_H_ #define TRIOPS_H_ +// ................................................. +// large file support (LFS) (files with size >2^31 (2 GiB) in linux, and >4 GiB in Windows) +#define _FILE_OFFSET_BITS 64 // stat, fseek +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE // off64_t for fseek64 +#define ZERO_LL 0LL // crafted specially to be used in FSEEK( , , SEEK_END); +// ................................................. + // ................................................. #undef WINDOWS_PLATFORM // Compile for Unix or for Windows: #undef o #define // this just includes (*nix) or don't (windows) "windef.h" @@ -28,16 +36,17 @@ #ifndef WINDOWS_PLATFORM #include "windef.h" // Windows types definitions #include // to change the modification time (and so to preverve the original one) +#define FSEEK fseeko // (LFS) #else #include #include // to use GetFileTime and SetFileTime (on Unix I use utime) +#include // _chsize_s, _open (LFS) +#define FSEEK _fseeki64 // large file support in windows (LFS) #endif #include #include // open, etc. #ifndef WINDOWS_PLATFORM #include // truncate -#else -#include // I use fopen(), not open(), except in truncateFile() #endif