]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: under fips, set flag to allow md5 in select rgw ops
authorMark Kogan <mkogan@redhat.com>
Tue, 12 Oct 2021 14:07:54 +0000 (14:07 +0000)
committerMark Kogan <mkogan@redhat.com>
Thu, 27 Jan 2022 12:47:29 +0000 (14:47 +0200)
Fixes: https://tracker.ceph.com/issues/52900
Signed-off-by: Mark Kogan <mkogan@redhat.com>
(cherry picked from commit a5df0cfcbe9b04832095f1f8ef0ce9f178888efd)

12 files changed:
src/common/ceph_crypto.cc
src/common/ceph_crypto.h
src/rgw/rgw_bucket.cc
src/rgw/rgw_etag_verifier.h
src/rgw/rgw_file.h
src/rgw/rgw_op.cc
src/rgw/rgw_putobj_processor.cc
src/rgw/rgw_rados.cc
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_tools.h
src/rgw/rgw_zone.cc
src/rgw/services/svc_zone.cc

index cbeb1b06df615f621e287a05d236ba174544eb1d..e1f8705c9e6545f3b2277d0b45c068115e8f4b91 100644 (file)
@@ -196,6 +196,11 @@ void ssl::OpenSSLDigest::Restart() {
   EVP_DigestInit_ex(mpContext, mpType, NULL);
 }
 
