]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
auth: CryptoKey, dynamic usage keys
authorMarcus Watts <mwatts@redhat.com>
Sat, 15 Nov 2025 02:57:53 +0000 (21:57 -0500)
committerPatrick Donnelly <pdonnell@ibm.com>
Mon, 29 Dec 2025 22:34:48 +0000 (17:34 -0500)
Make it possible to specify usage that was not initially declared
when the secret was set in CryptoKey.  As a prerequisite, simplify
the per-usage key storage structures so that is is less heavy-weight
and thread-safe.

Also, extend various encrypt and decrypt apis to enable passing
suage down to CryptoKey.

Signed-off-by: Marcus Watts <mwatts@redhat.com>
src/auth/Crypto.cc
src/auth/Crypto.h

index 8b25040c920833cb7f991b24c2693d84dc00872b..bd3d754e0abc517a4aa4915b93c7d04b8548df8b 100644 (file)
@@ -23,6 +23,7 @@
 #include "common/armor.h"
 #include "common/ceph_context.h"
 #include "common/ceph_crypto.h"
+#include "common/ceph_mutex.h"
 #include "common/debug.h"
 #include "common/hex.h"
 #include "common/safe_io.h"
@@ -440,7 +441,8 @@ public:
     return AES_BLOCK_LEN + p2align<std::size_t>(in.length, AES_BLOCK_LEN);
   }
 
