diff options
Diffstat (limited to 'weed/s3api/s3_sse_utils.go')
| -rw-r--r-- | weed/s3api/s3_sse_utils.go | 42 |
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 +} |
