diff options
| -rw-r--r-- | src/Makefile | 18 | ||||
| -rw-r--r-- | src/encryption.c | 76 | ||||
| -rw-r--r-- | 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 | |||
| 9 | LDLIBS += $$(pkg-config --libs-only-l libsodium) | 9 | LDLIBS += $$(pkg-config --libs-only-l libsodium) |
| 10 | LDFLAGS += $$(pkg-config --libs-only-L libsodium) | 10 | LDFLAGS += $$(pkg-config --libs-only-L libsodium) |
| 11 | 11 | ||
| 12 | 12 | OBJECTS := $(patsubst %.c,%.o, $(wildcard *.c)) | |
| 13 | BINARIES := main | ||
| 14 | 13 | ||
| 15 | .PHONY: all c clean val | 14 | .PHONY: all c clean val |
| 15 | .DELETE_ON_ERROR: | ||
| 16 | 16 | ||
| 17 | all: main | 17 | all: main |
| 18 | main: main.o encryption.o shared.o ll.o arena.o | ||
| 18 | 19 | ||
| 19 | main: main.o shared.o ll.o arena.o | ||
| 20 | 20 | ||
| 21 | ll.o: ll.c ll.h shared.h | 21 | $(OBJECTS): shared.h |
| 22 | main.o: main.c shared.h | 22 | ll.o: ll.c ll.h |
| 23 | arena.o: arena.c arena.h shared.h | 23 | main.o: main.c |
| 24 | shared.o: shared.c shared.h | 24 | arena.o: arena.c arena.h |
| 25 | shared.o: shared.c shared.h # Might as well put shared.h in here explicitly | ||
| 26 | encryption.o: encryption.c encryption.h | ||
| 25 | 27 | ||
| 26 | c clean: | 28 | c clean: |
| 27 | rm -rvf $(BINARIES) $(wildcard *.o) $(wildcard *.test*) $(wildcard *.enc) | 29 | -rm -rv main $(OBJECTS) $(wildcard *.test*) $(wildcard *.enc) |
| 28 | 30 | ||
| 29 | val: | 31 | val: |
| 30 | $(MAKE) all | 32 | $(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 @@ | |||
| 21 | void naclfaildefault(void *none) { | 21 | void naclfaildefault(void *none) { |
| 22 | none = none; // Makes gcc happy | 22 | none = none; // Makes gcc happy |
| 23 | if(___VXGG___VERBOSE_ERRORS___) | 23 | if(___VXGG___VERBOSE_ERRORS___) |
| 24 | error(1, ENOTSUP, "Couldn't initialize sodium for some reason. Quitting..."); | 24 | error(1, ENOTSUP, "<naclfaildefault> Couldn't initialize sodium for some reason. Quitting..."); |
| 25 | exit(EXIT_FAILURE); | 25 | exit(EXIT_FAILURE); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| @@ -59,7 +59,7 @@ void checksodium(void) { | |||
| 59 | 59 | ||
| 60 | if(sodium_init() < 0) { | 60 | if(sodium_init() < 0) { |
| 61 | errno = ENOTSUP; | 61 | errno = ENOTSUP; |
| 62 | XALLOC_EXIT("Couldn't initialize sodium for some reason. Quitting..."); | 62 | XALLOC_EXIT("<checksodium> Couldn't initialize sodium for some reason. Quitting..."); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | #endif | 65 | #endif |
| @@ -70,9 +70,20 @@ void checksodium(void) { | |||
| 70 | #endif | 70 | #endif |
| 71 | 71 | ||
| 72 | int maketmp(const char * const dest) { | 72 | int maketmp(const char * const dest) { |
| 73 | if(!dest) | ||
| 74 | RETURNWERR(EINVAL, -1); | ||
| 73 | return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); | 75 | return open(dest, (O_TMPFILE | O_WRONLY | O_CLOEXEC | O_SYNC), (S_IRUSR | S_IWUSR)); |
| 74 | } | 76 | } |
| 75 | 77 | ||
| 78 | int linkto(const char * const target, int tgfd) { | ||
| 79 | char *path = NULL; | ||
| 80 | asprintf(&path, "/proc/self/fd/%d", tgfd); | ||
| 81 | if(!path) | ||
| 82 | ERROR(1, errno, "<linkto> Couldn't get path to move file into system",); | ||
| 83 | 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) | ||
| 84 | return linkat(AT_FDCWD, path, AT_FDCWD, target, AT_SYMLINK_FOLLOW); | ||
| 85 | } | ||
| 86 | |||
| 76 | int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | 87 | int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { |
| 77 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 88 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| 78 | checksodium(); | 89 | checksodium(); |
| @@ -95,24 +106,19 @@ int encryptviatmp(const char * const target, const char * const output, const un | |||
| 95 | 106 | ||
| 96 | FILE *src, *dst; | 107 | FILE *src, *dst; |
| 97 | if(!(src = fdopen(fd, "rb"))) | 108 | if(!(src = fdopen(fd, "rb"))) |
| 98 | ERROR(1, errno, "Couldn't open \"%s\"", , target); | 109 | ERROR(1, errno, "<encryptviatmp> Couldn't open \"%s\"", , target); |
| 99 | if(!(dst = fdopen(tfd, "wb"))) | 110 | if(!(dst = fdopen(tfd, "wb"))) |
| 100 | ERROR(1, errno, "Couldn't open \"%s\"", , output); | 111 | ERROR(1, errno, "<encryptviatmp> Couldn't open \"%s\"", , output); |
| 101 | if(encryptToFile(src, dst, key) < 0) | 112 | if(encrypttofile(src, dst, key) < 0) |
| 102 | ERROR(1, ENOTRECOVERABLE, "I don't even have a way to cause an error here. How did you do it?",); | 113 | ERROR(1, ENOTRECOVERABLE, "<encryptviatmp> I don't even have a way to cause an error here. How did you do it?",); |
| 103 | 114 | ||
| 104 | // Link the temp file into the system | 115 | // Link the temp file into the system |
| 105 | char *path = NULL; | 116 | if(linkto(output, tfd) < 0) |
| 106 | asprintf(&path, "/proc/self/fd/%d", tfd); | 117 | ERROR(1, errno, "<encryptviatmp> Could not link \"%s\" into system after encryption", , output); |
| 107 | if(!path) | ||
| 108 | return -1; | ||
| 109 | remove(output); // Make sure an old version isn't sticking around | ||
| 110 | linkat(AT_FDCWD, path, AT_FDCWD, output, AT_SYMLINK_FOLLOW); | ||
| 111 | 118 | ||
| 112 | free(path); | ||
| 113 | fclose(dst); | 119 | fclose(dst); |
| 114 | fclose(src); | 120 | fclose(src); |
| 115 | // fclose alco closes fd and tfd, as fdopen does not dup the file descriptors | 121 | // fclose alco closes fd and tfd, as fdopen does not dup the file descriptors |
| 116 | 122 | ||
| 117 | return 0; | 123 | return 0; |
| 118 | } | 124 | } |
| @@ -131,27 +137,36 @@ int decryptto(const char * const encrypted, const char * const target, const uns | |||
| 131 | 137 | ||
| 132 | FILE *src, *dst; | 138 | FILE *src, *dst; |
| 133 | if(!(src = fopen(encrypted, "rb"))) | 139 | if(!(src = fopen(encrypted, "rb"))) |
| 134 | ERROR(1, errno, "Could not open \"%s\" for decryption", , encrypted); | 140 | ERROR(1, errno, "<decryptto> Could not open \"%s\" for decryption", , encrypted); |
| 135 | if(!(dst = fopen(target, "wb"))) | 141 | |
| 136 | ERROR(1, errno, "Could not open \"%s\" for writing decrypted data", , target); | 142 | int fdst = maketmp(target); |
| 143 | if(!fdst) | ||
| 144 | ERROR(1, errno, "<decryptto> Could not get temp file for decryption", ); | ||
| 145 | if(!(dst = fdopen(fdst, "wb"))) | ||
| 146 | ERROR(1, errno, "<decryptto> Could not open \"%s\" for writing decrypted data", , target); | ||
| 137 | 147 | ||
| 138 | if(decrypttofile(src, dst, key) < 0) | 148 | if(decrypttofile(src, dst, key) < 0) |
| 139 | ERROR(1, errno, "How did you even cause an error?",); | 149 | ERROR(1, errno, "<decryptto> How did you even cause an error?",); |
| 150 | |||
| 151 | // Link temp into system | ||
| 152 | if(linkto(target, fdst) < 0) | ||
| 153 | ERROR(1, errno, "<decryptto> Could not link \"%s\" into system", , target); | ||
| 140 | 154 | ||
| 141 | fclose(dst); | 155 | fclose(dst); |
| 142 | fclose(src); | 156 | fclose(src); |
| 157 | // fclose alco closes fd and tfd, as fdopen does not dup the file descriptors | ||
| 158 | |||
| 143 | 159 | ||
| 144 | return 0; | 160 | return 0; |
| 145 | } | 161 | } |
| 146 | 162 | ||
| 147 | int encrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | 163 | int encrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { |
| 148 | unsigned char buf[CHUNKSIZE], cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; | 164 | unsigned char buf[CHUNKSIZE], cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES]; |
| 149 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | 165 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; |
| 150 | crypto_secretstream_xchacha20poly1305_state state; | 166 | crypto_secretstream_xchacha20poly1305_state state; |
| 151 | unsigned long long cbuflen; | 167 | unsigned long long cbuflen; |
| 152 | unsigned char tag; | 168 | unsigned char tag; |
| 153 | size_t bytesread; | 169 | size_t bytesread; |
| 154 | FILE *dst, *src; | ||
| 155 | int eof; | 170 | int eof; |
| 156 | 171 | ||
| 157 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 172 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| @@ -169,33 +184,32 @@ int encrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xc | |||
| 169 | crypto_secretstream_xchacha20poly1305_init_push(&state, header, key); | 184 | crypto_secretstream_xchacha20poly1305_init_push(&state, header, key); |
| 170 | if(fwrite(header, 1, sizeof(header), dst) < sizeof(header)) | 185 | if(fwrite(header, 1, sizeof(header), dst) < sizeof(header)) |
| 171 | if(ferror(dst)) | 186 | if(ferror(dst)) |
| 172 | ERROR(1, errno, "Could not write header to \"%s\"",); | 187 | ERROR(1, errno, "<encrypttofile> Could not write header",); |
| 173 | 188 | ||
| 174 | // Encrypt each chunk | 189 | // Encrypt each chunk |
| 175 | do { | 190 | do { |
| 176 | if((bytesread = fread(buf, 1, sizeof(buf), src)) < sizeof(buf)) | 191 | if((bytesread = fread(buf, 1, sizeof(buf), src)) < sizeof(buf)) |
| 177 | if(ferror(src)) | 192 | if(ferror(src)) |
| 178 | ERROR(1, errno, "Could not read from source \"%s\"",); | 193 | ERROR(1, errno, "<encrypttofile> Could not read from source",); |
| 179 | eof = feof(src); | 194 | eof = feof(src); |
| 180 | tag = eof ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0; | 195 | tag = eof ? crypto_secretstream_xchacha20poly1305_TAG_FINAL : 0; |
| 181 | 196 | ||
| 182 | crypto_secretstream_xchacha20poly1305_push(&state, cbuf, &cbuflen, buf, bytesread, NULL, 0, tag); | 197 | crypto_secretstream_xchacha20poly1305_push(&state, cbuf, &cbuflen, buf, bytesread, NULL, 0, tag); |
| 183 | if(fwrite(cbuf, 1, (size_t)cbuflen, dst) < (size_t)cbuflen) | 198 | if(fwrite(cbuf, 1, (size_t)cbuflen, dst) < (size_t)cbuflen) |
| 184 | if(ferror(dst)) | 199 | if(ferror(dst)) |
| 185 | ERROR(1, errno, "Could not write to target \"%s\"",); | 200 | ERROR(1, errno, "<encrypttofile> Could not write to target",); |
| 186 | } while (!eof); | 201 | } while (!eof); |
| 187 | 202 | ||
| 188 | return 0; | 203 | return 0; |
| 189 | } | 204 | } |
| 190 | 205 | ||
| 191 | int decrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { | 206 | int decrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { |
| 192 | unsigned char cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES], buf[CHUNKSIZE]; | 207 | unsigned char cbuf[CHUNKSIZE + crypto_secretstream_xchacha20poly1305_ABYTES], buf[CHUNKSIZE]; |
| 193 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; | 208 | unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; |
| 194 | crypto_secretstream_xchacha20poly1305_state state; | 209 | crypto_secretstream_xchacha20poly1305_state state; |
| 195 | unsigned long long buflen; | 210 | unsigned long long buflen; |
| 196 | unsigned char tag; | 211 | unsigned char tag; |
| 197 | size_t bytesread; | 212 | size_t bytesread; |
| 198 | FILE *dst, *src; | ||
| 199 | int eof; | 213 | int eof; |
| 200 | 214 | ||
| 201 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 | 215 | #if ___VXGG___ALWAYS_CHECK_LIBSODIUM___ > 0 |
| @@ -212,26 +226,26 @@ int decrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xc | |||
| 212 | // Read the header | 226 | // Read the header |
| 213 | if(fread(header, 1, sizeof(header), src) < sizeof(header)) | 227 | if(fread(header, 1, sizeof(header), src) < sizeof(header)) |
| 214 | if(ferror(src)) | 228 | if(ferror(src)) |
| 215 | ERROR(1, errno, "Couldn't read header", ); | 229 | ERROR(1, errno, "<decrypttofile> Couldn't read header", ); |
| 216 | 230 | ||
| 217 | // Make sure the header isn't fuckey | 231 | // Make sure the header isn't fuckey |
| 218 | if(crypto_secretstream_xchacha20poly1305_init_pull(&state, header, key) != 0) | 232 | if(crypto_secretstream_xchacha20poly1305_init_pull(&state, header, key) != 0) |
| 219 | ERROR(1, errno, "Incomplete header", ); | 233 | ERROR(1, errno, "<decrypttofile> Incomplete header", ); |
| 220 | 234 | ||
| 221 | // Decrypt each chunk | 235 | // Decrypt each chunk |
| 222 | do { | 236 | do { |
| 223 | if((bytesread = fread(cbuf, 1, sizeof(cbuf), src)) < sizeof(cbuf)) | 237 | if((bytesread = fread(cbuf, 1, sizeof(cbuf), src)) < sizeof(cbuf)) |
| 224 | if(ferror(src)) | 238 | if(ferror(src)) |
| 225 | ERROR(1, errno, "Ran into problem reading for decryption", ); | 239 | ERROR(1, errno, "<decrypttofile> Ran into problem reading for decryption", ); |
| 226 | eof = feof(src); | 240 | eof = feof(src); |
| 227 | 241 | ||
| 228 | if (crypto_secretstream_xchacha20poly1305_pull(&state, buf, &buflen, &tag, cbuf, bytesread, NULL, 0) != 0) | 242 | if (crypto_secretstream_xchacha20poly1305_pull(&state, buf, &buflen, &tag, cbuf, bytesread, NULL, 0) != 0) |
| 229 | ERROR(1, errno, "Corrupted chunk", ); | 243 | ERROR(1, errno, "<decrypttofile> Corrupted chunk", ); |
| 230 | 244 | ||
| 231 | if(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !eof) | 245 | if(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL && !eof) |
| 232 | ERROR(1, errno, "End of stream before end of file", ); | 246 | ERROR(1, errno, "<decrypttofile> End of stream before end of file", ); |
| 233 | if(eof && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) | 247 | if(eof && tag != crypto_secretstream_xchacha20poly1305_TAG_FINAL) |
| 234 | ERROR(1, errno, "End of file before end of stream", ); | 248 | ERROR(1, errno, "<decrypttofile> End of file before end of stream", ); |
| 235 | 249 | ||
| 236 | fwrite(buf, 1, (size_t)buflen, dst); | 250 | fwrite(buf, 1, (size_t)buflen, dst); |
| 237 | } while(! eof); | 251 | } 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); | |||
| 90 | // open() with the flags O_TMPFILE, O_WRONLY, O_CLOEXEC, and O_SYNC. Opened with mode S_IRUSR, S_IWUSR | 90 | // open() with the flags O_TMPFILE, O_WRONLY, O_CLOEXEC, and O_SYNC. Opened with mode S_IRUSR, S_IWUSR |
| 91 | int maketmp(const char * const dest); | 91 | int maketmp(const char * const dest); |
| 92 | 92 | ||
| 93 | int encrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); | 93 | // Encrypt src to dst using libsodium's xchacha encryption suite |
| 94 | int decrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); | 94 | int encrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); |
| 95 | 95 | ||
| 96 | // Decrypt src to dst using libsodium's xchacha encryption suite | ||
| 97 | int decrypttofile(FILE *src, FILE *dst, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); | ||
| 98 | |||
| 99 | // Encrypt file at `target` to `output` using Linux's named temp file system to do it in the background | ||
| 96 | int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); | 100 | int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); |
| 101 | |||
| 102 | // Decrypt the file at `encrypted` to `target` | ||
| 97 | int decryptto(const char * const encrypted, const char * const target, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); | 103 | int decryptto(const char * const encrypted, const char * const target, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]); |
| 98 | 104 | ||
| 105 | // | ||
| 106 | int linkto(const char * const target, int tgfd); | ||
| 107 | |||
| 108 | // | ||
| 99 | int genpassword(char **str, unsigned int words); | 109 | int genpassword(char **str, unsigned int words); |
| 100 | 110 | ||
| 101 | #endif \ No newline at end of file | 111 | #endif \ No newline at end of file |
