]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/test/librbd/crypto/luks/test_mock_LoadRequest.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / librbd / crypto / luks / test_mock_LoadRequest.cc
index 1a2300616abc21f68ca83b83ca64714f2c130f95..5fb566a07bb7458b6c8dbff83b16ca028a09d492 100644 (file)
@@ -33,13 +33,14 @@ struct TestMockCryptoLuksLoadRequest : public TestMockFixture {
   std::string passphrase = passphrase_cstr;
 
   MockImageCtx* mock_image_ctx;
-  ceph::ref_t<CryptoInterface> crypto;
+  std::unique_ptr<CryptoInterface> crypto;
   MockLoadRequest* mock_load_request;
   C_SaferCond finished_cond;
   Context *on_finish = &finished_cond;
   Context* image_read_request;
   ceph::bufferlist header_bl;
   uint64_t data_offset;
+  std::string detected_format_name;
 
   void SetUp() override {
     TestMockFixture::SetUp();
@@ -47,31 +48,31 @@ struct TestMockCryptoLuksLoadRequest : public TestMockFixture {
     librbd::ImageCtx *ictx;
     ASSERT_EQ(0, open_image(m_image_name, &ictx));
     mock_image_ctx = new MockImageCtx(*ictx);
-    crypto = nullptr;
     mock_load_request = MockLoadRequest::create(
-            mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2, std::move(passphrase),
-            &crypto, on_finish);
+        mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2, std::move(passphrase),
+        &crypto, &detected_format_name, on_finish);
+    detected_format_name = "";
   }
 
   void TearDown() override {
     delete mock_image_ctx;
-    if (crypto != nullptr) {
-      crypto->put();
-      crypto = nullptr;
-    }
     TestMockFixture::TearDown();
   }
 
   // returns data offset in bytes
   void generate_header(const char* type, const char* alg, size_t key_size,
-                       const char* cipher_mode, uint32_t sector_size) {
+                       const char* cipher_mode, uint32_t sector_size,
+                       bool magic_switched) {
     Header header(mock_image_ctx->cct);
 
     ASSERT_EQ(0, header.init());
     ASSERT_EQ(0, header.format(type, alg, nullptr, key_size, cipher_mode,
                                sector_size, OBJECT_SIZE, true));
     ASSERT_EQ(0, header.add_keyslot(passphrase_cstr, strlen(passphrase_cstr)));
-    ASSERT_LE(0, header.read(&header_bl));
+    ASSERT_LT(0, header.read(&header_bl));
+    if (magic_switched) {
+      ASSERT_EQ(0, Magic::replace_magic(mock_image_ctx->cct, header_bl));
+    }
 
     data_offset = header.get_data_offset();
   }
@@ -102,108 +103,218 @@ struct TestMockCryptoLuksLoadRequest : public TestMockFixture {
                 image_read_request = ctx;
             }));
   }
+
+  void expect_get_image_size(uint64_t size) {
+    EXPECT_CALL(*mock_image_ctx, get_image_size(_)).WillOnce(
+        Return(size));
+  }
+
+  void expect_get_stripe_period(uint64_t period) {
+    EXPECT_CALL(*mock_image_ctx, get_stripe_period()).WillOnce(
+        Return(period));
+  }
 };
 
 TEST_F(TestMockCryptoLuksLoadRequest, AES128) {
-  generate_header(CRYPT_LUKS2, "aes", 32, "xts-plain64", 4096);
+  generate_header(CRYPT_LUKS2, "aes", 32, "xts-plain64", 4096, false);
   expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
   mock_load_request->send();
   image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
   ASSERT_EQ(0, finished_cond.wait());
-  ASSERT_NE(crypto, nullptr);
+  ASSERT_NE(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
 }
 
 TEST_F(TestMockCryptoLuksLoadRequest, AES256) {
-  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096);
+  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096, false);
   expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
   mock_load_request->send();
   image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
   ASSERT_EQ(0, finished_cond.wait());
