return AWS S3 compatible error for invalid but equal keys during key rotation (#5783)

This change let the server return the S3 error for a key rotation
if the source key is not valid but equal to the destination key.

This change also fixes the SSE-C error messages since AWS returns error messages
ending with a '.'.

Fixes #5625
master
Andreas Auernhammer 7 years ago committed by kannappanr
parent 73f7a98590
commit da9f0e324e
  1. 22
      cmd/api-errors.go
  2. 32
      cmd/encryption-v1.go

@ -138,6 +138,7 @@ const (
ErrMissingSSECustomerKey ErrMissingSSECustomerKey
ErrMissingSSECustomerKeyMD5 ErrMissingSSECustomerKeyMD5
ErrSSECustomerKeyMD5Mismatch ErrSSECustomerKeyMD5Mismatch
ErrInvalidSSECustomerParameters
// Bucket notification related errors. // Bucket notification related errors.
ErrEventNotification ErrEventNotification
@ -629,7 +630,7 @@ var errorCodeResponse = map[APIErrorCode]APIError{
}, },
ErrInsecureSSECustomerRequest: { ErrInsecureSSECustomerRequest: {
Code: "InvalidRequest", Code: "InvalidRequest",
Description: errInsecureSSERequest.Error(), Description: "Requests specifying Server Side Encryption with Customer provided keys must be made over a secure connection.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrSSEMultipartEncrypted: { ErrSSEMultipartEncrypted: {
@ -639,7 +640,7 @@ var errorCodeResponse = map[APIErrorCode]APIError{
}, },
ErrSSEEncryptedObject: { ErrSSEEncryptedObject: {
Code: "InvalidRequest", Code: "InvalidRequest",
Description: errEncryptedObject.Error(), Description: "The object was stored using a form of Server Side Encryption. The correct parameters must be provided to retrieve the object.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrInvalidEncryptionParameters: { ErrInvalidEncryptionParameters: {
@ -649,27 +650,32 @@ var errorCodeResponse = map[APIErrorCode]APIError{
}, },
ErrInvalidSSECustomerAlgorithm: { ErrInvalidSSECustomerAlgorithm: {
Code: "InvalidArgument", Code: "InvalidArgument",
Description: errInvalidSSEAlgorithm.Error(), Description: "Requests specifying Server Side Encryption with Customer provided keys must provide a valid encryption algorithm.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrInvalidSSECustomerKey: { ErrInvalidSSECustomerKey: {
Code: "InvalidArgument", Code: "InvalidArgument",
Description: errInvalidSSEKey.Error(), Description: "The secret key was invalid for the specified algorithm.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrMissingSSECustomerKey: { ErrMissingSSECustomerKey: {
Code: "InvalidArgument", Code: "InvalidArgument",
Description: errMissingSSEKey.Error(), Description: "Requests specifying Server Side Encryption with Customer provided keys must provide an appropriate secret key.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrMissingSSECustomerKeyMD5: { ErrMissingSSECustomerKeyMD5: {
Code: "InvalidArgument", Code: "InvalidArgument",
Description: errMissingSSEKeyMD5.Error(), Description: "Requests specifying Server Side Encryption with Customer provided keys must provide the client calculated MD5 of the secret key.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
ErrSSECustomerKeyMD5Mismatch: { ErrSSECustomerKeyMD5Mismatch: {
Code: "InvalidArgument", Code: "InvalidArgument",
Description: errSSEKeyMD5Mismatch.Error(), Description: "The calculated MD5 hash of the key did not match the hash that was provided.",
HTTPStatusCode: http.StatusBadRequest,
},
ErrInvalidSSECustomerParameters: {
Code: "InvalidArgument",
Description: "The provided encryption parameters did not match the ones used originally.",
HTTPStatusCode: http.StatusBadRequest, HTTPStatusCode: http.StatusBadRequest,
}, },
@ -884,6 +890,8 @@ func toAPIErrorCode(err error) (apiErr APIErrorCode) {
return ErrObjectTampered return ErrObjectTampered
case errEncryptedObject: case errEncryptedObject:
return ErrSSEEncryptedObject return ErrSSEEncryptedObject
case errInvalidSSEParameters:
return ErrInvalidSSECustomerParameters
case errSSEKeyMismatch: case errSSEKeyMismatch:
return ErrAccessDenied // no access without correct key return ErrAccessDenied // no access without correct key
} }

@ -35,14 +35,15 @@ import (
var ( var (
// AWS errors for invalid SSE-C requests. // AWS errors for invalid SSE-C requests.
errInsecureSSERequest = errors.New("Requests specifying Server Side Encryption with Customer provided keys must be made over a secure connection") errInsecureSSERequest = errors.New("SSE-C requests require TLS connections")
errEncryptedObject = errors.New("The object was stored using a form of Server Side Encryption. The correct parameters must be provided to retrieve the object") errEncryptedObject = errors.New("The object was stored using a form of SSE")
errInvalidSSEAlgorithm = errors.New("Requests specifying Server Side Encryption with Customer provided keys must provide a valid encryption algorithm") errInvalidSSEAlgorithm = errors.New("The SSE-C algorithm is not valid")
errMissingSSEKey = errors.New("Requests specifying Server Side Encryption with Customer provided keys must provide an appropriate secret key") errMissingSSEKey = errors.New("The SSE-C request is missing the customer key")
errInvalidSSEKey = errors.New("The secret key was invalid for the specified algorithm") errInvalidSSEKey = errors.New("The SSE-C key is invalid")
errMissingSSEKeyMD5 = errors.New("Requests specifying Server Side Encryption with Customer provided keys must provide the client calculated MD5 of the secret key") errMissingSSEKeyMD5 = errors.New("The SSE-C request is missing the customer key MD5")
errSSEKeyMD5Mismatch = errors.New("The calculated MD5 hash of the key did not match the hash that was provided") errSSEKeyMD5Mismatch = errors.New("The key MD5 does not match the SSE-C key")
errSSEKeyMismatch = errors.New("The client provided key does not match the key provided when the object was encrypted") // this msg is not shown to the client errSSEKeyMismatch = errors.New("The SSE-C key is not correct") // access denied
errInvalidSSEParameters = errors.New("The SSE-C key for key-rotation is not correct") // special access denied
// Additional Minio errors for SSE-C requests. // Additional Minio errors for SSE-C requests.
errObjectTampered = errors.New("The requested object was modified and may be compromised") errObjectTampered = errors.New("The requested object was modified and may be compromised")
@ -247,9 +248,6 @@ func ParseSSECustomerHeader(header http.Header) (key []byte, err error) {
// This function rotates old to new key. // This function rotates old to new key.
func rotateKey(oldKey []byte, newKey []byte, metadata map[string]string) error { func rotateKey(oldKey []byte, newKey []byte, metadata map[string]string) error {
if subtle.ConstantTimeCompare(oldKey, newKey) == 1 {
return nil
}
delete(metadata, SSECustomerKey) // make sure we do not save the key by accident delete(metadata, SSECustomerKey) // make sure we do not save the key by accident
if metadata[ServerSideEncryptionSealAlgorithm] != SSESealAlgorithmDareSha256 { // currently DARE-SHA256 is the only option if metadata[ServerSideEncryptionSealAlgorithm] != SSESealAlgorithmDareSha256 { // currently DARE-SHA256 is the only option
@ -273,10 +271,14 @@ func rotateKey(oldKey []byte, newKey []byte, metadata map[string]string) error {
n, err := sio.Decrypt(objectEncryptionKey, bytes.NewReader(sealedKey), sio.Config{ n, err := sio.Decrypt(objectEncryptionKey, bytes.NewReader(sealedKey), sio.Config{
Key: keyEncryptionKey, Key: keyEncryptionKey,
}) })
if n != 32 || err != nil { if n != 32 || err != nil { // Either the provided key does not match or the object was tampered.
// Either the provided key does not match or the object was tampered. if subtle.ConstantTimeCompare(oldKey, newKey) == 1 {
// To provide strict AWS S3 compatibility we return: access denied. return errInvalidSSEParameters // AWS returns special error for equal but invalid keys.
return errSSEKeyMismatch }
return errSSEKeyMismatch // To provide strict AWS S3 compatibility we return: access denied.
}
if subtle.ConstantTimeCompare(oldKey, newKey) == 1 {
return nil // we don't need to rotate keys if newKey == oldKey
} }
nonce := make([]byte, 32) // generate random values for key derivation nonce := make([]byte, 32) // generate random values for key derivation

Loading…
Cancel
Save