Skip to content

Commit

Permalink
librbd: add encryption api
Browse files Browse the repository at this point in the history
This commit exposes librbd encryption api

Signed-off-by: Or Ozeri <[email protected]>
  • Loading branch information
orozery committed Jan 11, 2021
1 parent 237eaac commit 99d8cf9
Show file tree
Hide file tree
Showing 38 changed files with 1,927 additions and 884 deletions.
3 changes: 3 additions & 0 deletions src/include/config-h.in.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,9 @@
/* Define if libcryptsetup version < 2.0.5 */
#cmakedefine LIBCRYPTSETUP_LEGACY_DATA_ALIGNMENT

/* Define if libcryptsetup can be used (linux only) */
#cmakedefine HAVE_LIBCRYPTSETUP

/* Shared library extension, such as .so, .dll or .dylib */
#cmakedefine CMAKE_SHARED_LIBRARY_SUFFIX "@CMAKE_SHARED_LIBRARY_SUFFIX@"

Expand Down
34 changes: 34 additions & 0 deletions src/include/rbd/librbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,30 @@ enum {
RBD_WRITE_ZEROES_FLAG_THICK_PROVISION = (1U<<0), /* fully allocated zeroed extent */
};

typedef enum {
RBD_ENCRYPTION_FORMAT_LUKS1 = 0,
RBD_ENCRYPTION_FORMAT_LUKS2 = 1
} rbd_encryption_format_t;

typedef enum {
RBD_ENCRYPTION_ALGORITHM_AES128 = 0,
RBD_ENCRYPTION_ALGORITHM_AES256 = 1
} rbd_encryption_algorithm_t;

typedef void *rbd_encryption_options_t;

typedef struct {
rbd_encryption_algorithm_t alg;
const char* passphrase;
size_t passphrase_size;
} rbd_encryption_luks1_format_options_t;

typedef struct {
rbd_encryption_algorithm_t alg;
const char* passphrase;
size_t passphrase_size;
} rbd_encryption_luks2_format_options_t;

