This applies when using ciphers that are not the original
AES-128 one. Use the hmac-sha256 hash now. With AES256KRB5
the original method of encrypting the combined challenges
doesn't work as the confounder randomizes the result.
Signed-off-by: Yehuda Sadeh <ysadehwe@ibm.com>
(cherry picked from commit
31c07fbbf3b8c911a51b41791d6b6265923acda2)
int encrypt(CephContext *cct, const ceph::bufferlist& in,
ceph::bufferlist& out,
std::string* /* unused */) const override {
+ ldout(cct, 20) << "CryptoAESKeyHandler::encrypt()" << dendl;
// we need to take into account the PKCS#7 padding. There *always* will
// be at least one byte of padding. This stays even to input aligned to
// AES_BLOCK_LEN. Otherwise we would face ambiguities during decryption.
int decrypt(CephContext *cct, const ceph::bufferlist& in,
ceph::bufferlist& out,
std::string* /* unused */) const override {
+ ldout(cct, 20) << "CryptoAESKeyHandler::decrypt()" << dendl;
// PKCS#7 padding enlarges even empty plain-text to take 16 bytes.
if (in.length() < AES_BLOCK_LEN || in.length() % AES_BLOCK_LEN) {
return -1;
int encrypt(CephContext *cct, const ceph::bufferlist& in,
ceph::bufferlist& out,
std::string* /* unused */) const override {
+ ldout(cct, 20) << "CryptoAES256KRB5KeyHandler::encrypt()" << dendl;
// encrypted (confounder | data) | hash
ceph::bufferptr out_tmp{static_cast<unsigned>(
AES256KRB5_BLOCK_LEN + in.length() + AES256KRB5_HASH_LEN)};
ceph::bufferlist& out,
std::string* /* unused */) const override {
+ ldout(cct, 20) << "CryptoAES256KRB5KeyHandler::decrypt()" << dendl;
if (in.length() < AES256KRB5_BLOCK_LEN + AES256KRB5_HASH_LEN) { /* minimum size: confounder + hmac */
return -EINVAL;
}
return 0;
}
-
};
return ckh->encrypt(cct, in, out);
}
- sha256_digest_t hmac_sha256(CephContext*, const ceph::buffer::list& in) {
+ sha256_digest_t hmac_sha256(CephContext*, const ceph::buffer::list& in) const {
ceph_assert(ckh);
return ckh->hmac_sha256(in);
}
b.client_challenge = client_challenge;
bufferlist enc;
- if (encode_encrypt(cct, b, secret, enc, error))
- return;
+ switch (secret.get_type()) {
+ case CEPH_CRYPTO_AES:
+ if (encode_encrypt(cct, b, secret, enc, error))
+ return;
+ break;
+ default:
+ /*
+ * AES256KRB5 has a builtin confounder that randomizes the result,
+ * so just encode_encrypt() cannot be used. We should use
+ * a cryptographic has anyway, keeping the old behavior
+ * for AES for backward compatibility.
+ */
+ if (encode_hash(cct, b, secret, enc, error))
+ return;
+ };
uint64_t k = 0;
const ceph_le64 *p = (const ceph_le64 *)enc.c_str();
return 0;
}
+template <typename T>
+int encode_hash(CephContext *cct, const T& t, const CryptoKey& key,
+ ceph::buffer::list& out, std::string &error)
+{
+ using ceph::encode;
+ ceph::buffer::list bl_enc;
+ /* simple encoding, we don't need to add any magic because this will not be decoded */
+ ::encode(t, bl_enc);
+ sha256_digest_t hash = key.hmac_sha256(cct, bl_enc);
+ out.append((const char *)&hash, sizeof(hash));
+ return 0;
+}
+
#endif