mirror of
				https://github.com/minio/minio.git
				synced 2025-10-31 08:11:19 +01:00 
			
		
		
		
	This commit adds 3 helper functions for SSE-C and SSE-S3 to simplify object key unsealing in server code. See #6600
		
			
				
	
	
		
			227 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Minio Cloud Storage, (C) 2015, 2016, 2017, 2018 Minio, Inc.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //    http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package crypto
 | |
| 
 | |
| import (
 | |
| 	"net/http"
 | |
| 	"testing"
 | |
| )
 | |
| 
 | |
| func TestS3String(t *testing.T) {
 | |
| 	const Domain = "SSE-S3"
 | |
| 	if domain := S3.String(); domain != Domain {
 | |
| 		t.Errorf("S3's string method returns wrong domain: got '%s' - want '%s'", domain, Domain)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestSSECString(t *testing.T) {
 | |
| 	const Domain = "SSE-C"
 | |
| 	if domain := SSEC.String(); domain != Domain {
 | |
| 		t.Errorf("SSEC's string method returns wrong domain: got '%s' - want '%s'", domain, Domain)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var ssecUnsealObjectKeyTests = []struct {
 | |
| 	Headers        http.Header
 | |
| 	Bucket, Object string
 | |
| 	Metadata       map[string]string
 | |
| 
 | |
| 	ExpectedErr error
 | |
| }{
 | |
| 	{ // 0 - Valid HTTP headers and valid metadata entries for bucket/object
 | |
| 		Headers: http.Header{
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
 | |
| 		},
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Sealed-Key":     "IAAfAMBdYor5tf/UlVaQvwYlw5yKbPBeQqfygqsfHqhu1wHD9KDAP4bw38AhL12prFTS23JbbR9Re5Qv26ZnlQ==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm": "DAREv2-HMAC-SHA256",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":             "coVfGS3I/CTrqexX5vUN+PQPoP9aUFiPYYrSzqTWfBA=",
 | |
| 		},
 | |
| 		ExpectedErr: nil,
 | |
| 	},
 | |
| 	{ // 1 - Valid HTTP headers but invalid metadata entries for bucket/object2
 | |
| 		Headers: http.Header{
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
 | |
| 		},
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object2",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Sealed-Key":     "IAAfAMBdYor5tf/UlVaQvwYlw5yKbPBeQqfygqsfHqhu1wHD9KDAP4bw38AhL12prFTS23JbbR9Re5Qv26ZnlQ==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm": "DAREv2-HMAC-SHA256",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":             "coVfGS3I/CTrqexX5vUN+PQPoP9aUFiPYYrSzqTWfBA=",
 | |
| 		},
 | |
| 		ExpectedErr: ErrSecretKeyMismatch,
 | |
| 	},
 | |
| 	{ // 2 - Valid HTTP headers but invalid metadata entries for bucket/object
 | |
| 		Headers: http.Header{
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
 | |
| 		},
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Sealed-Key": "IAAfAMBdYor5tf/UlVaQvwYlw5yKbPBeQqfygqsfHqhu1wHD9KDAP4bw38AhL12prFTS23JbbR9Re5Qv26ZnlQ==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":         "coVfGS3I/CTrqexX5vUN+PQPoP9aUFiPYYrSzqTWfBA=",
 | |
| 		},
 | |
| 		ExpectedErr: errMissingInternalSealAlgorithm,
 | |
| 	},
 | |
| 	{ // 3 - Invalid HTTP headers for valid metadata entries for bucket/object
 | |
| 		Headers: http.Header{
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
 | |
| 			"X-Amz-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
 | |
| 		},
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Sealed-Key":     "IAAfAMBdYor5tf/UlVaQvwYlw5yKbPBeQqfygqsfHqhu1wHD9KDAP4bw38AhL12prFTS23JbbR9Re5Qv26ZnlQ==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm": "DAREv2-HMAC-SHA256",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":             "coVfGS3I/CTrqexX5vUN+PQPoP9aUFiPYYrSzqTWfBA=",
 | |
| 		},
 | |
| 		ExpectedErr: ErrMissingCustomerKeyMD5,
 | |
| 	},
 | |
| }
 | |
| 
 | |