CEPH_RBD_API void rbd_image_options_create(rbd_image_options_t* opts);
CEPH_RBD_API void rbd_image_options_destroy(rbd_image_options_t opts);
CEPH_RBD_API int rbd_image_options_set_string(rbd_image_options_t opts,
Expand Down Expand Up @@ -791,6 +815,16 @@ CEPH_RBD_API int rbd_deep_copy_with_progress(rbd_image_t image,
librbd_progress_fn_t cb,
void *cbdata);

/* encryption */
CEPH_RBD_API int rbd_encryption_format(rbd_image_t image,
rbd_encryption_format_t format,
rbd_encryption_options_t opts,
size_t opts_size);
CEPH_RBD_API int rbd_encryption_load(rbd_image_t image,
rbd_encryption_format_t format,
rbd_encryption_options_t opts,
size_t opts_size);

/* snapshots */
CEPH_RBD_API int rbd_snap_list(rbd_image_t image, rbd_snap_info_t *snaps,
int *max_snaps);
Expand Down
20 changes: 20 additions & 0 deletions src/include/rbd/librbd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,20 @@ namespace librbd {
config_source_t source;
} config_option_t;

typedef rbd_encryption_format_t encryption_format_t;
typedef rbd_encryption_algorithm_t encryption_algorithm_t;
typedef rbd_encryption_options_t encryption_options_t;

typedef struct {
encryption_algorithm_t alg;
std::string passphrase;
} encryption_luks1_format_options_t;

typedef struct {
encryption_algorithm_t alg;
std::string passphrase;
} encryption_luks2_format_options_t;

class CEPH_RBD_API RBD
{
public:
Expand Down Expand Up @@ -576,6 +590,12 @@ class CEPH_RBD_API Image
int deep_copy_with_progress(IoCtx& dest_io_ctx, const char *destname,
ImageOptions& opts, ProgressContext &prog_ctx);

/* encryption */
int encryption_format(encryption_format_t format, encryption_options_t opts,
size_t opts_size);
int encryption_load(encryption_format_t format, encryption_options_t opts,
size_t opts_size);

/* striping */
uint64_t get_stripe_unit() const;
uint64_t get_stripe_count() const;
Expand Down
4 changes: 4 additions & 0 deletions src/librbd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ set(librbd_internal_srcs
api/PoolMetadata.cc
api/Snapshot.cc
api/Trash.cc
api/Utils.cc
asio/ContextWQ.cc
cache/ImageWriteback.cc
cache/ObjectCacherObjectDispatch.cc
Expand All @@ -63,6 +64,8 @@ set(librbd_internal_srcs
crypto/CryptoContextPool.cc
crypto/CryptoImageDispatch.cc
crypto/CryptoObjectDispatch.cc
crypto/FormatRequest.cc
crypto/LoadRequest.cc
crypto/openssl/DataCryptor.cc
deep_copy/ImageCopyRequest.cc
deep_copy/MetadataCopyRequest.cc
Expand Down Expand Up @@ -209,6 +212,7 @@ endif()

if(LINUX AND HAVE_LIBCRYPTSETUP)
list(APPEND librbd_internal_srcs
crypto/luks/EncryptionFormat.cc
crypto/luks/Header.cc
crypto/luks/FormatRequest.cc
crypto/luks/LoadRequest.cc)
Expand Down
12 changes: 12 additions & 0 deletions src/librbd/ImageCtx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,18 @@ librados::IoCtx duplicate_io_ctx(librados::IoCtx& io_ctx) {
return 0;
}

uint64_t ImageCtx::get_effective_image_size(snap_t in_snap_id) const {
auto raw_size = get_image_size(in_snap_id);
if (raw_size == 0) {
return 0;
}

io::Extents extents = {{raw_size, 0}};
io_image_dispatcher->remap_extents(
extents, io::IMAGE_EXTENTS_MAP_TYPE_PHYSICAL_TO_LOGICAL);
return extents.front().first;
}

uint64_t ImageCtx::get_object_count(snap_t in_snap_id) const {
ceph_assert(ceph_mutex_is_locked(image_lock));
uint64_t image_size = get_image_size(in_snap_id);
Expand Down
1 change: 1 addition & 0 deletions src/librbd/ImageCtx.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ namespace librbd {
std::string in_snap_name,
librados::snap_t id);
uint64_t get_image_size(librados::snap_t in_snap_id) const;
uint64_t get_effective_image_size(librados::snap_t in_snap_id) const;
uint64_t get_object_count(librados::snap_t in_snap_id) const;
bool test_features(uint64_t test_features) const;
bool test_features(uint64_t test_features,
Expand Down
80 changes: 64 additions & 16 deletions src/librbd/api/Image.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@
#include "librbd/Utils.h"
#include "librbd/api/Config.h"
#include "librbd/api/Trash.h"
#include "librbd/api/Utils.h"
#include "librbd/crypto/FormatRequest.h"
#include "librbd/crypto/LoadRequest.h"
#include "librbd/deep_copy/Handler.h"
#include "librbd/image/CloneRequest.h"
#include "librbd/image/RemoveRequest.h"
#include "librbd/image/PreRemoveRequest.h"
#include "librbd/io/ImageDispatcherInterface.h"
#include "librbd/io/ObjectDispatcherInterface.h"
#include <boost/scope_exit.hpp>

#define dout_subsys ceph_subsys_rbd
Expand Down Expand Up @@ -397,7 +402,8 @@ int Image<I>::list_descendants(
}

IoCtx ioctx;
r = util::create_ioctx(ictx->md_ctx, "child image", it.first, {}, &ioctx);
r = librbd::util::create_ioctx(
ictx->md_ctx, "child image", it.first, {}, &ioctx);
if (r == -ENOENT) {
continue;
} else if (r < 0) {
Expand Down Expand Up @@ -425,16 +431,17 @@ int Image<I>::list_descendants(

// retrieve clone v2 children attached to this snapshot
IoCtx parent_io_ctx;
r = util::create_ioctx(ictx->md_ctx, "parent image", parent_spec.pool_id,
parent_spec.pool_namespace, &parent_io_ctx);
r = librbd::util::create_ioctx(
ictx->md_ctx, "parent image",parent_spec.pool_id,
parent_spec.pool_namespace, &parent_io_ctx);
if (r < 0) {
return r;
}

cls::rbd::ChildImageSpecs child_images;
r = cls_client::children_list(&parent_io_ctx,
util::header_name(parent_spec.image_id),
parent_spec.snap_id, &child_images);
r = cls_client::children_list(
&parent_io_ctx, librbd::util::header_name(parent_spec.image_id),
parent_spec.snap_id, &child_images);
if (r < 0 && r != -ENOENT && r != -EOPNOTSUPP) {
lderr(cct) << "error retrieving children: " << cpp_strerror(r) << dendl;
return r;
Expand All @@ -446,8 +453,9 @@ int Image<I>::list_descendants(
child_image.image_id, "", false});
if (!child_max_level || *child_max_level > 0) {
IoCtx ioctx;
r = util::create_ioctx(ictx->md_ctx, "child image", child_image.pool_id,
child_image.pool_namespace, &ioctx);
r = librbd::util::create_ioctx(
ictx->md_ctx, "child image", child_image.pool_id,
child_image.pool_namespace, &ioctx);
if (r == -ENOENT) {
continue;
} else if (r < 0) {
Expand All @@ -470,8 +478,9 @@ int Image<I>::list_descendants(
for (auto& image : *images) {
if (child_pool_id == -1 || child_pool_id != image.pool_id ||
child_io_ctx.get_namespace() != image.pool_namespace) {
r = util::create_ioctx(ictx->md_ctx, "child image", image.pool_id,
image.pool_namespace, &child_io_ctx);
r = librbd::util::create_ioctx(
ictx->md_ctx, "child image", image.pool_id, image.pool_namespace,
&child_io_ctx);
if (r == -ENOENT) {
image.pool_name = "";
image.image_name = "";
Expand Down Expand Up @@ -604,8 +613,9 @@ int Image<I>::deep_copy(I *src, librados::IoCtx& dest_md_ctx,
r = create(dest_md_ctx, destname, "", src_size, opts, "", "", false);
} else {
librados::IoCtx parent_io_ctx;
r = util::create_ioctx(src->md_ctx, "parent image", parent_spec.pool_id,
parent_spec.pool_namespace, &parent_io_ctx);
r = librbd::util::create_ioctx(
src->md_ctx, "parent image", parent_spec.pool_id,
parent_spec.pool_namespace, &parent_io_ctx);
if (r < 0) {
return r;
}
Expand All @@ -614,7 +624,7 @@ int Image<I>::deep_copy(I *src, librados::IoCtx& dest_md_ctx,
api::Config<I>::apply_pool_overrides(dest_md_ctx, &config);

C_SaferCond ctx;
std::string dest_id = util::generate_image_id(dest_md_ctx);
std::string dest_id = librbd::util::generate_image_id(dest_md_ctx);
auto *req = image::CloneRequest<I>::create(
config, parent_io_ctx, parent_spec.image_id, "", {}, parent_spec.snap_id,
dest_md_ctx, destname, dest_id, opts, cls::rbd::MIRROR_IMAGE_MODE_JOURNAL,
Expand Down Expand Up @@ -874,9 +884,9 @@ int Image<I>::flatten_children(I *ictx, const char* snap_name,
if (child_pool_id == -1 ||
child_pool_id != child_image.pool_id ||
child_io_ctx.get_namespace() != child_image.pool_namespace) {
r = util::create_ioctx(ictx->md_ctx, "child image",
child_image.pool_id, child_image.pool_namespace,
&child_io_ctx);
r = librbd::util::create_ioctx(
ictx->md_ctx, "child image", child_image.pool_id,
child_image.pool_namespace, &child_io_ctx);
if (r < 0) {
return r;
}
Expand Down Expand Up @@ -924,6 +934,44 @@ int Image<I>::flatten_children(I *ictx, const char* snap_name,
return 0;
}

template <typename I>
int Image<I>::encryption_format(I* ictx, encryption_format_t format,
encryption_options_t opts, size_t opts_size,
bool c_api) {
crypto::EncryptionFormat<I>* result_format;
auto r = util::create_encryption_format(
ictx->cct, format, opts, opts_size, c_api, &result_format);
if (r != 0) {
return r;
}

C_SaferCond cond;
auto req = librbd::crypto::FormatRequest<I>::create(
ictx, std::unique_ptr<crypto::EncryptionFormat<I>>(result_format),
&cond);
req->send();
return cond.wait();
}

template <typename I>
int Image<I>::encryption_load(I* ictx, encryption_format_t format,
encryption_options_t opts, size_t opts_size,
bool c_api) {
crypto::EncryptionFormat<I>* result_format;
auto r = util::create_encryption_format(
ictx->cct, format, opts, opts_size, c_api, &result_format);
if (r != 0) {
return r;
}

C_SaferCond cond;
auto req = librbd::crypto::LoadRequest<I>::create(
ictx, std::unique_ptr<crypto::EncryptionFormat<I>>(result_format),
&cond);
req->send();
return cond.wait();
}

} // namespace api
} // namespace librbd

Expand Down
7 changes: 7 additions & 0 deletions src/librbd/api/Image.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ struct Image {

static int flatten_children(ImageCtxT *ictx, const char* snap_name, ProgressContext& pctx);

static int encryption_format(ImageCtxT *ictx, encryption_format_t format,
encryption_options_t opts, size_t opts_size,
bool c_api);
static int encryption_load(ImageCtxT *ictx, encryption_format_t format,
encryption_options_t opts, size_t opts_size,
bool c_api);

};

} // namespace api
Expand Down
84 changes: 84 additions & 0 deletions src/librbd/api/Utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

#include "librbd/api/Utils.h"
#include "common/dout.h"

#if defined(HAVE_LIBCRYPTSETUP)
#include "librbd/crypto/luks/EncryptionFormat.h"
#endif

#define dout_subsys ceph_subsys_rbd
#undef dout_prefix
#define dout_prefix *_dout << "librbd::api::util: " << __func__ << ": "

namespace librbd {
namespace api {
namespace util {

template <typename I>
int create_encryption_format(
CephContext* cct, encryption_format_t format,
encryption_options_t opts, size_t opts_size, bool c_api,
crypto::EncryptionFormat<I>** result_format) {
size_t expected_opts_size;
switch (format) {
#if defined(HAVE_LIBCRYPTSETUP)
case RBD_ENCRYPTION_FORMAT_LUKS1: {
if (c_api) {
expected_opts_size = sizeof(rbd_encryption_luks1_format_options_t);
if (expected_opts_size == opts_size) {
auto c_opts = (rbd_encryption_luks1_format_options_t*)opts;
*result_format = new crypto::luks::LUKS1EncryptionFormat<I>(
c_opts->alg, {c_opts->passphrase, c_opts->passphrase_size});
}
} else {
expected_opts_size = sizeof(encryption_luks1_format_options_t);
if (expected_opts_size == opts_size) {
auto cpp_opts = (encryption_luks1_format_options_t*)opts;
*result_format = new crypto::luks::LUKS1EncryptionFormat<I>(
cpp_opts->alg, std::move(cpp_opts->passphrase));
}
}
break;
}
case RBD_ENCRYPTION_FORMAT_LUKS2: {
if (c_api) {
expected_opts_size = sizeof(rbd_encryption_luks2_format_options_t);
if (expected_opts_size == opts_size) {
auto c_opts = (rbd_encryption_luks2_format_options_t*)opts;
*result_format = new crypto::luks::LUKS2EncryptionFormat<I>(
c_opts->alg, {c_opts->passphrase, c_opts->passphrase_size});
}
} else {
expected_opts_size = sizeof(encryption_luks2_format_options_t);
if (expected_opts_size == opts_size) {
auto cpp_opts = (encryption_luks2_format_options_t*)opts;
*result_format = new crypto::luks::LUKS2EncryptionFormat<I>(
cpp_opts->alg, std::move(cpp_opts->passphrase));
}
}
break;
}
#endif
default:
lderr(cct) << "unsupported encryption format: " << format << dendl;
return -ENOTSUP;
}

if (expected_opts_size != opts_size) {
lderr(cct) << "expected opts_size: " << expected_opts_size << dendl;
return -EINVAL;
}

return 0;
}

} // namespace util
} // namespace api
} // namespace librbd

template int librbd::api::util::create_encryption_format(
CephContext* cct, encryption_format_t format, encryption_options_t opts,
size_t opts_size, bool c_api,
crypto::EncryptionFormat<librbd::ImageCtx>** result_format);
Loading

0 comments on commit 99d8cf9

Please sign in to comment.