Skip to content
API Documentation
BastionGuard™
EncryptionSupport Class Reference

#include <encryption_support.hpp>

Static Public Member Functions

static std::vector< ScanResult > detect_encrypted_volumes (DiskReader &reader, const std::vector< ScanResult > &seed_results, std::vector< std::string > &logs)
static bool export_encrypted_metadata (DiskReader &reader, const ScanResult &result, const std::string &output_dir, std::vector< std::string > &logs, std::string &error)
static bool try_unlock_volume (const std::string &source_path, const ScanResult &result, UnlockSession &session, std::vector< std::string > &logs, std::string &error)

Detailed Description

Definition at line 23 of file encryption_support.hpp.

Member Function Documentation

◆ detect_encrypted_volumes()

std::vector< ScanResult > EncryptionSupport::detect_encrypted_volumes ( DiskReader & reader,
const std::vector< ScanResult > & seed_results,
std::vector< std::string > & logs )
static

Definition at line 422 of file encryption_support.cpp.

424 {
425 std::vector<ScanResult> out;
426 std::set<uint64_t> seen;
427 for (uint64_t offset : candidate_offsets(seed_results)) {
428 if (!seen.insert(offset).second || offset >= reader.size()) continue;
429 if (auto luks = probe_luks(reader, offset); !luks.type.empty()) out.push_back(luks);
430 if (auto bitlocker = probe_bitlocker(reader, offset); !bitlocker.type.empty()) out.push_back(bitlocker);
431 }
432 if (!out.empty()) logs.push_back(trs("Encryption probes: detected") + std::string(" ") + std::to_string(out.size()) + " encrypted container(s).");
433 return out;
434}
uint64_t size() const
std::string trs(const char *msgid)
Definition i18n.cpp:22
ScanResult probe_luks(DiskReader &reader, uint64_t offset)
ScanResult probe_bitlocker(DiskReader &reader, uint64_t offset)
std::vector< uint64_t > candidate_offsets(const std::vector< ScanResult > &seed_results)
std::string type
Definition models.hpp:23

References DiskReader::size(), trs(), and ScanResult::type.

◆ export_encrypted_metadata()

bool EncryptionSupport::export_encrypted_metadata ( DiskReader & reader,
const ScanResult & result,
const std::string & output_dir,
std::vector< std::string > & logs,
std::string & error )
static

Definition at line 436 of file encryption_support.cpp.

440 {
441 const fs::path root = fs::path(output_dir) / "filesystem_recovered" / "encrypted" /
442 (sanitize_name(result.type) + "_" + std::to_string(result.offset_bytes));
443 try {
444 fs::create_directories(root);
445 } catch (const std::exception& ex) {
446 error = ex.what();
447 return false;
448 }
449
450 const uint64_t header_length = result.type.find("BitLocker") != std::string::npos ? 65536ull : 16ull * 1024 * 1024;
451 const uint64_t available = result.offset_bytes < reader.size() ? reader.size() - result.offset_bytes : 0;
452 const uint64_t to_copy = std::min<uint64_t>(header_length, available);
453 if (to_copy == 0) return true;
454
455 fs::path meta_path = root / "header_and_metadata.bin";
456 if (!ensure_parent_created(meta_path, error)) return false;
457 if (!write_bytes(reader, result.offset_bytes, to_copy, meta_path, error)) return false;
458
459 std::ofstream readme(root / "README.txt");
460 if (readme) {
461 readme << result.type << "\n";
462 readme << "Offset: " << result.offset_bytes << "\n";
463 readme << "Detail: " << result.detail << "\n\n";
464 readme << "Unlock environment variables supported by this build:\n";
465 readme << "- RECOVERY_LUKS_PASSPHRASE\n";
466 readme << "- RECOVERY_LUKS_KEYFILE\n";
467 readme << "- RECOVERY_BITLOCKER_PASSWORD\n";
468 readme << "- RECOVERY_BITLOCKER_RECOVERY_KEY\n";
469 readme << "- RECOVERY_BITLOCKER_BEK_FILE\n";
470 readme << "The engine will attempt external read-only unlock through cryptsetup/dislocker when available.\n";
471 }
472
473 logs.push_back(trs("Exported encrypted volume metadata:") + std::string(" ") + meta_path.string());
474 return true;
475}
bool ensure_parent_created(const fs::path &p, std::string &error)
bool write_bytes(DiskReader &reader, uint64_t offset, uint64_t length, const fs::path &out_path, std::string &error)
std::string sanitize_name(const std::string &in)
bool available()
Definition NFQueue.cpp:251
std::string detail
Definition models.hpp:25
uint64_t offset_bytes
Definition models.hpp:21

References ScanResult::detail, ScanResult::offset_bytes, DiskReader::size(), trs(), and ScanResult::type.

◆ try_unlock_volume()

bool EncryptionSupport::try_unlock_volume ( const std::string & source_path,
const ScanResult & result,
UnlockSession & session,
std::vector< std::string > & logs,
std::string & error )
static

Definition at line 477 of file encryption_support.cpp.