| func TestSSECUnsealObjectKey(t *testing.T) {
 | |
| 	for i, test := range ssecUnsealObjectKeyTests {
 | |
| 		if _, err := SSEC.UnsealObjectKey(test.Headers, test.Metadata, test.Bucket, test.Object); err != test.ExpectedErr {
 | |
| 			t.Errorf("Test %d: got: %v - want: %v", i, err, test.ExpectedErr)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var sseCopyUnsealObjectKeyTests = []struct {
 | |
| 	Headers        http.Header
 | |
| 	Bucket, Object string
 | |
| 	Metadata       map[string]string
 | |
| 
 | |
| 	ExpectedErr error
 | |
| }{
 | |
| 	{ // 0 - Valid HTTP headers and valid metadata entries for bucket/object
 | |
| 		Headers: http.Header{
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
 | |
| 		},
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Sealed-Key":     "IAAfAMBdYor5tf/UlVaQvwYlw5yKbPBeQqfygqsfHqhu1wHD9KDAP4bw38AhL12prFTS23JbbR9Re5Qv26ZnlQ==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm": "DAREv2-HMAC-SHA256",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":             "coVfGS3I/CTrqexX5vUN+PQPoP9aUFiPYYrSzqTWfBA=",
 | |
| 		},
 | |
| 		ExpectedErr: nil,
 | |
| 	},
 | |
| 	{ // 1 - Valid HTTP headers but invalid metadata entries for bucket/object2
 | |
| 		Headers: http.Header{
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
 | |
| 		},
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object2",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Sealed-Key":     "IAAfAMBdYor5tf/UlVaQvwYlw5yKbPBeQqfygqsfHqhu1wHD9KDAP4bw38AhL12prFTS23JbbR9Re5Qv26ZnlQ==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm": "DAREv2-HMAC-SHA256",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":             "coVfGS3I/CTrqexX5vUN+PQPoP9aUFiPYYrSzqTWfBA=",
 | |
| 		},
 | |
| 		ExpectedErr: ErrSecretKeyMismatch,
 | |
| 	},
 | |
| 	{ // 2 - Valid HTTP headers but invalid metadata entries for bucket/object
 | |
| 		Headers: http.Header{
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5":   []string{"7PpPLAK26ONlVUGOWlusfg=="},
 | |
| 		},
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Sealed-Key": "IAAfAMBdYor5tf/UlVaQvwYlw5yKbPBeQqfygqsfHqhu1wHD9KDAP4bw38AhL12prFTS23JbbR9Re5Qv26ZnlQ==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":         "coVfGS3I/CTrqexX5vUN+PQPoP9aUFiPYYrSzqTWfBA=",
 | |
| 		},
 | |
| 		ExpectedErr: errMissingInternalSealAlgorithm,
 | |
| 	},
 | |
| 	{ // 3 - Invalid HTTP headers for valid metadata entries for bucket/object
 | |
| 		Headers: http.Header{
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": []string{"AES256"},
 | |
| 			"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key":       []string{"MzJieXRlc2xvbmdzZWNyZXRrZXltdXN0cHJvdmlkZWQ="},
 | |
| 		},
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Sealed-Key":     "IAAfAMBdYor5tf/UlVaQvwYlw5yKbPBeQqfygqsfHqhu1wHD9KDAP4bw38AhL12prFTS23JbbR9Re5Qv26ZnlQ==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm": "DAREv2-HMAC-SHA256",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":             "coVfGS3I/CTrqexX5vUN+PQPoP9aUFiPYYrSzqTWfBA=",
 | |
| 		},
 | |
| 		ExpectedErr: ErrMissingCustomerKeyMD5,
 | |
| 	},
 | |
| }
 | |
| 
 | |
| func TestSSECopyUnsealObjectKey(t *testing.T) {
 | |
| 	for i, test := range sseCopyUnsealObjectKeyTests {
 | |
| 		if _, err := SSECopy.UnsealObjectKey(test.Headers, test.Metadata, test.Bucket, test.Object); err != test.ExpectedErr {
 | |
| 			t.Errorf("Test %d: got: %v - want: %v", i, err, test.ExpectedErr)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var s3UnsealObjectKeyTests = []struct {
 | |
| 	KMS            KMS
 | |
| 	Bucket, Object string
 | |
| 	Metadata       map[string]string
 | |
| 
 | |
| 	ExpectedErr error
 | |
| }{
 | |
| 	{ // 0 - Valid KMS key-ID and valid metadata entries for bucket/object
 | |
| 		KMS:    NewKMS([32]byte{}),
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":                "hhVY0LKR1YtZbzAKxTWUfZt5enDfYX6Fxz1ma8Kiudc=",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-S3-Sealed-Key":     "IAAfALhsOeD5AE3s5Zgq3DZ5VFGsOa3B0ksVC86veDcaj+fXv2U0VadhPaOKYr9Emd5ssOsO0uIhIIrKiOy9rA==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-S3-Kms-Sealed-Key": "IAAfAMRS2iw45FsfiF3QXajSYVWj1lxMpQm6DxDGPtADCX6fJQQ4atHBtfpgqJFyeQmIHsm0FBI+UlHw1Lv4ug==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-S3-Kms-Key-Id":     "test-key-1",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm":    "DAREv2-HMAC-SHA256",
 | |
| 		},
 | |
| 		ExpectedErr: nil,
 | |
| 	},
 | |
| 	{ // 1 - Valid KMS key-ID for invalid metadata entries for bucket/object
 | |
| 		KMS:    NewKMS([32]byte{}),
 | |
| 		Bucket: "bucket",
 | |
| 		Object: "object",
 | |
| 		Metadata: map[string]string{
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-Iv":                "hhVY0LKR1YtZbzAKxTWUfZt5enDfYX6Fxz1ma8Kiudc=",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-S3-Sealed-Key":     "IAAfALhsOeD5AE3s5Zgq3DZ5VFGsOa3B0ksVC86veDcaj+fXv2U0VadhPaOKYr9Emd5ssOsO0uIhIIrKiOy9rA==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-S3-Kms-Sealed-Key": "IAAfAMRS2iw45FsfiF3QXajSYVWj1lxMpQm6DxDGPtADCX6fJQQ4atHBtfpgqJFyeQmIHsm0FBI+UlHw1Lv4ug==",
 | |
| 			"X-Minio-Internal-Server-Side-Encryption-S3-Kms-Key-Id":     "test-key-1",
 | |
| 		},
 | |
| 		ExpectedErr: errMissingInternalSealAlgorithm,
 | |
| 	},
 | |
| }
 | |
| 
 | |
| func TestS3UnsealObjectKey(t *testing.T) {
 | |
| 	for i, test := range s3UnsealObjectKeyTests {
 | |
| 		if _, err := S3.UnsealObjectKey(test.KMS, test.Metadata, test.Bucket, test.Object); err != test.ExpectedErr {
 | |
| 			t.Errorf("Test %d: got: %v - want: %v", i, err, test.ExpectedErr)
 | |
| 		}
 | |
| 	}
 | |
| }
 |