From 15771ebe8d349f47f620519015b73497ba2399f1 Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Thu, 12 Jul 2018 18:29:56 +0200 Subject: [PATCH] Fix decrypted object size and key derivation in CopyObjectPart (#6141) This commit fixes the size calculation for multipart objects. The decrypted size of an encrypted multipart object is the sum of the decrypted part sizes. Also fixes the key derivation in CopyObjectPart. Instead of using the same object-encryption-key for each part now an unique per-part key is derived. Updates #6139 --- cmd/encryption-v1.go | 20 ++++++++++++++++---- cmd/object-handlers.go | 9 +++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/cmd/encryption-v1.go b/cmd/encryption-v1.go index ab3422244..fe51341d5 100644 --- a/cmd/encryption-v1.go +++ b/cmd/encryption-v1.go @@ -786,11 +786,23 @@ func (o *ObjectInfo) DecryptedSize() (int64, error) { if !o.IsEncrypted() { return 0, errors.New("Cannot compute decrypted size of an unencrypted object") } - size, err := sio.DecryptedSize(uint64(o.Size)) - if err != nil { - err = errObjectTampered // assign correct error type + if len(o.Parts) == 0 { + size, err := sio.DecryptedSize(uint64(o.Size)) + if err != nil { + err = errObjectTampered // assign correct error type + } + return int64(size), err + } + + var size int64 + for _, part := range o.Parts { + partSize, err := sio.DecryptedSize(uint64(part.Size)) + if err != nil { + return 0, errObjectTampered + } + size += int64(partSize) } - return int64(size), err + return size, nil } // EncryptedSize returns the size of the object after encryption. diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index c8aff2351..464e5863a 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -1077,7 +1077,6 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt return } - // Calculating object encryption key var objectEncryptionKey []byte objectEncryptionKey, err = decryptObjectInfo(key, dstBucket, dstObject, li.UserDefined) if err != nil { @@ -1086,7 +1085,13 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt return } - reader, err = sio.EncryptReader(reader, sio.Config{Key: objectEncryptionKey}) + var partIDbin [4]byte + binary.LittleEndian.PutUint32(partIDbin[:], uint32(partID)) // marshal part ID + + mac := hmac.New(sha256.New, objectEncryptionKey) // derive part encryption key from part ID and object key + mac.Write(partIDbin[:]) + partEncryptionKey := mac.Sum(nil) + reader, err = sio.EncryptReader(reader, sio.Config{Key: partEncryptionKey}) if err != nil { pipeWriter.CloseWithError(err) writeErrorResponse(w, toAPIErrorCode(err), r.URL)