481 {
482 session = {};
483
484 if (result.type.find("LUKS") != std::string::npos) {
485 std::string err_keyfile;
486 if (const std::string keyfile = getenv_existing_file("RECOVERY_LUKS_KEYFILE");
487 !keyfile.empty() && cryptsetup_open_with_keyfile(source_path, result.offset_bytes, keyfile, session, logs, err_keyfile)) {
488 return true;
489 }
490 const std::string passphrase = getenv_str("RECOVERY_LUKS_PASSPHRASE");
491 if (cryptsetup_open(source_path, result.offset_bytes, passphrase, session, logs, error)) return true;
492 if (!err_keyfile.empty()) error = err_keyfile + "; " + error;
493 return false;
494 }
495
496 if (result.type.find("BitLocker") != std::string::npos) {
497 std::string err_password;
498 if (const std::string password = getenv_str("RECOVERY_BITLOCKER_PASSWORD");
499 !password.empty() && dislocker_open(source_path, result.offset_bytes, password, false, session, logs, err_password)) {
500 return true;
501 }
502 std::string err_recovery;
503 if (const std::string recovery_key = getenv_str("RECOVERY_BITLOCKER_RECOVERY_KEY");
504 !recovery_key.empty() && dislocker_open(source_path, result.offset_bytes, recovery_key, true, session, logs, err_recovery)) {
505 return true;
506 }
507 std::string err_bek;
508 if (const std::string bek_file = getenv_existing_file("RECOVERY_BITLOCKER_BEK_FILE"); !bek_file.empty()) {
509 // dislocker accepts -f with a BEK file path.
510 std::string open_target = source_path;
511 if (result.offset_bytes != 0) {
512 if (!create_loop_for_offset(source_path, result.offset_bytes, session.loop_path, logs, err_bek)) {
513 error = err_bek;
514 return false;
515 }
516 open_target = session.loop_path;
517 }
518 if (!command_exists("dislocker") || !command_exists("losetup")) {
519 error = "dislocker or losetup not available";
520 return false;
521 }
522 const std::string mapper = "recovery_bitlocker_" + sanitize_name(std::to_string(::getpid()) + "_" + std::to_string(result.offset_bytes));
523 fs::path mount_dir = fs::temp_directory_path() / (mapper + "_dislocker");
524 fs::create_directories(mount_dir);
525 std::ostringstream cmd;
526 cmd << "dislocker -r -V " << shell_quote(open_target) << ' '
527 << "-f " << shell_quote(bek_file) << ' '
528 << "-- " << shell_quote(mount_dir.string());
529 std::string out;
530 int rc = 0;
531 if (run_command_capture(cmd.str(), out, rc) && rc == 0) {
532 const fs::path dislocker_file = mount_dir / "dislocker-file";
533 std::string loop;
534 if (fs::exists(dislocker_file) && create_loop_for_offset(dislocker_file.string(), 0, loop, logs, err_bek)) {
535 session.container_type = "BitLocker";
536 session.source_path = source_path;
537 session.source_offset = result.offset_bytes;
538 session.mapper_name = mapper;
539 session.helper_mount_dir = mount_dir.string();
540 session.helper_loop_path = loop;
541 session.uses_dislocker = true;
542 session.mapped_path = loop;
543 logs.push_back(trs("Unlocked BitLocker container through BEK file:") + std::string(" ") + session.mapped_path);
544 return true;
545 }
546 } else {
547 err_bek = trim_copy(out.empty() ? "dislocker failed" : out);
548 }
549 }
550 error = !err_password.empty() ? err_password : (!err_recovery.empty() ? err_recovery : err_bek);
551 if (error.empty()) error = "no BitLocker credential environment variable provided";
552 return false;
553 }
554
555 error = "unsupported encrypted container type";
556 return false;
557}
std::string shell_quote(const std::string &argument)
std::string trim_copy(std::string value)
bool dislocker_open(const std::string &source_path, uint64_t offset, const std::string &credential, bool use_recovery_key, UnlockSession &session, std::vector< std::string > &logs, std::string &error)
bool cryptsetup_open(const std::string &source_path, uint64_t offset, const std::string &passphrase, UnlockSession &session, std::vector< std::string > &logs, std::string &error)
bool cryptsetup_open_with_keyfile(const std::string &source_path, uint64_t offset, const std::string &keyfile, UnlockSession &session, std::vector< std::string > &logs, std::string &error)
bool create_loop_for_offset(const std::string &source_path, uint64_t offset, std::string &loop_path, std::vector< std::string > &logs, std::string &error)
bool run_command_capture(const std::string &cmd, std::string &output, int &rc)
std::string getenv_existing_file(const char *name)
std::string source_path
std::string mapped_path
std::string helper_loop_path
std::string container_type
std::string helper_mount_dir
std::string mapper_name

References UnlockSession::container_type, UnlockSession::helper_loop_path, UnlockSession::helper_mount_dir, UnlockSession::loop_path, UnlockSession::mapped_path, UnlockSession::mapper_name, ScanResult::offset_bytes, UnlockSession::source_offset, UnlockSession::source_path, trs(), ScanResult::type, and UnlockSession::uses_dislocker.


The documentation for this class was generated from the following files: