]>
Commit | Line | Data |
---|---|---|
e3956dfb SP |
1 | #include <stdio.h> |
2 | #include <config.h> | |
3 | #include <sys/mman.h> | |
4 | ||
5 | #ifdef HAVE_OPENSSL | |
6 | #include <openssl/err.h> | |
7 | #include <openssl/evp.h> | |
8 | #include <openssl/rand.h> | |
9 | #include <openssl/pkcs12.h> | |
10 | #endif | |
11 | ||
12 | #ifdef HAVE_ZLIB | |
13 | #include <zlib.h> | |
14 | #endif /* HAVE_ZLIB */ | |
15 | ||
16 | #include "transformation.h" | |
17 | ||
18 | /* | |
19 | * IMPORTANT: this is an important piece of the puzzle for native | |
20 | * support of encrypted backups but Key management is much more | |
21 | * important and much harder. The best encryption algorithms in the | |
22 | * world won't help you if you have to reveal your one key to everyone. | |
23 | * | |
24 | * IMPORTANT: always comply with local laws! Do not modify the source | |
25 | * to give you stronger encryption than permitted by local law. | |
26 | * | |
27 | * ----------------------- | |
28 | * 30-second cryptanalysis | |
29 | * ----------------------- | |
30 | * | |
31 | * This is a known-plaintext problem since many of the encrypted blocks | |
32 | * will start with a BSD inode structure. (It will be compressed binary | |
33 | * data but still (mostly) known.) This means that it is very important | |
34 | * to choose a strong IV. | |
35 | * | |
36 | * The dump tape/file is written by multiple slave processes so we don't | |
37 | * have ready access to an intrinsic value such as tape position. That | |
38 | * leaves random salts that are included in the dump buffer. The salt | |
39 | * doesn't need to be cryptographically strong since it will be published. | |
40 | * | |
41 | * The IV is created by calculating the hash of the salt, a function of | |
42 | * the salt and session key, and the salt again. | |
43 | * | |
44 | * The greatest vulnerability is predictable keys (and weak ciphers | |
45 | * required by local laws). The key should also be protected in memory | |
46 | * while dumping and restoring files but it's not as critical since | |
47 | * anyone able to read the key probably has the ability to read the | |
48 | * filesystem directly. | |
49 | */ | |
50 | ||
51 | /* | |
52 | * Initialize. | |
53 | * | |
54 | * 1. load policy file, select ciphers based on it. | |
55 | * 2. PKCS12 keystore contains certificate (public keys) and | |
56 | * private keys. | |
57 | * 3. private keys can be password-protected individually, and | |
58 | * you can also password-protect the entire keystore. | |
59 | * 4. PKCS12 keystores can be manipulated by openssl, java, | |
60 | * windows apps, more. | |
61 | * | |
62 | * questions: | |
63 | * 1. how to select which keystore? (command line option passed | |
64 | * in as function argument? | |
65 | * 2. how to select which key, if doing restore? | |
66 | * 3. how to pass keystore password(s), if doing restore? | |
67 | */ | |
68 | static int | |
69 | ssl_initialize(Transformation *xform, int enc) | |
70 | { | |
71 | #ifdef HAVE_OPENSSL | |
72 | int keylen; | |
73 | ||
74 | OpenSSL_add_all_algorithms(); // see below */ | |
75 | OpenSSL_add_all_ciphers(); // see below */ | |
76 | OpenSSL_add_all_digests(); // see below */ | |
77 | ERR_load_crypto_strings(); | |
78 | ERR_load_RAND_strings(); | |
79 | ERR_load_ERR_strings(); | |
80 | ||
81 | // read policy file and call those two methods to load acceptable | |
82 | // ciphers and digests. We always want CBC mode, not ECB mode. | |
83 | ||
84 | /* | |
85 | If we are encrypting we need to | |
86 | 1. create a random session key (good random numbers are critical!) | |
87 | 2. read the X509 certificates for everyone who needs to be able to read the dump file - | |
88 | extract the public keys. These certificates may be in a PKCS12 keystore which many | |
89 | applications use. OpenSSL also provides a large number of programs for it. | |
90 | 3. encrypt the session key with the public keys and put it into another PKCS12 keystore. | |
91 | This keystore will be written to the tape in startnewtape(). | |
92 | 4. set up the cipher context. | |
93 | ||
94 | If we are decrypting we need to | |
95 | 1. open our keystore(PKCS12) containing our private keys. The keystore itself may be | |
96 | password protected, the individual keys definitely should be. | |
97 | 2. read the PKCS12 keystore from the tape header. | |
98 | 3. look for matching key ids. If we can't find a match tell the user. | |
99 | 4. we still need to be able to open the private key so get the password somewhere. | |
100 | 5. set up the cipher context. | |
101 | */ | |
102 | ||
103 | // RAND_egd(path); | |
104 | ||
105 | #endif /* HAVE_OPENSSL */ | |
106 | ||
107 | return 0; | |
108 | } | |
109 | ||
110 | /* | |
111 | * Shut down. | |
112 | * | |
113 | * The OpenSSL library may be using a physical crypto device so | |
114 | * we need to make sure we properly release it. | |
115 | */ | |
116 | static int | |
117 | ssl_shutdown(Transformation *xform) | |
118 | { | |
119 | #ifdef HAVE_OPENSSL | |
120 | OPENSSL_cleanse(xform->state.ssl.key, sizeof xform->state.ssl.key); | |
121 | ||
122 | munlock(xform, sizeof(Transformation)); | |
123 | free(xform); | |
124 | ||
125 | /* is this the right method? */ | |
126 | EVP_cleanup(); | |
127 | RAND_cleanup(); | |
128 | free(xform); | |
129 | #endif /* HAVE_OPENSSL */ | |
130 | return 0; | |
131 | } | |
132 | ||
133 | /* | |
134 | * We need to write new crypto header containing the encrypted | |
135 | * session key. | |
136 | */ | |
137 | static int | |
138 | ssl_startNewTape(Transformation *xform, struct tapebuf *tpbin, | |
139 | unsigned long *destlen) | |
140 | { | |
141 | #ifdef HAVE_OPENSSL | |
142 | /* write new TS containing PKCS12 containing encrypted session key. */ | |
143 | #endif /* HAVE_OPENSSL */ | |
144 | ||
145 | return 0; | |
146 | } | |
147 | ||
148 | /* | |
149 | * Start slave process. We need to reinitialize the encryption | |
150 | * engine. | |
151 | */ | |
152 | static int | |
153 | ssl_startDiskIOProcess(Transformation *xform) | |
154 | { | |
155 | #ifdef HAVE_OPENSSL | |
156 | mlock(xform, sizeof(Transformation)); | |
157 | ||
158 | OpenSSL_add_all_algorithms(); // see below */ | |
159 | OpenSSL_add_all_ciphers(); // see below */ | |
160 | OpenSSL_add_all_digests(); // see below */ | |
161 | ERR_load_crypto_strings(); | |
162 | ERR_load_RAND_strings(); | |
163 | ERR_load_ERR_strings(); | |
164 | ||
165 | // Initialize key information with values we obtained from parent | |
166 | // thread's startNewTape(). | |
167 | ||
168 | xform->state.ssl.dataCtx = EVP_CIPHER_CTX_new(); | |
169 | xform->state.ssl.ivCtx = EVP_CIPHER_CTX_new(); | |
170 | #endif /* HAVE_OPENSSL */ | |
171 | ||
172 | return 0; | |
173 | } | |
174 | ||
175 | /* | |
176 | * End of slave process. Clear encryption keys, etc. | |
177 | */ | |
178 | static int | |
179 | ssl_endDiskIOProcess(Transformation *xform) | |
180 | { | |
181 | #ifdef HAVE_OPENSSL | |
182 | EVP_CIPHER_CTX_cleanup(xform->state.ssl.dataCtx); | |
183 | EVP_CIPHER_CTX_cleanup(xform->state.ssl.ivCtx); | |
184 | EVP_CIPHER_CTX_free(xform->state.ssl.dataCtx); | |
185 | EVP_CIPHER_CTX_free(xform->state.ssl.ivCtx); | |
186 | ||
187 | OPENSSL_cleanse(xform->state.ssl.key, sizeof xform->state.ssl.key); | |
188 | ||
189 | munlock(xform, sizeof(Transformation)); | |
190 | free(xform); | |
191 | ||
192 | /* is this the right method? */ | |
193 | EVP_cleanup(); | |
194 | RAND_cleanup(); | |
195 | #endif /* HAVE_OPENSSL */ | |
196 | return 0; | |
197 | } | |
198 | ||
199 | /* | |
200 | * Method to generate 'random' salt and IV. | |
201 | * | |
202 | * The generated salt is 16 bytes long. It is duplicated to get a 256-bit value (to support | |
203 | * 256-bit block ciphers.) | |
204 | * | |
205 | */ | |
206 | #ifdef HAVE_OPENSSL | |
207 | static int | |
208 | generateIV(Transformation *xform, unsigned char *salt, unsigned int *saltlen, | |
209 | unsigned char *iv, unsigned int *ivlen) | |
210 | { | |
211 | unsigned char ivbuffer[64]; | |
212 | unsigned int buflen, y; | |
213 | ||
214 | /* we can use pseudorandom bytes since they're going */ | |
215 | /* to be exposed to any attacker anyway. */ | |
216 | *saltlen = 16; | |
217 | if (xform->enc == 1) { | |
218 | RAND_pseudo_bytes(salt, *saltlen); | |
219 | } | |
220 | memcpy(ivbuffer, salt, 16); | |
221 | ||
222 | /* -decrypt- salt value */ | |
223 | memset(ivbuffer, 0, sizeof(ivbuffer)); | |
224 | EVP_CipherInit_ex(xform->state.ssl.ivCtx, xform->state.ssl.cipher, xform->state.ssl.engine, NULL, NULL, 0); | |
225 | //EVP_CIPHER_CTX_set_key_length(&ctx, 8); | |
226 | EVP_CIPHER_CTX_set_padding(xform->state.ssl.ivCtx, 0); // -nopad | |
227 | EVP_CipherInit_ex(xform->state.ssl.ivCtx, NULL, NULL, xform->state.ssl.key, ivbuffer, 0); | |
228 | buflen = 32; | |
229 | if (!EVP_CipherUpdate(xform->state.ssl.ivCtx, ivbuffer + 16, &buflen, salt, 16)) { | |
230 | y = 32 - buflen; | |
231 | if (!EVP_CipherFinal(xform->state.ssl.ivCtx, ivbuffer + 16 + buflen, &y)) { | |
232 | buflen += y; | |
233 | } else { | |
234 | memset(ivbuffer + 16, 0, 32); | |
235 | } | |
236 | } else { | |
237 | memset(ivbuffer + 16, 0, 32); | |
238 | } | |
239 | memcpy(ivbuffer + 48, salt, 16); | |
240 | ||
241 | /* now digest it. */ | |
242 | EVP_Digest(ivbuffer, 64, iv, ivlen, xform->state.ssl.digest, NULL); | |
243 | ||
244 | return 0; | |
245 | } | |
246 | #endif | |
247 | ||
248 | ||
249 | /* | |
250 | * Encrypt a single chunk of blocks. Each chunk is encrypted | |
251 | * independently so it's critically important to choose a good | |
252 | * initial vector (iv). | |
253 | * | |
254 | * The ciphertext format is: | |
255 | * - 20 bytes of random salt | |
256 | * - encrypted (plaintext . digest(plaintext)) | |
257 | */ | |
258 | static int | |
259 | ssl_compress(Transformation *xform, struct tapebuf *tpbin, | |
260 | unsigned long *destlen, const char *src, int srclen) | |
261 | { | |
262 | #ifdef HAVE_OPENSSL | |
263 | unsigned char salt[16], iv[EVP_MAX_MD_SIZE]; | |
264 | unsigned int saltlen = sizeof(salt); | |
265 | unsigned int ivlen = sizeof(iv); | |
266 | unsigned char digest[EVP_MAX_MD_SIZE]; | |
267 | unsigned int digestlen = 0; | |
268 | char *buf; | |
269 | unsigned int len, len2; | |
270 | ||
271 | len = srclen + 1000; | |
272 | buf = malloc(len); | |
273 | ||
274 | digestlen = sizeof(digest); | |
275 | ||
276 | /* generate salt, put it in header */ | |
277 | generateIV(xform, salt, &saltlen, iv, &ivlen); | |
278 | memcpy(tpbin->buf, salt, saltlen); | |
279 | ||
280 | /* compress the buffer first - increase the entropy */ | |
281 | int compresult; | |
282 | compresult = compress2(buf, destlen, src, srclen, xform->state.ssl.complvl); | |
283 | if (compresult != Z_OK) { | |
284 | printf("unable to compress...\n"); | |
285 | return 0; | |
286 | } | |
287 | ||
288 | EVP_EncryptInit_ex(xform->state.ssl.dataCtx, xform->state.ssl.cipher, xform->state.ssl.engine, NULL, NULL); | |
289 | //EVP_CIPHER_CTX_set_key_length(&ctx, 8); | |
290 | EVP_EncryptInit_ex(xform->state.ssl.dataCtx, NULL, NULL, xform->state.ssl.key, iv); | |
291 | ||
292 | // encrypt content. | |
293 | if (!EVP_EncryptUpdate(xform->state.ssl.dataCtx, tpbin->buf + saltlen, &len, buf, *destlen)) { | |
294 | EVP_CIPHER_CTX_cleanup(xform->state.ssl.dataCtx); | |
295 | ERR_print_errors_fp(stdout); | |
296 | free(buf); | |
297 | return 0; | |
298 | } | |
299 | ||
300 | // calculate digest, add it. | |
301 | EVP_Digest(src, srclen, digest, &digestlen, xform->state.ssl.digest, xform->state.ssl.engine); | |
302 | ||
303 | len2 = *destlen - len - saltlen; | |
304 | if (!EVP_EncryptUpdate(xform->state.ssl.dataCtx, tpbin->buf + saltlen + len, &len2, digest, digestlen)) { | |
305 | EVP_CIPHER_CTX_cleanup(xform->state.ssl.dataCtx); | |
306 | ERR_print_errors_fp(stdout); | |
307 | free(buf); | |
308 | return 0; | |
309 | } | |
310 | ||
311 | len += len2; | |
312 | ||
313 | // finish up | |
314 | len2 = *destlen - len - saltlen; | |
315 | if (!EVP_EncryptFinal(xform->state.ssl.dataCtx, tpbin->buf + saltlen + len, &len2)) { | |
316 | EVP_CIPHER_CTX_cleanup(xform->state.ssl.dataCtx); | |
317 | ERR_print_errors_fp(stdout); | |
318 | free(buf); | |
319 | return 0; | |
320 | } | |
321 | ||
322 | *destlen = len + len2 + saltlen; | |
323 | free(buf); | |
324 | ||
325 | OPENSSL_cleanse(iv, sizeof iv); | |
326 | #endif /* HAVE_OPENSSL */ | |
327 | ||
328 | return 1; | |
329 | } | |
330 | ||
331 | /* | |
332 | * | |
333 | */ | |
334 | static int | |
335 | ssl_decompress(Transformation *xform, struct tapebuf *tpbin, | |
336 | unsigned long *destlen, const char *src, int srclen, char **reason) | |
337 | { | |
338 | #ifdef HAVE_OPENSSL | |
339 | unsigned char salt[16], iv[EVP_MAX_MD_SIZE]; | |
340 | unsigned int saltlen = sizeof(salt); | |
341 | unsigned int ivlen = sizeof(iv); | |
342 | unsigned char digest[EVP_MAX_MD_SIZE]; | |
343 | unsigned int digestlen; | |
344 | char *buf; | |
345 | unsigned int len, len2; | |
346 | ||
347 | digestlen = EVP_MD_size(xform->state.ssl.digest); | |
348 | ||
349 | len = *destlen + 1000; | |
350 | buf = malloc(len); | |
351 | ||
352 | // how to know salt length? | |
353 | memcpy(salt, src, saltlen); | |
354 | generateIV(xform, salt, &saltlen, iv, &ivlen); | |
355 | ||
356 | EVP_DecryptInit_ex(xform->state.ssl.dataCtx, xform->state.ssl.cipher, xform->state.ssl.engine, NULL, NULL); | |
357 | //EVP_CIPHER_CTX_set_key_length(&ctx, 8); | |
358 | EVP_DecryptInit_ex(xform->state.ssl.dataCtx, NULL, NULL, xform->state.ssl.key, iv); | |
359 | ||
360 | if (!EVP_DecryptUpdate(xform->state.ssl.dataCtx, buf, &len, src+saltlen, srclen-saltlen)) { | |
361 | EVP_CIPHER_CTX_cleanup(xform->state.ssl.dataCtx); | |
362 | free(buf); | |
363 | ERR_print_errors_fp(stdout); | |
364 | printf("error 1\n"); | |
365 | return 0; | |
366 | } | |
367 | ||
368 | len2 = *destlen + 1000 - len; | |
369 | if (!EVP_DecryptFinal(xform->state.ssl.dataCtx, buf + len, &len2)) { | |
370 | EVP_CIPHER_CTX_cleanup(xform->state.ssl.dataCtx); | |
371 | free(buf); | |
372 | ERR_print_errors_fp(stdout); | |
373 | printf("error 2\n"); | |
374 | return 0; | |
375 | } | |
376 | len += len2; | |
377 | len -= digestlen; | |
378 | ||
379 | OPENSSL_cleanse(iv, sizeof iv); | |
380 | ||
381 | int cresult; | |
382 | cresult = uncompress(tpbin->buf, destlen, buf, len); | |
383 | switch (cresult) { | |
384 | case Z_OK: | |
385 | *reason = ""; | |
386 | break; | |
387 | case Z_MEM_ERROR: | |
388 | *reason = "not enough memory"; | |
389 | break; | |
390 | case Z_BUF_ERROR: | |
391 | *reason = "buffer too small"; | |
392 | break; | |
393 | case Z_DATA_ERROR: | |
394 | *reason = "data error"; | |
395 | break; | |
396 | default: | |
397 | *reason = "unknown"; | |
398 | } | |
399 | if (cresult != Z_OK) { | |
400 | printf("compression failed: %s\n", *reason); | |
401 | free(buf); | |
402 | return 0; | |
403 | } | |
404 | ||
405 | /* verify digest */ | |
406 | EVP_Digest(tpbin->buf, *destlen, digest, &digestlen, xform->state.ssl.digest, xform->state.ssl.engine); | |
407 | ||
408 | if (memcmp(buf + len, digest, digestlen)) { | |
409 | *reason = "digests did not match"; | |
410 | return 0; | |
411 | } | |
412 | ||
413 | free(buf); | |
414 | ||
415 | #endif /* HAVE_OPENSSL */ | |
416 | ||
417 | return 1; | |
418 | } | |
419 | ||
420 | /* | |
421 | * | |
422 | */ | |
423 | #if 0 | |
424 | static int | |
425 | ssl_compress_ts_addr(char *state, struct tapebuf *comp_buf, | |
426 | unsigned int *worklen, char *data, int writesize, int compressed) | |
427 | { | |
428 | #ifdef HAVE_OPENSSL | |
429 | SSLState *s = (SSLState *) state; | |
430 | unsigned char iv[32]; | |
431 | unsigned int len; | |
432 | ||
433 | EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *) malloc(sizeof(EVP_CIPHER_CTX)); | |
434 | ||
435 | //EVP_BytesToKey(cipher, EVP_md5(), NULL, buf, strlen(buf), 1, key, iv); | |
436 | ||
437 | //EVP_CIPHER_CTX_init(ctx); | |
438 | //EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, do_encrypt); | |
439 | //blocksize = EVP_CIPHER_CTX_block_size(ctx); | |
440 | ||
441 | s->digest = EVP_md_null; | |
442 | s->cipher = EVP_enc_null; | |
443 | EVP_CIPHER_CTX_init(s->ctx); | |
444 | ||
445 | /* calculate 'random' IV. */ | |
446 | EVP_MD_CTX_init(&md); | |
447 | EVP_DigestInit_ex(s->md, s->md, NULL); | |
448 | /* EVP_DigestUpdate(s->md, x, len); <-- use logical record number */ | |
449 | EVP_DigestUpdate(s->md, s->salt, s->saltlen); | |
450 | len = sizeof(iv); | |
451 | EVP_DigestFinal(s->md, iv, &len); | |
452 | ||
453 | // mlock on state info... | |
454 | ||
455 | /* do the actual encryption */ | |
456 | EVP_CipherInit(s->ctx, s->cipher, s->key, iv); | |
457 | EVP_CipherUpdate(s->ctx, out, &n, buf, buflen); | |
458 | EVP_CipherFinal(s->ctx, out + n, outlen - y); | |
459 | return 1; | |
460 | #endif /* HAVE_OPENSSL */ | |
461 | ||
462 | return 1; | |
463 | } | |
464 | #endif | |
465 | ||
466 | ||
467 | /* | |
468 | * Factory. The cipher and digestnames should be read from a localized | |
469 | * policy file. | |
470 | * | |
471 | * TODO: indicate error if unknown cipher or digest. | |
472 | */ | |
473 | Transformation | |
474 | *transformation_ssl_factory(int enc, int complvl, const char *ciphername, const char *digestname) | |
475 | { | |
476 | int keylen; | |
477 | Transformation *t; | |
478 | ||
479 | t = (Transformation *) malloc(sizeof (Transformation)); | |
480 | mlock(t, sizeof(Transformation)); | |
481 | ||
482 | OpenSSL_add_all_ciphers(); | |
483 | OpenSSL_add_all_digests(); | |
484 | ||
485 | t->enc = enc; | |
486 | t->state.ssl.complvl = complvl; | |
487 | t->state.ssl.cipher = EVP_get_cipherbyname(ciphername); | |
488 | t->state.ssl.digest = EVP_get_digestbyname(digestname); | |
489 | t->state.ssl.engine = NULL; | |
490 | ||
491 | t->name = "ssl"; | |
492 | t->mandatory = 1; | |
493 | t->initialize = &ssl_initialize; | |
494 | t->shutdown = &ssl_shutdown; | |
495 | t->startNewTape = &ssl_startNewTape; | |
496 | t->startDiskIOProcess = &ssl_startDiskIOProcess; | |
497 | t->endDiskIOProcess = &ssl_endDiskIOProcess; | |
498 | t->compress = &ssl_compress; | |
499 | t->decompress = &ssl_decompress; | |
500 | ||
501 | // we could use this to generate a key from a passphrase. | |
502 | // using this as the actual encryption key has the problems | |
503 | // discussed elsewhere. | |
504 | //EVP_BytesToKey(cipher, EVP_md5(), NULL, buf, strlen(buf), 1, key, iv); | |
505 | ||
506 | if (enc) { | |
507 | /* generate random session key */ | |
508 | //EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); | |
509 | //EVP_CIPHER_CTX_init(ctx); | |
510 | //EVP_CIPHER_CTX_rand_key(ctx, t->state.ssl.key); | |
511 | //EVP_CIPHER_CTX_cleanup(ctx); | |
512 | //EVP_CIPHER_CTX_free(ctx); | |
513 | RAND_bytes(t->state.ssl.key, t->state.ssl.cipher->key_len); | |
514 | } else { | |
515 | // how do we get keys? | |
516 | } | |
517 | ||
518 | return t; | |
519 | } |