1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2000-2011 Free Software Foundation Europe e.V.
5    Copyright (C) 2011-2012 Planets Communications B.V.
6    Copyright (C) 2013-2016 Bareos GmbH & Co. KG
7 
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    Affero General Public License for more details.
17 
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22 */
23 /*
24  * Kern Sibbald, March MM
25  * Extracted from other source files by Marco van Wieringen, June 2011
26  */
27 /**
28  * @file
29  * Functions to handle cryptology
30  */
31 
32 #include "include/bareos.h"
33 #include "filed/filed.h"
34 #include "filed/restore.h"
35 #include "findlib/find_one.h"
36 #include "lib/edit.h"
37 
38 namespace filedaemon {
39 
40 #ifdef HAVE_SHA2
41 const bool have_sha2 = true;
42 #else
43 const bool have_sha2 = false;
44 #endif
45 
UnserCryptoPacketLen(RestoreCipherContext * ctx)46 static void UnserCryptoPacketLen(RestoreCipherContext *ctx)
47 {
48    unser_declare;
49    if (ctx->packet_len == 0 && ctx->buf_len >= CRYPTO_LEN_SIZE) {
50       UnserBegin(&ctx->buf[0], CRYPTO_LEN_SIZE);
51       unser_uint32(ctx->packet_len);
52       ctx->packet_len += CRYPTO_LEN_SIZE;
53    }
54 }
55 
CryptoSessionStart(JobControlRecord * jcr,crypto_cipher_t cipher)56 bool CryptoSessionStart(JobControlRecord *jcr, crypto_cipher_t cipher)
57 {
58    /**
59     * Create encryption session data and a cached, DER-encoded session data
60     * structure. We use a single session key for each backup, so we'll encode
61     * the session data only once.
62     */
63    if (jcr->crypto.pki_encrypt) {
64       uint32_t size = 0;
65 
66       /**
67        * Create per-job session encryption context
68        */
69       jcr->crypto.pki_session = crypto_session_new(cipher, jcr->crypto.pki_recipients);
70       if (!jcr->crypto.pki_session) {
71          Jmsg(jcr, M_FATAL, 0, _("Cannot create a new crypto session probably unsupported cipher configured.\n"));
72          return false;
73       }
74 
75       /**
76        * Get the session data size
77        */
78       if (!CryptoSessionEncode(jcr->crypto.pki_session, (uint8_t *)0, &size)) {
79          Jmsg(jcr, M_FATAL, 0, _("An error occurred while encrypting the stream.\n"));
80          return false;
81       }
82 
83       /**
84        * Allocate buffer
85        */
86       jcr->crypto.pki_session_encoded = GetMemory(size);
87 
88       /**
89        * Encode session data
90        */
91       if (!CryptoSessionEncode(jcr->crypto.pki_session, (uint8_t *)jcr->crypto.pki_session_encoded, &size)) {
92          Jmsg(jcr, M_FATAL, 0, _("An error occurred while encrypting the stream.\n"));
93          return false;
94       }
95 
96       /**
97        * ... and store the encoded size
98        */
99       jcr->crypto.pki_session_encoded_size = size;
100 
101       /**
102        * Allocate the encryption/decryption buffer
103        */
104       jcr->crypto.crypto_buf = GetMemory(CRYPTO_CIPHER_MAX_BLOCK_SIZE);
105    }
106 
107    return true;
108 }
109 
CryptoSessionEnd(JobControlRecord * jcr)110 void CryptoSessionEnd(JobControlRecord *jcr)
111 {
112    if (jcr->crypto.crypto_buf) {
113       FreePoolMemory(jcr->crypto.crypto_buf);
114       jcr->crypto.crypto_buf = NULL;
115    }
116    if (jcr->crypto.pki_session) {
117       CryptoSessionFree(jcr->crypto.pki_session);
118    }
119    if (jcr->crypto.pki_session_encoded) {
120       FreePoolMemory(jcr->crypto.pki_session_encoded);
121       jcr->crypto.pki_session_encoded = NULL;
122    }
123 }
124 
CryptoSessionSend(JobControlRecord * jcr,BareosSocket * sd)125 bool CryptoSessionSend(JobControlRecord *jcr, BareosSocket *sd)
126 {
127    POOLMEM *msgsave;
128 
129    /** Send our header */
130    Dmsg2(100, "Send hdr fi=%ld stream=%d\n", jcr->JobFiles, STREAM_ENCRYPTED_SESSION_DATA);
131    sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_ENCRYPTED_SESSION_DATA);
132 
133    msgsave = sd->msg;
134    sd->msg = jcr->crypto.pki_session_encoded;
135    sd->message_length = jcr->crypto.pki_session_encoded_size;
136    jcr->JobBytes += sd->message_length;
137 
138    Dmsg1(100, "Send data len=%d\n", sd->message_length);
139    sd->send();
140    sd->msg = msgsave;
141    sd->signal(BNET_EOD);
142    return true;
143 }
144 
145 /**
146  * Verify the signature for the last restored file
147  * Return value is either true (signature correct)
148  * or false (signature could not be verified).
149  * TODO landonf: Implement without using FindOneFile and
150  * without re-reading the file.
151  */
VerifySignature(JobControlRecord * jcr,r_ctx & rctx)152 bool VerifySignature(JobControlRecord *jcr, r_ctx &rctx)
153 {
154    X509_KEYPAIR *keypair = nullptr;
155    DIGEST *digest = NULL;
156    crypto_error_t err;
157    uint64_t saved_bytes;
158    crypto_digest_t signing_algorithm = have_sha2 ?
159                                        CRYPTO_DIGEST_SHA256 : CRYPTO_DIGEST_SHA1;
160    crypto_digest_t algorithm;
161    SIGNATURE *sig = rctx.sig;
162 
163    if (!jcr->crypto.pki_sign) {
164       /*
165        * no signature OK
166        */
167       return true;
168    }
169    if (!sig) {
170       if (rctx.type == FT_REGE || rctx.type == FT_REG || rctx.type == FT_RAW) {
171          Jmsg1(jcr, M_ERROR, 0, _("Missing cryptographic signature for %s\n"),
172                jcr->last_fname);
173          goto bail_out;
174       }
175       return true;
176    }
177 
178    /*
179     * Iterate through the trusted signers
180     */
181    foreach_alist(keypair, jcr->crypto.pki_signers) {
182       err = CryptoSignGetDigest(sig, jcr->crypto.pki_keypair, algorithm, &digest);
183       switch (err) {
184       case CRYPTO_ERROR_NONE:
185          Dmsg0(50, "== Got digest\n");
186          /*
187           * We computed jcr->crypto.digest using signing_algorithm while writing
188           * the file. If it is not the same as the algorithm used for
189           * this file, punt by releasing the computed algorithm and
190           * computing by re-reading the file.
191           */
192          if (algorithm != signing_algorithm) {
193             if (jcr->crypto.digest) {
194                CryptoDigestFree(jcr->crypto.digest);
195                jcr->crypto.digest = NULL;
196             }
197          }
198          if (jcr->crypto.digest) {
199              /*
200               * Use digest computed while writing the file to verify the signature
201               */
202             if ((err = CryptoSignVerify(sig, keypair, jcr->crypto.digest)) != CRYPTO_ERROR_NONE) {
203                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
204                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"),
205                      jcr->last_fname, crypto_strerror(err));
206                goto bail_out;
207             }
208          } else {
209             /*
210              * Signature found, digest allocated.  Old method,
211              * re-read the file and compute the digest
212              */
213             jcr->crypto.digest = digest;
214 
215             /*
216              * Checksum the entire file
217              * Make sure we don't modify JobBytes by saving and restoring it
218              */
219             saved_bytes = jcr->JobBytes;
220             if (FindOneFile(jcr, jcr->ff, DoFileDigest, jcr->last_fname, (dev_t)-1, 1) != 0) {
221                Jmsg(jcr, M_ERROR, 0, _("Digest one file failed for file: %s\n"),
222                     jcr->last_fname);
223                jcr->JobBytes = saved_bytes;
224                goto bail_out;
225             }
226             jcr->JobBytes = saved_bytes;
227 
228             /*
229              * Verify the signature
230              */
231             if ((err = CryptoSignVerify(sig, keypair, digest)) != CRYPTO_ERROR_NONE) {
232                Dmsg1(50, "Bad signature on %s\n", jcr->last_fname);
233                Jmsg2(jcr, M_ERROR, 0, _("Signature validation failed for file %s: ERR=%s\n"),
234                      jcr->last_fname, crypto_strerror(err));
235                goto bail_out;
236             }
237             jcr->crypto.digest = NULL;
238          }
239 
240          /*
241           * Valid signature
242           */
243          Dmsg1(50, "Signature good on %s\n", jcr->last_fname);
244          CryptoDigestFree(digest);
245          return true;
246 
247       case CRYPTO_ERROR_NOSIGNER:
248          /*
249           * Signature not found, try again
250           */
251          if (digest) {
252             CryptoDigestFree(digest);
253             digest = NULL;
254          }
255          continue;
256       default:
257          /*
258           * Something strange happened (that shouldn't happen!)...
259           */
260          Qmsg2(jcr, M_ERROR, 0, _("Signature validation failed for %s: %s\n"), jcr->last_fname, crypto_strerror(err));
261          goto bail_out;
262       }
263    }
264 
265    /*
266     * No signer
267     */
268    Dmsg1(50, "Could not find a valid public key for signature on %s\n", jcr->last_fname);
269 
270 bail_out:
271    if (digest) {
272       CryptoDigestFree(digest);
273    }
274    return false;
275 }
276 
277 /**
278  * In the context of jcr, flush any remaining data from the cipher context,
279  * writing it to bfd.
280  * Return value is true on success, false on failure.
281  */
FlushCipher(JobControlRecord * jcr,BareosWinFilePacket * bfd,uint64_t * addr,char * flags,int32_t stream,RestoreCipherContext * cipher_ctx)282 bool FlushCipher(JobControlRecord *jcr, BareosWinFilePacket *bfd, uint64_t *addr, char *flags, int32_t stream, RestoreCipherContext *cipher_ctx)
283 {
284    uint32_t decrypted_len = 0;
285    char *wbuf;                        /* write buffer */
286    uint32_t wsize;                    /* write size */
287    char ec1[50];                      /* Buffer printing huge values */
288    bool second_pass = false;
289 
290 again:
291    /*
292     * Write out the remaining block and free the cipher context
293     */
294    cipher_ctx->buf = CheckPoolMemorySize(cipher_ctx->buf, cipher_ctx->buf_len +
295                                             cipher_ctx->block_size);
296 
297    if (!CryptoCipherFinalize(cipher_ctx->cipher, (uint8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
298         &decrypted_len)) {
299       /*
300        * Writing out the final, buffered block failed. Shouldn't happen.
301        */
302       Jmsg3(jcr, M_ERROR, 0, _("Decryption error. buf_len=%d decrypt_len=%d on file %s\n"),
303             cipher_ctx->buf_len, decrypted_len, jcr->last_fname);
304    }
305 
306    Dmsg2(130, "Flush decrypt len=%d buf_len=%d\n", decrypted_len, cipher_ctx->buf_len);
307    /*
308     * If nothing new was decrypted, and our output buffer is empty, return
309     */
310    if (decrypted_len == 0 && cipher_ctx->buf_len == 0) {
311       return true;
312    }
313 
314    cipher_ctx->buf_len += decrypted_len;
315 
316    UnserCryptoPacketLen(cipher_ctx);
317    Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
318    wsize = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
319    /*
320     * Decrypted, possibly decompressed output here.
321     */
322    wbuf = &cipher_ctx->buf[CRYPTO_LEN_SIZE];
323    cipher_ctx->buf_len -= cipher_ctx->packet_len;
324    Dmsg2(130, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", wsize, cipher_ctx->buf_len);
325 
326    if (BitIsSet(FO_SPARSE, flags) || BitIsSet(FO_OFFSETS, flags)) {
327       if (!SparseData(jcr, bfd, addr, &wbuf, &wsize)) {
328          return false;
329       }
330    }
331 
332    if (BitIsSet(FO_COMPRESS, flags)) {
333       if (!DecompressData(jcr, jcr->last_fname, stream, &wbuf, &wsize, false)) {
334          return false;
335       }
336    }
337 
338    Dmsg0(130, "Call StoreData\n");
339    if (!StoreData(jcr, bfd, wbuf, wsize, BitIsSet(FO_WIN32DECOMP, flags))) {
340       return false;
341    }
342    jcr->JobBytes += wsize;
343    Dmsg2(130, "Flush write %u bytes, JobBytes=%s\n", wsize, edit_uint64(jcr->JobBytes, ec1));
344 
345    /*
346     * Move any remaining data to start of buffer
347     */
348    if (cipher_ctx->buf_len > 0) {
349       Dmsg1(130, "Moving %u buffered bytes to start of buffer\n", cipher_ctx->buf_len);
350       memmove(cipher_ctx->buf, &cipher_ctx->buf[cipher_ctx->packet_len],
351          cipher_ctx->buf_len);
352    }
353    /*
354     * The packet was successfully written, reset the length so that the next
355     * packet length may be re-read by UnserCryptoPacketLen()
356     */
357    cipher_ctx->packet_len = 0;
358 
359    if (cipher_ctx->buf_len >0 && !second_pass) {
360       second_pass = true;
361       goto again;
362    }
363 
364    /*
365     * Stop decryption
366     */
367    cipher_ctx->buf_len = 0;
368    cipher_ctx->packet_len = 0;
369 
370    return true;
371 }
372 
DeallocateCipher(r_ctx & rctx)373 void DeallocateCipher(r_ctx &rctx)
374 {
375    /*
376     * Flush and deallocate previous stream's cipher context
377     */
378    if (rctx.cipher_ctx.cipher) {
379       FlushCipher(rctx.jcr, &rctx.bfd, &rctx.fileAddr, rctx.flags, rctx.comp_stream, &rctx.cipher_ctx);
380       CryptoCipherFree(rctx.cipher_ctx.cipher);
381       rctx.cipher_ctx.cipher = NULL;
382    }
383 }
384 
DeallocateForkCipher(r_ctx & rctx)385 void DeallocateForkCipher(r_ctx &rctx)
386 {
387    /*
388     * Flush and deallocate previous stream's fork cipher context
389     */
390    if (rctx.fork_cipher_ctx.cipher) {
391       FlushCipher(rctx.jcr, &rctx.forkbfd, &rctx.fork_addr, rctx.fork_flags, rctx.comp_stream, &rctx.fork_cipher_ctx);
392       CryptoCipherFree(rctx.fork_cipher_ctx.cipher);
393       rctx.fork_cipher_ctx.cipher = NULL;
394    }
395 }
396 
397 /**
398  * Setup a encryption context
399  */
SetupEncryptionContext(b_ctx & bctx)400 bool SetupEncryptionContext(b_ctx &bctx)
401 {
402    uint32_t cipher_block_size;
403    bool retval = false;
404 
405    if (BitIsSet(FO_ENCRYPT, bctx.ff_pkt->flags)) {
406       if (BitIsSet(FO_SPARSE, bctx.ff_pkt->flags) ||
407           BitIsSet(FO_OFFSETS, bctx.ff_pkt->flags)) {
408          Jmsg0(bctx.jcr, M_FATAL, 0, _("Encrypting sparse or offset data not supported.\n"));
409          goto bail_out;
410       }
411       /*
412        * Allocate the cipher context
413        */
414       if ((bctx.cipher_ctx = crypto_cipher_new(bctx.jcr->crypto.pki_session, true,
415                                                &cipher_block_size)) == NULL) {
416          /*
417           * Shouldn't happen!
418           */
419          Jmsg0(bctx.jcr, M_FATAL, 0, _("Failed to initialize encryption context.\n"));
420          goto bail_out;
421       }
422 
423       /*
424        * Grow the crypto buffer, if necessary.
425        * CryptoCipherUpdate() will buffer up to (cipher_block_size - 1).
426        * We grow crypto_buf to the maximum number of blocks that
427        * could be returned for the given read buffer size.
428        * (Using the larger of either rsize or max_compress_len)
429        */
430       bctx.jcr->crypto.crypto_buf = CheckPoolMemorySize(bctx.jcr->crypto.crypto_buf,
431            (MAX(bctx.jcr->buf_size + (int)sizeof(uint32_t), (int32_t)bctx.max_compress_len) +
432             cipher_block_size - 1) / cipher_block_size * cipher_block_size);
433 
434       bctx.wbuf = bctx.jcr->crypto.crypto_buf; /* Encrypted, possibly compressed output here. */
435    }
436 
437    retval = true;
438 
439 bail_out:
440    return retval;
441 }
442 
443 /**
444  * Setup a decryption context
445  */
SetupDecryptionContext(r_ctx & rctx,RestoreCipherContext & rcctx)446 bool SetupDecryptionContext(r_ctx &rctx, RestoreCipherContext &rcctx)
447 {
448    if (!rctx.cs) {
449       Jmsg1(rctx.jcr, M_ERROR, 0, _("Missing encryption session data stream for %s\n"), rctx.jcr->last_fname);
450       return false;
451    }
452 
453    if ((rcctx.cipher = crypto_cipher_new(rctx.cs, false, &rcctx.block_size)) == NULL) {
454       Jmsg1(rctx.jcr, M_ERROR, 0, _("Failed to initialize decryption context for %s\n"), rctx.jcr->last_fname);
455       FreeSession(rctx);
456       return false;
457    }
458 
459    return true;
460 }
461 
EncryptData(b_ctx * bctx,bool * need_more_data)462 bool EncryptData(b_ctx *bctx, bool *need_more_data)
463 {
464    bool retval = false;
465    uint32_t initial_len = 0;
466 
467    /*
468     * Note, here we prepend the current record length to the beginning
469     *  of the encrypted data. This is because both sparse and compression
470     *  restore handling want records returned to them with exactly the
471     *  same number of bytes that were processed in the backup handling.
472     *  That is, both are block filters rather than a stream.  When doing
473     *  compression, the compression routines may buffer data, so that for
474     *  any one record compressed, when it is decompressed the same size
475     *  will not be obtained. Of course, the buffered data eventually comes
476     *  out in subsequent CryptoCipherUpdate() calls or at least
477     *  when CryptoCipherFinalize() is called.  Unfortunately, this
478     *  "feature" of encryption enormously complicates the restore code.
479     */
480    ser_declare;
481 
482    if (BitIsSet(FO_SPARSE, bctx->ff_pkt->flags) ||
483        BitIsSet(FO_OFFSETS, bctx->ff_pkt->flags)) {
484          bctx->cipher_input_len += OFFSET_FADDR_SIZE;
485    }
486 
487    /*
488     * Encrypt the length of the input block
489     */
490    uint8_t packet_len[sizeof(uint32_t)];
491 
492    SerBegin(packet_len, sizeof(uint32_t));
493    ser_uint32(bctx->cipher_input_len); /* store data len in begin of buffer */
494    Dmsg1(20, "Encrypt len=%d\n", bctx->cipher_input_len);
495 
496    if (!CryptoCipherUpdate(bctx->cipher_ctx, packet_len, sizeof(packet_len),
497                              (uint8_t *)bctx->jcr->crypto.crypto_buf, &initial_len)) {
498       /*
499        * Encryption failed. Shouldn't happen.
500        */
501       Jmsg(bctx->jcr, M_FATAL, 0, _("Encryption error\n"));
502       goto bail_out;
503    }
504 
505    /*
506     * Encrypt the input block
507     */
508    if (CryptoCipherUpdate(bctx->cipher_ctx, bctx->cipher_input, bctx->cipher_input_len,
509                             (uint8_t *)&bctx->jcr->crypto.crypto_buf[initial_len],
510                             &bctx->encrypted_len)) {
511       if ((initial_len + bctx->encrypted_len) == 0) {
512          /*
513           * No full block of data available, read more data
514           */
515          *need_more_data = true;
516          goto bail_out;
517       }
518 
519       Dmsg2(400, "encrypted len=%d unencrypted len=%d\n",
520             bctx->encrypted_len, bctx->jcr->store_bsock->message_length);
521 
522       bctx->jcr->store_bsock->message_length = initial_len + bctx->encrypted_len; /* set encrypted length */
523    } else {
524       /*
525        * Encryption failed. Shouldn't happen.
526        */
527       Jmsg(bctx->jcr, M_FATAL, 0, _("Encryption error\n"));
528       goto bail_out;
529    }
530 
531    retval = true;
532 
533 bail_out:
534    return retval;
535 }
536 
DecryptData(JobControlRecord * jcr,char ** data,uint32_t * length,RestoreCipherContext * cipher_ctx)537 bool DecryptData(JobControlRecord *jcr, char **data, uint32_t *length, RestoreCipherContext *cipher_ctx)
538 {
539    uint32_t decrypted_len = 0; /* Decryption output length */
540 
541    ASSERT(cipher_ctx->cipher);
542 
543    /*
544     * NOTE: We must implement block preserving semantics for the
545     * non-streaming compression and sparse code.
546     *
547     * Grow the crypto buffer, if necessary.
548     * CryptoCipherUpdate() will process only whole blocks,
549     * buffering the remaining input.
550     */
551    cipher_ctx->buf = CheckPoolMemorySize(cipher_ctx->buf,
552                      cipher_ctx->buf_len + *length + cipher_ctx->block_size);
553 
554    /*
555     * Decrypt the input block
556     */
557    if (!CryptoCipherUpdate(cipher_ctx->cipher,
558                              (const u_int8_t *)*data,
559                              *length,
560                              (u_int8_t *)&cipher_ctx->buf[cipher_ctx->buf_len],
561                              &decrypted_len)) {
562       /*
563        * Decryption failed. Shouldn't happen.
564        */
565       Jmsg(jcr, M_FATAL, 0, _("Decryption error\n"));
566       goto bail_out;
567    }
568 
569    if (decrypted_len == 0) {
570       /*
571        * No full block of encrypted data available, write more data
572        */
573       *length = 0;
574       return true;
575    }
576 
577    Dmsg2(200, "decrypted len=%d encrypted len=%d\n", decrypted_len, *length);
578 
579    cipher_ctx->buf_len += decrypted_len;
580    *data = cipher_ctx->buf;
581 
582    /*
583     * If one full preserved block is available, write it to disk,
584     * and then buffer any remaining data. This should be effecient
585     * as long as Bareos's block size is not significantly smaller than the
586     * encryption block size (extremely unlikely!)
587     */
588    UnserCryptoPacketLen(cipher_ctx);
589    Dmsg1(500, "Crypto unser block size=%d\n", cipher_ctx->packet_len - CRYPTO_LEN_SIZE);
590 
591    if (cipher_ctx->packet_len == 0 || cipher_ctx->buf_len < cipher_ctx->packet_len) {
592       /*
593        * No full preserved block is available.
594        */
595       *length = 0;
596       return true;
597    }
598 
599    /*
600     * We have one full block, set up the filter input buffers
601     */
602    *length = cipher_ctx->packet_len - CRYPTO_LEN_SIZE;
603    *data = &((*data)[CRYPTO_LEN_SIZE]); /* Skip the block length header */
604    cipher_ctx->buf_len -= cipher_ctx->packet_len;
605    Dmsg2(130, "Encryption writing full block, %u bytes, remaining %u bytes in buffer\n", *length, cipher_ctx->buf_len);
606 
607    return true;
608 
609 bail_out:
610    return false;
611 }
612 } /* namespace filedaemon */
613