-  std::size_t encrypt(CephContext *cct, const in_slice_t& in,
+  std::size_t encrypt_ext(CephContext *cct, uint32_t usage, const in_slice_t& in,
+                      const in_slice_t *confounder,
                      const out_slice_t& out) const override {
     if (out.buf == nullptr) {
       return enc_size(in, nullptr);
@@ -565,6 +567,7 @@ static constexpr const std::size_t AES256KRB5_KEY_LEN{32};
 static constexpr const std::size_t AES256KRB5_BLOCK_LEN{16};
 static constexpr const std::size_t AES256KRB5_HASH_LEN{24};
 static constexpr const std::size_t SHA384_LEN{48};
+static constexpr const int MAX_USAGE{20};
 
 class CryptoAES256KRB5KeyHandler : public CryptoKeyHandler {
   EVP_CIPHER *cipher{nullptr};
@@ -576,13 +579,11 @@ class CryptoAES256KRB5KeyHandler : public CryptoKeyHandler {
     const unsigned char *ke_raw;
   };
 
-  usage_keys default_usage_keys;
+  mutable ceph::mutex lock = ceph::make_mutex("CryptoAES256KRB5KeyHandler");
 
-  using usage_keys_ref = std::shared_ptr<usage_keys>;
+  mutable usage_keys *keys[MAX_USAGE];
 
-  std::vector<usage_keys_ref> keys;
-
-  int do_init_usage_keys(uint32_t usage, usage_keys *uk, ostringstream& err) {
+  int do_init_usage_keys(uint32_t usage, usage_keys *uk, ostringstream& err) const {
     int r = calc_kx(secret, usage,
                     0x55 /* Ki type */,
                     AES256KRB5_HASH_LEN /* 192 bit */,
@@ -606,48 +607,36 @@ class CryptoAES256KRB5KeyHandler : public CryptoKeyHandler {
     return 0;
   }
 
-  usage_keys *init_usage_keys(uint32_t usage) {
+  usage_keys *init_usage_keys(uint32_t usage) const {
     string err_str;
     ostringstream err(err_str);
 
-    if (usage == default_usage) {
-      int r = do_init_usage_keys(usage, &default_usage_keys, err);
-      if (r < 0) {
-        return nullptr;
-      }
-      return &default_usage_keys;
+    if (usage >= MAX_USAGE) {
+      return nullptr;
     }
 
-    if (usage >= keys.size()) {
-      keys.resize(usage + 8); /* so that we don't resize every time */
-    }
+    auto *uk = new usage_keys;
 
-    auto& uk = keys[usage];
-    if (!uk) {
-      uk = std::make_shared<usage_keys>();
-    }
-
-    int r = do_init_usage_keys(usage, uk.get(), err);
+    int r = do_init_usage_keys(usage, uk, err);
     if (r < 0) {
+      delete uk;
       return nullptr;
     }
-    return uk.get();
+    return uk;
   }
 
   const usage_keys *get_usage_keys(uint32_t usage) const {
-    if (usage == default_usage) {
-      return &default_usage_keys;
-    }
-
-    if (keys.size() <= usage) {
+    if (usage >= MAX_USAGE) {
       return nullptr;
     }
-    auto& k_ref = keys[usage];
-    if (!k_ref) {
-      return nullptr;
+    if (!keys[usage]) {
+      std::unique_lock l(lock);
+      if (!keys[usage]) {
+       auto *uk = init_usage_keys(usage);
+       keys[usage] = uk;
+      }
     }
-
-    return k_ref.get();
+    return keys[usage];
   }
 
 static void dump_buf(CephContext *cct, string title, const unsigned char *buf, int len)
@@ -664,7 +653,7 @@ static void dump_buf(CephContext *cct, string title, const unsigned char *buf, i
   ldout(cct, 0) << ss.str() << dendl;
 }
     
-  int calc_hmac_sha384(const unsigned char *data, 
+  static int calc_hmac_sha384(const unsigned char *data, 
                        int data_len,
                        const unsigned char* hmac_key,
                        int key_size,
@@ -672,7 +661,7 @@ static void dump_buf(CephContext *cct, string title, const unsigned char *buf, i
                        int iv_size,
                        char *out,
                        int out_size,
-                       ostringstream& err) const {
+                       ostringstream& err) {
     unsigned int len = 0;
     char _out[SHA384_LEN];
     char *pout;
@@ -706,7 +695,7 @@ static void dump_buf(CephContext *cct, string title, const unsigned char *buf, i
     return len;
   }
 
-  int calc_kx(const ceph::bufferptr& secret,
+  static int calc_kx(const ceph::bufferptr& secret,
               uint32_t usage,
               uint8_t type,
               int k,
@@ -848,6 +837,17 @@ static void dump_buf(CephContext *cct, string title, const unsigned char *buf, i
 
 public:
   CryptoAES256KRB5KeyHandler() : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_16B()) {
+    memset(keys, 0, sizeof keys);
+  }
+  ~CryptoAES256KRB5KeyHandler() {
+    uint32_t u;
+    for (u = 0; u < MAX_USAGE; ++u) {
+      auto *uk = keys[u];
+      if (uk) {
+        keys[u] = 0;
+        delete uk;
+      }
+    }
   }
 
   using CryptoKeyHandler::encrypt_ext;
@@ -866,6 +866,7 @@ public:
       if (!uk) {
         return -EIO;
       }
+      keys[usage] = uk;
     }
 
     return 0;
@@ -1015,12 +1016,6 @@ public:
     return 0;
   }
 
-  int encrypt(CephContext *cct, const ceph::bufferlist& in,
-             ceph::bufferlist& out,
-              std::string* unused) const override {
-    return encrypt_ext(cct, default_usage, 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 a8839c34c69a2967a75e91ffecba69e643a5f032..879f5e4edc1aca3020f825cb4b007203d4de286c 100644 (file)
@@ -126,19 +126,19 @@ public:
     return 0;
   }
 
-  virtual std::size_t encrypt(CephContext *cct,
+  std::size_t encrypt(CephContext *cct,
                               const in_slice_t& in,
                              const out_slice_t& out) const {
     return encrypt_ext(cct, default_usage, in, nullptr, out);
   }
-  virtual std::size_t encrypt_ext(CephContext *cct,
+  std::size_t encrypt_ext(CephContext *cct,
                               uint32_t usage,
                               const in_slice_t& in,
                              const out_slice_t& out) const {
     return encrypt_ext(cct, usage,
                        in, nullptr, out);
   }
-  virtual std::size_t encrypt_ext(CephContext *cct,
+  std::size_t encrypt_ext(CephContext *cct,
                               const in_slice_t& in,
                               const in_slice_t *confounder,
                              const out_slice_t& out) const {
@@ -151,7 +151,7 @@ public:
                               const in_slice_t *confounder,
                              const out_slice_t& out) const;
 
-  virtual std::size_t decrypt(CephContext *cct,
+  std::size_t decrypt(CephContext *cct,
                               const in_slice_t& in,
                              const out_slice_t& out) const {
     return decrypt_ext(cct, default_usage, in, out);
@@ -255,6 +255,20 @@ public:
     ceph_assert(!empty()); // Bad key?
     return ckh->decrypt(cct, in, out, error);
   }
+  int encrypt_ext(CephContext *cct, uint32_t usage,
+              const ceph::buffer::list& in,
+             ceph::buffer::list& out,
+             std::string *error) const {
+    ceph_assert(!empty()); // Bad key?
+    return ckh->encrypt_ext(cct, usage, in, out, error);
+  }
+  int decrypt_ext(CephContext *cct, uint32_t usage,
+              const ceph::buffer::list& in,
+             ceph::buffer::list& out,
+             std::string *error) const {
+    ceph_assert(!empty()); // Bad key?
+    return ckh->decrypt_ext(cct, usage, in, out, error);
+  }
 
   using in_slice_t = CryptoKeyHandler::in_slice_t;
   using out_slice_t = CryptoKeyHandler::out_slice_t;