From e5454e63a086e549f54c23a686ff300b99a83b58 Mon Sep 17 00:00:00 2001 From: "@syxhe" Date: Fri, 4 Apr 2025 21:04:18 -0500 Subject: Make decryptto function also use named temporary files for writing --- src/Makefile | 18 ++++++++------ src/encryption.c | 76 +++++++++++++++++++++++++++++++++----------------------- src/encryption.h | 14 +++++++++-- 3 files changed, 67 insertions(+), 41 deletions(-) diff --git a/src/Makefile b/src/Makefile index 4450727..53cd9fd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,22 +9,24 @@ CFLAGS = -std=c2x -Wall -Wextra -Wpedantic -pedantic-errors -fanalyzer -Wanalyze LDLIBS += $$(pkg-config --libs-only-l libsodium) LDFLAGS += $$(pkg-config --libs-only-L libsodium) - -BINARIES := main +OBJECTS := $(patsubst %.c,%.o, $(wildcard *.c)) .PHONY: all c clean val +.DELETE_ON_ERROR: all: main +main: main.o encryption.o shared.o ll.o arena.o -main: main.o shared.o ll.o arena.o -ll.o: ll.c ll.h shared.h -main.o: main.c shared.h -arena.o: arena.c arena.h shared.h -shared.o: shared.c shared.h +$(OBJECTS): shared.h +ll.o: ll.c ll.h +main.o: main.c +arena.o: arena.c arena.h +shared.o: shared.c shared.h # Might as well put shared.h in here explicitly +encryption.o: encryption.c encryption.h c clean: - rm -rvf $(BINARIES) $(wildcard *.o) $(wildcard *.test*) $(wildcard *.enc) + -rm -rv main $(OBJECTS) $(wildcard *.test*) $(wildcard *.enc) val: $(MAKE) all diff --git a/src/encryption.c b/src/encryption.c index c176d6e..4ff37cc 100644 --- a/src/encryption.c +++ b/src/encryption.c @@ -21,7 +21,7 @@ void naclfaildefault(void *none) { none = none; // Makes gcc happy if(___VXGG___VERBOSE_ERRORS___) - error(1, ENOTSUP, "Couldn't initialize sodium for some reason. Quitting..."); + error(1, ENOTSUP, " Couldn't initialize sodium for some reason. Quitting..."); exit(EXIT_FAILURE); } @@ -59,7 +59,7 @@ void checksodium(void) { if(sodium_init() < 0) { errno = ENOTSUP; - XALLOC_EXIT("Couldn't initialize sodium for some reason. Quitting..."); + XALLOC_EXIT(" Couldn't initialize sodium for some reason. Quitting..."); } #endif @@ -70,9 +70,20 @@ void checksodium(void) { #endif int maketmp(const char * const dest) { + if(!dest) + RETURNWERR(EINVAL, -1); return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); } +int linkto(const char * const target, int tgfd) { + char *path = NULL; + asprintf(&path, "/proc/self/fd/%d", tgfd); + if(!path) + ERROR(1, errno, " Couldn't get path to move file into system",); + remove(target); // Make sure an old version isn't sticking around (it's not catastrophic if this fails, but it should be noted or logged somewhere) + return linkat(AT_FDCWD, path, AT_FDCWD, target, AT_SYMLINK_FOLLOW); +} + int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 checksodium(); @@ -95,24 +106,19 @@ int encryptviatmp(const char * const target, const char * const output, const un FILE *src, *dst; if(!(src = fdopen(fd, "rb"))) - ERROR(1, errno, "Couldn't open \"%s\"", , target); + ERROR(1, errno, " Couldn't open \"%s\"", , target); if(!(dst = fdopen(tfd, "wb"))) - ERROR(1, errno, "Couldn't open \"%s\"", , output); - if(encryptToFile(src, dst, key) < 0) - ERROR(1, ENOTRECOVERABLE, "I don't even have a way to cause an error here. How did you do it?",); + ERROR(1, errno, " Couldn't open \"%s\"", , output); + if(encrypttofile(src, dst, key) < 0) + ERROR(1, ENOTRECOVERABLE, " I don't even have a way to cause an error here. How did you do it?",); // Link the temp file into the system - char *path = NULL; - asprintf(&path, "/proc/self/fd/%d", tfd); - if(!path) - return -1; - remove(output); // Make sure an old version isn't sticking around - linkat(AT_FDCWD, path, AT_FDCWD, output, AT_SYMLINK_FOLLOW); + if(linkto(output, tfd) < 0) + ERROR(1, errno, " Could not link \"%s\" into system after encryption", , output); - free(path); fclose(dst); fclose(src); - // fclose alco closes fd and tfd, as fdopen does not dup the file descriptors + // fclose alco closes fd and tfd, as fdopen does not dup the file descriptors return 0; } @@ -131,27 +137,36 @@ int decryptto(const char * const encrypted, const char * const target, const uns FILE *src, *dst; if(!(src = fopen(encrypted, "rb"))) - ERROR(1, errno, "Could not open \"%s\" for decryption", , encrypted); - if(!(dst = fopen(target, "wb"))) - ERROR(1, errno, "Could not open \"%s\" for writing decrypted data", , target); + ERROR(1, errno, " Could not open \"%s\" for decryption", , encrypted); + + int fdst = maketmp(target); + if(!fdst) + ERROR(1, errno, " Could not get temp file for decryption", ); + if(!(dst = fdopen(fdst, "wb"))) + ERROR(1, errno, " Could not open \"%s\" for writing decrypted data", , target); if(decrypttofile(src, dst, key) < 0) - ERROR(1, errno, "How did you even cause an error?",); + ERROR(1, errno, " How did you even cause an error?",); + + // Link temp into system + if(linkto(target, fdst) < 0) + ERROR(1, errno, " Could not link \"%s\" into system", , target); fclose(dst); fclose(src); + // fclose alco closes fd and tfd, as fdopen does not dup the file descriptors + return 0; } -int encrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { +int encrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { unsigned char buf[CHUNKSIZE], cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; crypto_secretstream_xchacha20poly1305_state state; unsigned long long cbuflen; unsigned char tag; size_t bytesread; - FILE *dst, *src; int eof; #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 @@ -169,33 +184,32 @@ int encrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xc crypto_secretstream_xchacha20poly1305_init_push(&state, header, key); if(fwrite(header, 1, sizeof(header), dst) < sizeof(header)) if(ferror(dst)) - ERROR(1, errno, "Could not write header to \"%s\"",); + ERROR(1, errno, " Could not write header",); // Encrypt each chunk do { if((bytesread = fread(buf, 1, sizeof(buf), src)) < sizeof(buf)) if(ferror(src)) - ERROR(1, errno, "Could not read from source \"%s\"",); + ERROR(1, errno, " Could not read from source",); eof = feof(src); tag = eof ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0; crypto_secretstream_xchacha20poly1305_push(&state, cbuf, &cbuflen, buf, bytesread, NULL, 0, tag); if(fwrite(cbuf, 1, (size_t)cbuflen, dst) < (size_t)cbuflen) if(ferror(dst)) - ERROR(1, errno, "Could not write to target \"%s\"",); + ERROR(1, errno, " Could not write to target",); } while (!eof); return 0; } -int decrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { +int decrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { unsigned char cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES], buf[CHUNKSIZE]; unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; crypto_secretstream_xchacha20poly1305_state state; unsigned long long buflen; unsigned char tag; size_t bytesread; - FILE *dst, *src; int eof; #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 @@ -212,26 +226,26 @@ int decrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xc // Read the header if(fread(header, 1, sizeof(header), src) < sizeof(header)) if(ferror(src)) - ERROR(1, errno, "Couldn't read header", ); + ERROR(1, errno, " Couldn't read header", ); // Make sure the header isn't fuckey if(crypto_secretstream_xchacha20poly1305_init_pull(&state, header, key) != 0) - ERROR(1, errno, "Incomplete header", ); + ERROR(1, errno, " Incomplete header", ); // Decrypt each chunk do { if((bytesread = fread(cbuf, 1, sizeof(cbuf), src)) < sizeof(cbuf)) if(ferror(src)) - ERROR(1, errno, "Ran into problem reading for decryption", ); + ERROR(1, errno, " Ran into problem reading for decryption", ); eof = feof(src); if (crypto_secretstream_xchacha20poly1305_pull(&state, buf, &buflen, &tag, cbuf, bytesread, NULL, 0) != 0) - ERROR(1, errno, "Corrupted chunk", ); + ERROR(1, errno, " Corrupted chunk", ); if(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !eof) - ERROR(1, errno, "End of stream before end of file", ); + ERROR(1, errno, " End of stream before end of file", ); if(eof && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) - ERROR(1, errno, "End of file before end of stream", ); + ERROR(1, errno, " End of file before end of stream", ); fwrite(buf, 1, (size_t)buflen, dst); } while(! eof); diff --git a/src/encryption.h b/src/encryption.h index b5fe04e..b02216f 100644 --- a/src/encryption.h +++ b/src/encryption.h @@ -90,12 +90,22 @@ void vxgg_setsodiumfailcb(const vxgg_naclfailcb cb, void *data); // open() with the flags O_TMPFILE, O_WRONLY, O_CLOEXEC, and O_SYNC. Opened with mode S_IRUSR, S_IWUSR int maketmp(const char * const dest); -int encrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); -int decrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); +// Encrypt src to dst using libsodium's xchacha encryption suite +int encrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); +// Decrypt src to dst using libsodium's xchacha encryption suite +int decrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); + +// Encrypt file at `target` to `output` using Linux's named temp file system to do it in the background int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); + +// Decrypt the file at `encrypted` to `target` int decryptto(const char * const encrypted, const char * const target, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); +// +int linkto(const char * const target, int tgfd); + +// int genpassword(char **str, unsigned int words); #endif \ No newline at end of file -- cgit v1.2.3