diff --git a/cmd/erasure-multipart.go b/cmd/erasure-multipart.go index 1f1bebd4c..46b3f12f4 100644 --- a/cmd/erasure-multipart.go +++ b/cmd/erasure-multipart.go @@ -993,15 +993,35 @@ func (er erasureObjects) CompleteMultipartUpload(ctx context.Context, bucket str // // Therefore, we adjust all ETags sent by the client to match what is stored // on the backend. - kind, isEncrypted := crypto.IsEncrypted(fi.Metadata) + kind, _ := crypto.IsEncrypted(fi.Metadata) var objectEncryptionKey []byte - if isEncrypted && kind == crypto.S3 { + switch kind { + case crypto.SSEC: + if checksumType.IsSet() { + if opts.EncryptFn == nil { + return oi, crypto.ErrMissingCustomerKey + } + baseKey := opts.EncryptFn("", nil) + if len(baseKey) != 32 { + return oi, crypto.ErrInvalidCustomerKey + } + objectEncryptionKey, err = decryptObjectMeta(baseKey, bucket, object, fi.Metadata) + if err != nil { + return oi, err + } + } + case crypto.S3, crypto.S3KMS: objectEncryptionKey, err = decryptObjectMeta(nil, bucket, object, fi.Metadata) if err != nil { return oi, err } } + if len(objectEncryptionKey) == 32 { + var key crypto.ObjectKey + copy(key[:], objectEncryptionKey) + opts.EncryptFn = metadataEncrypter(key) + } for i, part := range partInfoFiles { partID := parts[i].PartNumber diff --git a/cmd/object-api-options.go b/cmd/object-api-options.go index f401a1eca..649c123ef 100644 --- a/cmd/object-api-options.go +++ b/cmd/object-api-options.go @@ -374,5 +374,16 @@ func completeMultipartOpts(ctx context.Context, r *http.Request, bucket, object } opts.MTime = mtime opts.UserDefined = make(map[string]string) + + // Transfer SSEC key in opts.EncryptFn + if crypto.SSEC.IsRequested(r.Header) { + key, err := ParseSSECustomerRequest(r) + if err == nil { + // Set EncryptFn to return SSEC key + opts.EncryptFn = func(baseKey string, data []byte) []byte { + return key + } + } + } return opts, nil } diff --git a/cmd/test-utils_test.go b/cmd/test-utils_test.go index 3db2290fa..c903ec89d 100644 --- a/cmd/test-utils_test.go +++ b/cmd/test-utils_test.go @@ -2267,6 +2267,7 @@ func uploadTestObject(t *testing.T, apiRouter http.Handler, creds auth.Credentia } checkRespErr := func(rec *httptest.ResponseRecorder, exp int) { + t.Helper() if rec.Code != exp { b, err := io.ReadAll(rec.Body) t.Fatalf("Expected: %v, Got: %v, Body: %s, err: %v", exp, rec.Code, string(b), err)