std::string format;
bool pretty_format = false;
- std::optional<librbd::encryption_format_t> encryption_format;
- std::optional<std::string> encryption_passphrase_file;
+ std::vector<librbd::encryption_format_t> encryption_formats;
+ std::vector<std::string> encryption_passphrase_files;
Command command = None;
int pid = 0;
<< " [options] list-mapped List mapped nbd devices\n"
<< "Map and attach options:\n"
<< " --device <device path> Specify nbd device path (/dev/nbd{num})\n"
- << " --encryption-format Image encryption format\n"
- << " (possible values: luks1, luks2)\n"
+ << " --encryption-format luks|luks1|luks2\n"
+ << " Image encryption format (default: luks)\n"
<< " --encryption-passphrase-file Path of file containing passphrase for unlocking image encryption\n"
<< " --exclusive Forbid writes by other clients\n"
<< " --notrim Turn off trim/discard\n"
}
};
+struct EncryptionOptions {
+ std::vector<librbd::encryption_spec_t> specs;
+
+ ~EncryptionOptions() {
+ for (auto& spec : specs) {
+ switch (spec.format) {
+ case RBD_ENCRYPTION_FORMAT_LUKS: {
+ auto opts =
+ static_cast<librbd::encryption_luks_format_options_t*>(spec.opts);
+ ceph_memzero_s(opts->passphrase.data(), opts->passphrase.size(),
+ opts->passphrase.size());
+ delete opts;
+ break;
+ }
+ case RBD_ENCRYPTION_FORMAT_LUKS1: {
+ auto opts =
+ static_cast<librbd::encryption_luks1_format_options_t*>(spec.opts);
+ ceph_memzero_s(opts->passphrase.data(), opts->passphrase.size(),
+ opts->passphrase.size());
+ delete opts;
+ break;
+ }
+ case RBD_ENCRYPTION_FORMAT_LUKS2: {
+ auto opts =
+ static_cast<librbd::encryption_luks2_format_options_t*>(spec.opts);
+ ceph_memzero_s(opts->passphrase.data(), opts->passphrase.size(),
+ opts->passphrase.size());
+ delete opts;
+ break;
+ }
+ default:
+ ceph_abort();
+ }
+ }
+ }
+};
+
static std::string get_cookie(const std::string &devpath)
{
std::string cookie;
}
}
- if (cfg->encryption_format.has_value()) {
- if (!cfg->encryption_passphrase_file.has_value()) {
- r = -EINVAL;
- cerr << "rbd-nbd: missing encryption-passphrase-file" << std::endl;
- goto close_fd;
- }
- std::ifstream file(cfg->encryption_passphrase_file.value().c_str());
- if (file.fail()) {
- r = -errno;
- std::cerr << "rbd-nbd: unable to open passphrase file:"
- << cpp_strerror(errno) << std::endl;
- goto close_fd;
- }
- std::string passphrase((std::istreambuf_iterator<char>(file)),
- (std::istreambuf_iterator<char>()));
- auto sg = make_scope_guard([&] {
- ceph_memzero_s(&passphrase[0], passphrase.size(), passphrase.size()); });
- file.close();
- if (!passphrase.empty() && passphrase[passphrase.length() - 1] == '\n') {
- passphrase.erase(passphrase.length() - 1);
- }
+ if (!cfg->encryption_formats.empty()) {
+ EncryptionOptions encryption_options;
+ encryption_options.specs.reserve(cfg->encryption_formats.size());
- switch (cfg->encryption_format.value()) {
+ for (size_t i = 0; i < cfg->encryption_formats.size(); ++i) {
+ std::ifstream file(cfg->encryption_passphrase_files[i],
+ std::ios::in | std::ios::binary);
+ if (file.fail()) {
+ r = -errno;
+ std::cerr << "rbd-nbd: unable to open passphrase file '"
+ << cfg->encryption_passphrase_files[i] << "': "
+ << cpp_strerror(r) << std::endl;
+ goto close_fd;
+ }
+ std::string passphrase((std::istreambuf_iterator<char>(file)),
+ std::istreambuf_iterator<char>());
+ file.close();
+
+ switch (cfg->encryption_formats[i]) {
+ case RBD_ENCRYPTION_FORMAT_LUKS: {
+ auto opts = new librbd::encryption_luks_format_options_t{
+ std::move(passphrase)};
+ encryption_options.specs.push_back(
+ {RBD_ENCRYPTION_FORMAT_LUKS, opts, sizeof(*opts)});
+ break;
+ }
case RBD_ENCRYPTION_FORMAT_LUKS1: {
- librbd::encryption_luks1_format_options_t opts = {};
- opts.passphrase = passphrase;
- r = image.encryption_load(
- RBD_ENCRYPTION_FORMAT_LUKS1, &opts, sizeof(opts));
+ auto opts = new librbd::encryption_luks1_format_options_t{
+ .passphrase = std::move(passphrase)};
+ encryption_options.specs.push_back(
+ {RBD_ENCRYPTION_FORMAT_LUKS1, opts, sizeof(*opts)});
break;
}
case RBD_ENCRYPTION_FORMAT_LUKS2: {
- librbd::encryption_luks2_format_options_t opts = {};
- opts.passphrase = passphrase;
- r = image.encryption_load(
- RBD_ENCRYPTION_FORMAT_LUKS2, &opts, sizeof(opts));
- blksize = 4096;
+ auto opts = new librbd::encryption_luks2_format_options_t{
+ .passphrase = std::move(passphrase)};
+ encryption_options.specs.push_back(
+ {RBD_ENCRYPTION_FORMAT_LUKS2, opts, sizeof(*opts)});
break;
}
default:
- r = -ENOTSUP;
- cerr << "rbd-nbd: unsupported encryption format" << std::endl;
- goto close_fd;
+ ceph_abort();
+ }
}
+ r = image.encryption_load2(encryption_options.specs.data(),
+ encryption_options.specs.size());
if (r != 0) {
cerr << "rbd-nbd: failed to load encryption: " << cpp_strerror(r)
<< std::endl;
goto close_fd;
}
+
+ // luks2 block size can vary upto 4096, while luks1 always uses 512
+ // currently we don't have an rbd API for querying the loaded encryption
+ blksize = 4096;
}
r = image.stat(info, sizeof(info));
} else if (ceph_argparse_witharg(args, i, &arg_value,
"--encryption-format", (char *)NULL)) {
if (arg_value == "luks1") {
- cfg->encryption_format =
- std::make_optional(RBD_ENCRYPTION_FORMAT_LUKS1);
+ cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS1);
} else if (arg_value == "luks2") {
- cfg->encryption_format =
- std::make_optional(RBD_ENCRYPTION_FORMAT_LUKS2);
+ cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS2);
+ } else if (arg_value == "luks") {
+ cfg->encryption_formats.push_back(RBD_ENCRYPTION_FORMAT_LUKS);
} else {
*err_msg << "rbd-nbd: Invalid encryption format";
return -EINVAL;
} else if (ceph_argparse_witharg(args, i, &arg_value,
"--encryption-passphrase-file",
(char *)NULL)) {
- cfg->encryption_passphrase_file = std::make_optional(arg_value);
+ cfg->encryption_passphrase_files.push_back(arg_value);
} else {
++i;
}
}
+ if (cfg->encryption_formats.empty() &&
+ !cfg->encryption_passphrase_files.empty()) {
+ cfg->encryption_formats.resize(cfg->encryption_passphrase_files.size(),
+ RBD_ENCRYPTION_FORMAT_LUKS);
+ }
+
+ if (cfg->encryption_formats.size() != cfg->encryption_passphrase_files.size()) {
+ *err_msg << "rbd-nbd: Encryption formats count does not match "
+ << "passphrase files count";
+ return -EINVAL;
+ }
+
Command cmd = None;
if (args.begin() != args.end()) {
if (strcmp(*args.begin(), "map") == 0) {