From: Matthew N. Heler Date: Mon, 30 Mar 2026 23:44:36 +0000 (-0500) Subject: rgw: write RGW_ATTR_CRYPT_PREFETCH_ALIGN for AEAD ciphers X-Git-Tag: v21.0.1~125^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fcdc01a1a03148b5450eab18c7a71e07d809ff15;p=ceph.git rgw: write RGW_ATTR_CRYPT_PREFETCH_ALIGN for AEAD ciphers Store the plaintext and encrypted block sizes at upload time so future cls prefetch ops can compute on-disk read ranges from xattrs without instantiating a cipher. Only written for size-expanding ciphers (GCM). CBC objects have no attr — plaintext and ciphertext sizes are identical. Signed-off-by: Matthew N. Heler --- diff --git a/src/rgw/driver/rados/rgw_rados.cc b/src/rgw/driver/rados/rgw_rados.cc index b0abf4fd25a..a042c71355a 100644 --- a/src/rgw/driver/rados/rgw_rados.cc +++ b/src/rgw/driver/rados/rgw_rados.cc @@ -5299,6 +5299,7 @@ int RGWRados::copy_obj(RGWObjectCtx& src_obj_ctx, // Data is rewritten as a single stream; drop stale multipart boundaries attrs.erase(RGW_ATTR_CRYPT_PARTS); attrs.erase(RGW_ATTR_CRYPT_PART_NUMS); + attrs.erase(RGW_ATTR_CRYPT_PREFETCH_ALIGN); return copy_obj_data(dest_obj_ctx, owner, dest_bucket_info, dest_placement, read_op, obj_size - 1, dest_obj, mtime, real_time(), attrs, olh_epoch, delete_at, petag, dp_factory, dpp, y); } diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index cc86bce2c45..f69c934cd3b 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -194,6 +194,7 @@ using ceph::crypto::MD5; #define RGW_ATTR_CRYPT_PART_NUMS RGW_ATTR_CRYPT_PREFIX "part-numbers" #define RGW_ATTR_CRYPT_SALT RGW_ATTR_CRYPT_PREFIX "salt" #define RGW_ATTR_CRYPT_ORIGINAL_SIZE RGW_ATTR_CRYPT_PREFIX "original-size" +#define RGW_ATTR_CRYPT_PREFETCH_ALIGN RGW_ATTR_CRYPT_PREFIX "prefetch-align" /* SSE-S3 Encryption Attributes */ #define RGW_ATTR_BUCKET_ENCRYPTION_PREFIX RGW_ATTR_PREFIX "sse-s3." diff --git a/src/rgw/rgw_crypt.cc b/src/rgw/rgw_crypt.cc index ad796021a97..4fb2eef0d69 100644 --- a/src/rgw/rgw_crypt.cc +++ b/src/rgw/rgw_crypt.cc @@ -2016,6 +2016,25 @@ bool rgw_get_aead_decrypted_size(const DoutPrefixProvider* dpp, } +/* + * Write RGW_ATTR_CRYPT_PREFETCH_ALIGN for size-expanding ciphers + * so cls/prefetch can compute on-disk read ranges from xattrs. + */ +static void maybe_write_prefetch_align( + BlockCrypt* block_crypt, + std::map& attrs) +{ + if (!block_crypt) return; + size_t plain_bs = block_crypt->get_block_size(); + size_t enc_bs = block_crypt->get_encrypted_block_size(); + if (enc_bs > plain_bs) { + bufferlist bl; + encode(static_cast(plain_bs), bl); + encode(static_cast(enc_bs), bl); + attrs[RGW_ATTR_CRYPT_PREFETCH_ALIGN] = std::move(bl); + } +} + int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, std::map& attrs, std::unique_ptr* block_crypt, @@ -2106,6 +2125,13 @@ int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, if (use_gcm) { set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-C-AES256-GCM"); + if (!block_crypt) { + // multipart-init: write prefetch align from AEAD constants + bufferlist align_bl; + encode(static_cast(AEAD_CHUNK_SIZE), align_bl); + encode(static_cast(AEAD_ENCRYPTED_CHUNK_SIZE), align_bl); + attrs[RGW_ATTR_CRYPT_PREFETCH_ALIGN] = std::move(align_bl); + } std::string salt = generate_gcm_salt(s, attrs); set_gcm_plaintext_size(s, attrs, is_copy); @@ -2141,6 +2167,8 @@ int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, } } + if (block_crypt && *block_crypt) + maybe_write_prefetch_align(block_crypt->get(), attrs); crypt_http_responses["x-amz-server-side-encryption-customer-algorithm"] = "AES256"; crypt_http_responses["x-amz-server-side-encryption-customer-key-MD5"] = std::string(keymd5); return 0; @@ -2218,6 +2246,12 @@ int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, if (use_gcm) { set_attr(attrs, RGW_ATTR_CRYPT_MODE, "SSE-KMS-GCM"); + if (!block_crypt) { + bufferlist align_bl; + encode(static_cast(AEAD_CHUNK_SIZE), align_bl); + encode(static_cast(AEAD_ENCRYPTED_CHUNK_SIZE), align_bl); + attrs[RGW_ATTR_CRYPT_PREFETCH_ALIGN] = std::move(align_bl); + } std::string salt = generate_gcm_salt(s, attrs); set_gcm_plaintext_size(s, attrs, is_copy); @@ -2258,6 +2292,8 @@ int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, ::ceph::crypto::zeroize_for_security(actual_key.data(), actual_key.length()); crypt_http_responses["x-amz-server-side-encryption"] = "aws:kms"; + if (block_crypt && *block_crypt) + maybe_write_prefetch_align(block_crypt->get(), attrs); crypt_http_responses["x-amz-server-side-encryption-aws-kms-key-id"] = std::string(key_id); crypt_http_responses["x-amz-server-side-encryption-context"] = std::move(cooked_context); return 0; @@ -2308,6 +2344,12 @@ int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, if (use_gcm) { set_attr(attrs, RGW_ATTR_CRYPT_MODE, "AES256-GCM"); + if (!block_crypt) { + bufferlist align_bl; + encode(static_cast(AEAD_CHUNK_SIZE), align_bl); + encode(static_cast(AEAD_ENCRYPTED_CHUNK_SIZE), align_bl); + attrs[RGW_ATTR_CRYPT_PREFETCH_ALIGN] = std::move(align_bl); + } std::string salt = generate_gcm_salt(s, attrs); set_gcm_plaintext_size(s, attrs, is_copy); @@ -2347,6 +2389,8 @@ int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, } ::ceph::crypto::zeroize_for_security(actual_key.data(), actual_key.length()); + if (block_crypt && *block_crypt) + maybe_write_prefetch_align(block_crypt->get(), attrs); crypt_http_responses["x-amz-server-side-encryption"] = "AES256"; return 0; @@ -2373,6 +2417,12 @@ int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, if (use_gcm) { set_attr(attrs, RGW_ATTR_CRYPT_MODE, "RGW-AUTO-GCM"); + if (!block_crypt) { + bufferlist align_bl; + encode(static_cast(AEAD_CHUNK_SIZE), align_bl); + encode(static_cast(AEAD_ENCRYPTED_CHUNK_SIZE), align_bl); + attrs[RGW_ATTR_CRYPT_PREFETCH_ALIGN] = std::move(align_bl); + } std::string salt = generate_gcm_salt(s, attrs); set_gcm_plaintext_size(s, attrs, is_copy); @@ -2420,6 +2470,8 @@ int rgw_s3_prepare_encrypt(req_state* s, optional_yield y, } ::ceph::crypto::zeroize_for_security(actual_key, sizeof(actual_key)); } + if (block_crypt && *block_crypt) + maybe_write_prefetch_align(block_crypt->get(), attrs); return 0; } }