aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api/s3_sse_utils.go
diff options
context:
space:
mode:
Diffstat (limited to 'weed/s3api/s3_sse_utils.go')
-rw-r--r--weed/s3api/s3_sse_utils.go42
1 files changed, 42 insertions, 0 deletions
diff --git a/weed/s3api/s3_sse_utils.go b/weed/s3api/s3_sse_utils.go
new file mode 100644
index 000000000..848bc61ea
--- /dev/null
+++ b/weed/s3api/s3_sse_utils.go
@@ -0,0 +1,42 @@
+package s3api
+
+import "github.com/seaweedfs/seaweedfs/weed/glog"
+
+// calculateIVWithOffset calculates a unique IV by combining a base IV with an offset.
+// This ensures each chunk/part uses a unique IV, preventing CTR mode IV reuse vulnerabilities.
+// This function is shared between SSE-KMS and SSE-S3 implementations for consistency.
+func calculateIVWithOffset(baseIV []byte, offset int64) []byte {
+ if len(baseIV) != 16 {
+ glog.Errorf("Invalid base IV length: expected 16, got %d", len(baseIV))
+ return baseIV // Return original IV as fallback
+ }
+
+ // Create a copy of the base IV to avoid modifying the original
+ iv := make([]byte, 16)
+ copy(iv, baseIV)
+
+ // Calculate the block offset (AES block size is 16 bytes)
+ blockOffset := offset / 16
+ originalBlockOffset := blockOffset
+
+ // Add the block offset to the IV counter (last 8 bytes, big-endian)
+ // This matches how AES-CTR mode increments the counter
+ // Process from least significant byte (index 15) to most significant byte (index 8)
+ carry := uint64(0)
+ for i := 15; i >= 8; i-- {
+ sum := uint64(iv[i]) + uint64(blockOffset&0xFF) + carry
+ iv[i] = byte(sum & 0xFF)
+ carry = sum >> 8
+ blockOffset = blockOffset >> 8
+
+ // If no more blockOffset bits and no carry, we can stop early
+ if blockOffset == 0 && carry == 0 {
+ break
+ }
+ }
+
+ // Single consolidated debug log to avoid performance impact in high-throughput scenarios
+ glog.V(4).Infof("calculateIVWithOffset: baseIV=%x, offset=%d, blockOffset=%d, derivedIV=%x",
+ baseIV, offset, originalBlockOffset, iv)
+ return iv
+}