summaryrefslogtreecommitdiff
path: root/src/encryption.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/encryption.c')
-rw-r--r--src/encryption.c76
1 files changed, 45 insertions, 31 deletions
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 @@
21void naclfaildefault(void *none) { 21void 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
72int maketmp(const char * const dest) { 72int 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
78int 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
76int encryptviatmp(const char * const target, const char * const output, const unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { 87int 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
147int encrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { 163int 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
191int decrypttofile(FILE *dst, FILE *src, unsigned char key[crypto_secretstream_xchacha20poly1305_KEYBYTES]) { 206int 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);