+void ssl::OpenSSLDigest::SetFlags(int flags) {
+  EVP_MD_CTX_set_flags(mpContext, flags);
+  this->Restart();
+}
+
 void ssl::OpenSSLDigest::Update(const unsigned char *input, size_t length) {
   if (length) {
     EVP_DigestUpdate(mpContext, const_cast<void *>(reinterpret_cast<const void *>(input)), length);
index 6bf344aa8f13f1d03b9ff256048bb3f1219123fa..2feced03a99a5a1391489b4eee118bca563a7065 100644 (file)
@@ -52,6 +52,7 @@ namespace TOPNSPC::crypto {
        OpenSSLDigest (const EVP_MD *_type);
        ~OpenSSLDigest ();
        void Restart();
+       void SetFlags(int flags);
        void Update (const unsigned char *input, size_t length);
        void Final (unsigned char *digest);
     };
index 054de08e172a8e19afcc113cb8057886870218c4..4d9a9bc0877ef76a1cba1ed092f93f62c74e8bd4 100644 (file)
@@ -2719,6 +2719,8 @@ static void get_md5_digest(const RGWBucketEntryPoint *be, string& md5_digest) {
    f->flush(bl);
 
    MD5 hash;
+   // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+   hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
    hash.Update((const unsigned char *)bl.c_str(), bl.length());
    hash.Final(m);
 
index 7e2579b92c97bab95c480e4e8dc61db99f27e56f..8197fb872a1ec9f7c09ea30c5fed2b94db68bd99 100644 (file)
@@ -30,7 +30,10 @@ protected:
 
 public:
   ETagVerifier(CephContext* cct_, rgw::putobj::DataProcessor *next)
-    : Pipe(next), cct(cct_) {}
+    : Pipe(next), cct(cct_) {
+      // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+      hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+    }
 
   virtual void calculate_etag() = 0;
   string get_calculated_etag() { return calculated_etag;}
@@ -62,7 +65,10 @@ public:
                              rgw::putobj::DataProcessor *next)
     : ETagVerifier(cct, next),
       part_ofs(std::move(part_ofs))
-  {}
+  {
+    // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+    hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+  }
 
   int process(bufferlist&& data, uint64_t logical_offset) override;
   void calculate_etag() override;
index ac8ada0251f5fc64772f76a278d9c31bc2fc8764..f3ec1e885c1df13a496026089505a94cfb45fcdd 100644 (file)
@@ -2540,6 +2540,8 @@ public:
       ret = init_from_header(get_state());
     }
     op = this;
+    // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+    hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   }
 
   bool only_bucket() override { return true; }
index 7dc50a6ce1c795b990a19561a437a4dad24abb86..2339dccb7fd0e092f2677cf5d8847fdf5390b548 100644 (file)
@@ -794,7 +794,7 @@ int rgw_build_object_policies(rgw::sal::RGWRadosStore *store, struct req_state *
     }
     s->object_acl = std::make_unique<RGWAccessControlPolicy>(s->cct);
     rgw_obj obj(s->bucket, s->object);
-      
+
     store->getRados()->set_atomic(s->obj_ctx, obj);
     if (prefetch_data) {
       store->getRados()->set_prefetch_data(s->obj_ctx, obj);
@@ -1203,7 +1203,7 @@ void RGWGetBucketTags::pre_exec()
   rgw_bucket_object_pre_exec(s);
 }
 
-void RGWGetBucketTags::execute() 
+void RGWGetBucketTags::execute()
 {
   auto iter = s->bucket_attrs.find(RGW_ATTR_TAGS);
   if (iter != s->bucket_attrs.end()) {
@@ -1735,6 +1735,8 @@ static int iterate_user_manifest_parts(CephContext * const cct,
   list_op.params.delim = delim;
 
   MD5 etag_sum;
+  // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+  etag_sum.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   do {
 #define MAX_LIST_OBJS 100
     int r = list_op.list_objects(MAX_LIST_OBJS, &objs, NULL, &is_truncated, null_yield);
@@ -2017,6 +2019,8 @@ int RGWGetObj::handle_slo_manifest(bufferlist& bl)
   map<uint64_t, rgw_slo_part> slo_parts;
 
   MD5 etag_sum;
+  // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+  etag_sum.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   total_len = 0;
 
   for (const auto& entry : slo_info.entries) {
@@ -2835,7 +2839,7 @@ void RGWDeleteBucketWebsite::execute()
     bufferlist in_data;
     op_ret = forward_request_to_master(s, nullptr, store, in_data, nullptr);
     if (op_ret < 0) {
-      ldpp_dout(this, 0) << "NOTICE: forward_to_master failed on bucket=" << s->bucket.name 
+      ldpp_dout(this, 0) << "NOTICE: forward_to_master failed on bucket=" << s->bucket.name
                         << "returned err=" << op_ret << dendl;
       return;
     }
@@ -3534,7 +3538,7 @@ void RGWDeleteBucket::execute()
   if ( op_ret < 0) {
      ldpp_dout(this, 1) << "WARNING: failed to sync user stats before bucket delete: op_ret= " << op_ret << dendl;
   }
-  
+
   op_ret = store->getRados()->check_bucket_empty(s->bucket_info, s->yield);
   if (op_ret < 0) {
     return;
@@ -3847,6 +3851,8 @@ void RGWPutObj::execute()
   char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
   unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE];
   MD5 hash;
+  // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+  hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   bufferlist bl, aclbl, bs;
   int len;
   
@@ -4274,6 +4280,8 @@ void RGWPostObj::execute()
     char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
     unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE];
     MD5 hash;
+    // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+    hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
     ceph::buffer::list bl, aclbl;
     int len = 0;
 
@@ -5607,6 +5615,8 @@ void RGWPutLC::execute()
   ldpp_dout(this, 15) << "read len=" << data.length() << " data=" << (buf ? buf : "") << dendl;
 
   MD5 data_hash;
+  // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+  data_hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   unsigned char data_hash_res[CEPH_CRYPTO_MD5_DIGESTSIZE];
   data_hash.Update(reinterpret_cast<const unsigned char*>(buf), data.length());
   data_hash.Final(data_hash_res);
@@ -5972,7 +5982,7 @@ void RGWInitMultipart::execute()
 
     op_ret = obj_op.write_meta(bl.length(), 0, attrs, s->yield);
   } while (op_ret == -EEXIST);
-  
+
   const auto ret = rgw::notify::publish(s, s->object, s->obj_size, ceph::real_clock::now(), attrs[RGW_ATTR_ETAG].to_str(), rgw::notify::ObjectCreatedPost, store);
   if (ret < 0) {
     ldpp_dout(this, 5) << "WARNING: publishing notification failed, with error: " << ret << dendl;
@@ -6031,6 +6041,8 @@ void RGWCompleteMultipart::execute()
   map<string, bufferlist> attrs;
   off_t ofs = 0;
   MD5 hash;
+  // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+  hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE];
   char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16];
   bufferlist etag_bl;
@@ -6196,9 +6208,9 @@ void RGWCompleteMultipart::execute()
           ldpp_dout(this, 0) << "ERROR: compression type was changed during multipart upload ("
                            << cs_info.compression_type << ">>" << obj_part.cs_info.compression_type << ")" << dendl;
           op_ret = -ERR_INVALID_PART;
-          return; 
+          return;
       }
-      
+
       if (part_compressed) {
         int64_t new_ofs; // offset in compression data for new part
         if (cs_info.blocks.size() > 0)
@@ -6212,7 +6224,7 @@ void RGWCompleteMultipart::execute()
           cb.len = block.len;
           cs_info.blocks.push_back(cb);
           new_ofs = cb.new_ofs + cb.len;
-        } 
+        }
         if (!compressed)
           cs_info.compression_type = obj_part.cs_info.compression_type;
         cs_info.orig_size += obj_part.cs_info.orig_size;
@@ -6286,7 +6298,7 @@ void RGWCompleteMultipart::execute()
   } else {
     ldpp_dout(this, 0) << "WARNING: failed to remove object " << meta_obj << dendl;
   }
-  
+
   const auto ret = rgw::notify::publish(s, s->object, ofs, ceph::real_clock::now(), final_etag_str, rgw::notify::ObjectCreatedCompleteMultipartUpload, store);
 
   if (ret < 0) {
@@ -6690,7 +6702,7 @@ void RGWDeleteMultiObj::execute()
     bufferlist etag_bl;
     const auto etag = obj_state->get_attr(RGW_ATTR_ETAG, etag_bl) ? etag_bl.to_str() : "";
 
-    const auto ret = rgw::notify::publish(s, obj.key, obj_state->size, obj_state->mtime, etag, 
+    const auto ret = rgw::notify::publish(s, obj.key, obj_state->size, obj_state->mtime, etag,
             del_op.result.delete_marker && s->object.instance.empty() ? rgw::notify::ObjectRemovedDeleteMarkerCreated : rgw::notify::ObjectRemovedDelete,
             store);
     if (ret < 0) {
@@ -7288,6 +7300,8 @@ int RGWBulkUploadOp::handle_file(const boost::string_ref path,
   ssize_t len = 0;
   size_t ofs = 0;
   MD5 hash;
+  // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+  hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   do {
     ceph::bufferlist data;
     len = body.get_at_most(s->cct->_conf->rgw_max_chunk_size, data);
index 02ab414e22ca797e9facacd2546324759dc3027d..b65af0358db512ac9749338f9db59fa7ad54797e 100644 (file)
@@ -639,6 +639,8 @@ int AppendObjectProcessor::complete(size_t accounted_size, const string &etag, c
   //calculate the etag
   if (!cur_etag.empty()) {
     MD5 hash;
+    // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+    hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
     char petag[CEPH_CRYPTO_MD5_DIGESTSIZE];
     char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE];
     char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16];
index 7c4b2280965c8446dc53dc2e05c8cf98d5cbadf4..a677613793fb4ea3484c6743367605e9dfe3d065 100644 (file)
@@ -5228,6 +5228,8 @@ static void generate_fake_tag(RGWRados *store, map<string, bufferlist>& attrset,
   unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
   char md5_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
   MD5 hash;
+  // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+  hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   hash.Update((const unsigned char *)manifest_bl.c_str(), manifest_bl.length());
 
   map<string, bufferlist>::iterator iter = attrset.find(RGW_ATTR_ETAG);
index db3bb717014d699411cdb98969657b992e35235a..358b8d7fc182eea764a674bb619b271452c5a5ed 100644 (file)
@@ -988,6 +988,8 @@ int RGWPutObj_ObjStore_SWIFT::get_params()
     }
 
     MD5 etag_sum;
+    // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+    etag_sum.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
     uint64_t total_size = 0;
     for (auto& entry : slo_info->entries) {
       etag_sum.Update((const unsigned char *)entry.etag.c_str(),
index d49f39efa6eb9558fefad0c7f831482931bf4964..9e4449a50823107afa90a13b77c384a35cb90b70 100644 (file)
@@ -111,7 +111,12 @@ class RGWEtag
   H hash;
 
 public:
-  RGWEtag() {}
+  RGWEtag() {
+    if constexpr (std::is_same_v<H, MD5>) {
+      // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+      hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+    }
+  }
 
   void update(const char *buf, size_t len) {
     hash.Update((const unsigned char *)buf, len);
index 34c00014ad31ee92a8069bc5127660ab8a3a73e0..c3bf462500ffc0780425cb1639211ada38c3102d 100644 (file)
@@ -1800,6 +1800,8 @@ static uint32_t gen_short_zone_id(const std::string zone_id)
 {
   unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
   MD5 hash;
+  // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+  hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
   hash.Update((const unsigned char *)zone_id.c_str(), zone_id.size());
   hash.Final(md5);
 
index df5386930512b693a59dbbe522aeef45bcb6d730..a30d2c9395314c4ee3772ce31be577d9c983c137 100644 (file)
@@ -434,6 +434,8 @@ int RGWSI_Zone::replace_region_with_zonegroup()
     unsigned char md5[CEPH_CRYPTO_MD5_DIGESTSIZE];
     char md5_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
     MD5 hash;
+    // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
+    hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
     hash.Update((const unsigned char *)new_realm_name.c_str(), new_realm_name.length());
     hash.Final(md5);
     buf_to_hex(md5, CEPH_CRYPTO_MD5_DIGESTSIZE, md5_str);