bencrypt.c - dedup - deduplicating backup program
HTML git clone git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/
DIR Log
DIR Files
DIR Refs
DIR Tags
DIR README
DIR LICENSE
---
bencrypt.c (7144B)
---
1 /* Encryption layer implementation */
2 #include <sys/types.h>
3 #include <sys/stat.h>
4
5 #include <assert.h>
6 #include <fcntl.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <strings.h>
12 #include <unistd.h>
13
14 #include <sodium.h>
15
16 #include "block.h"
17 #include "config.h"
18 #include "misc.h"
19 #include "state.h"
20
21 extern struct param param;
22
23 #define EDNONETYPE 0x300
24 #define EDCHACHATYPE 0x301
25 #define NONCESIZE crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
26 #define EDSIZE (8 + 8 + NONCESIZE)
27
28 extern int pack(unsigned char *, char *, ...);
29 extern int unpack(unsigned char *, char *, ...);
30
31 static int becreat(struct bctx *bctx, char *path, int mode);
32 static int beopen(struct bctx *bctx, char *path, int flags, int mode);
33 static int beput(struct bctx *bctx, void *buf, size_t n, unsigned char *md);
34 static int beget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n);
35 static int berm(struct bctx *bctx, unsigned char *md);
36 static int begc(struct bctx *bctx);
37 static int besync(struct bctx *bctx);
38 static int beclose(struct bctx *bctx);
39
40 static struct bops bops = {
41 .creat = becreat,
42 .open = beopen,
43 .put = beput,
44 .get = beget,
45 .rm = berm,
46 .gc = begc,
47 .sync = besync,
48 .close = beclose,
49 };
50
51 /* Encryption layer context */
52 struct ectx {
53 int type; /* encryption algorithm type for new blocks */
54 };
55
56 /* Encryption descriptor */
57 struct ed {
58 uint16_t type; /* encryption algorithm type */
59 unsigned char reserved[6]; /* should be set to 0 when writing */
60 uint64_t size; /* size of encrypted block */
61 unsigned char nonce[NONCESIZE]; /* unpredictable nonce used when encrypting */
62 };
63
64 /* Unpack encryption descriptor */
65 static int
66 unpacked(unsigned char *buf, struct ed *ed)
67 {
68 char fmt[BUFSIZ];
69 int n;
70
71 snprintf(fmt, sizeof(fmt), "s'6q'%d", NONCESIZE);
72 n = unpack(buf, fmt,
73 &ed->type,
74 ed->reserved,
75 &ed->size,
76 ed->nonce);
77
78 assert(n == EDSIZE);
79 return n;
80 }
81
82 /* Pack encryption descriptor */
83 static int
84 packed(unsigned char *buf, struct ed *ed)
85 {
86 char fmt[BUFSIZ];
87 int n;
88
89 snprintf(fmt, sizeof(fmt), "s'6q'%d", NONCESIZE);
90 n = pack(buf, fmt,
91 ed->type,
92 ed->reserved,
93 ed->size,
94 ed->nonce);
95
96 assert(n == EDSIZE);
97 return n;
98 }
99
100 static int
101 becreat(struct bctx *bctx, char *path, int mode)
102 {
103 struct ectx *ectx;
104 int type;
105
106 /* Determine algorithm type */
107 if (strcasecmp(param.ealgo, "none") == 0) {
108 type = EDNONETYPE;
109 } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) {
110 type = EDCHACHATYPE;
111 } else {
112 seterr("invalid encryption type: %s", param.ealgo);
113 return -1;
114 }
115
116 /* Ensure a key has been provided if caller requested encryption */
117 if (type != EDNONETYPE && !param.keyloaded) {
118 seterr("expected encryption key");
119 return -1;
120 }
121
122 if (sodium_init() < 0) {
123 seterr("sodium_init: failed");
124 return -1;
125 }
126
127 bctx->ectx = calloc(1, sizeof(struct ectx));
128 if (bctx->ectx == NULL) {
129 seterr("calloc: out of memory");
130 return -1;
131 }
132 ectx = bctx->ectx;
133 ectx->type = type;
134
135 if (bstorageops()->creat(bctx, path, mode) < 0) {
136 free(ectx);
137 return -1;
138 }
139 return 0;
140 }
141
142 static int
143 beopen(struct bctx *bctx, char *path, int flags, int mode)
144 {
145 struct ectx *ectx;
146 int type;
147
148 /* Determine algorithm type */
149 if (strcasecmp(param.ealgo, "none") == 0) {
150 type = EDNONETYPE;
151 } else if (strcasecmp(param.ealgo, "XChaCha20-Poly1305") == 0) {
152 type = EDCHACHATYPE;
153 } else {
154 seterr("invalid encryption type: %s", param.ealgo);
155 return -1;
156 }
157
158 /* Ensure a key has been provided if caller requested encryption */
159 if (type != EDNONETYPE && !param.keyloaded) {
160 seterr("expected encryption key");
161 return -1;
162 }
163
164 if (sodium_init() < 0) {
165 seterr("sodium_init: failed");
166 return -1;
167 }
168
169 bctx->ectx = calloc(1, sizeof(struct ectx));
170 if (bctx->ectx == NULL) {
171 seterr("calloc: out of memory");
172 return -1;
173 }
174 ectx = bctx->ectx;
175 ectx->type = type;
176
177 if (bstorageops()->open(bctx, path, flags, mode) < 0) {
178 free(ectx);
179 return -1;
180 }
181 return 0;
182 }
183
184 static int
185 beput(struct bctx *bctx, void *buf, size_t n, unsigned char *md)
186 {
187 struct ectx *ectx;
188 struct ed ed;
189 unsigned char *ebuf;
190 unsigned long long elen;
191 size_t en;
192
193 /* Calculate size of encrypted block */
194 ectx = bctx->ectx;
195 switch (ectx->type) {
196 case EDNONETYPE:
197 en = n;
198 break;
199 case EDCHACHATYPE:
200 en = n + crypto_aead_xchacha20poly1305_ietf_ABYTES;
201 break;
202 }
203
204 ebuf = malloc(EDSIZE + en);
205 if (ebuf == NULL) {
206 seterr("malloc: out of memory");
207 return -1;
208 }
209
210 /* Prepare encryption descriptor */
211 ed.type = ectx->type;
212 memset(ed.reserved, 0, sizeof(ed.reserved));
213 ed.size = en;
214
215 /* Fill nonce buffer */
216 switch (ectx->type) {
217 case EDNONETYPE:
218 memset(ed.nonce, 0, sizeof(ed.nonce));
219 break;
220 case EDCHACHATYPE:
221 randombytes_buf(ed.nonce, sizeof(ed.nonce));
222 break;
223 }
224
225 /* Prepend encryption descriptor */
226 packed(ebuf, &ed);
227
228 /* Encrypt block */
229 switch (ectx->type) {
230 case EDNONETYPE:
231 memcpy(&ebuf[EDSIZE], buf, en);
232 break;
233 case EDCHACHATYPE:
234 crypto_aead_xchacha20poly1305_ietf_encrypt(&ebuf[EDSIZE], &elen,
235 buf, n, ebuf, EDSIZE, NULL,
236 ed.nonce, param.key);
237 assert(elen == en);
238 break;
239 }
240
241 if (bstorageops()->put(bctx, ebuf, EDSIZE + en, md) < 0) {
242 free(ebuf);
243 return -1;
244 }
245
246 free(ebuf);
247 return ed.size;
248 }
249
250 static int
251 beget(struct bctx *bctx, unsigned char *md, void *buf, size_t *n)
252 {
253 struct ed ed;
254 struct ectx *ectx;
255 unsigned char *ebuf;
256 unsigned long long dlen;
257 size_t dn, size;
258
259 /* Calculate maximum size of encrypted block */
260 size = EDSIZE + *n + crypto_aead_xchacha20poly1305_ietf_ABYTES;
261
262 ebuf = malloc(size);
263 if (ebuf == NULL) {
264 seterr("malloc: out of memory");
265 return -1;
266 }
267
268 if (bstorageops()->get(bctx, md, ebuf, &size) < 0) {
269 free(ebuf);
270 return -1;
271 }
272
273 unpacked(ebuf, &ed);
274
275 /* Decrypt block */
276 ectx = bctx->ectx;
277 switch (ed.type) {
278 case EDNONETYPE:
279 dn = ed.size;
280 if (*n < dn) {
281 free(ebuf);
282 seterr("buffer too small");
283 return -1;
284 }
285 memcpy(buf, &ebuf[EDSIZE], dn);
286 break;
287 case EDCHACHATYPE:
288 dn = ed.size - crypto_aead_xchacha20poly1305_ietf_ABYTES;
289 if (*n < dn) {
290 free(ebuf);
291 seterr("buffer too small");
292 return -1;
293 }
294
295 if (crypto_aead_xchacha20poly1305_ietf_decrypt(buf, &dlen,
296 NULL,
297 &ebuf[EDSIZE], ed.size,
298 ebuf, EDSIZE,
299 ed.nonce, param.key) < 0) {
300 free(ebuf);
301 seterr("authentication failed");
302 return -1;
303 }
304
305 assert(dn == dlen);
306 break;
307 }
308
309 free(ebuf);
310 *n = dn;
311 return 0;
312 }
313
314 static int
315 berm(struct bctx *bctx, unsigned char *md)
316 {
317 return bstorageops()->rm(bctx, md);
318 }
319
320 static int
321 begc(struct bctx *bctx)
322 {
323 return bstorageops()->gc(bctx);
324 }
325
326 static int
327 besync(struct bctx *bctx)
328 {
329 return bstorageops()->sync(bctx);
330 }
331
332 static int
333 beclose(struct bctx *bctx)
334 {
335 struct ectx *ectx = bctx->ectx;
336
337 free(ectx);
338 return bstorageops()->close(bctx);
339 }
340
341 struct bops *
342 bencryptops(void)
343 {
344 return &bops;
345 }