diff --git a/docs/security/README.md b/docs/security/README.md new file mode 100644 index 000000000..e2a50ae32 --- /dev/null +++ b/docs/security/README.md @@ -0,0 +1,248 @@ +# Minio Security Overview [![Slack](https://slack.minio.io/slack?type=svg)](https://slack.minio.io) + +## Server-Side Encryption + +Minio supports two different types of server-side encryption ([SSE](#sse)): + - **SSE-C**: The Minio server en/decrypts an object with a secret key provided by the S3 client + as part of the HTTP request headers. Therefore, [SSE-C](#ssec) requires TLS/HTTPS. + - **SSE-S3**: The Minio server en/decrypts an object with a secret key managed by a KMS. + Therefore, Minio requires a valid KMS configuration for [SSE-S3](#sses3). + +### Server-Side Encryption - Preliminaries + +#### Secret Keys + +The Minio server uses an unique, randomly generated secret key per object also known as, +Object Encryption Key ([OEK](#oek)). Neither the client-provided SSE-C key nor the KMS-managed +key is directly used to en/decrypt an object. Instead, the OEK is stored as part of the object +metadata next to the object in an encrypted form. To en/decrypt the OEK another secret key is +needed also known as, Key Encryption Key ([KEK](#kek)). + +The Minio server runs a key-derivation algorithm to generate the KEK using a pseudo-random +function ([PRF](#prf)): +`KEK := PRF(EK, IV, context_values)` where + - [EK](#ek): is the external key. In case of SSE-C this is the client-provided key. In case of SSE-S3 + this is secret key generated by the KMS. For further details see + [SSE-C](#Server-Side-Encryption-with-client-provided-Keys) or + [SSE-S3](#Server-Side-Encryption-with-a-KMS). + - [IV](#iv): is a randomly generated initialization vector. It is public and part of the + object metadata. + - `context_values`: are values like the bucket and object name and other information which should be + cryptographically bound to the KEK. + +To summarize for any encrypted object there exists (at least) three different keys: + 1. [OEK](#oek): A secret and unique key used to encrypted the object, stored in an encrypted form as + part of the object metadata and only loaded to RAM in plaintext during en/decrypting the object. + 2. [KEK](#kek): A secret and unique key used to en/decrypt the OEK and never stored anywhere. + It is(re-)generated whenever en/decrypting an object using an external secret key and public + parameters. + 3. [EK](#ek): An external secret key - either the SSE-C client-provided key or a secret key + generated by the KMS. + +#### Content Encryption + +The Minio server uses an authenticated encryption scheme ([AEAD](#aead)) to en/decrypt and +authenticate the object content. The AEAD is combined with some state to build a +*Secure Channel*. A *Secure Channel* is a cryptographic construction that ensures confidentiality +and integrity of the processed data. In particular the *Secure Channel* splits the plaintext content +into fixed size chunks and en/decrypts each chunk separately using an unique key-nonce combination. + +``` +plaintext := chunk_0 || chunk_1 || chunk_2 || ... + | | | + | | | + AEAD <- key, nonce + 0 AEAD <- key, nonce + 1 AEAD <- key, nonce + 2 ... + | | | + | | | +ciphertext := sealed_chunk_0 || sealed_chunk_1 || sealed_chunk_2 || ... +``` +
Figure 1 - Secure Channel construction
+ +In case of a S3 multi-part operation each part is en/decrypted with the scheme shown in +Figure 1. However, for each part an unique secret key is derived from the OEK and the part +number using a PRF. So in case of multi-part not the OEK but the output of `PRF(OEK, part_id)` +is used as secret key. + +#### Cryptographic Primitives + +The SSE schemes described in [Secret Keys](#Secret-Keys) and [Content Encryption](#Content-Encryption) +are generic over the cryptographic primitives. However, the Minio server uses the following +cryptographic primitive implementations: + - [PRF](#prf): HMAC-SHA-256 + - [AEAD](#aead): AES-256-GCM if the CPU supports AES-NI, ChaCha20-Poly1305 otherwise. + More specifically AES-256-GCM is only selected for X86-64 CPUs with AES-NI extension. + +Further any secret key (apart from the KMS-generated ones) is 256 bits long. The KMS-generated keys +may be 256 bits but this depends on the KMS capabilities and configuration. + +The *Secure Channel* splits the object content into chunks of a fixed size of `65536` bytes. The last +chunk may be smaller to avoid adding additional overhead and is treated specially to prevent truncation +attacks. The nonce value is 96 bits long and generated randomly per object / multi-part part. The +*Secure Channel* supports plaintexts up to `65536 * 2^32 = 256 TiB`. + +#### Randomness + +The Minio server generates unique keys and other cryptographic values using a cryptographically +secure pseudo-random number generator ([CSPRNG](#csprng)). However, in the context of SSE, +the Minio server does not require that the CSPRNG generates values that are indistinguishable +from truly random bit strings. Instead, it is sufficient if the generated values are unique - which +is a weaker requirement. Nevertheless other parts - for example the TLS-stack - may require that +CSPRNG-generated values are indistinguishable from truly random bit strings. + +### Server-Side Encryption with client-provided Keys + +SSE-C allows an S3 client to en/decrypt an object at the Minio server. Therefore the S3 client +sends a secret key as part of the HTTP request. This secret key is **never** stored by the +Minio server and only resides in RAM during the en/decryption process. + +Minio does not assume or require that the client-provided key is unique. It may be used for +multiple objects or buckets. Especially a single client-provided key may be used for all +objects - even though all objects must be treated as compromised if that key is ever compromised. + +#### Key rotation + +S3 clients can change the client-provided key of an existing object. Therefore an S3 client +must perform a S3 COPY operation where the copy source and destination are equal. Further the +COPY request headers must contain the current and the new client key: + - `X-Amz-Server-Side-Encryption-Customer-Key`: Base64 encoded new key. + - `X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key`: Base64 encoded current key. + +Such a special COPY request is also known as S3 SSE-C key rotation. + +### Server-Side Encryption with a KMS + +SSE-S3 allows an S3 client to en/decrypt an object at the Minio server using a KMS. The Minio +server only assumes that the KMS provides two services: + 1. `GenerateKey`: Takes a key ID and generates a new data key from a master key referenced by + the key ID. It returns the new data key in two different forms: The plain data key + and the data key encrypted using the master key. + 2. `DecryptKey`: Takes a key ID and an encrypted data key and returns the plain data key - the + decryption of the encrypted data key using the master key referenced by the key ID - + on success or an error otherwise. + +More details about supported KMS implementations and configuration can be found at the [KMS guide](https://github.com/minio/minio/blob/master/docs/kms/README.md). + +The Minio server requests a new data key from the KMS for each uploaded object and uses that data key +as EK. Additionally it stores the encrypted form of the data key and the master key ID as part +of the object metadata. The plain data only resides in RAM during the en/decryption process. +The Minio server does not store any SSE-related key at the KMS. Instead the KMS is treated as trusted +component that performs key sealing/unsealing operations to build a key hierarchy: + +``` + CMK (master key) + | + +-----------------------------------+-----------------------------------+ + | | | + +-------+----------------+ +-------+----------------+ ... + | EK_1 | EK_1_encrypted | | EK_2 | EK_2_encrypted | + +---+----------+---------+ +---+----------+---------+ + | | | | + | | | | + +---+---+ | +---+---+ | + | KEK_1 | | | KEK_2 | | + +---+---+ | +---+---+ | + | | | | + | | | | + +---+---+ | +---+---+ | + | OEK_1 | | | OEK_2 | | + +---+---+ | +---+---+ | + | | + | | + | | + +---------+---------+ +---------+---------+ + | object_metadata_1 | | object_metadata_2 | + +-------------------+ +-------------------+ +``` +
Figure 2 - KMS key hierarchy
+ + +#### Key rotation - Basic Operation + +The Minio server supports key rotation for SSE-S3 encrypted objects. Therefore, an S3 client +must perform a S3 COPY operation where the copy source and destination are equal and the SSE-S3 HTTP +header is set. The minio server decrypts the OEK using the current encrypted data key and the +master key ID of the object metadata. If this succeeds, the server requests a new data key +from the KMS using the master key ID of the **current Minio KMS configuration** and re-wraps the +*OEK* with a new *KEK* derived from the new data key / EK: + +``` + object metadata KMS + | | + | +----------------+ 1a | +-------+ + |-------------------->| EK_1_encrypted |-----------|->| CMK_1 | + | +----------------+ | +---+---+ + | | | + | +---------------+ +------+ 1b | | + |------------->| OEK_encrypted | | EK_1 |<---|------+ + | +-------+-------+ +------+ | + | \ / | + | \___ 2 ___/ | + | \___/ | + | | | + | +--+--+ | + | | OEK | | +-------+ + | +--+--+ | | CMK_2 | + | | | +---+---+ + | | | | + | 5 +----------------+ |4 +------+ 3a | | + |<------| OEK_encrypted' |<----+-------| EK_2 |<---|------+ + | +----------------+ +------+ | | + | +----------------+ 3b | | + |<-------------------| EK_2_encrypted |<-----------|------+ + | +----------------+ | + | | + + +1a) Send encrypted data key and master key ID to KMS. +1b) Receive decrypted data key. +2) Decrypt encrypted object key with the KEK derived from the data key. +3a) Receive new plain data key from the KMS using the master key ID of the server config. +3b) Receive encrypted form of the data key from the KMS. +4) Derive a new KEK from the new data key and re-encrypt the OEK with it. +5) Store the encrypted OEK encrypted data key and master key ID in object metadata. + ``` +
Figure 3 - KMS data key rotation
+ +#### Key rotation - Extensions + +The basic SSE-S3 key rotation operation can be used to build more powerful key management +operations. The following options are possible to perform manually but do not have fully +functional API's at this time. + +1. **Master key migration**: The [SSE-S3 key rotation](#Key-rotation---Basic-Operation) can be performed + on multiple/all objects to move them from one to another master key. +2. **Secure object erasure**: The [SSE-S3 key rotation](#Key-rotation---Basic-Operation) can be applied + to one/multiple objects with a randomly generated master key which is + not stored at the KMS. That leads to an encrypted data key which can + never be decrypted anymore. +3. **Periodical key migration**: The [SSE-S3 key rotation](#Key-rotation---Basic-Operation) can be + invoked after a certain time period to migrate one or more objects + from one master key to another. + +#### Secure Erasure and Locking + +The Minio server requires an available KMS to en/decrypt SSE-S3 encrypted objects. Therefore it +is possible to erase or lock some or all encrypted objects. For example in case of a detected attack +or other emergency situations the following actions can be taken: + - Seal the KMS such that it cannot be accessed by Minio server anymore. That will lock **all** + SSE-S3 encrypted objects protected by master keys stored on the KMS. All these objects + can not be decrypted as long as the KMS is sealed. + - Seal/Unmount one/some master keys. That will lock all SSE-S3 encrypted objects protected by + these master keys. All these objects can not be decrypted as long as the key(s) are sealed. + - Delete one/some master keys. From a security standpoint, this is equal to erasing all SSE-S3 + encrypted objects protected by these master keys. All these objects are lost forever as they cannot + be decrypted. Especially deleting all master keys at the KMS is equivalent to secure erasing all + SSE-S3 encrypted objects. + +## Acronyms + + - **AEAD**: Authenticated Encryption with Associated Data + - **CSPRNG**: Cryptographically Secure Pseudo Random Number Generator + - **EK**: External Key + - **IV**: Initialization Vector + - **KEK**: Key Encryption Key + - **OEK**: Object Encryption Key + - **PRF**: Pseudo Random Function + - **SSE**: Server-Side Encryption + - **SSE-C**: Server-Side Encryption with client-provided Keys + - **SSE-S3**: Server-Side Encryption with a KMS