]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
auth: test slice interface for aes256k
authorYehuda Sadeh <ysadehwe@ibm.com>
Mon, 17 Mar 2025 11:44:30 +0000 (07:44 -0400)
committerPatrick Donnelly <pdonnell@ibm.com>
Wed, 1 Oct 2025 18:46:46 +0000 (14:46 -0400)
AES256KRB5 uses the default slice encryption implementation, testing that
it works correctly.

Signed-off-by: Yehuda Sadeh <ysadehwe@ibm.com>
src/auth/Crypto.cc
src/auth/Crypto.h
src/test/crypto.cc

index cf8c318f89f3baa74b2cc9742035b502c0252827..1c45ecb734dd45f57a7b855768645af8a831f751 100644 (file)
@@ -156,18 +156,28 @@ int CryptoRandom::open_urandom()
 // fallback implementation of the bufferlist-free
 // interface.
 
-std::size_t CryptoKeyHandler::encrypt(
+std::size_t CryptoKeyHandler::encrypt_ext(
   CephContext *cct,
   const CryptoKeyHandler::in_slice_t& in,
+  const CryptoKeyHandler::in_slice_t *confounder,
   const CryptoKeyHandler::out_slice_t& out) const
 {
+  if (out.buf == nullptr) {
+    return enc_size(in, confounder);
+  }
+
   ceph::bufferptr inptr(reinterpret_cast<const char*>(in.buf), in.length);
   ceph::bufferlist plaintext;
   plaintext.append(std::move(inptr));
 
+  ceph::bufferlist confounder_bl;
+  if (confounder) {
+    ceph::bufferptr cfp(reinterpret_cast<const char*>(confounder->buf), confounder->length);
+    confounder_bl.append(std::move(cfp));
+  }
   ceph::bufferlist ciphertext;
   std::string error;
-  const int ret = encrypt(cct, plaintext, ciphertext, &error);
+  const int ret = encrypt_ext(cct, plaintext, (confounder ? &confounder_bl : nullptr), ciphertext, &error);
   if (ret != 0 || !error.empty()) {
     throw std::runtime_error(std::move(error));
   }
@@ -228,11 +238,11 @@ public:
     : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_0B()) {
   }
 
-  using CryptoKeyHandler::encrypt;
+  using CryptoKeyHandler::encrypt_ext;
   using CryptoKeyHandler::decrypt;
 
-  int encrypt(CephContext *cct, const bufferlist& in,
-              bufferlist& out, std::string *error) const override {
+  int encrypt_ext(CephContext *cct, const bufferlist& in, const bufferlist *confounder,
+                  bufferlist& out, std::string *error) const override {
     out = in;
     return 0;
   }
@@ -290,6 +300,9 @@ public:
     : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_16B()) {
   }
 
+  using CryptoKeyHandler::encrypt;
+  using CryptoKeyHandler::encrypt_ext;
+
   int init(const bufferptr& s, ostringstream& err) {
     secret = s;
 
@@ -312,7 +325,8 @@ public:
     return 0;
   }
 
-  int encrypt(CephContext *cct, const ceph::bufferlist& in,
+  int encrypt_ext(CephContext *cct, const ceph::bufferlist& in,
+                  const bufferlist *confounder /* ignored */,
              ceph::bufferlist& out,
               std::string* /* unused */) const override {
     ldout(cct, 20) << "CryptoAESKeyHandler::encrypt()" << dendl;
@@ -388,12 +402,17 @@ public:
     return 0;
   }
 
+  std::size_t enc_size(const in_slice_t& in,
+                       const in_slice_t *confounder) const override {
+    // 16 + p2align(10, 16) -> 16
+    // 16 + p2align(16, 16) -> 32
+    return AES_BLOCK_LEN + p2align<std::size_t>(in.length, AES_BLOCK_LEN);
+  }
+
   std::size_t encrypt(CephContext *cct, const in_slice_t& in,
                      const out_slice_t& out) const override {
     if (out.buf == nullptr) {
-      // 16 + p2align(10, 16) -> 16
-      // 16 + p2align(16, 16) -> 32
-      return AES_BLOCK_LEN + p2align<std::size_t>(in.length, AES_BLOCK_LEN);
+      return enc_size(in, nullptr);
     }
 
     // how many bytes of in.buf hang outside the alignment boundary and how
@@ -716,8 +735,9 @@ public:
   CryptoAES256KRB5KeyHandler() : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_16B()) {
   }
 
-  using CryptoKeyHandler::encrypt;
+  using CryptoKeyHandler::encrypt_ext;
   using CryptoKeyHandler::decrypt;
+  using CryptoKeyHandler::encrypt;
 
   int init(const ceph::bufferptr& s, uint32_t usage, ostringstream& err) {
     cipher = EVP_CIPHER_fetch(NULL, "AES-256-CBC-CTS", NULL);
@@ -882,6 +902,11 @@ public:
               std::string* unused) const override {
     return encrypt_ext(cct, in, nullptr,  out, unused);
   }
+
+  std::size_t enc_size(const in_slice_t& in,
+                       const in_slice_t *confounder) const override {
+    return 24 + (confounder ? confounder->length : 0 ) + in.length;
+  }
 };
 
 
index 7bd708d3597373bcf8c18709930b4f9ff4d20200..3f7d7ebe491b9c0eeab75c74a9a9ca98548d16cb 100644 (file)
@@ -72,23 +72,33 @@ public:
 
   virtual int encrypt(CephContext *cct,
                       const ceph::buffer::list& in,
-                     ceph::buffer::list& out, std::string *error) const = 0;
+                     ceph::buffer::list& out, std::string *error) const {
+    return encrypt_ext(cct, in, nullptr, out, error);
+  }
 
   /* should either used internally, or for unitests. Confounder should be nullptr otherwise */
   virtual int encrypt_ext(CephContext *cct,
                           const ceph::buffer::list& in,
                           const ceph::buffer::list *confounder,
-                          ceph::buffer::list& out, std::string *error) const {
-    return -ENOTSUP;
-  }
+                          ceph::buffer::list& out, std::string *error) const = 0;
+
   virtual int decrypt(CephContext *cct,
                       const ceph::buffer::list& in,
                      ceph::buffer::list& out, std::string *error) const = 0;
 
