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