github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/crypto/metadata.go (about)

     1  // Copyright (c) 2015-2021 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package crypto
    19  
    20  import (
    21  	xhttp "github.com/minio/minio/internal/http"
    22  )
    23  
    24  const (
    25  	// MetaMultipart indicates that the object has been uploaded
    26  	// in multiple parts - via the S3 multipart API.
    27  	MetaMultipart = "X-Minio-Internal-Encrypted-Multipart"
    28  
    29  	// MetaIV is the random initialization vector (IV) used for
    30  	// the MinIO-internal key derivation.
    31  	MetaIV = "X-Minio-Internal-Server-Side-Encryption-Iv"
    32  
    33  	// MetaAlgorithm is the algorithm used to derive internal keys
    34  	// and encrypt the objects.
    35  	MetaAlgorithm = "X-Minio-Internal-Server-Side-Encryption-Seal-Algorithm"
    36  
    37  	// MetaSealedKeySSEC is the sealed object encryption key in case of SSE-C.
    38  	MetaSealedKeySSEC = "X-Minio-Internal-Server-Side-Encryption-Sealed-Key"
    39  	// MetaSealedKeyS3 is the sealed object encryption key in case of SSE-S3
    40  	MetaSealedKeyS3 = "X-Minio-Internal-Server-Side-Encryption-S3-Sealed-Key"
    41  	// MetaSealedKeyKMS is the sealed object encryption key in case of SSE-KMS
    42  	MetaSealedKeyKMS = "X-Minio-Internal-Server-Side-Encryption-Kms-Sealed-Key"
    43  
    44  	// MetaKeyID is the KMS master key ID used to generate/encrypt the data
    45  	// encryption key (DEK).
    46  	MetaKeyID = "X-Minio-Internal-Server-Side-Encryption-S3-Kms-Key-Id"
    47  	// MetaDataEncryptionKey is the sealed data encryption key (DEK) received from
    48  	// the KMS.
    49  	MetaDataEncryptionKey = "X-Minio-Internal-Server-Side-Encryption-S3-Kms-Sealed-Key"
    50  
    51  	// MetaContext is the KMS context provided by a client when encrypting an
    52  	// object with SSE-KMS. A client may not send a context in which case the
    53  	// MetaContext will not be present.
    54  	// MetaContext only contains the bucket/object name if the client explicitly
    55  	// added it. However, when decrypting an object the bucket/object name must
    56  	// be part of the object. Therefore, the bucket/object name must be added
    57  	// to the context, if not present, whenever a decryption is performed.
    58  	MetaContext = "X-Minio-Internal-Server-Side-Encryption-Context"
    59  
    60  	// ARNPrefix prefix for "arn:aws:kms"
    61  	ARNPrefix = "arn:aws:kms:"
    62  )
    63  
    64  // IsMultiPart returns true if the object metadata indicates
    65  // that it was uploaded using some form of server-side-encryption
    66  // and the S3 multipart API.
    67  func IsMultiPart(metadata map[string]string) bool {
    68  	if _, ok := metadata[MetaMultipart]; ok {
    69  		return true
    70  	}
    71  	return false
    72  }
    73  
    74  // RemoveSensitiveEntries removes confidential encryption
    75  // information - e.g. the SSE-C key - from the metadata map.
    76  // It has the same semantics as RemoveSensitiveHeaders.
    77  func RemoveSensitiveEntries(metadata map[string]string) { // The functions is tested in TestRemoveSensitiveHeaders for compatibility reasons
    78  	delete(metadata, xhttp.AmzServerSideEncryptionCustomerKey)
    79  	delete(metadata, xhttp.AmzServerSideEncryptionCopyCustomerKey)
    80  	delete(metadata, xhttp.AmzMetaUnencryptedContentLength)
    81  	delete(metadata, xhttp.AmzMetaUnencryptedContentMD5)
    82  }
    83  
    84  // RemoveSSEHeaders removes all crypto-specific SSE
    85  // header entries from the metadata map.
    86  func RemoveSSEHeaders(metadata map[string]string) {
    87  	delete(metadata, xhttp.AmzServerSideEncryption)
    88  	delete(metadata, xhttp.AmzServerSideEncryptionKmsID)
    89  	delete(metadata, xhttp.AmzServerSideEncryptionKmsContext)
    90  	delete(metadata, xhttp.AmzServerSideEncryptionCustomerAlgorithm)
    91  	delete(metadata, xhttp.AmzServerSideEncryptionCustomerKey)
    92  	delete(metadata, xhttp.AmzServerSideEncryptionCustomerKeyMD5)
    93  	delete(metadata, xhttp.AmzServerSideEncryptionCopyCustomerAlgorithm)
    94  	delete(metadata, xhttp.AmzServerSideEncryptionCopyCustomerKey)
    95  	delete(metadata, xhttp.AmzServerSideEncryptionCopyCustomerKeyMD5)
    96  }
    97  
    98  // RemoveInternalEntries removes all crypto-specific internal
    99  // metadata entries from the metadata map.
   100  func RemoveInternalEntries(metadata map[string]string) {
   101  	delete(metadata, MetaMultipart)
   102  	delete(metadata, MetaAlgorithm)
   103  	delete(metadata, MetaIV)
   104  	delete(metadata, MetaSealedKeySSEC)
   105  	delete(metadata, MetaSealedKeyS3)
   106  	delete(metadata, MetaSealedKeyKMS)
   107  	delete(metadata, MetaKeyID)
   108  	delete(metadata, MetaDataEncryptionKey)
   109  }
   110  
   111  // IsSourceEncrypted returns true if the source is encrypted
   112  func IsSourceEncrypted(metadata map[string]string) bool {
   113  	if _, ok := metadata[xhttp.AmzServerSideEncryptionCustomerAlgorithm]; ok {
   114  		return true
   115  	}
   116  	if _, ok := metadata[xhttp.AmzServerSideEncryption]; ok {
   117  		return true
   118  	}
   119  	return false
   120  }
   121  
   122  // IsEncrypted returns true if the object metadata indicates
   123  // that it was uploaded using some form of server-side-encryption.
   124  //
   125  // IsEncrypted only checks whether the metadata contains at least
   126  // one entry indicating SSE-C or SSE-S3.
   127  func IsEncrypted(metadata map[string]string) (Type, bool) {
   128  	if S3KMS.IsEncrypted(metadata) {
   129  		return S3KMS, true
   130  	}
   131  	if S3.IsEncrypted(metadata) {
   132  		return S3, true
   133  	}
   134  	if SSEC.IsEncrypted(metadata) {
   135  		return SSEC, true
   136  	}
   137  	if IsMultiPart(metadata) {
   138  		return nil, true
   139  	}
   140  	if _, ok := metadata[MetaIV]; ok {
   141  		return nil, true
   142  	}
   143  	if _, ok := metadata[MetaAlgorithm]; ok {
   144  		return nil, true
   145  	}
   146  	if _, ok := metadata[MetaKeyID]; ok {
   147  		return nil, true
   148  	}
   149  	if _, ok := metadata[MetaDataEncryptionKey]; ok {
   150  		return nil, true
   151  	}
   152  	if _, ok := metadata[MetaContext]; ok {
   153  		return nil, true
   154  	}
   155  	return nil, false
   156  }
   157  
   158  // CreateMultipartMetadata adds the multipart flag entry to metadata
   159  // and returns modified metadata. It allocates a new metadata map if
   160  // metadata is nil.
   161  func CreateMultipartMetadata(metadata map[string]string) map[string]string {
   162  	if metadata == nil {
   163  		return map[string]string{MetaMultipart: ""}
   164  	}
   165  	metadata[MetaMultipart] = ""
   166  	return metadata
   167  }
   168  
   169  // IsETagSealed returns true if the etag seems to be encrypted.
   170  func IsETagSealed(etag []byte) bool { return len(etag) > 16 }