Skip to content

docs: specify how caching CMM should handle max plaintext length in Get Encryption Materials #159

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
159 changes: 159 additions & 0 deletions changes/2020-07-13_caching-cmm-max-plaintext-length/change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
[//]: # "Copyright Amazon.com Inc. or its affiliates. All Rights Reserved."
[//]: # "SPDX-License-Identifier: CC-BY-SA-4.0"

# Enforce Safe Handling of Max Plaintext Length in Caching Cryptographic Materials Manager

## Affected Features

| Feature |
| ------------------------------------------------------------------------- |
| [Caching Cryptographic Materials Manager](../../framework/caching-cmm.md) |

## Affected Specifications

| Specification |
| ------------------------------------------------------------------------- |
| [Caching Cryptographic Materials Manager](../../framework/caching-cmm.md) |

## Affected Implementations

| Language | Repository |
| ---------- | ------------------------------------------------------------------------------------- |
| C | [aws-encryption-sdk-c](https://github.com/aws/aws-encryption-sdk-c) |
| Java | [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java) |
| JavaScript | [aws-encryption-sdk-javascript](https://github.com/aws/aws-encryption-sdk-javascript) |
| Python | [aws-encryption-sdk-python](https://github.com/aws/aws-encryption-sdk-python) |

## 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 Get Encryption Materials operation accepts an optional `max plaintext length` parameter,
but the specification does not state
how the caching Cryptographic Materials Manager (caching CMM)
should behave when the caller does not provide the parameter value.
This change specifies that the caching CMM MUST bypass the cache in this case.

Also, when the caching CMM is performing a Get Encryption Materials operation
for which no materials are cached,
it MUST call its underlying CMM's Get Encryption Materials operation.
The specification does not state what value of `max plaintext length` (if any)
the caching CMM should pass to its underlying CMM.
This change specifies that the caching CMM MUST pass its `byte limit` value
as the `max plaintext length` parameter of the call to the underlying CMM.

## Out of Scope

- Changing the shape of any CMM APIs is out of scope.

## Motivation

### Fulfulling Encryption Materials Requests Without `max plaintext length`

The Get Encryption Materials operation of the CMM
accepts an Encryption Materials Request that MUST optionally include a `max plaintext length` field,
indicating the maximum length of plaintext
that the caller intends to encrypt using the returned materials.
The caching CMM aims to prevent its users from using encryption materials
to encrypt more bytes than its configured `byte limit`,
and existing implementations do so by bypassing the cache
whenever it does not know the `max plaintext length`.
This behavior is safe but previously unspecified,
and this change mandates that implementations implement it.

### Setting `max plaintext length` for Underlying CMM's Get Encryption Materials

The CMM interface specification implicitly allows an underlying CMM
to produce encryption materials using logic
that depends on the `max plaintext length` of an Encryption Materials Request.
Suppose the caching CMM passes a `max plaintext length` value of `N`
to its underlying CMM's Get Encryption Materials operation,
and caches the materials that it receives.
This signals to the underlying CMM that it intends to use the materials
to _only_ encrypt up to `N` bytes.
If a later Get Encryption Materials operation has a `max plaintext length` greater than `N`,
and if the caching CMM returns the cached materials,
then the user may use the materials to encrypt _more_ than `N` bytes.
The caching CMM violates its prior intent, which is unsafe.

It is therefore important that the caching CMM
carefully selects the `max plaintext length` parameter to pass to its underlying CMM.
This change mandates that the caching CMM passes its configured `byte limit` value
as the `max plaintext length` parameter to the underlying CMM,
whereas previously, the caching CMM could choose any value.
With this change in place,
even if the underlying CMM produces materials using plaintext-length-dependent logic,
the caching CMM receives and caches materials
that are safe to use for up to `byte limit` bytes of plaintext.
It follows that if a later Get Encryption Materials operation's `max plaintext length`
does not exceed the remaining number of bytes for which the cached materials can be safely used
(i.e.,
the difference between the caching CMM's `byte limit`
and the sum of `max plaintext length` values from past uses of the cached materials),
then it is also safe for the caching CMM to return the cached materials.

## Drawbacks

Bypassing the cache in the caching CMM on Get Encryption Materials operations
that do not specify `max plaintext length`
could be confusing to the user.
Warning the user when this happens could help prevent users from running into
unexpected (and potentially expensive) calls to the underlying CMM,
but we leave this as an implementation choice.

## Security Implications

This change SHOULD NOT have any security implications.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because our current implementations do not pass a max plaintext length value to the underlying CMM, and this is changing to now pass the byte limit value instead, the security implications for the value received from the underlying CMM are changing. This is both a security and operational change, as the underlying CMM could be making security decisions based on the max plaintext length value (or absence); for example if it is another caching CMM.


## Operational Implications

This change will break any customer use case
that depends on the Caching CMM passing no `max plaintext length` parameter
to the underlying CMM on Get Encryption Materials calls.
Comment on lines +118 to +120
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good call-out, but you don't actually mention anywhere that this is what implementations currently do.


## Guide-level Explanation

When making a Get Encryption Materials call to the caching CMM,
the user may optionally specify a value for the `max plaintext length` parameter,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
the user may optionally specify a value for the `max plaintext length` parameter,
the user MAY optionally specify a value for the `max plaintext length` parameter,

which indicates the maximum number of bytes the user intends to encrypt
with the materials received from the call.
If the user does not specify a `max plaintext length` value,
then the caching CMM will neither use cached materials
nor cache materials from its underlying CMM.
Comment on lines +128 to +130
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can simplify this to say something along the lines of "the caching CMM will pass through to the underlying CMM without involving the cache".

This helps to ensure that the number of bytes encrypted with the materials
does not exceed the `byte limit` that the user configures on the caching CMM,
while also maximizing the benefits of caching.
So whenever the user can determine an appropriate upper bound for bytes they will encrypt,
they should specify the `max plaintext length` value.
Comment on lines +134 to +135
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
So whenever the user can determine an appropriate upper bound for bytes they will encrypt,
they should specify the `max plaintext length` value.
If the user can determine an appropriate upper bound for bytes they will encrypt,
they SHOULD specify the `max plaintext length` value.


If the user customizes the underlying CMM of a caching CMM,
then whenever the caching CMM makes a Get Encryption Materials call
to the customized underlying CMM,
the Encryption Materials Request will have a `max plaintext length` value
equal to the `byte limit` value configured on the caching CMM.
Comment on lines +137 to +141
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "customizes the underlying CMM" mean in this case? This statement is true regardless of what underlying CMM you use.

This helps to ensure that the caching CMM can safely cache materials
that it receives from the customized underlying CMM.

## Reference-level Explanation

When the caching CMM is performing the Get Encryption Materials operation
for an Encryption Materials Request that does not specify a `max plaintext length`,

- The caching CMM MUST NOT return materials from its CMC.
- If the caching CMM calls its underlying CMM's Get Encryption Materials operation
in order to obtain encryption materials,
it MUST NOT cache the encryption materials in its CMC.

When the caching CMM calls its underlying CMM's Get Encryption Materials operation
in order to obtain encryption materials,
it MUST use its configured `byte limit` value
as the `max plaintext length` field of the Encryption Materials Request
that it sends to the underlying CMM.
17 changes: 13 additions & 4 deletions framework/caching-cmm.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@

## Version

0.3.0
0.4.0

### Changelog

- 0.4.0
- [Enforce Safe Handling of Max Plaintext Length in Caching Cryptographic Materials Manager](../changes/2020-07-13_caching-cmm-max-plaintext-length/change.md)
- 0.3.0
- [Specify Cache Entry Identifier Formulas for Caching Cryptographic Materials Manager](../changes/2020-07-17_cache-entry-identifier-formulas/change.md)
- 0.2.0
Expand Down Expand Up @@ -135,7 +137,8 @@ The number of bytes encrypted by the [encryption](structures.md#encryption-mater

### Get Encryption Materials

If the [algorithm suite](algorithm-suites.md) requested contains a [Identity KDF](algorithm-suites.md#identity-kdf),
If the [algorithm suite](algorithm-suites.md) requested contains a [Identity KDF](algorithm-suites.md#identity-kdf)
or if the request does not include a [Max Plaintext Length](cmm-interface.md#encryption-materials-request) value,
the caching CMM MUST obtain the encryption materials by making a call to the underlying CMM's [Get Encryption Materials](cmm-interface.md#get-encryption-materials) function.

Otherwise, the caching CMM MUST attempt to find the [encryption materials](structures.md#encryption-materials)
Expand All @@ -147,10 +150,16 @@ If a cache entry is found, the caching CMM MUST return the encryption materials
If a cache entry is not found, the caching CMM MUST then attempt to obtain the encryption materials
by making a call to the underlying CMM's [Get Encryption Materials](cmm-interface.md#get-encryption-materials).

If the [algorithm suite](algorithm-suites.md) requested does not contain an [Identity KDF](algorithm-suites.md#identity-kdf),
If the caching CMM makes a call to the underlying CMM's [Get Encryption Materials](cmm-interface.md#get-encryption-materials) operation,
then the request MUST include a [Max Plaintext Length](cmm-interface.md#encryption-materials-request)
with a value equal to its [Limit Bytes](#limit-bytes) value.

If the [algorithm suite](algorithm-suites.md) requested does not contain an [Identity KDF](algorithm-suites.md#identity-kdf)
and if the request includes a [Max Plaintext Length](cmm-interface.md#encryption-materials-request) value,
the caching CMM MUST add the encryption materials obtained from the underlying CMM into the underlying CMC.

If the [algorithm suite](algorithm-suites.md) requested contains an Identity KDF,
If the [algorithm suite](algorithm-suites.md) requested contains an Identity KDF
or if the request does not include a [Max Plaintext Length](cmm-interface.md#encryption-materials-request) value,
the caching CMM MUST NOT store the encryption materials in the underlying CMC.

### Decrypt Materials
Expand Down