Skip to content

chore: spec for S3EC Keyring/KmsKeyring #306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions s3-encryption/materials/keyrings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved."
[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0"

# Keyrings

This specification refers to Keyrings used in S3EC v3 and is largely similar to the keyring interface present in the Material Providers Library (MPL), available [here](https://github.com/awslabs/aws-encryption-sdk-specification/blob/master/framework/keyring-interface.md).

## Version

0.1.0

### Changelog

- 0.1.0
- Initial

## Definitions

### Conventions used in this document

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL"
in this document are to be interpreted as described in [RFC2119](https://tools.ietf.org/html/rfc2119).

## Interface

The Keyring interface and its operations SHOULD adhere to the naming conventions of the implementation language.

The Keyring interface MUST include the OnEncrypt operation.
The OnEncrypt operation MUST accept an instance of EncryptionMaterials as input.
The OnEncrypt operation MUST return an instance of EncryptionMaterials as output.

The Keyring interface MUST include the OnDecrypt operation.
The OnDecrypt operation MUST accept an instance of DecryptionMaterials and a collection of EncryptedDataKey instances as input.
The OnDecrypt operation MUST return an instance of DecryptionMaterials as output.

## Supported Keyrings

The Amazon S3 Encryption Client provides the following keyring implementations:

- [S3 Keyring](s3-keyring.md)
- [S3 KMS Keyring](s3-kms-keyring.md)
- [S3 AES Keyring](s3-aes-keyring.md)
- [S3 RSA Keyring](s3-rsa-keyring.md)

Note: A user MAY create their own custom keyring(s).
49 changes: 49 additions & 0 deletions s3-encryption/materials/s3-keyring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved."
[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0"

# S3 Keyring

## Version

0.1.0

### Changelog

- 0.1.0
- Initial

## Definitions

### Conventions used in this document

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL"
in this document are to be interpreted as described in [RFC2119](https://tools.ietf.org/html/rfc2119).

## Overview

The S3EC SHOULD implement an S3 Keyring to consolidate validation and other functionality common to all S3 Keyrings.
If implemented, the S3 Keyring MUST implement the Keyring interface.
If implemented, the S3 Keyring MUST NOT be able to be instantiated as a Keyring instance.

### Abstract Methods

In addition to the methods defined in the Keyring interface, the S3 Keyring must define or support the following:

- The S3 Keyring MUST define an abstract method GenerateDataKey.
- The S3 Keyring MUST define an abstract method EncryptDataKey.
- The S3 Keyring MUST define an abstract method DecryptDataKey.

### Functionality

#### OnEncrypt

If the Plaintext Data Key in the input EncryptionMaterials is null, the S3 Keyring MUST call the GenerateDataKey method using the materials.
If the materials returned from GenerateDataKey contain an EncryptedDataKey, the S3 Keyring MUST return the materials.
If the materials returned from GenerateDataKey do not contain an EncryptedDataKey, the S3 Keyring MUST call the EncryptDataKey method using the materials.

#### OnDecrypt

If the input DecryptionMaterials contains a Plaintext Data Key, the S3 Keyring MUST throw an exception.
If the input collection of EncryptedDataKey instances contains any number of EDKs other than 1, the S3 Keyring MUST throw an exception.
The S3 Keyring MAY validate that the Key Provider ID of the Encrypted Data Key matches the expected default Key Provider ID value.
The S3 Keyring MUST call the DecryptDataKey method using the materials and add the resulting plaintext data key to the materials.
92 changes: 92 additions & 0 deletions s3-encryption/materials/s3-kms-keyring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved."
[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0"

# KMS Keyring

## Overview

A keyring which interacts with AWS Key Management Service (AWS KMS) to create, encrypt, and decrypt data keys using AWS KMS keys.

## Definitions

### Conventions used in this document

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119).

## Interface

The KmsKeyring MUST implement the [Keyring interface](keyring-interface.md#interface) and include the behavior described in the [S3 Keyring](s3-keyring.md).

## Initialization

On initialization, the caller MAY provide an AWS KMS SDK client instance.
If the caller does not provide an AWS KMS SDK client instance or provides a null value, the KmsKeyring MUST create a default KMS client instance.
On initialization, the caller MUST provide an AWS KMS key identifier.

The KmsKeyring MAY validate that the AWS KMS key identifier is not null or empty.
If the KmsKeyring validates that the AWS KMS key identifier is not null or empty, then it MUST throw an exception.
The KmsKeyring MAY validate that the AWS KMS key identifier is [a valid AWS KMS Key identifier](../../framework/aws-kms/aws-kms-key-arn.md#a-valid-aws-kms-identifier).
If the KmsKeyring validates that the AWS KMS key identifier is not a valid AWS KMS Key identifier, then it MUST throw an exception.

## Supported Wrapping Algorithm Modes

The KmsKeyring has two supported algorithm modes: KmsV1 and Kms+Context (V2).
The KmsKeyring MUST NOT support encryption using KmsV1 mode.
The KmsKeyring MUST support decryption using KmsV1 mode.
The KmsV1 mode MUST be only enabled when legacy wrapping algorithms are enabled.
The KmsKeyring MUST support encryption using Kms+Context mode.
The KmsKeyring MUST support decryption using Kms+Context mode.
The Kms+Context mode MUST be enabled as a fully-supported (non-legacy) wrapping algorithm.

### EncryptDataKey

The KmsKeyring MUST implement the EncryptDataKey method.
The keyring MUST call [AWS KMS Encrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Encrypt.html) using the configured AWS KMS client.
The keyring must AWS KMS Encrypt call with a request constructed as follows:

- `KeyId` MUST be the configured AWS KMS key identifier.
- `PlaintextDataKey` MUST be the plaintext data key in the [encryption materials](../structures.md#encryption-materials).
- `EncryptionContext` MUST be the [encryption context](../structures.md#encryption-context) included in the input [encryption materials](../structures.md#encryption-materials).
- A custom API Name or User Agent string SHOULD be provided in order to provide metrics on KMS calls associated with the S3 Encryption Client.

If the call to [AWS KMS Encrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Encrypt.html) does not succeed, OnEncrypt MUST fail.

If the call to AWS KMS Encrypt is successful, OnEncrypt MUST return the `CiphertextBlob` as a collection of bytes.

### DecryptDataKey

The KmsKeyring MUST determine whether to decrypt using KmsV1 mode or Kms+Context mode.
If the Key Provider Info of the Encrypted Data Key is "kms", the KmsKeyring MUST attempt to decrypt using KmsV1 mode.
If the Key Provider Info of the Encrypted Data Key is "kms+context", the KmsKeyring MUST attempt to decrypt using Kms+Context mode.

#### KmsV1

To attempt to decrypt a particular [encrypted data key](../structures.md#encrypted-data-key), the KmsKeyring MUST call [AWS KMS Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) with the configured AWS KMS client.

When calling [AWS KMS Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html), the keyring must call with a request constructed as follows:

- `KeyId` MUST be the configured AWS KMS key identifier.
- `CiphertextBlob` MUST be the [encrypted data key ciphertext](../structures.md#ciphertext).
- `EncryptionContext` MUST be the [encryption context](../structures.md#encryption-context) included in the input [decryption materials](../structures.md#decryption-materials).
- A custom API Name or User Agent string SHOULD be provided in order to provide metrics on KMS calls associated with the S3 Encryption Client.

The KmsKeyring MUST immediately return the plaintext as a collection of bytes.
If the KmsKeyring fails to successfully decrypt the [encrypted data key](../structures.md#encrypted-data-key), then it MUST throw an exception.

#### Kms+Context

To attempt to decrypt a particular [encrypted data key](../structures.md#encrypted-data-key), the KmsKeyring MUST call [AWS KMS Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) with the configured AWS KMS client.

When decrypting using Kms+Context mode, the KmsKeyring MUST validate the provided (request) encryption context with the stored (materials) encryption context.
The stored encryption context with the two reserved keys removed MUST match the provided encryption context.
If the stored encryption context with the two reserved keys removed does not match the provided encryption context, the KmsKeyring MUST throw an exception.

When calling [AWS KMS Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html), the keyring must call with a request constructed as follows:

- `KeyId` MUST be the configured AWS KMS key identifier.
- `CiphertextBlob` MUST be the [encrypted data key ciphertext](../structures.md#ciphertext).
- `EncryptionContext` MUST be the [encryption context](../structures.md#encryption-context) included in the input [decryption materials](../structures.md#decryption-materials).
- A custom API Name or User Agent string SHOULD be provided in order to provide metrics on KMS calls associated with the S3 Encryption Client.

The KmsKeyring MUST immediately return the plaintext as a collection of bytes.
If the KmsKeyring fails to successfully decrypt the [encrypted data key](../structures.md#encrypted-data-key), then it MUST throw an exception.