]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librbd/crypto/luks/test_mock_FormatRequest.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / librbd / crypto / luks / test_mock_FormatRequest.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "test/librbd/test_mock_fixture.h"
5 #include "test/librbd/test_support.h"
6 #include "test/librbd/mock/MockImageCtx.h"
7
8 namespace librbd {
9 namespace util {
10
11 inline ImageCtx *get_image_ctx(MockImageCtx *image_ctx) {
12 return image_ctx->image_ctx;
13 }
14
15 } // namespace util
16 } // namespace librbd
17
18 #include "librbd/crypto/luks/FormatRequest.cc"
19
20 namespace librbd {
21 namespace crypto {
22 namespace luks {
23
24 using ::testing::_;
25 using ::testing::Invoke;
26 using ::testing::Return;
27
28 struct TestMockCryptoLuksFormatRequest : public TestMockFixture {
29 typedef FormatRequest<librbd::MockImageCtx> MockFormatRequest;
30
31 const size_t OBJECT_SIZE = 4 * 1024 * 1024;
32 const size_t IMAGE_SIZE = 1024 * 1024 * 1024;
33 const char* passphrase_cstr = "password";
34 std::string passphrase = passphrase_cstr;
35
36 MockImageCtx* mock_image_ctx;
37 C_SaferCond finished_cond;
38 Context *on_finish = &finished_cond;
39 io::AioCompletion* aio_comp;
40 ceph::bufferlist header_bl;
41 std::unique_ptr<CryptoInterface> crypto;
42
43 void SetUp() override {
44 TestMockFixture::SetUp();
45
46 librbd::ImageCtx *ictx;
47 ASSERT_EQ(0, open_image(m_image_name, &ictx));
48 mock_image_ctx = new MockImageCtx(*ictx);
49 }
50
51 void TearDown() override {
52 delete mock_image_ctx;
53 TestMockFixture::TearDown();
54 }
55
56 void expect_get_stripe_period() {
57 EXPECT_CALL(*mock_image_ctx, get_stripe_period()).WillOnce(Return(
58 OBJECT_SIZE));
59 }
60
61 void expect_get_image_size(uint64_t image_size) {
62 EXPECT_CALL(*mock_image_ctx, get_image_size(CEPH_NOSNAP)).WillOnce(Return(
63 image_size));
64 }
65
66 void expect_image_write() {
67 EXPECT_CALL(*mock_image_ctx->io_image_dispatcher, send(_))
68 .WillOnce(Invoke([this](io::ImageDispatchSpec* spec) {
69 auto* write = boost::get<io::ImageDispatchSpec::Write>(
70 &spec->request);
71 ASSERT_TRUE(write != nullptr);
72
73 ASSERT_EQ(1, spec->image_extents.size());
74 ASSERT_EQ(0, spec->image_extents[0].first);
75 ASSERT_GT(spec->image_extents[0].second, 0);
76
77 spec->dispatch_result = io::DISPATCH_RESULT_COMPLETE;
78 aio_comp = spec->aio_comp;
79 header_bl = write->bl;
80 }));
81 }
82
83 void complete_aio(int r) {
84 if (r < 0) {
85 aio_comp->fail(r);
86 } else {
87 aio_comp->set_request_count(1);
88 aio_comp->add_request();
89 aio_comp->complete_request(r);
90 }
91 }
92
93 void verify_header(const char* expected_format, size_t expected_key_length,
94 uint64_t expected_sector_size, bool magic_switched) {
95 Header header(mock_image_ctx->cct);
96
97 ASSERT_EQ(0, header.init());
98
99 if (magic_switched) {
100 Header non_switched_header(mock_image_ctx->cct);
101 ASSERT_EQ(0, non_switched_header.init());
102 ASSERT_EQ(0, non_switched_header.write(header_bl));
103 ASSERT_EQ(-EINVAL, non_switched_header.load(expected_format));
104 ASSERT_EQ(0, Magic::replace_magic(mock_image_ctx->cct, header_bl));
105 }
106 ASSERT_EQ(0, header.write(header_bl));
107 ASSERT_EQ(0, header.load(expected_format));
108
109 ASSERT_EQ(expected_sector_size, header.get_sector_size());
110 ASSERT_EQ(0, header.get_data_offset() % OBJECT_SIZE);
111
112 char volume_key[64];
113 size_t volume_key_size = sizeof(volume_key);
114 ASSERT_EQ(0, header.read_volume_key(
115 passphrase_cstr, strlen(passphrase_cstr),
116 reinterpret_cast<char*>(volume_key), &volume_key_size));
117
118 ASSERT_EQ(expected_key_length, crypto->get_key_length());
119 ASSERT_EQ(0, std::memcmp(
120 volume_key, crypto->get_key(), expected_key_length));
121 ASSERT_EQ(expected_sector_size, crypto->get_block_size());
122 ASSERT_EQ(header.get_data_offset(), crypto->get_data_offset());
123 }
124 };
125
126 TEST_F(TestMockCryptoLuksFormatRequest, LUKS1) {
127 auto mock_format_request = MockFormatRequest::create(
128 mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS1,
129 RBD_ENCRYPTION_ALGORITHM_AES128, std::move(passphrase), &crypto,
130 on_finish, true);
131 expect_get_stripe_period();
132 expect_get_image_size(IMAGE_SIZE);
133 expect_image_write();
134 mock_format_request->send();
135 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
136 complete_aio(0);
137 ASSERT_EQ(0, finished_cond.wait());
138 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS1, 32, 512, false));
139 }
140
141 TEST_F(TestMockCryptoLuksFormatRequest, AES128) {
142 auto mock_format_request = MockFormatRequest::create(
143 mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2,
144 RBD_ENCRYPTION_ALGORITHM_AES128, std::move(passphrase), &crypto,
145 on_finish, true);
146 expect_get_stripe_period();
147 expect_get_image_size(IMAGE_SIZE);
148 expect_image_write();
149 mock_format_request->send();
150 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
151 complete_aio(0);
152 ASSERT_EQ(0, finished_cond.wait());
153 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS2, 32, 4096, false));
154 }
155
156 TEST_F(TestMockCryptoLuksFormatRequest, AES256) {
157 auto mock_format_request = MockFormatRequest::create(
158 mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2,
159 RBD_ENCRYPTION_ALGORITHM_AES256, std::move(passphrase), &crypto,
160 on_finish, true);
161 expect_get_stripe_period();
162 expect_get_image_size(IMAGE_SIZE);
163 expect_image_write();
164 mock_format_request->send();
165 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
166 complete_aio(0);
167 ASSERT_EQ(0, finished_cond.wait());
168 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS2, 64, 4096, false));
169 }
170
171 TEST_F(TestMockCryptoLuksFormatRequest, LUKS1OnCloned) {
172 mock_image_ctx->parent = mock_image_ctx;
173 auto mock_format_request = MockFormatRequest::create(
174 mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS1,
175 RBD_ENCRYPTION_ALGORITHM_AES256, std::move(passphrase), &crypto,
176 on_finish, true);
177 expect_get_stripe_period();
178 expect_get_image_size(IMAGE_SIZE);
179 expect_image_write();
180 mock_format_request->send();
181 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
182 complete_aio(0);
183 ASSERT_EQ(0, finished_cond.wait());
184 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS1, 64, 512, true));
185 }
186
187 TEST_F(TestMockCryptoLuksFormatRequest, LUKS2OnCloned) {
188 mock_image_ctx->parent = mock_image_ctx;
189 auto mock_format_request = MockFormatRequest::create(
190 mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2,
191 RBD_ENCRYPTION_ALGORITHM_AES256, std::move(passphrase), &crypto,
192 on_finish, true);
193 expect_get_stripe_period();
194 expect_get_image_size(IMAGE_SIZE);
195 expect_image_write();
196 mock_format_request->send();
197 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
198 complete_aio(0);
199 ASSERT_EQ(0, finished_cond.wait());
200 ASSERT_NO_FATAL_FAILURE(verify_header(CRYPT_LUKS2, 64, 4096, true));
201 }
202
203 TEST_F(TestMockCryptoLuksFormatRequest, ImageTooSmall) {
204 auto mock_format_request = MockFormatRequest::create(
205 mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2,
206 RBD_ENCRYPTION_ALGORITHM_AES256, std::move(passphrase), &crypto,
207 on_finish, true);
208 expect_get_stripe_period();
209 expect_get_image_size(1024*1024);
210 mock_format_request->send();
211 ASSERT_EQ(-ENOSPC, finished_cond.wait());
212 }
213
214 TEST_F(TestMockCryptoLuksFormatRequest, WriteFail) {
215 auto mock_format_request = MockFormatRequest::create(
216 mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2,
217 RBD_ENCRYPTION_ALGORITHM_AES256, std::move(passphrase), &crypto,
218 on_finish, true);
219 expect_get_stripe_period();
220 expect_get_image_size(IMAGE_SIZE);
221 expect_image_write();
222 mock_format_request->send();
223 ASSERT_EQ(ETIMEDOUT, finished_cond.wait_for(0));
224 complete_aio(-123);
225 ASSERT_EQ(-123, finished_cond.wait());
226 }
227
228 } // namespace luks
229 } // namespace crypto
230 } // namespace librbd