|
|
bencrypt.c - dedup - deduplicating backup program |
|
|
 |
git clone git://bitreich.org/dedup/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/dedup/ (git://bitreich.org) |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
Tags |
|
|
 |
README |
|
|
 |
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 } |
|