-  // TODO: provide nullptr in the out::buf to get/estimate size requirements?
-  // Or maybe dedicated methods?
+  virtual std::size_t enc_size(const in_slice_t& in,
+                       const in_slice_t *confounder) const {
+    return 0;
+  }
+
   virtual std::size_t encrypt(CephContext *cct,
                               const in_slice_t& in,
+                             const out_slice_t& out) const {
+    return encrypt_ext(cct, in, nullptr, out);
+  }
+  virtual std::size_t encrypt_ext(CephContext *cct,
+                              const in_slice_t& in,
+                              const in_slice_t *confounder,
                              const out_slice_t& out) const;
   virtual std::size_t decrypt(CephContext *cct,
                               const in_slice_t& in,
index 8ae35ec7c703b3fdfa543f0a9b58df3dd1b81480..8e239a74ed614cf1c7e83680fa8ea8a09ca3ddc2 100644 (file)
@@ -406,6 +406,49 @@ TEST(AES256KRB5, Encrypt) {
   delete kh;
 }
 
+TEST(AES256KRB5, EncryptNoBl) {
+  auto h = g_ceph_context->get_crypto_manager()->get_handler(CEPH_CRYPTO_AES256KRB5);
+  unsigned char secret_s[] = {
+      0x6D, 0x40, 0x4D, 0x37, 0xFA, 0xF7, 0x9F, 0x9D, 0xF0, 0xD3, 0x35, 0x68, 0xD3, 0x20, 0x66, 0x98,
+      0x00, 0xEB, 0x48, 0x36, 0x47, 0x2E, 0xA8, 0xA0, 0x26, 0xD1, 0x6B, 0x71, 0x82, 0x46, 0x0C, 0x52 };
+
+  bufferptr secret((char *)secret_s, sizeof(secret_s));
+
+  unsigned char confounder_data[] = { 0xB8, 0x0D, 0x32, 0x51, 0xC1, 0xF6, 0x47, 0x14, 0x94, 0x25, 0x6F, 0xFE, 0x71, 0x2D, 0x0B, 0x9A };
+  const CryptoKey::in_slice_t confounder_slice { sizeof(confounder_data), confounder_data };
+
+  unsigned char plaintext_s[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+
+  std::string error;
+  std::unique_ptr<CryptoKeyHandler> kh(h->get_key_handler_ext(secret, 2, error));
+
+  const CryptoKey::in_slice_t plain_slice { sizeof(plaintext_s), plaintext_s };
+
+  // we need to deduce size first
+  const CryptoKey::out_slice_t probe_slice { 0, nullptr };
+  const auto needed = kh->encrypt_ext(g_ceph_context, plain_slice, &confounder_slice, probe_slice);
+  ASSERT_GE(needed, plain_slice.length);
+
+  boost::container::small_vector<
+    // FIXME?
+    //unsigned char, sizeof(plaintext) + kh->get_block_size()> buf;
+    unsigned char, sizeof(plaintext_s) + 16> buf(needed);
+  const CryptoKey::out_slice_t cipher_slice { needed, buf.data() };
+  const auto cipher_size = kh->encrypt_ext(g_ceph_context, plain_slice, &confounder_slice, cipher_slice);
+  ASSERT_EQ(cipher_size, needed);
+
+  unsigned char want_cipher[] = {
+      0x4E, 0xD7, 0xB3, 0x7C, 0x2B, 0xCA, 0xC8, 0xF7, 0x4F, 0x23, 0xC1, 0xCF, 0x07, 0xE6, 0x2B, 0xC7,
+      0xB7, 0x5F, 0xB3, 0xF6, 0x37, 0xB9, 0xF5, 0x59, 0xC7, 0xF6, 0x64, 0xF6, 0x9E, 0xAB, 0x7B, 0x60,
+      0x92, 0x23, 0x75, 0x26, 0xEA, 0x0D, 0x1F, 0x61, 0xCB, 0x20, 0xD6, 0x9D, 0x10, 0xF2
+  };
+
+  ASSERT_EQ(sizeof(want_cipher), cipher_size);
+
+  const int err = memcmp(buf.data(), want_cipher, sizeof(want_cipher));
+  ASSERT_EQ(0, err);
+}
+
 TEST(AES256KRB5, Decrypt) {
   auto h = g_ceph_context->get_crypto_manager()->get_handler(CEPH_CRYPTO_AES256KRB5);
   unsigned char secret_s[] = {