1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "FormatRequest.h"
7 #include <openssl/rand.h>
8 #include "common/dout.h"
9 #include "common/errno.h"
10 #include "include/compat.h"
11 #include "librbd/Utils.h"
12 #include "librbd/crypto/Utils.h"
13 #include "librbd/crypto/luks/Header.h"
14 #include "librbd/io/AioCompletion.h"
15 #include "librbd/io/ImageDispatchSpec.h"
17 #define dout_subsys ceph_subsys_rbd
19 #define dout_prefix *_dout << "librbd::crypto::luks::FormatRequest: " << this \
20 << " " << __func__ << ": "
26 using librbd::util::create_context_callback
;
29 FormatRequest
<I
>::FormatRequest(
30 I
* image_ctx
, encryption_format_t format
, encryption_algorithm_t alg
,
31 std::string
&& passphrase
, ceph::ref_t
<CryptoInterface
>* result_crypto
,
33 bool insecure_fast_mode
) : m_image_ctx(image_ctx
), m_format(format
),
35 m_passphrase(std::move(passphrase
)),
36 m_result_crypto(result_crypto
),
37 m_on_finish(on_finish
),
38 m_insecure_fast_mode(insecure_fast_mode
),
39 m_header(image_ctx
->cct
) {
43 void FormatRequest
<I
>::send() {
47 case RBD_ENCRYPTION_FORMAT_LUKS1
:
51 case RBD_ENCRYPTION_FORMAT_LUKS2
:
56 lderr(m_image_ctx
->cct
) << "unsupported format type: " << m_format
65 case RBD_ENCRYPTION_ALGORITHM_AES128
:
69 case RBD_ENCRYPTION_ALGORITHM_AES256
:
74 lderr(m_image_ctx
->cct
) << "unsupported cipher algorithm: " << m_alg
80 // generate encryption key
81 unsigned char* key
= (unsigned char*)alloca(key_size
);
82 if (RAND_bytes((unsigned char *)key
, key_size
) != 1) {
83 lderr(m_image_ctx
->cct
) << "cannot generate random encryption key"
89 // setup interface with libcryptsetup
90 auto r
= m_header
.init();
96 // format (create LUKS header)
97 r
= m_header
.format(type
, cipher
, reinterpret_cast<char*>(key
), key_size
,
98 "xts-plain64", sector_size
,
99 m_image_ctx
->get_object_size(), m_insecure_fast_mode
);
105 m_image_ctx
->image_lock
.lock_shared();
106 uint64_t image_size
= m_image_ctx
->get_image_size(CEPH_NOSNAP
);
107 m_image_ctx
->image_lock
.unlock_shared();
109 if (m_header
.get_data_offset() >= image_size
) {
110 lderr(m_image_ctx
->cct
) << "image is too small. format requires more than "
111 << m_header
.get_data_offset() << " bytes" << dendl
;
116 // add keyslot (volume key encrypted with passphrase)
117 r
= m_header
.add_keyslot(m_passphrase
.c_str(), m_passphrase
.size());
123 r
= util::build_crypto(m_image_ctx
->cct
, key
, key_size
,
124 m_header
.get_sector_size(),
125 m_header
.get_data_offset(), m_result_crypto
);
126 ceph_memzero_s(key
, key_size
, key_size
);
132 // read header from libcryptsetup interface
134 r
= m_header
.read(&bl
);
140 // write header to offset 0 of the image
141 auto ctx
= create_context_callback
<
142 FormatRequest
<I
>, &FormatRequest
<I
>::handle_write_header
>(this);
143 auto aio_comp
= io::AioCompletion::create_and_start(
144 ctx
, librbd::util::get_image_ctx(m_image_ctx
), io::AIO_TYPE_WRITE
);
146 ZTracer::Trace trace
;
147 auto req
= io::ImageDispatchSpec::create_write(
148 *m_image_ctx
, io::IMAGE_DISPATCH_LAYER_API_START
, aio_comp
,
149 {{0, bl
.length()}}, std::move(bl
),
150 m_image_ctx
->get_data_io_context(), 0, trace
);
154 template <typename I
>
155 void FormatRequest
<I
>::handle_write_header(int r
) {
157 lderr(m_image_ctx
->cct
) << "error writing header to image: "
158 << cpp_strerror(r
) << dendl
;
166 template <typename I
>
167 void FormatRequest
<I
>::finish(int r
) {
169 &m_passphrase
[0], m_passphrase
.capacity(), m_passphrase
.size());
170 m_on_finish
->complete(r
);
175 } // namespace crypto
176 } // namespace librbd
178 template class librbd::crypto::luks::FormatRequest
<librbd::ImageCtx
>;