-  ASSERT_NE(crypto, nullptr);
+  ASSERT_NE(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
 }
 
 TEST_F(TestMockCryptoLuksLoadRequest, LUKS1) {
   delete mock_load_request;
   mock_load_request = MockLoadRequest::create(
-          mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS1, {passphrase_cstr},
-          &crypto, on_finish);
-  generate_header(CRYPT_LUKS1, "aes", 32, "xts-plain64", 512);
+      mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS1, {passphrase_cstr}, &crypto,
+      &detected_format_name, on_finish);
+  generate_header(CRYPT_LUKS1, "aes", 32, "xts-plain64", 512, false);
   expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
   mock_load_request->send();
   image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
   ASSERT_EQ(0, finished_cond.wait());
-  ASSERT_NE(crypto, nullptr);
+  ASSERT_NE(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS1", detected_format_name);
+}
+
+TEST_F(TestMockCryptoLuksLoadRequest, LUKS1ViaLUKS) {
+  delete mock_load_request;
+  mock_load_request = MockLoadRequest::create(
+      mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS, {passphrase_cstr}, &crypto,
+      &detected_format_name, on_finish);
+  generate_header(CRYPT_LUKS1, "aes", 32, "xts-plain64", 512, false);
+  expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
+  mock_load_request->send();
+  image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
+  ASSERT_EQ(0, finished_cond.wait());
+  ASSERT_NE(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS1", detected_format_name);
+}
+
+TEST_F(TestMockCryptoLuksLoadRequest, UnknownFormat) {
+  header_bl.append_zero(MAXIMUM_HEADER_SIZE);
+  expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  mock_load_request->send();
+
+  image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
+
+  ASSERT_EQ(-EINVAL, finished_cond.wait());
+  ASSERT_EQ(crypto.get(), nullptr);
+  ASSERT_EQ("<unknown>", detected_format_name);
 }
 
 TEST_F(TestMockCryptoLuksLoadRequest, WrongFormat) {
-  generate_header(CRYPT_LUKS1, "aes", 32, "xts-plain64", 512);
+  generate_header(CRYPT_LUKS1, "aes", 32, "xts-plain64", 512, false);
   expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
   mock_load_request->send();
 
   expect_image_read(DEFAULT_INITIAL_READ_SIZE,
                     MAXIMUM_HEADER_SIZE - DEFAULT_INITIAL_READ_SIZE);
-  image_read_request->complete(DEFAULT_INITIAL_READ_SIZE); // complete 1st read
+  image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
+  image_read_request->complete(MAXIMUM_HEADER_SIZE - DEFAULT_INITIAL_READ_SIZE);
 
-  image_read_request->complete(
-          MAXIMUM_HEADER_SIZE - DEFAULT_INITIAL_READ_SIZE);
   ASSERT_EQ(-EINVAL, finished_cond.wait());
-  ASSERT_EQ(crypto, nullptr);
+  ASSERT_EQ(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS", detected_format_name);
 }
 
 TEST_F(TestMockCryptoLuksLoadRequest, UnsupportedAlgorithm) {
-  generate_header(CRYPT_LUKS2, "twofish", 32, "xts-plain64", 4096);
+  generate_header(CRYPT_LUKS2, "twofish", 32, "xts-plain64", 4096, false);
   expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
   mock_load_request->send();
   image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
   ASSERT_EQ(-ENOTSUP, finished_cond.wait());
-  ASSERT_EQ(crypto, nullptr);
+  ASSERT_EQ(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
 }
 
 TEST_F(TestMockCryptoLuksLoadRequest, UnsupportedCipherMode) {
-  generate_header(CRYPT_LUKS2, "aes", 32, "cbc-essiv:sha256", 4096);
+  generate_header(CRYPT_LUKS2, "aes", 32, "cbc-essiv:sha256", 4096, false);
   expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
   mock_load_request->send();
   image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
   ASSERT_EQ(-ENOTSUP, finished_cond.wait());
-  ASSERT_EQ(crypto, nullptr);
+  ASSERT_EQ(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
+}
+
+TEST_F(TestMockCryptoLuksLoadRequest, BadSize) {
+  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096, false);
+  expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE - 1);
+  mock_load_request->send();
+  image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
+  ASSERT_EQ(-EINVAL, finished_cond.wait());
+  ASSERT_EQ(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
+}
+
+TEST_F(TestMockCryptoLuksLoadRequest, BadStripePattern) {
+  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096, false);
+  expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE * 3);
+  mock_load_request->send();
+  image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
+  ASSERT_EQ(-EINVAL, finished_cond.wait());
+  ASSERT_EQ(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
 }
 
 TEST_F(TestMockCryptoLuksLoadRequest, HeaderBiggerThanInitialRead) {
-  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096);
+  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096, false);
   mock_load_request->set_initial_read_size(4096);
   expect_image_read(0, 4096);
   mock_load_request->send();
 
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
   expect_image_read(4096, MAXIMUM_HEADER_SIZE - 4096);
   image_read_request->complete(4096); // complete initial read
 
   image_read_request->complete(MAXIMUM_HEADER_SIZE - 4096);
   ASSERT_EQ(0, finished_cond.wait());
-  ASSERT_NE(crypto, nullptr);
+  ASSERT_NE(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
+}
+
+TEST_F(TestMockCryptoLuksLoadRequest, LUKS1FormattedClone) {
+  mock_image_ctx->parent = mock_image_ctx;
+  delete mock_load_request;
+  mock_load_request = MockLoadRequest::create(
+      mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS1, {passphrase_cstr}, &crypto,
+      &detected_format_name, on_finish);
+  generate_header(CRYPT_LUKS1, "aes", 64, "xts-plain64", 512, true);
+  expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
+  mock_load_request->send();
+  image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
+  ASSERT_EQ(0, finished_cond.wait());
+  ASSERT_NE(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS1", detected_format_name);
+}
+
+TEST_F(TestMockCryptoLuksLoadRequest, LUKS2FormattedClone) {
+  mock_image_ctx->parent = mock_image_ctx;
+  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096, true);
+  expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
+  mock_load_request->send();
+  image_read_request->complete(DEFAULT_INITIAL_READ_SIZE);
+  ASSERT_EQ(0, finished_cond.wait());
+  ASSERT_NE(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
 }
 
 TEST_F(TestMockCryptoLuksLoadRequest, KeyslotsBiggerThanInitialRead) {
-  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096);
+  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096, false);
   mock_load_request->set_initial_read_size(16384);
   expect_image_read(0, 16384);
   mock_load_request->send();
 
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
   expect_image_read(16384, data_offset - 16384);
   image_read_request->complete(16384); // complete initial read
 
   image_read_request->complete(data_offset - 16384);
   ASSERT_EQ(0, finished_cond.wait());
-  ASSERT_NE(crypto, nullptr);
+  ASSERT_NE(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
 }
 
 TEST_F(TestMockCryptoLuksLoadRequest, WrongPassphrase) {
   delete mock_load_request;
   mock_load_request = MockLoadRequest::create(
-        mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2, "wrong", &crypto,
-        on_finish);
+      mock_image_ctx, RBD_ENCRYPTION_FORMAT_LUKS2, "wrong", &crypto,
+      &detected_format_name, on_finish);
 
-  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096);
+  generate_header(CRYPT_LUKS2, "aes", 64, "xts-plain64", 4096, false);
   expect_image_read(0, DEFAULT_INITIAL_READ_SIZE);
+  expect_get_image_size(OBJECT_SIZE << 5);
+  expect_get_stripe_period(OBJECT_SIZE);
   mock_load_request->send();
 
   // crypt_volume_key_get will fail, we will retry reading more
@@ -213,7 +324,8 @@ TEST_F(TestMockCryptoLuksLoadRequest, WrongPassphrase) {
 
   image_read_request->complete(data_offset - DEFAULT_INITIAL_READ_SIZE);
   ASSERT_EQ(-EPERM, finished_cond.wait());
-  ASSERT_EQ(crypto, nullptr);
+  ASSERT_EQ(crypto.get(), nullptr);
+  ASSERT_EQ("LUKS2", detected_format_name);
 }
 
 } // namespace luks