diff --git a/changes/2023-09-26_encryption-context-decrypt/background.md b/changes/2023-09-26_encryption-context-decrypt/background.md new file mode 100644 index 00000000..00567eb4 --- /dev/null +++ b/changes/2023-09-26_encryption-context-decrypt/background.md @@ -0,0 +1,155 @@ +[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved." +[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0" + +# Which Encryption Context should be used in Decrypt Operations + +## 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). + +## Issues and Alternatives + +### What kind of Encryption Context should Decrypt return? + +With the addition of the [required encryption context cmm](../../framework/required-encryption-context-cmm.md), +the `encrypt` API is able to filter out encryption context key-value pairs that +are not stored on the message. + +`decrypt` returns Encryption Context. +We were able to satisfy this requirement by returning the parsed message header. +This is no longer adequate as the header may not contain all Encryption Context values used to +authenticate the message. + +Currently, `decrypt` takes in optional encryption context. +This optional encryption context MAY not be stored in the message header, but is still authenticated. + +If `decrypt` uses [encryption context to only authenticate](../../client-apis/decrypt.md#encryption-context-to-only-authenticate) +to successfully decrypt a message, then the encryption context output +MUST be the union of the encryption context serialized into the message header and +the [encryption context for authentication only](#encryption-context-to-only-authenticate), if available. + +### Can you construct message that stores different encryption context than the encryption context returned by a CMM? + +None of the built-in implementations of the [CMM interface](../../framework/cmm-interface.md) +modify the encryption context on DecryptMaterials. + +However, the CMMs DecryptMaterials is allowed to modify the encryption context on decrypt. +A poorly designed CMM could theoretically return materials with an "incorrect" encryption context +that contradicts the encryption context in the header of the message. + +The `decrypt` API SHOULD not check if the encryption context that was stored on the message matches +what it receives from the CMMs DecryptMaterials because the current implementation +of the `encrypt` API used with the built-in CMMs is not able to write a message +that on `decrypt` the CMM returns "incorrect" encryption context that contradicts +the encryption context stored in the header of the message. + +### What changes to the existing Required Encryption Context CMM are required? + +None + +### What changes to the existing Cryptographic Materials Manager Interface are required? + +None + +## Testing + +In order to test that decrypt behaves as expected according to the specification, testing should include the following +scenarios to accurately reason about the behavior of using the Required Encryption Context CMM. + +To test the new encryption context (EC) features +the following dimensions exists: + +- Stored EC -- EC stored in the header +- Not stored EC -- EC authenticated to the header but not stored +- CMM Material EC -- EC on the decryption material +- Required keys -- Keys for the EC that MAY be only authenticated +- Reproduced EC -- EC passed on decrypt + +Given the EC `{ a: a, b: b }` +we break this into the following interesting options: + +Stored EC/Not Stored EC + +- `{a: a, b: b}` / `{}` +- `{a: a}` / `{b: b}` +- `{}` / `{a: a, b: b}` + +CMM Material/Required Keys + +- `{a: a, b: b}` / `{}` +- `{a: a, b: b}` / `{a}` +- `{a: a, b: b}` / `{a,b}` +- `{a: a, b: c}` / `{a}` +- `{a: a, b: b}` / `{c}` + +Reproduced EC + +- `{}` +- `{ a: a }` +- `{ b: b }` +- `{ a: a, b: b }` +- `{ a: c }` +- `{ b: c }` +- `{ a: c, b: b }` +- `{ a: c, b: c }` +- `{ c: c }` +- `{ a: a, c: c }` +- `{ b: b, c: c}` +- `{ a: a, b: b, c: c }` + +### Message: `{a: a, b: b}` / `{}` + +| CMM Material/Required Keys →
Reproduced EC ↓ | `{a: a, b: b}` / `{}` | `{a: a, b: b}` / `{a}` | `{a: a, b: b}` / `{a,b}` | `{a: a, b: c}` / `{a}` | `{a: a, b: b}` / `{c}` | +| ----------------------------------------------------------- | --------------------- | ---------------------- | ------------------------ | ---------------------- | ---------------------- | +| `{}` | pass | fail | fail | fail | fail | +| `{ a: a }` | pass | pass | fail | fail | fail | +| `{ b: b }` | pass | pass | fail | fail | fail | +| `{ a: a, b: b }` | pass | pass | pass | fail | fail | +| `{ a: c }` | fail | fail | fail | fail | fail | +| `{ b: c }` | fail | fail | fail | fail | fail | +| `{ a: c, b: b }` | fail | fail | fail | fail | fail | +| `{ a: c, b: c }` | fail | fail | fail | fail | fail | +| `{ c: c }` | fail | fail | fail | fail | fail | +| `{ a: a, c: c }` | fail | fail | fail | fail | fail | +| `{ b: b, c: c}` | fail | fail | fail | fail | fail | +| `{ a: a, b: b, c: c }` | fail | fail | fail | fail | fail | + +### Message: `{a: a}` / `{b: b}` + +| CMM Material/Required Keys →
Reproduced EC ↓ | `{a: a, b: b}` / `{}` | `{a: a, b: b}` / `{a}` | `{a: a, b: b}` / `{a,b}` | `{a: a, b: c}` / `{a}` | `{a: a, b: b}` / `{c}` | +| ----------------------------------------------------------- | --------------------- | ---------------------- | ------------------------ | ---------------------- | ---------------------- | +| `{}` | fail | fail | fail | fail | fail | +| `{ a: a }` | fail | fail | fail | fail | fail | +| `{ b: b }` | pass | fail | fail | fail | fail | +| `{ a: a, b: b }` | pass | pass | pass | pass | fail | +| `{ a: c }` | fail | fail | fail | fail | fail | +| `{ b: c }` | fail | fail | fail | fail | fail | +| `{ a: c, b: b }` | fail | fail | fail | fail | fail | +| `{ a: c, b: c }` | fail | fail | fail | fail | fail | +| `{ c: c }` | fail | fail | fail | fail | fail | +| `{ a: a, c: c }` | fail | fail | fail | fail | fail | +| `{ b: b, c: c}` | fail | fail | fail | fail | fail | +| `{ a: a, b: b, c: c }` | fail | fail | fail | fail | fail | + +### Message:`{}` / `{a: a, b: b}` + +| CMM Material/Required Keys →
Reproduced EC ↓ | `{a: a, b: b}` / `{}` | `{a: a, b: b}` / `{a}` | `{a: a, b: b}` / `{a,b}` | `{a: a, b: c}` / `{a}` | `{a: a, b: b}` / `{c}` | +| ----------------------------------------------------------- | --------------------- | ---------------------- | ------------------------ | ---------------------- | ---------------------- | +| `{}` | fail | fail | fail | fail | fail | +| `{ a: a }` | fail | pass | fail | fail | fail | +| `{ b: b }` | fail | fail | fail | fail | fail | +| `{ a: a, b: b }` | pass | fail | pass | fail | fail | +| `{ a: c }` | fail | fail | fail | fail | fail | +| `{ b: c }` | fail | fail | fail | fail | fail | +| `{ a: c, b: b }` | fail | fail | fail | fail | fail | +| `{ a: c, b: c }` | fail | fail | fail | fail | fail | +| `{ c: c }` | fail | fail | fail | fail | fail | +| `{ a: a, c: c }` | fail | fail | fail | fail | fail | +| `{ b: b, c: c}` | fail | fail | fail | fail | fail | +| `{ a: a, b: b, c: c }` | fail | fail | fail | fail | fail | diff --git a/changes/2023-09-26_encryption-context-decrypt/change.md b/changes/2023-09-26_encryption-context-decrypt/change.md new file mode 100644 index 00000000..6c68312d --- /dev/null +++ b/changes/2023-09-26_encryption-context-decrypt/change.md @@ -0,0 +1,58 @@ +[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved." +[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0" + +# Check Required Encryption Context Keys exist in Encryption Context in Decrypt and the values match in the stored Encryption Context in the message header + +## Affected Implementations + +This serves as a reference for all implementations that this change affects. + +| Language | Repository | +| ---------- | -------------------------------------------------------------------------------------------------------------- | +| Java | [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java) | +| .NET | [aws-encryption-sdk-net](https://github.com/aws/aws-encryption-sdk-dafny/tree/mainline/aws-encryption-sdk-net) | +| Python | [aws-encryption-sdk-python](https://github.com/aws/aws-encryption-sdk-python) | +| CLI | [aws-encryption-sdk-cli](https://github.com/aws/aws-encryption-sdk-cli) | +| C | [aws-encryption-sdk-c](https://github.com/aws/aws-encryption-sdk-c) | +| Javascript | [aws-encryption-sdk-javascript](https://github.com/aws/aws-encryption-sdk-javascript) | + +## 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). + +## Summary + +The [Decrypt](../../client-apis/decrypt.md) only requires +that the [encryption context](../../framework/structures.md#encryption-context) that is used as +additional authenticated data during the decryption of the input [encrypted message](#encrypted-message) +is returned. + +Additionally it should also return the +[encryption context used for authentication only](../../client-apis/decrypt.md#encryption-context-to-only-authenticate) +if it used any during the operation. + +### `decrypt` API returns encryption context used as AAD and encryption context used for authentication only + +On encrypt the [required encryption context cmm](../../framework/required-encryption-context-cmm.md), +is able to filter out encryption context key-value pairs that are not stored on the message. + +If the required encryption context CMM filters out encryption context keys from the Additional Authenticated +Data stored on the header, Decrypt MUST use the +[encryption context to only authenticate](../../client-apis/decrypt.md#encryption-context-to-only-authenticate) +to verify the header auth tag. + +The encryption context to only authenticate MUST be the [encryption context](../framework/structures.md#encryption-context) +in the [decryption materials](../framework/structures.md#decryption-materials) +filtered to only contain key value pairs listed in +the [decryption material's](../framework/structures.md#decryption-materials) +[required encryption context keys](../framework/structures.md#required-encryption-context-keys-1) +serialized according to the [encryption context serialization specification](../framework/structures.md#serialization). + +`decrypt` MUST return the union of the encryption context serialized into the message header and +the [encryption context for authentication only](#encryption-context-to-only-authenticate), if available. diff --git a/client-apis/decrypt.md b/client-apis/decrypt.md index 40c1096e..da2cb9d6 100644 --- a/client-apis/decrypt.md +++ b/client-apis/decrypt.md @@ -162,6 +162,8 @@ that implementation SHOULD NOT provide an API that allows the caller to stream t The [encryption context](../framework/structures.md#encryption-context) that is used as additional authenticated data during the decryption of the input [encrypted message](#encrypted-message). +Specifically, it MUST be the union of the encryption context serialized into the message header and +the [encryption context for authentication only](#encryption-context-to-only-authenticate), if available. This output MAY be satisfied by outputting a [parsed header](#parsed-header) containing this value. @@ -427,6 +429,15 @@ Note that the message header and message body MAY have already been input during If this verification is not successful, this operation MUST immediately halt and fail. +##### Encryption Context to Only Authenticate + +The encryption context to only authenticate MUST be the [encryption context](../framework/structures.md#encryption-context) +in the [decryption materials](../framework/structures.md#decryption-materials) +filtered to only contain key value pairs listed in +the [decryption material's](../framework/structures.md#decryption-materials) +[required encryption context keys](../framework/structures.md#required-encryption-context-keys-1) +serialized according to the [encryption context serialization specification](../framework/structures.md#serialization). + ## Security Considerations If this operation is [streaming](streaming.md) output to the caller