]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
copy object encryption fixes - complete_multipart_upload w/ sse-c
authorMarcus Watts <mwatts@redhat.com>
Thu, 18 Sep 2025 04:59:53 +0000 (00:59 -0400)
committerThomas Serlin <tserlin@redhat.com>
Mon, 22 Sep 2025 19:18:18 +0000 (15:18 -0400)
complete_multipart_upload: the spec requires that the client
provide the same values for sse-c as were used to initiate
the upload.  Verify the required paraemeters exist and match.

XXX fixup merge w/ previous

Resolves: rhbz#2394511

Fixes: https://tracker.ceph.com/issues/23264
Signed-off-by: Marcus Watts <mwatts@redhat.com>
(cherry picked from commit a5b3ac39619d3c15f5fbed3cd8c564a1e2beaa59)

src/rgw/rgw_crypt.cc
src/rgw/rgw_op.cc

index ed120006136c169b062166e79048017cd4ec6c4f..5970aad9d52fa1506a5157eaf4863287c971de85 100644 (file)
@@ -1522,11 +1522,47 @@ int rgw_s3_prepare_decrypt(req_state* s,
                        map<string, bufferlist>& attrs,
                        std::map<std::string, std::string>& crypt_http_responses)
 {
-  // RGWDecryptContext cb(s);
+  const char *req_cust_alg = s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM");
+  const char *req_cust_key = s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY");
+  const char *req_cust_key_md5 = s->info.env->get("HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5");
   std::string stored_mode = get_str_attribute(attrs, RGW_ATTR_CRYPT_MODE);
   ldpp_dout(s, 15) << "Encryption mode: " << stored_mode << dendl;
   if (stored_mode == "SSE-C-AES256") {
-    auto keymd5 = to_base64(get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYMD5));
+    auto keymd5_bin = get_str_attribute(attrs, RGW_ATTR_CRYPT_KEYMD5);
+    auto keymd5 = to_base64(keymd5_bin);
+    std::string key_bin;
+    MD5 key_hash;
+
+    if (!req_cust_alg || strcmp(req_cust_alg, "AES256")
+           || !req_cust_key || !req_cust_key_md5
+           || strcmp(req_cust_key_md5, keymd5.c_str()) ) {
+       s->err.message = "sse-c parameters do not match initial values";
+       return -EINVAL;
+    }
+
+    try {
+      key_bin = from_base64(req_cust_key);
+    } catch (...) {
+      ldpp_dout(s, 5) << "ERROR: invalid sse-c encryption "
+                       << "key which contains character that is not base64 encoded."
+                       << dendl;
+      s->err.message = "Requests specifying Server Side Encryption with Customer "
+                       "provided keys must provide an appropriate secret key.";
+      return -EINVAL;
+    }
+
+    // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+    key_hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+    unsigned char key_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
+    key_hash.Update(reinterpret_cast<const unsigned char*>(key_bin.c_str()), key_bin.size());
+    key_hash.Final(key_hash_res);
+
+    if (memcmp(key_hash_res, keymd5_bin.c_str(), CEPH_CRYPTO_MD5_DIGESTSIZE) != 0) {
+      ldpp_dout(s, 5) << "ERROR: Invalid key md5 hash" << dendl;
+      s->err.message = "The calculated MD5 hash of the key did not match the hash that was provided.";
+      return -EINVAL;
+    }
+
     crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256";
     crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = keymd5;
     return 0;
index 06f5e036b7b7012dcfe10cd3d1c8e938d4a838c7..68b4b0c2b5bd9725a9d2fb27272fc6130796d204 100644 (file)
@@ -7585,7 +7585,11 @@ void RGWCompleteMultipart::execute(optional_yield y)
 
   auto& target_attrs = meta_obj->get_attrs();
 
-  (void) rgw_s3_prepare_decrypt(s, target_attrs, crypt_http_responses);
+  op_ret = rgw_s3_prepare_decrypt(s, target_attrs, crypt_http_responses);
+  if (op_ret < 0) {
+      ldpp_dout(this, 16) << "ERROR: incosistent crypto ret=" << op_ret << dendl;
+      return;
+  }
 
   if (cksum) {
     /* validate computed checksum against supplied checksum, if present */