From fae4ed05986562e6b1e516d45883dcc536140d6d Mon Sep 17 00:00:00 2001 From: Marcus Watts Date: Fri, 14 Nov 2025 21:57:53 -0500 Subject: [PATCH] auth: CryptoKey, dynamic usage keys 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 --- src/auth/Crypto.cc | 79 ++++++++++++++++++++++------------------------ src/auth/Crypto.h | 22 ++++++++++--- 2 files changed, 55 insertions(+), 46 deletions(-) diff --git a/src/auth/Crypto.cc b/src/auth/Crypto.cc index 8b25040c920..bd3d754e0ab 100644 --- a/src/auth/Crypto.cc +++ b/src/auth/Crypto.cc @@ -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(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; + mutable usage_keys *keys[MAX_USAGE]; - std::vector 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(); - } - - 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; diff --git a/src/auth/Crypto.h b/src/auth/Crypto.h index a8839c34c69..879f5e4edc1 100644 --- a/src/auth/Crypto.h +++ b/src/auth/Crypto.h @@ -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; -- 2.47.3